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 | #include "GLONASSEphemeris.hpp" | ||
10 | #include <cstdint> | ||
11 | |||
12 | #include "Navigation/Constants.hpp" | ||
13 | #include "Navigation/Math/NumericalIntegration.hpp" | ||
14 | #include "Navigation/Transformations/CoordinateFrames.hpp" | ||
15 | |||
16 | #include "util/Logger.hpp" | ||
17 | |||
18 | namespace NAV | ||
19 | { | ||
20 | |||
21 | 3628 | GLONASSEphemeris::GLONASSEphemeris(const InsTime& toc, double tau_c, | |
22 | double tau_n, double gamma_n, bool health, | ||
23 | Eigen::Vector3d pos, Eigen::Vector3d vel, Eigen::Vector3d accelLuniSolar, | ||
24 | 3628 | int8_t frequencyNumber) | |
25 | : SatNavData(SatNavData::GLONASSEphemeris, toc), | ||
26 | 3628 | tau_c(tau_c), | |
27 | 3628 | toc(toc), | |
28 | 3628 | tau_n(tau_n), | |
29 | 3628 | gamma_n(gamma_n), | |
30 | 3628 | health(health), | |
31 | 3628 | PZ90_pos(std::move(pos)), | |
32 | 3628 | PZ90_vel(std::move(vel)), | |
33 | 3628 | PZ90_accelLuniSolar(std::move(accelLuniSolar)), | |
34 | 3628 | frequencyNumber(frequencyNumber) {} | |
35 | |||
36 | #ifdef TESTING | ||
37 | |||
38 | 11033 | GLONASSEphemeris::GLONASSEphemeris(int32_t year, int32_t month, int32_t day, int32_t hour, int32_t minute, double second, | |
39 | double m_tau_n, double gamma_n, double /* messageFrameTime */, | ||
40 | double satPos_x, double satVel_x, double satAccel_x, double health, | ||
41 | double satPos_y, double satVel_y, double satAccel_y, double frequencyNumber, | ||
42 | double satPos_z, double satVel_z, double satAccel_z, double /* ageOfOperationInfo */, | ||
43 | double /* statusFlags */, double /* L1L2groupDelayDifference */, double /* URAI */, double /* healthFlags */, | ||
44 | 11033 | double tau_c) | |
45 |
1/2✓ Branch 1 taken 11033 times.
✗ Branch 2 not taken.
|
11033 | : SatNavData(SatNavData::GLONASSEphemeris, InsTime(year, month, day, hour, minute, second, UTC)), |
46 | 11033 | tau_c(tau_c), | |
47 | 11033 | toc(refTime), | |
48 | 11033 | tau_n(-m_tau_n), | |
49 | 11033 | gamma_n(gamma_n), | |
50 | 11033 | health(static_cast<bool>(health)), | |
51 | ✗ | PZ90_pos(satPos_x * 1e3, satPos_y * 1e3, satPos_z * 1e3), | |
52 |
1/2✓ Branch 1 taken 11033 times.
✗ Branch 2 not taken.
|
11033 | PZ90_vel(satVel_x * 1e3, satVel_y * 1e3, satVel_z * 1e3), |
53 |
1/2✓ Branch 1 taken 11033 times.
✗ Branch 2 not taken.
|
11033 | PZ90_accelLuniSolar(satAccel_x * 1e3, satAccel_y * 1e3, satAccel_z * 1e3), |
54 |
2/4✓ Branch 2 taken 11033 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 11033 times.
✗ Branch 6 not taken.
|
22066 | frequencyNumber(static_cast<int8_t>(frequencyNumber)) |
55 | 11033 | {} | |
56 | |||
57 | #endif | ||
58 | |||
59 | 962 | Clock::Corrections GLONASSEphemeris::calcClockCorrections(const InsTime& recvTime, double dist, const Frequency& /* freq */) const | |
60 | { | ||
61 | LOG_DATA("Calc Sat Clock corrections at receiver time {}", recvTime.toGPSweekTow()); | ||
62 | LOG_DATA(" toc {} (Time of clock)", toc.toGPSweekTow()); | ||
63 | |||
64 | // Time at transmission | ||
65 |
2/4✓ Branch 2 taken 962 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 962 times.
✗ Branch 6 not taken.
|
962 | InsTime transTime = recvTime - std::chrono::duration<double>(dist / InsConst::C); |
66 | |||
67 | // SV clock time offset [s] | ||
68 |
1/2✓ Branch 1 taken 962 times.
✗ Branch 2 not taken.
|
962 | double dt_sv = -tau_n + gamma_n * static_cast<double>((transTime - toc).count()); |
69 | LOG_DATA(" dt_sv {} [s] (SV clock time offset)", dt_sv); | ||
70 | |||
71 |
2/4✓ Branch 2 taken 962 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 962 times.
✗ Branch 6 not taken.
|
962 | transTime += std::chrono::duration<double>(dt_sv); |
72 | LOG_DATA(" transTime {} (Time at transmission)", transTime.toGPSweekTow()); | ||
73 | |||
74 | 962 | return { .transmitTime = transTime, .bias = dt_sv, .drift = -gamma_n }; | |
75 | } | ||
76 | |||
77 | 2290 | Orbit::PosVelAccel GLONASSEphemeris::calcSatelliteData(const InsTime& transTime, Orbit::Calc calc) const | |
78 | { | ||
79 | LOG_DATA("Calc Sat Position at transmit time {}", transTime.toGPSweekTow()); | ||
80 | LOG_DATA(" toc {} (Time of clock)", toc.toGPSweekTow()); | ||
81 | |||
82 | // Calculates the position and velocity derivative for the satellite position | ||
83 | // y State [x, y, z, v_x, v_y, v_z]^T | ||
84 | // c Constant values needed to calculate the derivatives | ||
85 | // Returns the derivative ∂/∂t [x, y, z, v_x, v_y, v_z]^T | ||
86 | 75183 | auto calcPosVelDerivative = [](const Eigen::Matrix<double, 6, 1>& y, int /* z */, const Eigen::Vector3d& accelLuniSolar, double /* t */ = 0.0) { | |
87 | // 0 1 2 3 4 5 | ||
88 | // ∂/∂t [x, y, z, v_x, v_y, v_z]^T | ||
89 |
2/4✓ Branch 1 taken 75183 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 75183 times.
✗ Branch 5 not taken.
|
75183 | Eigen::Matrix<double, 6, 1> y_dot = Eigen::Matrix<double, 6, 1>::Zero(); |
90 | |||
91 | enum State : uint8_t | ||
92 | { | ||
93 | X, | ||
94 | Y, | ||
95 | Z, | ||
96 | VX, | ||
97 | VY, | ||
98 | VZ | ||
99 | }; | ||
100 | |||
101 |
2/4✓ Branch 1 taken 75183 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 75183 times.
✗ Branch 5 not taken.
|
75183 | double r = y.topRows<3>().norm(); |
102 | |||
103 | 75183 | double omega_ie2 = std::pow(InsConst::GLO::omega_ie, 2); | |
104 | |||
105 | 75183 | double a = 1.5 * InsConst::GLO::J2 * InsConst::GLO::MU * std::pow(InsConst::GLO::a, 2) / std::pow(r, 5); | |
106 | 75183 | double c = -InsConst::GLO::MU / std::pow(r, 3) - a * (1. - 5. * std::pow(y(Z), 2) / std::pow(r, 2)); | |
107 | |||
108 |
3/6✓ Branch 1 taken 75183 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 75183 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 75183 times.
✗ Branch 8 not taken.
|
75183 | y_dot.topRows<3>() = y.bottomRows<3>(); |
109 | 75183 | y_dot(3) = (c + omega_ie2) * y(X) + 2 * InsConst::GLO::omega_ie * y(VY) + accelLuniSolar.x(); | |
110 | 75183 | y_dot(4) = (c + omega_ie2) * y(Y) - 2 * InsConst::GLO::omega_ie * y(VX) + accelLuniSolar.y(); | |
111 | 75183 | y_dot(5) = (c - 2. * a) * y(Z) + accelLuniSolar.z(); | |
112 | |||
113 | 75183 | return y_dot; | |
114 | }; | ||
115 | |||
116 | // State [x, y, z, v_x, v_y, v_z]^T | ||
117 |
1/2✓ Branch 1 taken 2290 times.
✗ Branch 2 not taken.
|
2290 | Eigen::Matrix<double, 6, 1> y; |
118 |
2/4✓ Branch 1 taken 2290 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2290 times.
✗ Branch 5 not taken.
|
2290 | y << PZ90_pos, PZ90_vel; |
119 | |||
120 | // Time to integrate in [s] | ||
121 |
1/2✓ Branch 1 taken 2290 times.
✗ Branch 2 not taken.
|
2290 | double dt = static_cast<double>((transTime - toc).count()); |
122 | LOG_DATA(" dt {} [s] (Time to integrate)", dt); | ||
123 | |||
124 |
2/2✓ Branch 1 taken 18630 times.
✓ Branch 2 taken 2290 times.
|
20920 | while (std::abs(dt) > 1e-9) |
125 | { | ||
126 |
2/2✓ Branch 0 taken 11805 times.
✓ Branch 1 taken 6825 times.
|
18630 | double step = dt > 0 ? _h : -_h; |
127 |
2/2✓ Branch 1 taken 2288 times.
✓ Branch 2 taken 16342 times.
|
18630 | if (std::abs(dt) < _h) |
128 | { | ||
129 | 2288 | step = dt; | |
130 | } | ||
131 | LOG_DATA(" step {:0.2f}, pos {}, vel {}", step, y.topRows<3>().transpose(), y.bottomRows<3>().transpose()); | ||
132 | ; | ||
133 |
1/2✓ Branch 1 taken 18630 times.
✗ Branch 2 not taken.
|
18630 | y = RungeKutta4(y, std::array<int, 4>{}, step, calcPosVelDerivative, PZ90_accelLuniSolar); |
134 | 18630 | dt -= step; | |
135 | } | ||
136 | LOG_DATA(" pos {}, vel {} (end state)", y.topRows<3>().transpose(), y.bottomRows<3>().transpose()); | ||
137 | |||
138 |
2/4✓ Branch 1 taken 2290 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2290 times.
✗ Branch 5 not taken.
|
2290 | Eigen::Vector3d e_pos = Eigen::Vector3d::Zero(); |
139 |
2/4✓ Branch 1 taken 2290 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2290 times.
✗ Branch 5 not taken.
|
2290 | Eigen::Vector3d e_vel = Eigen::Vector3d::Zero(); |
140 |
2/4✓ Branch 1 taken 2290 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2290 times.
✗ Branch 5 not taken.
|
2290 | Eigen::Vector3d e_accel = Eigen::Vector3d::Zero(); |
141 | |||
142 |
1/2✓ Branch 1 taken 2290 times.
✗ Branch 2 not taken.
|
2290 | if (calc & Calc_Position) |
143 | { | ||
144 |
2/4✓ Branch 1 taken 2290 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2290 times.
✗ Branch 5 not taken.
|
2290 | e_pos = y.topRows<3>(); // trafo::pz90toWGS84_pos(y.topRows<3>()); |
145 | // LOG_DATA(" pos (WGS84) {}", e_pos.transpose()); | ||
146 | } | ||
147 |
2/2✓ Branch 1 taken 1328 times.
✓ Branch 2 taken 962 times.
|
2290 | if (calc & Calc_Velocity) |
148 | { | ||
149 |
2/4✓ Branch 1 taken 1328 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1328 times.
✗ Branch 5 not taken.
|
1328 | e_vel = y.bottomRows<3>(); // trafo::pz90toWGS84(y.bottomRows<3>(), y.topRows<3>()); |
150 | // LOG_DATA(" vel (WGS84) {}", e_vel.transpose()); | ||
151 | } | ||
152 |
2/2✓ Branch 1 taken 663 times.
✓ Branch 2 taken 1627 times.
|
2290 | if (calc & Calc_Acceleration) |
153 | { | ||
154 |
1/2✓ Branch 1 taken 663 times.
✗ Branch 2 not taken.
|
663 | Eigen::Matrix<double, 6, 1> y_dot = calcPosVelDerivative(y, 0, PZ90_accelLuniSolar, 0.0); |
155 |
2/4✓ Branch 1 taken 663 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 663 times.
✗ Branch 5 not taken.
|
663 | e_accel = y_dot.bottomRows<3>(); // trafo::pz90toWGS84(y_dot.bottomRows<3>(), y.topRows<3>()); |
156 | // LOG_DATA(" accel (WGS84) {}", e_accel.transpose()); | ||
157 | } | ||
158 | |||
159 | return { .e_pos = e_pos, | ||
160 | .e_vel = e_vel, | ||
161 |
3/6✓ Branch 1 taken 2290 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2290 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2290 times.
✗ Branch 8 not taken.
|
4580 | .e_accel = e_accel }; |
162 | } | ||
163 | |||
164 | 972 | bool GLONASSEphemeris::isHealthy() const | |
165 | { | ||
166 | 972 | return !health; | |
167 | } | ||
168 | |||
169 | ✗ | double GLONASSEphemeris::calcSatellitePositionVariance() const | |
170 | { | ||
171 | ✗ | return 5 * 5; | |
172 | } | ||
173 | |||
174 | } // namespace NAV | ||
175 |