PID APIs
PID
The PID component provides a simple, thread-safe class representing a PID controller. It tracks how frequently its update() method is called and can have its gains change dynamically.
Code examples for the task API are provided in the pid example folder.
API Reference
Header File
Classes
-
class Pid : public espp::BaseComponent
Simple PID (proportional, integral, derivative) controller class with integrator clamping, output clamping, and prevention of integrator windup during output saturation. This class is thread-safe, so you can update(), clear(), and change_gains() from multiple threads if needed.
Basic PID Example
espp::Pid pid({.kp = 1.0f, .ki = 0.1f, .kd = 0.0f, .integrator_min = -1000.0f, .integrator_max = 1000.0f, .output_min = -100.0f, .output_max = 100.0f}); for (int i = 0; i < num_seconds_to_run; i++) { float error = (float)num_seconds_to_run / (float)(i + 1); float output = pid.update(error); fmt::print("PID: ({}) -> {:0.3f}\n", pid, output); // std::this_thread::sleep_for(5ms); }
Complex PID Example
espp::Pid::Config pid_config{.kp = 1.0f, .ki = 0.1f, .kd = 0.0f, .integrator_min = -1000.0f, .integrator_max = 1000.0f, .output_min = -100.0f, .output_max = 100.0f, .log_level = espp::Logger::Verbosity::INFO}; espp::Pid pid(pid_config); auto task_fn = [&pid](std::mutex &m, std::condition_variable &cv) { auto now = std::chrono::high_resolution_clock::now(); float elapsed = std::chrono::duration<float>(now - start).count(); float error = 2.0f / elapsed; float output = pid.update(error); fmt::print("PID: ({}) -> {:0.3f}\n", pid, output); // NOTE: sleeping in this way allows the sleep to exit early when the // task is being stopped / destroyed { std::unique_lock<std::mutex> lk(m); cv.wait_for(lk, 100ms); } // don't want to stop the task return false; }; auto task = espp::Task({.callback = task_fn, .task_config = {.name = "PID Update"}, .log_level = espp::Logger::Verbosity::INFO}); task.start(); for (int i = 0; i < num_seconds_to_run; i++) { // change PID gains here fmt::print("Increasing p-gain\n"); pid_config.kp = (float)i / (float)num_seconds_to_run; pid.change_gains(pid_config); std::this_thread::sleep_for(1s); }
Public Functions
-
inline void change_gains(const Config &config, bool reset_state = true)
Change the gains and other configuration for the PID controller.
- Parameters
config – Configuration struct with new gains and sampling time.
reset_state – Reset / clear the PID controller state.
-
inline void set_config(const Config &config, bool reset_state = true)
Change the gains and other configuration for the PID controller.
- Parameters
config – Configuration struct with new gains and sampling time.
reset_state – Reset / clear the PID controller state.
-
inline void clear()
Clear the PID controller state.
-
inline float update(float error)
Update the PID controller with the latest error measurement, getting the output control signal in return.
Note
Tracks invocation timing to better compute time-accurate integral/derivative signals.
- Parameters
error – Latest error signal.
- Returns
The output control signal based on the PID state and error.
-
inline float operator()(float error)
Update the PID controller with the latest error measurement, getting the output control signal in return.
Note
Tracks invocation timing to better compute time-accurate integral/derivative signals.
- Parameters
error – Latest error signal.
- Returns
The output control signal based on the PID state and error.
-
inline float get_error() const
Get the current error (as of the last time update() or operator() were called)
- Returns
Most recent error.
-
inline float get_integrator() const
Get the current integrator (as of the last time update() or operator() were called)
- Returns
Most recent integrator value.
-
inline Config get_config() const
Get the configuration for the PID (gains, etc.).
- Returns
Config structure containing gains, etc.
-
inline const std::string &get_name() const
Get the name of the component
Note
This is the tag of the logger
- Returns
A const reference to the name of the component
-
inline void set_log_tag(const std::string_view &tag)
Set the tag for the logger
- Parameters
tag – The tag to use for the logger
-
inline espp::Logger::Verbosity get_log_level() const
Get the log level for the logger
See also
See also
- Returns
The verbosity level of the logger
-
inline void set_log_level(espp::Logger::Verbosity level)
Set the log level for the logger
See also
See also
- Parameters
level – The verbosity level to use for the logger
-
inline void set_log_verbosity(espp::Logger::Verbosity level)
Set the log verbosity for the logger
See also
See also
See also
Note
This is a convenience method that calls set_log_level
- Parameters
level – The verbosity level to use for the logger
-
inline espp::Logger::Verbosity get_log_verbosity() const
Get the log verbosity for the logger
See also
See also
See also
Note
This is a convenience method that calls get_log_level
- Returns
The verbosity level of the logger
-
inline void set_log_rate_limit(std::chrono::duration<float> rate_limit)
Set the rate limit for the logger
See also
Note
Only calls to the logger that have _rate_limit suffix will be rate limited
- Parameters
rate_limit – The rate limit to use for the logger
-
struct Config
Public Members
-
float kp
Proportional gain.
-
float ki
Integral gain.
Note
should not be pre-multiplied by the time constant.
-
float kd
Derivative gain.
Note
should not be pre-divided by the time-constant.
-
float integrator_min
Minimum value the integrator can wind down to.
Note
Operates at the same scale as
output_min
andoutput_max
. Could be 0 or negative. Can have different magnitude from integrator_max for asymmetric response.
-
float integrator_max
Maximum value the integrator can wind up to.
Note
Operates at the same scale as
output_min
andoutput_max
.
-
float output_min
Limit the minimum output value. Can be a different magnitude from output max for asymmetric output behavior.
-
float output_max
Limit the maximum output value.
-
float kp
-
inline void change_gains(const Config &config, bool reset_state = true)