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 "Troposphere.hpp" | ||
10 | |||
11 | #include "internal/gui/widgets/EnumCombo.hpp" | ||
12 | #include "internal/gui/NodeEditorApplication.hpp" | ||
13 | #include "util/Logger.hpp" | ||
14 | |||
15 | #include "Models/Saastamoinen.hpp" | ||
16 | #include "Models/GPT.hpp" | ||
17 | |||
18 | #include "MappingFunctions/Cosecant.hpp" | ||
19 | #include "MappingFunctions/GMF.hpp" | ||
20 | #include "MappingFunctions/NiellMappingFunction.hpp" | ||
21 | #include "Navigation/Transformations/Units.hpp" | ||
22 | |||
23 | namespace NAV | ||
24 | { | ||
25 | |||
26 | ✗ | const char* to_string(TroposphereModel troposphereZhdModel) | |
27 | { | ||
28 | ✗ | switch (troposphereZhdModel) | |
29 | { | ||
30 | ✗ | case TroposphereModel::None: | |
31 | ✗ | return "None"; | |
32 | ✗ | case TroposphereModel::Saastamoinen: | |
33 | ✗ | return "Saastamoinen"; | |
34 | ✗ | case TroposphereModel::GPT2: | |
35 | ✗ | return "GPT2"; | |
36 | ✗ | case TroposphereModel::GPT3: | |
37 | ✗ | return "GPT3"; | |
38 | ✗ | case TroposphereModel::COUNT: | |
39 | ✗ | break; | |
40 | } | ||
41 | ✗ | return ""; | |
42 | } | ||
43 | |||
44 | ✗ | const char* to_string(MappingFunction mappingFunction) | |
45 | { | ||
46 | ✗ | switch (mappingFunction) | |
47 | { | ||
48 | ✗ | case MappingFunction::None: | |
49 | ✗ | return "None"; | |
50 | ✗ | case MappingFunction::Cosecant: | |
51 | ✗ | return "Cosecant(elevation)"; | |
52 | ✗ | case MappingFunction::GMF: | |
53 | ✗ | return "GMF"; | |
54 | ✗ | case MappingFunction::NMF: | |
55 | ✗ | return "NMF"; | |
56 | ✗ | case MappingFunction::VMF_GPT2: | |
57 | ✗ | return "VMF(GPT2)"; | |
58 | ✗ | case MappingFunction::VMF_GPT3: | |
59 | ✗ | return "VMF(GPT3)"; | |
60 | ✗ | case MappingFunction::COUNT: | |
61 | ✗ | break; | |
62 | } | ||
63 | ✗ | return ""; | |
64 | } | ||
65 | |||
66 | namespace | ||
67 | { | ||
68 | |||
69 | ✗ | AtmosphereModels MappingFunctionDefaults(MappingFunction mappingFunction) | |
70 | { | ||
71 | ✗ | switch (mappingFunction) | |
72 | { | ||
73 | ✗ | case MappingFunction::Cosecant: | |
74 | return { .pressureModel = PressureModel::ISA, | ||
75 | .temperatureModel = TemperatureModel::ISA, | ||
76 | ✗ | .waterVaporModel = WaterVaporModel::ISA }; | |
77 | ✗ | case MappingFunction::GMF: | |
78 | return { .pressureModel = PressureModel::ISA, | ||
79 | .temperatureModel = TemperatureModel::ISA, | ||
80 | ✗ | .waterVaporModel = WaterVaporModel::ISA }; | |
81 | ✗ | case MappingFunction::NMF: | |
82 | return { .pressureModel = PressureModel::ISA, | ||
83 | .temperatureModel = TemperatureModel::ISA, | ||
84 | ✗ | .waterVaporModel = WaterVaporModel::ISA }; | |
85 | ✗ | case MappingFunction::VMF_GPT2: | |
86 | return { .pressureModel = PressureModel::GPT2, | ||
87 | .temperatureModel = TemperatureModel::GPT2, | ||
88 | ✗ | .waterVaporModel = WaterVaporModel::GPT2 }; | |
89 | ✗ | case MappingFunction::VMF_GPT3: | |
90 | return { .pressureModel = PressureModel::GPT3, | ||
91 | .temperatureModel = TemperatureModel::GPT3, | ||
92 | ✗ | .waterVaporModel = WaterVaporModel::GPT3 }; | |
93 | ✗ | case MappingFunction::None: | |
94 | case MappingFunction::COUNT: | ||
95 | ✗ | break; | |
96 | } | ||
97 | return { .pressureModel = PressureModel::None, | ||
98 | .temperatureModel = TemperatureModel::None, | ||
99 | ✗ | .waterVaporModel = WaterVaporModel::None }; | |
100 | } | ||
101 | |||
102 | /// @brief Returns the default atmosphere model, mapping function and mapping function atmosphere model for the given troposphere model | ||
103 | /// @param troposphereModel Troposphere model to give the defaults for | ||
104 | /// @return Tuple of <atmosphere model, mapping function, mapping function atmosphere model> | ||
105 | ✗ | std::tuple<AtmosphereModels, MappingFunction, AtmosphereModels> ModelDefaults(TroposphereModel troposphereModel) | |
106 | { | ||
107 | ✗ | switch (troposphereModel) | |
108 | { | ||
109 | ✗ | case TroposphereModel::Saastamoinen: | |
110 | ✗ | return { AtmosphereModels{ .pressureModel = PressureModel::ISA, | |
111 | .temperatureModel = TemperatureModel::ISA, | ||
112 | .waterVaporModel = WaterVaporModel::ISA }, | ||
113 | ✗ | MappingFunction::GMF, | |
114 | ✗ | MappingFunctionDefaults(MappingFunction::GMF) }; | |
115 | ✗ | case TroposphereModel::GPT2: | |
116 | ✗ | return { AtmosphereModels{ .pressureModel = PressureModel::GPT2, | |
117 | .temperatureModel = TemperatureModel::GPT2, | ||
118 | .waterVaporModel = WaterVaporModel::GPT2 }, | ||
119 | ✗ | MappingFunction::VMF_GPT2, | |
120 | ✗ | MappingFunctionDefaults(MappingFunction::VMF_GPT2) }; | |
121 | ✗ | case TroposphereModel::GPT3: | |
122 | ✗ | return { AtmosphereModels{ .pressureModel = PressureModel::GPT3, | |
123 | .temperatureModel = TemperatureModel::GPT3, | ||
124 | .waterVaporModel = WaterVaporModel::GPT3 }, | ||
125 | ✗ | MappingFunction::VMF_GPT3, | |
126 | ✗ | MappingFunctionDefaults(MappingFunction::VMF_GPT3) }; | |
127 | ✗ | case TroposphereModel::None: | |
128 | case TroposphereModel::COUNT: | ||
129 | ✗ | break; | |
130 | } | ||
131 | |||
132 | ✗ | return { AtmosphereModels{ .pressureModel = PressureModel::None, | |
133 | .temperatureModel = TemperatureModel::None, | ||
134 | .waterVaporModel = WaterVaporModel::None }, | ||
135 | ✗ | MappingFunction::None, | |
136 | ✗ | MappingFunctionDefaults(MappingFunction::None) }; | |
137 | } | ||
138 | |||
139 | } // namespace | ||
140 | |||
141 | ✗ | bool ComboTroposphereModel(const char* label, TroposphereModelSelection& troposphereModelSelection, float width) | |
142 | { | ||
143 | ✗ | bool changed = false; | |
144 | |||
145 | ✗ | const float BUTTON_WIDTH = 25.0F * gui::NodeEditorApplication::windowFontRatio(); | |
146 | |||
147 | ✗ | std::string mapFuncPreview; | |
148 | ✗ | if (troposphereModelSelection.zwdMappingFunction.first != std::get<1>(ModelDefaults(troposphereModelSelection.zwdModel.first)) | |
149 | ✗ | || troposphereModelSelection.zhdMappingFunction.first != std::get<1>(ModelDefaults(troposphereModelSelection.zhdModel.first))) | |
150 | { | ||
151 | ✗ | mapFuncPreview = fmt::format(" + {}", troposphereModelSelection.zhdMappingFunction.first); | |
152 | |||
153 | ✗ | if (troposphereModelSelection.zhdMappingFunction.first != troposphereModelSelection.zwdMappingFunction.first) | |
154 | { | ||
155 | ✗ | mapFuncPreview += fmt::format(" | {}", troposphereModelSelection.zwdMappingFunction.first); | |
156 | } | ||
157 | } | ||
158 | |||
159 | ✗ | ImGui::SetNextItemWidth(width - BUTTON_WIDTH - 2 * ImGui::GetStyle().ItemInnerSpacing.x); | |
160 | ✗ | if (gui::widgets::EnumCombo(fmt::format("##{}", label).c_str(), | |
161 | ✗ | troposphereModelSelection.zhdModel.first, | |
162 | ✗ | troposphereModelSelection.zwdModel.first, | |
163 | mapFuncPreview.c_str())) | ||
164 | { | ||
165 | ✗ | std::tie(troposphereModelSelection.zhdModel.second, | |
166 | ✗ | troposphereModelSelection.zhdMappingFunction.first, | |
167 | ✗ | troposphereModelSelection.zhdMappingFunction.second) = ModelDefaults(troposphereModelSelection.zhdModel.first); | |
168 | ✗ | std::tie(troposphereModelSelection.zwdModel.second, | |
169 | ✗ | troposphereModelSelection.zwdMappingFunction.first, | |
170 | ✗ | troposphereModelSelection.zwdMappingFunction.second) = ModelDefaults(troposphereModelSelection.zwdModel.first); | |
171 | ✗ | changed = true; | |
172 | } | ||
173 | ✗ | ImGui::SameLine(); | |
174 | ✗ | if (ImGui::Button(fmt::format("...##{}", label).c_str(), ImVec2(BUTTON_WIDTH, 0))) | |
175 | { | ||
176 | ✗ | ImGui::OpenPopup(fmt::format("{} Popup", label).c_str()); | |
177 | } | ||
178 | ✗ | if (ImGui::BeginPopup(fmt::format("{} Popup", label).c_str())) | |
179 | { | ||
180 | ✗ | const float ATMOSPHERE_COMBO_WIDTH = 95.0F * gui::NodeEditorApplication::windowFontRatio(); | |
181 | ✗ | if (ImGui::BeginTable(fmt::format("{} Table", label).c_str(), 5)) | |
182 | { | ||
183 | ✗ | ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed); | |
184 | ✗ | ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed); | |
185 | ✗ | ImGui::TableSetupColumn("Pressure", ImGuiTableColumnFlags_WidthFixed); | |
186 | ✗ | ImGui::TableSetupColumn("Temperature", ImGuiTableColumnFlags_WidthFixed); | |
187 | ✗ | ImGui::TableSetupColumn("Water vapor", ImGuiTableColumnFlags_WidthFixed); | |
188 | ✗ | ImGui::TableHeadersRow(); | |
189 | |||
190 | ✗ | ImGui::TableNextColumn(); | |
191 | ✗ | ImGui::TextUnformatted("ZHD model"); | |
192 | ✗ | ImGui::TableNextColumn(); | |
193 | ✗ | ImGui::SetNextItemWidth(width); | |
194 | ✗ | if (gui::widgets::EnumCombo(fmt::format("##{} ZHD - Combo", label).c_str(), troposphereModelSelection.zhdModel.first)) | |
195 | { | ||
196 | ✗ | std::tie(troposphereModelSelection.zhdModel.second, | |
197 | ✗ | troposphereModelSelection.zhdMappingFunction.first, | |
198 | ✗ | troposphereModelSelection.zhdMappingFunction.second) = ModelDefaults(troposphereModelSelection.zhdModel.first); | |
199 | ✗ | changed = true; | |
200 | } | ||
201 | ✗ | if (troposphereModelSelection.zhdModel.first == TroposphereModel::None) { ImGui::BeginDisabled(); } | |
202 | ✗ | ImGui::TableNextColumn(); | |
203 | ✗ | ImGui::SetNextItemWidth(ATMOSPHERE_COMBO_WIDTH); | |
204 | ✗ | changed |= ComboPressureModel(fmt::format("##{} ZHD - Pressure", label).c_str(), troposphereModelSelection.zhdModel.second.pressureModel); | |
205 | ✗ | ImGui::TableNextColumn(); | |
206 | ✗ | ImGui::SetNextItemWidth(ATMOSPHERE_COMBO_WIDTH); | |
207 | ✗ | changed |= ComboTemperatureModel(fmt::format("##{} ZHD - Temperature", label).c_str(), troposphereModelSelection.zhdModel.second.temperatureModel); | |
208 | ✗ | ImGui::TableNextColumn(); | |
209 | ✗ | ImGui::SetNextItemWidth(ATMOSPHERE_COMBO_WIDTH); | |
210 | ✗ | changed |= ComboWaterVaporModel(fmt::format("##{} ZHD - Water vapor", label).c_str(), troposphereModelSelection.zhdModel.second.waterVaporModel); | |
211 | ✗ | if (troposphereModelSelection.zhdModel.first == TroposphereModel::None) { ImGui::EndDisabled(); } | |
212 | |||
213 | ✗ | ImGui::TableNextColumn(); | |
214 | ✗ | ImGui::TextUnformatted("ZWD model"); | |
215 | ✗ | ImGui::TableNextColumn(); | |
216 | ✗ | ImGui::SetNextItemWidth(width); | |
217 | ✗ | if (gui::widgets::EnumCombo(fmt::format("##{} ZWD - Combo", label).c_str(), troposphereModelSelection.zwdModel.first)) | |
218 | { | ||
219 | ✗ | std::tie(troposphereModelSelection.zwdModel.second, | |
220 | ✗ | troposphereModelSelection.zwdMappingFunction.first, | |
221 | ✗ | troposphereModelSelection.zwdMappingFunction.second) = ModelDefaults(troposphereModelSelection.zwdModel.first); | |
222 | ✗ | changed = true; | |
223 | } | ||
224 | ✗ | if (troposphereModelSelection.zwdModel.first == TroposphereModel::None) { ImGui::BeginDisabled(); } | |
225 | ✗ | ImGui::TableNextColumn(); | |
226 | ✗ | ImGui::SetNextItemWidth(ATMOSPHERE_COMBO_WIDTH); | |
227 | ✗ | changed |= ComboPressureModel(fmt::format("##{} ZWD - Pressure", label).c_str(), troposphereModelSelection.zwdModel.second.pressureModel); | |
228 | ✗ | ImGui::TableNextColumn(); | |
229 | ✗ | ImGui::SetNextItemWidth(ATMOSPHERE_COMBO_WIDTH); | |
230 | ✗ | changed |= ComboTemperatureModel(fmt::format("##{} ZWD - Temperature", label).c_str(), troposphereModelSelection.zwdModel.second.temperatureModel); | |
231 | ✗ | ImGui::TableNextColumn(); | |
232 | ✗ | ImGui::SetNextItemWidth(ATMOSPHERE_COMBO_WIDTH); | |
233 | ✗ | changed |= ComboWaterVaporModel(fmt::format("##{} ZWD - Water vapor", label).c_str(), troposphereModelSelection.zwdModel.second.waterVaporModel); | |
234 | ✗ | if (troposphereModelSelection.zwdModel.first == TroposphereModel::None) { ImGui::EndDisabled(); } | |
235 | |||
236 | ✗ | if (troposphereModelSelection.zhdModel.first == TroposphereModel::None) { ImGui::BeginDisabled(); } | |
237 | ✗ | ImGui::TableNextColumn(); | |
238 | ✗ | ImGui::TextUnformatted("Mapping function ZHD"); | |
239 | ✗ | ImGui::TableNextColumn(); | |
240 | ✗ | ImGui::SetNextItemWidth(width); | |
241 | ✗ | if (gui::widgets::EnumCombo(fmt::format("##{} MapZHD - Combo", label).c_str(), troposphereModelSelection.zhdMappingFunction.first)) | |
242 | { | ||
243 | ✗ | troposphereModelSelection.zhdMappingFunction.second = MappingFunctionDefaults(troposphereModelSelection.zhdMappingFunction.first); | |
244 | ✗ | changed = true; | |
245 | } | ||
246 | ✗ | if (troposphereModelSelection.zhdModel.first != TroposphereModel::None | |
247 | ✗ | && troposphereModelSelection.zhdMappingFunction.first == MappingFunction::None) { ImGui::BeginDisabled(); } | |
248 | ✗ | ImGui::TableNextColumn(); | |
249 | ✗ | ImGui::SetNextItemWidth(ATMOSPHERE_COMBO_WIDTH); | |
250 | ✗ | changed |= ComboPressureModel(fmt::format("##{} MapZHD - Pressure", label).c_str(), troposphereModelSelection.zhdMappingFunction.second.pressureModel); | |
251 | ✗ | ImGui::TableNextColumn(); | |
252 | ✗ | ImGui::SetNextItemWidth(ATMOSPHERE_COMBO_WIDTH); | |
253 | ✗ | changed |= ComboTemperatureModel(fmt::format("##{} MapZHD - Temperature", label).c_str(), troposphereModelSelection.zhdMappingFunction.second.temperatureModel); | |
254 | ✗ | ImGui::TableNextColumn(); | |
255 | ✗ | ImGui::SetNextItemWidth(ATMOSPHERE_COMBO_WIDTH); | |
256 | ✗ | changed |= ComboWaterVaporModel(fmt::format("##{} MapZHD - Water vapor", label).c_str(), troposphereModelSelection.zhdMappingFunction.second.waterVaporModel); | |
257 | ✗ | if (troposphereModelSelection.zhdModel.first == TroposphereModel::None | |
258 | ✗ | || troposphereModelSelection.zhdMappingFunction.first == MappingFunction::None) { ImGui::EndDisabled(); } | |
259 | |||
260 | ✗ | if (troposphereModelSelection.zwdModel.first == TroposphereModel::None) { ImGui::BeginDisabled(); } | |
261 | ✗ | ImGui::TableNextColumn(); | |
262 | ✗ | ImGui::TextUnformatted("Mapping function ZWD"); | |
263 | ✗ | ImGui::TableNextColumn(); | |
264 | ✗ | ImGui::SetNextItemWidth(width); | |
265 | ✗ | if (gui::widgets::EnumCombo(fmt::format("##{} MapZWD - Combo", label).c_str(), troposphereModelSelection.zwdMappingFunction.first)) | |
266 | { | ||
267 | ✗ | troposphereModelSelection.zwdMappingFunction.second = MappingFunctionDefaults(troposphereModelSelection.zwdMappingFunction.first); | |
268 | ✗ | changed = true; | |
269 | } | ||
270 | ✗ | if (troposphereModelSelection.zwdModel.first != TroposphereModel::None | |
271 | ✗ | && troposphereModelSelection.zwdMappingFunction.first == MappingFunction::None) { ImGui::BeginDisabled(); } | |
272 | ✗ | ImGui::TableNextColumn(); | |
273 | ✗ | ImGui::SetNextItemWidth(ATMOSPHERE_COMBO_WIDTH); | |
274 | ✗ | changed |= ComboPressureModel(fmt::format("##{} MapZWD - Pressure", label).c_str(), troposphereModelSelection.zwdMappingFunction.second.pressureModel); | |
275 | ✗ | ImGui::TableNextColumn(); | |
276 | ✗ | ImGui::SetNextItemWidth(ATMOSPHERE_COMBO_WIDTH); | |
277 | ✗ | changed |= ComboTemperatureModel(fmt::format("##{} MapZWD - Temperature", label).c_str(), troposphereModelSelection.zwdMappingFunction.second.temperatureModel); | |
278 | ✗ | ImGui::TableNextColumn(); | |
279 | ✗ | ImGui::SetNextItemWidth(ATMOSPHERE_COMBO_WIDTH); | |
280 | ✗ | changed |= ComboWaterVaporModel(fmt::format("##{} MapZWD - Water vapor", label).c_str(), troposphereModelSelection.zwdMappingFunction.second.waterVaporModel); | |
281 | ✗ | if (troposphereModelSelection.zwdModel.first == TroposphereModel::None | |
282 | ✗ | || troposphereModelSelection.zwdMappingFunction.first == MappingFunction::None) { ImGui::EndDisabled(); } | |
283 | |||
284 | ✗ | ImGui::EndTable(); | |
285 | } | ||
286 | |||
287 | ✗ | ImGui::EndPopup(); | |
288 | } | ||
289 | |||
290 | ✗ | ImGui::SameLine(0.0F, ImGui::GetStyle().ItemInnerSpacing.x); | |
291 | ✗ | std::string labelStr = label; | |
292 | ✗ | ImGui::TextUnformatted(labelStr.substr(0, labelStr.find('#')).c_str()); | |
293 | |||
294 | ✗ | return changed; | |
295 | ✗ | } | |
296 | |||
297 | 41798 | ZenithDelay calcTroposphericDelayAndMapping(const InsTime& insTime, const Eigen::Vector3d& lla_pos, double elevation, double /* azimuth */, | |
298 | const TroposphereModelSelection& troposphereModels, [[maybe_unused]] const std::string& nameId) | ||
299 | { | ||
300 |
2/2✓ Branch 0 taken 19413 times.
✓ Branch 1 taken 22385 times.
|
41798 | if (troposphereModels.zhdModel.first == TroposphereModel::None |
301 |
1/2✓ Branch 0 taken 19413 times.
✗ Branch 1 not taken.
|
19413 | && troposphereModels.zwdModel.first == TroposphereModel::None) { return {}; } |
302 | |||
303 |
9/12✓ Branch 1 taken 22385 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 22237 times.
✓ Branch 4 taken 148 times.
✓ Branch 6 taken 22237 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 21941 times.
✓ Branch 9 taken 296 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 21941 times.
✓ Branch 13 taken 444 times.
✓ Branch 14 taken 21941 times.
|
22385 | if (lla_pos(2) < -1000 || lla_pos(2) > 1e4 || std::isnan(elevation)) |
304 | { | ||
305 | LOG_TRACE("{}: Not calculating tropospheric delay, due to altitude being invalid: {}m", nameId, lla_pos(2)); | ||
306 | 444 | return {}; | |
307 | } | ||
308 | |||
309 | enum : uint8_t | ||
310 | { | ||
311 | ZHD, | ||
312 | ZWD, | ||
313 | ZHDMapFunc, | ||
314 | ZWDMapFunc, | ||
315 | COUNT, | ||
316 | }; | ||
317 | |||
318 | const std::array<std::reference_wrapper<const AtmosphereModels>, COUNT> atmosphereModels = { | ||
319 | 21941 | troposphereModels.zhdModel.second, | |
320 | 21941 | troposphereModels.zwdModel.second, | |
321 | 21941 | troposphereModels.zhdMappingFunction.second, | |
322 | 21941 | troposphereModels.zwdMappingFunction.second, | |
323 | 21941 | }; | |
324 | 21941 | std::array<double, COUNT> pressure{}; // Total barometric pressure in [millibar] | |
325 | 21941 | std::array<double, COUNT> temperature{}; // Absolute temperature in [K] | |
326 | 21941 | std::array<double, COUNT> waterVapor{}; // Partial pressure of water vapour in [hPa] | |
327 | |||
328 | 21941 | GPT2output gpt2outputs; | |
329 | 21941 | GPT3output gpt3outputs; | |
330 | // UTC->GPST | ||
331 |
2/4✓ Branch 1 taken 21941 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 21941 times.
✗ Branch 6 not taken.
|
21941 | auto epoch_temp = InsTime(insTime) + std::chrono::duration<long double>(insTime.leapGps2UTC()); |
332 |
2/4✓ Branch 2 taken 21941 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 21941 times.
✗ Branch 7 not taken.
|
21941 | double mjd = static_cast<double>(epoch_temp.toMJD().mjd_day) + static_cast<double>(epoch_temp.toMJD().mjd_frac); |
333 | |||
334 | 43882 | if (troposphereModels.zhdModel.first == TroposphereModel::GPT2 | |
335 |
1/2✓ Branch 0 taken 21941 times.
✗ Branch 1 not taken.
|
21941 | || troposphereModels.zwdModel.first == TroposphereModel::GPT2 |
336 |
1/2✓ Branch 0 taken 21941 times.
✗ Branch 1 not taken.
|
21941 | || troposphereModels.zhdMappingFunction.first == MappingFunction::VMF_GPT2 |
337 |
1/2✓ Branch 0 taken 21941 times.
✗ Branch 1 not taken.
|
21941 | || troposphereModels.zwdMappingFunction.first == MappingFunction::VMF_GPT2 |
338 |
4/8✓ Branch 0 taken 21941 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 21941 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 21941 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 21941 times.
|
43882 | || std::ranges::any_of(atmosphereModels, |
339 | 87764 | [](const auto& model) { return model.get().pressureModel == PressureModel::GPT2 | |
340 |
1/2✓ Branch 2 taken 87764 times.
✗ Branch 3 not taken.
|
175528 | || model.get().temperatureModel == TemperatureModel::GPT2 |
341 |
2/4✓ Branch 0 taken 87764 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 87764 times.
|
175528 | || model.get().waterVaporModel == WaterVaporModel::GPT2; })) |
342 | { | ||
343 | LOG_DATA("{}: Calculating GPT2 parameters", nameId); | ||
344 | ✗ | gpt2outputs = GPT2_param(mjd, lla_pos); | |
345 | } | ||
346 | |||
347 | 43882 | if (troposphereModels.zhdModel.first == TroposphereModel::GPT3 | |
348 |
1/2✓ Branch 0 taken 21941 times.
✗ Branch 1 not taken.
|
21941 | || troposphereModels.zwdModel.first == TroposphereModel::GPT3 |
349 |
1/2✓ Branch 0 taken 21941 times.
✗ Branch 1 not taken.
|
21941 | || troposphereModels.zhdMappingFunction.first == MappingFunction::VMF_GPT3 |
350 |
1/2✓ Branch 0 taken 21941 times.
✗ Branch 1 not taken.
|
21941 | || troposphereModels.zwdMappingFunction.first == MappingFunction::VMF_GPT3 |
351 |
4/8✓ Branch 0 taken 21941 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 21941 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 21941 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 21941 times.
|
43882 | || std::ranges::any_of(atmosphereModels, |
352 | 87764 | [](const auto& model) { return model.get().pressureModel == PressureModel::GPT3 | |
353 |
1/2✓ Branch 2 taken 87764 times.
✗ Branch 3 not taken.
|
175528 | || model.get().temperatureModel == TemperatureModel::GPT3 |
354 |
2/4✓ Branch 0 taken 87764 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 87764 times.
|
175528 | || model.get().waterVaporModel == WaterVaporModel::GPT3; })) |
355 | { | ||
356 | LOG_DATA("{}: Calculating GPT3 parameters", nameId); | ||
357 | ✗ | gpt3outputs = GPT3_param(mjd, lla_pos); | |
358 | } | ||
359 | |||
360 | LOG_DATA("{}: Calculating Atmosphere parameters ZHD=({},{}) ZWD=({},{}) [el={}°, pos={} {} {}]", nameId, | ||
361 | troposphereModels.zhdModel.first, troposphereModels.zhdMappingFunction.first, | ||
362 | troposphereModels.zwdModel.first, troposphereModels.zwdMappingFunction.first, | ||
363 | rad2deg(elevation), rad2deg(lla_pos(0)), rad2deg(lla_pos(1)), lla_pos(2)); | ||
364 |
2/2✓ Branch 0 taken 87764 times.
✓ Branch 1 taken 21941 times.
|
109705 | for (size_t i = 0; i < COUNT; i++) |
365 | { | ||
366 | 87764 | bool alreadyCalculated = false; | |
367 |
2/2✓ Branch 0 taken 65823 times.
✓ Branch 1 taken 21941 times.
|
87764 | for (size_t j = 0; j < i; j++) |
368 | { | ||
369 |
3/6✓ Branch 1 taken 65823 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 65823 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 65823 times.
✗ Branch 9 not taken.
|
65823 | if (atmosphereModels.at(i).get().pressureModel == atmosphereModels.at(j).get().pressureModel) |
370 | { | ||
371 |
2/4✓ Branch 1 taken 65823 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 65823 times.
✗ Branch 5 not taken.
|
65823 | pressure.at(i) = pressure.at(j); |
372 | 65823 | alreadyCalculated = true; | |
373 | 65823 | break; | |
374 | } | ||
375 | } | ||
376 | |||
377 |
2/2✓ Branch 0 taken 21941 times.
✓ Branch 1 taken 65823 times.
|
87764 | if (!alreadyCalculated) |
378 | { | ||
379 |
2/4✓ Branch 1 taken 21941 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 21941 times.
|
21941 | if (atmosphereModels.at(i).get().pressureModel == PressureModel::GPT2) |
380 | { | ||
381 | ✗ | pressure.at(i) = gpt2outputs.p; | |
382 | } | ||
383 |
2/4✓ Branch 1 taken 21941 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 21941 times.
|
21941 | else if (atmosphereModels.at(i).get().pressureModel == PressureModel::GPT3) |
384 | { | ||
385 | ✗ | pressure.at(i) = gpt3outputs.p; | |
386 | } | ||
387 | else | ||
388 | { | ||
389 |
4/8✓ Branch 1 taken 21941 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 21941 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 21941 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 21941 times.
✗ Branch 12 not taken.
|
21941 | pressure.at(i) = calcTotalPressure(lla_pos(2), atmosphereModels.at(i).get().pressureModel); |
390 | } | ||
391 | } | ||
392 | LOG_DATA("{}: [{}]: {} - p {} [millibar] (Total barometric pressure) - value {}", nameId, i, atmosphereModels.at(i).get().pressureModel, | ||
393 | pressure.at(i), alreadyCalculated ? "reused" : "calculated"); | ||
394 | |||
395 | 87764 | alreadyCalculated = false; | |
396 |
2/2✓ Branch 0 taken 65823 times.
✓ Branch 1 taken 21941 times.
|
87764 | for (size_t j = 0; j < i; j++) |
397 | { | ||
398 |
3/6✓ Branch 1 taken 65823 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 65823 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 65823 times.
✗ Branch 10 not taken.
|
65823 | if (atmosphereModels.at(i).get().temperatureModel == atmosphereModels.at(j).get().temperatureModel) |
399 | { | ||
400 |
2/4✓ Branch 1 taken 65823 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 65823 times.
✗ Branch 5 not taken.
|
65823 | temperature.at(i) = temperature.at(j); |
401 | 65823 | alreadyCalculated = true; | |
402 | 65823 | break; | |
403 | } | ||
404 | } | ||
405 | |||
406 |
2/2✓ Branch 0 taken 21941 times.
✓ Branch 1 taken 65823 times.
|
87764 | if (!alreadyCalculated) |
407 | { | ||
408 |
2/4✓ Branch 1 taken 21941 times.
✗ Branch 2 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 21941 times.
|
21941 | if (atmosphereModels.at(i).get().temperatureModel == TemperatureModel::GPT2) |
409 | { | ||
410 | ✗ | temperature.at(i) = gpt2outputs.T; | |
411 | } | ||
412 |
2/4✓ Branch 1 taken 21941 times.
✗ Branch 2 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 21941 times.
|
21941 | else if (atmosphereModels.at(i).get().temperatureModel == TemperatureModel::GPT3) |
413 | { | ||
414 | ✗ | temperature.at(i) = gpt3outputs.T; | |
415 | } | ||
416 | else | ||
417 | { | ||
418 |
4/8✓ Branch 1 taken 21941 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 21941 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 21941 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 21941 times.
✗ Branch 12 not taken.
|
21941 | temperature.at(i) = atmosphereModels.at(i).get().temperatureModel.calcAbsoluteTemperature(lla_pos(2)); |
419 | } | ||
420 | } | ||
421 | LOG_DATA("{}: [{}]: {} - T {} [K] (Absolute temperature) - value {}", nameId, i, atmosphereModels.at(i).get().temperatureModel, | ||
422 | temperature.at(i), alreadyCalculated ? "reused" : "calculated"); | ||
423 | |||
424 | 87764 | alreadyCalculated = false; | |
425 |
2/2✓ Branch 0 taken 65823 times.
✓ Branch 1 taken 21941 times.
|
87764 | for (size_t j = 0; j < i; j++) |
426 | { | ||
427 |
3/6✓ Branch 1 taken 65823 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 65823 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 65823 times.
✗ Branch 9 not taken.
|
65823 | if (atmosphereModels.at(i).get().waterVaporModel == atmosphereModels.at(j).get().waterVaporModel) |
428 | { | ||
429 |
2/4✓ Branch 1 taken 65823 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 65823 times.
✗ Branch 5 not taken.
|
65823 | waterVapor.at(i) = waterVapor.at(j); |
430 | 65823 | alreadyCalculated = true; | |
431 | 65823 | break; | |
432 | } | ||
433 | } | ||
434 | |||
435 | // Partial pressure of water vapour in [millibar] - RTKLIB ch. E.5, p. 149 specifies 70% | ||
436 |
2/2✓ Branch 0 taken 21941 times.
✓ Branch 1 taken 65823 times.
|
87764 | if (!alreadyCalculated) |
437 | { | ||
438 |
2/4✓ Branch 1 taken 21941 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 21941 times.
|
21941 | if (atmosphereModels.at(i).get().waterVaporModel == WaterVaporModel::GPT2) |
439 | { | ||
440 | ✗ | waterVapor.at(i) = gpt2outputs.e; | |
441 | } | ||
442 |
2/4✓ Branch 1 taken 21941 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 21941 times.
|
21941 | else if (atmosphereModels.at(i).get().waterVaporModel == WaterVaporModel::GPT3) |
443 | { | ||
444 | ✗ | waterVapor.at(i) = gpt3outputs.e; | |
445 | } | ||
446 | else | ||
447 | { | ||
448 |
4/8✓ Branch 1 taken 21941 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 21941 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 21941 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 21941 times.
✗ Branch 12 not taken.
|
21941 | waterVapor.at(i) = calcWaterVaporPartialPressure(temperature.at(i), 0.7, atmosphereModels.at(i).get().waterVaporModel); |
449 | } | ||
450 | } | ||
451 | LOG_DATA("{}: [{}]: {} - e {} [millibar] (Partial pressure of water vapour) - value {}", nameId, i, | ||
452 | atmosphereModels.at(i).get().waterVaporModel, waterVapor.at(i), alreadyCalculated ? "reused" : "calculated"); | ||
453 | } | ||
454 | |||
455 | 21941 | double zhd = 0.0; | |
456 |
1/3✓ Branch 0 taken 21941 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
|
21941 | switch (troposphereModels.zhdModel.first) |
457 | { | ||
458 | 21941 | case TroposphereModel::Saastamoinen: | |
459 | case TroposphereModel::GPT2: | ||
460 | case TroposphereModel::GPT3: | ||
461 |
1/2✓ Branch 2 taken 21941 times.
✗ Branch 3 not taken.
|
21941 | zhd = calcZHD_Saastamoinen(lla_pos, pressure[ZHD]); |
462 | 21941 | break; | |
463 | ✗ | case TroposphereModel::None: | |
464 | case TroposphereModel::COUNT: | ||
465 | ✗ | break; | |
466 | } | ||
467 | |||
468 | 21941 | double zwd = 0.0; | |
469 |
1/5✓ Branch 0 taken 21941 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
21941 | switch (troposphereModels.zwdModel.first) |
470 | { | ||
471 | 21941 | case TroposphereModel::Saastamoinen: | |
472 |
1/2✓ Branch 3 taken 21941 times.
✗ Branch 4 not taken.
|
21941 | zwd = calcZWD_Saastamoinen(temperature[ZWD], waterVapor[ZWD]); |
473 | 21941 | break; | |
474 | ✗ | case TroposphereModel::GPT2: | |
475 | ✗ | zwd = asknewet(waterVapor[ZWD], gpt2outputs.Tm, gpt2outputs.la); | |
476 | ✗ | break; | |
477 | ✗ | case TroposphereModel::GPT3: | |
478 | ✗ | zwd = asknewet(waterVapor[ZWD], gpt3outputs.Tm, gpt3outputs.la); | |
479 | ✗ | break; | |
480 | ✗ | case TroposphereModel::None: | |
481 | case TroposphereModel::COUNT: | ||
482 | ✗ | break; | |
483 | } | ||
484 | |||
485 | 21941 | double zhdMappingFactor = 1.0; | |
486 |
2/7✓ Branch 0 taken 15556 times.
✓ Branch 1 taken 6385 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
21941 | switch (troposphereModels.zhdMappingFunction.first) |
487 | { | ||
488 | 15556 | case MappingFunction::Cosecant: | |
489 |
1/2✓ Branch 1 taken 15556 times.
✗ Branch 2 not taken.
|
15556 | zhdMappingFactor = calcTropoMapFunc_cosecant(elevation); |
490 | 15556 | break; | |
491 | 6385 | case MappingFunction::GMF: | |
492 |
1/2✓ Branch 1 taken 6385 times.
✗ Branch 2 not taken.
|
6385 | zhdMappingFactor = calcTropoMapFunc_GMFH(mjd, lla_pos, elevation); |
493 | 6385 | break; | |
494 | ✗ | case MappingFunction::NMF: | |
495 | ✗ | zhdMappingFactor = calcTropoMapFunc_NMFH(insTime, lla_pos, elevation); | |
496 | ✗ | break; | |
497 | ✗ | case MappingFunction::VMF_GPT2: | |
498 | ✗ | zhdMappingFactor = vmf1h(gpt2outputs.ah, mjd, lla_pos(0), lla_pos(2), M_PI / 2.0 - elevation); | |
499 | ✗ | break; | |
500 | ✗ | case MappingFunction::VMF_GPT3: | |
501 | ✗ | zhdMappingFactor = vmf1h(gpt3outputs.ah, mjd, lla_pos(0), lla_pos(2), M_PI / 2.0 - elevation); | |
502 | ✗ | break; | |
503 | ✗ | case MappingFunction::None: | |
504 | case MappingFunction::COUNT: | ||
505 | ✗ | break; | |
506 | } | ||
507 | |||
508 | 21941 | double zwdMappingFactor = 1.0; | |
509 |
2/7✓ Branch 0 taken 15556 times.
✓ Branch 1 taken 6385 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
21941 | switch (troposphereModels.zwdMappingFunction.first) |
510 | { | ||
511 | 15556 | case MappingFunction::Cosecant: | |
512 |
1/2✓ Branch 1 taken 15556 times.
✗ Branch 2 not taken.
|
15556 | zwdMappingFactor = calcTropoMapFunc_cosecant(elevation); |
513 | 15556 | break; | |
514 | 6385 | case MappingFunction::GMF: | |
515 |
1/2✓ Branch 1 taken 6385 times.
✗ Branch 2 not taken.
|
6385 | zwdMappingFactor = calcTropoMapFunc_GMFW(mjd, lla_pos, elevation); |
516 | 6385 | break; | |
517 | ✗ | case MappingFunction::NMF: | |
518 | ✗ | zwdMappingFactor = calcTropoMapFunc_NMFW(lla_pos, elevation); | |
519 | ✗ | break; | |
520 | ✗ | case MappingFunction::VMF_GPT2: | |
521 | ✗ | zwdMappingFactor = vmf1w(gpt2outputs.aw, M_PI / 2.0 - elevation); | |
522 | ✗ | break; | |
523 | ✗ | case MappingFunction::VMF_GPT3: | |
524 | ✗ | zwdMappingFactor = vmf1w(gpt3outputs.aw, M_PI / 2.0 - elevation); | |
525 | ✗ | break; | |
526 | ✗ | case MappingFunction::None: | |
527 | case MappingFunction::COUNT: | ||
528 | ✗ | break; | |
529 | } | ||
530 | LOG_DATA("{}: el = {}, ZHD = {}, ZWD = {}, ZHDMF = {}, ZWDMF = {}", nameId, elevation, zhd, zwd, zhdMappingFactor, zwdMappingFactor); | ||
531 | |||
532 | return { .ZHD = zhd, | ||
533 | .ZWD = zwd, | ||
534 | .zhdMappingFactor = zhdMappingFactor, | ||
535 | 21941 | .zwdMappingFactor = zwdMappingFactor }; | |
536 | } | ||
537 | |||
538 | 41798 | double tropoErrorVar(double dpsr_T, double elevation) | |
539 | { | ||
540 | 41798 | constexpr double ERR_SAAS = 0.3; // Saastamoinen model error std [m] (maximum zenith wet delay - formulas with worst possible values) | |
541 | |||
542 |
2/2✓ Branch 0 taken 21941 times.
✓ Branch 1 taken 19857 times.
|
41798 | return dpsr_T == 0.0 ? 0.0 : std::pow(ERR_SAAS / (std::sin(elevation) + 0.1), 2); |
543 | } | ||
544 | |||
545 | ✗ | void to_json(json& j, const AtmosphereModels& obj) | |
546 | { | ||
547 | ✗ | j = json{ | |
548 | ✗ | { "pressureModel", obj.pressureModel }, | |
549 | ✗ | { "temperatureModel", obj.temperatureModel }, | |
550 | ✗ | { "waterVaporModel", obj.waterVaporModel }, | |
551 | ✗ | }; | |
552 | ✗ | } | |
553 | |||
554 | 32 | void from_json(const json& j, AtmosphereModels& obj) | |
555 | { | ||
556 |
1/2✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
|
32 | if (j.contains("pressureModel")) { j.at("pressureModel").get_to(obj.pressureModel); } |
557 |
3/6✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 32 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 32 times.
|
32 | if (j.contains("temperatureModel") && !j.at("temperatureModel").is_number()) { j.at("temperatureModel").get_to(obj.temperatureModel); } |
558 |
1/2✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
|
32 | if (j.contains("waterVaporModel")) { j.at("waterVaporModel").get_to(obj.waterVaporModel); } |
559 | 32 | } | |
560 | |||
561 | ✗ | void to_json(json& j, const TroposphereModelSelection& obj) | |
562 | { | ||
563 | ✗ | j = json{ | |
564 | ✗ | { "zhdModel", obj.zhdModel }, | |
565 | ✗ | { "zwdModel", obj.zwdModel }, | |
566 | ✗ | { "zhdMappingFunction", obj.zhdMappingFunction }, | |
567 | ✗ | { "zwdMappingFunction", obj.zwdMappingFunction }, | |
568 | ✗ | }; | |
569 | ✗ | } | |
570 | |||
571 | 8 | void from_json(const json& j, TroposphereModelSelection& obj) | |
572 | { | ||
573 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
8 | if (j.contains("zhdModel")) { j.at("zhdModel").get_to(obj.zhdModel); } |
574 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
8 | if (j.contains("zwdModel")) { j.at("zwdModel").get_to(obj.zwdModel); } |
575 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
8 | if (j.contains("zhdMappingFunction")) { j.at("zhdMappingFunction").get_to(obj.zhdMappingFunction); } |
576 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
8 | if (j.contains("zwdMappingFunction")) { j.at("zwdMappingFunction").get_to(obj.zwdMappingFunction); } |
577 | 8 | } | |
578 | |||
579 | } // namespace NAV | ||
580 |