Choisir un programme autonome

Souvent, les équipes ont plus d’un programme autonome, soit pour des raisons de concurrence, soit pour tester de nouveaux logiciels. Les programmes varient souvent en ajoutant des éléments tels que des délais, des stratégies différentes, etc. Les méthodes pour choisir la stratégie à exécuter impliquent généralement des commutateurs, des boutons de joystick, des boutons ou d’autres entrées matérielles.

With the SmartDashboard you can simply display a widget on the screen to choose the autonomous program that you would like to run. And with command based programs, that program is encapsulated in one of several commands. This article shows how to select an autonomous program with only a few lines of code and a nice looking user interface, with examples for both TimedRobot and Command-Based Robots.

TimedRobot

Note

The code snippets shown below are part of the TimedRobot template (Java, C++):

Creating SendableChooser Object

In Robot.java / Robot.h, create a variable to hold a reference to a SendableChooser object. Two or more auto modes can be added by creating strings to send to the chooser. Using the SendableChooser, one can choose between them. In this example, Default and My Auto are shown as options. You will also need a variable to store which auto has been chosen, m_autoSelected.

  private static final String kDefaultAuto = "Default";
  private static final String kCustomAuto = "My Auto";
  private String m_autoSelected;
  private final SendableChooser<String> m_chooser = new SendableChooser<>();
  frc::SendableChooser<std::string> m_chooser;
  const std::string kAutoNameDefault = "Default";
  const std::string kAutoNameCustom = "My Auto";
  std::string m_autoSelected;
import wpilib

self.defaultAuto = "Default"
self.customAuto = "My Auto";
self.chooser = wpilib.SendableChooser()

Setting Up Options

The chooser allows you to pick from a list of defined elements, in this case the strings we defined above. In robotInit, add your options created as strings above using setDefaultOption or addOption. setDefaultOption will be the one selected by default when the dashboard starts. The putData function will push it to the dashboard on your driver station computer.

  public void robotInit() {
    m_chooser.setDefaultOption("Default Auto", kDefaultAuto);
    m_chooser.addOption("My Auto", kCustomAuto);
    SmartDashboard.putData("Auto choices", m_chooser);
  }
void Robot::RobotInit() {
  m_chooser.SetDefaultOption(kAutoNameDefault, kAutoNameDefault);
  m_chooser.AddOption(kAutoNameCustom, kAutoNameCustom);
  frc::SmartDashboard::PutData("Auto Modes", &m_chooser);
}
from wpilib import SmartDashboard

self.chooser.setDefaultOption("Default Auto", self.defaultAuto)
self.chooser.addOption("My Auto", self.customAuto)
SmartDashboard.putData("Auto choices", self.chooser)

Running Autonomous Code

Now, in autonomousInit and autonomousPeriodic, you can use the m_autoSelected variable to read which option was chosen, and change what happens during the autonomous period.

  @Override
  public void autonomousInit() {
    m_autoSelected = m_chooser.getSelected();
    System.out.println("Auto selected: " + m_autoSelected);
  }

  /** This function is called periodically during autonomous. */
  @Override
  public void autonomousPeriodic() {
    switch (m_autoSelected) {
      case kCustomAuto:
        // Put custom auto code here
        break;
      case kDefaultAuto:
      default:
        // Put default auto code here
        break;
    }
  }
void Robot::AutonomousInit() {
  m_autoSelected = m_chooser.GetSelected();
  fmt::print("Auto selected: {}\n", m_autoSelected);

  if (m_autoSelected == kAutoNameCustom) {
    // Custom Auto goes here
  } else {
    // Default Auto goes here
  }
}

void Robot::AutonomousPeriodic() {
  if (m_autoSelected == kAutoNameCustom) {
    // Custom Auto goes here
  } else {
    // Default Auto goes here
  }
}
def autonomousInit(self):
   self.autoSelected = self.chooser.getSelected()
   print("Auto selected: " + self.autoSelected)

def autonomousPeriodic(self):
   match self.autoSelected:
      case self.customAuto:
         # Put custom auto code here
      case _:
         # Put default auto code here

Command-Based

Note

The code snippets shown below are part of the HatchbotTraditional example project (Java, C++, Python):

Création de l’objet SendableChooser

Dans RobotContainer, créez une variable pour contenir une référence à un objet SendableChooser. Deux commandes ou plus peuvent être créées et stockées dans de nouvelles variables. En utilisant le SendableChooser, on peut choisir l’une ou l’autres des deux variables. Dans cet exemple, SimpleAuto et ComplexAuto sont affichés comme des options.

  // A simple auto routine that drives forward a specified distance, and then stops.
  private final Command m_simpleAuto =
      new DriveDistance(
          AutoConstants.kAutoDriveDistanceInches, AutoConstants.kAutoDriveSpeed, m_robotDrive);

  // A complex auto routine that drives forward, drops a hatch, and then drives backward.
  private final Command m_complexAuto = new ComplexAuto(m_robotDrive, m_hatchSubsystem);

  // A chooser for autonomous commands
  SendableChooser<Command> m_chooser = new SendableChooser<>();
  // The autonomous routines
  DriveDistance m_simpleAuto{AutoConstants::kAutoDriveDistanceInches,
                             AutoConstants::kAutoDriveSpeed, &m_drive};
  ComplexAuto m_complexAuto{&m_drive, &m_hatch};

  // The chooser for the autonomous routines
  frc::SendableChooser<frc2::Command*> m_chooser;
  // The autonomous routines
  frc2::CommandPtr m_simpleAuto = autos::SimpleAuto(&m_drive);
  frc2::CommandPtr m_complexAuto = autos::ComplexAuto(&m_drive, &m_hatch);

  // The chooser for the autonomous routines
  frc::SendableChooser<frc2::Command*> m_chooser;
        # A simple auto routine that drives forward a specified distance, and then stops.
        self.simpleAuto = DriveDistance(
            constants.kAutoDriveDistanceInches, constants.kAutoDriveSpeed, self.drive
        )

        # A complex auto routine that drives forward, drops a hatch, and then drives backward.
        self.complexAuto = ComplexAuto(self.drive, self.hatch)

        # Chooser
        self.chooser = wpilib.SendableChooser()

