Drivetrain Modules - Gongoliers/Library-of-Gongolierium GitHub Wiki
Many drivetrain programs can become complex as different features are added to meet a team's needs. Drivetrain modules simplify a team's drivetrain code while still adding the needed complexity. Modules can be installed into a ModularDrivetrain instance and currently only work for arcade driving.
The modular drivetrain is a wrapper around a DifferentialDrivetrain which allows a drivetrain to install modules. All modules are run, in the order that they are installed, when the ModularDrivetrain.arcade()
or ModularDrivetrain.tank()
methods are called.
A modular drivetrain can be created with the following code:
DifferentialDrive differentialDrive = /* Create a differential drive here */;
ModularDrivetrain drivetrain = ModularDrivetrain.from(differentialDrive);
Modules can be added to the drivetrain using the ModularDrivetrain.setModules()
method.
drivetrain.setModules(
powerModule,
stabilityModule,
pathFollowingModule
);
There are several premade modules based on the code developed by FRC Team 5112. All the modules have been tested to verify that they perform correctly and efficiently.
The anchor module attempts to keep the drivetrain in place. This can be used to stay put on a slanted platform or to defend a goal.
Encoder leftEncoder = /* Get your robot's left encoder here */
Encoder rightEncoder = /* Get your robot's right encoder here */
double strength = 0.1;
var anchorModule = new AnchorModule(leftEncoder, rightEncoder, strength);
The path follower module allows your robot to follow paths consisting of straightaways and rotations. This is especially useful in autonomous. Note, the robot must have both a gyro and encoder(s) to use this module - this may change in the future.
Gyro gyro = /* Get your robot's gyro here */
List<Encoder> encoders = List.of(/* Get your robot's encoders here */);
double forwardStrength = 0.1;
double turnStrength = 0.1;
var pathFollowerModule = new PathFollowerModule(gyro, encoders, forwardStrength, turnStrength);
To start following a path, you can use the following method:
var path = new SimplePath();
path.addRotation(90); // degrees
path.addStraightAway(10); // Same units as the encoders
// To start following a path
pathFollowerModule.startFollowingPath(path);
// To check if it is still following a path
boolean isFollowing = pathFollowerModule.isFollowingPath();
// To stop following a path
pathFollowerModule.stopFollowingPath();
Once the startFollowingPath
method is called, the tank
or arcade
method of the modular drivetrain must be called repeatedly (ex. in a command) in order for the path to be followed. To simplify this, you can use the FollowPathCommand
.
// This requires that you pass in the drivetrain subsystem as well as the modular drivetrain - this ensures that only one command is running on the drivetrain at the same time
var pathCommand = new FollowPathCommand(drivetrainSubsystem, drivetrain, path);
The power efficiency module ramps up/down the drivetrain to avoid large current spikes which draw unnecessary power and could even lead to a brownout on the Roborio.
double secondsToReachFullSpeed = 0.5;
double turningThreshold = 0.1;
var powerModule = new PowerEfficiency(secondsToReachFullSpeed, turningThreshold);
The precision module allows for finer movement at slower speeds. This is useful if you need to be precise when interacting with game pieces.
double strength = 0.5;
var precisionModule = new PrecisionModule(strength);
The shifter module allows for easier gear shifting. Note: FRC team 5112 has not used shifters on our robots, so we were not able to test this on an actual bot.
GearShifter shifter = /* Get your robot's gear shifter here */
Trigger upshiftTrigger = /* Map the upshift trigger to a button */
double shiftStopTime = 0.1; // the time in seconds it should take to switch gears safely
var shifterModule = new ShifterModule(shifter, shiftStopTime);
To upshift or downshift, the following methods can be used:
shifterModule.upshift();
shifterModule.downshift();
After a shift is requested, the modular drivetrain's arcade
or tank
method must be called for the shift to actually occur.
The speed constraint module limits the maximum speed of the robot. This is useful if your drivetrain is too fast and is hard for the drivers to control.
double maxSpeed = 0.9; // 90% power
boolean shouldScaleSpeeds = true; // Scale the joystick input from -0.9 to 0.9, rather than a sharp cutoff
var speedModule = new SpeedConstraintModule(maxSpeed, shouldScaleSpeeds);
The stability module corrects the rotational drift of a drivetrain using a gyroscope. This can be used if you see that your robot should be driving straight but is going to the left or right. This module can also be used to drive straight over obstacles or when being hit by another robot.
double strength = 0.02; // Between 0 and 1
double settlingTime = 0.5; // The settling time in seconds
Gyro gyro = /* Get your robot's gyroscope */
var stabilityModule = new StabilityModule(gyro, strength, settlingTime);
The strength determines how much the robot will move to correct drift.
The settling time can be used to allow the robot to come to a complete stop when the drive turns it and then stops before setting the new heading. This value represents the time to wait after the driver stops turning to begin correcting the drift.
The target alignment module allows your robot to align to a target using a camera. This module allows the robot to both aim at the target and drive to a specific distance away from the target. This is useful for shooting into a target or any game in which a vision target must be used. This module works best with the Limelight, other cameras may have too much latency but may still be usable.
ITargetingCamera camera = /* Get your robot's camera here */
// Set either strength to 0 to ignore it (ex. setting aimStrength to 0 will make the robot only drive to a specific range) - both can't be 0 though
double aimStrength = 0.1;
double rangeStrength = 0.1;
boolean shouldSeek = true; // Should the robot spin in place to find the target if it can't see it at first
var alignmentModule = new TargetAlignmentModule(camera, aimStrength, rangeStrength, shouldSeek);
// Note: There are more properties that can be accessed through setters such as thresholds for the aim and range, and the seek speed
To start aligning, you can use the following method:
double desiredHorizontalOffset = 0; // degrees - 0 centers the robot with the target
double desiredTargetArea = 50; // Percent of the image area, can be used as an estimate of distance
alignmentModule.align(desiredHorizontalOffset, desiredTargetArea);
// Determine if it is aligning
boolean isAligning = alignmentModule.isAligning();
// Stop aligning
alignmentModule.stopAligning();
The traction control module can be used to ensure both sides of the drivetrain spin at the same speed and maintain traction. This can be used if you notice your robot is slipping when accelerating or is having trouble getting a grip on the playing field.
Encoder leftEncoder = /* Get your robot's left encoder here */
Encoder rightEncoder = /* Get your robot's right encoder here */
double strength = 0.1;
double slipThreshold = 0.1;
var tractionModule = new TractionControlModule(leftEncoder, rightEncoder, strength, slipThreshold);
The velocity control module can be used to set the drivetrain motors to a set velocity rather than voltage or PWM.
double maxVelocity = 10; // In same units as encoder / second
double strength = 0.1;
Encoder leftEncoder = /* Get your robot's encoder here */
Encoder rightEncoder = /* Get your robot's encoder here */
var velocityModule = new VelocityControlModule(leftEncoder, rightEncoder, maxVelocity, strength);
To set the robot to the velocity do the following:
double desiredVelocity = 9;
modularDrivetrain.set(desiredVelocity / maxVelocity);
The voltage control module can be used to keep the drivetrain motors running at a consistent voltage even though the battery voltage of the robot might fluctuate. This is useful if you want the robot's movement to be more predictable and consistent throughout a match.
double maxDriveVoltage = 12;
var voltageModule = new VoltageControlModule(maxDriveVoltage);