Combining Motion Profiling and PID Control with ProfiledPIDController¶
For a guide on implementing the
ProfiledPIDController class in the command-based framework framework, see Combining Motion Profiling and PID in Command-Based.
In the previous article, we saw how to use the
TrapezoidProfile class to create and use a trapezoidal motion profile. The example code from that article demonstrates manually composing the
TrapezoidProfile class with the external PID control feature of a “smart” motor controller.
This combination of functionality (a motion profile for generating setpoints combined with a PID controller for following them) is extremely common. To facilitate this, WPILib comes with a
ProfiledPIDController class (Java, C++) that does most of the work of combining these two functionalities. The API of the
ProfiledPIDController is very similar to that of the
PIDController, allowing users to add motion profiling to a PID-controlled mechanism with very few changes to their code.
Using the ProfiledPIDController class¶
In C++, the
ProfiledPIDController class is templated on the unit type used for distance measurements, which may be angular or linear. The passed-in values must have units consistent with the distance units, or a compile-time error will be thrown. For more information on C++ units, see The C++ Units Library.
Much of the functionality of
ProfiledPIDController is effectively identical to that of
PIDController. Accordingly, this article will only cover features that are substantially-changed to accomodate the motion profiling functionality. For information on standard
PIDController features, see PID Control in WPILib.
Constructing a ProfiledPIDController¶
C++ is often able to infer the type of the inner classes, and thus a simple initializer list (without the class name) can be sent as a parameter. The full class name is included in the example below for clarity.
ProfiledPIDController is nearly identical to creating a PIDController. The only difference is the need to supply a set of trapezoidal profile constraints, which will be automatically forwarded to the internally-generated
Goal vs Setpoint¶
A major difference between a standard
PIDController and a
ProfiledPIDController is that the actual setpoint of the control loop is not directly specified by the user. Rather, the user specifies a goal position or state, and the setpoint for the controller is computed automatically from the generated motion profile between the current state and the goal. So, while the user-side call looks mostly identical:
goal value (which can be either a position value or a
TrapezoidProfile.State, if nonzero velocity is desired) is not necessarily the current setpoint of the loop - rather, it is the eventual setpoint once the generated profile terminates.
Getting/Using the Setpoint¶
ProfiledPIDController goal differs from the setpoint, is if often desirable to poll the current setpoint of the controller (for instance, to get values to use with feedforward). This can be done with the
The returned setpoint might then be used as in the following example: