use nalgebra::{RealField, SMatrix, SVector};
pub trait Measurement<T, const N: usize, const M: usize> {
fn covariance(&self) -> &SMatrix<T, M, M>;
fn measurement(&self) -> &SVector<T, M>;
fn set_measurement(&mut self, z: SVector<T, M>);
fn predict(&self, x: &SVector<T, N>) -> SVector<T, M>;
}
pub trait LinearisableMeasurement<T, const N: usize, const M: usize>: Measurement<T, N, M> {
fn observation(&self) -> &SMatrix<T, M, N>;
fn observation_transpose(&self) -> &SMatrix<T, N, M>;
}
#[allow(non_snake_case)]
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct LinearMeasurement<T: RealField, const N: usize, const M: usize> {
pub z: SVector<T, M>,
H: SMatrix<T, M, N>,
H_t: SMatrix<T, N, M>,
pub R: SMatrix<T, M, M>,
}
impl<T: RealField, const N: usize, const M: usize> LinearMeasurement<T, N, M> {
#[allow(non_snake_case)]
pub fn new(H: SMatrix<T, M, N>, R: SMatrix<T, M, M>, z: SVector<T, M>) -> Self {
Self {
z,
H_t: H.transpose(),
H,
R,
}
}
}
impl<T: RealField + Copy, const N: usize, const M: usize> Measurement<T, N, M>
for LinearMeasurement<T, N, M>
{
fn covariance(&self) -> &SMatrix<T, M, M> {
&self.R
}
fn set_measurement(&mut self, z: SVector<T, M>) {
self.z = z;
}
fn predict(&self, x: &SVector<T, N>) -> SVector<T, M> {
self.H * x
}
fn measurement(&self) -> &SVector<T, M> {
&self.z
}
}
impl<T: RealField + Copy, const N: usize, const M: usize> LinearisableMeasurement<T, N, M>
for LinearMeasurement<T, N, M>
{
fn observation(&self) -> &SMatrix<T, M, N> {
&self.H
}
fn observation_transpose(&self) -> &SMatrix<T, N, M> {
&self.H_t
}
}
pub type Prediction<T, const N: usize, const M: usize> = fn(&SVector<T, N>) -> SVector<T, M>;
#[allow(non_snake_case)]
#[derive(Debug, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct NonLinearMeasurement<T, const N: usize, const M: usize> {
pub z: SVector<T, M>,
H: SMatrix<T, M, N>,
H_t: SMatrix<T, N, M>,
pub R: SMatrix<T, M, M>,
prediction_fn: Prediction<T, N, M>,
}
impl<T: RealField, const N: usize, const M: usize> NonLinearMeasurement<T, N, M> {
#[allow(non_snake_case)]
pub fn new(prediction_fn: Prediction<T, N, M>, R: SMatrix<T, M, M>, z: SVector<T, M>) -> Self {
Self {
z,
H: SMatrix::zeros(),
H_t: SMatrix::zeros(),
R,
prediction_fn,
}
}
}
impl<T: RealField + Copy, const N: usize, const M: usize> Measurement<T, N, M>
for NonLinearMeasurement<T, N, M>
{
fn covariance(&self) -> &SMatrix<T, M, M> {
&self.R
}
fn set_measurement(&mut self, z: SVector<T, M>) {
self.z = z;
}
fn predict(&self, x: &SVector<T, N>) -> SVector<T, M> {
(self.prediction_fn)(x)
}
fn measurement(&self) -> &SVector<T, M> {
&self.z
}
}
impl<T: RealField + Copy, const N: usize, const M: usize> LinearisableMeasurement<T, N, M>
for NonLinearMeasurement<T, N, M>
{
fn observation(&self) -> &SMatrix<T, M, N> {
&self.H
}
fn observation_transpose(&self) -> &SMatrix<T, N, M> {
&self.H_t
}
}