ADRC APIs
ADRC
The adrc component provides active disturbance rejection controllers for first-order and second-order plants, including both linear ADRC and Han-style nonlinear ADRC variants.
At a high level, ADRC treats plant uncertainty and external disturbances as an
extra state that can be estimated online by an extended state observer (ESO).
Instead of relying on a very accurate plant model, you provide an approximate
input gain b0 and let the observer estimate the remaining dynamics. That
usually makes ADRC attractive for embedded robotics systems where friction,
battery sag, payload changes, cable drag, and contact disturbances are present
but hard to model precisely.
This component includes:
HanTrackingDifferentiatorfor setpoint shaping and reference-rate estimationLinearAdrcFirstOrderfor approximately first-order plantsLinearAdrcSecondOrderfor approximately second-order plantsHanAdrcFirstOrderfor nonlinear first-order ADRCHanAdrcSecondOrderfor nonlinear second-order ADRC
Choosing a controller
For many motor-control applications, a good starting point is:
use a faster inner current or torque loop if one already exists,
place first-order ADRC around motor speed, or second-order ADRC around position,
move to the Han nonlinear variants only if the linear controllers do not give the disturbance rejection or large-error behavior you want.
Robotics motor-control usage
In a practical robotics stack, ADRC is usually most effective in the outer mechanical loops rather than as a replacement for every low-level regulator. For example:
a BLDC or DC motor drive might keep its inner current loop and use ADRC for wheel speed,
a servo joint might use second-order ADRC on position with the motor driver handling the faster electrical dynamics,
a mobile robot heading controller can use second-order ADRC to compensate for uneven traction, slope changes, or payload variation.
The observer states are often useful for debugging and tuning:
z2in the first-order controllers is the estimated lumped disturbance,z3in the second-order controllers is the estimated lumped disturbance,large persistent disturbance estimates usually indicate load torque, friction, bias, or a poor
b0estimate.
Those estimated disturbance states are especially valuable in robotics, because they can explain why a loop feels “mysteriously” different under battery sag, ground contact, or changing payload.
Tuning for motors and actuators
ADRC is often tuned by bandwidth rather than by directly shaping multiple independent gains. A practical workflow for motor-control applications is:
Pick the structure first. Use first-order ADRC for speed-like loops and second-order ADRC for position-like loops.
Estimate ``b0``. The sign must be correct. The magnitude only needs to be approximate, but if it is very wrong the controller will feel badly scaled and may saturate too early.
Start with conservative bandwidth. Increase the controller bandwidth until the loop is responsive but not noisy or oscillatory.
Make the observer faster than the controller. A faster ESO helps reject disturbances early, but too much observer bandwidth will amplify encoder or velocity-estimate noise.
Use the tracking differentiator to soften steps. This is especially helpful for position commands that would otherwise demand unrealistic acceleration from the motor.
Watch saturation. If the command rails against
output_min/output_max, back off the bandwidth or revisitb0and trajectory shaping before increasing gains further.
Some practical heuristics:
for the linear variants, choose
observer_bandwidthseveral times larger thancontroller_bandwidthand increase gradually;if encoder noise or quantization dominates, reduce observer bandwidth before blaming the control law;
if large setpoint steps cause overshoot or chatter, enable the tracking differentiator or lower its aggressiveness;
for the Han nonlinear variants, increase
fal_deltaif the loop is too sharp around zero error, and adjust thealphaparameters only after the main gain and bandwidth choices are in the right range.
Note
The most important ADRC tuning parameter is usually not a fancy nonlinear
exponent, but the combination of loop rate, actuator saturation, sensor
quality, and a reasonable b0 estimate. If the sample period is too slow
or the actuator is saturating constantly, ADRC will not rescue the loop.
References
Useful starting points for ADRC background and tuning include:
Jingqing Han, From PID to Active Disturbance Rejection Control, IEEE Transactions on Industrial Electronics, 2009.
Zhiqiang Gao, Active Disturbance Rejection Control: A Paradigm Shift in Feedback Control System Design, Proceedings of the American Control Conference, 2006.
Zhiqiang Gao, Scaling and Bandwidth-Parameterization Based Controller Tuning, Proceedings of the American Control Conference, 2002.
Gernot Herbst, Practical Active Disturbance Rejection Control: Tuning Methods and Guidelines for Continuous-Time Systems, IFAC-PapersOnLine, 2015.
Code examples for the ADRC API are provided in the components/adrc/example
folder.
API Reference
Header File
Classes
-
class HanTrackingDifferentiator : public espp::BaseComponent
Han tracking differentiator for smoothing a reference trajectory and estimating its rate.
The tracking differentiator (TD) is commonly used at the front of an ADRC loop to turn a stepped reference into a smooth internal command. That reduces jerk, limits observer shock, and provides an internally consistent reference derivative for second-order loops.
For robotics motor control, the TD is useful when a planner or user interface produces abrupt setpoint changes but the plant should accelerate smoothly. In a position loop, for example, the TD can convert a position step into a smoother position and velocity command pair.
- Tuning
`tracking_bandwidth` controls how aggressively the TD chases the target. Larger values follow the reference more tightly but can reintroduce abrupt motion. `filter_factor` scales the internal `h0` term and can be increased to further soften the commanded trajectory.
Public Functions
-
inline explicit HanTrackingDifferentiator(const Config &config)
Construct the tracking differentiator.
- Parameters:
config – Tracking differentiator configuration.
-
inline void set_config(const Config &config, bool reset_state = true)
Change the tracking differentiator configuration.
- Parameters:
config – New configuration.
reset_state – If true, reset the differentiator state after applying the config.
-
inline void clear(float value = 0.0f)
Reset the differentiator state.
- Parameters:
value – Initial position value after reset.
-
inline State update(float target, float dt)
Advance the tracking differentiator.
- Parameters:
target – Target reference value to follow.
dt – Timestep in seconds.
- Returns:
Updated tracking differentiator state.
-
inline State operator()(float target, float dt)
Advance the tracking differentiator.
- Parameters:
target – Target reference value to follow.
dt – Timestep in seconds.
- Returns:
Updated tracking differentiator state.
-
inline State get_state() const
Get the most recently computed state.
- Returns:
Current differentiator state.
-
inline Config get_config() const
Get the active differentiator configuration.
- Returns:
Current configuration.
-
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
Configuration for the Han tracking differentiator.
-
class LinearAdrcFirstOrder : public espp::BaseComponent
Linear first-order active disturbance rejection controller.
This controller targets plants that can be approximated as a first-order system in the controlled variable, such as a velocity loop whose command acts roughly like torque or acceleration after inner current regulation.
The linear ESO estimates:
`z1`: the controlled output, and
`z2`: the lumped disturbance and modeling error.
The resulting control law is simple to tune with bandwidth parameters and is often a good first ADRC choice when migrating from PI or PID speed control.
- Typical robotics use
Use this class for wheel speed control, conveyor speed control, or other actuator loops where the measured state is dominated by a single pole. In a cascaded servo, this is commonly the outer speed loop above a faster current controller.
- Tuning
Start with a conservative `controller_bandwidth`, then choose `observer_bandwidth` several times higher so the ESO settles faster than the controller. `b0` should match the sign of the actuator path and roughly scale command to output-rate change. If the controller saturates immediately, reduce the bandwidth or improve the `b0` estimate before increasing gains.
Linear First-Order ADRC Example
espp::LinearAdrcFirstOrder controller({ .b0 = 1.0f, .controller_bandwidth = 8.0f, .observer_bandwidth = 24.0f, .output_min = -4.0f, .output_max = 4.0f, }); FirstOrderPlant plant; for (int i = 0; i < num_steps; ++i) { auto time = i * dt; auto reference = time >= 0.25f ? 1.0f : 0.0f; plant.disturbance = time >= 2.5f ? -0.8f : 0.0f; auto control = controller.update(reference, plant.y, dt); auto output = plant.update(control, dt); if (i % print_interval == 0 || i == num_steps - 1) { auto state = controller.get_state(); fmt::print("t={:0.2f}s ref={:0.2f} y={:0.3f} u={:0.3f} z2={:0.3f}\n", time, reference, output, state.output, state.z2); } }
Public Functions
-
inline explicit LinearAdrcFirstOrder(const Config &config)
Construct the first-order linear ADRC controller.
- Parameters:
config – Controller configuration.
-
inline void set_config(const Config &config, bool reset_state = true)
Change the controller configuration.
- Parameters:
config – New controller configuration.
reset_state – If true, reset the observer and control state after applying the config.
-
inline void clear(float measurement = 0.0f)
Reset the observer and controller state.
- Parameters:
measurement – Initial measured output for the observer state.
-
inline float update(float reference, float measurement, float dt)
Update the controller.
- Parameters:
reference – Desired output reference.
measurement – Measured output.
dt – Timestep in seconds.
- Returns:
Control output.
-
inline float operator()(float reference, float measurement, float dt)
Update the controller.
- Parameters:
reference – Desired output reference.
measurement – Measured output.
dt – Timestep in seconds.
- Returns:
Control output.
-
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
Configuration for the first-order linear ADRC controller.
Public Members
-
float b0
Estimated control gain of the plant.
-
float controller_bandwidth
Closed-loop bandwidth used for the state error feedback gain.
-
float observer_bandwidth
Observer bandwidth used for the linear extended state observer.
-
float output_min
Minimum output command.
-
float output_max
Maximum output command.
-
float b0
-
struct State
Observer and controller state.
-
class LinearAdrcSecondOrder : public espp::BaseComponent
Linear second-order active disturbance rejection controller.
This controller targets plants whose commanded input primarily affects the second derivative of the controlled variable. Typical examples include motor position loops, gimbal angle loops, and heading loops where the command acts like torque or angular acceleration.
The linear ESO estimates:
`z1`: position,
`z2`: rate, and
`z3`: the lumped disturbance and unmodeled dynamics.
- Typical robotics use
Use this class when your feedback variable is position but your actuator fundamentally produces acceleration. In a mobile robot or arm joint, this is usually the position controller that sits above a faster velocity or torque loop.
- Tuning
`controller_bandwidth` shapes the closed-loop stiffness and damping. The observer is usually tuned faster than the controller so `z3` converges before it dominates the motion. If a trajectory generator already provides a velocity feedforward term, pass it through the four-argument `update()` overload as `reference_rate`.
Linear Second-Order ADRC Example
espp::LinearAdrcSecondOrder controller({ .b0 = 1.0f, .controller_bandwidth = 10.0f, .observer_bandwidth = 36.0f, .output_min = -8.0f, .output_max = 8.0f, }); SecondOrderPlant plant; for (int i = 0; i < num_steps; ++i) { auto time = i * dt; auto reference = time >= 0.25f ? 1.0f : 0.0f; plant.disturbance = time >= 2.5f ? 1.2f : 0.0f; auto control = controller.update(reference, plant.x1, dt); auto output = plant.update(control, dt); if (i % print_interval == 0 || i == num_steps - 1) { auto state = controller.get_state(); fmt::print("t={:0.2f}s ref={:0.2f} y={:0.3f} u={:0.3f} z3={:0.3f}\n", time, reference, output, state.output, state.z3); } }
Public Functions
-
inline explicit LinearAdrcSecondOrder(const Config &config)
Construct the second-order linear ADRC controller.
- Parameters:
config – Controller configuration.
-
inline void set_config(const Config &config, bool reset_state = true)
Change the controller configuration.
- Parameters:
config – New controller configuration.
reset_state – If true, reset the observer and control state after applying the config.
-
inline void clear(float measurement = 0.0f, float measurement_rate = 0.0f)
Reset the observer and controller state.
- Parameters:
measurement – Initial measured position for the observer state.
measurement_rate – Initial measured rate estimate for the observer state.
-
inline float update(float reference, float reference_rate, float measurement, float dt)
Update the controller using an explicit reference rate.
- Parameters:
reference – Desired position reference.
reference_rate – Desired reference rate.
measurement – Measured position.
dt – Timestep in seconds.
- Returns:
Control output.
-
inline float update(float reference, float measurement, float dt)
Update the controller assuming a zero reference-rate command.
- Parameters:
reference – Desired position reference.
measurement – Measured position.
dt – Timestep in seconds.
- Returns:
Control output.
-
inline float operator()(float reference, float measurement, float dt)
Update the controller assuming a zero reference-rate command.
- Parameters:
reference – Desired position reference.
measurement – Measured position.
dt – Timestep in seconds.
- Returns:
Control output.
-
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
Configuration for the second-order linear ADRC controller.
Public Members
-
float b0
Estimated control gain of the plant.
-
float controller_bandwidth
Closed-loop bandwidth used to derive the feedback gains.
-
float observer_bandwidth
Observer bandwidth used for the linear extended state observer.
-
float output_min
Minimum output command.
-
float output_max
Maximum output command.
-
float b0
-
struct State
Observer and controller state.
Public Members
-
float measurement = {0.0f}
Most recent measured position.
-
float reference = {0.0f}
Most recent reference position.
-
float reference_rate = {0.0f}
Most recent reference rate.
-
float z1 = {0.0f}
Estimated plant position state.
-
float z2 = {0.0f}
Estimated plant rate state.
-
float z3 = {0.0f}
Estimated total disturbance state.
-
float output = {0.0f}
Most recent controller output.
-
float measurement = {0.0f}
-
class HanAdrcFirstOrder : public espp::BaseComponent
Han-style nonlinear first-order active disturbance rejection controller.
This variant replaces the linear error terms with Han’s nonlinear `fal()` functions and can optionally prefilter the reference with a tracking differentiator. The nonlinear feedback is often attractive when you want high authority on large errors without making the loop excessively sharp around the operating point.
- Typical robotics use
Use this class for speed loops that must reject large step disturbances but remain well-behaved near zero speed, for example wheel or propeller speed control with friction, stiction, or battery-voltage variation.
- Tuning
`controller_gain` is the main feedback gain. `observer_bandwidth` sets the speed of the nonlinear ESO. `controller_alpha`, `observer_alpha`, and `fal_delta` determine how strongly the loop transitions between linear small-error behavior and nonlinear large-error behavior. Increase `fal_delta` if the loop is too twitchy around the setpoint, especially with noisy sensors.
Han First-Order ADRC Example
espp::HanAdrcFirstOrder controller({ .b0 = 1.0f, .controller_gain = 7.0f, .observer_bandwidth = 22.0f, .observer_alpha = 0.5f, .controller_alpha = 0.8f, .fal_delta = 0.01f, .use_tracking_differentiator = true, .tracking_config = { .tracking_bandwidth = 45.0f, .filter_factor = 5.0f, }, .output_min = -4.0f, .output_max = 4.0f, }); FirstOrderPlant plant; for (int i = 0; i < num_steps; ++i) { auto time = i * dt; auto reference = time >= 0.25f ? 1.0f : 0.0f; plant.disturbance = time >= 2.5f ? -0.8f : 0.0f; auto control = controller.update(reference, plant.y, dt); auto output = plant.update(control, dt); if (i % print_interval == 0 || i == num_steps - 1) { auto state = controller.get_state(); fmt::print("t={:0.2f}s ref={:0.2f} td={:0.3f} y={:0.3f} u={:0.3f}\n", time, reference, state.td_reference, output, state.output); } }
Public Functions
-
inline explicit HanAdrcFirstOrder(const Config &config)
Construct the first-order nonlinear ADRC controller.
- Parameters:
config – Controller configuration.
-
inline void set_config(const Config &config, bool reset_state = true)
Change the controller configuration.
- Parameters:
config – New controller configuration.
reset_state – If true, reset the observer and control state after applying the config.
-
inline void clear(float measurement = 0.0f)
Reset the observer, controller, and tracking differentiator state.
- Parameters:
measurement – Initial measured output for the observer state.
-
inline float update(float reference, float measurement, float dt)
Update the controller.
- Parameters:
reference – Desired output reference.
measurement – Measured output.
dt – Timestep in seconds.
- Returns:
Control output.
-
inline float operator()(float reference, float measurement, float dt)
Update the controller.
- Parameters:
reference – Desired output reference.
measurement – Measured output.
dt – Timestep in seconds.
- Returns:
Control output.
-
inline HanTrackingDifferentiator::State get_tracking_state() const
Get the current tracking differentiator state.
- Returns:
Tracking differentiator state.
-
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
Configuration for the first-order nonlinear ADRC controller.
Public Members
-
float b0
Estimated control gain of the plant.
-
float controller_gain
Nonlinear state error feedback gain.
-
float observer_bandwidth
Observer bandwidth used to derive nonlinear ESO gains.
-
float observer_alpha = {0.5f}
`fal()` exponent used by the observer disturbance state.
-
float controller_alpha = {0.8f}
`fal()` exponent used by the nonlinear feedback term.
-
float fal_delta = {0.01f}
Small-signal linear region width used by `fal()`.
-
bool use_tracking_differentiator = {true}
Enable reference smoothing through the Han TD.
- HanTrackingDifferentiator::Config tracking_config {.tracking_bandwidth = 40.0f,.filter_factor = 5.0f}
Tracking differentiator configuration.
-
float output_min
Minimum output command.
-
float output_max
Maximum output command.
-
float b0
-
struct State
Observer and controller state.
Public Members
-
float measurement = {0.0f}
Most recent measured output.
-
float reference = {0.0f}
Most recent reference input.
-
float td_reference = {0.0f}
Smoothed reference from the tracking differentiator.
-
float z1 = {0.0f}
Estimated plant output state.
-
float z2 = {0.0f}
Estimated total disturbance state.
-
float output = {0.0f}
Most recent controller output.
-
float measurement = {0.0f}
-
class HanAdrcSecondOrder : public espp::BaseComponent
Han-style nonlinear second-order active disturbance rejection controller.
This controller combines a second-order ESO with nonlinear state error feedback and an optional Han tracking differentiator. It is the most flexible controller in this component and is useful when a position-like loop must reject significant disturbances while still handling large setpoint changes gracefully.
- Typical robotics use
Use this class for position control of motor-driven joints, pan/tilt systems, steering axes, or mobile-robot heading loops when load variation and unmodeled friction are too large for simple PD or PID tuning to stay robust.
- Tuning
`position_gain` and `rate_gain` play roles similar to proportional and derivative action in the nonlinear feedback law. `observer_bandwidth` should usually be faster than the desired closed-loop motion, but if encoder noise is significant you may need to back it off and rely more on the tracking differentiator to keep the reference smooth. `controller_alpha1` and `controller_alpha2` change how strongly large position and rate errors are amplified relative to small errors.
Han Second-Order ADRC Example
espp::HanAdrcSecondOrder controller({ .b0 = 1.0f, .position_gain = 30.0f, .rate_gain = 6.0f, .observer_bandwidth = 32.0f, .observer_alpha1 = 0.5f, .observer_alpha2 = 0.25f, .controller_alpha1 = 0.8f, .controller_alpha2 = 1.5f, .fal_delta = 0.01f, .use_tracking_differentiator = true, .tracking_config = { .tracking_bandwidth = 60.0f, .filter_factor = 5.0f, }, .output_min = -8.0f, .output_max = 8.0f, }); SecondOrderPlant plant; for (int i = 0; i < num_steps; ++i) { auto time = i * dt; auto reference = time >= 0.25f ? 1.0f : 0.0f; plant.disturbance = time >= 2.5f ? 1.2f : 0.0f; auto control = controller.update(reference, plant.x1, dt); auto output = plant.update(control, dt); if (i % print_interval == 0 || i == num_steps - 1) { auto state = controller.get_state(); fmt::print("t={:0.2f}s ref={:0.2f} td={:0.3f} y={:0.3f} u={:0.3f} z3={:0.3f}\n", time, reference, state.td_reference, output, state.output, state.z3); } }
Note
When `use_tracking_differentiator` is true, the explicit `reference_rate` argument passed to the four-argument `update()` overload is ignored. In that mode the controller uses the tracking differentiator’s internally generated rate estimate instead.
Public Functions
-
inline explicit HanAdrcSecondOrder(const Config &config)
Construct the second-order nonlinear ADRC controller.
- Parameters:
config – Controller configuration.
-
inline void set_config(const Config &config, bool reset_state = true)
Change the controller configuration.
- Parameters:
config – New controller configuration.
reset_state – If true, reset the observer and control state after applying the config.
-
inline void clear(float measurement = 0.0f, float measurement_rate = 0.0f)
Reset the observer, controller, and tracking differentiator state.
- Parameters:
measurement – Initial measured position for the observer state.
measurement_rate – Initial measured rate estimate for the observer state.
-
inline float update(float reference, float reference_rate, float measurement, float dt)
Update the controller using an externally supplied reference rate when the tracking differentiator is disabled.
Note
If `use_tracking_differentiator` is true, `reference_rate` is ignored and the tracking differentiator’s internally estimated rate is used instead.
- Parameters:
reference – Desired position reference.
reference_rate – Desired reference rate.
measurement – Measured position.
dt – Timestep in seconds.
- Returns:
Control output.
-
inline float update(float reference, float measurement, float dt)
Update the controller assuming a zero reference-rate command when the tracking differentiator is disabled.
- Parameters:
reference – Desired position reference.
measurement – Measured position.
dt – Timestep in seconds.
- Returns:
Control output.
-
inline float operator()(float reference, float measurement, float dt)
Update the controller assuming a zero reference-rate command when the tracking differentiator is disabled.
- Parameters:
reference – Desired position reference.
measurement – Measured position.
dt – Timestep in seconds.
- Returns:
Control output.
-
inline HanTrackingDifferentiator::State get_tracking_state() const
Get the current tracking differentiator state.
- Returns:
Tracking differentiator state.
-
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
Configuration for the second-order nonlinear ADRC controller.
Public Members
-
float b0
Estimated control gain of the plant.
-
float position_gain
Nonlinear feedback gain for position error.
-
float rate_gain
Nonlinear feedback gain for rate error.
-
float observer_bandwidth
Observer bandwidth used to derive nonlinear ESO gains.
-
float observer_alpha1 = {0.5f}
`fal()` exponent used for the ESO middle state.
-
float observer_alpha2 = {0.25f}
`fal()` exponent used for the ESO disturbance state.
-
float controller_alpha1 = {0.8f}
`fal()` exponent used for the position error.
-
float controller_alpha2 = {1.5f}
`fal()` exponent used for the rate error.
-
float fal_delta = {0.01f}
Small-signal linear region width used by `fal()`.
-
bool use_tracking_differentiator = {true}
Enable reference smoothing through the Han TD.
- HanTrackingDifferentiator::Config tracking_config {.tracking_bandwidth = 60.0f,.filter_factor = 5.0f}
Tracking differentiator configuration.
-
float output_min
Minimum output command.
-
float output_max
Maximum output command.
-
float b0
-
struct State
Observer and controller state.
Public Members
-
float measurement = {0.0f}
Most recent measured position.
-
float reference = {0.0f}
Most recent reference position.
-
float td_reference = {0.0f}
Smoothed reference position.
-
float td_reference_rate = {0.0f}
Smoothed reference rate.
-
float z1 = {0.0f}
Estimated plant position state.
-
float z2 = {0.0f}
Estimated plant rate state.
-
float z3 = {0.0f}
Estimated total disturbance state.
-
float output = {0.0f}
Most recent controller output.
-
float measurement = {0.0f}