frc5024 / InfiniteRecharge

The source and tooling behind FRC team 5024's 2020 competition robot
http://cs.5024.ca/InfiniteRecharge/
MIT License
11 stars 2 forks source link

Add DriveTrain and control stubs, and fill in abstract DriveTrain code #21

Closed ewpratten closed 4 years ago

ewpratten commented 4 years ago

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 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:

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,

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.

ewpratten commented 4 years ago

This is finished, and waiting on #34 to be merged