1use nalgebra::{RealField, SMatrix, SVector};
11
12pub trait System<T, const N: usize, const U: usize> {
16 fn covariance(&self) -> &SMatrix<T, N, N>;
18 fn state(&self) -> &SVector<T, N>;
20 fn state_mut(&mut self) -> &mut SVector<T, N>;
22}
23
24pub trait LinearisableSystem<T, const N: usize, const U: usize>: System<T, N, U> {
26 fn transition(&self) -> &SMatrix<T, N, N>;
28 fn transition_transpose(&self) -> &SMatrix<T, N, N>;
30}
31
32pub trait InputSystem<T, const N: usize, const U: usize>: System<T, N, U> {
34 fn step(&mut self, u: SVector<T, U>) -> &SVector<T, N> {
36 *self.state_mut() = self.predict(self.state(), &u);
37 self.state()
38 }
39 fn predict(&self, x: &SVector<T, N>, u: &SVector<T, U>) -> SVector<T, N>;
41}
42
43pub trait NoInputSystem<T, const N: usize>: System<T, N, 0> {
46 fn step(&mut self) -> &SVector<T, N> {
48 *self.state_mut() = self.predict(self.state());
49 self.state()
50 }
51 fn predict(&self, x: &SVector<T, N>) -> SVector<T, N>;
53}
54
55#[allow(non_snake_case)]
58#[derive(Debug, Clone)]
59#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
60#[cfg_attr(feature = "defmt", derive(defmt::Format))]
61pub struct LinearSystem<T: RealField, const N: usize, const U: usize> {
63 x: SVector<T, N>,
64 F: SMatrix<T, N, N>,
65 F_t: SMatrix<T, N, N>,
66 Q: SMatrix<T, N, N>,
67 B: SMatrix<T, N, U>,
68}
69
70#[allow(non_snake_case)]
71impl<T: RealField + Copy, const N: usize, const U: usize> LinearSystem<T, N, U> {
72 pub fn new(
75 F: SMatrix<T, N, N>,
76 Q: SMatrix<T, N, N>,
77 B: SMatrix<T, N, U>,
78 x_initial: SVector<T, N>,
79 ) -> Self {
80 LinearSystem {
81 x: x_initial,
82 F,
83 F_t: F.transpose(),
84 Q,
85 B,
86 }
87 }
88 pub fn set_transition(&mut self, transition: SMatrix<T, N, N>) {
90 self.F_t = transition.transpose();
91 self.F = transition;
92 }
93 pub fn covariance_mut(&mut self) -> &mut SMatrix<T, N, N> {
95 &mut self.Q
96 }
97}
98
99impl<T: RealField + Copy, const N: usize, const U: usize> System<T, N, U>
101 for LinearSystem<T, N, U>
102{
103 fn covariance(&self) -> &SMatrix<T, N, N> {
104 &self.Q
105 }
106
107 fn state(&self) -> &SVector<T, N> {
108 &self.x
109 }
110
111 fn state_mut(&mut self) -> &mut SVector<T, N> {
112 &mut self.x
113 }
114}
115
116impl<T: RealField + Copy, const N: usize, const U: usize> LinearisableSystem<T, N, U>
117 for LinearSystem<T, N, U>
118{
119 fn transition(&self) -> &SMatrix<T, N, N> {
120 &self.F
121 }
122 fn transition_transpose(&self) -> &SMatrix<T, N, N> {
123 &self.F_t
124 }
125}
126
127impl<T: RealField + Copy, const N: usize, const U: usize> InputSystem<T, N, U>
129 for LinearSystem<T, N, U>
130{
131 fn predict(&self, x: &SVector<T, N>, u: &SVector<T, U>) -> SVector<T, N> {
132 self.F * x + self.B * u
133 }
134}
135
136#[allow(non_snake_case)]
139#[derive(Debug, Clone)]
140#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
141#[cfg_attr(feature = "defmt", derive(defmt::Format))]
142pub struct LinearNoInputSystem<T: RealField, const N: usize> {
143 x: SVector<T, N>,
144 F: SMatrix<T, N, N>,
145 F_t: SMatrix<T, N, N>,
146 Q: SMatrix<T, N, N>,
147}
148
149#[allow(non_snake_case)]
150impl<T: RealField + Copy, const N: usize> LinearNoInputSystem<T, N> {
151 pub fn new(F: SMatrix<T, N, N>, Q: SMatrix<T, N, N>, x_initial: SVector<T, N>) -> Self {
153 LinearNoInputSystem {
154 x: x_initial,
155 F,
156 F_t: F.transpose(),
157 Q,
158 }
159 }
160
161 pub fn set_transition(&mut self, transition: SMatrix<T, N, N>) {
163 self.F_t = transition.transpose();
164 self.F = transition;
165 }
166 pub fn covariance_mut(&mut self) -> &mut SMatrix<T, N, N> {
168 &mut self.Q
169 }
170}
171
172impl<T: RealField + Copy, const N: usize> System<T, N, 0> for LinearNoInputSystem<T, N> {
173 fn covariance(&self) -> &SMatrix<T, N, N> {
174 &self.Q
175 }
176
177 fn state(&self) -> &SVector<T, N> {
178 &self.x
179 }
180
181 fn state_mut(&mut self) -> &mut SVector<T, N> {
182 &mut self.x
183 }
184}
185
186impl<T: RealField + Copy, const N: usize> LinearisableSystem<T, N, 0>
187 for LinearNoInputSystem<T, N>
188{
189 fn transition(&self) -> &SMatrix<T, N, N> {
190 &self.F
191 }
192 fn transition_transpose(&self) -> &SMatrix<T, N, N> {
193 &self.F_t
194 }
195}
196
197impl<T: RealField + Copy, const N: usize> NoInputSystem<T, N> for LinearNoInputSystem<T, N> {
198 fn predict(&self, x: &SVector<T, N>) -> SVector<T, N> {
199 self.F * x
200 }
201}
202
203#[derive(Debug, Clone)]
207#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
208#[cfg_attr(feature = "defmt", derive(defmt::Format))]
209pub struct StepReturn<T: RealField, const N: usize> {
210 pub state: SVector<T, N>,
212 pub jacobian: SMatrix<T, N, N>,
214 pub covariance: SMatrix<T, N, N>,
216}
217
218pub type StepFunction<T, const N: usize, const U: usize> =
222 fn(SVector<T, N>, SVector<T, U>) -> StepReturn<T, N>;
223
224#[allow(non_snake_case)]
227#[derive(Debug, Clone)]
228#[cfg_attr(feature = "defmt", derive(defmt::Format))]
230pub struct NonLinearSystem<T: RealField, const N: usize, const U: usize> {
231 x: SVector<T, N>,
233 Q: SMatrix<T, N, N>,
235 F: SMatrix<T, N, N>,
237 F_t: SMatrix<T, N, N>,
239 step_fn: StepFunction<T, N, U>,
243}
244
245impl<T: RealField, const N: usize, const U: usize> NonLinearSystem<T, N, U> {
246 pub fn new(step_fn: StepFunction<T, N, U>, x_initial: SVector<T, N>) -> Self {
248 Self {
249 x: x_initial,
250 Q: SMatrix::zeros(),
251 F: SMatrix::zeros(),
252 F_t: SMatrix::zeros(),
253 step_fn,
254 }
255 }
256}
257
258impl<T: RealField + Copy, const N: usize, const U: usize> System<T, N, U>
259 for NonLinearSystem<T, N, U>
260{
261 fn covariance(&self) -> &SMatrix<T, N, N> {
262 &self.Q
263 }
264
265 fn state(&self) -> &SVector<T, N> {
266 &self.x
267 }
268
269 fn state_mut(&mut self) -> &mut SVector<T, N> {
270 &mut self.x
271 }
272}
273
274impl<T: RealField + Copy, const N: usize, const U: usize> LinearisableSystem<T, N, U>
275 for NonLinearSystem<T, N, U>
276{
277 fn transition(&self) -> &SMatrix<T, N, N> {
278 &self.F
279 }
280 fn transition_transpose(&self) -> &SMatrix<T, N, N> {
281 &self.F_t
282 }
283}
284
285impl<T: RealField + Copy, const N: usize, const U: usize> InputSystem<T, N, U>
286 for NonLinearSystem<T, N, U>
287{
288 fn step(&mut self, u: SVector<T, U>) -> &SVector<T, N> {
289 let r = (self.step_fn)(self.x, u);
291 self.x = r.state;
292 self.F = r.jacobian;
293 self.F_t = self.F.transpose();
294 self.Q = r.covariance;
295 self.state()
297 }
298
299 fn predict(&self, x: &SVector<T, N>, u: &SVector<T, U>) -> SVector<T, N> {
300 let r = (self.step_fn)(*x, *u);
301 r.state
302 }
303}
304
305pub fn zero_order_hold<T: RealField, const N: usize>(
307 state_matrix: SMatrix<T, N, N>,
308 timestep: T,
309) -> SMatrix<T, N, N> {
310 SMatrix::identity() + state_matrix * timestep
311}