0.4.1
Loading...
Searching...
No Matches
ObservationFilter.hpp
Go to the documentation of this file.
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 ObservationFilter.hpp
10/// @brief Observation Filter
11/// @author T. Topp (topp@ins.uni-stuttgart.de)
12/// @date 2023-12-21
13
14#pragma once
15
16#include <algorithm>
17#include <cstddef>
18#include <cstdint>
19#include <memory>
20#include <unordered_map>
21#include <unordered_set>
22#include <utility>
23#include <array>
24#include <vector>
25
26#include <imgui.h>
29
38
41
42#include "util/Assert.h"
44#include "util/Json.hpp"
45#include "util/Logger.hpp"
46#include <fmt/core.h>
47
48namespace NAV
49{
50
51/// Observation Filter
53{
54 public:
55 /// @brief Constructor
56 /// @param[in] receiverCount Number of receivers
57 /// @param[in] availableObsTypes Available observation types (e.g. SPP does not have Carrier)
58 /// @param[in] neededObsTypes Needed observation types (cannot be unchecked)
59 explicit ObservationFilter(size_t receiverCount,
60 const std::unordered_set<GnssObs::ObservationType>& availableObsTypes = { GnssObs::Pseudorange, GnssObs::Carrier, GnssObs::Doppler },
61 std::unordered_set<GnssObs::ObservationType> neededObsTypes = {})
62 : _snrMask(receiverCount), _availableObsTypes(availableObsTypes), _neededObsTypes(std::move(neededObsTypes)), _usedObsTypes(availableObsTypes)
63 {
64 // Disable Geostationary satellites, as they not working correctly
65 for (const auto& satSys : SatelliteSystem::GetAll())
66 {
67 for (const auto& satNum : satSys.getSatellites())
68 {
69 if (SatId satId(satSys, satNum);
70 satId.isGeo()) { _excludedSatellites.push_back(satId); }
71 }
72 }
73 }
74
75 /// @brief Destructor
76 ~ObservationFilter() = default;
77 /// @brief Copy constructor
78 ObservationFilter(const ObservationFilter& other) = default;
79 /// @brief Move constructor
80 ObservationFilter(ObservationFilter&& other) noexcept = default;
81 /// @brief Copy assignment operator
83 {
84 if (this != &other) // not a self-assignment
85 {
90 _snrMask = other._snrMask;
94 std::vector<GnssObs::ObservationType> obsTypeToRemove;
95 for (const auto& obsType : _usedObsTypes)
96 {
97 if (!_availableObsTypes.contains(obsType)) { obsTypeToRemove.push_back(obsType); }
98 }
99 for (const auto& obsType : obsTypeToRemove)
100 {
101 _usedObsTypes.erase(obsType);
102 }
103 }
104 return *this;
105 }
106 /// @brief Move assignment operator
108 {
109 if (this != &other) // not a self-assignment
110 {
111 _filterFreq = other._filterFreq;
112 _filterCode = other._filterCode;
113 _excludedSatellites = std::move(other._excludedSatellites);
114 _elevationMask = other._elevationMask;
115 _snrMask = std::move(other._snrMask);
116 _sameSnrMaskForAllReceivers = other._sameSnrMaskForAllReceivers;
117 _neededObsTypes = std::move(other._neededObsTypes);
118 _usedObsTypes = std::move(other._usedObsTypes);
119 std::vector<GnssObs::ObservationType> obsTypeToRemove;
120 for (const auto& obsType : _usedObsTypes)
121 {
122 if (!_availableObsTypes.contains(obsType)) { obsTypeToRemove.push_back(obsType); }
123 }
124 for (const auto& obsType : obsTypeToRemove)
125 {
126 _usedObsTypes.erase(obsType);
127 }
128 }
129 return *this;
130 }
131
132 /// @brief Reset the temporary settings
133 void reset()
134 {
136 }
137
138 /// Filtered signals
139 struct Filtered
140 {
141 std::vector<SatSigId> frequencyFilter; ///< Signals excluded because the frequency is not used
142 std::vector<SatSigId> codeFilter; ///< Signals excluded because the code is not used
143 std::vector<SatSigId> excludedSatellites; ///< Signals excluded because the satellite is excluded
144 std::vector<SatSigId> tempExcludedSignal; ///< Signals temporarily excluded
145 std::vector<SatSigId> notAllReceiversObserved; ///< Signals not observed by all receivers
146 std::vector<SatSigId> singleObservation; ///< Only signal for this code/type (relevant for double differences)
147 std::vector<SatSigId> noPseudorangeMeasurement; ///< Signals without pseudorange measurement
148 std::vector<SatSigId> navigationDataMissing; ///< Signals without navigation data
149 std::vector<std::pair<SatSigId, double>> elevationMaskTriggered; ///< Signals triggering the elevation mask. Also includes elevation [rad]
150 std::vector<std::pair<SatSigId, double>> snrMaskTriggered; ///< Signals triggering the SNR mask. Also includes the Carrier-to-Noise density [dBHz]
151 };
152
153 /// @brief Returns a list of satellites and observations filtered by GUI settings & NAV data available & ...)
154 /// @param[in] receiverType Receiver type index to filter
155 /// @param[in] e_posMarker Marker Position in ECEF frame [m]
156 /// @param[in] lla_posMarker Marker Position in LLA frame [rad, rad, m]
157 /// @param[in] gnssObs GNSS observation
158 /// @param[in] gnssNavInfos Collection of navigation data providers
159 /// @param[in] nameId Name and Id of the node used for log messages only
160 /// @param[in] observations List of observations which will be filled. If you have multiple receivers, the observations list will be the same object
161 /// @param[in] filtered Optional Filtered object to get back the filtered signals
162 /// @param[in] ignoreElevationMask Flag wether the elevation mask should be ignored
163 template<typename ReceiverType, typename DerivedPe, typename DerivedPn>
164 void selectObservationsForCalculation(ReceiverType receiverType,
165 const Eigen::MatrixBase<DerivedPe>& e_posMarker,
166 const Eigen::MatrixBase<DerivedPn>& lla_posMarker,
167 const std::shared_ptr<const GnssObs>& gnssObs,
168 const std::vector<const GnssNavInfo*>& gnssNavInfos,
169 Observations& observations,
170 Filtered* filtered,
171 [[maybe_unused]] const std::string& nameId,
172 bool ignoreElevationMask = false)
173 {
174 bool firstReceiver = observations.receivers.empty();
175 observations.receivers.insert(receiverType);
176
177 observations.signals.reserve(gnssObs->data.size());
178
179 for (size_t obsIdx = 0; obsIdx < gnssObs->data.size(); obsIdx++)
180 {
181 const GnssObs::ObservationData& obsData = gnssObs->data.at(obsIdx);
182 SatSigId satSigId = obsData.satSigId;
183 SatId satId = satSigId.toSatId();
184 LOG_DATA("{}: Considering [{}] for receiver {}", nameId, satSigId, receiverType);
185
186 // Decrease the temporary exclude counter
187 if (firstReceiver && _temporarilyExcludedSignalsSatellites.contains(satSigId))
188 {
189 if (_temporarilyExcludedSignalsSatellites.at(satSigId)-- == 0)
190 {
192 }
193 }
194
195 if (!(satSigId.freq() & _filterFreq))
196 {
197 LOG_DATA("{}: [{}] Skipping obs due to GUI frequency filter", nameId, satSigId);
198 if (filtered) { filtered->frequencyFilter.push_back(satSigId); }
199 continue;
200 }
201 if (!(satSigId.code & _filterCode))
202 {
203 LOG_DATA("{}: [{}] Skipping obs due to GUI code filter", nameId, satSigId);
204 if (filtered) { filtered->codeFilter.push_back(satSigId); }
205 continue;
206 }
207 if (std::ranges::find(_excludedSatellites, satId) != _excludedSatellites.end())
208 {
209 LOG_DATA("{}: [{}] Skipping obs due to GUI excluded satellites", nameId, satSigId);
210 if (filtered) { filtered->excludedSatellites.push_back(satSigId); }
211 continue;
212 }
213 if (_temporarilyExcludedSignalsSatellites.contains(satSigId))
214 {
215 LOG_DATA("{}: [{}] Skipping obs because temporarily excluded signal", nameId, satSigId);
216 if (filtered) { filtered->tempExcludedSignal.push_back(satSigId); }
217 continue;
218 }
219
220 if (!obsData.pseudorange)
221 {
222 LOG_DATA("{}: [{}] Skipping obs because no pseudorange measurement (needed for satellite position calculation)", nameId, satSigId);
223 if (filtered) { filtered->noPseudorangeMeasurement.push_back(satSigId); }
224 continue;
225 }
226
227 if (!firstReceiver && !observations.signals.contains(satSigId)) // TODO:
228 {
229 bool signalWithSameFrequencyFound = false;
230 for (const auto& signals : observations.signals)
231 {
232 if (signals.first.toSatId() == satId && signals.first.freq() == satSigId.freq() // e.g. Rover has [G5Q], but Base has [G5X]
233 && signals.second.recvObs.size() != observations.receivers.size()) // But not: Rover has [G5Q], but Base has [G5Q] and [G5X]
234 {
235 LOG_DATA("{}: [{}] Not observed by all receivers, but other receivers have [{}]. Treating as such.",
236 nameId, satSigId, signals.first);
237 satSigId = signals.first;
238 satId = satSigId.toSatId();
239 signalWithSameFrequencyFound = true;
240 break;
241 }
242 }
243 if (!signalWithSameFrequencyFound)
244 {
245 LOG_DATA("{}: [{}] Skipping obs because not observed by all receivers", nameId, satSigId);
246 if (filtered) { filtered->notAllReceiversObserved.push_back((satSigId)); }
247 continue;
248 }
249 }
250
251 std::shared_ptr<NAV::SatNavData> satNavData = nullptr;
252 for (const auto* gnssNavInfo : gnssNavInfos)
253 {
254 auto satNav = gnssNavInfo->searchNavigationData(satId, gnssObs->insTime);
255 if (satNav && satNav->isHealthy())
256 {
257 satNavData = satNav;
258 break;
259 }
260 }
261 if (satNavData == nullptr)
262 {
263 LOG_DATA("{}: [{}] Skipping obs because no navigation data available to calculaten the satellite position", nameId, satSigId);
264 if (filtered) { filtered->navigationDataMissing.push_back(satSigId); }
265 continue;
266 }
267
268 int8_t freqNum = -128;
269 if (satId.satSys == GLO)
270 {
271 if (auto gloSatNavData = std::dynamic_pointer_cast<GLONASSEphemeris>(satNavData))
272 {
273 freqNum = gloSatNavData->frequencyNumber;
274 }
275 }
276
277 auto satClk = satNavData->calcClockCorrections(gnssObs->insTime,
278 obsData.pseudorange->value,
279 satSigId.freq());
280 auto satPosVel = satNavData->calcSatellitePosVel(satClk.transmitTime);
281
282 auto recvData = std::make_shared<Observations::SignalObservation::ReceiverSpecificData>(
283 gnssObs, obsIdx,
284 satPosVel.e_pos, satPosVel.e_vel, satClk);
285
286 if (!ignoreElevationMask)
287 {
288 const auto& satElevation = recvData->satElevation(e_posMarker, lla_posMarker);
289 if (satElevation < _elevationMask)
290 {
291 LOG_DATA("{}: Signal {} is skipped because of elevation mask. ({} < {})", nameId, satSigId,
292 rad2deg(satElevation), rad2deg(_elevationMask));
293 if (filtered) { filtered->elevationMaskTriggered.emplace_back(satSigId, satElevation); }
294 continue;
295 }
296 if (obsData.CN0 // If no CN0 available, we do not check the SNR mask, so we use the signal
297 && !_snrMask
298 .at(_sameSnrMaskForAllReceivers ? static_cast<ReceiverType>(0) : receiverType)
299 .checkSNRMask(satSigId.freq(), satElevation, obsData.CN0.value()))
300 {
301 LOG_DATA("{}: [{}] SNR mask triggered for [{}] on receiver [{}] with CN0 {} dbHz",
302 nameId, gnssObs->insTime.toYMDHMS(GPST), satSigId, receiverType, *obsData.CN0);
303 if (filtered) { filtered->snrMaskTriggered.emplace_back(satSigId, *obsData.CN0); }
304 continue;
305 }
306 }
307
308 for (const GnssObs::ObservationType& obsType : _usedObsTypes)
309 {
310 auto removeObsTypeIfExist = [&]() {
311 if (!observations.signals.contains(satSigId)) { return; }
312 std::for_each(observations.signals.at(satSigId).recvObs.begin(),
313 observations.signals.at(satSigId).recvObs.end(),
314 [&](auto& r) {
315 if (r.second->obs.contains(obsType))
316 {
317 LOG_DATA("{}: [{}] Erasing previously added obs '{}' on this signal.", nameId, satSigId, obsType);
318 r.second->obs.erase(obsType);
319 }
320 });
321 };
322
323 if (!firstReceiver
324 && std::any_of(observations.signals.at(satSigId).recvObs.begin(),
325 observations.signals.at(satSigId).recvObs.end(),
326 [&](const auto& r) {
327 return !r.second->obs.contains(obsType);
328 }))
329 {
330 LOG_DATA("{}: [{}][{}] Skipping '{}' measurement. Not all receivers have this observation.", nameId, receiverType, satSigId, obsType);
331 removeObsTypeIfExist();
332 continue;
333 }
334 switch (obsType)
335 {
337 if (recvData->gnssObsData().pseudorange)
338 {
339 recvData->obs[obsType].measurement = recvData->gnssObsData().pseudorange->value;
340 LOG_DATA("{}: [{}] Taking {:11} observation into account on {:5} receiver ({:.3f} [m])", nameId, satSigId,
341 obsType, receiverType, recvData->obs[obsType].measurement);
342 }
343 else { removeObsTypeIfExist(); }
344 break;
345 case GnssObs::Carrier:
346 if (recvData->gnssObsData().carrierPhase)
347 {
348 recvData->obs[obsType].measurement = InsConst::C / satSigId.freq().getFrequency(freqNum)
349 * recvData->gnssObsData().carrierPhase->value;
350 LOG_DATA("{}: [{}] Taking {:11} observation into account on {:5} receiver ({:.3f} [m] = {:.3f} [cycles])", nameId, satSigId,
351 obsType, receiverType, recvData->obs[obsType].measurement, recvData->gnssObsData().carrierPhase->value);
352 }
353 else { removeObsTypeIfExist(); }
354 break;
355 case GnssObs::Doppler:
356 if (recvData->gnssObsData().doppler)
357 {
358 recvData->obs[obsType].measurement = doppler2rangeRate(recvData->gnssObsData().doppler.value(),
359 satSigId.freq(),
360 freqNum);
361 LOG_DATA("{}: [{}] Taking {:11} observation into account on {:5} receiver ({:.3f} [m/s] = {:.3f} [Hz])", nameId, satSigId,
362 obsType, receiverType, recvData->obs[obsType].measurement, recvData->gnssObsData().doppler.value());
363 }
364 else { removeObsTypeIfExist(); }
365 break;
367 break;
368 }
369 }
370
371 if (!firstReceiver
372 && std::any_of(observations.signals.at(satSigId).recvObs.begin(),
373 observations.signals.at(satSigId).recvObs.end(),
374 [&](const auto& r) {
375 return r.second->obs.empty();
376 }))
377 {
378 LOG_DATA("{}: [{}] Skipping obs because not observed by all receivers", nameId, satSigId);
379 if (filtered) { filtered->notAllReceiversObserved.push_back(satSigId); }
380 observations.signals.erase(satSigId);
381 continue;
382 }
383 LOG_DATA("{}: Adding satellite [{}] for receiver {}", nameId, satSigId, receiverType);
384 if (!observations.signals.contains(satSigId))
385 {
386 observations.signals.insert(std::make_pair(satSigId,
387 Observations::SignalObservation{ satNavData, freqNum }));
388 }
389 observations.signals.at(satSigId).recvObs.emplace(receiverType, recvData);
390 }
391 std::vector<SatSigId> sigToRemove;
392 for (const auto& [satSigId, sigObs] : observations.signals)
393 {
394 if (sigObs.recvObs.size() != observations.receivers.size())
395 {
396 sigToRemove.push_back(satSigId);
397 }
398 }
399 for (const auto& satSigId : sigToRemove)
400 {
401 LOG_DATA("{}: [{}] Removing signal because not observed by all receivers.", nameId, satSigId);
402 if (filtered) { filtered->notAllReceiversObserved.push_back(satSigId); }
403 observations.signals.erase(satSigId);
404 }
405
406 observations.recalcObservableCounts(nameId);
407
408#if LOG_LEVEL <= LOG_LEVEL_DATA
409 LOG_DATA("{}: usedSatSystems = [{}]", nameId, joinToString(observations.systems));
410 size_t nMeasTotal = 0;
411 std::string nMeasStr;
412 for (size_t obsType = 0; obsType < GnssObs::ObservationType_COUNT; obsType++)
413 {
414 auto& nMeas = observations.nObservables.at(obsType);
415 nMeasStr += fmt::format("{} {}, ", nMeas, static_cast<GnssObs::ObservationType>(obsType));
416 nMeasTotal += nMeas;
417 }
418 if (nMeasStr.ends_with(", ")) { nMeasStr = nMeasStr.erase(nMeasStr.length() - 2); }
419
420 LOG_DATA("{}: Using {} measurements ({}) from {} satellites", nameId, nMeasTotal, nMeasStr, observations.satellites.size());
421
424 for (const auto& obs : observations.signals)
425 {
426 satData[obs.first.toSatId()].first |= obs.first.freq();
427 satData[obs.first.toSatId()].second |= obs.first.code;
428 for (size_t obsType = 0; obsType < GnssObs::ObservationType_COUNT; obsType++)
429 {
430 if (std::ranges::all_of(obs.second.recvObs, [&obsType](const auto& recvObs) {
431 return recvObs.second->obs.contains(static_cast<GnssObs::ObservationType>(obsType));
432 }))
433 {
434 sigData[obs.first].insert(static_cast<GnssObs::ObservationType>(obsType));
435 }
436 }
437 }
438 for ([[maybe_unused]] const auto& [satId, freqCode] : satData)
439 {
440 LOG_DATA("{}: [{}] on frequencies [{}] with codes [{}]", nameId, satId, freqCode.first, freqCode.second);
441 for (const auto& [satSigId, obs] : sigData)
442 {
443 if (satSigId.toSatId() != satId) { continue; }
444 std::string str;
445 for (const auto& o : obs)
446 {
447 if (!str.empty()) { str += ", "; }
448 str += fmt::format("{}", o);
449 }
450 LOG_DATA("{}: [{}] has obs: {}", nameId, satSigId.code, str);
451 }
452 }
453#endif
454 }
455
456 /// @brief Shows the GUI input to select the options
457 /// @param[in] id Unique id for ImGui.
458 /// @param[in] itemWidth Width of the widgets
459 template<typename ReceiverType>
460 bool ShowGuiWidgets(const char* id, float itemWidth)
461 {
462 bool changed = false;
463
464 ImGui::SetNextItemWidth(itemWidth);
465 if (ShowFrequencySelector(fmt::format("Satellite Frequencies##{}", id).c_str(), _filterFreq))
466 {
467 changed = true;
468 }
469
470 ImGui::SetNextItemWidth(itemWidth);
471 if (ShowCodeSelector(fmt::format("Signal Codes##{}", id).c_str(), _filterCode, _filterFreq))
472 {
473 changed = true;
474 }
475
476 ImGui::SetNextItemWidth(itemWidth);
477 if (ShowSatelliteSelector(fmt::format("Excluded satellites##{}", id).c_str(), _excludedSatellites))
478 {
479 changed = true;
480 }
481
482 double elevationMaskDeg = rad2deg(_elevationMask);
483 ImGui::SetNextItemWidth(itemWidth);
484 if (ImGui::InputDoubleL(fmt::format("Elevation mask##{}", id).c_str(), &elevationMaskDeg, 0.0, 90.0, 5.0, 5.0, "%.1f°", ImGuiInputTextFlags_AllowTabInput))
485 {
486 _elevationMask = deg2rad(elevationMaskDeg);
487 LOG_DEBUG("{}: Elevation mask changed to {}°", id, elevationMaskDeg);
488 changed = true;
489 }
490
491 for (size_t i = 0; i < _snrMask.size(); ++i)
492 {
493 if (i != 0)
494 {
495 ImGui::SameLine();
496 if (_sameSnrMaskForAllReceivers) { ImGui::BeginDisabled(); }
497 }
498 if (_snrMask.at(i).ShowGuiWidgets(fmt::format("{} SNR Mask", static_cast<ReceiverType>(i)).c_str()))
499 {
500 changed = true;
501 }
502 if (i != 0 && _sameSnrMaskForAllReceivers) { ImGui::EndDisabled(); }
503 }
504 if (_snrMask.size() > 1)
505 {
506 ImGui::SameLine();
507 if (ImGui::Checkbox(fmt::format("Use same SNR for all receivers##{}", id).c_str(), &_sameSnrMaskForAllReceivers))
508 {
509 changed = true;
510 }
511 }
512
513 ImGui::BeginHorizontal(fmt::format("Observables##{}", id).c_str(),
514 ImVec2(itemWidth - ImGui::GetStyle().ItemSpacing.x + ImGui::GetStyle().ItemInnerSpacing.x, 0.0F));
515 for (size_t i = 0; i < GnssObs::ObservationType_COUNT; i++)
516 {
517 auto obsType = static_cast<GnssObs::ObservationType>(i);
518 if (!_availableObsTypes.contains(obsType)) { continue; }
519 if (_neededObsTypes.contains(obsType)) { ImGui::BeginDisabled(); }
520 bool enabled = _usedObsTypes.contains(obsType);
521 if (ImGui::Checkbox(fmt::format("{}##{}", obsType, id).c_str(), &enabled))
522 {
523 LOG_DEBUG("{}: Using {}: {}", id, obsType, enabled);
524 if (enabled) { _usedObsTypes.insert(obsType); }
525 else { _usedObsTypes.erase(obsType); }
526 changed = true;
527 }
528 if (_neededObsTypes.contains(obsType)) { ImGui::EndDisabled(); }
529 }
530 ImGui::EndHorizontal();
531
532 ImGui::SameLine();
533 ImGui::TextUnformatted("Used observables");
534
535 return changed;
536 }
537
538 /// @brief Checks if the satellite is allowed. Does not check elevation or SNR mask
539 /// @param[in] satId Satellite Identifier
540 [[nodiscard]] bool isSatelliteAllowed(const SatId& satId) const
541 {
542 return (satId.satSys & _filterFreq)
543 && std::ranges::find(_excludedSatellites, satId) == _excludedSatellites.end();
544 }
545
546 /// @brief Checks if the Observation type is used by the GUI settings
547 /// @param[in] obsType Observation Type
548 [[nodiscard]] bool isObsTypeUsed(GnssObs::ObservationType obsType) const
549 {
550 return _usedObsTypes.contains(obsType);
551 }
552
553 /// @brief Set the observation type to use
554 /// @param obsType Observation Type
556 {
557 _usedObsTypes.insert(obsType);
558 }
559
560 /// @brief Set the observation type as needed (cannot be unchecked in the GUI) or unneeded
561 /// @param obsType Observation Type
562 /// @param needed Needed or unneeded
563 void markObsTypeAsNeeded(GnssObs::ObservationType obsType, bool needed = true)
564 {
565 if (needed) { _neededObsTypes.insert(obsType); }
566 else if (_neededObsTypes.contains(obsType)) { _neededObsTypes.erase(obsType); }
567 }
568
569 /// @brief Temporarily excludes a signal
570 /// @param[in] satSigId Satellite Signal Id
571 /// @param[in] count Amount of function calls to exclude
572 void excludeSignalTemporarily(const SatSigId& satSigId, size_t count)
573 {
574 if (count == 0) { return; }
576 }
577
578 /// @brief Get the Frequency Filter
579 [[nodiscard]] const Frequency& getFrequencyFilter() const
580 {
581 return _filterFreq;
582 }
583 /// @brief Get the Code Filter
584 [[nodiscard]] const Code& getCodeFilter() const
585 {
586 return _filterCode;
587 }
588
589 /// @brief Get the Satellite System Filter
590 [[nodiscard]] SatelliteSystem getSystemFilter() const
591 {
592 return _filterFreq.getSatSys();
593 }
594
595 /// @brief Get the used observation types
596 [[nodiscard]] const std::unordered_set<GnssObs::ObservationType>& getUsedObservationTypes() const
597 {
598 return _usedObsTypes;
599 }
600
601 /// @brief Opens all settings to the maximum, disabling the filter
603 {
604 for (const auto& freq : Frequency::GetAll()) { _filterFreq |= freq; }
606 _excludedSatellites.clear();
607 _elevationMask = 0.0;
608 for (auto& snrMask : _snrMask) { snrMask.disable(); }
611 }
612
613 private:
614 /// Frequencies used for calculation (GUI filter)
616 | E01 | E05 | E06 | E07 | E08;
617 /// Codes used for calculation (GUI filter)
619 /// List of satellites to exclude
620 std::vector<SatId> _excludedSatellites;
621 /// Elevation cut-off angle for satellites in [rad]
622 double _elevationMask = static_cast<double>(10.0_deg);
623 /// SNR Mask for all receivers
624 std::vector<SNRMask> _snrMask;
625 /// Flag wether to use the same SNR mask for all receivers
627 /// Available observation types (e.g. SPP does not have Carrier)
628 const std::unordered_set<GnssObs::ObservationType> _availableObsTypes;
629 /// Needed observation types (cannot be unchecked in GUI)
630 std::unordered_set<GnssObs::ObservationType> _neededObsTypes;
631 /// Utilized observations
632 std::unordered_set<GnssObs::ObservationType> _usedObsTypes;
633
634 /// List of signals to exclude temporarily
635 std::unordered_map<SatSigId, size_t> _temporarilyExcludedSignalsSatellites;
636
637 /// @brief Converts the provided object into json
638 /// @param[out] j Json object which gets filled with the info
639 /// @param[in] obj Object to convert into json
640 friend void to_json(json& j, const ObservationFilter& obj)
641 {
642 j = json{
643 { "frequencies", Frequency_(obj._filterFreq) },
644 { "codes", obj._filterCode },
645 { "excludedSatellites", obj._excludedSatellites },
646 { "elevationMask", rad2deg(obj._elevationMask) },
647 { "snrMask", obj._snrMask },
648 { "sameSnrMaskForAllReceivers", obj._sameSnrMaskForAllReceivers },
649 { "usedObsTypes", obj._usedObsTypes },
650 { "neededObsType", obj._neededObsTypes },
651 };
652 }
653 /// @brief Converts the provided json object into a node object
654 /// @param[in] j Json object with the needed values
655 /// @param[out] obj Object to fill from the json
656 friend void from_json(const json& j, ObservationFilter& obj)
657 {
658 if (j.contains("frequencies"))
659 {
660 uint64_t value = 0;
661 j.at("frequencies").get_to(value);
662 obj._filterFreq = Frequency_(value);
663 }
664 if (j.contains("codes")) { j.at("codes").get_to(obj._filterCode); }
665 if (j.contains("excludedSatellites"))
666 {
667 j.at("excludedSatellites").get_to(obj._excludedSatellites);
668 // Disable Geostationary satellites, as they not working correctly
669 for (const auto& satSys : SatelliteSystem::GetAll())
670 {
671 for (const auto& satNum : satSys.getSatellites())
672 {
673 if (SatId satId(satSys, satNum);
674 satId.isGeo()
675 && std::ranges::find(obj._excludedSatellites, satId) == obj._excludedSatellites.end())
676 {
677 obj._excludedSatellites.push_back(satId);
678 }
679 }
680 }
681 }
682 if (j.contains("elevationMask"))
683 {
684 j.at("elevationMask").get_to(obj._elevationMask);
686 }
687 if (j.contains("snrMask")) { j.at("snrMask").get_to(obj._snrMask); }
688 if (j.contains("sameSnrMaskForAllReceivers")) { j.at("sameSnrMaskForAllReceivers").get_to(obj._sameSnrMaskForAllReceivers); }
689 if (j.contains("usedObsTypes")) { j.at("usedObsTypes").get_to(obj._usedObsTypes); }
690 if (j.contains("neededObsTypes")) { j.at("neededObsTypes").get_to(obj._neededObsTypes); }
691 }
692};
693
694} // namespace NAV
Assertion helpers.
Code definitions.
nlohmann::json json
json namespace
Frequency definition for different satellite systems.
Galileo Ephemeris information.
Navigation message information.
GNSS Observation messages.
Defines how to save certain datatypes to json.
Utility class for logging to console and file.
#define LOG_DEBUG
Debug information. Should not be called on functions which receive observations (spamming)
Definition Logger.hpp:67
#define LOG_DATA
All output which occurs repeatedly every time observations are received.
Definition Logger.hpp:29
Observation data used for calculations.
Receiver information.
Signal to Noise Ratio Mask.
Algorithms concerning the STL containers.
Structs identifying a unique satellite.
GNSS Satellite System.
ankerl::unordered_dense::map< Key, T > unordered_map
Unordered map type.
Enumerate for GNSS Codes.
Definition Code.hpp:89
Frequency definition for different satellite systems.
Definition Frequency.hpp:59
static constexpr std::array< Frequency, 27 > GetAll()
Returns a list with all possible frequencies.
double getFrequency(int8_t num) const
Get the frequency in [Hz].
ObservationType
Observation types.
Definition GnssObs.hpp:37
@ Doppler
Doppler (Pseudorange rate)
Definition GnssObs.hpp:40
@ ObservationType_COUNT
Count.
Definition GnssObs.hpp:41
@ Carrier
Carrier-Phase.
Definition GnssObs.hpp:39
@ Pseudorange
Pseudorange.
Definition GnssObs.hpp:38
static constexpr double C
Speed of light [m/s].
Definition Constants.hpp:34
const std::unordered_set< GnssObs::ObservationType > & getUsedObservationTypes() const
Get the used observation types.
ObservationFilter(ObservationFilter &&other) noexcept=default
Move constructor.
std::vector< SatId > _excludedSatellites
List of satellites to exclude.
friend void to_json(json &j, const ObservationFilter &obj)
Converts the provided object into json.
ObservationFilter & operator=(ObservationFilter &&other) noexcept
Move assignment operator.
bool isSatelliteAllowed(const SatId &satId) const
Checks if the satellite is allowed. Does not check elevation or SNR mask.
std::unordered_map< SatSigId, size_t > _temporarilyExcludedSignalsSatellites
List of signals to exclude temporarily.
friend void from_json(const json &j, ObservationFilter &obj)
Converts the provided json object into a node object.
const Code & getCodeFilter() const
Get the Code Filter.
void useObsType(GnssObs::ObservationType obsType)
Set the observation type to use.
Code _filterCode
Codes used for calculation (GUI filter)
void disableFilter()
Opens all settings to the maximum, disabling the filter.
~ObservationFilter()=default
Destructor.
const std::unordered_set< GnssObs::ObservationType > _availableObsTypes
Available observation types (e.g. SPP does not have Carrier)
std::unordered_set< GnssObs::ObservationType > _usedObsTypes
Utilized observations.
bool isObsTypeUsed(GnssObs::ObservationType obsType) const
Checks if the Observation type is used by the GUI settings.
void markObsTypeAsNeeded(GnssObs::ObservationType obsType, bool needed=true)
Set the observation type as needed (cannot be unchecked in the GUI) or unneeded.
SatelliteSystem getSystemFilter() const
Get the Satellite System Filter.
void reset()
Reset the temporary settings.
bool ShowGuiWidgets(const char *id, float itemWidth)
Shows the GUI input to select the options.
ObservationFilter(size_t receiverCount, const std::unordered_set< GnssObs::ObservationType > &availableObsTypes={ GnssObs::Pseudorange, GnssObs::Carrier, GnssObs::Doppler }, std::unordered_set< GnssObs::ObservationType > neededObsTypes={})
Constructor.
const Frequency & getFrequencyFilter() const
Get the Frequency Filter.
ObservationFilter(const ObservationFilter &other)=default
Copy constructor.
double _elevationMask
Elevation cut-off angle for satellites in [rad].
ObservationFilter & operator=(const ObservationFilter &other)
Copy assignment operator.
std::unordered_set< GnssObs::ObservationType > _neededObsTypes
Needed observation types (cannot be unchecked in GUI)
std::vector< SNRMask > _snrMask
SNR Mask for all receivers.
void excludeSignalTemporarily(const SatSigId &satSigId, size_t count)
Temporarily excludes a signal.
Frequency _filterFreq
Frequencies used for calculation (GUI filter)
bool _sameSnrMaskForAllReceivers
Flag wether to use the same SNR mask for all receivers.
void selectObservationsForCalculation(ReceiverType receiverType, const Eigen::MatrixBase< DerivedPe > &e_posMarker, const Eigen::MatrixBase< DerivedPn > &lla_posMarker, const std::shared_ptr< const GnssObs > &gnssObs, const std::vector< const GnssNavInfo * > &gnssNavInfos, Observations &observations, Filtered *filtered, const std::string &nameId, bool ignoreElevationMask=false)
Returns a list of satellites and observations filtered by GUI settings & NAV data available & ....
ImGui extensions.
bool InputDoubleL(const char *label, double *v, double v_min, double v_max, double step, double step_fast, const char *format, ImGuiInputTextFlags flags)
Shows a value limited InputText GUI element for 'double'.
Definition imgui_ex.cpp:294
std::string joinToString(const T &container, const char *delimiter=", ", const std::string &elementFormat="")
Joins the container to a string.
Definition STL.hpp:30
@ GPST
GPS Time.
Frequency_
Enumerate for GNSS frequencies.
Definition Frequency.hpp:26
@ E07
Galileo E5b (1207.14 MHz).
Definition Frequency.hpp:34
@ E06
Galileo E6 (1278.75 MHz).
Definition Frequency.hpp:33
@ E01
Galileo, "E1" (1575.42 MHz).
Definition Frequency.hpp:31
@ E05
Galileo E5a (1176.45 MHz).
Definition Frequency.hpp:32
@ G02
GPS L2 (1227.6 MHz).
Definition Frequency.hpp:29
@ G01
GPS L1 (1575.42 MHz).
Definition Frequency.hpp:28
@ E08
Galileo E5 (E5a + E5b) (1191.795MHz).
Definition Frequency.hpp:35
@ G05
GPS L5 (1176.45 MHz).
Definition Frequency.hpp:30
bool ShowFrequencySelector(const char *label, Frequency &frequency, bool singleSelect)
Shows a ComboBox to select GNSS frequencies.
bool ShowCodeSelector(const char *label, Code &code, const Frequency &filterFreq, bool singleSelect)
Shows a ComboBox to select signal codes.
Definition Code.cpp:1199
const Code Code_ALL
Definition Code.hpp:653
const Code Code_Default
Default selection for codes.
Definition Code.hpp:655
void move(std::vector< T > &v, size_t sourceIdx, size_t targetIdx)
Moves an element within a vector to a new position.
Definition Vector.hpp:27
constexpr auto deg2rad(const T &deg)
Convert Degree to Radians.
Definition Units.hpp:21
bool ShowSatelliteSelector(const char *label, std::vector< SatId > &satellites, SatelliteSystem filterSys, bool displayOnlyNumber)
Shows a ComboBox to select satellites.
double doppler2rangeRate(double doppler, Frequency freq, int8_t num)
Transforms a doppler-shift into a range-rate.
Definition Functions.cpp:14
@ GLO
Globalnaja nawigazionnaja sputnikowaja sistema (GLONASS)
constexpr auto rad2deg(const T &rad)
Convert Radians to Degree.
Definition Units.hpp:39
Stores the satellites observations.
Definition GnssObs.hpp:46
std::optional< Pseudorange > pseudorange
Pseudorange measurement [m].
Definition GnssObs.hpp:121
std::optional< double > CN0
Carrier-to-Noise density [dBHz].
Definition GnssObs.hpp:124
SatSigId satSigId
SignalId and satellite number.
Definition GnssObs.hpp:120
std::vector< SatSigId > codeFilter
Signals excluded because the code is not used.
std::vector< SatSigId > noPseudorangeMeasurement
Signals without pseudorange measurement.
std::vector< SatSigId > excludedSatellites
Signals excluded because the satellite is excluded.
std::vector< SatSigId > navigationDataMissing
Signals without navigation data.
std::vector< SatSigId > notAllReceiversObserved
Signals not observed by all receivers.
std::vector< SatSigId > frequencyFilter
Signals excluded because the frequency is not used.
std::vector< SatSigId > singleObservation
Only signal for this code/type (relevant for double differences)
std::vector< std::pair< SatSigId, double > > snrMaskTriggered
Signals triggering the SNR mask. Also includes the Carrier-to-Noise density [dBHz].
std::vector< std::pair< SatSigId, double > > elevationMaskTriggered
Signals triggering the elevation mask. Also includes elevation [rad].
std::vector< SatSigId > tempExcludedSignal
Signals temporarily excluded.
Receiver specific observation of the signal.
Observation storage type.
unordered_map< SatSigId, SignalObservation > signals
Observations and calculated data for each signal.
std::unordered_set< size_t > receivers
Receivers included.
Identifies a satellite (satellite system and number)
bool isGeo() const
Checks if the satellite is geostationary.
SatelliteSystem satSys
Satellite system (GPS, GLONASS, GALILEO, QZSS, BDS, IRNSS, SBAS)
Identifies a satellite signal (satellite frequency and number)
Frequency freq() const
Returns the frequency of the satellite signal.
SatId toSatId() const
Returns a satellite identifier for the satellite signal.
Satellite System type.
static std::vector< SatelliteSystem > GetAll()
Returns a list with all possible satellite systems.