For the complete documentation index, see llms.txt. This page is also available as Markdown.
Arm
We will learn how to program an Arm!
Mechanism classes are meant to be used with "tightly coupled" mechanisms where the Mechanism has 1 or more motor controlling it on a connected shaft, gearbox, or other linkage.
IF your mechanism is "loosely coupled", you CAN still use YAMS. HOWEVER you have to create and control the SmartMotorController directly as shown in How do I control a Mechanism without a Mechanism Class? OR use SmartMotorControllerConfig.withLooselyCoupledFollowers(SmartMotorController...)
Intro
At the end of this tutorial you will have an Arm that will work in both real life and simulation with the same code!
Simulation
Real Life
Details
This Arm will be using the following hardware specs and control details
SparkMax controlling the Arm
12:1 GearBox on the Arm
Pressing A will make the Arm go to -5deg
Pressing B will make the Arm go to 15deg
Pressing X will make the Arm go up.
Pressing Y will make the Arm go down.
Lets create a WPILib Command-Based Project!
IF you already have a project and know how to place the Arm mechanism into your own subsystem please skip to Install YAMS!
Setup our Command-Based Project
Here we will follow WPILib's tutorial on how to create a Command-Based project.
Bring up the Visual Studio Code command palette with Ctrl+Shift+P. Then, type “WPILib” into the prompt. Since all WPILib commands start with “WPILib”, this will bring up the list of WPILib-specific VS Code commands. Now, select the “Create a new project” command:
This will bring up the “New Project Creator Window:”
Click on Select a project type (Example or Template)
Select Template then Java then Command Robot
Click on Select a new project folder and select a folder to store your robot project in.
Fill in Project Name with the name of your robot code project.
Enter your Team Number in so you can deploy to your robot.
Be sure to check Enable Desktop Support so we can run simulations!
If you followed these instructions it should look something like whats filled out below.
Congratulations! You now have a Command Based robot project!
Install YAMS!
Click on the WPILib logo on the left pane. Scroll down to Yet Another Mechanism System and click Install!
Congratulations you have now installed YAMS! 🎉
Lets make an Arm move!
1
Create a SmartMotorControllerConfig
We are going to start by configuring out motor controller.
2
Create our motor controller
To control our Arm motor we will create the vendor motor controller object.
First we install REVLib by clicking on the WPILib logo in the left bar.
Now we add it to the ExampleSubsystem.java
3
Create our SmartMotorController
Our SmartMotorController will easily configure and interface with the vendor motor controller object.
4
Create and Configure our Arm
Our Arm will easily configure the SmartMotorController and create a simple and intuitive interface.
5
Create Commands with our Arm
We use the Arm class as a interface to create commands!
6
Bind buttons to our Arm
We bind buttons to use the Commands from our Arm
7
Simulate our Arm!
We can use our Arm in simulation, with the exact same code that will control the real robot!
Connect an Xbox controller to your system and drag and drop from System Joysticks to Joystick[0]
Open up the Simulated mechanism with NetworkTables -> SmartDashboard -> Arm -> mechanism
Resize Arm/mechanism to your liking
Press Teleoperated in Robot State then you can use your controller like its controlling the real robot!
Congratulations on successfully programming your Arm!! 🎉🎉
Complete Example
The following files show a complete, working Arm implementation matching the hardware described in this tutorial.
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
package frc.robot.subsystems;
import static edu.wpi.first.units.Units.Amps;
import static edu.wpi.first.units.Units.DegreesPerSecond;
import static edu.wpi.first.units.Units.DegreesPerSecondPerSecond;
import static edu.wpi.first.units.Units.Seconds;
import edu.wpi.first.math.controller.ArmFeedforward;
import edu.wpi.first.wpilibj2.command.Command;
import edu.wpi.first.wpilibj2.command.SubsystemBase;
import yams.mechanisms.SmartMechanism;
import yams.motorcontrollers.SmartMotorControllerConfig;
import yams.motorcontrollers.SmartMotorControllerConfig.ControlMode;
import yams.motorcontrollers.SmartMotorControllerConfig.MotorMode;
import yams.motorcontrollers.SmartMotorControllerConfig.TelemetryVerbosity;
public class ExampleSubsystem extends SubsystemBase {
private SmartMotorControllerConfig smcConfig = new SmartMotorControllerConfig(this)
.withControlMode(ControlMode.CLOSED_LOOP)
// Feedback Constants (PID Constants)
.withClosedLoopController(50, 0, 0)
.withTrapezoidalProfile(DegreesPerSecond.of(90), DegreesPerSecondPerSecond.of(45))
.withSimClosedLoopController(50, 0, 0)
// Feedforward Constants
.withFeedforward(new ArmFeedforward(0, 0, 0))
.withSimFeedforward(new ArmFeedforward(0, 0, 0))
// Telemetry name and verbosity level
.withTelemetry("ArmMotor", TelemetryVerbosity.HIGH)
// Gearing from the motor rotor to final shaft.
// In this example GearBox.fromReductionStages(3,4) is the same as GearBox.fromStages("3:1","4:1") which corresponds to the gearbox attached to your motor.
// You could also use .withGearing(12) which does the same thing.
.withGearing(new MechanismGearing(GearBox.fromReductionStages(3, 4)))
// Motor properties to prevent over currenting.
.withMotorInverted(false)
.withIdleMode(MotorMode.BRAKE)
.withStatorCurrentLimit(Amps.of(40))
.withClosedLoopRampRate(Seconds.of(0.25))
.withOpenLoopRampRate(Seconds.of(0.25));
/** Creates a new ExampleSubsystem. */
public ExampleSubsystem() {}
/**
* Example command factory method.
*
* @return a command
*/
public Command exampleMethodCommand() {
// Inline construction of command goes here.
// Subsystem::RunOnce implicitly requires `this` subsystem.
return runOnce(
() -> {
/* one-time action goes here */
});
}
/**
* An example method querying a boolean state of the subsystem (for example, a digital sensor).
*
* @return value of some boolean subsystem state, such as a digital sensor.
*/
public boolean exampleCondition() {
// Query some boolean state, such as a digital sensor.
return false;
}
@Override
public void periodic() {
// This method will be called once per scheduler run
}
@Override
public void simulationPeriodic() {
// This method will be called once per scheduler run during simulation
}
}
ExampleSubsystem.java
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
package frc.robot.subsystems;
import static edu.wpi.first.units.Units.Amps;
import static edu.wpi.first.units.Units.Degrees;
import static edu.wpi.first.units.Units.DegreesPerSecond;
import static edu.wpi.first.units.Units.DegreesPerSecondPerSecond;
import static edu.wpi.first.units.Units.Seconds;
import com.revrobotics.spark.SparkLowLevel.MotorType;
import com.revrobotics.spark.SparkMax;
import edu.wpi.first.math.controller.ArmFeedforward;
import edu.wpi.first.wpilibj2.command.Command;
import edu.wpi.first.wpilibj2.command.SubsystemBase;
import yams.mechanisms.SmartMechanism;
import yams.motorcontrollers.SmartMotorControllerConfig;
import yams.motorcontrollers.SmartMotorControllerConfig.ControlMode;
import yams.motorcontrollers.SmartMotorControllerConfig.MotorMode;
import yams.motorcontrollers.SmartMotorControllerConfig.TelemetryVerbosity;
public class ExampleSubsystem extends SubsystemBase {
private SmartMotorControllerConfig smcConfig = new SmartMotorControllerConfig(this)
.withControlMode(ControlMode.CLOSED_LOOP)
// Feedback Constants (PID Constants)
.withClosedLoopController(50, 0, 0)
.withTrapezoidalProfile(DegreesPerSecond.of(90), DegreesPerSecondPerSecond.of(45))
.withSimClosedLoopController(50, 0, 0)
// Feedforward Constants
.withFeedforward(new ArmFeedforward(0, 0, 0))
.withSimFeedforward(new ArmFeedforward(0, 0, 0))
// Telemetry name and verbosity level
.withTelemetry("ArmMotor", TelemetryVerbosity.HIGH)
// Gearing from the motor rotor to final shaft.
// In this example GearBox.fromReductionStages(3,4) is the same as GearBox.fromStages("3:1","4:1") which corresponds to the gearbox attached to your motor.
.withGearing(new MechanismGearing(GearBox.fromReductionStages(3, 4)))
// Motor properties to prevent over currenting.
.withMotorInverted(false)
.withIdleMode(MotorMode.BRAKE)
.withStatorCurrentLimit(Amps.of(40))
.withClosedLoopRampRate(Seconds.of(0.25))
.withOpenLoopRampRate(Seconds.of(0.25));
// Vendor motor controller object
private SparkMax spark = new SparkMax(4, MotorType.kBrushless);
/** Creates a new ExampleSubsystem. */
public ExampleSubsystem() {}
/**
* Example command factory method.
*
* @return a command
*/
public Command exampleMethodCommand() {
// Inline construction of command goes here.
// Subsystem::RunOnce implicitly requires `this` subsystem.
return runOnce(
() -> {
/* one-time action goes here */
});
}
/**
* An example method querying a boolean state of the subsystem (for example, a digital sensor).
*
* @return value of some boolean subsystem state, such as a digital sensor.
*/
public boolean exampleCondition() {
// Query some boolean state, such as a digital sensor.
return false;
}
@Override
public void periodic() {
// This method will be called once per scheduler run
}
@Override
public void simulationPeriodic() {
// This method will be called once per scheduler run during simulation
}
}
ExampleSubsystem.java
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
package frc.robot.subsystems;
import static edu.wpi.first.units.Units.Amps;
import static edu.wpi.first.units.Units.Degrees;
import static edu.wpi.first.units.Units.DegreesPerSecond;
import static edu.wpi.first.units.Units.DegreesPerSecondPerSecond;
import static edu.wpi.first.units.Units.Seconds;
import com.revrobotics.spark.SparkLowLevel.MotorType;
import com.revrobotics.spark.SparkMax;
import edu.wpi.first.math.controller.ArmFeedforward;
import edu.wpi.first.math.system.plant.DCMotor;
import edu.wpi.first.wpilibj2.command.Command;
import edu.wpi.first.wpilibj2.command.SubsystemBase;
import yams.mechanisms.SmartMechanism;
import yams.motorcontrollers.SmartMotorController;
import yams.motorcontrollers.SmartMotorControllerConfig;
import yams.motorcontrollers.SmartMotorControllerConfig.ControlMode;
import yams.motorcontrollers.SmartMotorControllerConfig.MotorMode;
import yams.motorcontrollers.SmartMotorControllerConfig.TelemetryVerbosity;
import yams.motorcontrollers.local.SparkWrapper;
public class ExampleSubsystem extends SubsystemBase {
private SmartMotorControllerConfig smcConfig = new SmartMotorControllerConfig(this)
.withControlMode(ControlMode.CLOSED_LOOP)
// Feedback Constants (PID Constants)
.withClosedLoopController(50, 0, 0)
.withTrapezoidalProfile(DegreesPerSecond.of(90), DegreesPerSecondPerSecond.of(45))
.withSimClosedLoopController(50, 0, 0)
// Feedforward Constants
.withFeedforward(new ArmFeedforward(0, 0, 0))
.withSimFeedforward(new ArmFeedforward(0, 0, 0))
// Telemetry name and verbosity level
.withTelemetry("ArmMotor", TelemetryVerbosity.HIGH)
// Gearing from the motor rotor to final shaft.
// In this example GearBox.fromReductionStages(3,4) is the same as GearBox.fromStages("3:1","4:1") which corresponds to the gearbox attached to your motor.
.withGearing(new MechanismGearing(GearBox.fromReductionStages(3, 4)))
// Motor properties to prevent over currenting.
.withMotorInverted(false)
.withIdleMode(MotorMode.BRAKE)
.withStatorCurrentLimit(Amps.of(40))
.withClosedLoopRampRate(Seconds.of(0.25))
.withOpenLoopRampRate(Seconds.of(0.25));
// Vendor motor controller object
private SparkMax spark = new SparkMax(4, MotorType.kBrushless);
// Create our SmartMotorController from our Spark and config with the NEO.
private SmartMotorController sparkSmartMotorController = new SparkWrapper(spark, DCMotor.getNEO(1), smcConfig);
/** Creates a new ExampleSubsystem. */
public ExampleSubsystem() {}
/**
* Example command factory method.
*
* @return a command
*/
public Command exampleMethodCommand() {
// Inline construction of command goes here.
// Subsystem::RunOnce implicitly requires `this` subsystem.
return runOnce(
() -> {
/* one-time action goes here */
});
}
/**
* An example method querying a boolean state of the subsystem (for example, a digital sensor).
*
* @return value of some boolean subsystem state, such as a digital sensor.
*/
public boolean exampleCondition() {
// Query some boolean state, such as a digital sensor.
return false;
}
@Override
public void periodic() {
// This method will be called once per scheduler run
}
@Override
public void simulationPeriodic() {
// This method will be called once per scheduler run during simulation
}
}
ExampleSubsystem.java
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
package frc.robot.subsystems;
import static edu.wpi.first.units.Units.Amps;
import static edu.wpi.first.units.Units.Degrees;
import static edu.wpi.first.units.Units.DegreesPerSecond;
import static edu.wpi.first.units.Units.DegreesPerSecondPerSecond;
import static edu.wpi.first.units.Units.Feet;
import static edu.wpi.first.units.Units.Pounds;
import static edu.wpi.first.units.Units.Seconds;
import com.revrobotics.spark.SparkLowLevel.MotorType;
import com.revrobotics.spark.SparkMax;
import edu.wpi.first.math.controller.ArmFeedforward;
import edu.wpi.first.math.system.plant.DCMotor;
import edu.wpi.first.wpilibj2.command.Command;
import edu.wpi.first.wpilibj2.command.SubsystemBase;
import yams.mechanisms.SmartMechanism;
import yams.mechanisms.config.ArmConfig;
import yams.mechanisms.positional.Arm;
import yams.motorcontrollers.SmartMotorController;
import yams.motorcontrollers.SmartMotorControllerConfig;
import yams.motorcontrollers.SmartMotorControllerConfig.ControlMode;
import yams.motorcontrollers.SmartMotorControllerConfig.MotorMode;
import yams.motorcontrollers.SmartMotorControllerConfig.TelemetryVerbosity;
import yams.motorcontrollers.local.SparkWrapper;
public class ExampleSubsystem extends SubsystemBase {
private SmartMotorControllerConfig smcConfig = new SmartMotorControllerConfig(this)
.withControlMode(ControlMode.CLOSED_LOOP)
// Feedback Constants (PID Constants)
.withClosedLoopController(50, 0, 0)
.withTrapezoidalProfile(DegreesPerSecond.of(90), DegreesPerSecondPerSecond.of(45))
.withSimClosedLoopController(50, 0, 0)
// Feedforward Constants
.withFeedforward(new ArmFeedforward(0, 0, 0))
.withSimFeedforward(new ArmFeedforward(0, 0, 0))
// Telemetry name and verbosity level
.withTelemetry("ArmMotor", TelemetryVerbosity.HIGH)
// Gearing from the motor rotor to final shaft.
// In this example GearBox.fromReductionStages(3,4) is the same as GearBox.fromStages("3:1","4:1") which corresponds to the gearbox attached to your motor.
.withGearing(new MechanismGearing(GearBox.fromReductionStages(3, 4)))
// Motor properties to prevent over currenting.
.withMotorInverted(false)
.withIdleMode(MotorMode.BRAKE)
.withStatorCurrentLimit(Amps.of(40))
.withClosedLoopRampRate(Seconds.of(0.25))
.withOpenLoopRampRate(Seconds.of(0.25))
// Starting position is where your arm starts
.withStartingPosition(Degrees.of(-5))
// Soft limit is applied to the SmartMotorControllers PID
.withSoftLimits(Degrees.of(-20), Degrees.of(10));
// Vendor motor controller object
private SparkMax spark = new SparkMax(4, MotorType.kBrushless);
// Create our SmartMotorController from our Spark and config with the NEO.
private SmartMotorController sparkSmartMotorController = new SparkWrapper(spark, DCMotor.getNEO(1), smcConfig);
private ArmConfig armCfg = new ArmConfig()
// Hard limit is applied to the simulation.
.withHardLimits(Degrees.of(-30), Degrees.of(40))
// Length and mass of your arm for sim.
.withLength(Feet.of(3))
// Telemetry name and verbosity for the arm.
.withTelemetry("Arm", TelemetryVerbosity.HIGH);
// Arm Mechanism
private Arm arm = new Arm(armCfg, sparkSmartMotorController);
/** Creates a new ExampleSubsystem. */
public ExampleSubsystem() {}
/**
* Example command factory method.
*
* @return a command
*/
public Command exampleMethodCommand() {
// Inline construction of command goes here.
// Subsystem::RunOnce implicitly requires `this` subsystem.
return runOnce(
() -> {
/* one-time action goes here */
});
}
/**
* An example method querying a boolean state of the subsystem (for example, a digital sensor).
*
* @return value of some boolean subsystem state, such as a digital sensor.
*/
public boolean exampleCondition() {
// Query some boolean state, such as a digital sensor.
return false;
}
@Override
public void periodic() {
// This method will be called once per scheduler run
arm.updateTelemetry();
}
@Override
public void simulationPeriodic() {
// This method will be called once per scheduler run during simulation
arm.simIterate();
}
}
ExampleSubsystem.java
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
package frc.robot.subsystems;
import static edu.wpi.first.units.Units.Amps;
import static edu.wpi.first.units.Units.Degrees;
import static edu.wpi.first.units.Units.DegreesPerSecond;
import static edu.wpi.first.units.Units.DegreesPerSecondPerSecond;
import static edu.wpi.first.units.Units.Feet;
import static edu.wpi.first.units.Units.Pounds;
import static edu.wpi.first.units.Units.Second;
import static edu.wpi.first.units.Units.Seconds;
import static edu.wpi.first.units.Units.Volts;
import com.revrobotics.spark.SparkLowLevel.MotorType;
import com.revrobotics.spark.SparkMax;
import edu.wpi.first.math.controller.ArmFeedforward;
import edu.wpi.first.math.system.plant.DCMotor;
import edu.wpi.first.units.measure.Angle;
import edu.wpi.first.wpilibj2.command.Command;
import edu.wpi.first.wpilibj2.command.SubsystemBase;
import yams.mechanisms.SmartMechanism;
import yams.mechanisms.config.ArmConfig;
import yams.mechanisms.positional.Arm;
import yams.motorcontrollers.SmartMotorController;
import yams.motorcontrollers.SmartMotorControllerConfig;
import yams.motorcontrollers.SmartMotorControllerConfig.ControlMode;
import yams.motorcontrollers.SmartMotorControllerConfig.MotorMode;
import yams.motorcontrollers.SmartMotorControllerConfig.TelemetryVerbosity;
import yams.motorcontrollers.local.SparkWrapper;
public class ExampleSubsystem extends SubsystemBase {
private SmartMotorControllerConfig smcConfig = new SmartMotorControllerConfig(this)
.withControlMode(ControlMode.CLOSED_LOOP)
// Feedback Constants (PID Constants)
.withClosedLoopController(50, 0, 0)
.withTrapezoidalProfile(DegreesPerSecond.of(90), DegreesPerSecondPerSecond.of(45))
.withSimClosedLoopController(50, 0, 0)
// Feedforward Constants
.withFeedforward(new ArmFeedforward(0, 0, 0))
.withSimFeedforward(new ArmFeedforward(0, 0, 0))
// Telemetry name and verbosity level
.withTelemetry("ArmMotor", TelemetryVerbosity.HIGH)
// Gearing from the motor rotor to final shaft.
// In this example GearBox.fromReductionStages(3,4) is the same as GearBox.fromStages("3:1","4:1") which corresponds to the gearbox attached to your motor.
.withGearing(new MechanismGearing(GearBox.fromReductionStages(3, 4)))
// Motor properties to prevent over currenting.
.withMotorInverted(false)
.withIdleMode(MotorMode.BRAKE)
.withStatorCurrentLimit(Amps.of(40))
.withClosedLoopRampRate(Seconds.of(0.25))
.withOpenLoopRampRate(Seconds.of(0.25));
// Vendor motor controller object
private SparkMax spark = new SparkMax(4, MotorType.kBrushless);
// Create our SmartMotorController from our Spark and config with the NEO.
private SmartMotorController sparkSmartMotorController = new SparkWrapper(spark, DCMotor.getNEO(1), smcConfig);
private ArmConfig armCfg = new ArmConfig()
// Soft limit is applied to the SmartMotorControllers PID
.withSoftLimits(Degrees.of(-20), Degrees.of(10))
// Hard limit is applied to the simulation.
.withHardLimits(Degrees.of(-30), Degrees.of(40))
// Starting position is where your arm starts
.withStartingPosition(Degrees.of(-5))
// Length and mass of your arm for sim.
.withLength(Feet.of(3))
// Telemetry name and verbosity for the arm.
.withTelemetry("Arm", TelemetryVerbosity.HIGH);
// Arm Mechanism
private Arm arm = new Arm(armCfg, sparkSmartMotorController);
/**
* Run the arm to the given angle, does not stop when the arm reaches the setpoint.
* @param angle Angle to go to.
* @return A command.
*/
public Command run(Angle angle) { return arm.run(angle);}
/**
* Run the arm to the given angle, ends the command when the arm reaches the setpoint within tolerance.
* @param angle Angle to go to.
* @param tolerance Angle tolerance for completion.
* @return A Command
*/
public Command runTo(Angle angle, Angle tolerance) { return arm.runTo(angle, tolerance);}
/**
* Set arm closed loop controller to go to the specified mechanism position.
* @param angle Angle to go to.
*/
public void setAngleSetpoint(Angle angle) { arm.setMechanismPositionSetpoint(angle); }
/**
* Move the arm up and down.
* @param dutycycle [-1, 1] speed to set the arm too.
*/
public Command set(double dutycycle) { return arm.set(dutycycle);}
/** Creates a new ExampleSubsystem. */
public ExampleSubsystem() {}
/**
* Example command factory method.
*
* @return a command
*/
public Command exampleMethodCommand() {
// Inline construction of command goes here.
// Subsystem::RunOnce implicitly requires `this` subsystem.
return runOnce(
() -> {
/* one-time action goes here */
});
}
/**
* An example method querying a boolean state of the subsystem (for example, a digital sensor).
*
* @return value of some boolean subsystem state, such as a digital sensor.
*/
public boolean exampleCondition() {
// Query some boolean state, such as a digital sensor.
return false;
}
@Override
public void periodic() {
// This method will be called once per scheduler run
arm.updateTelemetry();
}
@Override
public void simulationPeriodic() {
// This method will be called once per scheduler run during simulation
arm.simIterate();
}
}
RobotContainer.java
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
package frc.robot;
import frc.robot.Constants.OperatorConstants;
import frc.robot.commands.Autos;
import frc.robot.commands.ExampleCommand;
import frc.robot.subsystems.ExampleSubsystem;
import static edu.wpi.first.units.Units.Degrees;
import edu.wpi.first.wpilibj2.command.Command;
import edu.wpi.first.wpilibj2.command.button.CommandXboxController;
import edu.wpi.first.wpilibj2.command.button.Trigger;
/**
* This class is where the bulk of the robot should be declared. Since Command-based is a
* "declarative" paradigm, very little robot logic should actually be handled in the {@link Robot}
* periodic methods (other than the scheduler calls). Instead, the structure of the robot (including
* subsystems, commands, and trigger mappings) should be declared here.
*/
public class RobotContainer {
// The robot's subsystems and commands are defined here...
private final ExampleSubsystem m_exampleSubsystem = new ExampleSubsystem();
// Replace with CommandPS4Controller or CommandJoystick if needed
private final CommandXboxController m_driverController =
new CommandXboxController(OperatorConstants.kDriverControllerPort);
/** The container for the robot. Contains subsystems, OI devices, and commands. */
public RobotContainer() {
// Configure the trigger bindings
configureBindings();
// Set the default command to force the arm to go to 0.
m_exampleSubsystem.setDefaultCommand(m_exampleSubsystem.run(Degrees.of(0)));
}
/**
* Use this method to define your trigger->command mappings. Triggers can be created via the
* {@link Trigger#Trigger(java.util.function.BooleanSupplier)} constructor with an arbitrary
* predicate, or via the named factories in {@link
* edu.wpi.first.wpilibj2.command.button.CommandGenericHID}'s subclasses for {@link
* CommandXboxController Xbox}/{@link edu.wpi.first.wpilibj2.command.button.CommandPS4Controller
* PS4} controllers or {@link edu.wpi.first.wpilibj2.command.button.CommandJoystick Flight
* joysticks}.
*/
private void configureBindings() {
// Schedule `run` when the Xbox controller's B button is pressed,
// cancelling on release.
m_driverController.a().whileTrue(m_exampleSubsystem.run(Degrees.of(-5)));
m_driverController.b().whileTrue(m_exampleSubsystem.run(Degrees.of(15)));
// Schedule `set` when the Xbox controller's B button is pressed,
// cancelling on release.
m_driverController.x().whileTrue(m_exampleSubsystem.set(0.3));
m_driverController.y().whileTrue(m_exampleSubsystem.set(-0.3));
}
/**
* Use this to pass the autonomous command to the main {@link Robot} class.
*
* @return the command to run in autonomous
*/
public Command getAutonomousCommand() {
// An example command will be run in autonomous
return Autos.exampleAuto(m_exampleSubsystem);
}
}