Skip to content

Multi-Variant Autonomous Modes

In FTC your autonomous flow often needs to adapt based on alliance or starting position, this is where multi-variant AutonomousModes come in.


Currently Volt comes with three types of multi-variant AutonomousModes:

  • DualAutonomousMode: Creates two variants, one for red and one for blue alliance
  • MultiAutonomousMode: Creates one variant for every type defined in an enum class
  • MultiDualAutonomousMode: Creates two variants for every type defined in an enum class, one for red and one for blue alliance

Use DualAutonomousMode when your AutonomousMode needs to do different things when you are on blue alliance vs red alliance.

The color property references the selected AllianceColor.

DualAutonomousMode also provides helper methods:

  • <T> forAlliance(red: T, blue: T): T: Returns red if the selected alliance is RED or blue if the selected alliance is BLUE.
  • mirroredForAlliance(redPose: Pose): Returns a PedroPathing Pose that is mirrored if the selected alliance is BLUE.
class Park : DualAutonomousMode<RobotWithMecanumDrivetrain<MecanumDriveWithPP>>() {
companion object {
// Define RED poses
private val START_RED = Pose(12.0, 60.0, 270.0.toRadians())
private val PARK_RED = Pose(12.0, 36.0, 270.0.toRadians())
}
// Mirror poses if BLUE
val initialPose = mirroredForAlliance(START_RED)
val parkPose = mirroredForAlliance(PARK_RED)
override val robot = RobotWithMecanumDrivetrain<MecanumDriveWithPP>(
hardwareMap,
MecanumDriveWithPP(
hardwareMap,
FollowerConstants(),
DriveEncoderConstants(),
PathConstraints(),
MecanumConstants(),
initialPose,
),
)
init {
blackboard["allianceColor"] = color // Save color to the blackboard
Start then {
+robot.drivetrain.path { lineTo(parkPose) }
}
}
}

Use MultiAutonomousMode to create as many variants for your AutonomousMode as you want. Examples include multiple starting positions, launch positions, speeds, etc.

The variant property references the selected variant. The type of variant, E, is provided via a type parameter.

enum class StartingPosition {
LEFT,
RIGHT,
}
class Park : MultiAutonomousMode<RobotWithMecanumDrivetrain<MecanumDriveWithPP>, StartingPosition>() {
companion object {
// Define poses
private val START_LEFT = Pose(12.0, 60.0, 270.0.toRadians())
private val START_RIGHT = Pose(12.0, 66.0, 270.0.toRadians())
private val PARK = Pose(12.0, 36.0, 270.0.toRadians())
}
// Get initial pose
val initialPose = if (variant == StartingPosition.LEFT) START_LEFT else START_RIGHT
override val robot = RobotWithMecanumDrivetrain<MecanumDriveWithPP>(
hardwareMap,
MecanumDriveWithPP(
hardwareMap,
FollowerConstants(),
DriveEncoderConstants(),
PathConstraints(),
MecanumConstants(),
initialPose,
),
)
init {
Start then {
+robot.drivetrain.path { lineTo(PARK) }
}
}
}

MultiDualAutonomousMode combines DualAutonomousMode and MultiAutonomousMode, use it when you want alliance color variants for each of your MultiAutonomousMode variants.

MultiDualAutonomousMode extends DualAutonomousMode, adding the variant property from MultiAutonomousMode.

enum class StartingPosition {
LEFT,
RIGHT,
}
class Park : MultiDualAutonomousMode<RobotWithMecanumDrivetrain<MecanumDriveWithPP>, StartingPosition>() {
companion object {
// Define RED poses
private val START_LEFT_RED = Pose(12.0, 60.0, 270.0.toRadians())
private val START_RIGHT_RED = Pose(12.0, 66.0, 270.0.toRadians())
private val PARK_RED = Pose(12.0, 36.0, 270.0.toRadians())
}
// Get initial pose and mirror poses if BLUE
val initialPose = if (variant == StartingPosition.LEFT) mirroredForAlliance(START_LEFT_RED) else mirroredForAlliance(START_RIGHT_RED)
val parkPose = mirroredForAlliance(PARK_RED)
override val robot = RobotWithMecanumDrivetrain<MecanumDriveWithPP>(
hardwareMap,
MecanumDriveWithPP(
hardwareMap,
FollowerConstants(),
DriveEncoderConstants(),
PathConstraints(),
MecanumConstants(),
initialPose,
),
)
init {
blackboard["allianceColor"] = color // Save color to the blackboard
Start then {
+robot.drivetrain.path { lineTo(parkPose) }
}
}
}