-
Notifications
You must be signed in to change notification settings - Fork 3
Tutorial 03: More than one subsystem
I don't know what robot you (whoever you are) has access to, but nearly every robot has one of the following:
- Some sort of lifter/arm. Spinning a motor one way makes it go up, and the other way makes it go down.
- Some sort of shooter or wheel, for something other than driving.
- At least one motor for something other than driving, that you may want to spin one way or the other.
I'm going to be calling it a lifter, but you can change the name to whatever makes sense for your bot. We're going to make it so that holding one button makes the motor spin forwards/upwards, and holding the other button makes it spin backwards/downwards. We won't be introducing any new concepts here, so as an exercise, you might want to see if you can guess how this would work and try it, before reading. Really, I just want to set up for the next tutorial, where I'll talk about how commands and subsystems work in more detail, and I need the robot to be able to do two things independent of each other.
As before, add a constant for the motor to RobotMap
:
public class RobotMap {
public static class Drive {
@Port(type = Type.PWM) public static final int LEFT_MOTOR = 0;
@Port(type = Type.PWM) public static final int RIGHT_MOTOR = 1;
}
public static class Lifter {
@Port(type = Type.PWM) public static final int LIFT_MOTOR = 2;
}
}
Create a subsystem, with three commands: up, down, and stop. Here, I
use constants UP_POWER
and DOWN_POWER
, to avoid having "magic
numbers" floating around in the code. Later, we'll replace these with
preferences, so that we can adjust them without having to compile and
deploy again.
public class LifterSubsystem extends Subsystem {
private VictorSP liftMotor = new VictorSP(RobotMap.Lifter.LIFT_MOTOR);
private static final double UP_POWER = 0.5;
private static final double DOWN_POWER = -0.5;
@Override
protected void initDefaultCommand() {
setDefaultCommand(stopCmd());
}
public Command upCmd() {
return QuickCommand.continuous(this, () -> {
liftMotor.set(UP_POWER);
});
}
public Command downCmd() {
return QuickCommand.continuous(this, () -> {
liftMotor.set(DOWN_POWER);
});
}
public Command stopCmd() {
return QuickCommand.continuous(this, () -> {
liftMotor.set(0.0);
});
}
}
Remember to add an instance to the Robot
class, and initialize it in
initSubsystems
. I'll leave this part as an exercise to the reader.
Last, bind the up and down commands to buttons in OIMap
. I'll add
them to the right driver stick. (I'm assuming that instance you made
earlier is called lifter
here.)
public static class RightDriver {
@WhileHeld(1) public final Command lifterUp = Robot.lifter.upCmd();
@WhileHeld(2) public final Command lifterDown = Robot.lifter.downCmd();
}
And that should be it! While you test this, notice how you can
start/stop driving, and move the lifter up/down/stopped, independent
of each other. However, upCmd
and downCmd
should never run at the
same time, just how driveCmd
and stopCmd
didn't in the last
tutorial. Next, we'll look at how commands and subsystems work in
more detail to see why this is, and how you can use it effectively.