How the Heck do you use SelectCommand?

I’m working in a C++ CommandBased project and I want to create a command that can select between running different commands. From what I can tell from the docs the [SelectCommand](Command Compositions — FIRST Robotics Competition documentation class is what i’m looking for. I cannot for the life of me understand how I’m supposed to implement this. I searched on github and nobody seems to have ever used it in a public repo.

My current implementation so far is here https://github.com/4698RaiderRobotics/FRC-2023/blob/a06b1d5944772b4dede575e30a7ef36fe8cce96f/src/main/cpp/commands/LedCommands/LedIdle.cpp#LL15C1-L15C1 but honestly I don’t know where to go from here.

Please ask me questions if I need to provide any follow up information.

1 Like

There is an example at allwpilib/RobotContainer.h at main · wpilibsuite/allwpilib · GitHub

In particular, the documentation indicates that there is no default (that is, no argument) constructor, which is the cause of the error message you are seeing.

1 Like

We use conditional command a bunch but I don’t think we’ve had a situation for our robots where there was more than 2 options needed for a decision point

Perhaps we should remove the magic SFINAE constructor, though, because i don’t think anyone who isn’t a C++ wizard will have any idea what it’s doing.

SFINAE constructor?

To use this, you have to understand the template expression, which only expands properly in some contexts and otherwise is ignored (this is called “Substitution Failure Is Not an Error”, or “SFINAE”). It also contains a fold expression…

What would you replace it with?

We were using nested select commands at one point. We ended up not using vision so we simplified this greatly but at one point this is what we had.

frc2::ScheduleCommand(
          new frc2::SelectCommand<GamePieceType>{[this] {return m_pGripper->GetGamePieceType();},
            std::pair{CUBE, frc2::SelectCommand<ScoringPosition>{[this] {return m_scoringPosition;}, 
                              std::pair{FLOOR, frc2::SequentialCommandGroup{
                                    m_pElevator->GoToFloorCommand(),
                                    m_pSlide->TrackAprilTagsMidShelfCommand(),
                                  },
                              },
                              std::pair{MID, frc2::SequentialCommandGroup{
                                    m_pElevator->GoToBottomPostCommand(),
                                    m_pSlide->TrackAprilTagsMidShelfCommand(),
                                },
                              },
                              std::pair{TOP, frc2::SequentialCommandGroup{
                                    m_pElevator->GoToTopPostCommand(),
                                    m_pSlide->TrackAprilTagsTopShelfCommand(),
                                },
                              },
                            },
              },
            std::pair{CONE, frc2::SelectCommand<ScoringPosition>{[this] {return m_scoringPosition;}, 
                              std::pair{FLOOR, frc2::SequentialCommandGroup{
                                    m_pElevator->GoToFloorCommand(),
                                    m_pSlide->TrackLimelightBottomPostCommand(),
                                },
                              },
                              std::pair{MID, frc2::SequentialCommandGroup{
                                    m_pElevator->GoToBottomPostCommand(),
                                    m_pSlide->TrackLimelightBottomPostCommand(),
                                },
                              },
                              std::pair{TOP, frc2::SequentialCommandGroup{
                                    m_pElevator->GoToTopPostCommand(),
                                    m_pSlide->TrackLimelightTopPostCommand(),
                                },
                              },
                            },
            },
            std::pair{NONE, frc2::PrintCommand("Unknown Game Piece, Cannot Score")}
          }
        ),

The std::vector<std::pair<Key, CommandPtr>> constructor should be fine. There’s no need to do fancy fold expression sugaring here; it saves a single pair of brackets at the cost of requiring the user to know high-powered template magic to know what it even is.

1 Like

so how do I create a command that uses a selectcommand?
How do i extend CommandHelper<Base, Subclass> with selectcommand

I’m not sure why you would need to do that. In the example I gave you above, a SelectCommand is created directly from the selector and the sub-commands.