Adding a Drivetrain
A Drivetrain is a type of Attachment that defines Actions that can move Robots autonomously and tele-operated.
Volt provides many pre-built Drivetrain classes for many combinations of drivetrain types, localization methods, and backends. Using these pre-built classes is the simplest way to add a Drivetrain to your Robot.
1. Choose a Drivetrain
Section titled “1. Choose a Drivetrain”Choosing a Drivetrain is a three-step process:
- Select a type of physical drivetrain (What drivetrain does your robot physically use?)
- Select a localization method (What localization hardware do you have?)
- Select a compatible backend (Which pathing backend/actions do you want to use?)
This table contains all of Volt’s pre-built Drivetrain classes:
| Drivetrain | Localization | Backend | Class |
|---|---|---|---|
| Mecanum | Drive Encoder | PedroPathing | DriveEncoderMecanumPedroPathingDrivetrain |
| Mecanum | Drive Encoder | RoadRunner | DriveEncoderMecanumRoadRunnerDrivetrain |
| Mecanum | Two Wheel | PedroPathing | TwoWheelMecanumPedroPathingDrivetrain |
| Mecanum | Two Wheel | RoadRunner | TwoWheelMecanumRoadRunnerDrivetrain |
| Mecanum | Three Wheel | PedroPathing | ThreeWheelMecanumPedroPathingDrivetrain |
| Mecanum | Three Wheel | RoadRunner | ThreeWheelMecanumRoadRunnerDrivetrain |
| Mecanum | Three Wheel + IMU | PedroPathing | ThreeWheelIMUMecanumPedroPathingDrivetrain |
| Mecanum | Pinpoint | PedroPathing | PinpointMecanumPedroPathingDrivetrain |
| Mecanum | Pinpoint | RoadRunner | PinpointMecanumRoadRunnerDrivetrain |
| Mecanum | OTOS | PedroPathing | OTOSMecanumPedroPathingDrivetrain |
| Mecanum | OTOS | RoadRunner | OTOSMecanumRoadRunnerDrivetrain |
| Swerve | Drive Encoder | PedroPathing | DriveEncoderSwervePedroPathingDrivetrain |
| Swerve | Two Wheel | PedroPathing | TwoWheelSwervePedroPathingDrivetrain |
| Swerve | Three Wheel | PedroPathing | ThreeWheelSwervePedroPathingDrivetrain |
| Swerve | Three Wheel + IMU | PedroPathing | ThreeWheelIMUSwervePedroPathingDrivetrain |
| Swerve | Pinpoint | PedroPathing | PinpointSwervePedroPathingDrivetrain |
| Swerve | OTOS | PedroPathing | OTOSSwervePedroPathingDrivetrain |
| Tank | Drive Encoder | RoadRunner | DriveEncoderTankRoadRunnerDrivetrain |
| Tank | Two Wheel | RoadRunner | TwoWheelTankRoadRunnerDrivetrain |
| Tank | Three Wheel | RoadRunner | ThreeWheelTankRoadRunnerDrivetrain |
| Tank | Pinpoint | RoadRunner | PinpointTankRoadRunnerDrivetrain |
| Tank | OTOS | RoadRunner | OTOSTankRoadRunnerDrivetrain |
Let’s use a mecanum drivetrain, drive encoder localization, and PedroPathing.
2. Create a DrivetrainRobot
Section titled “2. Create a DrivetrainRobot”Make a Robot class that extends DrivetrainRobot. This gives your Robot access to a drivetrain instance.
class MyRobot(hardwareMap: HardwareMap) : DrivetrainRobot(hardwareMap)public class MyRobot extends DrivetrainRobot { public MyRobot(HardwareMap hardwareMap) { super(hardwareMap); }}3. Declare Drivetrain Type
Section titled “3. Declare Drivetrain Type”Pass a generic type parameter that inherits Drivetrain. This lets Volt know what type of Drivetrain class your Robot uses.
In this case we’ll use DriveEncoderMecanumPedroPathingDrivetrain:
class MyRobot(hardwareMap: HardwareMap) : DrivetrainRobot<DriveEncoderMecanumPedroPathingDrivetrain>(hardwareMap)public class MyRobot extends DrivetrainRobot<DriveEncoderMecanumPedroPathingDrivetrain> { public MyRobot(HardwareMap hardwareMap) { super(hardwareMap); }}4. Create and Configure Drivetrain Instance
Section titled “4. Create and Configure Drivetrain Instance”Create a new instance of your Drivetrain type. This is where you define hardware and tune your Drivetrain.
For our DriveEncoderMecanumDrivetrain, we’ll supply simple FollowerConstants, DriveEncoderConstants, and MecanumConstants.
class MyRobot(hardwareMap: HardwareMap) : DrivetrainRobot<DriveEncoderMecanumPedroPathingDrivetrain>( hardwareMap, DriveEncoderMecanumPedroPathingDrivetrain( hardwareMap = hardwareMap, followerConstants = FollowerConstants() .mass(9.8) .translationalPIDFCoefficients(PIDFCoefficients(0.02, 0.0, 0.0, 0.07)), localizerConstants = DriveEncoderConstants() .robotWidth(14.0) .robotLength(9.0) .forwardTicksToInches(0.0057725) .strafeTicksToInches(0.0069642) .turnTicksToInches(0.009961), driveConstants = MecanumConstants() .maxPower(0.8), ), )public class MyRobot extends DrivetrainRobot<DriveEncoderMecanumPedroPathingDrivetrain> { public MyRobot(HardwareMap hardwareMap) { super( hardwareMap, new DriveEncoderMecanumPedroPathingDrivetrain( hardwareMap, new FollowerConstants() .mass(9.8) .translationalPIDFCoefficients(new PIDFCoefficients(0.02, 0.0, 0.0, 0.07)), new DriveEncoderConstants() .robotWidth(14.0) .robotLength(9.0) .forwardTicksToInches(0.0057725) .strafeTicksToInches(0.0069642) .turnTicksToInches(0.009961), new PathConstraints(), new MecanumConstants() .maxPower(0.8), new Pose() ) ); }}In this case, we would have calculated the Robot’s mass, driving base width, and driving base length; tuned translational PIDF coefficients, forward ticks per inch, strafe ticks per inch, and turn ticks per inch; and experimented with various maximum powers.
Result
Section titled “Result”import com.pedropathing.control.PIDFCoefficientsimport com.pedropathing.follower.FollowerConstantsimport com.pedropathing.ftc.drivetrains.MecanumConstantsimport com.pedropathing.ftc.localization.constants.DriveEncoderConstantsimport com.pedropathing.geometry.Poseimport com.qualcomm.robotcore.hardware.HardwareMapimport dev.kingssack.volt.robot.DrivetrainRobotimport dev.kingssack.volt.attachment.drivetrain.pp.mecanum.DriveEncoderMecanumPedroPathingDrivetrain
class MyRobot(hardwareMap: HardwareMap) : DrivetrainRobot<DriveEncoderMecanumPedroPathingDrivetrain>( hardwareMap, DriveEncoderMecanumPedroPathingDrivetrain( hardwareMap = hardwareMap, followerConstants = FollowerConstants() .mass(9.8) .translationalPIDFCoefficients(PIDFCoefficients(0.02, 0.0, 0.0, 0.07)), localizerConstants = DriveEncoderConstants() .robotWidth(14.0) .robotLength(9.0) .forwardTicksToInches(0.0057725) .strafeTicksToInches(0.0069642) .turnTicksToInches(0.009961), driveConstants = MecanumConstants() .maxPower(0.8), ), )import com.pedropathing.control.PIDFCoefficients;import com.pedropathing.follower.FollowerConstants;import com.pedropathing.ftc.drivetrains.MecanumConstants;import com.pedropathing.ftc.localization.constants.DriveEncoderConstants;import com.pedropathing.geometry.Pose;import com.pedropathing.paths.PathConstraints;import com.qualcomm.robotcore.hardware.HardwareMap;import dev.kingssack.volt.robot.DrivetrainRobot;import dev.kingssack.volt.attachment.drivetrain.pp.mecanum.DriveEncoderMecanumPedroPathingDrivetrain;
public class MyRobot extends DrivetrainRobot<PedroPathingDriveEncoderMecanumDrivetrain> { public MyRobot(HardwareMap hardwareMap) { super( hardwareMap, new DriveEncoderPedroPathingMecanumDrivetrain( hardwareMap, new FollowerConstants() .mass(9.8) .translationalPIDFCoefficients(new PIDFCoefficients(0.02, 0, 0, 0.07)), new DriveEncoderConstants() .robotWidth(14.0) .robotLength(9.0) .forwardTicksToInches(0.0057725) .strafeTicksToInches(0.0069642) .turnTicksToInches(0.009961), new PathConstraints(), new MecanumConstants() .maxPower(0.8), new Pose() ) ); }}Next Steps
Section titled “Next Steps”- Create an OpMode that controls your drivetrain
- Learn more about Actions