Command Based Questions

I have a few questions about Command Based.

We have a couple pneumatic cylinders on our robot. I am currently using a constructor with a variable to control one of them, like this:


        Button shiftButton = new JoystickButton( operatorJoystick, 1 );
        shiftButton.whenPressed( new ShiftCommand( Gear.HIGH ) );
        shiftButton.whenReleased( new ShiftCommand( Gear.LOW ) );

The other I am using a TimedCommand which I have added an additional command to determine if it is timed or not, for the purpose of autonomous. In TeleOp, it is bound to toggleWhenPressed so the timing is not needed.


        Button gearButton = new JoystickButton( operatorJoystick, 3 );
        gearButton.toggleWhenPressed( new DropGear() );

These work as expected, but I am wondering if there are better ways to accomplish this sort of thing.

My second question is regarding subsystems. I’m really not sure how “require” works and how or when interrupted() will be called. For now, I am leaving out all require statements as my code won’t work with them. I don’t think this is good practice though.

My third question is regarding non-subsystem non-command classes. How do these fit into the Command based framework? I have them in the same package as Robot, RobotMap, and OI currently. The way I am writing code “works”, but I would like to pass on better practices to the future programmers (I am a senior on a Rookie team :ahh:)

My rules of thumb are:

  • ALWAYS use requires() in your command’s constructor when your command manipulates or changes the state of a subsystem.
  • Omit the requires() in your command’s constructor if it does not use a subsystem or only uses “read-only” features from a subsystem.
  • By default, your interrupt() method should always call your end() method (there are only special cases where you might not want to do this and I would address them as they occur).

Example of what happens when you don’t use requires when you should:

  • Default drive command responds to gamepad and allows operator to drive the robot.
  • You add a new smart “rotate 90 degree” button the driver can press
  • If the requires() is missing from these two commands, then they will run at the same time when the driver presses the button.
  • This will cause the two commands to fight each other as they both send different power outputs to the motors (things won’t be pretty).

Example of when to skip using requires:

  • You have a button command to open your gear collector.
  • You want the command to be smart and not allow the collector to open if the robot is moving backwards quickly.
  • Your drive subsystem has a getVelocity() command you want to check to see the direction of the robot’s movement.
  • Since calling getVelocity() doesn’t change the state of the drive subsystem, you will want to omit the requires.
  • If you accidentally include the requires in your new command, the normal gamepad drive will be interrupted and the operator won’t be able to control the robot when they try to open the gear collector.

The interrupt feature is used when you have multiple commands using the same subsystem. Here is an example:

  • You have one button programmed to drive forward until a bump is detected from the built in accelerometer.
  • You have another button that stops the robot (sets output power to 0 while pressed).
  • The driver presses the drive until bump command to place a gear.
  • The driver doesn’t like how things are looking and presses the stop button.
  • The drive until bump command will be interrupted by the stop command and its interrupt() method will be invoked instead of its end() method.
  • The stop command will then run and set the motors to 0.
  • When the stop button is released, its end() or interrupt() method will be invoked and the default command for the subsystem (probably a drive with gamepad type of command) will take over.

Not all classes need to be Commands or Subsystems in a command based Java project. You may often have utility classes or special classes for special sensors. I like to think of the standard Robot, RobotMap and OI classes as the glue used to construct and run your commands and subsystems.

Hope that helps.

Thank you, that helps alot.

We have a shifting drive train, and the code to control the pnuematics is in the drive train subsystem, but controlled by a different command than the rest of it. What would you recommend in this situation?

In order to keep the commands simple, I would be tempted to break the gear shifting component out into its own transmission subsystem. This would allow the engine (motors) portion of your robot to be controlled separately from your transmission.

  • Manual commands to shift gears would only need to require or know about the transmission subsystem.
  • An automatic transmission command, would need to require the transmission subsystem. However it might also need to use some of the read-only methods from the drive subsystem. For example, this command might decide to shift to high gear when the speed reaches 2 meters/sec and then shift back to low gear if the speed falls below 1 meters/sec. Since the automatic shift command is only using the drive subsystem to query the speed of the robot, it does not need to require the drive subsystem. It will still need to require the transmission subsystem as it is actively controlling it.
  • The automatic shifting command could be the default command for the transmission subsystem (driver doesn’t need to think about shifting unless they want to manually control it).
  • Alternatively, you could omit the default command on the transmission and provide the driver with button presses to shift gears.

If you decide to implement an automatic transmission, be a bit careful and ready to hit the disable key. There can be a surprising number of cases to handle and you can easily find your robot slamming between high and low gear repeatedly and quickly. I’d recommend including a minimum time between shifts check until you are happy with your logic.