#![allow(non_snake_case)]
use nalgebra::{allocator::Allocator, Const, DefaultAllocator, Dim, OMatrix, OVector, RealField};
use crate::matrix;
pub struct UncorrelatedNoise<N: RealField, QD: Dim>
where
DefaultAllocator: Allocator<N, QD>,
{
pub q: OVector<N, QD>,
}
pub struct CorrelatedNoise<N: RealField, D: Dim>
where
DefaultAllocator: Allocator<N, D, D>,
{
pub Q: OMatrix<N, D, D>,
}
pub struct CoupledNoise<N: RealField, D: Dim, QD: Dim>
where
DefaultAllocator: Allocator<N, D, QD> + Allocator<N, QD>,
{
pub q: OVector<N, QD>,
pub G: OMatrix<N, D, QD>,
}
impl<'a, N: Copy + RealField, D: Dim> CorrelatedNoise<N, D>
where
DefaultAllocator: Allocator<N, D, D> + Allocator<N, D>,
{
pub fn from_coupled<QD: Dim>(coupled: &'a CoupledNoise<N, D, QD>) -> Self
where
DefaultAllocator: Allocator<N, QD, QD> + Allocator<N, D, QD> + Allocator<N, QD>,
{
let mut Q = OMatrix::zeros_generic(coupled.G.shape_generic().0, coupled.G.shape_generic().0);
matrix::quadform_tr(&mut Q, N::one(), &coupled.G, &coupled.q, N::one());
CorrelatedNoise { Q }
}
pub fn from_uncorrelated(uncorrelated: &'a UncorrelatedNoise<N, D>) -> Self {
let z_size = uncorrelated.q.shape_generic().0;
let mut correlated = CorrelatedNoise {
Q: OMatrix::zeros_generic(z_size, z_size),
};
for i in 0..uncorrelated.q.nrows() {
correlated.Q[(i, i)] = uncorrelated.q[i];
}
correlated
}
}
impl<N: Copy + RealField, D: Dim> CoupledNoise<N, D, D>
where
DefaultAllocator: Allocator<N, D, D> + Allocator<N, D>,
{
pub fn from_uncorrelated(uncorrelated: UncorrelatedNoise<N, D>) -> Self {
let nrows = uncorrelated.q.shape_generic().0;
CoupledNoise {
q: uncorrelated.q,
G: OMatrix::identity_generic(nrows, nrows),
}
}
pub fn from_correlated(correlated: &CorrelatedNoise<N, D>) -> Result<Self, &'static str> {
let d = correlated.Q.shape_generic().0;
let cholesky = correlated.Q.clone().cholesky().ok_or("Q not PSD")?;
Ok(CoupledNoise {
q: OVector::repeat_generic(d, Const::<1>, N::one()),
G: cholesky.l(),
})
}
}