One of the first things we need to do, is get the robot's drivebase moving. This issue plays a key part in the process.
This issue is written a bit like a tutorial, just to make sure everyone knows what they are doing. Future issues will be less hand-hold-y
Outline
Here is a quick outline of all that needs to get done:
Fill out method stub for controlling the robot with driver inputs
Make the DriveTrain stateful
Add Open-Loop controller
Add Closed-Loop voltage controller & overload to accept WPILib's inputs
Add a stub for ramp-rate control
Add a "safety stop" method
Stub out state-handling logic
Getting started
This is just a reminder to make, and switch to a new branch of the project before starting work. If you do not know how to do this, ask a returning team member.
All of the work outlined in this issue is to be done in the DriveTrain class located at src/main/java/frc/robot/subsystems/DriveTrain.java. We will need a RobotLogger instance for the DriveTrain (I forgot to add it when setting up the project). Just create a public static object of RobotLogger at the top of the DriveTrain source. It should look something like this:
public class DriveTrain extends SubsystemBase {
private RobotLogger logger = RobotLogger.getInstance();
...
Making the DriveTrain stateful
We will talk about autonomous control a little later (probably week 2), it will require the DriveTrain to behave a little differently than when the drivers are controlling the robot. Because of this, we will have to give the DriveTrain a way to know which "mode" it is running in. We can do this with a simple enum.
For now, I think well only need to define 2 modes:
Open-Loop
Used to control the robot with "percent output". This is basically telling the robot to do things like "move at 50% speed forward".
This is how we will control the robot from Xbox controller inputs
Voltage control
As the name suggests, this will be a method of controlling the robot by specifying how much voltage to send to each motor.
These modes can be defined with the following enum. Remember to comment the code (please). For the new members, this should be defined above the class constructor (private DriveTrain())
/**
* Drive control modes
*/
public enum DriveMode {
OPEN_LOOP, // Open loop control (percent output control)
VOLTAGE // Voltage control
}
We will also want a private variable just to keep track of the current mode
// Keep track of the current DriveMode
private DriveMode m_currentDriveMode = DriveMode.OPEN_LOOP;
Open-Loop & Voltage controllers
Before starting, we will need another private variable to keep track of the current DriveSignal. Name it m_currentSignal.
We need a method to actually specify our inputs. We'll start with the Open-Loop input. Voltage control is very similar. The idea of these methods is,
Check if the DriveTrain is currently running in a diffrent mode
If so, do anything needed to safely switch mode, and log the mode change
Set the "desired output"
Ill write the Open-Loop controller as an example
/**
* Set the Open loop control signal. The values of this signal should be in the
* rage of [-1.0-1.0]
*
* @param signal Open loop signal
*/
public void setOpenLoop(DriveSignal signal) {
// Force-set the mode if not already set
if (m_currentDriveMode != DriveMode.OPEN_LOOP) {
// Enable motor brakes
setBrakes(true);
// Log the state change
logger.log("DriveTrain", String.format("Set control mode to OPEN_LOOP with signal: %s", signal.toString()));
// Set the new state
m_currentDriveMode = DriveMode.OPEN_LOOP;
}
// Set the current DriveTrain signal
m_currentSignal = signal;
}
Make sure to also add a method called setVoltage. It should be similar, except all references to OPEN_LOOP should be changed to VOLTAGE, and the brakes value should be false.
Make sure to update the javadoc at the top. The setVoltage method will take values from -12.0 to 12.0.
WPILib also requires a slightly different method. Just overload setVoltage (create another method with the exact same name) and make it take in two double values. called "left" and "right". With these values, create a DriveSignal object, and pass it into the other setVoltage method. This can be done in one line with
setVoltage(new DriveSignal(left, right));
Remember: Comment, and add a javadoc to each method
Ramp Rate
We need a method stub for ramp rate control. Just call it setRampRate, and make it take a double. Also, add a comment that says something like TODO: Method stub. We will fill this out once we have sorted out our motor controllers.
Safety Stop
Add a method called stop, and make it call setOpenLoop with a DriveSignal of zero (new DriveSignal(0,0))
Call this in Robot.java in the disabledInit method near the bottom. Just call m_driveTrain.stop(); (and add a comment describing why it's there).
Controlling the bot
We need a way to let the drivers control the bot. I have already stubbed out a drive method. Just add the following logic for me:
// Square inputs
speed = InputUtils.scale(speed, ScalingMode.SQUARED);
rotation = InputUtils.scale(rotation, ScalingMode.SQUARED);
// Compute a DriveSignal from inputs
DriveSignal signal = DifferentialDriveCalculation.semiConstCurve(speed, rotation);
// Set the signal
setOpenLoop(signal);
This will square the inputs, then calculate, and set a DriveSignal.
Stubbing state handling
We have no logic to do for each state yet, so just add this statement to the periodic method:
// Handle motor outputs for each mode
switch (m_currentDriveMode) {
case OPEN_LOOP:
// Set Open loop outputs for motors
// TODO: Set outputs here (reading from m_currentSignal)
break;
case VOLTAGE:
// Set Voltage outputs for motors
// TODO: Set outputs here (reading from m_currentSignal)
break;
default:
// This code should never run, but if it does, we set the mode to OPEN_LOOP, and
// the outputs to 0
setOpenLoop(new DriveSignal(0, 0));
}
Once finished
Once this is finished, make sure it builds, then open a Pull Request on GitHub from your branch into master. Ill review it, then merge it.
One of the first things we need to do, is get the robot's drivebase moving. This issue plays a key part in the process.
This issue is written a bit like a tutorial, just to make sure everyone knows what they are doing. Future issues will be less hand-hold-y
Outline
Here is a quick outline of all that needs to get done:
Getting started
This is just a reminder to make, and switch to a new branch of the project before starting work. If you do not know how to do this, ask a returning team member.
All of the work outlined in this issue is to be done in the DriveTrain class located at
src/main/java/frc/robot/subsystems/DriveTrain.java
. We will need a RobotLogger instance for the DriveTrain (I forgot to add it when setting up the project). Just create a public static object ofRobotLogger
at the top of the DriveTrain source. It should look something like this:Making the DriveTrain stateful
We will talk about autonomous control a little later (probably week 2), it will require the DriveTrain to behave a little differently than when the drivers are controlling the robot. Because of this, we will have to give the DriveTrain a way to know which "mode" it is running in. We can do this with a simple enum.
For now, I think well only need to define 2 modes:
These modes can be defined with the following enum. Remember to comment the code (please). For the new members, this should be defined above the class constructor (
private DriveTrain()
)We will also want a private variable just to keep track of the current mode
Open-Loop & Voltage controllers
Before starting, we will need another private variable to keep track of the current DriveSignal. Name it
m_currentSignal
.We need a method to actually specify our inputs. We'll start with the Open-Loop input. Voltage control is very similar. The idea of these methods is,
Ill write the Open-Loop controller as an example
Make sure to also add a method called
setVoltage
. It should be similar, except all references toOPEN_LOOP
should be changed toVOLTAGE
, and the brakes value should befalse
.Make sure to update the javadoc at the top. The
setVoltage
method will take values from-12.0
to12.0
.WPILib also requires a slightly different method. Just overload
setVoltage
(create another method with the exact same name) and make it take in twodouble
values. called "left" and "right". With these values, create aDriveSignal
object, and pass it into the other setVoltage method. This can be done in one line withRemember: Comment, and add a javadoc to each method
Ramp Rate
We need a method stub for ramp rate control. Just call it
setRampRate
, and make it take adouble
. Also, add a comment that says something likeTODO: Method stub
. We will fill this out once we have sorted out our motor controllers.Safety Stop
Add a method called
stop
, and make it callsetOpenLoop
with a DriveSignal of zero (new DriveSignal(0,0)
)Call this in
Robot.java
in thedisabledInit
method near the bottom. Just callm_driveTrain.stop();
(and add a comment describing why it's there).Controlling the bot
We need a way to let the drivers control the bot. I have already stubbed out a
drive
method. Just add the following logic for me:This will square the inputs, then calculate, and set a DriveSignal.
Stubbing state handling
We have no logic to do for each state yet, so just add this statement to the
periodic
method:Once finished
Once this is finished, make sure it builds, then open a Pull Request on GitHub from your branch into master. Ill review it, then merge it.