wiki:ControlSystems/SoftwareTeam/Training/WPILib/CommandGroupProgramming

The last example showed two simple commands and how to connect them with the user interface, but the commands were simple: they set a servo position and immediately finished. In practice, robot commands often need to run continuously until something happens; for example, a command to raise an arm might start a motor moving and continue until some time has passed or an encoder indicates that the arm has moved a certain distance or a limit switch is pressed. WPILib commands make this easy. Even better, you can string several such commands together in a CommandGroup to effect complex behaviors.

Commands can be grouped together to run in sequence for example, when the X button is pressed, the following code will run the servo open command, allow time for it to finish, and then run the servo close command. The OpenCommand adds a Timer to allow the servo motor time to complete moving to the open position before the CloseCommand is run :

Constants.java

package frc.robot;

public final class Constants {
    public static int SERVO_PORT = 0;   // PWM port for servo motor
    public static int OPEN_BUTTON = 1;  // A button opens mechanism
    public static int CLOSE_BUTTON = 2; // B button closes mechanism   
    public static int OPEN_THEN_CLOSE_BUTTON = 3; // X button opens then closes
}

ServoSubSystem.java:

package frc.robot.subsystems;

import edu.wpi.first.wpilibj2.command.SubsystemBase;
import frc.robot.Constants;
import edu.wpi.first.wpilibj.Servo;

public class ServoSubsystem extends SubsystemBase {
  private Servo servo;
  private static ServoSubsystem instance = null;

  private ServoSubsystem() {
      servo = new Servo(Constants.SERVO_PORT);
  }

  // Singleton design pattern
  public static ServoSubsystem getInstance() {
      if (instance == null) {
          instance = new ServoSubsystem();
      }
      return instance;
  }

  public void setAngle(double degrees) {
    servo.setAngle(degrees);
  }
}

OpenCommand.java

package frc.robot.commands;

import edu.wpi.first.wpilibj2.command.CommandBase;
import edu.wpi.first.wpilibj2.command.SubsystemBase;
import frc.robot.subsystems.ServoSubsystem;
import edu.wpi.first.wpilibj.Timer;

public class OpenCommand extends CommandBase {
  private Timer delayTimer;

  public OpenCommand(SubsystemBase servoSubsystem) {
      delayTimer = new Timer();
      addRequirements(servoSubsystem);
  }

  @Override
  public void initialize() {
    ServoSubsystem.getInstance().setAngle(30); // set servo to open position
    delayTimer.start();
  }

  @Override
  public boolean isFinished() {
    return delayTimer.hasPeriodPassed(0.5); // allow 500ms for command to finish
  }
}

CloseCommand.java

package frc.robot.commands;

import edu.wpi.first.wpilibj2.command.CommandBase;
import edu.wpi.first.wpilibj2.command.SubsystemBase;
import frc.robot.subsystems.ServoSubsystem;

public class CloseCommand extends CommandBase {

    public CloseCommand(SubsystemBase servoSubsystem) {
        addRequirements(servoSubsystem);
    }

    @Override
    public boolean isFinished() {
        ServoSubsystem.getInstance().setAngle(120); // set servo to closed position
        return true;                 // and then finish
    }
}

OpenThenCloseCommand.java:

package frc.robot.commands;

import edu.wpi.first.wpilibj2.command.SequentialCommandGroup;
import edu.wpi.first.wpilibj2.command.SubsystemBase;

public class OpenThenCloseCommand extends SequentialCommandGroup {

    public OpenThenCloseCommand(SubsystemBase servoSubsystem) {
        this.addCommands(new OpenCommand(servoSubsystem), new CloseCommand(servoSubsystem));
    }
}

RobotContainer.java:

package frc.robot;

import edu.wpi.first.wpilibj.XboxController;
import edu.wpi.first.wpilibj2.command.button.Button;
import edu.wpi.first.wpilibj2.command.button.JoystickButton;
import edu.wpi.first.wpilibj2.command.Command;
import frc.robot.subsystems.ServoSubsystem;
import frc.robot.commands.OpenCommand;
import frc.robot.commands.CloseCommand;
import frc.robot.commands.OpenThenCloseCommand;

public class RobotContainer {
  private final ServoSubsystem m_servo = ServoSubsystem.getInstance();
  private final XboxController xbox;
  private final Button openButton, closeButton, openThenCloseButton;

  public RobotContainer() {
    xbox = new XboxController(0);
    openButton = new JoystickButton(xbox, Constants.OPEN_BUTTON);
    closeButton = new JoystickButton(xbox, Constants.CLOSE_BUTTON);   
    openThenCloseButton = new JoystickButton(xbox, Constants.OPEN_THEN_CLOSE_BUTTON);

    // Configure the button bindings
    configureButtonBindings();
  }

  private void configureButtonBindings() {
    openButton.whenPressed(new OpenCommand(m_servo));
    closeButton.whenPressed(new CloseCommand(m_servo));
    openThenCloseButton.whenPressed(new OpenThenCloseCommand(m_servo));
  }

  public Command getAutonomousCommand() {
    return null;
  }
}
Last modified 15 months ago Last modified on Feb 27, 2020, 11:08:46 PM