Java Command Based Command

New to Command Based… We are about to start coding the commands for each subsystem and before we get too far, we need the following info on how to handle multiple commands…

For example, we have a feeder motor… we want a command to FeederOn(clockwise), FeederOnRev(counterclockwise) and FeederOff…

We created a Feeder_Command class…


public class TeleopFeederOn_Command extends Command{
	@Override
	protected void execute(){
		while(Robot.oi.getOperatorJoystick().getRawButton(4) ==true){
			Robot.fuelFeederSubsystem.FeederOn();
		}
		Robot.fuelFeederSubsystem.FeederOff();	
	}
	@Override
	protected boolean isFinished() {
		// TODO Auto-generated method stub
		return false;
	}
	@Override
	protected void end() {
		Robot.fuelFeederSubsystem.FeederOff();
	}
	@Override
	protected void interrupted(){
		end();
	}	
}

That should take care of our FeederOn command using button 4. Now should we build a new command class for FeederOnRev (button5) or do we want to add the command to this class?

If you want a button to execute a command you should be doing this in the OI class.
See here for an example: https://wpilib.screenstepslive.com/s/4485/m/13809/l/599739-running-commands-on-joystick-input

Basically:

  • create a command for each of your actions (or one that takes in a parameter for the “speed” to pass on to the motors).
  • In OI, you link the command to execute to a Joystick action on a button (e.g. WhenPressed, WhileHeld, etc.).
  • the execute method of your command is just going to call in to the subsystem it requires and call the right setter method that ultimately calls someMotorName.set(speed).

To specifically address your code example, get rid of everything except “Robot.fuelFeederSubsystem.FeederOn();” in the execute method. Then add something like the following to the OI class:

Joystick myJoystick = new Joystick(0);
Button aButton = new JoystickButton(myJoystick, 5);

...

aButton.whileHeld(new TeleopFeederOn_Command());

Check the Javadoc for Buttonto see understand what the different methods for button presses (whileHeld, whenPressed…) do.

The guides for command based programming on screensteps live are pretty good. You could also use RobotBuilder to generate some example code to see what the “right” way to do it is. And there’s also lots of example code out there to pull from.

I think you need to override the initialize method as well for your command, then use requires(fuelFeederSubsystem) just to make sure you don’t get two commands using said system at the same time.

Also, it seems you are using the command in a strange way. You could just put the code in the execute method into the teleOp periodic method (in Robot) and it would run perfectly fine.

Whether you create several classes for each command or add a parameter to your constructor to indicate the action to take is a matter of choice. Both methods will work.

Here is an example of a FeederOffCommand implementation based on what you’ve shown:


public class FeederOffCommand extends Command {

    public FeederOffCommand() {

      // Since this command will change the state of the feeder subsystem
      // it MUST require it!
      requires(Robot.fuelFeederSubsystem);

    }
    
    @Override
    protected void execute(){

        // This could be moved to initialize if you don't need to continuously
        // call this method to keep the feeder off
        Robot.fuelFeederSubsystem.FeederOff();  
    }

    @Override
    protected boolean isFinished() {
        return false;
    }

    @Override
    protected void end() {
        // Redundant for this command, but does not hurt
        Robot.fuelFeederSubsystem.FeederOff();
    }

    @Override
    protected void interrupted(){
        end();
    }   
}

As mentioned in earlier posts, the requires() invocation in the constructor is very important as it tells the robot’s scheduler that this command will manipulate the feeder subsystem and interrupt any other commands requiring the same subsystem (this prevents multiple commands from trying to change the state of a subsystem at the same time).

Another thing to notice is that the example above does not actually provide a way to actually invoke the command. To do that you can add a static method to your OI class or add it to the OI constructor that “glues” your commands to buttons. For example the following will cause the FeederOffCommand to start running when the user presses button 5 on the joystick. It also adds a button to the smart dash board so you can test the command when you don’t have a joystick (or run out of buttons):


    void initialize() {
      // When user presses button 5 on joystick, fire off command to stop the feeder
      Button feederOffButton = new JoystickButton(myJoystick, 5);
      feederOffButton.whenPressed(new FeederOffCommand());
      
      // Let's add one to the smart dashboard as well so we can test without the joystick
      SmartDashboard.putData("Stop Feeder", new FeederOffCommand());
    }

If you create a separate method like the one shown above, you will need to invoke it in your robotInit() method in your Robot.java file.

Finally, the commands can be used in both teleop and autonomuos modes. For example, if you want to turn off the feeder at the end of autonomous, you could add a new FeederOffCommand instance to your autonomous command group.

Good luck and I hope that helps.