Symptom A: It oscillates / buzzes at the setpoint
Usually too much kP or kD, or a feedback delay. Fix: back kP off (or, per WPILib's guidance for position loops, increase kD instead) until the oscillation stops — WPILib's tuning docs describe this qualitatively, not as a fixed percentage cut. Confirm your loop reads a fresh sensor each iteration and that you're not double-applying feedforward and integral windup. Lower the velocity/acceleration constraints to see if the mechanism is being asked to move impossibly fast.
Symptom B: It sags or drifts under gravity
Missing or wrong gravity feedforward. For an arm, kG must be multiplied by cos(angle) (use ArmFeedforward, which does this); a constant kG on an arm will hold at one angle and sag at others. For an elevator, kG is constant (use ElevatorFeedforward). Tune kG first, raise it until the mechanism just holds against gravity without drifting.
Symptom C: It runs away or fights itself
Classic encoder phase / sign error or wrong conversion factor. The controller sees the mechanism move the 'wrong' way and commands harder, accelerating the runaway. Diagnose: disable the motor, move the mechanism by hand, and confirm the reported position increases in the commanded-positive direction. Fix the encoder inversion or conversion factor (counts-to-radians/meters) before touching gains.
Symptom D: It slams into the setpoint
No motion profile, or profile constraints set too aggressively. Use a ProfiledPIDController / TrapezoidProfile so the controller chases a physically realistic position+velocity+acceleration trajectory instead of an instantaneous step. WPILib recommends starting with modest constraints and increasing.
The correct tuning order (don't improvise)
For gravity-loaded mechanisms, WPILib's sequence is: kG -> kV -> kA -> kP, then add kD only if needed, and find kS via SysId. Tuning kP before kG is the most common reason a mechanism 'won't tune', the feedback is fighting uncompensated gravity.
Use SysId, then refine
Run a SysId quasistatic + dynamic routine to get kS/kV/kA/(kG) empirically. These get you most of the way; only then hand-tune kP/kD for the last bit of tracking.
Workflow
- Verify sensor direction/scale by hand.
- Add/verify the correct gravity feedforward (arm = cosine, elevator = constant).
- Set conservative profile constraints.
- Characterize with SysId; apply kS/kV/kA/kG.
- Raise kP until it just starts to oscillate, then back it off (or add kD) until the oscillation stops — WPILib doesn't specify a fixed percentage.
Key takeaways
- Tune in the order kG -> kV -> kA -> kP; tuning kP first while gravity is uncompensated is why mechanisms 'won't tune'.
- Sag means missing gravity FF: arms need cosine-scaled kG (ArmFeedforward), elevators need a constant kG (ElevatorFeedforward).
- Runaway is almost always an encoder sign/conversion error, verify by hand before changing gains, and use a motion profile to stop slamming.
Keep going
Take the quiz · +10 XP with an accountMore in Common Mistakes & Troubleshooting
Sources & corrections
This lesson is AI-assisted: drafted from primary sources, then reviewed and edited by hand. Errors still get through. When one is reported we fix it and write down what changed — publicly, in the corrections log.
Sources and further reading
- WPILib Tuning a Vertical Elevatordocs.wpilib.org
- WPILib ProfiledPIDControllerdocs.wpilib.org
- WPILib Feedforward Controldocs.wpilib.org
Read next
Articles on this, for competition day
The lesson covers how it works. These cover what to do when it breaks.
- 16 min read
FRC Elevator and Arm Design: Staging, Rigging, Motors, Gravity, and Safety
A primary-source FRC guide to designing elevators and arms: cascade vs continuous rigging, staging, motor and gear-ratio sizing, gravity math, and safe holding.
Read - 7 min read
FRC Motion Profiling Explained: TrapezoidProfile and ProfiledPIDController
How WPILib's TrapezoidProfile and ProfiledPIDController smooth mechanism motion, how to pick velocity and acceleration constraints, and when a profile beats plain PID.
Read - 8 min read
How to Tune PID on an FRC Robot: A Practical Guide
A hands-on guide to tuning PID and feedforward on FRC mechanisms: a safe tuning order, fixing oscillation and steady-state error, and using WPILib SysId.
Read
Lesson quiz
RequiredAll 3 right completes the lesson. Miss one and only that question comes back — anything you already answered correctly stays banked.
0 of 3 answered
01.A position-controlled arm oscillates around its setpoint, overshooting back and forth. In a PID loop, which gain is most appropriate to add or increase to damp this oscillation?
02.An arm sags below its commanded angle and the PID has to constantly fight gravity to hold position. What is the correct WPILib-style fix?
03.In WPILib's ArmFeedforward, the gravity gain kG is multiplied by which quantity, and what does that imply about where gravity load is greatest?
Answer every question to submit.
All 47 lessons in Mechanical, Build & Pneumatics
- Not started:Mini-Project 1: A Single-Jointed Arm From Math to Motion
- Not started:Mini-Project 2: A Two-Stage Cascade Elevator
- Not started:Mini-Project 3: A Velocity-Controlled Flywheel Shooter
- Not started:Mini-Project 4: A Pivoting Roller Intake
- Not started:Mini-Project 5: Integrating a COTS Swerve Module
- Not started:Pneumatics Won't Fire: A Full Diagnostic Tree
- Not started:The Robot Won't Drive Straight (and Other Drivetrain Sins)
- Not started:Gearboxes That Grenade and Fasteners That Vibrate Loose
- Not started:Closed-Loop Mechanisms That Oscillate, Sag, or Stall
- Not started:Field-Ready Reliability: Inspection, Spares, and the Pit Checklist
- Not started:Characterizing Any Mechanism with SysId
- Not started:Simulation-Driven Design with WPILib Physics Models
- Not started:Motion Profiling and Superstructure Coordination
- Not started:Designing for Weight, Stiffness, and Manufacturability
- Not started:Case Studies: Learning From Open Alliance Robots