1#[cfg(feature = "alloc")]
4use rrtk::streams::converters::*;
5#[cfg(feature = "alloc")]
6use rrtk::streams::math::*;
7#[cfg(feature = "alloc")]
8use rrtk::*;
9#[cfg(feature = "alloc")]
13struct StreamPID {
14 int: Reference<dyn Getter<Quantity, ()>>,
22 drv: Reference<dyn Getter<Quantity, ()>>,
23 pro_float_maker: Reference<dyn Getter<f32, ()>>,
24 int_float_maker: Reference<dyn Getter<f32, ()>>,
25 drv_float_maker: Reference<dyn Getter<f32, ()>>,
26 output: SumStream<f32, 3, ()>,
27}
28#[cfg(feature = "alloc")]
29impl StreamPID {
30 pub fn new(
31 input: Reference<dyn Getter<Quantity, ()>>,
32 setpoint: Quantity,
33 kp: Quantity,
34 ki: Quantity,
35 kd: Quantity,
36 ) -> Self {
37 let time_getter = rc_ref_cell_reference(TimeGetterFromGetter::new(input.clone()));
38 let setpoint = rc_ref_cell_reference(ConstantGetter::new(time_getter.clone(), setpoint));
39 let kp = rc_ref_cell_reference(ConstantGetter::new(time_getter.clone(), kp));
40 let ki = rc_ref_cell_reference(ConstantGetter::new(time_getter.clone(), ki));
41 let kd = rc_ref_cell_reference(ConstantGetter::new(time_getter.clone(), kd));
42 let error = rc_ref_cell_reference(DifferenceStream::new(setpoint.clone(), input.clone()));
43 let int = rc_ref_cell_reference(IntegralStream::new(error.clone()));
44 let drv = rc_ref_cell_reference(DerivativeStream::new(error.clone()));
45 let int_zeroer = rc_ref_cell_reference(NoneToValue::new(
50 int.clone(),
51 time_getter.clone(),
52 Quantity::new(0.0, MILLIMETER),
53 ));
54 let drv_zeroer = rc_ref_cell_reference(NoneToValue::new(
55 drv.clone(),
56 time_getter.clone(),
57 Quantity::new(0.0, MILLIMETER),
58 ));
59 let kp_mul = rc_ref_cell_reference(ProductStream::new([
60 to_dyn!(Getter<Quantity, ()>, kp.clone()),
61 to_dyn!(Getter<Quantity, ()>, error.clone()),
62 ]));
63 let pro_float_maker = rc_ref_cell_reference(QuantityToFloat::new(kp_mul));
67 let ki_mul = rc_ref_cell_reference(ProductStream::new([
68 to_dyn!(Getter<Quantity, ()>, ki.clone()),
69 to_dyn!(Getter<Quantity, ()>, int_zeroer.clone()),
70 ]));
71 let int_float_maker = rc_ref_cell_reference(QuantityToFloat::new(ki_mul));
72 let kd_mul = rc_ref_cell_reference(ProductStream::new([
73 to_dyn!(Getter<Quantity, ()>, kd.clone()),
74 to_dyn!(Getter<Quantity, ()>, drv_zeroer.clone()),
75 ]));
76 let drv_float_maker = rc_ref_cell_reference(QuantityToFloat::new(kd_mul));
77 let output = SumStream::new([
78 to_dyn!(Getter<f32, ()>, pro_float_maker.clone()),
79 to_dyn!(Getter<f32, ()>, int_float_maker.clone()),
80 to_dyn!(Getter<f32, ()>, drv_float_maker.clone()),
81 ]);
82 Self {
83 int: to_dyn!(Getter<Quantity, ()>, int),
84 drv: to_dyn!(Getter<Quantity, ()>, drv),
85 pro_float_maker: to_dyn!(Getter<f32, ()>, pro_float_maker),
86 int_float_maker: to_dyn!(Getter<f32, ()>, int_float_maker),
87 drv_float_maker: to_dyn!(Getter<f32, ()>, drv_float_maker),
88 output: output,
89 }
90 }
91}
92#[cfg(feature = "alloc")]
93impl Getter<f32, ()> for StreamPID {
94 fn get(&self) -> Output<f32, ()> {
95 self.output.get()
96 }
97}
98#[cfg(feature = "alloc")]
99impl Updatable<()> for StreamPID {
100 fn update(&mut self) -> NothingOrError<()> {
101 self.int.borrow_mut().update()?;
106 self.drv.borrow_mut().update()?;
107 self.pro_float_maker.borrow_mut().update()?;
108 self.int_float_maker.borrow_mut().update()?;
109 self.drv_float_maker.borrow_mut().update()?;
110 Ok(())
111 }
112}
113#[cfg(feature = "alloc")]
114struct MyStream {
115 time: Time,
116}
117#[cfg(feature = "alloc")]
118impl MyStream {
119 pub fn new() -> Self {
120 Self { time: Time(0) }
121 }
122}
123#[cfg(feature = "alloc")]
128impl Getter<Quantity, ()> for MyStream {
129 fn get(&self) -> Output<Quantity, ()> {
130 Ok(Some(Datum::new(
131 self.time,
132 Quantity::from(self.time) * Quantity::new(0.5, MILLIMETER_PER_SECOND),
133 )))
134 }
135}
136#[cfg(feature = "alloc")]
137impl Updatable<()> for MyStream {
138 fn update(&mut self) -> NothingOrError<()> {
139 self.time += Time(2_000_000_000);
140 Ok(())
141 }
142}
143#[cfg(feature = "alloc")]
144fn main() {
145 const SETPOINT: Quantity = Quantity::new(5.0, MILLIMETER);
146 const KP: Quantity = Quantity::dimensionless(1.0);
147 const KI: Quantity = Quantity::dimensionless(0.01);
148 const KD: Quantity = Quantity::dimensionless(0.1);
149 println!("PID Controller using RRTK Streams");
150 println!(
151 "kp = {:?}; ki = {:?}; kd = {:?}",
152 KP.value, KI.value, KD.value
153 );
154 let input = to_dyn!(Getter<Quantity, ()>, rc_ref_cell_reference(MyStream::new()));
155 let mut stream = StreamPID::new(input.clone(), SETPOINT, KP, KI, KD);
156 stream.update().unwrap();
157 println!(
158 "time: {:?}; setpoint: {:?}; process: {:?}; command: {:?}",
159 stream.get().unwrap().unwrap().time.0,
160 SETPOINT.value,
161 input.borrow().get().unwrap().unwrap().value.value,
162 stream.get().unwrap().unwrap().value
163 );
164 for _ in 0..6 {
165 input.borrow_mut().update().unwrap();
166 stream.update().unwrap();
167 println!(
168 "time: {:?}; setpoint: {:?}; process: {:?}; command: {:?}",
169 stream.get().unwrap().unwrap().time,
170 SETPOINT,
171 input.borrow().get().unwrap().unwrap().value,
172 stream.get().unwrap().unwrap().value
173 );
174 }
175}
176#[cfg(not(feature = "alloc"))]
177fn main() {
178 println!("Enable the `alloc` feature to run this example.\nAssuming you're using Cargo, add the `--features alloc` flag to your command.");
179}