Class: DrivingPhysics::PIDController
- Inherits:
-
Object
- Object
- DrivingPhysics::PIDController
- Defined in:
- lib/driving_physics/pid_controller.rb
Overview
for example, where to set the throttle to maintain 1000 RPM SP - 1000 RPM PV - current RPM CV - throttle position
Constant Summary collapse
- HZ =
1000
- TICK =
Rational(1) / HZ
- ZN =
Ziegler-Nichols method for tuning PID gain knobs
{ # Kp Ti Td Ki Kd # Var: Ku Tu Tu Ku/Tu Ku*Tu 'P' => [0.500], 'PI' => [0.450, 0.800, nil, 0.540], 'PD' => [0.800, nil, 0.125, nil, 0.100], 'PID' => [0.600, 0.500, 0.125, 1.200, 0.075], 'PIR' => [0.700, 0.400, 0.150, 1.750, 0.105], # less overshoot than standard PID below 'some' => [0.333, 0.500, 0.333, 0.666, 0.111], 'none' => [0.200, 0.500, 0.333, 0.400, 0.066], }
Instance Attribute Summary collapse
-
#d_range ⇒ Object
Returns the value of attribute d_range.
-
#dt ⇒ Object
Returns the value of attribute dt.
-
#error ⇒ Object
readonly
Returns the value of attribute error.
-
#i_range ⇒ Object
Returns the value of attribute i_range.
-
#kd ⇒ Object
Returns the value of attribute kd.
-
#ki ⇒ Object
Returns the value of attribute ki.
-
#kp ⇒ Object
Returns the value of attribute kp.
-
#last_error ⇒ Object
readonly
Returns the value of attribute last_error.
-
#measure ⇒ Object
Returns the value of attribute measure.
-
#o_range ⇒ Object
Returns the value of attribute o_range.
-
#p_range ⇒ Object
Returns the value of attribute p_range.
-
#setpoint ⇒ Object
Returns the value of attribute setpoint.
-
#sum_error ⇒ Object
readonly
Returns the value of attribute sum_error.
Class Method Summary collapse
-
.tune(type, ku, tu) ⇒ Object
ultimate gain, oscillation.
Instance Method Summary collapse
- #derivative ⇒ Object
-
#initialize(setpoint, dt: TICK) {|_self| ... } ⇒ PIDController
constructor
A new instance of PIDController.
- #integral ⇒ Object
- #output ⇒ Object
- #proportion ⇒ Object
- #to_s ⇒ Object
- #update(measure) ⇒ Object
Constructor Details
#initialize(setpoint, dt: TICK) {|_self| ... } ⇒ PIDController
Returns a new instance of PIDController.
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
# File 'lib/driving_physics/pid_controller.rb', line 47 def initialize(setpoint, dt: TICK) @setpoint, @dt, @measure = setpoint, dt, 0.0 # track error over time for integral and derivative @error, @last_error, @sum_error = 0.0, 0.0, 0.0 # gain / multipliers for PID; tunables @kp, @ki, @kd = 1.0, 1.0, 1.0 # optional clamps for PID terms and output @p_range = (-Float::INFINITY..Float::INFINITY) @i_range = (-Float::INFINITY..Float::INFINITY) @d_range = (-Float::INFINITY..Float::INFINITY) @o_range = (-Float::INFINITY..Float::INFINITY) yield self if block_given? end |
Instance Attribute Details
#d_range ⇒ Object
Returns the value of attribute d_range.
43 44 45 |
# File 'lib/driving_physics/pid_controller.rb', line 43 def d_range @d_range end |
#dt ⇒ Object
Returns the value of attribute dt.
43 44 45 |
# File 'lib/driving_physics/pid_controller.rb', line 43 def dt @dt end |
#error ⇒ Object (readonly)
Returns the value of attribute error.
45 46 47 |
# File 'lib/driving_physics/pid_controller.rb', line 45 def error @error end |
#i_range ⇒ Object
Returns the value of attribute i_range.
43 44 45 |
# File 'lib/driving_physics/pid_controller.rb', line 43 def i_range @i_range end |
#kd ⇒ Object
Returns the value of attribute kd.
43 44 45 |
# File 'lib/driving_physics/pid_controller.rb', line 43 def kd @kd end |
#ki ⇒ Object
Returns the value of attribute ki.
43 44 45 |
# File 'lib/driving_physics/pid_controller.rb', line 43 def ki @ki end |
#kp ⇒ Object
Returns the value of attribute kp.
43 44 45 |
# File 'lib/driving_physics/pid_controller.rb', line 43 def kp @kp end |
#last_error ⇒ Object (readonly)
Returns the value of attribute last_error.
45 46 47 |
# File 'lib/driving_physics/pid_controller.rb', line 45 def last_error @last_error end |
#measure ⇒ Object
Returns the value of attribute measure.
45 46 47 |
# File 'lib/driving_physics/pid_controller.rb', line 45 def measure @measure end |
#o_range ⇒ Object
Returns the value of attribute o_range.
43 44 45 |
# File 'lib/driving_physics/pid_controller.rb', line 43 def o_range @o_range end |
#p_range ⇒ Object
Returns the value of attribute p_range.
43 44 45 |
# File 'lib/driving_physics/pid_controller.rb', line 43 def p_range @p_range end |
#setpoint ⇒ Object
Returns the value of attribute setpoint.
43 44 45 |
# File 'lib/driving_physics/pid_controller.rb', line 43 def setpoint @setpoint end |
#sum_error ⇒ Object (readonly)
Returns the value of attribute sum_error.
45 46 47 |
# File 'lib/driving_physics/pid_controller.rb', line 45 def sum_error @sum_error end |
Class Method Details
.tune(type, ku, tu) ⇒ Object
ultimate gain, oscillation
32 33 34 35 36 37 38 39 40 41 |
# File 'lib/driving_physics/pid_controller.rb', line 32 def self.tune(type, ku, tu) record = ZN[type.downcase] || ZN[type.upcase] || ZN.fetch(type) kp, ti, td, ki, kd = *record kp *= ku if kp ti *= tu if ti td *= tu if td ki *= (ku / tu) if ki kd *= (ku * tu) if kd { kp: kp, ti: ti, td: td, ki: ki, kd: kd } end |
Instance Method Details
#derivative ⇒ Object
95 96 97 |
# File 'lib/driving_physics/pid_controller.rb', line 95 def derivative (@kd * (@error - @last_error) / @dt).clamp(@d_range.begin, @d_range.end) end |
#integral ⇒ Object
91 92 93 |
# File 'lib/driving_physics/pid_controller.rb', line 91 def integral (@ki * @sum_error * @dt).clamp(@i_range.begin, @i_range.end) end |
#output ⇒ Object
81 82 83 84 85 |
# File 'lib/driving_physics/pid_controller.rb', line 81 def output (self.proportion + self.integral + self.derivative).clamp(@o_range.begin, @o_range.end) end |
#proportion ⇒ Object
87 88 89 |
# File 'lib/driving_physics/pid_controller.rb', line 87 def proportion (@kp * @error).clamp(@p_range.begin, @p_range.end) end |
#to_s ⇒ Object
99 100 101 102 103 104 105 106 107 108 109 |
# File 'lib/driving_physics/pid_controller.rb', line 99 def to_s [format("Setpoint: %.3f Measure: %.3f", @setpoint, @measure), format("Error: %+.3f\tLast: %+.3f\tSum: %+.3f", @error, @last_error, @sum_error), format(" Gain:\t%.3f\t%.3f\t%.3f", @kp, @ki, @kd), format(" PID:\t%+.3f\t%+.3f\t%+.3f\t= %.5f", self.proportion, self.integral, self.derivative, self.output), ].join("\n") end |
#update(measure) ⇒ Object
65 66 67 68 |
# File 'lib/driving_physics/pid_controller.rb', line 65 def update(measure) self.measure = measure self.output end |