-
Notifications
You must be signed in to change notification settings - Fork 6
PID Configuration and Usage
A PID, or a Proportional-Integral-Derivative controller is an example of feedback control, where the device reacts to the error in the system in order to approach a destination at maximum precision. In order to fully understand how we use PID and other motion control features of motor controllers, we need to understand these concepts:
Closed-loop control: A control system using feedback and feedforward, wherein error from the system sensor data is used to adjust values in the approach to a target. The device reacts to error to counteract it and get to the destination. Feedback refers to calculations done to automatically offset error found in the system. Feedforward is directly specifying values to be added, multiplied or input in some other calculation to the system to approximate control over error.
Open-loop control: A control system using feedforward, wherein we specify values to directly control device output. We basically guess that it will hopefully get us to a target position/output we want. This control method does NOT use PID, so we don't use it here.
Motor Control Output Types: Motors have a variety of control output types we can use to specify the types of values that control it. The most basic form is known generally as percentage output, where the value is a percentage of voltage to apply to the motor. More types are covered in the linked documentation.
When we want absolute control over a motor's actions on the robot, we want to use a combination of both open-loop and closed-loop control to both account for error, and to manually approximate needed offsets to reach our target. These systems apply to any value we are trying to reach on a motor, whether it be velocity, position, etc.
It’s the special magic sauce of Mustard. It’s like Grey Poupon. Goes nice with ketchup.
PID is the closed-loop control we use for motors on the robot. It contains 3 values that are set as constants for a motor controller:
Proportional- Drives the value towards the target
Integral- Unused in FRC, keep as 0
Derivative- Compensates for error
For actual use cases, PID is run as part of a motion control request that modifies the motor's movement with PID calculations to reduce error and be as accurate as possible. Tuning these values is of utmost importance, and we use the Ziegler-Nichols method to do so.
Before jumping into using PID or other advanced motion control, we need to clarify what motor type we are using. REVLib and Pheonix use very different systems to assign values and drive motors with them, so make sure to follow the steps listed for your specified motor.
Really Sparks your imagination to the MAX
The REV library includes support for REV hardware, such as SparkMAXes and SparkFlexes. To configure and use PID, you must create a SparkMaxConfig ; object and config its P, I, and D, along with another optional variable, FF, corresponding to "FeedForward". This extra value is taken into account directly into PID calculations, so it directly affects your motor's movement to some place. This object is directly related to a specific motor, so running methods on it will affect the motor.
SparkMaxConfig sparkMaxConfig = new SparkMaxConfig();
sparkMaxConfig.closedLoop.pidf(sparkConstants.SPARK_KP, sparkConstants.SPARK_KI, sparkConstants.SPARK_KD, sparkConstants.SPARK_KFF);
//once you've set up the configs with SparkMaxConfig, use the below as a example for how to apply it to the motor
sparkMaxMotor.configure(sparkMaxConfig, SparkBase.ResetMode.kResetSafeParameters, SparkBase.PersistMode.kPersistParameters);- ResetMode and PersistMode are expanded upon here, but here they are used as placeholders;
Note that the pidf command configures the motor object, and must be paired with the .configure method to apply P, I, D, and FF to the motor. Also, these configs are stored on a virtual "slot" on the motor controller. Each motor controller has several slots where these values can be stored, starting at slot 0;
We use the setReference(double value, ControlType ctrl, int pidSlot) method to set both the motor output type and the reference value for PID calculations to reach for the motor, along with the PID slot being used.
The following example sets a reference value of 20 (rotations) in the position control mode, using the values from the 1st pid slot.
pidController.setReference(20, ControlType.kPosition, 1);For more information on REV control output types with or without PID, see here.
Pheonix 6, the most updated vendordep version, provides a PID value config process integrated into their general configuration process.
You need to create a TalonFXConfiguration object and access its stored instance of SlotXConfigs, where "X" is the pid slot the values are stored in.
TalonFXConfiguration configs = new TalonFXConfiguration();
slot0Configs = configs.Slot0;The SlotXConfigs object can then be used to access instances of P, I, and D.
slot0configs.kP = 0.01;
slot0configs.kI = 0;
slot0configs.kD = 0.5;NOTE: the "k" is part of a naming scheme. Don't question it or use it when writing new configurable value code.
Using closed loop control (with PID) also enables us to use some other configurable values with this object: kS, kV, and kA (and kG, but ignore that for now). These are the feedforward values that can be used in conjuction with our feedback PID values to account for more error. See Pheonix 6 Documentation for more information.
Once we have the configuration object, we just have to apply it to a motor of choice, like so:
motor.getConfigurator().apply(configs)In Pheonix 6, PID has to be used in conjuction with a closed-loop control request. In the example below, we create a control request specifying position, with a voltage output (pid calculation to determine what voltage is needed to fulfill position request).
final PositionVoltage controlRequest = new PositionVoltage(0).withSlot(0);
motor.setControl(controlRequest.withPosition(15));PLEASE refer to the Pheonix 6 documentation for more info regarding their control requests, control output types, and TalonFX in general
This is an officially licensed product of Team 4026. Decatur Robotics 2024 is not sponsored by any other Team, and is not responsible for any damages caused by using this product or trusting the programming team, which is by far the least most trustworthy team(Shadow owen money gang, we love coding the robot). By using this product, you are consenting to your information, and thus your identity to be stolen and first-born child taken.
- Editing Documentation & Markdown Syntax
- Code Team to-do List
- Code Standards
- Common Library Structure
- Interfaces
- General Setup
- Branching System
- How to Create Pull Requests
- How to Switch Branches
- Code Reviews
- Reverting Commits
- Singleton Pattern
- Software Installations
- Necessary IntelliJ Plugins
- Vendordeps
- Setting Up New Projects
- Autoformatter Set Up
- Showbot Requirements
- Autonomous
- Calling a Command Based on a Button Press
- CAN
- Clearing Sticky Faults
- Current Limits
- PID Config and Usage
- Robot.java, TeleopInit, DisabledInit
- RoboRio Ports
- SetDefaultCommand
- Wait for Time
- SlewRateLimiter
- LEDs
- InstantCommand
- PhotonVision
- Apriltags
- Camera Display on Shuffleboard
- Object Detection
- Raspberry Pi
- Network Tables
- List of Network Tables (2023)
Up to date as of SJ2, end of 2023 season