|
|
|
![]() |
|
|||||||
|
||||||||
|
|
Thread Tools | Rate Thread | Display Modes |
|
#1
|
|||
|
|||
|
Building Commands at Runtime
Last year, our team tried to have a modular autonomous command. The way this worked was something like this:
Code:
autoDefenseChooser = new SendableChooser();
autoSideChooser = new SendableChooser();
...
autoDefenseChooser.addDefault("Do not drive forward", new WaitCommand(.01));
autoDefenseChooser.addObject("Only move forward", new DriveStraight(.8,1));
autoDefenseChooser.addObject("Go over terrain defense", new DriveStraight(1,2.5));
autoDefenseChooser.addObject("Low bar", new DriveStraight(.8, 5));
SmartDashboard.putData("Auto Defense", autoDefenseChooser);
autoSideChooser.addDefault("Do not turn", new WaitCommand(.01));
autoSideChooser.addObject("Turn Right", new MultiRotate(60,3));
autoSideChooser.addObject("Turn Left", new MultiRotate(-60,3));
SmartDashboard.putData("Auto Side Selector", autoSideChooser);
...
Code:
addSequential((Command)Robot.autoDefenseChooser.getSelected()); Here are two solutions to this: the boring way and the fun(ctional) way. (Note that this post uses a lot of method references, so I recommend that you take a look at them beforehand if you aren't familiar with them). 1. The boring (but effective) way First, create a command that does nothing. I'll call it DoNothingCommand. This command should immediately return true or be a timed command with a very short timeout. For this, we will use a Supplier. This allows us to get a "fresh" instance of the same command every time (so that way we aren't adding the same instance of a command to different instances of a commandgroup). In Robot.java: Code:
public static SendableChooser<Supplier<Command>> autoStep1 = new SendableChooser<>();
public static SendableChooser<Supplier<Command>> autoStep2 = new SendableChooser<>();
...
public void robotInit(){
...
autoStep1.addDefault("Do nothing", DoNothingCommand::new);
autoStep1.addObject("Go Straight",GoStraightCommand::new);
autoStep1.addObject("Turn Left", TurnLeftCommand::new);
autoStep1.addObject("Turn Right", TurnRightCommand::new);
SmartDashboard.putData("Auto Step 1", autoStep1);
autoStep2.addDefault("Do nothing", DoNothingCommand::new);
autoStep2.addObject("Shoot Fuel", ShootFuelCommand::new);
autoStep2.addObject("Place Gear", PlaceGearCommand::new);
...
}
Code:
Supplier<TurnRightCommand> s = TurnRightCommand::new; TurnRightCommand c1 = s.get(); TurnRightCommand c2 = s.get(); System.out.println(c1 == c2);//false Code:
addSequential(Robot.autoStep1.getSelected().get()); addSequential(Robot.autoStep2.getSelected().get()); This way throws an optional into the mix. An optional is meant to represent an object that may or may not be there, kind of like a null with superpowers. In Robot.java: Code:
public static SendableChooser<Optional<Supplier<Command>>> autoStep1 = new SendableChooser<>();
public static SendableChooser<Optional<Supplier<Command>>> autoStep2 = new SendableChooser<>();
...
public void robotInit(){
...
autoStep1.addDefault("Do nothing", Optional.empty());
autoStep1.addObject("Go Straight", Optional.of(GoStraightCommand::new));
autoStep1.addObject("Turn Left", Optional.of(TurnLeftCommand::new));
autoStep1.addObject("Turn Right", Optional.of(TurnRightCommand::new));
SmartDashboard.putData("Auto Step 1", autoStep1);
autoStep2.addDefault("Do nothing", Optional.empty());
autoStep2.addObject("Shoot Fuel", Optional.of(ShootFuelCommand::new));
autoStep2.addObject("Place Gear", Optional.of(PlaceGearCommand::new));
...
}
Code:
Robot.autoStep1.getSelected().map(Supplier::get).ifPresent(this::addSequential); Robot.autoStep2.getSelected().map(Supplier::get).ifPresent(this::addSequential); |
| Thread Tools | |
| Display Modes | Rate This Thread |
|
|