0.5.0
Loading...
Searching...
No Matches
BsplineKF.cpp
Go to the documentation of this file.
1// This file is part of INSTINCT, the INS Toolkit for Integrated
2// Navigation Concepts and Training by the Institute of Navigation of
3// the University of Stuttgart, Germany.
4//
5// This Source Code Form is subject to the terms of the Mozilla Public
6// License, v. 2.0. If a copy of the MPL was not distributed with this
7// file, You can obtain one at https://mozilla.org/MPL/2.0/.
8
9#include "BsplineKF.hpp"
10
11#include "QuadraticBsplines.hpp"
12
14#include "util/Logger.hpp"
15
16Eigen::MatrixXd NAV::BsplineKF::initialErrorCovarianceMatrix_P0(const std::vector<Eigen::VectorXd>& initCovariances, const uint8_t& numStates, const bool& imuCharacteristicsIdentical)
17{
18 Eigen::MatrixXd P = Eigen::MatrixXd::Zero(numStates, numStates);
19
20 P.block<9, 9>(0, 0).diagonal() = initCovariances.at(0); // Angular rate B-spline factors
21 P.block<9, 9>(9, 9).diagonal() = initCovariances.at(1); // Acceleration B-spline factors
22
23 // Biases
24 size_t j = 2;
25 for (uint32_t i = 18; i < numStates; i += 6)
26 {
27 if (!imuCharacteristicsIdentical)
28 {
29 j = 2 + (i - 18) / 3; // access bias variances for each sensor from the third element onwards
30 }
31 P.block<3, 3>(i, i).diagonal() = initCovariances.at(j);
32 P.block<3, 3>(i + 3, i + 3).diagonal() = initCovariances.at(j + 1);
33 }
34
35 return P;
36}
37
38void NAV::BsplineKF::processNoiseMatrix_Q(Eigen::MatrixXd& Q, const double& dt, const std::vector<Eigen::VectorXd>& processNoiseVariances, const uint8_t& numStates, const bool& imuCharacteristicsIdentical)
39{
40 Q.block<9, 9>(0, 0).diagonal() = processNoiseVariances.at(0) * dt; // Random walk of the angular rate B-spline factors
41 Q.block<9, 9>(9, 9).diagonal() = processNoiseVariances.at(1) * dt; // Random walk of the acceleration B-spline factors
42
43 // Random walk of the bias states
44 size_t j = 2;
45 for (uint32_t i = 18; i < numStates; i += 6) // FIXME: i = 'numStatesEst' better than '12'? (magic numbers)
46 {
47 if (!imuCharacteristicsIdentical)
48 {
49 j = 2 + (i - 18) / 3; // access 2 bias variances for each sensor from the third element onwards
50 }
51 Q.block<3, 3>(i, i).diagonal() = processNoiseVariances.at(j) * dt; // variance for the process noise of the angular rate
52 Q.block<3, 3>(i + 3, i + 3).diagonal() = processNoiseVariances.at(j + 1) * dt; // variance for the process noise of the acceleration
53 }
54}
55
56void NAV::BsplineKF::rotateCoeffStates(Eigen::MatrixXd& x)
57{
58 x.block<6, 1>(0, 0) = x.block<6, 1>(3, 0); // Angular rate coeffs (c_{omega,k+1} = c_{omega,k})
59 x.block<6, 1>(9, 0) = x.block<6, 1>(9, 0); // Acceleration coeffs (c_{f,k+1} = c_{f,k})
60}
61
62void NAV::BsplineKF::rotateErrorCovariances(Eigen::MatrixXd& P, uint8_t& numStates, const double& sigmaScalingFactorAngRate, const double& sigmaScalingFactorAccel)
63{
64 int nCoeffsPerStackedBspline = 9;
65 auto nCoeffsRemainingAngRate = static_cast<int>(numStates) - nCoeffsPerStackedBspline;
66 auto nCoeffsRemainingAccel = static_cast<int>(numStates) - 2 * nCoeffsPerStackedBspline;
67
68 // Shift all error covariances corresponding to angular rate B-spline coeffs
69 P.block<6, 6>(0, 0) = P.block<6, 6>(3, 3); // Variances of the angular rate
70 P.block(0, 9, 6, nCoeffsRemainingAngRate) = P.block(3, 9, 6, nCoeffsRemainingAngRate); // Upper right corner
71 P.block(9, 0, nCoeffsRemainingAngRate, 6) = P.block(9, 3, nCoeffsRemainingAngRate, 6); // Lower left corner
72
73 // Set angular rate error covariances for the new B-spline coeff
74 P.block(0, 6, numStates, 3) = Eigen::MatrixXd::Zero(numStates, 3); // Column
75 P.block(6, 0, 3, numStates) = Eigen::MatrixXd::Zero(3, numStates); // Row
76 P.block<3, 3>(6, 6).diagonal() = std::pow(sigmaScalingFactorAngRate, 2) * P.block<3, 3>(3, 3).diagonal(); // Variance (i.e. squared)
77
78 // Shift all error covariances corresponding to acceleration B-spline coeffs
79 P.block<6, 6>(9, 9) = P.block<6, 6>(12, 12); // Variances of the acceleration
80 P.block<9, 6>(0, 9) = P.block<9, 6>(0, 12); // Top middle part
81 P.block(9, 18, 6, nCoeffsRemainingAccel) = P.block(12, 18, 6, nCoeffsRemainingAccel); // Middle right part
82 P.block<6, 9>(9, 0) = P.block<6, 9>(12, 0); // Middle left part
83 P.block(18, 9, nCoeffsRemainingAccel, 6) = P.block(18, 12, nCoeffsRemainingAccel, 6); // Lower middle part
84
85 // Set acceleration error covariances for the new B-spline coeff
86 P.block(0, 15, numStates, 3) = Eigen::MatrixXd::Zero(numStates, 3); // Column
87 P.block(15, 0, 3, numStates) = Eigen::MatrixXd::Zero(3, numStates); // Row
88 P.block<3, 3>(15, 15).diagonal() = std::pow(sigmaScalingFactorAccel, 2) * P.block<3, 3>(12, 12).diagonal(); // Variance (i.e. squared)
89}
90
91Eigen::MatrixXd NAV::BsplineKF::designMatrix_H(const double& ti, const double& splineSpacing, const Eigen::Matrix3d& DCM_accel, const Eigen::Matrix3d& DCM_gyro, const size_t& pinIndex, const uint8_t& numMeasurements, const uint8_t& numStates, const uint8_t& numStatesEst, const uint8_t& numStatesPerPin)
92{
93 Eigen::MatrixXd H = Eigen::MatrixXd::Zero(numMeasurements, numStates);
94
95 auto qBspline = NAV::BsplineKF::quadraticBsplines(ti, splineSpacing);
96
97 // Set quadratic B-splines in design matrix H
98 for (size_t knotIdx = 0; knotIdx < 3; knotIdx++)
99 {
100 auto stateIdx = static_cast<Eigen::Index>(3 * knotIdx);
101 H.block<3, 3>(0, stateIdx).diagonal() = qBspline.at(knotIdx) * Eigen::Vector3d::Ones();
102 LOG_DATA("stateIdx = {}, knotIdx = {}, H =\n{}", stateIdx, knotIdx, H);
103 }
104
105 // Set the three stacked quadratic B-spline elements for the acceleration (analogous to the angular rate block)
106 H.block<3, 9>(3, 9) = DCM_accel.transpose() * H.block<3, 9>(0, 0);
107 // Rotate the angular rate blocks
108 H.block<3, 9>(0, 0) = DCM_gyro.transpose() * H.block<3, 9>(0, 0);
109 LOG_DATA("H =\n{}", H);
110
111 // Map the biases to the states as in the IRWKF
112 if (pinIndex > 0)
113 {
114 const auto stateIndex = static_cast<uint8_t>(numStatesEst + numStatesPerPin * (pinIndex - 1));
115 LOG_DATA("stateIndex = {}", stateIndex);
116
117 H.block<6, 6>(0, stateIndex) = Eigen::MatrixXd::Identity(6, 6);
118 }
119
120 return H;
121}
122
123NAV::KalmanFilter NAV::BsplineKF::initializeKalmanFilterManually(const size_t& numInputPins, const std::vector<PinData>& pinData, const PinDataBsplineKF& pinDataBsplineKF, const uint8_t& numStates, const double& dtInit, std::vector<Eigen::VectorXd>& processNoiseVariances, KalmanFilter& kalmanFilter, const bool& imuCharacteristicsIdentical, const bool& imuBiasesIdentical)
124{
125 // ------------------------------------------ State vector x ---------------------------------------------
126 std::vector<Eigen::VectorXd> initStates;
127 initStates.resize(numStates);
128
129 // Initial B-spline coefficients of the angular rate in [rad/s]
131 {
132 initStates[0] = deg2rad(pinDataBsplineKF.initCoeffsAngRate);
133 }
135 {
136 initStates[0] = pinDataBsplineKF.initCoeffsAngRate;
137 }
138
139 // Initial B-spline coefficients of the acceleration in [m/s]
141 {
142 initStates[1] = pinDataBsplineKF.initCoeffsAccel;
143 }
144
145 size_t pinDataBiasesIdenticalIdx = 1;
146 for (size_t pinIndex = 1; pinIndex < numInputPins; ++pinIndex)
147 {
148 if (!imuBiasesIdentical)
149 {
150 pinDataBiasesIdenticalIdx = pinIndex;
151 }
152
153 // Initial bias of the angular rate in [rad/s]
154 if (pinData[pinDataBiasesIdenticalIdx].initAngularRateBiasUnit == PinData::AngRateUnit::rad_s)
155 {
156 initStates[2 * pinIndex] = pinData[pinDataBiasesIdenticalIdx].initAngularRateBias.array();
157 }
158 else if (pinData[pinDataBiasesIdenticalIdx].initAngularRateBiasUnit == PinData::AngRateUnit::deg_s)
159 {
160 initStates[2 * pinIndex] = deg2rad(pinData[pinDataBiasesIdenticalIdx].initAngularRateBias).array();
161 }
162
163 // Initial bias of the acceleration in [m/s²]
164 if (pinData[pinDataBiasesIdenticalIdx].initAccelerationBiasUnit == PinData::AccelerationUnit::m_s2)
165 {
166 initStates[1 + 2 * pinIndex] = pinData[pinDataBiasesIdenticalIdx].initAccelerationBias.array();
167 }
168 }
169
170 kalmanFilter.x.block<9, 1>(0, 0) = initStates[0];
171 kalmanFilter.x.block<9, 1>(9, 0) = initStates[1];
172 LOG_DATA("Initial B-spline coefficients in the state vector x:\n{}", kalmanFilter.x.block<18, 1>(0, 0));
173
174 uint32_t containerIndex = 2;
175 for (uint32_t pinIndex = 0; pinIndex < numInputPins - 1UL; ++pinIndex)
176 {
177 if (!imuBiasesIdentical)
178 {
179 containerIndex = 2 + 2 * pinIndex;
180 }
181 kalmanFilter.x.block<3, 1>(18 + 6 * pinIndex, 0) = initStates[containerIndex];
182 kalmanFilter.x.block<3, 1>(21 + 6 * pinIndex, 0) = initStates[1 + containerIndex];
183 }
184 LOG_DATA("Initial bias values:\n{}", kalmanFilter.x.block<18, 1>(18, 0));
185
186 // -------------------------------------- State transition matrix ----------------------------------------
187 kalmanFilter.Phi = Eigen::MatrixXd::Identity(numStates, numStates);
188
189 // ------------------------------------- Error covariance matrix P ---------------------------------------
190
191 std::vector<Eigen::VectorXd> initErrorCovariances;
192 initErrorCovariances.resize(2 + 2 * (numInputPins - 1));
193
194 // Initial error covariance of the B-spline KF angular rate coefficients in [rad²/s²]
196 {
197 initErrorCovariances[0] = pinDataBsplineKF.initCovarianceCoeffsAngRate;
198 }
200 {
201 initErrorCovariances[0] = deg2rad(pinDataBsplineKF.initCovarianceCoeffsAngRate);
202 }
204 {
205 initErrorCovariances[0] = pinDataBsplineKF.initCovarianceCoeffsAngRate.array().pow(2);
206 }
208 {
209 initErrorCovariances[0] = deg2rad(pinDataBsplineKF.initCovarianceCoeffsAngRate).array().pow(2);
210 }
211
212 // Initial error covariance of the B-spline KF acceleration coefficients in [(m^2)/(s^4)]
214 {
215 initErrorCovariances[1] = pinDataBsplineKF.initCovarianceCoeffsAccel;
216 }
218 {
219 initErrorCovariances[1] = pinDataBsplineKF.initCovarianceCoeffsAccel.array().pow(2);
220 }
221
222 size_t pinDataIdx = 1;
223 for (size_t pinIndex = 1; pinIndex < numInputPins; ++pinIndex)
224 {
225 if (!imuCharacteristicsIdentical)
226 {
227 pinDataIdx = pinIndex;
228 }
229
230 // Initial Covariance of the bias of the angular rate in [rad²/s²]
231 if (pinData[pinDataIdx].initCovarianceBiasAngRateUnit == PinData::AngRateVarianceUnit::rad2_s2)
232 {
233 initErrorCovariances[2 * pinIndex] = pinData[pinDataIdx].initCovarianceBiasAngRate;
234 }
235 else if (pinData[pinDataIdx].initCovarianceBiasAngRateUnit == PinData::AngRateVarianceUnit::deg2_s2)
236 {
237 initErrorCovariances[2 * pinIndex] = deg2rad(pinData[pinDataIdx].initCovarianceBiasAngRate);
238 }
239 else if (pinData[pinDataIdx].initCovarianceBiasAngRateUnit == PinData::AngRateVarianceUnit::rad_s)
240 {
241 initErrorCovariances[2 * pinIndex] = pinData[pinDataIdx].initCovarianceBiasAngRate.array().pow(2);
242 }
243 else if (pinData[pinDataIdx].initCovarianceBiasAngRateUnit == PinData::AngRateVarianceUnit::deg_s)
244 {
245 initErrorCovariances[2 * pinIndex] = deg2rad(pinData[pinDataIdx].initCovarianceBiasAngRate).array().pow(2);
246 }
247
248 // Initial Covariance of the bias of the acceleration in [(m^2)/(s^4)]
249 if (pinData[pinDataIdx].initCovarianceBiasAccUnit == PinData::AccelerationVarianceUnit::m2_s4)
250 {
251 initErrorCovariances[1 + 2 * pinIndex] = pinData[pinDataIdx].initCovarianceBiasAcc;
252 }
253 else if (pinData[pinDataIdx].initCovarianceBiasAccUnit == PinData::AccelerationVarianceUnit::m_s2)
254 {
255 initErrorCovariances[1 + 2 * pinIndex] = pinData[pinDataIdx].initCovarianceBiasAcc.array().pow(2);
256 }
257 }
258
259 kalmanFilter.P = NAV::BsplineKF::initialErrorCovarianceMatrix_P0(initErrorCovariances, numStates, imuCharacteristicsIdentical);
260
261 // -------------------------------------- Process noise matrix Q -----------------------------------------
262 processNoiseVariances.resize(2 * numInputPins);
263
264 // 𝜎_AngRateFactors: Standard deviation of the noise on the B-spline coefficients angular rate states [rad/s]
265 switch (pinDataBsplineKF.varCoeffsAngRateUnit)
266 {
268 processNoiseVariances[0] = pinDataBsplineKF.varCoeffsAngRateNoise;
269 break;
271 processNoiseVariances[0] = deg2rad(pinDataBsplineKF.varCoeffsAngRateNoise);
272 break;
274 processNoiseVariances[0] = deg2rad(pinDataBsplineKF.varCoeffsAngRateNoise).array().pow(2);
275 break;
277 processNoiseVariances[0] = pinDataBsplineKF.varCoeffsAngRateNoise.array().pow(2);
278 break;
279 }
280
281 // 𝜎_AccelFactors: Standard deviation of the noise on the B-spline coefficients acceleration states [m/s]
282 switch (pinDataBsplineKF.varCoeffsAccelUnit)
283 {
285 processNoiseVariances[1] = pinDataBsplineKF.varCoeffsAccelNoise;
286 break;
288 processNoiseVariances[1] = pinDataBsplineKF.varCoeffsAccelNoise.array().pow(2);
289 break;
290 }
291
292 for (size_t pinIndex = 1; pinIndex < numInputPins; ++pinIndex)
293 {
294 if (!imuCharacteristicsIdentical)
295 {
296 pinDataIdx = pinIndex;
297 }
298
299 // 𝜎_biasAngRate Standard deviation of the bias on the angular rate state [rad/s²]
300 switch (pinData[pinDataIdx].varBiasAngRateNoiseUnit)
301 {
303 processNoiseVariances[2 * pinIndex] = pinData[pinDataIdx].varBiasAngRateNoise;
304 break;
306 processNoiseVariances[2 * pinIndex] = deg2rad(pinData[pinDataIdx].varBiasAngRateNoise);
307 break;
309 processNoiseVariances[2 * pinIndex] = deg2rad(pinData[pinDataIdx].varBiasAngRateNoise).array().pow(2);
310 break;
312 processNoiseVariances[2 * pinIndex] = pinData[pinDataIdx].varBiasAngRateNoise.array().pow(2);
313 break;
314 }
315
316 // 𝜎_biasAcceleration Standard deviation of the noise on the acceleration state [m/s³]
317 switch (pinData[pinDataIdx].varBiasAccelerationNoiseUnit)
318 {
320 processNoiseVariances[1 + 2 * pinIndex] = pinData[pinDataIdx].varBiasAccelerationNoise;
321 break;
323 processNoiseVariances[1 + 2 * pinIndex] = pinData[pinDataIdx].varBiasAccelerationNoise.array().pow(2);
324 break;
325 }
326 }
327
328 NAV::BsplineKF::processNoiseMatrix_Q(kalmanFilter.Q, dtInit, processNoiseVariances, numStates, imuCharacteristicsIdentical);
329
330 return kalmanFilter;
331}
Kalman filter matrices for the B-spline Multi-IMU fusion.
Utility class for logging to console and file.
#define LOG_DATA
All output which occurs repeatedly every time observations are received.
Definition Logger.hpp:29
Constructs four overlapping qaudratic B-splines.
Generalized Kalman Filter class.
Eigen::MatrixXd x
x̂ State vector
Eigen::MatrixXd P
𝐏 Error covariance matrix
Eigen::MatrixXd Q
𝐐 System/Process noise covariance matrix
Eigen::MatrixXd Phi
𝚽 State transition matrix
void rotateErrorCovariances(Eigen::MatrixXd &P, uint8_t &numStates, const double &sigmaScalingFactorAngRate=3.0, const double &sigmaScalingFactorAccel=3.0)
Rotates the B-spline coefficient error covariances in P, once a new B-spline is introduced.
Definition BsplineKF.cpp:62
std::array< double, 3 > quadraticBsplines(const double &ti, const double &splineSpacing=1.0)
Set the points/knots of the four B-splines.
void processNoiseMatrix_Q(Eigen::MatrixXd &Q, const double &dt, const std::vector< Eigen::VectorXd > &processNoiseVariances, const uint8_t &numStates, const bool &imuCharacteristicsIdentical=false)
Calculates the process noise matrix Q.
Definition BsplineKF.cpp:38
void rotateCoeffStates(Eigen::MatrixXd &x)
Rotates the B-spline coefficient states in the state vector x, once a new B-spline is introduced.
Definition BsplineKF.cpp:56
KalmanFilter initializeKalmanFilterManually(const size_t &numInputPins, const std::vector< PinData > &pinData, const PinDataBsplineKF &pinDataBsplineKF, const uint8_t &numStates, const double &dtInit, std::vector< Eigen::VectorXd > &processNoiseVariances, KalmanFilter &kalmanFilter, const bool &imuCharacteristicsIdentical, const bool &imuBiasesIdentical)
Initializes the BsplineKF manually (i.e. using GUI inputs instead of averaging)
Eigen::MatrixXd initialErrorCovarianceMatrix_P0(const std::vector< Eigen::VectorXd > &initCovariances, const uint8_t &numStates, const bool &imuCharacteristicsIdentical=false)
Initial error covariance matrix P_0.
Definition BsplineKF.cpp:16
Eigen::MatrixXd designMatrix_H(const double &ti, const double &splineSpacing, const Eigen::Matrix3d &DCM_accel, const Eigen::Matrix3d &DCM_gyro, const size_t &pinIndex, const uint8_t &numMeasurements, const uint8_t &numStates, const uint8_t &numStatesEst, const uint8_t &numStatesPerPin)
Calculates the design matrix H.
Definition BsplineKF.cpp:91
constexpr auto deg2rad(const T &deg)
Convert Degree to Radians.
Definition Units.hpp:21
Sensor information specific to the Bspline-KF.
Definition PinData.hpp:179
Eigen::VectorXd initCovarianceCoeffsAngRate
GUI selection for the initial covariance of the B-spline coefficients of the angular rate.
Definition PinData.hpp:205
PinData::AccelerationUnit initCoeffsAccelUnit
Gui selection for the unit of the initial coefficients of the acceleration B-splines.
Definition PinData.hpp:185
PinData::AccelerationVarianceUnit initCovarianceCoeffsAccelUnit
Gui selection for the unit of the initial covariance for the coefficients of acceleration.
Definition PinData.hpp:190
Eigen::VectorXd initCoeffsAngRate
GUI selection for the initial B-spline coefficients of the angular rate.
Definition PinData.hpp:200
PinData::AngRateVarianceUnit initCovarianceCoeffsAngRateUnit
Gui selection for the unit of the initial covariance for the coefficients of angular rate.
Definition PinData.hpp:188
Eigen::VectorXd varCoeffsAccelNoise
GUI selection for the coeffs of the acceleration process noise (diagonal values)
Definition PinData.hpp:212
Eigen::VectorXd initCoeffsAccel
GUI selection for the initial B-spline coefficients of the acceleration.
Definition PinData.hpp:202
Eigen::VectorXd initCovarianceCoeffsAccel
GUI selection for the initial covariance of the B-spline coefficients of the acceleration.
Definition PinData.hpp:207
Eigen::VectorXd varCoeffsAngRateNoise
GUI selection for the coeffs of the angular rate process noise (diagonal values)
Definition PinData.hpp:210
PinData::AngRateVarianceUnit varCoeffsAngRateUnit
GUI selection for the B-spline coeffs of the angular rate process noise (diagonal values)
Definition PinData.hpp:193
PinData::AccelerationVarianceUnit varCoeffsAccelUnit
GUI selection for the B-spline coeffs of the acceleration process noise (diagonal values)
Definition PinData.hpp:195
PinData::AngRateUnit initCoeffsAngularRateUnit
Gui selection for the unit of the initial coefficients of the angular rate B-splines.
Definition PinData.hpp:183
@ m2_s4
Variance [(m^2)/(s^4), (m^2)/(s^4), (m^2)/(s^4)].
Definition PinData.hpp:50
@ m_s2
Standard deviation [m/s², m/s², m/s²].
Definition PinData.hpp:51
@ rad2_s2
Variance [rad²/s², rad²/s², rad²/s²].
Definition PinData.hpp:41
@ deg2_s2
Variance [deg²/s², deg²/s², deg²/s²].
Definition PinData.hpp:43
@ deg_s
Standard deviation [deg/s, deg/s, deg/s].
Definition PinData.hpp:44
@ rad_s
Standard deviation [rad/s, rad/s, rad/s].
Definition PinData.hpp:42
@ m_s2
in [m/s², m/s², m/s²]
Definition PinData.hpp:35
@ deg_s
in [deg/s, deg/s, deg/s]
Definition PinData.hpp:28
@ rad_s
in [rad/s, rad/s, rad/s]
Definition PinData.hpp:29