INSTINCT Code Coverage Report


Directory: src/
File: Navigation/GNSS/Functions.hpp
Date: 2025-02-07 16:54:41
Exec Total Coverage
Lines: 11 11 100.0%
Functions: 5 5 100.0%
Branches: 8 16 50.0%

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 315583 [[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 315583 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 315583 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 315583 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 315583 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 315583 times.
✗ Branch 14 not taken.
315583 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 126783 [[nodiscard]] typename Derived::Scalar calcSatElevation(const Eigen::MatrixBase<Derived>& n_lineOfSightUnitVector)
44 {
45 126783 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 83280 [[nodiscard]] typename Derived::Scalar calcSatAzimuth(const Eigen::MatrixBase<Derived>& n_lineOfSightUnitVector)
55 {
56 83280 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 41798 [[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 41798 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 41798 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 41798 times.
✗ Branch 8 not taken.
41798 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 40922 [[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 40922 * (e_satVel.y() * e_recvPos.x() + e_satPos.y() * e_recvVel.x()
88 40922 - 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