@@ -94,11 +94,11 @@ pub struct Pid<T: FloatCore> {
9494 pub ki : T ,
9595 /// Derivative gain.
9696 pub kd : T ,
97- /// Limiter for the proportional term: `( -p_limit <= P <= p_limit) `.
97+ /// Limiter for the proportional term: `-p_limit <= P <= p_limit`.
9898 pub p_limit : T ,
99- /// Limiter for the integral term: `( -i_limit <= I <= i_limit) `.
99+ /// Limiter for the integral term: `-i_limit <= I <= i_limit`.
100100 pub i_limit : T ,
101- /// Limiter for the derivative term: `( -d_limit <= D <= d_limit) `.
101+ /// Limiter for the derivative term: `-d_limit <= D <= d_limit`.
102102 pub d_limit : T ,
103103 /// Last calculated integral value if [Pid::ki] is used.
104104 integral_term : T ,
@@ -107,6 +107,22 @@ pub struct Pid<T: FloatCore> {
107107}
108108
109109/// Output of [controller iterations](Pid::next_control_output) with weights
110+ ///
111+ /// # Example
112+ ///
113+ /// This structure is simple to use and features three weights: [p](Self::p), [i](Self::i), and [d](Self::d). These can be used to figure out how much each term from [Pid] contributed to the final [output](Self::output) value which should be taken as the final controller output for this iteration:
114+ ///
115+ /// ```rust
116+ /// use pid::{Pid, ControlOutput};
117+ ///
118+ /// // Setup controller
119+ /// let mut pid = Pid::new(15.0, 100.0);
120+ /// pid.p(10.0, 100.0).i(1.0, 100.0).d(2.0, 100.0);
121+ ///
122+ /// // Input an example value and get a report for an output iteration
123+ /// let output = pid.next_control_output(26.2456);
124+ /// println!("P: {}\nI: {}\nD: {}\nFinal Output: {}", output.p, output.i, output.d, output.output);
125+ /// ```
110126#[ derive( Debug , PartialEq , Eq ) ]
111127pub struct ControlOutput < T : FloatCore > {
112128 /// Contribution of the P term to the output.
@@ -173,14 +189,17 @@ where
173189 self
174190 }
175191
176- /// Given a new measurement, calculates the next control output.
192+ /// Given a new measurement, calculates the next [ control output](ControlOutput) .
177193 ///
178194 /// # Panics
179195 ///
180196 /// - If a setpoint has not been set via `update_setpoint()`.
181197 pub fn next_control_output ( & mut self , measurement : T ) -> ControlOutput < T > {
198+ // Calculate the error between the ideal setpoint and the current
199+ // measurement to compare against
182200 let error = self . setpoint - measurement;
183201
202+ // Calculate the proportional term and limit to it's individual limit
184203 let p_unbounded = error * self . kp ;
185204 let p = apply_limit ( self . p_limit , p_unbounded) ;
186205
@@ -190,6 +209,7 @@ where
190209 // we store the entire term so that we don't need to remember previous
191210 // ki values.
192211 self . integral_term = self . integral_term + error * self . ki ;
212+
193213 // Mitigate integral windup: Don't want to keep building up error
194214 // beyond what i_limit will allow.
195215 self . integral_term = apply_limit ( self . i_limit , self . integral_term ) ;
@@ -203,9 +223,12 @@ where
203223 self . prev_measurement = Some ( measurement) ;
204224 let d = apply_limit ( self . d_limit , d_unbounded) ;
205225
226+ // Calculate the final output by adding together the PID terms, then
227+ // apply the final defined output limit
206228 let output = p + self . integral_term + d;
207229 let output = apply_limit ( self . output_limit , output) ;
208230
231+ // Return the individual term's contributions and the final output
209232 ControlOutput {
210233 p,
211234 i : self . integral_term ,
0 commit comments