39class TightlyCoupledKF : public Node
45 ~TightlyCoupledKF() override;
47 TightlyCoupledKF(const TightlyCoupledKF&) = delete;
49 TightlyCoupledKF(TightlyCoupledKF&&) = delete;
51 TightlyCoupledKF& operator=(const TightlyCoupledKF&) = delete;
53 TightlyCoupledKF& operator=(TightlyCoupledKF&&) = delete;
55 [[nodiscard]] static std::string typeStatic();
57 [[nodiscard]] std::string type() const override;
59 [[nodiscard]] static std::string category();
63 void guiConfig() override;
66 [[nodiscard]] json save() const override;
70 void restore(const json& j) override;
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
88 bool initialize() override;
91 void deinitialize() override;
95 void invokeCallbackWithPosVelAtt(const PosVelAtt& posVelAtt);
100 void recvImuObservation(InputPin::NodeDataQueue& queue, size_t pinIdx);
105 void recvGnssObs(InputPin::NodeDataQueue& queue, size_t pinIdx);
110 void recvPosVelAttInit(InputPin::NodeDataQueue& queue, size_t pinIdx);
116 void tightlyCoupledPrediction(const std::shared_ptr<const PosVelAtt>& inertialNavSol, double tau_i, const ImuPos& imuPos);
120 void tightlyCoupledUpdate(const std::shared_ptr<const GnssObs>& gnssObservation);
123 void addKalmanMatricesPins();
126 void removeKalmanMatricesPins();
129 void updateExternalPvaInitPin();
132 int _dragAndDropPinIndex = -1;
134 size_t _nNavInfoPins = 1;
136 void updateNumberOfInputPins();
139 InertialIntegrator _inertialIntegrator;
141 bool _preferAccelerationOverDeltaMeasurements = false;
144 std::shared_ptr<const ImuObs> _lastImuObs = nullptr;
147 std::array<double, 3> _initalRollPitchYaw{};
149 bool _initializeStateOverExternalPin{};
151 InsTime _externalInitTime;
154 ReceiverClock _recvClk{ std::vector<SatelliteSystem>{ GPS } };
157 Frequency _filterFreq = G01;
159 Code _filterCode = Code_Default;
161 std::vector<SatId> _excludedSatellites;
163 double _elevationMask = static_cast<double>(15.0_deg);
166 IonosphereModel _ionosphereModel = IonosphereModel::Klobuchar;
169 TroposphereModelSelection _troposphereModels;
172 std::vector<SPP::States::StateKeyType> _interSysErrs;
175 std::vector<SPP::States::StateKeyType> _interSysDrifts;
178 InsTime _lastEpochTime; // TODO: Remove?
181 KalmanFilter _kalmanFilter{ 17, 8 };
183 // ###########################################################################################################
185 // ###########################################################################################################
188 bool _showKalmanFilterOutputPins = false;
191 bool _checkKalmanMatricesRanks = true;
193 // ###########################################################################################################
195 // ###########################################################################################################
198 Eigen::Vector3d _b_leverArm_InsGnss{ 0.0, 0.0, 0.0 };
200 // ###########################################################################################################
203 enum class StdevAccelNoiseUnits : uint8_t
205 mg_sqrtHz, ///< [mg / √(Hz)]
206 m_s2_sqrtHz, ///< [m / s^2 / √(Hz)]
209 StdevAccelNoiseUnits _stdevAccelNoiseUnits = StdevAccelNoiseUnits::mg_sqrtHz;
213 Eigen::Vector3d _stdev_ra = 0.04 * Eigen::Vector3d::Ones(); // [mg/√(Hz)]
215 // ###########################################################################################################
218 enum class StdevGyroNoiseUnits : uint8_t
220 deg_hr_sqrtHz, ///< [deg / hr /√(Hz)]
221 rad_s_sqrtHz, ///< [rad / s /√(Hz)]
224 StdevGyroNoiseUnits _stdevGyroNoiseUnits = StdevGyroNoiseUnits::deg_hr_sqrtHz;
228 Eigen::Vector3d _stdev_rg = 5 * Eigen::Vector3d::Ones(); // [deg/hr/√(Hz)]^2
230 // ###########################################################################################################
233 enum class StdevAccelBiasUnits : uint8_t
239 StdevAccelBiasUnits _stdevAccelBiasUnits = StdevAccelBiasUnits::microg;
243 Eigen::Vector3d _stdev_bad = 10 * Eigen::Vector3d::Ones(); // [µg]
246 Eigen::Vector3d _tau_bad = 0.1 * Eigen::Vector3d::Ones();
248 // ###########################################################################################################
251 enum class StdevGyroBiasUnits : uint8_t
257 StdevGyroBiasUnits _stdevGyroBiasUnits = StdevGyroBiasUnits::deg_h;
261 Eigen::Vector3d _stdev_bgd = 1 * Eigen::Vector3d::Ones(); // [°/h]
264 Eigen::Vector3d _tau_bgd = 0.1 * Eigen::Vector3d::Ones();
266 // ###########################################################################################################
269 enum class StdevClockPhaseUnits : uint8_t
271 m_sqrtHz, ///< [m / √(Hz)]
274 StdevClockPhaseUnits _stdevClockPhaseUnits = StdevClockPhaseUnits::m_sqrtHz;
278 double _stdev_cp = 0; // [m / √(Hz)]
280 // ###########################################################################################################
283 enum class StdevClockFreqUnits : uint8_t
285 m_s_sqrtHz, ///< [m / s / √(Hz)]
288 StdevClockFreqUnits _stdevClockFreqUnits = StdevClockFreqUnits::m_s_sqrtHz;
292 double _stdev_cf = 5; // [m / s / √(Hz)]
294 // ###########################################################################################################
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
300 // meter2, ///< Variance [m²]
301 // meter, ///< Standard deviation [m]
303 // /// Gui selection for the Unit of the input gnssMeasurementUncertaintyPseudorangeUnit parameter
304 // GnssMeasurementUncertaintyPseudorangeUnit _gnssMeasurementUncertaintyPseudorangeUnit = GnssMeasurementUncertaintyPseudorangeUnit::meter;
306 // /// @brief GUI selection of the GNSS pseudorange measurement uncertainty (standard deviation σ or Variance σ²).
307 // double _gnssMeasurementUncertaintyPseudorange = 5; // [m]
309 // // ###########################################################################################################
311 // /// Possible Units for the Standard deviation of the pseudorange-rate measurement
312 // enum class GnssMeasurementUncertaintyPseudorangeRateUnit : uint8_t
314 // m2_s2, ///< Variance [m²/s²]
315 // m_s, ///< Standard deviation [m/s]
317 // /// Gui selection for the Unit of the input gnssMeasurementUncertaintyPseudorangeRateUnit parameter
318 // GnssMeasurementUncertaintyPseudorangeRateUnit _gnssMeasurementUncertaintyPseudorangeRateUnit = GnssMeasurementUncertaintyPseudorangeRateUnit::m_s;
320 // /// @brief GUI selection of the GNSS pseudorange-rate measurement uncertainty (standard deviation σ or Variance σ²).
321 // double _gnssMeasurementUncertaintyPseudorangeRate = 5; // [m/s]
323 // ###########################################################################################################
326 enum class RandomProcess : uint8_t
328 // WhiteNoise, ///< White noise
329 // RandomConstant, ///< Random constant
331 RandomWalk, ///< Random Walk
332 GaussMarkov1, ///< Gauss-Markov 1st Order
334 // GaussMarkov2, ///< Gauss-Markov 2nd Order
335 // GaussMarkov3, ///< Gauss-Markov 3rd Order
339 RandomProcess _randomProcessAccel = RandomProcess::RandomWalk;
341 RandomProcess _randomProcessGyro = RandomProcess::RandomWalk;
343 // ###########################################################################################################
346 enum class InitCovarianceClockPhaseUnit : uint8_t
348 m2, ///< Variance [m²]
349 s2, ///< Variance [s²]
350 m, ///< Standard deviation [m]
351 s ///< Standard deviation [s]
354 InitCovarianceClockPhaseUnit _initCovariancePhaseUnit = InitCovarianceClockPhaseUnit::m;
357 double _initCovariancePhase{ 5 };
359 // ###########################################################################################################
362 enum class InitCovarianceClockFreqUnit : uint8_t
364 m2_s2, ///< Variance [m²/s²]
365 m_s, ///< Standard deviation [m/s]
368 InitCovarianceClockFreqUnit _initCovarianceFreqUnit = InitCovarianceClockFreqUnit::m_s;
371 double _initCovarianceFreq{ 5 };
373 // ###########################################################################################################
376 enum class InitCovariancePositionUnit : uint8_t
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]
384 InitCovariancePositionUnit _initCovariancePositionUnit = InitCovariancePositionUnit::meter;
387 Eigen::Vector3d _initCovariancePosition{ 100, 100, 100 };
389 // ###########################################################################################################
392 enum class InitCovarianceVelocityUnit : uint8_t
394 m2_s2, ///< Variance [m^2/s^2]
395 m_s, ///< Standard deviation [m/s]
398 InitCovarianceVelocityUnit _initCovarianceVelocityUnit = InitCovarianceVelocityUnit::m_s;
401 Eigen::Vector3d _initCovarianceVelocity{ 10, 10, 10 };
403 // ###########################################################################################################
406 enum class InitCovarianceAttitudeAnglesUnit : uint8_t
408 rad2, ///< Variance [rad^2]
409 deg2, ///< Variance [deg^2]
410 rad, ///< Standard deviation [rad]
411 deg, ///< Standard deviation [deg]
414 InitCovarianceAttitudeAnglesUnit _initCovarianceAttitudeAnglesUnit = InitCovarianceAttitudeAnglesUnit::deg;
417 Eigen::Vector3d _initCovarianceAttitudeAngles{ 10, 10, 10 };
419 // ###########################################################################################################
422 enum class InitCovarianceBiasAccelUnit : uint8_t
424 m2_s4, ///< Variance [m^2/s^4]
425 m_s2, ///< Standard deviation [m/s^2]
428 InitCovarianceBiasAccelUnit _initCovarianceBiasAccelUnit = InitCovarianceBiasAccelUnit::m_s2;
431 Eigen::Vector3d _initCovarianceBiasAccel{ 1, 1, 1 };
433 // ###########################################################################################################
436 enum class InitCovarianceBiasGyroUnit : uint8_t
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]
444 InitCovarianceBiasGyroUnit _initCovarianceBiasGyroUnit = InitCovarianceBiasGyroUnit::deg_s;
447 Eigen::Vector3d _initCovarianceBiasGyro{ 0.5, 0.5, 0.5 };
449 // ###########################################################################################################
452 enum class PhiCalculationAlgorithm : uint8_t
454 Exponential, ///< Van-Loan
458 PhiCalculationAlgorithm _phiCalculationAlgorithm = PhiCalculationAlgorithm::Taylor;
461 int _phiCalculationTaylorOrder = 2;
464 enum class QCalculationAlgorithm : uint8_t
466 VanLoan, ///< Van-Loan
470 QCalculationAlgorithm _qCalculationAlgorithm = QCalculationAlgorithm::Taylor1;
472 // ###########################################################################################################
475 enum class InitBiasAccelUnit : uint8_t
477 m_s2, ///< acceleration [m/s^2]
480 InitBiasAccelUnit _initBiasAccelUnit = InitBiasAccelUnit::m_s2;
483 Eigen::Vector3d _initBiasAccel{ 0.0, 0.0, 0.0 };
485 // ###########################################################################################################
488 enum class InitBiasGyroUnit : uint8_t
490 rad_s, ///< angular rate [rad/s]
491 deg_s, ///< angular rate [deg/s]
494 InitBiasGyroUnit _initBiasGyroUnit = InitBiasGyroUnit::deg_s;
497 Eigen::Vector3d _initBiasGyro{ 0.0, 0.0, 0.0 };
499 // ###########################################################################################################
501 // ###########################################################################################################
503 // ------------------------------------------- System matrix 𝐅 ----------------------------------------------
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,
527 const Eigen::Vector3d& tau_bad,
528 const Eigen::Vector3d& tau_bgd) const;
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,
545 const Eigen::Vector3d& e_omega_ie,
546 const Eigen::Vector3d& tau_bad,
547 const Eigen::Vector3d& tau_bgd) const;
549 // ----------------------------- Noise input matrix 𝐆 & Noise scale matrix 𝐖 -------------------------------
550 // ----------------------------------- System noise covariance matrix 𝐐 -------------------------------------
555 [[nodiscard]] static Eigen::Matrix<double, 17, 14> noiseInputMatrix_G(const Eigen::Quaterniond& ien_Quat_b);
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);
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);
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);
613 // --------------------------------------- Error covariance matrix P -----------------------------------------
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;
632 // ###########################################################################################################
634 // ###########################################################################################################
643 [[nodiscard]] static Eigen::MatrixXd n_measurementMatrix_H(const double& R_N,
645 const Eigen::Vector3d& lla_position,
646 const std::vector<Eigen::Vector3d>& n_lineOfSightUnitVectors,
647 std::vector<double>& pseudoRangeRateObservations);
654 [[nodiscard]] static Eigen::MatrixXd measurementNoiseCovariance_R(const double& sigma_rhoZ,
655 const double& sigma_rZ,
656 const std::vector<double>& satElevation);
666 [[nodiscard]] static double sigma2(const double& satElevation,
667 const double& sigma_Z,
668 const double& sigma_C,
669 const double& sigma_A,
671 const double& rangeAccel);
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);