use core::marker::PhantomData;
use crate::kalman::*;
use crate::matrix::{Matrix, MatrixDataType, MatrixMut, SquareMatrix};
#[allow(clippy::type_complexity)]
pub struct RegularObservationBuilder<H, Z, R, Y, S, K, TempSInv, TempHP, TempPHt, TempKHP> {
_phantom: (
PhantomData<Z>,
PhantomData<H>,
PhantomData<R>,
PhantomData<Y>,
PhantomData<S>,
PhantomData<K>,
PhantomData<TempSInv>,
PhantomData<TempHP>,
PhantomData<TempPHt>,
PhantomData<TempKHP>,
),
}
impl<H, Z, R, Y, S, K, TempSInv, TempHP, TempPHt, TempKHP>
RegularObservationBuilder<H, Z, R, Y, S, K, TempSInv, TempHP, TempPHt, TempKHP>
{
#[allow(non_snake_case, clippy::too_many_arguments, clippy::new_ret_no_self)]
pub fn new<const STATES: usize, const OBSERVATIONS: usize, T>(
H: H,
z: Z,
R: R,
y: Y,
S: S,
K: K,
temp_S_inv: TempSInv,
temp_HP: TempHP,
temp_PHt: TempPHt,
temp_KHP: TempKHP,
) -> RegularObservation<
STATES,
OBSERVATIONS,
T,
H,
Z,
R,
Y,
S,
K,
TempSInv,
TempHP,
TempPHt,
TempKHP,
>
where
T: MatrixDataType,
Z: MeasurementVector<OBSERVATIONS, T>,
H: ObservationMatrix<OBSERVATIONS, STATES, T>,
R: MeasurementNoiseCovarianceMatrix<OBSERVATIONS, T>,
Y: InnovationVector<OBSERVATIONS, T>,
S: InnovationCovarianceMatrix<OBSERVATIONS, T>,
K: KalmanGainMatrix<STATES, OBSERVATIONS, T>,
TempSInv: TemporaryResidualCovarianceInvertedMatrix<OBSERVATIONS, T>,
TempHP: TemporaryHPMatrix<OBSERVATIONS, STATES, T>,
TempPHt: TemporaryPHTMatrix<STATES, OBSERVATIONS, T>,
TempKHP: TemporaryKHPMatrix<STATES, T>,
{
RegularObservation::<STATES, OBSERVATIONS, T, _, _, _, _, _, _, _, _, _, _> {
z,
H,
R,
y,
S,
K,
temp_S_inv,
temp_HP,
temp_PHt,
temp_KHP,
_phantom: Default::default(),
}
}
}
#[allow(non_snake_case, unused)]
pub struct RegularObservation<
const STATES: usize,
const OBSERVATIONS: usize,
T,
H,
Z,
R,
Y,
S,
K,
TempSInv,
TempHP,
TempPHt,
TempKHP,
> {
pub(crate) z: Z,
pub(crate) H: H,
pub(crate) R: R,
pub(crate) y: Y,
pub(crate) S: S,
pub(crate) K: K,
pub(crate) temp_S_inv: TempSInv,
pub(crate) temp_HP: TempHP,
pub(crate) temp_PHt: TempPHt,
pub(crate) temp_KHP: TempKHP,
_phantom: PhantomData<T>,
}
impl<
const STATES: usize,
const OBSERVATIONS: usize,
T,
Z,
H,
R,
Y,
S,
K,
TempSInv,
TempHP,
TempKHP,
TempPHt,
>
RegularObservation<
STATES,
OBSERVATIONS,
T,
H,
Z,
R,
Y,
S,
K,
TempSInv,
TempHP,
TempPHt,
TempKHP,
>
{
#[inline(always)]
pub const fn measurements(&self) -> usize {
OBSERVATIONS
}
#[inline(always)]
pub const fn states(&self) -> usize {
STATES
}
#[inline(always)]
pub fn measurement_vector(&self) -> &Z {
&self.z
}
#[inline(always)]
#[doc(alias = "kalman_get_measurement_vector")]
pub fn measurement_vector_mut(&mut self) -> &mut Z {
&mut self.z
}
#[inline(always)]
pub fn observation_matrix(&self) -> &H {
&self.H
}
#[inline(always)]
pub fn measurement_noise_covariance(&self) -> &R {
&self.R
}
#[inline(always)]
#[doc(alias = "kalman_get_measurement_noise")]
pub fn measurement_noise_covariance_mut(&mut self) -> &mut R {
&mut self.R
}
}
impl<
const STATES: usize,
const OBSERVATIONS: usize,
T,
Z,
H,
R,
Y,
S,
K,
TempSInv,
TempHP,
TempKHP,
TempPHt,
>
RegularObservation<
STATES,
OBSERVATIONS,
T,
H,
Z,
R,
Y,
S,
K,
TempSInv,
TempHP,
TempPHt,
TempKHP,
>
where
H: ObservationMatrix<OBSERVATIONS, STATES, T>,
K: KalmanGainMatrix<STATES, OBSERVATIONS, T>,
S: InnovationCovarianceMatrix<OBSERVATIONS, T>,
R: MeasurementNoiseCovarianceMatrix<OBSERVATIONS, T>,
Y: InnovationVector<OBSERVATIONS, T>,
Z: MeasurementVector<OBSERVATIONS, T>,
TempSInv: TemporaryResidualCovarianceInvertedMatrix<OBSERVATIONS, T>,
TempHP: TemporaryHPMatrix<OBSERVATIONS, STATES, T>,
TempPHt: TemporaryPHTMatrix<STATES, OBSERVATIONS, T>,
TempKHP: TemporaryKHPMatrix<STATES, T>,
T: MatrixDataType,
{
#[inline]
#[allow(non_snake_case)]
pub fn correct<X, P>(&mut self, x: &mut X, P: &mut P)
where
X: StateVectorMut<STATES, T>,
P: EstimateCovarianceMatrix<STATES, T>,
{
let H = self.H.as_matrix();
let y = self.y.as_matrix_mut();
let z = self.z.as_matrix();
H.mult_rowvector(x.as_matrix(), y);
z.sub_inplace_b(y);
self.update_with_innovation(x, P);
}
#[allow(non_snake_case)]
fn update_with_innovation<X, P>(&mut self, x: &mut X, P: &mut P)
where
X: StateVectorMut<STATES, T>,
P: EstimateCovarianceMatrix<STATES, T>,
{
let P = P.as_matrix_mut();
let x = x.as_matrix_mut();
let H = self.H.as_matrix();
let K = self.K.as_matrix_mut();
let S = self.S.as_matrix_mut();
let R = self.R.as_matrix_mut();
let y = self.y.as_matrix_mut();
let S_inv = self.temp_S_inv.as_matrix_mut();
let temp_HP = self.temp_HP.as_matrix_mut();
let temp_KHP = self.temp_KHP.as_matrix_mut();
let temp_PHt = self.temp_PHt.as_matrix_mut();
H.mult(P, temp_HP); temp_HP.mult_transb(H, S); S.add_inplace_a(R);
S.cholesky_decompose_lower();
S.invert_l_cholesky(S_inv); P.mult_transb(H, temp_PHt); temp_PHt.mult(S_inv, K);
K.multadd_rowvector(y, x);
H.mult(P, temp_HP); K.mult(temp_HP, temp_KHP); P.sub_inplace_a(temp_KHP); }
}
impl<
const STATES: usize,
const OBSERVATIONS: usize,
T,
Z,
H,
R,
Y,
S,
K,
TempSInv,
TempHP,
TempPHt,
TempKHP,
>
RegularObservation<
STATES,
OBSERVATIONS,
T,
H,
Z,
R,
Y,
S,
K,
TempSInv,
TempHP,
TempPHt,
TempKHP,
>
where
H: ObservationMatrixMut<OBSERVATIONS, STATES, T>,
{
#[inline(always)]
#[doc(alias = "kalman_get_measurement_transformation")]
pub fn observation_matrix_mut(&mut self) -> &mut H {
&mut self.H
}
}
impl<
const STATES: usize,
const OBSERVATIONS: usize,
T,
Z,
H,
R,
Y,
S,
K,
TempSInv,
TempHP,
TempPHt,
TempKHP,
> KalmanFilterNumStates<STATES>
for RegularObservation<
STATES,
OBSERVATIONS,
T,
H,
Z,
R,
Y,
S,
K,
TempSInv,
TempHP,
TempPHt,
TempKHP,
>
{
}
impl<
const STATES: usize,
const OBSERVATIONS: usize,
T,
Z,
H,
R,
Y,
S,
K,
TempSInv,
TempHP,
TempPHt,
TempKHP,
> KalmanFilterNumObservations<OBSERVATIONS>
for RegularObservation<
STATES,
OBSERVATIONS,
T,
H,
Z,
R,
Y,
S,
K,
TempSInv,
TempHP,
TempPHt,
TempKHP,
>
{
}
impl<
const STATES: usize,
const OBSERVATIONS: usize,
T,
Z,
H,
R,
Y,
S,
K,
TempSInv,
TempHP,
TempPHt,
TempKHP,
> KalmanFilterMeasurementVector<OBSERVATIONS, T>
for RegularObservation<
STATES,
OBSERVATIONS,
T,
H,
Z,
R,
Y,
S,
K,
TempSInv,
TempHP,
TempPHt,
TempKHP,
>
where
Z: MeasurementVector<OBSERVATIONS, T>,
{
type MeasurementVector = Z;
#[inline(always)]
fn measurement_vector(&self) -> &Self::MeasurementVector {
self.measurement_vector()
}
}
impl<
const STATES: usize,
const OBSERVATIONS: usize,
T,
Z,
H,
R,
Y,
S,
K,
TempSInv,
TempHP,
TempPHt,
TempKHP,
> KalmanFilterObservationVectorMut<OBSERVATIONS, T>
for RegularObservation<
STATES,
OBSERVATIONS,
T,
H,
Z,
R,
Y,
S,
K,
TempSInv,
TempHP,
TempPHt,
TempKHP,
>
where
Z: MeasurementVectorMut<OBSERVATIONS, T>,
{
type MeasurementVectorMut = Z;
#[inline(always)]
fn measurement_vector_mut(&mut self) -> &mut Self::MeasurementVectorMut {
self.measurement_vector_mut()
}
}
impl<
const STATES: usize,
const OBSERVATIONS: usize,
T,
Z,
H,
R,
Y,
S,
K,
TempSInv,
TempHP,
TempPHt,
TempKHP,
> KalmanFilterObservationTransformation<STATES, OBSERVATIONS, T>
for RegularObservation<
STATES,
OBSERVATIONS,
T,
H,
Z,
R,
Y,
S,
K,
TempSInv,
TempHP,
TempPHt,
TempKHP,
>
where
H: ObservationMatrix<OBSERVATIONS, STATES, T>,
{
type ObservationTransformationMatrix = H;
#[inline(always)]
fn observation_matrix(&self) -> &Self::ObservationTransformationMatrix {
self.observation_matrix()
}
}
impl<
const STATES: usize,
const OBSERVATIONS: usize,
T,
Z,
H,
R,
Y,
S,
K,
TempSInv,
TempHP,
TempPHt,
TempKHP,
> KalmanFilterObservationTransformationMut<STATES, OBSERVATIONS, T>
for RegularObservation<
STATES,
OBSERVATIONS,
T,
H,
Z,
R,
Y,
S,
K,
TempSInv,
TempHP,
TempPHt,
TempKHP,
>
where
H: ObservationMatrixMut<OBSERVATIONS, STATES, T>,
{
type ObservationTransformationMatrixMut = H;
#[inline(always)]
fn observation_matrix_mut(&mut self) -> &mut Self::ObservationTransformationMatrixMut {
self.observation_matrix_mut()
}
}
impl<
const STATES: usize,
const OBSERVATIONS: usize,
T,
Z,
H,
R,
Y,
S,
K,
TempSInv,
TempHP,
TempPHt,
TempKHP,
> KalmanFilterMeasurementNoiseCovariance<OBSERVATIONS, T>
for RegularObservation<
STATES,
OBSERVATIONS,
T,
H,
Z,
R,
Y,
S,
K,
TempSInv,
TempHP,
TempPHt,
TempKHP,
>
where
R: MeasurementNoiseCovarianceMatrix<OBSERVATIONS, T>,
{
type MeasurementNoiseCovarianceMatrix = R;
#[inline(always)]
fn measurement_noise_covariance(&self) -> &Self::MeasurementNoiseCovarianceMatrix {
self.measurement_noise_covariance()
}
}
impl<
const STATES: usize,
const OBSERVATIONS: usize,
T,
Z,
H,
R,
Y,
S,
K,
TempSInv,
TempHP,
TempPHt,
TempKHP,
> KalmanFilterMeasurementNoiseCovarianceMut<OBSERVATIONS, T>
for RegularObservation<
STATES,
OBSERVATIONS,
T,
H,
Z,
R,
Y,
S,
K,
TempSInv,
TempHP,
TempPHt,
TempKHP,
>
where
R: MeasurementNoiseCovarianceMatrix<OBSERVATIONS, T>,
{
type MeasurementNoiseCovarianceMatrixMut = R;
#[inline(always)]
fn measurement_noise_covariance_mut(
&mut self,
) -> &mut Self::MeasurementNoiseCovarianceMatrixMut {
self.measurement_noise_covariance_mut()
}
}
impl<
const STATES: usize,
const OBSERVATIONS: usize,
T,
Z,
H,
R,
Y,
S,
K,
TempSInv,
TempHP,
TempPHt,
TempKHP,
> KalmanFilterObservationCorrectFilter<STATES, T>
for RegularObservation<
STATES,
OBSERVATIONS,
T,
H,
Z,
R,
Y,
S,
K,
TempSInv,
TempHP,
TempPHt,
TempKHP,
>
where
H: ObservationMatrix<OBSERVATIONS, STATES, T>,
K: KalmanGainMatrix<STATES, OBSERVATIONS, T>,
S: InnovationCovarianceMatrix<OBSERVATIONS, T>,
R: MeasurementNoiseCovarianceMatrix<OBSERVATIONS, T>,
Y: InnovationVector<OBSERVATIONS, T>,
Z: MeasurementVector<OBSERVATIONS, T>,
TempSInv: TemporaryResidualCovarianceInvertedMatrix<OBSERVATIONS, T>,
TempHP: TemporaryHPMatrix<OBSERVATIONS, STATES, T>,
TempPHt: TemporaryPHTMatrix<STATES, OBSERVATIONS, T>,
TempKHP: TemporaryKHPMatrix<STATES, T>,
T: MatrixDataType,
{
#[inline(always)]
#[allow(non_snake_case)]
fn correct<X, P>(&mut self, x: &mut X, P: &mut P)
where
X: StateVectorMut<STATES, T>,
P: EstimateCovarianceMatrix<STATES, T>,
{
self.correct(x, P)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::prelude::{AsMatrix, AsMatrixMut};
use crate::test_dummies::make_dummy_observation;
#[test]
#[cfg(feature = "alloc")]
fn test_mut_apply() {
use crate::regular::builder::KalmanFilterBuilder;
let builder = KalmanFilterBuilder::<3, f32>::default();
let mut filter = builder.build();
let mut measurement = builder.observations().build::<5>();
filter.predict();
filter.correct(&mut measurement);
}
fn trait_impl<const STATES: usize, const OBSERVATIONS: usize, T, M>(mut measurement: M) -> M
where
M: KalmanFilterObservation<STATES, OBSERVATIONS, T>
+ KalmanFilterObservationTransformationMut<STATES, OBSERVATIONS, T>,
{
assert_eq!(measurement.states(), STATES);
assert_eq!(measurement.observations(), OBSERVATIONS);
let test_fn = || 42;
let mut temp = 0;
let mut test_fn_mut = || {
temp += 0;
42
};
let _vec = measurement.measurement_vector();
let _vec = measurement.measurement_vector_mut();
measurement
.measurement_vector()
.as_matrix()
.inspect(|_vec| test_fn());
measurement
.measurement_vector()
.as_matrix()
.inspect(|_vec| test_fn_mut());
measurement
.measurement_vector_mut()
.as_matrix_mut()
.apply(|_vec| test_fn());
measurement
.measurement_vector_mut()
.as_matrix_mut()
.apply(|_vec| test_fn_mut());
let _mat = measurement.observation_matrix();
let _mat = measurement.observation_matrix_mut();
let _ = measurement
.observation_matrix()
.as_matrix()
.inspect(|_mat| test_fn());
let _ = measurement
.observation_matrix()
.as_matrix()
.inspect(|_mat| test_fn_mut());
measurement
.observation_matrix_mut()
.as_matrix_mut()
.apply(|_mat| test_fn());
measurement
.observation_matrix_mut()
.as_matrix_mut()
.apply(|_mat| test_fn_mut());
let _mat = measurement.measurement_noise_covariance();
let _mat = measurement.measurement_noise_covariance_mut();
let _ = measurement
.measurement_noise_covariance()
.as_matrix()
.inspect(|_mat| test_fn());
let _ = measurement
.measurement_noise_covariance()
.as_matrix()
.inspect(|_mat| test_fn_mut());
measurement
.measurement_noise_covariance_mut()
.as_matrix_mut()
.apply(|_mat| test_fn());
measurement
.measurement_noise_covariance_mut()
.as_matrix_mut()
.apply(|_mat| test_fn_mut());
measurement
}
#[test]
fn builder_simple() {
let measurement = make_dummy_observation();
let mut measurement = trait_impl(measurement);
assert_eq!(measurement.states(), 3);
assert_eq!(measurement.observations(), 1);
let test_fn = || 42;
let mut temp = 0;
let mut test_fn_mut = || {
temp += 0;
42
};
let _vec = measurement.measurement_vector();
let _vec = measurement.measurement_vector_mut();
let _ = measurement
.measurement_vector()
.as_matrix()
.inspect(|_vec| test_fn());
let _ = measurement
.measurement_vector()
.as_matrix()
.inspect(|_vec| test_fn_mut());
measurement
.measurement_vector_mut()
.as_matrix_mut()
.apply(|_vec| test_fn());
measurement
.measurement_vector_mut()
.as_matrix_mut()
.apply(|_vec| test_fn_mut());
let _mat = measurement.observation_matrix();
let _mat = measurement.observation_matrix_mut();
let _ = measurement
.observation_matrix()
.as_matrix()
.inspect(|_mat| test_fn());
let _ = measurement
.observation_matrix()
.as_matrix()
.inspect(|_mat| test_fn_mut());
measurement
.observation_matrix_mut()
.as_matrix_mut()
.apply(|_mat| test_fn());
measurement
.observation_matrix_mut()
.as_matrix_mut()
.apply(|_mat| test_fn_mut());
let _mat = measurement.measurement_noise_covariance();
let _mat = measurement.measurement_noise_covariance_mut();
let _ = measurement
.measurement_noise_covariance()
.as_matrix()
.inspect(|_mat| test_fn());
let _ = measurement
.measurement_noise_covariance()
.as_matrix()
.inspect(|_mat| test_fn_mut());
measurement
.measurement_noise_covariance_mut()
.as_matrix_mut()
.apply(|_mat| test_fn());
measurement
.measurement_noise_covariance_mut()
.as_matrix_mut()
.apply(|_mat| test_fn_mut());
}
}