Activity 6.6: Tune a PID Loop
🎯 Goal
By the end of this activity you will have:
- Selected a mechanism with PID or feedforward control on your team’s robot
- Recorded baseline performance data using AdvantageScope or Shuffleboard
- Adjusted PID and/or feedforward gains systematically
- Verified the improvement with before-and-after data comparison
Step 1: Choose a Mechanism to Tune
Pick a mechanism that uses PID or feedforward control. Good candidates:
| Mechanism | What to Tune | Where to Find Gains |
|---|---|---|
| Shooter flywheel | Velocity PID + feedforward | |
| Turret position | Position PID | |
| Swerve steer motors | Position PID | |
| Swerve drive motors | Velocity feedforward |
Mechanism I’m tuning: _______________ Current gains (kP, kI, kD, kS, kV, etc.): _______________
Step 2: Add Logging for Tuning Data
To tune effectively, you need to see both the target and actual values over time. Add logging to your subsystem if it’s not already there:
// In your subsystem's periodic() method:SmartDashboard.putNumber("Mechanism/TargetValue", targetValue);SmartDashboard.putNumber("Mechanism/ActualValue", actualValue);SmartDashboard.putNumber("Mechanism/Error", targetValue - actualValue);SmartDashboard.putNumber("Mechanism/OutputVoltage", outputVoltage);Or if using AdvantageKit:
Logger.recordOutput("Mechanism/TargetValue", targetValue);Logger.recordOutput("Mechanism/ActualValue", actualValue);Logger.recordOutput("Mechanism/Error", targetValue - actualValue);Step 3: Record Baseline Data
Before changing anything, record how the mechanism currently performs:
- Deploy the current code to the robot
- Open AdvantageScope and connect via NetworkTables
- Create a graph with both target and actual values overlaid
- Run the mechanism through its typical operation (e.g., spin up the flywheel, move the turret to a target)
- Take a screenshot or note the key metrics
Baseline Metrics
| Metric | Value |
|---|---|
| Rise time (how long to reach target) | |
| Overshoot (how far past the target) | |
| Steady-state error (final offset from target) | |
| Settling time (how long until stable) | |
| Oscillation (does it wobble?) |
Step 4: Tune Systematically
Follow this tuning process. Change one thing at a time and test after each change.
If Tuning Feedforward First (Recommended)
- Set all PID gains to zero (kP = 0, kI = 0, kD = 0)
- Find kS — slowly increase kS until the mechanism just barely starts moving. This is the static friction compensation.
- Find kV — command a known velocity and measure the voltage needed. kV = voltage / velocity.
- Find kG (for arms/elevators) — hold the mechanism at different angles and find the voltage that holds it steady.
- Test — with only feedforward, the mechanism should get close to the target but may have some error.
Then Add PID
- Start with kP only — increase kP until the mechanism responds to error without oscillating. A good starting point is small (0.1-1.0 for position, 0.01-0.1 for velocity).
- Add kD if needed — if the mechanism overshoots, add a small kD to dampen the response.
- Add kI only if necessary — if there’s persistent steady-state error that P can’t fix, add a very small kI. Most FRC mechanisms don’t need it.
- If the mechanism is sluggish: Increase kP
- If the mechanism overshoots and oscillates: Decrease kP or increase kD
- If the mechanism oscillates rapidly: kP is too high, reduce it
- If there’s a small persistent error: Try increasing kP first. Only add kI as a last resort.
- If the mechanism is jerky: kD might be too high, or your sensor data is noisy
- If the mechanism can’t hold position against gravity: Add or increase kG feedforward
- Always tune feedforward before PID — it’s easier and more effective
Step 5: Record Tuned Data
After tuning, record the same metrics as your baseline:
- Deploy the updated code
- Run the same test as before
- Graph the target vs actual in AdvantageScope
- Compare to the baseline
Tuned Metrics
| Metric | Baseline | After Tuning | Improvement |
|---|---|---|---|
| Rise time | |||
| Overshoot | |||
| Steady-state error | |||
| Settling time | |||
| Oscillation |
Step 6: Document Your Gains
Record the final gains so your team can reference them:
| Gain | Before | After |
|---|---|---|
| kP | ||
| kI | ||
| kD | ||
| kS | ||
| kV | ||
| kG | ||
| kA |
Update the gains in your team’s code and commit the change with a descriptive message:
git commit -m "Tune [mechanism] PID: kP=X, kD=Y, kV=Z"Strong answers include:
-
Specific mechanism and gains — e.g., “I tuned the shooter flywheel. Original gains were kP=0.5, kI=0, kD=0, kV=0. The flywheel took 1.2 seconds to reach 4000 RPM and had 150 RPM of steady-state error.”
-
Measurable improvement — e.g., “After tuning, rise time dropped from 1.2s to 0.4s and steady-state error went from 150 RPM to under 20 RPM. The flywheel now reaches target speed before the note reaches the shooter.”
-
Which gain mattered most — e.g., “Adding kV feedforward (0.12 V/RPM) had the biggest impact — it got the flywheel to within 50 RPM of the target without any PID. Then a small kP (0.3) closed the remaining gap. I didn’t need kI or kD at all.”
Bonus: Tune in Simulation
If you have physics simulation set up (from Lesson 6.3), try tuning in simulation first:
- Get approximate gains in simulation
- Deploy to the real robot
- Fine-tune on the real robot (gains will need adjustment due to real-world friction and load)
This workflow is faster because you can iterate in simulation without waiting for deploy cycles.
What’s Next?
You’ve now tuned a real mechanism using control theory principles. In Lesson 6.7: Vision Processing, you’ll learn how cameras and AprilTags give your robot the ability to see — enabling auto-alignment, pose correction, and target tracking.