| Line | Branch | Exec | Source |
|---|---|---|---|
| 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 Functions.hpp | ||
| 10 | /// @brief Inertial Navigation Helper Functions | ||
| 11 | /// @author T. Topp (topp@ins.uni-stuttgart.de) | ||
| 12 | /// @date 2020-09-02 | ||
| 13 | |||
| 14 | #pragma once | ||
| 15 | |||
| 16 | #include <Eigen/Core> | ||
| 17 | |||
| 18 | #include "Navigation/Constants.hpp" | ||
| 19 | #include "Navigation/Math/Math.hpp" | ||
| 20 | |||
| 21 | namespace NAV | ||
| 22 | { | ||
| 23 | /// @brief Calculates the transport rate ω_en_n (rotation rate of the Earth frame relative to the navigation frame) | ||
| 24 | /// | ||
| 25 | /// \anchor eq-INS-Mechanization-TransportRate \f{equation}{ \label{eq:eq-INS-Mechanization-TransportRate} | ||
| 26 | /// \boldsymbol{\omega}_{en}^n = \begin{bmatrix} \dfrac{v_E}{R_E + h} & \dfrac{-v_N}{R_N + h} & \dfrac{-v_E \tan{\phi}}{R_E + h} \end{bmatrix}^T | ||
| 27 | /// \f} | ||
| 28 | /// | ||
| 29 | /// @param[in] lla_position [𝜙, λ, h] Latitude, Longitude and altitude in [rad, rad, m] | ||
| 30 | /// @param[in] n_velocity Velocity in [m/s], in navigation coordinate | ||
| 31 | /// @param[in] R_N North/South (meridian) earth radius [m] | ||
| 32 | /// @param[in] R_E East/West (prime vertical) earth radius [m] | ||
| 33 | /// @return ω_en_n Transport Rate in local-navigation coordinates in [rad/s] | ||
| 34 | /// | ||
| 35 | /// @note See \cite Groves2013 Groves, ch. 5.4.1, eq. 5.44, p. 177 | ||
| 36 | /// @note See \cite Gleason2009 Gleason, ch. 6.2.3.2, eq. 6.15, p. 155 | ||
| 37 | /// @note See \cite Titterton2004 Titterton, ch. 3.7.2, eq. 3.87, p. 50 (mistake in denominator 3rd term) | ||
| 38 | template<typename DerivedA, typename DerivedB> | ||
| 39 | 5824570 | [[nodiscard]] Eigen::Vector3<typename DerivedA::Scalar> n_calcTransportRate(const Eigen::MatrixBase<DerivedA>& lla_position, | |
| 40 | const Eigen::MatrixBase<DerivedB>& n_velocity, | ||
| 41 | const auto& R_N, | ||
| 42 | const auto& R_E) | ||
| 43 | { | ||
| 44 | // 𝜙 Latitude in [rad] | ||
| 45 |
1/2✓ Branch 1 taken 111327 times.
✗ Branch 2 not taken.
|
5824570 | const auto& latitude = lla_position(0); |
| 46 | // h Altitude in [m] | ||
| 47 |
1/2✓ Branch 1 taken 111327 times.
✗ Branch 2 not taken.
|
5807816 | const auto& altitude = lla_position(2); |
| 48 | |||
| 49 | // Velocity North in [m/s] | ||
| 50 |
1/2✓ Branch 1 taken 111327 times.
✗ Branch 2 not taken.
|
5814458 | const auto& v_N = n_velocity(0); |
| 51 | // Velocity East in [m/s] | ||
| 52 |
1/2✓ Branch 1 taken 111327 times.
✗ Branch 2 not taken.
|
5816922 | const auto& v_E = n_velocity(1); |
| 53 | |||
| 54 |
1/2✓ Branch 1 taken 111327 times.
✗ Branch 2 not taken.
|
5818513 | Eigen::Vector3<typename DerivedA::Scalar> n_omega_en__t1; |
| 55 |
1/2✓ Branch 1 taken 111327 times.
✗ Branch 2 not taken.
|
5814167 | n_omega_en__t1(0) = v_E / (R_E + altitude); |
| 56 |
1/2✓ Branch 1 taken 111327 times.
✗ Branch 2 not taken.
|
5817414 | n_omega_en__t1(1) = -v_N / (R_N + altitude); |
| 57 |
2/4✓ Branch 1 taken 111327 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 111327 times.
✗ Branch 5 not taken.
|
5819875 | n_omega_en__t1(2) = -n_omega_en__t1(0) * std::tan(latitude); |
| 58 | |||
| 59 | 5931455 | return n_omega_en__t1; | |
| 60 | } | ||
| 61 | |||
| 62 | /// @brief Calculates the centrifugal acceleration in [m/s^2] (acceleration that makes a body follow a curved path) | ||
| 63 | /// | ||
| 64 | /// \anchor eq-INS-Mechanization-CentrifugalAcceleration \f{equation}{ \label{eq:eq-INS-Mechanization-CentrifugalAcceleration} | ||
| 65 | /// \boldsymbol{\omega}_{ie}^e \times [ \boldsymbol{\omega}_{ie}^e \times \mathbf{x}^e ] | ||
| 66 | /// \f} | ||
| 67 | /// | ||
| 68 | /// @param[in] e_position Position in coordinates in [m] | ||
| 69 | /// @param[in] e_omega_ie Angular rate of the Earth rotation in [rad/s] in the Earth coordinate frame | ||
| 70 | /// @return Centrifugal acceleration in the Earth coordinate frame in [m/s^2] | ||
| 71 | template<typename DerivedA, typename DerivedB = DerivedA> | ||
| 72 | 5954718 | [[nodiscard]] Eigen::Vector3<typename DerivedA::Scalar> e_calcCentrifugalAcceleration(const Eigen::MatrixBase<DerivedA>& e_position, | |
| 73 | const Eigen::MatrixBase<DerivedB>& e_omega_ie = InsConst::e_omega_ie) | ||
| 74 | { | ||
| 75 | // ω_ie_e ⨯ [ω_ie_e ⨯ x_e] | ||
| 76 |
2/8✗ Branch 2 not taken.
✓ Branch 3 taken 2982183 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 2984946 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
|
5954718 | return e_omega_ie.template cast<typename DerivedA::Scalar>().cross(e_omega_ie.template cast<typename DerivedA::Scalar>().cross(e_position)); |
| 77 | } | ||
| 78 | |||
| 79 | /// @brief Calculates the coriolis acceleration in [m/s^2] (acceleration due to motion in rotating reference frame) | ||
| 80 | /// | ||
| 81 | /// \anchor eq-INS-Mechanization-CoriolisAcceleration \f{equation}{ \label{eq:eq-INS-Mechanization-CoriolisAcceleration} | ||
| 82 | /// (2 \boldsymbol{\omega}_{ie}^n + \boldsymbol{\omega}_{en}^n) \times \boldsymbol{v}^n | ||
| 83 | /// \f} | ||
| 84 | /// | ||
| 85 | /// @param[in] n_omega_ie ω_ie_n Angular rate of the Earth rotation in [rad/s] in local-navigation coordinates | ||
| 86 | /// @param[in] n_omega_en ω_en_n Transport rate in [rad/s] in local-navigation coordinates | ||
| 87 | /// @param[in] n_velocity Velocity in local-navigation frame coordinates in [m/s^2] | ||
| 88 | /// @return Coriolis acceleration in local-navigation coordinates in [m/s^2] | ||
| 89 | template<typename DerivedA, typename DerivedB, typename DerivedC> | ||
| 90 | 2936635 | [[nodiscard]] Eigen::Vector3<typename DerivedA::Scalar> n_calcCoriolisAcceleration(const Eigen::MatrixBase<DerivedA>& n_omega_ie, | |
| 91 | const Eigen::MatrixBase<DerivedB>& n_omega_en, | ||
| 92 | const Eigen::MatrixBase<DerivedC>& n_velocity) | ||
| 93 | { | ||
| 94 |
3/6✓ Branch 1 taken 2934099 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2935393 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2942849 times.
✗ Branch 8 not taken.
|
5879484 | return (2.0 * n_omega_ie + n_omega_en).cross(n_velocity); |
| 95 | } | ||
| 96 | |||
| 97 | /// @brief Calculates the coriolis acceleration in [m/s^2] (acceleration due to motion in rotating reference frame) | ||
| 98 | /// | ||
| 99 | /// \anchor eq-INS-Mechanization-CoriolisAcceleration-e \f{equation}{ \label{eq:eq-INS-Mechanization-CoriolisAcceleration-e} | ||
| 100 | /// 2 \boldsymbol{\omega}_{ie}^e \times \boldsymbol{v}^e | ||
| 101 | /// \f} | ||
| 102 | /// | ||
| 103 | /// @param[in] e_omega_ie ω_ie_e Angular rate of the Earth rotation in [rad/s] in ECEF coordinates | ||
| 104 | /// @param[in] e_velocity Velocity in ECEF frame coordinates in [m/s^2] | ||
| 105 | /// @return Coriolis acceleration in ECEF coordinates in [m/s^2] | ||
| 106 | template<typename DerivedA, typename DerivedB> | ||
| 107 | 38664 | [[nodiscard]] Eigen::Vector3<typename DerivedB::Scalar> e_calcCoriolisAcceleration(const Eigen::MatrixBase<DerivedA>& e_omega_ie, const Eigen::MatrixBase<DerivedB>& e_velocity) | |
| 108 | { | ||
| 109 |
2/4✓ Branch 2 taken 38664 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 38664 times.
✗ Branch 6 not taken.
|
38664 | return (2.0 * e_omega_ie.template cast<typename DerivedB::Scalar>()).cross(e_velocity); |
| 110 | } | ||
| 111 | |||
| 112 | /// @brief Calculates the roll angle from a static acceleration measurement | ||
| 113 | /// @param[in] b_accel Acceleration measurement in static condition in [m/s^2] | ||
| 114 | /// @return The roll angle in [rad] | ||
| 115 | /// | ||
| 116 | /// @note See E.-H. Shin (2005) - Estimation Techniques for Low-Cost Inertial Navigation (Chapter 2.6) | ||
| 117 | template<typename Derived> | ||
| 118 | ✗ | [[nodiscard]] typename Derived::Scalar calcRollFromStaticAcceleration(const Eigen::MatrixBase<Derived>& b_accel) | |
| 119 | { | ||
| 120 | // See E.-H. Shin (2005) - Estimation Techniques for Low-Cost Inertial Navigation (Chapter 2.6 - eq. 2.72a) | ||
| 121 | ✗ | return math::sgn(b_accel.z()) * std::asin(b_accel.y() / b_accel.norm()); | |
| 122 | |||
| 123 | // Another possible calculation would be: | ||
| 124 | // return std::atan2(b_accel.y(), b_accel.z()); | ||
| 125 | } | ||
| 126 | |||
| 127 | /// @brief Calculates the pitch angle from a static acceleration measurement | ||
| 128 | /// @param[in] b_accel Acceleration measurement in static condition in [m/s^2] | ||
| 129 | /// @return The pitch angle in [rad] | ||
| 130 | /// | ||
| 131 | /// @note See E.-H. Shin (2005) - Estimation Techniques for Low-Cost Inertial Navigation (Chapter 2.6) | ||
| 132 | template<typename Derived> | ||
| 133 | ✗ | [[nodiscard]] typename Derived::Scalar calcPitchFromStaticAcceleration(const Eigen::MatrixBase<Derived>& b_accel) | |
| 134 | { | ||
| 135 | // See E.-H. Shin (2005) - Estimation Techniques for Low-Cost Inertial Navigation (Chapter 2.6 - eq. 2.72b) | ||
| 136 | ✗ | return -math::sgn(b_accel.z()) * std::asin(b_accel.x() / b_accel.norm()); | |
| 137 | |||
| 138 | // Another possible calculation would be: | ||
| 139 | // return std::atan2((-b_accel.x()), sqrt(std::pow(b_accel.y(), 2) + std::pow(b_accel.z(), 2))); | ||
| 140 | } | ||
| 141 | |||
| 142 | /// @brief Calculates the Yaw angle from the trajectory defined by the given velocity | ||
| 143 | /// | ||
| 144 | /// \anchor eq-INS-Mechanization-Yaw \f{equation}{ \label{eq:eq-INS-Mechanization-Yaw} | ||
| 145 | /// Y = \tan^{-1}\left(\frac{v_E}{v_N}\right) | ||
| 146 | /// \f} | ||
| 147 | /// | ||
| 148 | /// @param[in] n_velocity Velocity in [m/s] in local-navigation frame coordinates | ||
| 149 | /// @return Yaw angle in [rad] | ||
| 150 | /// | ||
| 151 | /// @note See \cite Groves2013 Groves, ch. 6.1.4, eq. 6.14, p. 225 | ||
| 152 | template<typename Derived> | ||
| 153 | 1343745 | [[nodiscard]] typename Derived::Scalar calcYawFromVelocity(const Eigen::MatrixBase<Derived>& n_velocity) | |
| 154 | { | ||
| 155 | 1343745 | return std::atan2(n_velocity(1), n_velocity(0)); | |
| 156 | } | ||
| 157 | |||
| 158 | /// @brief Calculates the Pitch angle from the trajectory defined by the given velocity | ||
| 159 | /// | ||
| 160 | /// \anchor eq-INS-Mechanization-Pitch \f{equation}{ \label{eq:eq-INS-Mechanization-Pitch} | ||
| 161 | /// P = \tan^{-1}\left(\frac{-v_D}{\sqrt{v_N^2 + v_E^2}}\right) | ||
| 162 | /// \f} | ||
| 163 | /// | ||
| 164 | /// @param[in] n_velocity Velocity in [m/s] in local-navigation frame coordinates | ||
| 165 | /// @return Pitch angle in [rad] | ||
| 166 | /// | ||
| 167 | /// @note See \cite Groves2013 Groves, ch. 6.1.4, eq. 6.17, p. 225 | ||
| 168 | template<typename Derived> | ||
| 169 | 1343745 | [[nodiscard]] typename Derived::Scalar calcPitchFromVelocity(const Eigen::MatrixBase<Derived>& n_velocity) | |
| 170 | { | ||
| 171 | 1343745 | return std::atan(-n_velocity(2) / std::sqrt(std::pow(n_velocity(0), 2) + std::pow(n_velocity(1), 2))); | |
| 172 | } | ||
| 173 | |||
| 174 | } // namespace NAV | ||
| 175 |