PID treats the mechanism as a black box. State-space control instead uses a model of the physics, which lets you place poles deliberately, fuse noisy sensors optimally, and reason about stability. WPILib ships first-class support via LinearSystem, LinearQuadraticRegulator, KalmanFilter, and LinearSystemLoop.
The three pieces
- Plant model (
LinearSystem): the math of how input voltage produces velocity. WPILib'sLinearSystemIdbuilds one from physical constants or from SysId's kV/kA viaidentifyVelocitySystem(kV, kA). - LQR (
LinearQuadraticRegulator): the controller. You tell it how much you care about state error vs. control effort, and it computes the optimal gains. For a single-state flywheel the result is mathematically just a P controller -- but a principled one. - Kalman filter (
KalmanFilter): the observer. It fuses the noisy encoder reading with the model prediction, giving a smooth state estimate with little lag -- so it rejects sensor noise while still reacting fast to real disturbances (like a game piece passing through the flywheel).
A flywheel loop
private final LinearSystem<N1, N1, N1> m_plant =
LinearSystemId.identifyVelocitySystem(kV, kA);
private final KalmanFilter<N1, N1, N1> m_observer =
new KalmanFilter<>(Nat.N1(), Nat.N1(), m_plant,
VecBuilder.fill(3.0), // model (state) std dev
VecBuilder.fill(0.01), // encoder std dev
0.020);
private final LinearQuadraticRegulator<N1, N1, N1> m_controller =
new LinearQuadraticRegulator<>(m_plant,
VecBuilder.fill(8.0), // how badly we want to hit the target rad/s
VecBuilder.fill(12.0), // max control effort (volts)
0.020);
private final LinearSystemLoop<N1, N1, N1> m_loop =
new LinearSystemLoop<>(m_plant, m_controller, m_observer, 12.0, 0.020);
Each loop you correct with the measurement, set the next reference, predict, then apply the computed voltage:
m_loop.setNextR(VecBuilder.fill(targetRadPerSec)); // desired state
m_loop.correct(VecBuilder.fill(m_encoder.getRate()));
m_loop.predict(0.020);
m_motor.setVoltage(m_loop.getU(0));
Why teams do this
A well-tuned Kalman flywheel shows little measurement lag during spin-up while still rejecting noise and recovering fast when a ball loads it -- behavior that's hard to get from hand-tuned PID. The C++ includes mirror the Java classes: <frc/estimator/KalmanFilter.h>, <frc/controller/LinearQuadraticRegulator.h>, <frc/system/LinearSystemLoop.h>.
Where to apply it
State-space shines for flywheels, drivetrains, and elevators where you have a good kV/kA model. For a first attempt, characterize with SysId, plug kV/kA into LinearSystemId, and start from the WPILib state-space flywheel example rather than from scratch. Tune the two std-dev knobs: smaller measurement std-dev trusts the encoder more (faster, noisier); larger trusts the model more (smoother, laggier).
Key takeaways
- State-space uses a physics model: LinearSystem (plant) + LinearQuadraticRegulator (controller) + KalmanFilter (observer), tied together by LinearSystemLoop.
- Build the plant from SysId's kV/kA via LinearSystemId.identifyVelocitySystem().
- Each loop: setNextR -> correct(measurement) -> predict -> setVoltage(getU(0)).
- Tune Kalman std-devs to trade encoder trust (fast/noisy) against model trust (smooth/laggy).
Go deeper
Lesson quiz
RequiredAnswer all 5 questions correctly to complete this lesson.
01.In a WPILib state-space LinearSystemLoop, what are the three core components combined to control the system?
02.What is the primary purpose of the Kalman Filter in a WPILib state-space controller?
03.When constructing WPILib's LinearQuadraticRegulator, how do you typically specify the desired behavior?
04.What is the correct per-loop sequence when running a WPILib LinearSystemLoop flywheel?
05.How does adjusting the measurement (encoder) standard-deviation knob affect a Kalman flywheel?
Answer every question to submit.
All 51 lessons in Programming, Controls & Sensors
- Not started:Mini-Project: A Closed-Loop Elevator with Motion Magic
- Not started:Mini-Project: A Velocity-Controlled Shooter on REVLib
- Not started:Mini-Project: A Teleop Swerve Drive Subsystem
- Not started:Mini-Project: An Autonomous Routine with PathPlanner
- Not started:Mini-Project: Vision-Aligned Scoring with Limelight
- Not started:State-Space Control and Kalman Filtering
- Not started:Log Replay Architecture with AdvantageKit
- Not started:Advanced Pose Estimation: Multi-Tag Fusion and Standard Deviations
- Not started:Robot Coordination, Alerts, and Operator Feedback
- Not started:Case Study: Hardening Software Before an Event