|
| 1 | +""" |
| 2 | +Active Disturbance Rejection Control (ADRC) is a robust control strategy |
| 3 | +that estimates and compensates for disturbances in real-time without needing |
| 4 | +an explicit mathematical model of the system. |
| 5 | +
|
| 6 | +It consists of: |
| 7 | +1. Tracking Differentiator (TD) - Smooths the reference signal |
| 8 | +2. Extended State Observer (ESO) - Estimates system states and disturbances |
| 9 | +3. Nonlinear State Error Feedback (NLSEF) - Generates the control signal |
| 10 | +
|
| 11 | +Refer - https://en.wikipedia.org/wiki/Active_disturbance_rejection_control |
| 12 | +""" |
| 13 | + |
| 14 | + |
| 15 | +class ADRC: |
| 16 | + def __init__(self, beta1: float, beta2: float, beta3: float, setpoint: float = 0.0): |
| 17 | + """ |
| 18 | + Initialize the ADRC controller. |
| 19 | +
|
| 20 | + :param beta1: Gain for error correction in ESO |
| 21 | + :param beta2: Gain for disturbance estimation in ESO |
| 22 | + :param beta3: Gain for acceleration estimation in ESO |
| 23 | + :param setpoint: Desired target value |
| 24 | + """ |
| 25 | + self.beta1 = beta1 |
| 26 | + self.beta2 = beta2 |
| 27 | + self.beta3 = beta3 |
| 28 | + self.setpoint = setpoint |
| 29 | + |
| 30 | + self.z1 = 0.0 # Estimated system output |
| 31 | + self.z2 = 0.0 # Estimated system velocity |
| 32 | + self.z3 = 0.0 # Estimated total disturbance |
| 33 | + |
| 34 | + def compute(self, measured_value: float, dt: float) -> float: |
| 35 | + """ |
| 36 | + Compute the control signal based on error estimation and disturbance rejection. |
| 37 | +
|
| 38 | + :param measured_value: The current process variable |
| 39 | + :param dt: Time difference since the last update |
| 40 | + :return: Control output |
| 41 | + """ |
| 42 | + error = self.setpoint - measured_value |
| 43 | + |
| 44 | + # Extended State Observer (ESO) Update |
| 45 | + self.z1 += dt * (self.z2 - self.beta1 * (self.z1 - measured_value)) |
| 46 | + self.z2 += dt * (self.z3 - self.beta2 * (self.z1 - measured_value)) |
| 47 | + self.z3 -= self.beta3 * (self.z1 - measured_value) |
| 48 | + |
| 49 | + # Control Law (Nonlinear State Error Feedback - NLSEF) |
| 50 | + control_output = self.z2 - self.z3 |
| 51 | + return control_output |
| 52 | + |
| 53 | + def reset(self): |
| 54 | + """Reset the estimated states.""" |
| 55 | + self.z1 = 0.0 |
| 56 | + self.z2 = 0.0 |
| 57 | + self.z3 = 0.0 |
| 58 | + |
| 59 | + |
| 60 | +if __name__ == "__main__": |
| 61 | + import doctest |
| 62 | + doctest.testmod() |
| 63 | + |
| 64 | + |
0 commit comments