Skip to content

Autonomous

James Hagborg edited this page Dec 17, 2018 · 1 revision

HYPERLib provides two abstractions for managing autonomous mode: routines and strategies. The distinction exists because in some years, such as 2018 POWER UP, game-specific data is provided at the start of the match. A routine defines a command or sequence of commands to run, together with extra data for managing preferences. A strategy associates possible values of the game-specific data with routines. In the most common use-case, the driver selects a strategy from a list on the dashboard before the match starts.

Defining a routine

To define an autonomous routine, subclass AutonomousRoutine, and override the build method. This method accepts a CommandBuilder, which you can use to build the routine. This method will be run at the start of autonomous. After it finishes, the command it generated will be run. For example, a command that drives straight at a specified speed and time:

public class OffWallNudge extends AutonomousRoutine {
    @AutoPref public DoublePreference speed, time;
    
    @Override
    public void build(CommandBuilder builder) {
        builder.sequential(AutoDrive.forwardCmd(speed), time.get());
        builder.sequential(Robot.driveTrain.stopDriveCmd());
    }
}

The @AutoPref annotation here automatically creates preferences with the names speed and time. These are namespaced in such a way that defining preferences called speed and time in a different routine won't cause any conflicts. These preferences become accessible through the AutoViewer plugin on the dashboard.

Composing routines

It's possible to compose routines, i.e. call one routine from another. To ensure that all the relevant preferences get displayed, it's necessary to call addSubroutine. For example:

public class CenterToLeftSwitchNoVision extends AutonomousRoutine {
    @AutoPref public DoublePreference fwdSpeed, fwdTime, rotateAngle, driveDist;
    
    AutonomousRoutine offWallNudge = addSubroutine(new OffWallNudge());
    AutonomousRoutine raiseCube = addSubroutine(new RaiseCubeToSwitch());
    AutonomousRoutine unGrip = addSubroutine(new UnGrip());
    
    @Override
    public void build(CommandBuilder builder) {
        offWallNudge.build(builder);         // Add all steps of offWallNudge in sequence
        builder.parallel(raiseCube::build);  // Add all steps of raiseCube in parallel
        
        builder.sequential(new GyroRotateCommand(-rotateAngle.get(), true, true));
        builder.sequential(new DriveToDistance(driveDist.get(), true, true));
        builder.sequential(new GyroRotateCommand(rotateAngle.get(), true, true));
        builder.sequential(AutoDrive.forwardCmd(fwdSpeed), fwdTime.get());
        builder.sequential(Robot.driveTrain.stopDriveCmd());

        unGrip.build(builder);               // Add all steps of unGrip in sequence
    }
}

Defining strategies

At the end of the day, the driver sees something like this:

Selecting a strategy from the autonomous chooser

This is the (abridged) code which defines this selection of strategies:

AutonomousStrategy leftSwitch = new AutonomousStrategy.Builder("Left: Priority SWITCH")
	.addScenario("LLL", new LeftToSwitchVision())
	.addScenario("LRL", new LeftToSwitchVision())
	.addScenario("RLR", new SideCrossBaseline())
	.addScenario("RRR", new SideCrossBaseline())
	.addDefault(new SideCrossBaseline())
	.build();
AutonomousStrategy rightSwitch = new AutonomousStrategy.Builder("Right: Priority SWITCH")
	.addScenario("RRR", new RightToSwitchVision())
	.addScenario("RLR", new RightToSwitchVision())
	.addScenario("LRL", new SideCrossBaseline())
	.addScenario("LLL", new SideCrossBaseline())
	.addDefault(new SideCrossBaseline())
	.build();
AutonomousStrategy center = new AutonomousStrategy.Builder("Center: Priority SWITCH")
	.addScenario("RRR", new CenterToRightSwitchVision())
	.addScenario("RLR", new CenterToRightSwitchVision())
	.addScenario("LRL", new CenterToLeftSwitchVision())
	.addScenario("LLL", new CenterToLeftSwitchVision())
	.addDefault(new DoNothing())
	.build();
// This should be stored as an instance variable somewhere
autoInfo = new AutonomousInfo.Builder()
	.addStrategy(leftSwitch)
	.addStrategy(rightSwitch)
	.addDefault(center)
	.build();

This should run once in robotInit, to put the chooser on the dashboard. Then in autonomousInit, we need to read the chosen value and run it:

AutonomousStrategy strat = autoInfo.getSelection();
String fmsData = DriverStation.getInstance().getGameSpecificMessage();
AutonomousRoutine rtn = strat.getRoutineForScenario(fmsData);
CommandBuilder builder = new CommandBuilder();
rtn.build(builder);
// autoCmd should be an instance variable, so you can cancel it when auto is done
autoCmd = builder.build()
autoCmd.start();
Clone this wiki locally