0.4.1
Loading...
Searching...
No Matches
TightlyCoupledKF.hpp
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/// @file TightlyCoupledKF.hpp
10/// @brief Kalman Filter class for the tightly coupled INS/GNSS integration
11/// @author M. Maier (marcel.maier@ins.uni-stuttgart.de)
12/// @date 2023-01-18
13
14#pragma once
15
16/*
17
18#include "Navigation/GNSS/Core/SatelliteSystem.hpp"
19#include "internal/Node/Node.hpp"
20#include "Navigation/GNSS/Core/Frequency.hpp"
21#include "Navigation/GNSS/Core/Code.hpp"
22#include "Navigation/Time/InsTime.hpp"
23#include "NodeData/State/PosVelAtt.hpp"
24#include "NodeData/GNSS/GnssObs.hpp"
25#include "Navigation/INS/InertialIntegrator.hpp"
26#include "Navigation/GNSS/Positioning/ReceiverClock.hpp"
27#include "Navigation/Atmosphere/Ionosphere/Ionosphere.hpp"
28#include "Navigation/Atmosphere/Troposphere/Troposphere.hpp"
29#include "Navigation/GNSS/Positioning/SPP/Algorithm.hpp"
30#include "NodeData/State/InsGnssTCKFSolution.hpp"
31#include "NodeData/IMU/ImuObs.hpp"
32
33#include "Navigation/Math/KalmanFilter.hpp"
34#include "Navigation/Transformations/Units.hpp"
35
36namespace NAV
37{
38/// @brief Tightly-coupled Kalman Filter for INS/GNSS integration
39class TightlyCoupledKF : public Node
40{
41 public:
42 /// @brief Default constructor
43 TightlyCoupledKF();
44 /// @brief Destructor
45 ~TightlyCoupledKF() override;
46 /// @brief Copy constructor
47 TightlyCoupledKF(const TightlyCoupledKF&) = delete;
48 /// @brief Move constructor
49 TightlyCoupledKF(TightlyCoupledKF&&) = delete;
50 /// @brief Copy assignment operator
51 TightlyCoupledKF& operator=(const TightlyCoupledKF&) = delete;
52 /// @brief Move assignment operator
53 TightlyCoupledKF& operator=(TightlyCoupledKF&&) = delete;
54 /// @brief String representation of the class type
55 [[nodiscard]] static std::string typeStatic();
56 /// @brief String representation of the class type
57 [[nodiscard]] std::string type() const override;
58 /// @brief String representation of the class category
59 [[nodiscard]] static std::string category();
60
61 /// @brief ImGui config window which is shown on double click
62 /// @attention Don't forget to set _hasConfig to true in the constructor of the node
63 void guiConfig() override;
64
65 /// @brief Saves the node into a json object
66 [[nodiscard]] json save() const override;
67
68 /// @brief Restores the node from a json object
69 /// @param j Json object with the node state
70 void restore(const json& j) override;
71
72 private:
73 constexpr static size_t INPUT_PORT_INDEX_IMU = 0; ///< @brief Flow (ImuObs)
74 constexpr static size_t INPUT_PORT_INDEX_GNSS_OBS = 1; ///< @brief Flow (GnssObs)
75 constexpr static size_t INPUT_PORT_INDEX_POS_VEL_ATT_INIT = 2; ///< @brief Flow (PosVelAtt)
76 constexpr static size_t INPUT_PORT_INDEX_GNSS_NAV_INFO = 2; ///< @brief GnssNavInfo
77 constexpr static size_t OUTPUT_PORT_INDEX_SOLUTION = 0; ///< @brief Flow (InsGnssTCKFSolution)
78 constexpr static size_t OUTPUT_PORT_INDEX_x = 1; ///< @brief x̂ State vector
79 constexpr static size_t OUTPUT_PORT_INDEX_P = 2; ///< @brief 𝐏 Error covariance matrix
80 constexpr static size_t OUTPUT_PORT_INDEX_Phi = 3; ///< @brief 𝚽 State transition matrix
81 constexpr static size_t OUTPUT_PORT_INDEX_Q = 4; ///< @brief 𝐐 System/Process noise covariance matrix
82 constexpr static size_t OUTPUT_PORT_INDEX_z = 5; ///< @brief 𝐳 Measurement vector
83 constexpr static size_t OUTPUT_PORT_INDEX_H = 6; ///< @brief 𝐇 Measurement sensitivity Matrix
84 constexpr static size_t OUTPUT_PORT_INDEX_R = 7; ///< @brief 𝐑 = 𝐸{𝐰ₘ𝐰ₘᵀ} Measurement noise covariance matrix
85 constexpr static size_t OUTPUT_PORT_INDEX_K = 8; ///< @brief 𝐊 Kalman gain matrix
86
87 /// @brief Initialize the node
88 bool initialize() override;
89
90 /// @brief Deinitialize the node
91 void deinitialize() override;
92
93 /// @brief Invoke the callback with a PosVelAtt solution (without TCKF specific output)
94 /// @param[in] posVelAtt PosVelAtt solution
95 void invokeCallbackWithPosVelAtt(const PosVelAtt& posVelAtt);
96
97 /// @brief Receive Function for the IMU observation
98 /// @param[in] queue Queue with all the received data messages
99 /// @param[in] pinIdx Index of the pin the data is received on
100 void recvImuObservation(InputPin::NodeDataQueue& queue, size_t pinIdx);
101
102 /// @brief Receive Function for the Gnss observations
103 /// @param[in] queue Queue with all the received data messages
104 /// @param[in] pinIdx Index of the pin the data is received on
105 void recvGnssObs(InputPin::NodeDataQueue& queue, size_t pinIdx);
106
107 /// @brief Receive Function for the PosVelAtt observation
108 /// @param[in] queue Queue with all the received data messages
109 /// @param[in] pinIdx Index of the pin the data is received on
110 void recvPosVelAttInit(InputPin::NodeDataQueue& queue, size_t pinIdx);
111
112 /// @brief Predicts the state from the InertialNavSol
113 /// @param[in] inertialNavSol Inertial navigation solution triggering the prediction
114 /// @param[in] tau_i Time since the last prediction in [s]
115 /// @param[in] imuPos IMU platform frame position with respect to body frame
116 void tightlyCoupledPrediction(const std::shared_ptr<const PosVelAtt>& inertialNavSol, double tau_i, const ImuPos& imuPos);
117
118 /// @brief Updates the predicted state from the InertialNavSol with the GNSS observation
119 /// @param[in] gnssObservation Gnss observation triggering the update
120 void tightlyCoupledUpdate(const std::shared_ptr<const GnssObs>& gnssObservation);
121
122 /// @brief Add the output pins for the Kalman matrices
123 void addKalmanMatricesPins();
124
125 /// @brief Removes the output pins for the Kalman matrices
126 void removeKalmanMatricesPins();
127
128 /// Add or remove the external PVA Init pin
129 void updateExternalPvaInitPin();
130
131 /// Index of the Pin currently being dragged
132 int _dragAndDropPinIndex = -1;
133 /// Number of NavInfo input pins
134 size_t _nNavInfoPins = 1;
135 /// @brief Adds/Deletes Input Pins depending on the variable _nNavInfoPins
136 void updateNumberOfInputPins();
137
138 /// @brief Inertial Integrator
139 InertialIntegrator _inertialIntegrator;
140 /// Prefer the raw acceleration measurements over the deltaVel & deltaTheta values
141 bool _preferAccelerationOverDeltaMeasurements = false;
142
143 /// Last received IMU observation (to get ImuPos)
144 std::shared_ptr<const ImuObs> _lastImuObs = nullptr;
145
146 /// Roll, Pitch and Yaw angles in [deg] used for initialization if not taken from separate pin
147 std::array<double, 3> _initalRollPitchYaw{};
148 /// Whether to initialize the state over an external pin
149 bool _initializeStateOverExternalPin{};
150 /// Time from the external init
151 InsTime _externalInitTime;
152
153 /// Estimated receiver clock parameters
154 ReceiverClock _recvClk{ std::vector<SatelliteSystem>{ GPS } };
155
156 /// Frequencies used for calculation (GUI filter)
157 Frequency _filterFreq = G01;
158 /// Codes used for calculation (GUI filter)
159 Code _filterCode = Code_Default;
160 /// List of satellites to exclude
161 std::vector<SatId> _excludedSatellites;
162 /// Elevation cut-off angle for satellites in [rad]
163 double _elevationMask = static_cast<double>(15.0_deg);
164
165 /// Ionosphere Model used for the calculation
166 IonosphereModel _ionosphereModel = IonosphereModel::Klobuchar;
167
168 /// Troposphere Models used for the calculation
169 TroposphereModelSelection _troposphereModels;
170
171 /// @brief All Inter-system clock error keys
172 std::vector<SPP::States::StateKeyType> _interSysErrs;
173 /// @brief All Inter-system clock drift keys
174 /// @note Groves2013 does not estimate inter-system drifts, but we do for all models.
175 std::vector<SPP::States::StateKeyType> _interSysDrifts;
176
177 /// Time of last epoch
178 InsTime _lastEpochTime; // TODO: Remove?
179
180 /// Kalman Filter representation - States: 3xAtt, 3xVel, 3xPos, 3xAccelBias, 3xGyroBias, receiver clock offset, receiver clock drift - Measurements: (4+n) x psr, (4+n) x psrRate (from Doppler)
181 KalmanFilter _kalmanFilter{ 17, 8 };
182
183 // ###########################################################################################################
184 // GUI Settings
185 // ###########################################################################################################
186
187 /// @brief Show output pins for the Kalman matrices
188 bool _showKalmanFilterOutputPins = false;
189
190 /// @brief Check the rank of the Kalman matrices every iteration (computational expensive)
191 bool _checkKalmanMatricesRanks = true;
192
193 // ###########################################################################################################
194 // Parameters
195 // ###########################################################################################################
196
197 /// Lever arm between INS and GNSS in [m, m, m]
198 Eigen::Vector3d _b_leverArm_InsGnss{ 0.0, 0.0, 0.0 };
199
200 // ###########################################################################################################
201
202 /// Possible Units for the Standard deviation of the noise on the accelerometer specific-force measurements
203 enum class StdevAccelNoiseUnits : uint8_t
204 {
205 mg_sqrtHz, ///< [mg / √(Hz)]
206 m_s2_sqrtHz, ///< [m / s^2 / √(Hz)]
207 };
208 /// Gui selection for the Unit of the input stdev_ra parameter
209 StdevAccelNoiseUnits _stdevAccelNoiseUnits = StdevAccelNoiseUnits::mg_sqrtHz;
210
211 /// @brief 𝜎_ra Standard deviation of the noise on the accelerometer specific-force measurements
212 /// @note Value from VN-310 Datasheet but verify with values from Brown (2012) table 9.3 for 'High quality'
213 Eigen::Vector3d _stdev_ra = 0.04 * Eigen::Vector3d::Ones(); // [mg/√(Hz)]
214
215 // ###########################################################################################################
216
217 /// Possible Units for the Standard deviation of the noise on the gyro angular-rate measurements
218 enum class StdevGyroNoiseUnits : uint8_t
219 {
220 deg_hr_sqrtHz, ///< [deg / hr /√(Hz)]
221 rad_s_sqrtHz, ///< [rad / s /√(Hz)]
222 };
223 /// Gui selection for the Unit of the input stdev_rg parameter
224 StdevGyroNoiseUnits _stdevGyroNoiseUnits = StdevGyroNoiseUnits::deg_hr_sqrtHz;
225
226 /// @brief 𝜎_rg Standard deviation of the noise on the gyro angular-rate measurements
227 /// @note Value from VN-310 Datasheet but verify with values from Brown (2012) table 9.3 for 'High quality'
228 Eigen::Vector3d _stdev_rg = 5 * Eigen::Vector3d::Ones(); // [deg/hr/√(Hz)]^2
229
230 // ###########################################################################################################
231
232 /// Possible Units for the Variance of the accelerometer dynamic bias
233 enum class StdevAccelBiasUnits : uint8_t
234 {
235 microg, ///< [µg]
236 m_s2, ///< [m / s^2]
237 };
238 /// Gui selection for the Unit of the input variance_bad parameter
239 StdevAccelBiasUnits _stdevAccelBiasUnits = StdevAccelBiasUnits::microg;
240
241 /// @brief 𝜎²_bad Variance of the accelerometer dynamic bias
242 /// @note Value from VN-310 Datasheet (In-Run Bias Stability (Allan Variance))
243 Eigen::Vector3d _stdev_bad = 10 * Eigen::Vector3d::Ones(); // [µg]
244
245 /// @brief Correlation length of the accelerometer dynamic bias in [s]
246 Eigen::Vector3d _tau_bad = 0.1 * Eigen::Vector3d::Ones();
247
248 // ###########################################################################################################
249
250 /// Possible Units for the Variance of the accelerometer dynamic bias
251 enum class StdevGyroBiasUnits : uint8_t
252 {
253 deg_h, ///< [°/h]
254 rad_s, ///< [1/s]
255 };
256 /// Gui selection for the Unit of the input variance_bad parameter
257 StdevGyroBiasUnits _stdevGyroBiasUnits = StdevGyroBiasUnits::deg_h;
258
259 /// @brief 𝜎²_bgd Variance of the gyro dynamic bias
260 /// @note Value from VN-310 Datasheet (In-Run Bias Stability (Allan Variance))
261 Eigen::Vector3d _stdev_bgd = 1 * Eigen::Vector3d::Ones(); // [°/h]
262
263 /// @brief Correlation length of the gyro dynamic bias in [s]
264 Eigen::Vector3d _tau_bgd = 0.1 * Eigen::Vector3d::Ones();
265
266 // ###########################################################################################################
267
268 /// Possible Units for the Standard deviation of the receiver clock phase drift
269 enum class StdevClockPhaseUnits : uint8_t
270 {
271 m_sqrtHz, ///< [m / √(Hz)]
272 };
273 /// Gui selection for the Unit of the input stdev_cp parameter
274 StdevClockPhaseUnits _stdevClockPhaseUnits = StdevClockPhaseUnits::m_sqrtHz;
275
276 /// @brief 𝜎_cf Standard deviation of the receiver clock phase drift
277 /// @note See Groves (2013) eq. (9.153)
278 double _stdev_cp = 0; // [m / √(Hz)]
279
280 // ###########################################################################################################
281
282 /// Possible Units for the Standard deviation of the receiver clock frequency drift
283 enum class StdevClockFreqUnits : uint8_t
284 {
285 m_s_sqrtHz, ///< [m / s / √(Hz)]
286 };
287 /// Gui selection for the Unit of the input stdev_cf parameter
288 StdevClockFreqUnits _stdevClockFreqUnits = StdevClockFreqUnits::m_s_sqrtHz;
289
290 /// @brief 𝜎_cf Standard deviation of the receiver clock frequency drift
291 /// @note See Brown (2012) table 9.2
292 double _stdev_cf = 5; // [m / s / √(Hz)]
293
294 // ###########################################################################################################
295
296 // TODO: Replace with GNSS Measurement Error Model (see SPP node)
297 // /// Possible Units for the Standard deviation of the pseudorange measurement
298 // enum class GnssMeasurementUncertaintyPseudorangeUnit : uint8_t
299 // {
300 // meter2, ///< Variance [m²]
301 // meter, ///< Standard deviation [m]
302 // };
303 // /// Gui selection for the Unit of the input gnssMeasurementUncertaintyPseudorangeUnit parameter
304 // GnssMeasurementUncertaintyPseudorangeUnit _gnssMeasurementUncertaintyPseudorangeUnit = GnssMeasurementUncertaintyPseudorangeUnit::meter;
305
306 // /// @brief GUI selection of the GNSS pseudorange measurement uncertainty (standard deviation σ or Variance σ²).
307 // double _gnssMeasurementUncertaintyPseudorange = 5; // [m]
308
309 // // ###########################################################################################################
310
311 // /// Possible Units for the Standard deviation of the pseudorange-rate measurement
312 // enum class GnssMeasurementUncertaintyPseudorangeRateUnit : uint8_t
313 // {
314 // m2_s2, ///< Variance [m²/s²]
315 // m_s, ///< Standard deviation [m/s]
316 // };
317 // /// Gui selection for the Unit of the input gnssMeasurementUncertaintyPseudorangeRateUnit parameter
318 // GnssMeasurementUncertaintyPseudorangeRateUnit _gnssMeasurementUncertaintyPseudorangeRateUnit = GnssMeasurementUncertaintyPseudorangeRateUnit::m_s;
319
320 // /// @brief GUI selection of the GNSS pseudorange-rate measurement uncertainty (standard deviation σ or Variance σ²).
321 // double _gnssMeasurementUncertaintyPseudorangeRate = 5; // [m/s]
322
323 // ###########################################################################################################
324
325 /// @brief Available Random processes
326 enum class RandomProcess : uint8_t
327 {
328 // WhiteNoise, ///< White noise
329 // RandomConstant, ///< Random constant
330
331 RandomWalk, ///< Random Walk
332 GaussMarkov1, ///< Gauss-Markov 1st Order
333
334 // GaussMarkov2, ///< Gauss-Markov 2nd Order
335 // GaussMarkov3, ///< Gauss-Markov 3rd Order
336 };
337
338 /// @brief Random Process used to estimate the accelerometer biases
339 RandomProcess _randomProcessAccel = RandomProcess::RandomWalk;
340 /// @brief Random Process used to estimate the gyroscope biases
341 RandomProcess _randomProcessGyro = RandomProcess::RandomWalk;
342
343 // ###########################################################################################################
344
345 /// Possible Units for the initial covariance for the receiver clock phase drift (standard deviation σ or Variance σ²)
346 enum class InitCovarianceClockPhaseUnit : uint8_t
347 {
348 m2, ///< Variance [m²]
349 s2, ///< Variance [s²]
350 m, ///< Standard deviation [m]
351 s ///< Standard deviation [s]
352 };
353 /// Gui selection for the Unit of the initial covariance of the receiver clock phase drift
354 InitCovarianceClockPhaseUnit _initCovariancePhaseUnit = InitCovarianceClockPhaseUnit::m;
355
356 /// GUI selection of the initial covariance of the receiver clock phase drift (standard deviation σ or Variance σ²)
357 double _initCovariancePhase{ 5 };
358
359 // ###########################################################################################################
360
361 /// Possible Units for the initial covariance for the receiver clock frequency drift (standard deviation σ or Variance σ²)
362 enum class InitCovarianceClockFreqUnit : uint8_t
363 {
364 m2_s2, ///< Variance [m²/s²]
365 m_s, ///< Standard deviation [m/s]
366 };
367 /// Gui selection for the Unit of the initial covariance of the receiver clock frequency drift
368 InitCovarianceClockFreqUnit _initCovarianceFreqUnit = InitCovarianceClockFreqUnit::m_s;
369
370 /// GUI selection of the initial covariance of the receiver clock frequency drift (standard deviation σ or Variance σ²)
371 double _initCovarianceFreq{ 5 };
372
373 // ###########################################################################################################
374
375 /// Possible Units for the initial covariance for the position (standard deviation σ or Variance σ²)
376 enum class InitCovariancePositionUnit : uint8_t
377 {
378 rad2_rad2_m2, ///< Variance LatLonAlt^2 [rad^2, rad^2, m^2]
379 rad_rad_m, ///< Standard deviation LatLonAlt [rad, rad, m]
380 meter2, ///< Variance NED [m^2, m^2, m^2]
381 meter, ///< Standard deviation NED [m, m, m]
382 };
383 /// Gui selection for the Unit of the initial covariance for the position
384 InitCovariancePositionUnit _initCovariancePositionUnit = InitCovariancePositionUnit::meter;
385
386 /// GUI selection of the initial covariance diagonal values for position (standard deviation σ or Variance σ²)
387 Eigen::Vector3d _initCovariancePosition{ 100, 100, 100 };
388
389 // ###########################################################################################################
390
391 /// Possible Units for the initial covariance for the velocity (standard deviation σ or Variance σ²)
392 enum class InitCovarianceVelocityUnit : uint8_t
393 {
394 m2_s2, ///< Variance [m^2/s^2]
395 m_s, ///< Standard deviation [m/s]
396 };
397 /// Gui selection for the Unit of the initial covariance for the velocity
398 InitCovarianceVelocityUnit _initCovarianceVelocityUnit = InitCovarianceVelocityUnit::m_s;
399
400 /// GUI selection of the initial covariance diagonal values for velocity (standard deviation σ or Variance σ²)
401 Eigen::Vector3d _initCovarianceVelocity{ 10, 10, 10 };
402
403 // ###########################################################################################################
404
405 /// Possible Units for the initial covariance for the attitude angles (standard deviation σ or Variance σ²)
406 enum class InitCovarianceAttitudeAnglesUnit : uint8_t
407 {
408 rad2, ///< Variance [rad^2]
409 deg2, ///< Variance [deg^2]
410 rad, ///< Standard deviation [rad]
411 deg, ///< Standard deviation [deg]
412 };
413 /// Gui selection for the Unit of the initial covariance for the attitude angles
414 InitCovarianceAttitudeAnglesUnit _initCovarianceAttitudeAnglesUnit = InitCovarianceAttitudeAnglesUnit::deg;
415
416 /// GUI selection of the initial covariance diagonal values for attitude angles (standard deviation σ or Variance σ²)
417 Eigen::Vector3d _initCovarianceAttitudeAngles{ 10, 10, 10 };
418
419 // ###########################################################################################################
420
421 /// Possible Units for the initial covariance for the accelerometer biases (standard deviation σ or Variance σ²)
422 enum class InitCovarianceBiasAccelUnit : uint8_t
423 {
424 m2_s4, ///< Variance [m^2/s^4]
425 m_s2, ///< Standard deviation [m/s^2]
426 };
427 /// Gui selection for the Unit of the initial covariance for the accelerometer biases
428 InitCovarianceBiasAccelUnit _initCovarianceBiasAccelUnit = InitCovarianceBiasAccelUnit::m_s2;
429
430 /// GUI selection of the initial covariance diagonal values for accelerometer biases (standard deviation σ or Variance σ²)
431 Eigen::Vector3d _initCovarianceBiasAccel{ 1, 1, 1 };
432
433 // ###########################################################################################################
434
435 /// Possible Units for the initial covariance for the gyroscope biases (standard deviation σ or Variance σ²)
436 enum class InitCovarianceBiasGyroUnit : uint8_t
437 {
438 rad2_s2, ///< Variance [rad²/s²]
439 deg2_s2, ///< Variance [deg²/s²]
440 rad_s, ///< Standard deviation [rad/s]
441 deg_s, ///< Standard deviation [deg/s]
442 };
443 /// Gui selection for the Unit of the initial covariance for the gyroscope biases
444 InitCovarianceBiasGyroUnit _initCovarianceBiasGyroUnit = InitCovarianceBiasGyroUnit::deg_s;
445
446 /// GUI selection of the initial covariance diagonal values for gyroscope biases (standard deviation σ or Variance σ²)
447 Eigen::Vector3d _initCovarianceBiasGyro{ 0.5, 0.5, 0.5 };
448
449 // ###########################################################################################################
450
451 /// GUI option for the Phi calculation algorithm
452 enum class PhiCalculationAlgorithm : uint8_t
453 {
454 Exponential, ///< Van-Loan
455 Taylor, ///< Taylor
456 };
457 /// GUI option for the Phi calculation algorithm
458 PhiCalculationAlgorithm _phiCalculationAlgorithm = PhiCalculationAlgorithm::Taylor;
459
460 /// GUI option for the order of the Taylor polynom to calculate the Phi matrix
461 int _phiCalculationTaylorOrder = 2;
462
463 /// GUI option for the Q calculation algorithm
464 enum class QCalculationAlgorithm : uint8_t
465 {
466 VanLoan, ///< Van-Loan
467 Taylor1, ///< Taylor
468 };
469 /// GUI option for the Q calculation algorithm
470 QCalculationAlgorithm _qCalculationAlgorithm = QCalculationAlgorithm::Taylor1;
471
472 // ###########################################################################################################
473
474 /// Possible Units for the initial accelerometer biases
475 enum class InitBiasAccelUnit : uint8_t
476 {
477 m_s2, ///< acceleration [m/s^2]
478 };
479 /// Gui selection for the unit of the initial accelerometer biases
480 InitBiasAccelUnit _initBiasAccelUnit = InitBiasAccelUnit::m_s2;
481
482 /// GUI selection of the initial accelerometer biases
483 Eigen::Vector3d _initBiasAccel{ 0.0, 0.0, 0.0 };
484
485 // ###########################################################################################################
486
487 /// Possible Units for the initial gyroscope biases
488 enum class InitBiasGyroUnit : uint8_t
489 {
490 rad_s, ///< angular rate [rad/s]
491 deg_s, ///< angular rate [deg/s]
492 };
493 /// Gui selection for the unit of the initial gyroscope biases
494 InitBiasGyroUnit _initBiasGyroUnit = InitBiasGyroUnit::deg_s;
495
496 /// GUI selection of the initial gyroscope biases
497 Eigen::Vector3d _initBiasGyro{ 0.0, 0.0, 0.0 };
498
499 // ###########################################################################################################
500 // Prediction
501 // ###########################################################################################################
502
503 // ------------------------------------------- System matrix 𝐅 ----------------------------------------------
504
505 /// @brief Calculates the system matrix 𝐅 for the local navigation frame
506 /// @param[in] n_Quat_b Attitude of the body with respect to n-system
507 /// @param[in] b_specForce_ib Specific force of the body with respect to inertial frame in [m / s^2], resolved in body coordinates
508 /// @param[in] n_omega_in Angular rate of navigation system with respect to the inertial system [rad / s], resolved in navigation coordinates.
509 /// @param[in] n_velocity Velocity in n-system in [m / s]
510 /// @param[in] lla_position Position as Lat Lon Alt in [rad rad m]
511 /// @param[in] R_N Meridian radius of curvature in [m]
512 /// @param[in] R_E Prime vertical radius of curvature (East/West) [m]
513 /// @param[in] g_0 Magnitude of the gravity vector in [m/s^2] (see \cite Groves2013 Groves, ch. 2.4.7, eq. 2.135, p. 70)
514 /// @param[in] r_eS_e Geocentric radius. The distance of a point on the Earth's surface from the center of the Earth in [m]
515 /// @param[in] tau_bad Correleation length for the accelerometer in [s]
516 /// @param[in] tau_bgd Correleation length for the gyroscope in [s]
517 /// @note See Groves (2013) chapter 14.2.4, equation (14.63) and chapter 9.4.2, equation (9.149)
518 [[nodiscard]] Eigen::Matrix<double, 17, 17> n_systemMatrix_F(const Eigen::Quaterniond& n_Quat_b,
519 const Eigen::Vector3d& b_specForce_ib,
520 const Eigen::Vector3d& n_omega_in,
521 const Eigen::Vector3d& n_velocity,
522 const Eigen::Vector3d& lla_position,
523 double R_N,
524 double R_E,
525 double g_0,
526 double r_eS_e,
527 const Eigen::Vector3d& tau_bad,
528 const Eigen::Vector3d& tau_bgd) const;
529
530 /// @brief Calculates the system matrix 𝐅 for the ECEF frame
531 /// @param[in] e_Quat_b Attitude of the body with respect to e-system
532 /// @param[in] b_specForce_ib Specific force of the body with respect to inertial frame in [m / s^2], resolved in body coordinates
533 /// @param[in] e_position Position in ECEF coordinates in [m]
534 /// @param[in] e_gravitation Gravitational acceleration in [m/s^2]
535 /// @param[in] r_eS_e Geocentric radius. The distance of a point on the Earth's surface from the center of the Earth in [m]
536 /// @param[in] e_omega_ie Angular velocity of Earth with respect to inertial system, represented in e-sys in [rad/s]
537 /// @param[in] tau_bad Correleation length for the accelerometer in [s]
538 /// @param[in] tau_bgd Correleation length for the gyroscope in [s]
539 /// @note See Groves (2013) chapter 14.2.3, equation (14.48) and chapter 9.4.2, equation (9.148)
540 [[nodiscard]] Eigen::Matrix<double, 17, 17> e_systemMatrix_F(const Eigen::Quaterniond& e_Quat_b,
541 const Eigen::Vector3d& b_specForce_ib,
542 const Eigen::Vector3d& e_position,
543 const Eigen::Vector3d& e_gravitation,
544 double r_eS_e,
545 const Eigen::Vector3d& e_omega_ie,
546 const Eigen::Vector3d& tau_bad,
547 const Eigen::Vector3d& tau_bgd) const;
548
549 // ----------------------------- Noise input matrix 𝐆 & Noise scale matrix 𝐖 -------------------------------
550 // ----------------------------------- System noise covariance matrix 𝐐 -------------------------------------
551
552 /// @brief Calculates the noise input matrix 𝐆
553 /// @param[in] ien_Quat_b Quaternion from body frame to {i,e,n} frame
554 /// @note See \cite Groves2013 Groves, ch. 14.2.6, eq. 14.79, p. 590 (INS part) and ch. 9.4.2, eq. 9.151, p. 416 (GNSS part)
555 [[nodiscard]] static Eigen::Matrix<double, 17, 14> noiseInputMatrix_G(const Eigen::Quaterniond& ien_Quat_b);
556
557 /// @brief Calculates the noise scale matrix 𝐖
558 /// @param[in] sigma2_ra Variance of the noise on the accelerometer specific-force measurements
559 /// @param[in] sigma2_rg Variance of the noise on the gyro angular-rate measurements
560 /// @param[in] sigma2_bad Variance of the accelerometer dynamic bias
561 /// @param[in] sigma2_bgd Variance of the gyro dynamic bias
562 /// @param[in] tau_bad Correleation length for the accelerometer in [s]
563 /// @param[in] tau_bgd Correleation length for the gyroscope in [s]
564 /// @param[in] sigma2_cPhi Variance of the noise on the clock offset in [m]
565 /// @param[in] sigma2_cf Variance of the noise on the clock frequency in [m/s]
566 /// @note See \cite Groves2013 Groves, ch. 14.2.6, eq. 14.79, p. 590 (INS part) and ch. 9.4.2, eq. 9.151, p. 416 (GNSS part)
567 [[nodiscard]] Eigen::Matrix<double, 14, 14> noiseScaleMatrix_W(const Eigen::Vector3d& sigma2_ra, const Eigen::Vector3d& sigma2_rg,
568 const Eigen::Vector3d& sigma2_bad, const Eigen::Vector3d& sigma2_bgd,
569 const Eigen::Vector3d& tau_bad, const Eigen::Vector3d& tau_bgd,
570 const double& sigma2_cPhi, const double& sigma2_cf);
571
572 /// @brief System noise covariance matrix 𝐐_{k-1}
573 /// @param[in] sigma2_ra Variance of the noise on the accelerometer specific-force measurements
574 /// @param[in] sigma2_rg Variance of the noise on the gyro angular-rate measurements
575 /// @param[in] sigma2_bad Variance of the accelerometer dynamic bias
576 /// @param[in] sigma2_bgd Variance of the gyro dynamic bias
577 /// @param[in] tau_bad Correleation length for the accelerometer in [s]
578 /// @param[in] tau_bgd Correleation length for the gyroscope in [s]
579 /// @param[in] sigma2_cPhi Variance of the noise on the clock offset in [m]
580 /// @param[in] sigma2_cf Variance of the noise on the clock frequency in [m/s]
581 /// @param[in] n_F_21 Submatrix 𝐅_21 of the system matrix 𝐅
582 /// @param[in] T_rn_p Conversion matrix between cartesian and curvilinear perturbations to the position
583 /// @param[in] n_Dcm_b Direction Cosine Matrix from body to navigation coordinates
584 /// @param[in] tau_s Time interval in [s]
585 /// @return The 15x15 matrix of system noise covariances
586 [[nodiscard]] static Eigen::Matrix<double, 17, 17> n_systemNoiseCovarianceMatrix_Q(const Eigen::Vector3d& sigma2_ra, const Eigen::Vector3d& sigma2_rg,
587 const Eigen::Vector3d& sigma2_bad, const Eigen::Vector3d& sigma2_bgd,
588 const Eigen::Vector3d& tau_bad, const Eigen::Vector3d& tau_bgd,
589 const double& sigma2_cPhi, const double& sigma2_cf,
590 const Eigen::Matrix3d& n_F_21, const Eigen::Matrix3d& T_rn_p,
591 const Eigen::Matrix3d& n_Dcm_b, const double& tau_s);
592
593 /// @brief System noise covariance matrix 𝐐_{k-1}
594 /// @param[in] sigma2_ra Variance of the noise on the accelerometer specific-force measurements
595 /// @param[in] sigma2_rg Variance of the noise on the gyro angular-rate measurements
596 /// @param[in] sigma2_bad Variance of the accelerometer dynamic bias
597 /// @param[in] sigma2_bgd Variance of the gyro dynamic bias
598 /// @param[in] tau_bad Correleation length for the accelerometer in [s]
599 /// @param[in] tau_bgd Correleation length for the gyroscope in [s]
600 /// @param[in] sigma2_cPhi Variance of the noise on the clock offset in [m]
601 /// @param[in] sigma2_cf Variance of the noise on the clock frequency in [m/s]
602 /// @param[in] e_F_21 Submatrix 𝐅_21 of the system matrix 𝐅
603 /// @param[in] e_Dcm_b Direction Cosine Matrix from body to Earth coordinates
604 /// @param[in] tau_s Time interval in [s]
605 /// @return The 15x15 matrix of system noise covariances
606 [[nodiscard]] static Eigen::Matrix<double, 17, 17> e_systemNoiseCovarianceMatrix_Q(const Eigen::Vector3d& sigma2_ra, const Eigen::Vector3d& sigma2_rg,
607 const Eigen::Vector3d& sigma2_bad, const Eigen::Vector3d& sigma2_bgd,
608 const Eigen::Vector3d& tau_bad, const Eigen::Vector3d& tau_bgd,
609 const double& sigma2_cPhi, const double& sigma2_cf,
610 const Eigen::Matrix3d& e_F_21,
611 const Eigen::Matrix3d& e_Dcm_b, const double& tau_s);
612
613 // --------------------------------------- Error covariance matrix P -----------------------------------------
614
615 /// @brief Initial error covariance matrix P_0
616 /// @param[in] variance_angles Initial Covariance of the attitude angles in [rad²]
617 /// @param[in] variance_vel Initial Covariance of the velocity in [m²/s²]
618 /// @param[in] variance_pos Initial Covariance of the position in [rad² rad² m²] n-frame / [m²] i,e-frame
619 /// @param[in] variance_accelBias Initial Covariance of the accelerometer biases in [m^2/s^4]
620 /// @param[in] variance_gyroBias Initial Covariance of the gyroscope biases in [rad^2/s^2]
621 /// @param[in] variance_clkPhase Initial Covariance of the receiver clock phase drift in [m²]
622 /// @param[in] variance_clkFreq Initial Covariance of the receiver clock frequency-drift in [m²/s²]
623 /// @return The 17x17 matrix of initial state variances
624 [[nodiscard]] Eigen::Matrix<double, 17, 17> initialErrorCovarianceMatrix_P0(const Eigen::Vector3d& variance_angles,
625 const Eigen::Vector3d& variance_vel,
626 const Eigen::Vector3d& variance_pos,
627 const Eigen::Vector3d& variance_accelBias,
628 const Eigen::Vector3d& variance_gyroBias,
629 const double& variance_clkPhase,
630 const double& variance_clkFreq) const;
631
632 // ###########################################################################################################
633 // Update
634 // ###########################################################################################################
635
636 /// @brief Measurement matrix for GNSS observations at timestep k, represented in navigation coordinates
637 /// @param[in] R_N Meridian radius of curvature in [m]
638 /// @param[in] R_E Prime vertical radius of curvature (East/West) [m]
639 /// @param[in] lla_position Position as Lat Lon Alt in [rad rad m]
640 /// @param[in] n_lineOfSightUnitVectors Vector of line-of-sight unit vectors to each satellite in NED frame coordinates (Groves ch. 8.5.3, eq. 8.41, p. 341)
641 /// @param[in] pseudoRangeRateObservations Pseudorange-Rate observations
642 /// @return The 2*m x 17 measurement matrix 𝐇 (m: number of satellites)
643 [[nodiscard]] static Eigen::MatrixXd n_measurementMatrix_H(const double& R_N,
644 const double& R_E,
645 const Eigen::Vector3d& lla_position,
646 const std::vector<Eigen::Vector3d>& n_lineOfSightUnitVectors,
647 std::vector<double>& pseudoRangeRateObservations);
648
649 /// @brief Measurement noise covariance matrix 𝐑
650 /// @param[in] sigma_rhoZ Standard deviation of the zenith pseudo-range error in [m]
651 /// @param[in] sigma_rZ Standard deviation of the zenith pseudo-range-rate error in [m/s]
652 /// @param[in] satElevation Elevation angles of all m satellites in [rad]
653 /// @return The 2*m x 2*m measurement covariance matrix 𝐑 (m: number of satellites)
654 [[nodiscard]] static Eigen::MatrixXd measurementNoiseCovariance_R(const double& sigma_rhoZ,
655 const double& sigma_rZ,
656 const std::vector<double>& satElevation);
657
658 /// @brief Calculates the elements for the measurement noise covariance matrix 𝐑
659 /// @param[in] satElevation Elevation angles of all m satellites in [rad]
660 /// @param[in] sigma_Z Standard deviation of the zenith pseudo-range error in [m] or the zenith pseudo-range-rate error in [m/s]
661 /// @param[in] sigma_C Standard deviation of the clock pseudo-range error in [m] or the clock pseudo-range-rate error in [m/s]
662 /// @param[in] sigma_A Standard deviation of the antenna pseudo-range error in [m] or the antenna pseudo-range-rate error in [m/s]
663 /// @param[in] CN0 Carrier-to-Noise density of all m satellites in [dBHz]
664 /// @param[in] rangeAccel Range acceleration of all m satellites in [m / s^2]
665 /// @return Variance of the pseudo-range error in [m²] or pseudo-range-rate error in [m²/s²]
666 [[nodiscard]] static double sigma2(const double& satElevation,
667 const double& sigma_Z,
668 const double& sigma_C,
669 const double& sigma_A,
670 const double& CN0,
671 const double& rangeAccel);
672
673 /// @brief Measurement innovation vector 𝜹𝐳
674 /// @param[in] pseudoRangeObservations Vector of Pseudorange observations from all available satellites in [m]
675 /// @param[in] pseudoRangeEstimates Vector of Pseudorange estimates from all available satellites in [m/s]
676 /// @param[in] pseudoRangeRateObservations Vector of Pseudorange-Rate observations from all available satellites in [m]
677 /// @param[in] pseudoRangeRateEstimates Vector of Pseudorange-Rate estimates from all available satellites in [m/s]
678 /// @return The 2*m x1 measurement innovation vector 𝜹𝐳 (m: number of satellites)
679 [[nodiscard]] static Eigen::MatrixXd measurementInnovation_dz(const std::vector<double>& pseudoRangeObservations,
680 const std::vector<double>& pseudoRangeEstimates,
681 const std::vector<double>& pseudoRangeRateObservations,
682 const std::vector<double>& pseudoRangeRateEstimates);
683};
684
685} // namespace NAV
686
687*/