| 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 GNSS helper functions | ||
| 11 | /// @author T. Topp (topp@ins.uni-stuttgart.de) | ||
| 12 | /// @date 2022-05-19 | ||
| 13 | |||
| 14 | #pragma once | ||
| 15 | |||
| 16 | #include <cmath> | ||
| 17 | #include <Eigen/Core> | ||
| 18 | #include "Navigation/Constants.hpp" | ||
| 19 | #include "Navigation/GNSS/Core/Frequency.hpp" | ||
| 20 | |||
| 21 | namespace NAV | ||
| 22 | { | ||
| 23 | |||
| 24 | /// @brief Calculates the line-of-sight unit vector from the user antenna to the satellite | ||
| 25 | /// @param[in] e_posAnt Position of the user antenna in ECEF frame coordinates | ||
| 26 | /// @param[in] e_posSat Position of the satellite in ECEF frame coordinates | ||
| 27 | /// @return The line-of-sight unit vector in ECEF frame coordinates | ||
| 28 | /// | ||
| 29 | /// @note See \cite Groves2013 Groves, ch. 8.5.3, eq. 8.41, p. 341 | ||
| 30 | template<typename DerivedA, typename DerivedB> | ||
| 31 | 1490612 | [[nodiscard]] Eigen::Vector3<typename DerivedA::Scalar> e_calcLineOfSightUnitVector(const Eigen::MatrixBase<DerivedA>& e_posAnt, | |
| 32 | const Eigen::MatrixBase<DerivedB>& e_posSat) | ||
| 33 | { | ||
| 34 |
5/10✓ Branch 1 taken 1490594 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1490513 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1490547 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1490534 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 1490467 times.
✗ Branch 14 not taken.
|
1490612 | return (e_posSat - e_posAnt) / (e_posSat - e_posAnt).norm(); |
| 35 | } | ||
| 36 | |||
| 37 | /// @brief Calculates the elevation of the satellite from the antenna | ||
| 38 | /// @param[in] n_lineOfSightUnitVector Line-of-sight unit vector from the antenna to the satellite in NED frame coordinates | ||
| 39 | /// @return Elevation [rad] | ||
| 40 | /// | ||
| 41 | /// @note See \cite Groves2013 Groves, ch. 8.5.4, eq. 8.57, p. 344 | ||
| 42 | template<typename Derived> | ||
| 43 | 836195 | [[nodiscard]] typename Derived::Scalar calcSatElevation(const Eigen::MatrixBase<Derived>& n_lineOfSightUnitVector) | |
| 44 | { | ||
| 45 | 836195 | return -asin(n_lineOfSightUnitVector(2)); | |
| 46 | } | ||
| 47 | |||
| 48 | /// @brief Calculates the azimuth of the satellite from the antenna | ||
| 49 | /// @param[in] n_lineOfSightUnitVector Line-of-sight unit vector from the antenna to the satellite in NED frame coordinates | ||
| 50 | /// @return Azimuth [rad] | ||
| 51 | /// | ||
| 52 | /// @note See \cite Groves2013 Groves, ch. 8.5.4, eq. 8.57, p. 344 | ||
| 53 | template<typename Derived> | ||
| 54 | 209579 | [[nodiscard]] typename Derived::Scalar calcSatAzimuth(const Eigen::MatrixBase<Derived>& n_lineOfSightUnitVector) | |
| 55 | { | ||
| 56 | 209579 | return atan2(n_lineOfSightUnitVector(1), n_lineOfSightUnitVector(0)); | |
| 57 | } | ||
| 58 | |||
| 59 | /// @brief Calculates the Earth rotation/Sagnac correction | ||
| 60 | /// @param[in] e_posAnt Position of the user antenna in ECEF frame coordinates | ||
| 61 | /// @param[in] e_satPos Position of the satellite in ECEF frame coordinates | ||
| 62 | /// @return Earth rotation/Sagnac correction [m] | ||
| 63 | /// | ||
| 64 | /// @note See \cite SpringerHandbookGNSS2017 Springer Handbook ch. 19.1.1, eq. 19.7, p. 562 | ||
| 65 | template<typename DerivedA, typename DerivedB> | ||
| 66 | 160460 | [[nodiscard]] typename DerivedA::Scalar calcSagnacCorrection(const Eigen::MatrixBase<DerivedA>& e_posAnt, | |
| 67 | const Eigen::MatrixBase<DerivedB>& e_satPos) | ||
| 68 | { | ||
| 69 |
3/6✓ Branch 1 taken 160463 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 160462 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 160461 times.
✗ Branch 8 not taken.
|
160460 | return 1.0 / InsConst::C * (e_posAnt - e_satPos).dot(InsConst::e_omega_ie.cross(e_posAnt)); |
| 70 | } | ||
| 71 | |||
| 72 | /// @brief Calculates the Range-rate Earth rotation/Sagnac correction | ||
| 73 | /// @param[in] e_recvPos Position of the user antenna in ECEF frame coordinates | ||
| 74 | /// @param[in] e_satPos Position of the satellite in ECEF frame coordinates | ||
| 75 | /// @param[in] e_recvVel Velocity of the user antenna in ECEF frame coordinates | ||
| 76 | /// @param[in] e_satVel Velocity of the satellite in ECEF frame coordinates | ||
| 77 | /// @return Range-rate Earth rotation/Sagnac correction [m/s] | ||
| 78 | /// | ||
| 79 | /// @note See \cite Groves2013 Groves ch. 8.5.3, eq. 8.46, p. 342 | ||
| 80 | template<typename DerivedA, typename DerivedB, typename DerivedC, typename DerivedD> | ||
| 81 | 159587 | [[nodiscard]] typename DerivedA::Scalar calcSagnacRateCorrection(const Eigen::MatrixBase<DerivedA>& e_recvPos, | |
| 82 | const Eigen::MatrixBase<DerivedB>& e_satPos, | ||
| 83 | const Eigen::MatrixBase<DerivedC>& e_recvVel, | ||
| 84 | const Eigen::MatrixBase<DerivedD>& e_satVel) | ||
| 85 | { | ||
| 86 | return InsConst::omega_ie / InsConst::C | ||
| 87 | 159587 | * (e_satVel.y() * e_recvPos.x() + e_satPos.y() * e_recvVel.x() | |
| 88 | 159585 | - e_satVel.x() * e_recvPos.y() - e_satPos.x() * e_recvVel.y()); | |
| 89 | } | ||
| 90 | |||
| 91 | /// @brief Transforms a doppler-shift into a range-rate | ||
| 92 | /// @param[in] doppler The doppler-shift to transform [Hz] | ||
| 93 | /// @param[in] freq Frequency | ||
| 94 | /// @param[in] num Frequency number. Only used for GLONASS G1 and G2 | ||
| 95 | /// @return The corresponding range-rate [m/s] | ||
| 96 | /// | ||
| 97 | /// @note See \cite Groves2013 Groves, ch. 9.2.7, eq. 9.70, p. 388 | ||
| 98 | [[nodiscard]] double doppler2rangeRate(double doppler, Frequency freq, int8_t num); | ||
| 99 | |||
| 100 | /// @brief Transforms a range-rate into a doppler-shift | ||
| 101 | /// @param[in] rangeRate The range-rate to transform [m/s] | ||
| 102 | /// @param[in] freq Frequency | ||
| 103 | /// @param[in] num Frequency number. Only used for GLONASS G1 and G2 | ||
| 104 | /// @return The corresponding doppler-shift [Hz] | ||
| 105 | /// | ||
| 106 | /// @note See \cite Groves2013 Groves, ch. 9.2.7, eq. 9.70, p. 388 | ||
| 107 | [[nodiscard]] double rangeRate2doppler(double rangeRate, Frequency freq, int8_t num); | ||
| 108 | |||
| 109 | /// @brief Calculates the ration of the frequencies squared γ | ||
| 110 | /// | ||
| 111 | /// \anchor eq-GNSS-freqRatio \f{equation}{ \label{eq:eq-GNSS-freqRatio} | ||
| 112 | /// \gamma = (f_1 / f_2)^2 | ||
| 113 | /// \f} | ||
| 114 | /// | ||
| 115 | /// @param[in] f1 First frequency (usually L1) | ||
| 116 | /// @param[in] f2 Second frequency (usually L2) | ||
| 117 | /// @param[in] num1 First frequency number. Only used for GLONASS G1 and G2 | ||
| 118 | /// @param[in] num2 Second frequency number. Only used for GLONASS G1 and G2 | ||
| 119 | /// @return The ratio (f1/f2)^2 [-] | ||
| 120 | /// @note See \cite IS-GPS-200M IS-GPS-200 ch. 20.3.3.3.3.2 p.99 | ||
| 121 | [[nodiscard]] double ratioFreqSquared(Frequency f1, Frequency f2, int8_t num1, int8_t num2); | ||
| 122 | |||
| 123 | /// @brief Converts a GALILEO SISA (Signal in space accuracy) value to it's index | ||
| 124 | /// @param[in] val SISA value in [m] | ||
| 125 | /// @return The SISA index | ||
| 126 | /// | ||
| 127 | /// @note See \cite GAL-ICD-2.0 GAL ICD ch. 5.1.12, p.58 | ||
| 128 | [[nodiscard]] uint8_t galSisaVal2Idx(double val); | ||
| 129 | |||
| 130 | /// @brief Converts a GALILEO SISA (Signal in space accuracy) index to it's value | ||
| 131 | /// @param[in] idx The SISA index | ||
| 132 | /// @return SISA value in [m] | ||
| 133 | /// | ||
| 134 | /// @note See \cite GAL-ICD-2.0 GAL ICD ch. 5.1.12, p.58 | ||
| 135 | [[nodiscard]] double galSisaIdx2Val(uint8_t idx); | ||
| 136 | |||
| 137 | /// @brief Converts a GPS URA (user range accuracy) value to it's index | ||
| 138 | /// @param[in] val URA value in [m] | ||
| 139 | /// @return The URA index | ||
| 140 | /// | ||
| 141 | /// @note See \cite IS-GPS-200M GPS ICD ch. 20.3.3.3.1.3, p.92ff | ||
| 142 | [[nodiscard]] uint8_t gpsUraVal2Idx(double val); | ||
| 143 | |||
| 144 | /// @brief Converts a GPS URA (user range accuracy) index to it's value | ||
| 145 | /// @param[in] idx The URA index | ||
| 146 | /// @return URA value in [m] | ||
| 147 | /// | ||
| 148 | /// @note See \cite IS-GPS-200M GPS ICD ch. 20.3.3.3.1.3, p.92ff | ||
| 149 | [[nodiscard]] double gpsUraIdx2Val(uint8_t idx); | ||
| 150 | |||
| 151 | } // namespace NAV | ||
| 152 |