0.4.1
Loading...
Searching...
No Matches
IRWKF.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 "IRWKF.hpp"
10
12#include "util/Logger.hpp"
13
14Eigen::MatrixXd NAV::IRWKF::initialStateTransitionMatrix_Phi(const double& dt, const uint8_t& numStates)
15{
16 const auto nStates = static_cast<Eigen::Index>(numStates);
17 Eigen::MatrixXd Phi = Eigen::MatrixXd::Identity(nStates, nStates);
18
19 Phi.block<3, 3>(0, 3).diagonal().setConstant(dt); // dependency of angular rate on angular acceleration
20 Phi.block<3, 3>(6, 9).diagonal().setConstant(dt); // dependency of acceleration on jerk
21
22 return Phi;
23}
24
25Eigen::MatrixXd NAV::IRWKF::initialErrorCovarianceMatrix_P0(const std::vector<Eigen::Vector3d>& initCovariances, const uint8_t& numStates, const bool& imuCharacteristicsIdentical)
26{
27 Eigen::MatrixXd P = Eigen::MatrixXd::Zero(numStates, numStates);
28
29 P.block<3, 3>(0, 0).diagonal() = initCovariances.at(0); // initial covariance of the angular rate
30 P.block<3, 3>(3, 3).diagonal() = initCovariances.at(1); // initial covariance of the angular acceleration
31 P.block<3, 3>(6, 6).diagonal() = initCovariances.at(2); // initial covariance of the acceleration
32 P.block<3, 3>(9, 9).diagonal() = initCovariances.at(3); // initial covariance of the jerk
33
34 size_t j = 4;
35 for (uint32_t i = 12; i < numStates; i += 6)
36 {
37 if (!imuCharacteristicsIdentical)
38 {
39 j = 4 + (i - 12) / 3; // access bias variances for each sensor from the fifth element onwards
40 }
41
42 P.block<3, 3>(i, i).diagonal() = initCovariances.at(j);
43 P.block<3, 3>(i + 3, i + 3).diagonal() = initCovariances.at(j + 1);
44 }
45
46 return P;
47}
48
49void NAV::IRWKF::processNoiseMatrix_Q(Eigen::MatrixXd& Q, const double& dt, const std::vector<Eigen::VectorXd>& processNoiseVariances, const uint8_t& numStates, const bool& imuCharacteristicsIdentical)
50{
51 // Integrated Random Walk of the angular rate
52 Q.block<3, 3>(0, 0).diagonal() = processNoiseVariances.at(0) / 3. * std::pow(dt, 3);
53 Q.block<3, 3>(0, 3).diagonal() = processNoiseVariances.at(0) / 2. * std::pow(dt, 2);
54 Q.block<3, 3>(3, 0).diagonal() = processNoiseVariances.at(0) / 2. * std::pow(dt, 2);
55 Q.block<3, 3>(3, 3).diagonal() = processNoiseVariances.at(0) * dt;
56
57 // Integrated Random Walk of the acceleration
58 Q.block<3, 3>(6, 6).diagonal() = processNoiseVariances.at(1) / 3. * std::pow(dt, 3);
59 Q.block<3, 3>(6, 9).diagonal() = processNoiseVariances.at(1) / 2. * std::pow(dt, 2);
60 Q.block<3, 3>(9, 6).diagonal() = processNoiseVariances.at(1) / 2. * std::pow(dt, 2);
61 Q.block<3, 3>(9, 9).diagonal() = processNoiseVariances.at(1) * dt;
62
63 // Random Walk of the bias states
64 size_t j = 4;
65 for (uint32_t i = 12; i < numStates; i += 6) // FIXME: i = 'numStatesEst' better than '12'? (magic numbers)
66 {
67 if (!imuCharacteristicsIdentical)
68 {
69 j = 2 + (i - 12) / 3; // access 2 bias variances for each sensor from the third element onwards
70 }
71 Q.block<3, 3>(i, i).diagonal() = processNoiseVariances.at(j) * dt; // variance for the process noise of the angular rate
72 Q.block<3, 3>(i + 3, i + 3).diagonal() = processNoiseVariances.at(j + 1) * dt; // variance for the process noise of the acceleration
73 }
74}
75
76void NAV::IRWKF::stateTransitionMatrix_Phi(Eigen::MatrixXd& Phi, const double& dt)
77{
78 Phi.block<3, 3>(0, 3).diagonal().setConstant(dt); // dependency of angular rate on angular acceleration
79 Phi.block<3, 3>(6, 9).diagonal().setConstant(dt); // dependency of acceleration on jerk
80}
81
82Eigen::MatrixXd NAV::IRWKF::designMatrix_H(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)
83{
84 Eigen::MatrixXd H = Eigen::MatrixXd::Zero(numMeasurements, numStates);
85
86 // Mounting angles of sensor with latest measurement
87 H.block<3, 3>(0, 0) = DCM_accel.transpose(); // Inverse rotation for angular rate
88 H.block<3, 3>(3, 6) = DCM_gyro.transpose(); // Inverse rotation for acceleration
89
90 // Mapping of bias states on sensor with the latest measurement
91 if (pinIndex > 0)
92 {
93 const auto stateIndex = static_cast<uint8_t>(numStatesEst + numStatesPerPin * (pinIndex - 1));
94 LOG_DATA("stateIndex = {}", stateIndex);
95
96 H.block<6, 6>(0, stateIndex) = Eigen::MatrixXd::Identity(6, 6);
97 }
98
99 return H;
100}
101
102NAV::KalmanFilter NAV::IRWKF::initializeKalmanFilterManually(const size_t& numInputPins, const std::vector<PinData>& pinData, const PinDataIRWKF& pinDataIRWKF, const uint8_t& numStates, const double& dtInit, std::vector<Eigen::VectorXd>& processNoiseVariances, KalmanFilter& kalmanFilter, const bool& imuCharacteristicsIdentical, const bool& imuBiasesIdentical)
103{
104 // ------------------------------------------ State vector x ---------------------------------------------
105
106 std::vector<Eigen::Vector3d> initStates;
107 initStates.resize(6 + 2 * numInputPins); // FIXME: Shouldn't this be 'numStates'?
108
109 // Initial angular rate in [rad/s]
111 {
112 initStates[0] = deg2rad(pinDataIRWKF.initAngularRate);
113 }
115 {
116 initStates[0] = pinDataIRWKF.initAngularRate;
117 }
118
119 // Initial acceleration in [m/s²]
121 {
122 initStates[1] = pinDataIRWKF.initAcceleration;
123 }
124
125 // Initial angular acceleration in [rad/s²]
127 {
128 initStates[2] = deg2rad(pinDataIRWKF.initAngularAcc);
129 }
131 {
132 initStates[2] = pinDataIRWKF.initAngularAcc;
133 }
134
135 // Initial jerk in [m/s³]
136 if (pinDataIRWKF.initJerkUnit == PinDataIRWKF::JerkUnit::m_s3)
137 {
138 initStates[3] = pinDataIRWKF.initJerk;
139 }
140
141 size_t pinDataBiasesIdenticalIdx = 1;
142 for (size_t pinIndex = 1; pinIndex < numInputPins; ++pinIndex)
143 {
144 if (!imuBiasesIdentical)
145 {
146 pinDataBiasesIdenticalIdx = pinIndex;
147 }
148
149 // Initial bias of the angular rate in [rad/s]
150 if (pinData[pinDataBiasesIdenticalIdx].initAngularRateBiasUnit == PinData::AngRateUnit::rad_s)
151 {
152 initStates[2 + 2 * pinIndex] = pinData[pinDataBiasesIdenticalIdx].initAngularRateBias.array();
153 }
154 else if (pinData[pinDataBiasesIdenticalIdx].initAngularRateBiasUnit == PinData::AngRateUnit::deg_s)
155 {
156 initStates[2 + 2 * pinIndex] = deg2rad(pinData[pinDataBiasesIdenticalIdx].initAngularRateBias).array();
157 }
158
159 // Initial bias of the acceleration in [m/s²]
160 if (pinData[pinDataBiasesIdenticalIdx].initAccelerationBiasUnit == PinData::AccelerationUnit::m_s2)
161 {
162 initStates[3 + 2 * pinIndex] = pinData[pinDataBiasesIdenticalIdx].initAccelerationBias.array();
163 }
164 }
165
166 kalmanFilter.x.block<3, 1>(0, 0) = initStates[0];
167 kalmanFilter.x.block<3, 1>(3, 0) = initStates[1];
168 kalmanFilter.x.block<3, 1>(6, 0) = initStates[2];
169 kalmanFilter.x.block<3, 1>(9, 0) = initStates[3];
170
171 uint32_t containerIndex = 4;
172 for (uint32_t pinIndex = 0; pinIndex < numInputPins - 1UL; ++pinIndex)
173 {
174 if (!imuBiasesIdentical)
175 {
176 containerIndex = 4 + 2 * pinIndex;
177 }
178 kalmanFilter.x.block<3, 1>(12 + 6 * pinIndex, 0) = initStates[containerIndex];
179 kalmanFilter.x.block<3, 1>(15 + 6 * pinIndex, 0) = initStates[1 + containerIndex];
180 }
181
182 // -------------------------------------- State transition matrix ----------------------------------------
183 kalmanFilter.Phi = NAV::IRWKF::initialStateTransitionMatrix_Phi(dtInit, numStates);
184
185 // ------------------------------------- Error covariance matrix P ---------------------------------------
186
187 std::vector<Eigen::Vector3d> initErrorCovariances;
188 initErrorCovariances.resize(6 + 2 * numInputPins);
189
190 // Initial Covariance of the angular rate in [rad²/s²]
191 if (pinData[0].initCovarianceAngularRateUnit == PinData::AngRateVarianceUnit::rad2_s2)
192 {
193 initErrorCovariances[0] = pinData[0].initCovarianceAngularRate;
194 }
195 else if (pinData[0].initCovarianceAngularRateUnit == PinData::AngRateVarianceUnit::deg2_s2)
196 {
197 initErrorCovariances[0] = deg2rad(pinData[0].initCovarianceAngularRate);
198 }
199 else if (pinData[0].initCovarianceAngularRateUnit == PinData::AngRateVarianceUnit::rad_s)
200 {
201 initErrorCovariances[0] = pinData[0].initCovarianceAngularRate.array().pow(2);
202 }
203 else if (pinData[0].initCovarianceAngularRateUnit == PinData::AngRateVarianceUnit::deg_s)
204 {
205 initErrorCovariances[0] = deg2rad(pinData[0].initCovarianceAngularRate).array().pow(2);
206 }
207
208 // Initial Covariance of the angular acceleration in [(rad^2)/(s^4)]
210 {
211 initErrorCovariances[1] = pinDataIRWKF.initCovarianceAngularAcc;
212 }
214 {
215 initErrorCovariances[1] = deg2rad(pinDataIRWKF.initCovarianceAngularAcc);
216 }
218 {
219 initErrorCovariances[1] = pinDataIRWKF.initCovarianceAngularAcc.array().pow(2);
220 }
222 {
223 initErrorCovariances[1] = deg2rad(pinDataIRWKF.initCovarianceAngularAcc).array().pow(2);
224 }
225
226 // Initial Covariance of the acceleration in [(m^2)/(s^4)]
227 if (pinData[0].initCovarianceAccelerationUnit == PinData::AccelerationVarianceUnit::m2_s4)
228 {
229 initErrorCovariances[2] = pinData[0].initCovarianceAcceleration;
230 }
231 else if (pinData[0].initCovarianceAccelerationUnit == PinData::AccelerationVarianceUnit::m_s2)
232 {
233 initErrorCovariances[2] = pinData[0].initCovarianceAcceleration.array().pow(2);
234 }
235
236 // Initial Covariance of the jerk in [(m^2)/(s^6)]
238 {
239 initErrorCovariances[3] = pinDataIRWKF.initCovarianceJerk;
240 }
242 {
243 initErrorCovariances[3] = pinDataIRWKF.initCovarianceJerk.array().pow(2);
244 }
245
246 size_t pinDataIdx = 1;
247 for (size_t pinIndex = 1; pinIndex < numInputPins; ++pinIndex)
248 {
249 if (!imuCharacteristicsIdentical)
250 {
251 pinDataIdx = pinIndex;
252 }
253
254 // Initial Covariance of the bias of the angular rate in [rad²/s²]
255 if (pinData[pinDataIdx].initCovarianceBiasAngRateUnit == PinData::AngRateVarianceUnit::rad2_s2)
256 {
257 initErrorCovariances[2 + 2 * pinIndex] = pinData[pinDataIdx].initCovarianceBiasAngRate;
258 }
259 else if (pinData[pinDataIdx].initCovarianceBiasAngRateUnit == PinData::AngRateVarianceUnit::deg2_s2)
260 {
261 initErrorCovariances[2 + 2 * pinIndex] = deg2rad(pinData[pinDataIdx].initCovarianceBiasAngRate);
262 }
263 else if (pinData[pinDataIdx].initCovarianceBiasAngRateUnit == PinData::AngRateVarianceUnit::rad_s)
264 {
265 initErrorCovariances[2 + 2 * pinIndex] = pinData[pinDataIdx].initCovarianceBiasAngRate.array().pow(2);
266 }
267 else if (pinData[pinDataIdx].initCovarianceBiasAngRateUnit == PinData::AngRateVarianceUnit::deg_s)
268 {
269 initErrorCovariances[2 + 2 * pinIndex] = deg2rad(pinData[pinDataIdx].initCovarianceBiasAngRate).array().pow(2);
270 }
271
272 // Initial Covariance of the bias of the acceleration in [(m^2)/(s^4)]
273 if (pinData[pinDataIdx].initCovarianceBiasAccUnit == PinData::AccelerationVarianceUnit::m2_s4)
274 {
275 initErrorCovariances[3 + 2 * pinIndex] = pinData[pinDataIdx].initCovarianceBiasAcc;
276 }
277 else if (pinData[pinDataIdx].initCovarianceBiasAccUnit == PinData::AccelerationVarianceUnit::m_s2)
278 {
279 initErrorCovariances[3 + 2 * pinIndex] = pinData[pinDataIdx].initCovarianceBiasAcc.array().pow(2);
280 }
281 }
282
283 kalmanFilter.P = NAV::IRWKF::initialErrorCovarianceMatrix_P0(initErrorCovariances, numStates, imuCharacteristicsIdentical);
284
285 // -------------------------------------- Process noise matrix Q -----------------------------------------
286 processNoiseVariances.resize(2 * numInputPins);
287
288 // 𝜎_AngAcc Standard deviation of the noise on the angular acceleration state [rad/s²]
289 switch (pinDataIRWKF.varAngularAccNoiseUnit)
290 {
292 processNoiseVariances[0] = pinDataIRWKF.varAngularAccNoise;
293 break;
295 processNoiseVariances[0] = deg2rad(pinDataIRWKF.varAngularAccNoise);
296 break;
298 processNoiseVariances[0] = deg2rad(pinDataIRWKF.varAngularAccNoise).array().pow(2);
299 break;
301 processNoiseVariances[0] = pinDataIRWKF.varAngularAccNoise.array().pow(2);
302 break;
303 }
304
305 // 𝜎_jerk Standard deviation of the noise on the jerk state [m/s³]
306 switch (pinDataIRWKF.varJerkNoiseUnit)
307 {
309 processNoiseVariances[1] = pinDataIRWKF.varJerkNoise;
310 break;
312 processNoiseVariances[1] = pinDataIRWKF.varJerkNoise.array().pow(2);
313 break;
314 }
315
316 for (size_t pinIndex = 1; pinIndex < numInputPins; ++pinIndex)
317 {
318 if (!imuCharacteristicsIdentical)
319 {
320 pinDataIdx = pinIndex;
321 }
322
323 // 𝜎_biasAngRate Standard deviation of the bias on the angular rate state [rad/s²]
324 switch (pinData[pinDataIdx].varBiasAngRateNoiseUnit)
325 {
327 processNoiseVariances[2 * pinIndex] = pinData[pinDataIdx].varBiasAngRateNoise;
328 break;
330 processNoiseVariances[2 * pinIndex] = deg2rad(pinData[pinDataIdx].varBiasAngRateNoise);
331 break;
333 processNoiseVariances[2 * pinIndex] = deg2rad(pinData[pinDataIdx].varBiasAngRateNoise).array().pow(2);
334 break;
336 processNoiseVariances[2 * pinIndex] = pinData[pinDataIdx].varBiasAngRateNoise.array().pow(2);
337 break;
338 }
339
340 // 𝜎_biasAcceleration Standard deviation of the noise on the acceleration state [m/s³]
341 switch (pinData[pinIndex].varBiasAccelerationNoiseUnit)
342 {
344 processNoiseVariances[1 + 2 * pinIndex] = pinData[pinDataIdx].varBiasAccelerationNoise;
345 break;
347 processNoiseVariances[1 + 2 * pinIndex] = pinData[pinDataIdx].varBiasAccelerationNoise.array().pow(2);
348 break;
349 }
350 }
351
352 NAV::IRWKF::processNoiseMatrix_Q(kalmanFilter.Q, dtInit, processNoiseVariances, numStates, imuCharacteristicsIdentical);
353
354 return kalmanFilter;
355}
356
357NAV::KalmanFilter NAV::IRWKF::initializeKalmanFilterAuto(const size_t& nInputPins, const std::vector<PinData>& pinData, const PinDataIRWKF& pinDataIRWKF, const std::vector<size_t>& cumulatedPinIds, const std::vector<std::shared_ptr<const NAV::ImuObs>>& cumulatedImuObs, const bool& initJerkAngAcc, const double& dtInit, const uint8_t& numStates, const uint8_t& numMeasurements, std::vector<Eigen::VectorXd>& processNoiseVariances, KalmanFilter& kalmanFilter)
358{
359 // ---------------------------- Measurements (for initial state vector x0) -------------------------------
360
361 std::vector<std::vector<std::shared_ptr<const NAV::ImuObs>>> sensorMeasurements; // pinIndex / msgIndex(imuObs)
362 sensorMeasurements.resize(nInputPins);
363
364 std::vector<Eigen::Vector3d> initStates;
365 initStates.resize(6 + 2 * nInputPins); // state vector x
366
367 // Split cumulated imuObs into vectors for each sensor
368 for (size_t msgIndex = 0; msgIndex < cumulatedImuObs.size(); msgIndex++)
369 {
370 sensorMeasurements[cumulatedPinIds[msgIndex]].push_back(cumulatedImuObs[msgIndex]); // 'push_back' instead of 'resize()' and 'operator[]' since number of msgs of a certain pin are not known in advance
371 }
372
373 std::vector<std::vector<std::vector<double>>> sensorComponents; // pinIndex / axisIndex / msgIndex(double)
374 sensorComponents.resize(nInputPins);
375
376 for (size_t pinIndex = 0; pinIndex < nInputPins; pinIndex++) // loop thru connected sensors
377 {
378 sensorComponents[pinIndex].resize(numMeasurements);
379 for (size_t axisIndex = 0; axisIndex < numMeasurements; axisIndex++) // loop thru the 6 measurements: AccX, GyroX, AccY, GyroY, AccZ, GyroZ
380 {
381 for (size_t msgIndex = 0; msgIndex < sensorMeasurements[pinIndex].size(); msgIndex++) // loop thru the msg of each measurement axis
382 {
383 if (axisIndex < 3) // Accelerations X/Y/Z
384 {
385 sensorComponents[pinIndex][axisIndex].push_back(sensorMeasurements[pinIndex][msgIndex]->p_acceleration(static_cast<uint32_t>(axisIndex)));
386 }
387 else // Gyro X/Y/Z
388 {
389 sensorComponents[pinIndex][axisIndex].push_back(sensorMeasurements[pinIndex][msgIndex]->p_angularRate(static_cast<uint32_t>(axisIndex - 3)));
390 }
391 }
392 }
393 }
394
395 // --------------------------- Averaging single measurements of each sensor ------------------------------
396 // Accelerations X/Y/Z (pos. 6,7,8 in state vector) - init value is mean of reference sensor, i.e. pinIndex = 0
397 initStates[2] = mean(sensorComponents[0], 0);
398 // Jerk X/Y/Z
399 initStates[3] = Eigen::Vector3d::Zero();
400 // Angular Rate X/Y/Z (pos. 0,1,2 in state vector) - init value is mean of reference sensor, i.e. pinIndex = 0
401 initStates[0] = mean(sensorComponents[0], 3);
402 // Angular Acceleration X/Y/Z
403 initStates[1] = Eigen::Vector3d::Zero();
404
405 // Bias-inits
406 for (size_t pinIndex = 0; pinIndex < nInputPins - 1; pinIndex++) // nInputPins - 1 since there are only relative biases
407 {
408 auto stateIndex = 4 + 2 * pinIndex; // 4 states are Acceleration, Jerk, Angular Rate, Angular Acceleration (see above), plus 2 bias states per sensor
409 initStates[stateIndex + 1] = mean(sensorComponents[pinIndex + 1], 0) - initStates[2]; // Acceleration biases
410 initStates[stateIndex] = mean(sensorComponents[pinIndex + 1], 3) - initStates[0]; // Angular rate biases
411 }
412
413 // ------------------------------------ State transition matrix Phi --------------------------------------
414
415 kalmanFilter.Phi = IRWKF::initialStateTransitionMatrix_Phi(dtInit, numStates);
416
417 // ----------------------- Variance of each sensor (initial error covariance P0) -------------------------
418
419 std::vector<Eigen::Vector3d> initErrorCovariances;
420 initErrorCovariances.resize(6 + 2 * nInputPins); // error covariance matrix P
421
422 // Acceleration variances X/Y/Z (pos. 6,7,8 on diagonal of P matrix) - init value is variance of reference sensor, i.e. pinIndex = 0
423 initErrorCovariances[2] = variance(sensorComponents[0], 0);
424 // Angular Rate variances X/Y/Z (pos. 0,1,2 on diagonal of P matrix) - init value is variance of reference sensor, i.e. pinIndex = 0
425 initErrorCovariances[0] = variance(sensorComponents[0], 3);
426
427 if (initJerkAngAcc)
428 {
429 // Jerk variances X/Y/Z
430 initErrorCovariances[3] = initErrorCovariances[2];
431 // Angular Acceleration variances X/Y/Z
432 initErrorCovariances[1] = initErrorCovariances[0];
433 }
434 else
435 {
436 // Jerk variances X/Y/Z
437 initErrorCovariances[3] = Eigen::Vector3d::Zero();
438 // Angular Acceleration variances X/Y/Z
439 initErrorCovariances[1] = Eigen::Vector3d::Zero();
440 }
441
442 // P-matrix bias inits
443 for (size_t pinIndex = 0; pinIndex < nInputPins - 1; pinIndex++) // nInputPins - 1 since there are only relative biases
444 {
445 auto stateIndex = 4 + 2 * pinIndex; // 4 states are Acceleration, Jerk, Angular Rate, Angular Acceleration (see above), plus 2 bias states per sensor
446 initErrorCovariances[stateIndex + 1] = variance(sensorComponents[pinIndex + 1], 0); // Acceleration biases
447 initErrorCovariances[stateIndex] = variance(sensorComponents[pinIndex + 1], 3); // Angular rate biases
448
449 // Choose the bigger one of the two variances, i.e. of sensor #'pinIndex' and the reference sensor #0 (since bias is the difference of these two sensors)
450 for (int axisIndex = 0; axisIndex < 3; axisIndex++)
451 {
452 // Acceleration variance
453 initErrorCovariances[stateIndex + 1](axisIndex) = std::max(initErrorCovariances[stateIndex + 1](axisIndex),
454 initErrorCovariances[2](axisIndex));
455 // Angular rate variance
456 initErrorCovariances[stateIndex](axisIndex) = std::max(initErrorCovariances[stateIndex](axisIndex),
457 initErrorCovariances[0](axisIndex));
458 }
459 }
460
461 kalmanFilter.x.block<3, 1>(0, 0) = initStates[0];
462 kalmanFilter.x.block<3, 1>(3, 0) = initStates[1];
463 kalmanFilter.x.block<3, 1>(6, 0) = initStates[2];
464 kalmanFilter.x.block<3, 1>(9, 0) = initStates[3];
465 for (uint32_t pinIndex = 0; pinIndex < nInputPins - 1UL; ++pinIndex)
466 {
467 auto containerIndex = 4 + 2 * pinIndex;
468 kalmanFilter.x.block<3, 1>(12 + 6 * pinIndex, 0) = initStates[containerIndex];
469 kalmanFilter.x.block<3, 1>(15 + 6 * pinIndex, 0) = initStates[1 + containerIndex];
470 }
471
472 kalmanFilter.P = IRWKF::initialErrorCovarianceMatrix_P0(initErrorCovariances, numStates);
473
474 // ------------------------------------------------------- Process noise matrix Q ----------------------------------------------------------
475 processNoiseVariances.resize(2 * nInputPins);
476
477 // 𝜎_AngAcc Standard deviation of the noise on the angular acceleration state [rad/s²]
478 switch (pinDataIRWKF.varAngularAccNoiseUnit)
479 {
481 processNoiseVariances[0] = pinDataIRWKF.varAngularAccNoise;
482 break;
484 processNoiseVariances[0] = deg2rad(pinDataIRWKF.varAngularAccNoise);
485 break;
487 processNoiseVariances[0] = deg2rad(pinDataIRWKF.varAngularAccNoise).array().pow(2);
488 break;
490 processNoiseVariances[0] = pinDataIRWKF.varAngularAccNoise.array().pow(2);
491 break;
492 }
493
494 // 𝜎_jerk Standard deviation of the noise on the jerk state [m/s³]
495 switch (pinDataIRWKF.varJerkNoiseUnit)
496 {
498 processNoiseVariances[1] = pinDataIRWKF.varJerkNoise;
499 break;
501 processNoiseVariances[1] = pinDataIRWKF.varJerkNoise.array().pow(2);
502 break;
503 }
504
505 for (size_t pinIndex = 0; pinIndex < nInputPins - 1; ++pinIndex)
506 {
507 // 𝜎_biasAngRate Standard deviation of the bias on the angular rate state [rad/s²]
508 switch (pinData[1 + pinIndex].varBiasAngRateNoiseUnit)
509 {
511 processNoiseVariances[2 + 2 * pinIndex] = pinData[1 + pinIndex].varBiasAngRateNoise;
512 break;
514 processNoiseVariances[2 + 2 * pinIndex] = deg2rad(pinData[1 + pinIndex].varBiasAngRateNoise);
515 break;
517 processNoiseVariances[2 + 2 * pinIndex] = deg2rad(pinData[1 + pinIndex].varBiasAngRateNoise).array().pow(2);
518 break;
520 processNoiseVariances[2 + 2 * pinIndex] = pinData[1 + pinIndex].varBiasAngRateNoise.array().pow(2);
521 break;
522 }
523
524 // 𝜎_biasAcceleration Standard deviation of the noise on the acceleration state [m/s³]
525 switch (pinData[pinIndex].varBiasAccelerationNoiseUnit)
526 {
528 processNoiseVariances[3 + 2 * pinIndex] = pinData[1 + pinIndex].varBiasAccelerationNoise;
529 break;
531 processNoiseVariances[3 + 2 * pinIndex] = pinData[1 + pinIndex].varBiasAccelerationNoise.array().pow(2);
532 break;
533 }
534 }
535
536 IRWKF::processNoiseMatrix_Q(kalmanFilter.Q, dtInit, processNoiseVariances, numStates);
537
538 return kalmanFilter;
539}
540
541Eigen::Vector3d NAV::IRWKF::mean(const std::vector<std::vector<double>>& sensorType, const size_t& containerPos)
542{
543 Eigen::Vector3d meanVector = Eigen::Vector3d::Zero();
544
545 for (size_t axisIndex = 0; axisIndex < 3; axisIndex++)
546 {
547 meanVector(static_cast<int>(axisIndex)) = std::accumulate(sensorType[axisIndex + containerPos].begin(), // NOLINT(boost-use-ranges,modernize-use-ranges) // There is no ranges::accumulate
548 sensorType[axisIndex + containerPos].end(), 0.)
549 / static_cast<double>(sensorType[axisIndex + containerPos].size());
550 }
551
552 return meanVector;
553}
554
555Eigen::Vector3d NAV::IRWKF::variance(const std::vector<std::vector<double>>& sensorType, const size_t& containerPos)
556{
557 Eigen::Vector3d varianceVector = Eigen::Vector3d::Zero();
558
559 auto means = mean(sensorType, containerPos); // mean values for each axis
560
561 for (size_t axisIndex = 0; axisIndex < 3; axisIndex++)
562 {
563 auto N = sensorType.at(axisIndex + containerPos).size(); // Number of msgs along the specific axis
564
565 std::vector<double> absolSquared(N, 0.); // Inner part of the variance calculation (squared absolute values)
566
567 for (size_t msgIndex = 0; msgIndex < N; msgIndex++)
568 {
569 absolSquared[msgIndex] = std::pow(std::abs(sensorType[axisIndex + containerPos][msgIndex] - means(static_cast<int>(axisIndex))), 2);
570 }
571
572 varianceVector(static_cast<int>(axisIndex)) = (1. / (static_cast<double>(N) - 1.)) * std::accumulate(absolSquared.begin(), absolSquared.end(), 0.); // NOLINT(boost-use-ranges,modernize-use-ranges) // There is no ranges::accumulate
573 }
574
575 return varianceVector;
576}
Kalman filter matrices for the Integrated-Random-Walk (IRW) 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
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 stateTransitionMatrix_Phi(Eigen::MatrixXd &Phi, const double &dt)
Calculates the state-transition-matrix 𝚽
Definition IRWKF.cpp:76
Eigen::MatrixXd initialStateTransitionMatrix_Phi(const double &dt, const uint8_t &numStates)
Calculates the state-transition-matrix 𝚽
Definition IRWKF.cpp:14
Eigen::MatrixXd designMatrix_H(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 IRWKF.cpp:82
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 IRWKF.cpp:49
Eigen::Vector3d mean(const std::vector< std::vector< double > > &sensorType, const size_t &containerPos)
Calculates the mean values of each axis in a vector that contains 3d measurements of a certain sensor...
Definition IRWKF.cpp:541
KalmanFilter initializeKalmanFilterManually(const size_t &numInputPins, const std::vector< PinData > &pinData, const PinDataIRWKF &pinDataIRWKF, const uint8_t &numStates, const double &dtInit, std::vector< Eigen::VectorXd > &processNoiseVariances, KalmanFilter &kalmanFilter, const bool &imuCharacteristicsIdentical, const bool &imuBiasesIdentical)
Initializes the IRWKF manually (i.e. using GUI inputs instead of averaging)
Definition IRWKF.cpp:102
Eigen::Vector3d variance(const std::vector< std::vector< double > > &sensorType, const size_t &containerPos)
Calculates the variance of each axis in a vector that contains 3d measurements of a certain sensor ty...
Definition IRWKF.cpp:555
Eigen::MatrixXd initialErrorCovarianceMatrix_P0(const std::vector< Eigen::Vector3d > &initCovariances, const uint8_t &numStates, const bool &imuCharacteristicsIdentical=false)
Initial error covariance matrix P_0.
Definition IRWKF.cpp:25
KalmanFilter initializeKalmanFilterAuto(const size_t &nInputPins, const std::vector< PinData > &pinData, const PinDataIRWKF &pinDataIRWKF, const std::vector< size_t > &cumulatedPinIds, const std::vector< std::shared_ptr< const NAV::ImuObs > > &cumulatedImuObs, const bool &initJerkAngAcc, const double &dtInit, const uint8_t &numStates, const uint8_t &numMeasurements, std::vector< Eigen::VectorXd > &processNoiseVariances, KalmanFilter &kalmanFilter)
Initializes the IRWKF automatically, i.e. init values are calculated by averaging the data in the fir...
Definition IRWKF.cpp:357
constexpr auto deg2rad(const T &deg)
Convert Degree to Radians.
Definition Units.hpp:21
Sensor information specific to the IRW-KF.
Definition PinData.hpp:105
JerkVarianceUnit initCovarianceJerkUnit
Gui selection for the unit of the initial covariance for the jerk.
Definition PinData.hpp:148
PinData::AccelerationUnit initAccelerationUnit
Gui selection for the unit of the initial acceleration.
Definition PinData.hpp:141
Eigen::Vector3d initAcceleration
GUI selection for the initial acceleration.
Definition PinData.hpp:162
AngularAccUnit initAngularAccUnit
Gui selection for the unit of the initial angular acceleration.
Definition PinData.hpp:139
Eigen::Vector3d initCovarianceAngularAcc
GUI selection for the initial covariance diagonal values for angular acceleration (standard deviation...
Definition PinData.hpp:167
Eigen::Vector3d initAngularRate
GUI selection for the initial angular rate.
Definition PinData.hpp:158
Eigen::Vector3d initCovarianceJerk
GUI selection for the initial covariance diagonal values for jerk (standard deviation σ or Variance σ...
Definition PinData.hpp:169
Eigen::Vector3d varJerkNoise
GUI selection for the jerk process noise diagonal values.
Definition PinData.hpp:174
AngularAccVarianceUnit varAngularAccNoiseUnit
Gui selection for the unit of the angular acceleration process noise.
Definition PinData.hpp:151
Eigen::Vector3d initJerk
GUI selection for the initial jerk.
Definition PinData.hpp:164
Eigen::Vector3d varAngularAccNoise
GUI selection for the angular acceleration process noise diagonal values.
Definition PinData.hpp:172
@ m2_s6
Variance [(m^2)/(s^6), (m^2)/(s^6), (m^2)/(s^6)].
Definition PinData.hpp:130
@ m_s3
Standard deviation [m/s³, m/s³, m/s³].
Definition PinData.hpp:131
@ m_s3
in [m/s³, m/s³, m/s³]
Definition PinData.hpp:116
AngularAccVarianceUnit initCovarianceAngularAccUnit
Gui selection for the unit of the initial covariance for the angular acceleration.
Definition PinData.hpp:146
PinData::AngRateUnit initAngularRateUnit
Gui selection for the unit of the initial angular rate.
Definition PinData.hpp:137
Eigen::Vector3d initAngularAcc
GUI selection for the initial angular acceleration.
Definition PinData.hpp:160
JerkVarianceUnit varJerkNoiseUnit
Gui selection for the unit of the jerk process noise.
Definition PinData.hpp:153
@ deg_s2
in [deg/s², deg/s², deg/s²]
Definition PinData.hpp:110
@ rad_s2
in [rad/s², rad/s², rad/s²]
Definition PinData.hpp:111
JerkUnit initJerkUnit
Gui selection for the Unit of the initial jerk.
Definition PinData.hpp:143
@ deg_s2
Standard deviation [deg/s², deg/s², deg/s²].
Definition PinData.hpp:125
@ deg2_s4
Variance [(deg^2)/(s^4), (deg^2)/(s^4), (deg^2)/(s^4)].
Definition PinData.hpp:124
@ rad2_s4
Variance [(rad^2)/(s^4), (rad^2)/(s^4), (rad^2)/(s^4)].
Definition PinData.hpp:122
@ rad_s2
Standard deviation [rad/s², rad/s², rad/s²].
Definition PinData.hpp:123
@ 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