Commands & Buttons

In this next chapter we will learn how to connect a command to a button on the joystick so that command will be executed when the button is pressed. We are going to connect our previously created DriveForTimeCommand to button 1 (i.e. the trigger button) on the joystick so that when we press that button, the DriveForTimeCommand will override the normally running ArcadeDriveCommand and make the robot drive forward for a period of time.

Open the file OI.java and you will currently see:

package robot;

import robotCore.Joystick;
import robotWpi.buttons.Button;
import robotWpi.buttons.JoystickButton;

/**
 * This class is the glue that binds the controls on the physical operator
 * interface to the commands and command groups that allow control of the robot.
 */
public class OI {
    //// CREATING BUTTONS
    // One type of button is a joystick button which is any button on a joystick.
    // You create one by telling it which joystick it's on and which button
    // number it is.
     Joystick m_stick = new Joystick(0);
     Button m_trigger = new JoystickButton(m_stick, 1);
    
    // There are a few additional built in buttons you can use. Additionally,
    // by subclassing Button you can create custom triggers and bind those to
    // commands the same as any other Button.
    
    //// TRIGGERING COMMANDS WITH BUTTONS
    // Once you have a button, it's trivial to bind it to a button in one of
    // three ways:
    
    // Start the command when the button is pressed and let it run the command
    // until it is finished as determined by it's isFinished method.
    public OI()
    {
//    	m_trigger.whenPressed(new ExampleCommand());
    }
}

Since this class will need to access the joystick, you can see that it is already creating an instance of the Joystick class. We also need one instance of the Button class for each button that we wish to control and, as you can see, there is already one created (m_trigger) which will monitor button 1 on the joystick, which is the trigger button.

Now to connect the button to a specific command we add a line to the OI() constructor like the one you see commented out:

    	m_trigger.whenPressed(new DriveForTimeCommand(0.75, 2));

This tells the command system to execute the DriveForTimeCommand(0.75, 2) whenever the trigger button is pressed which will result in the robot driving forward at three quarters power for two seconds.

You OI.java file should now look like:

package robot;

import commands.DriveForTimeCommand;
import robotCore.Joystick;
import robotWpi.buttons.Button;
import robotWpi.buttons.JoystickButton;

/**
 * This class is the glue that binds the controls on the physical operator
 * interface to the commands and command groups that allow control of the robot.
 */
public class OI {
    //// CREATING BUTTONS
    // One type of button is a joystick button which is any button on a joystick.
    // You create one by telling it which joystick it's on and which button
    // number it is.
     Joystick m_stick = new Joystick(0);
     Button m_trigger = new JoystickButton(m_stick, 1);
    
    // There are a few additional built in buttons you can use. Additionally,
    // by subclassing Button you can create custom triggers and bind those to
    // commands the same as any other Button.
    
    //// TRIGGERING COMMANDS WITH BUTTONS
    // Once you have a button, it's trivial to bind it to a button in one of
    // three ways:
    
    // Start the command when the button is pressed and let it run the command
    // until it is finished as determined by it's isFinished method.
    public OI()
    {
    	m_trigger.whenPressed(new DriveForTimeCommand(0.75, 2));
    }
}

Now deploy and run your program. Verify that you can still drive the robot around using the joystick, and then press the trigger button and the robot should drive forward for 2 seconds. Note that while the DriveForTimeCommand is executing, you can no longer control the robot with the joystick. This is because the DriveForTimeCommand has temporarily interrupted the ArcadeDriveCommand because it needs to use the DriveSubsystem which is also required by the ArcadeDriveCommand. Note, however, that once the DriveForTimeCommand has completed, the ArcadeDriveCommand starts running again and we can control the robot with the joystick.

If we take a look at the logging information in our Console window, we can see just how these events unfold:

31303:DriverStation(2):Enable()					// Robot enabled
0:Robot(2):teleopInit()							// Teleop mode started
8:DriveSubsystem(2):initDefaultCommand()		// Start default command for the DriveSubsystem
10:ArcadeDriveCommand(3):ArcadeDriveCommand()	// Create the ArcadeDriveCommand
26:ExampleSubsystem(2):initDefaultCommand()		// Start default command for the ExampleSubsystem
49:ArcadeDriveCommand(2):initialize()			// Start the ArcadeDriveCommand
15071:ArcadeDriveCommand(2):interrupted()		// The trigger button was pressed, interrupt the ArcadeDriveCommand
15084:DriveForTimeCommand(2):initialize()		// Start the DriveForTimeCommand
17100:DriveForTimeCommand(2):end()				// The timer has expired, end the DriveForTimeCommand
17114:ArcadeDriveCommand(2):initialize()		// Restart the ArcadeDriveCommand

I have added comments to each log line explaining what that line means.

Next: Wheel encoders