1use nalgebra::{RealField, SMatrix, SVector};
11
12pub trait System<T, const N: usize, const U: usize> {
16 fn transition(&self) -> &SMatrix<T, N, N>;
18 fn transition_transpose(&self) -> &SMatrix<T, N, N>;
20 fn covariance(&self) -> &SMatrix<T, N, N>;
22 fn state(&self) -> &SVector<T, N>;
24 fn state_mut(&mut self) -> &mut SVector<T, N>;
26}
27
28pub trait InputSystem<T, const N: usize, const U: usize>: System<T, N, U> {
30 fn step(&mut self, u: SVector<T, U>) -> &SVector<T, N>;
32}
33
34pub trait NoInputSystem<T, const N: usize>: System<T, N, 0> {
37 fn step(&mut self) -> &SVector<T, N>;
39}
40
41#[allow(non_snake_case)]
44#[derive(Debug, Clone)]
45#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
46#[cfg_attr(feature = "defmt", derive(defmt::Format))]
47pub struct LinearSystem<T: RealField, const N: usize, const U: usize> {
48 #[cfg_attr(feature = "defmt", defmt(Debug2Format))]
49 x: SVector<T, N>,
50 #[cfg_attr(feature = "defmt", defmt(Debug2Format))]
51 F: SMatrix<T, N, N>,
52 #[cfg_attr(feature = "defmt", defmt(Debug2Format))]
53 F_t: SMatrix<T, N, N>,
54 #[cfg_attr(feature = "defmt", defmt(Debug2Format))]
55 Q: SMatrix<T, N, N>,
56 #[cfg_attr(feature = "defmt", defmt(Debug2Format))]
57 B: SMatrix<T, N, U>,
58}
59
60#[allow(non_snake_case)]
61impl<T: RealField + Copy, const N: usize, const U: usize> LinearSystem<T, N, U> {
62 pub fn new(
65 F: SMatrix<T, N, N>,
66 Q: SMatrix<T, N, N>,
67 B: SMatrix<T, N, U>,
68 x_initial: SVector<T, N>,
69 ) -> Self {
70 LinearSystem {
71 x: x_initial,
72 F,
73 F_t: F.transpose(),
74 Q,
75 B,
76 }
77 }
78 pub fn set_transition(&mut self, transition: SMatrix<T, N, N>) {
80 self.F_t = transition.transpose();
81 self.F = transition;
82 }
83 pub fn covariance_mut(&mut self) -> &mut SMatrix<T, N, N> {
85 &mut self.Q
86 }
87}
88
89impl<T: RealField + Copy, const N: usize, const U: usize> System<T, N, U>
91 for LinearSystem<T, N, U>
92{
93 fn transition(&self) -> &SMatrix<T, N, N> {
94 &self.F
95 }
96 fn transition_transpose(&self) -> &SMatrix<T, N, N> {
97 &self.F_t
98 }
99
100 fn covariance(&self) -> &SMatrix<T, N, N> {
101 &self.Q
102 }
103
104 fn state(&self) -> &SVector<T, N> {
105 &self.x
106 }
107
108 fn state_mut(&mut self) -> &mut SVector<T, N> {
109 &mut self.x
110 }
111}
112
113impl<T: RealField + Copy, const N: usize, const U: usize> InputSystem<T, N, U>
115 for LinearSystem<T, N, U>
116{
117 fn step(&mut self, u: SVector<T, U>) -> &SVector<T, N> {
118 self.x = self.F * self.x + self.B * u;
119 &self.x
120 }
121}
122
123#[allow(non_snake_case)]
126#[derive(Debug, Clone)]
127#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
128#[cfg_attr(feature = "defmt", derive(defmt::Format))]
129pub struct LinearNoInputSystem<T: RealField, const N: usize> {
130 #[cfg_attr(feature = "defmt", defmt(Debug2Format))]
131 x: SVector<T, N>,
132 #[cfg_attr(feature = "defmt", defmt(Debug2Format))]
133 F: SMatrix<T, N, N>,
134 #[cfg_attr(feature = "defmt", defmt(Debug2Format))]
135 F_t: SMatrix<T, N, N>,
136 #[cfg_attr(feature = "defmt", defmt(Debug2Format))]
137 Q: SMatrix<T, N, N>,
138}
139
140#[allow(non_snake_case)]
141impl<T: RealField + Copy, const N: usize> LinearNoInputSystem<T, N> {
142 pub fn new(F: SMatrix<T, N, N>, Q: SMatrix<T, N, N>, x_initial: SVector<T, N>) -> Self {
144 LinearNoInputSystem {
145 x: x_initial,
146 F,
147 F_t: F.transpose(),
148 Q,
149 }
150 }
151
152 pub fn set_transition(&mut self, transition: SMatrix<T, N, N>) {
154 self.F_t = transition.transpose();
155 self.F = transition;
156 }
157 pub fn covariance_mut(&mut self) -> &mut SMatrix<T, N, N> {
159 &mut self.Q
160 }
161}
162
163impl<T: RealField + Copy, const N: usize> System<T, N, 0> for LinearNoInputSystem<T, N> {
164 fn transition(&self) -> &SMatrix<T, N, N> {
165 &self.F
166 }
167 fn transition_transpose(&self) -> &SMatrix<T, N, N> {
168 &self.F_t
169 }
170
171 fn covariance(&self) -> &SMatrix<T, N, N> {
172 &self.Q
173 }
174
175 fn state(&self) -> &SVector<T, N> {
176 &self.x
177 }
178
179 fn state_mut(&mut self) -> &mut SVector<T, N> {
180 &mut self.x
181 }
182}
183
184impl<T: RealField + Copy, const N: usize> NoInputSystem<T, N> for LinearNoInputSystem<T, N> {
185 fn step(&mut self) -> &SVector<T, N> {
186 self.x = self.F * self.x;
187 &self.x
188 }
189}
190
191#[derive(Debug, Clone)]
195#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
196#[cfg_attr(feature = "defmt", derive(defmt::Format))]
197pub struct StepReturn<T: RealField, const N: usize> {
198 #[cfg_attr(feature = "defmt", defmt(Debug2Format))]
200 pub state: SVector<T, N>,
201 #[cfg_attr(feature = "defmt", defmt(Debug2Format))]
203 pub jacobian: SMatrix<T, N, N>,
204 #[cfg_attr(feature = "defmt", defmt(Debug2Format))]
206 pub covariance: SMatrix<T, N, N>,
207}
208
209pub type StepFunction<T, const N: usize, const U: usize> =
213 fn(SVector<T, N>, SVector<T, U>) -> StepReturn<T, N>;
214
215#[allow(non_snake_case)]
218#[derive(Debug, Clone)]
219#[cfg_attr(feature = "defmt", derive(defmt::Format))]
221pub struct NonLinearSystem<T: RealField, const N: usize, const U: usize> {
222 #[cfg_attr(feature = "defmt", defmt(Debug2Format))]
224 x: SVector<T, N>,
225 #[cfg_attr(feature = "defmt", defmt(Debug2Format))]
227 Q: SMatrix<T, N, N>,
228 #[cfg_attr(feature = "defmt", defmt(Debug2Format))]
230 F: SMatrix<T, N, N>,
231 #[cfg_attr(feature = "defmt", defmt(Debug2Format))]
233 F_t: SMatrix<T, N, N>,
234 step_fn: StepFunction<T, N, U>,
238}
239
240impl<T: RealField, const N: usize, const U: usize> NonLinearSystem<T, N, U> {
241 pub fn new(step_fn: StepFunction<T, N, U>, x_initial: SVector<T, N>) -> Self {
243 Self {
244 x: x_initial,
245 Q: SMatrix::zeros(),
246 F: SMatrix::zeros(),
247 F_t: SMatrix::zeros(),
248 step_fn,
249 }
250 }
251}
252
253impl<T: RealField + Copy, const N: usize, const U: usize> System<T, N, U>
254 for NonLinearSystem<T, N, U>
255{
256 fn transition(&self) -> &SMatrix<T, N, N> {
257 &self.F
258 }
259
260 fn transition_transpose(&self) -> &SMatrix<T, N, N> {
261 &self.F_t
262 }
263
264 fn covariance(&self) -> &SMatrix<T, N, N> {
265 &self.Q
266 }
267
268 fn state(&self) -> &SVector<T, N> {
269 &self.x
270 }
271
272 fn state_mut(&mut self) -> &mut SVector<T, N> {
273 &mut self.x
274 }
275}
276
277impl<T: RealField + Copy, const N: usize, const U: usize> InputSystem<T, N, U>
278 for NonLinearSystem<T, N, U>
279{
280 fn step(&mut self, u: SVector<T, U>) -> &SVector<T, N> {
281 let r = (self.step_fn)(self.x, u);
283 self.x = r.state;
284 self.F = r.jacobian;
285 self.F_t = self.F.transpose();
286 self.Q = r.covariance;
287 self.state()
289 }
290}
291
292pub fn zero_order_hold<T: RealField, const N: usize>(
294 state_matrix: SMatrix<T, N, N>,
295 timestep: T,
296) -> SMatrix<T, N, N> {
297 SMatrix::identity() + state_matrix * timestep
298}