1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#![allow(non_snake_case)]
use na::{allocator::Allocator, DefaultAllocator, Dim, MatrixMN, MatrixN, VectorN};
use na::SimdRealField;
use na::storage::Storage;
use nalgebra as na;
use nalgebra::{RealField, U1};
use crate::cholesky::UDU;
use crate::matrix;
use crate::matrix::check_non_negativ;
pub struct UncorrelatedNoise<N: SimdRealField, QD: Dim>
where
DefaultAllocator: Allocator<N, QD>
{
pub q: VectorN<N, QD>,
}
pub struct CorrelatedNoise<N: SimdRealField, D: Dim>
where
DefaultAllocator: Allocator<N, D, D>
{
pub Q: MatrixN<N, D>
}
pub struct CoupledNoise<N: RealField, D: Dim, QD: Dim>
where
DefaultAllocator: Allocator<N, D, QD> + Allocator<N, QD>,
{
pub q: VectorN<N, QD>,
pub G: MatrixMN<N, D, QD>,
}
impl<'a, N: 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 = MatrixMN::zeros_generic(coupled.G.data.shape().0, coupled.G.data.shape().0);
matrix::quadform_tr(&mut Q, N::one(), &coupled.G, &coupled.q, N::one());
CorrelatedNoise {
Q
}
}
}
impl<'a, N: SimdRealField, QD: Dim> CorrelatedNoise<N, QD>
where
DefaultAllocator: Allocator<N, QD, QD> + Allocator<N, QD>
{
pub fn from_uncorrelated(uncorrelated: &'a UncorrelatedNoise<N, QD>) -> Self {
let z_size = uncorrelated.q.data.shape().0;
let mut correlated = CorrelatedNoise {
Q: MatrixMN::zeros_generic(z_size, z_size)
};
for i in 0..uncorrelated.q.nrows() {
correlated.Q[(i,i)] = uncorrelated.q[i];
}
correlated
}
}
impl<N: RealField, D: Dim> CoupledNoise<N, D, D>
where
DefaultAllocator: Allocator<N, D, D> + Allocator<N, D>,
{
pub fn from_correlated(correlated: &CorrelatedNoise<N, D>) -> Result<Self, &'static str> {
let mut uc = correlated.Q.clone();
let udu = UDU::new();
let rcond = udu.UCfactor_n(&mut uc, correlated.Q.nrows());
check_non_negativ(rcond, "Q not PSD")?;
uc.fill_lower_triangle(N::zero(), 1);
Ok(CoupledNoise {
q: VectorN::repeat_generic(uc.data.shape().0, U1, N::one()),
G: uc
})
}
}