Configurer SendableChooser

Imaginez que vous ayez le choix entre deux programmes autonomes et qu’ils soient encapsulés dans les commandes SimpleAuto et ComplexAuto. Pour choisir entre eux:

Dans RobotContainer, créez un objet SendableChooser et ajoutez-y des instances des deux commandes. Il peut y avoir n’importe quel nombre de commandes, et celle ajoutée par défaut (setDefaultOption), devient celle qui est initialement sélectionnée. Notez que chaque commande est incluse dans un appel de méthode setDefaultOption() ou addOption() sur l’instance SendableChooser.

    // Add commands to the autonomous command chooser
    m_chooser.setDefaultOption("Simple Auto", m_simpleAuto);
    m_chooser.addOption("Complex Auto", m_complexAuto);
  // Add commands to the autonomous command chooser
  m_chooser.SetDefaultOption("Simple Auto", &m_simpleAuto);
  m_chooser.AddOption("Complex Auto", &m_complexAuto);
  // Add commands to the autonomous command chooser
  // Note that we do *not* move ownership into the chooser
  m_chooser.SetDefaultOption("Simple Auto", m_simpleAuto.get());
  m_chooser.AddOption("Complex Auto", m_complexAuto.get());
        # Add commands to the autonomous command chooser
        self.chooser.setDefaultOption("Simple Auto", self.simpleAuto)
        self.chooser.addOption("Complex Auto", self.complexAuto)

Then, publish the chooser to the dashboard:

// Put the chooser on the dashboard
SmartDashboard.putData(m_chooser);
// Put the chooser on the dashboard
frc::SmartDashboard::PutData(&m_chooser);
from wpilib import SmartDashboard

# Put the chooser on the dashboard
SmartDashboard.putData(chooser)

Démarrer une commande autonome

Dans Robot.java, lorsque la période autonome démarre, l’objet SendableChooser est interrogé pour obtenir la commande sélectionnée et cette commande doit être planifiée.

  public Command getAutonomousCommand() {
    return m_chooser.getSelected();
  }
  public void autonomousInit() {
    m_autonomousCommand = m_robotContainer.getAutonomousCommand();

    // schedule the autonomous command (example)
    if (m_autonomousCommand != null) {
      m_autonomousCommand.schedule();
    }
  }
frc2::Command* RobotContainer::GetAutonomousCommand() {
  // Runs the chosen command in autonomous
  return m_chooser.GetSelected();
}
void Robot::AutonomousInit() {
  m_autonomousCommand = m_container.GetAutonomousCommand();

  if (m_autonomousCommand != nullptr) {
    m_autonomousCommand->Schedule();
  }
}
    def getAutonomousCommand(self) -> commands2.Command:
        return self.chooser.getSelected()
    def autonomousInit(self) -> None:
        """This autonomous runs the autonomous command selected by your RobotContainer class."""
        self.autonomousCommand = self.container.getAutonomousCommand()

        if self.autonomousCommand:
            self.autonomousCommand.schedule()

Exécution du planificateur en mode autonome

In Robot.java, this will run the scheduler every driver station update period (about every 20ms) and cause the selected autonomous command to run. In Python the scheduler runs automatically when TimedCommandRobot is used.

Note

L’exécution du planificateur peut se produire dans la fonction autonomousPeriodic() ou robotPeriodic(), les deux fonctionneront de la même manière en mode autonome.

40  @Override
41  public void robotPeriodic() {
42    CommandScheduler.getInstance().run();
43  }
29void Robot::RobotPeriodic() {
30  frc2::CommandScheduler::GetInstance().Run();
31}

Annulation de la commande autonome

Dans Robot.java, lorsque la période téléop commence, la commande autonome sera annulée.

78  @Override
79  public void teleopInit() {
80    // This makes sure that the autonomous stops running when
81    // teleop starts running. If you want the autonomous to
82    // continue until interrupted by another command, remove
83    // this line or comment it out.
84    if (m_autonomousCommand != null) {
85      m_autonomousCommand.cancel();
86    }
87  }
56void Robot::TeleopInit() {
57  // This makes sure that the autonomous stops running when
58  // teleop starts running. If you want the autonomous to
59  // continue until interrupted by another command, remove
60  // this line or comment it out.
61  if (m_autonomousCommand != nullptr) {
62    m_autonomousCommand->Cancel();
63    m_autonomousCommand = nullptr;
64  }
65}
51    def teleopInit(self) -> None:
52        # This makes sure that the autonomous stops running when
53        # teleop starts running. If you want the autonomous to
54        # continue until interrupted by another command, remove
55        # this line or comment it out.
56        if self.autonomousCommand:
57            self.autonomousCommand.cancel()

Affichage du tableau de bord intelligent

SendableChooser affiche deux commandes autonomes sélectionnables : Simple Auto et Complex Auto.

Lorsque le SmartDashboard est exécuté, les choix du SendableChooser sont automatiquement affichés. Vous pouvez simplement choisir une option avant le début de la période autonome et la commande correspondante s’exécutera.