Add simple pid controller
This commit is contained in:
50
pycar/src/car/control/pid.py
Normal file
50
pycar/src/car/control/pid.py
Normal file
@@ -0,0 +1,50 @@
|
||||
"""
|
||||
PID Controller implementation.
|
||||
"""
|
||||
|
||||
import time
|
||||
|
||||
|
||||
class PIDController:
|
||||
def __init__(self, set_point=0, kp=3, ki=None, kd=None):
|
||||
"""
|
||||
Simple implementation of PID control. All calculations are serial.
|
||||
Updates will only occur when you call the compute_timestep function, so
|
||||
call it as often as is needed when using the control (ideally a set timestep).
|
||||
You must ensure you set the set_point before calculations, otherwise you will see
|
||||
that nothing will happen.
|
||||
"""
|
||||
self._set_point = set_point
|
||||
self._kp = kp
|
||||
self._ki = ki
|
||||
self._kd = kd
|
||||
self._reset_errors()
|
||||
|
||||
@properrty
|
||||
def set_point(self) -> float:
|
||||
return self._set_point
|
||||
|
||||
@set_point.setter
|
||||
def set_point(self, new_point: float):
|
||||
self._set_point = new_point
|
||||
self._reset_errors()
|
||||
|
||||
def _reset_errors(self):
|
||||
self._previous_error = 0
|
||||
self._sum_errors = 0
|
||||
self._start_timestep = 0
|
||||
|
||||
def compute_timestep(self, process_value: float):
|
||||
"""
|
||||
Compute the manipulated value at the current timestep, given the current Process Value
|
||||
"""
|
||||
error = self._set_point - process_value
|
||||
dt = time.time - self._start_timestep
|
||||
self._sum_errors += self._sum_errors + error * dt
|
||||
derivative = (error - self._previous_error) / dt
|
||||
self._previous_error = error
|
||||
# Calculate pid control, integral/deritive time are the sample rate
|
||||
# (estimate standard form since we're doing serial calculation) if omitted
|
||||
return self._kp * (error +
|
||||
((1/dt) if self._ki is None else self._ki / self._kp) * self._sum_errors +
|
||||
((1/dt) if self._kd is None else self._kd / self._kp) * derivative)
|
||||
Reference in New Issue
Block a user