20#include <unordered_map>
21#include <unordered_set>
61 std::unordered_set<GnssObs::ObservationType> neededObsTypes = {})
67 for (
const auto& satNum : satSys.getSatellites())
69 if (SatId satId(satSys, satNum);
94 std::vector<GnssObs::ObservationType> obsTypeToRemove;
99 for (
const auto& obsType : obsTypeToRemove)
115 _snrMask = std::move(other._snrMask);
119 std::vector<GnssObs::ObservationType> obsTypeToRemove;
124 for (
const auto& obsType : obsTypeToRemove)
163 template<
typename ReceiverType,
typename DerivedPe,
typename DerivedPn>
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,
171 [[maybe_unused]]
const std::string& nameId,
172 bool ignoreElevationMask =
false)
174 bool firstReceiver = observations.
receivers.empty();
175 observations.
receivers.insert(receiverType);
177 observations.
signals.reserve(gnssObs->data.size());
179 for (
size_t obsIdx = 0; obsIdx < gnssObs->data.size(); obsIdx++)
184 LOG_DATA(
"{}: Considering [{}] for receiver {}", nameId, satSigId, receiverType);
197 LOG_DATA(
"{}: [{}] Skipping obs due to GUI frequency filter", nameId, satSigId);
203 LOG_DATA(
"{}: [{}] Skipping obs due to GUI code filter", nameId, satSigId);
204 if (filtered) { filtered->
codeFilter.push_back(satSigId); }
209 LOG_DATA(
"{}: [{}] Skipping obs due to GUI excluded satellites", nameId, satSigId);
215 LOG_DATA(
"{}: [{}] Skipping obs because temporarily excluded signal", nameId, satSigId);
222 LOG_DATA(
"{}: [{}] Skipping obs because no pseudorange measurement (needed for satellite position calculation)", nameId, satSigId);
227 if (!firstReceiver && !observations.
signals.contains(satSigId))
229 bool signalWithSameFrequencyFound =
false;
230 for (
const auto& signals : observations.
signals)
232 if (signals.first.toSatId() == satId && signals.first.freq() == satSigId.
freq()
233 && signals.second.recvObs.size() != observations.
receivers.size())
235 LOG_DATA(
"{}: [{}] Not observed by all receivers, but other receivers have [{}]. Treating as such.",
236 nameId, satSigId, signals.first);
237 satSigId = signals.first;
239 signalWithSameFrequencyFound =
true;
243 if (!signalWithSameFrequencyFound)
245 LOG_DATA(
"{}: [{}] Skipping obs because not observed by all receivers", nameId, satSigId);
251 std::shared_ptr<NAV::SatNavData> satNavData =
nullptr;
252 for (
const auto* gnssNavInfo : gnssNavInfos)
254 auto satNav = gnssNavInfo->searchNavigationData(satId, gnssObs->insTime);
255 if (satNav && satNav->isHealthy())
261 if (satNavData ==
nullptr)
263 LOG_DATA(
"{}: [{}] Skipping obs because no navigation data available to calculaten the satellite position", nameId, satSigId);
268 int8_t freqNum = -128;
271 if (
auto gloSatNavData = std::dynamic_pointer_cast<GLONASSEphemeris>(satNavData))
273 freqNum = gloSatNavData->frequencyNumber;
277 auto satClk = satNavData->calcClockCorrections(gnssObs->insTime,
280 auto satPosVel = satNavData->calcSatellitePosVel(satClk.transmitTime);
282 auto recvData = std::make_shared<Observations::SignalObservation::ReceiverSpecificData>(
284 satPosVel.e_pos, satPosVel.e_vel, satClk);
286 if (!ignoreElevationMask)
288 const auto& satElevation = recvData->satElevation(e_posMarker, lla_posMarker);
291 LOG_DATA(
"{}: Signal {} is skipped because of elevation mask. ({} < {})", nameId, satSigId,
299 .checkSNRMask(satSigId.
freq(), satElevation, obsData.
CN0.value()))
301 LOG_DATA(
"{}: [{}] SNR mask triggered for [{}] on receiver [{}] with CN0 {} dbHz",
302 nameId, gnssObs->insTime.toYMDHMS(
GPST), satSigId, receiverType, *obsData.
CN0);
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(),
315 if (r.second->obs.contains(obsType))
317 LOG_DATA(
"{}: [{}] Erasing previously added obs '{}' on this signal.", nameId, satSigId, obsType);
318 r.second->obs.erase(obsType);
324 && std::any_of(observations.
signals.at(satSigId).recvObs.begin(),
325 observations.
signals.at(satSigId).recvObs.end(),
327 return !r.second->obs.contains(obsType);
330 LOG_DATA(
"{}: [{}][{}] Skipping '{}' measurement. Not all receivers have this observation.", nameId, receiverType, satSigId, obsType);
331 removeObsTypeIfExist();
337 if (recvData->gnssObsData().pseudorange)
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);
343 else { removeObsTypeIfExist(); }
346 if (recvData->gnssObsData().carrierPhase)
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);
353 else { removeObsTypeIfExist(); }
356 if (recvData->gnssObsData().doppler)
358 recvData->obs[obsType].measurement =
doppler2rangeRate(recvData->gnssObsData().doppler.value(),
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());
364 else { removeObsTypeIfExist(); }
372 && std::any_of(observations.
signals.at(satSigId).recvObs.begin(),
373 observations.
signals.at(satSigId).recvObs.end(),
375 return r.second->obs.empty();
378 LOG_DATA(
"{}: [{}] Skipping obs because not observed by all receivers", nameId, satSigId);
380 observations.
signals.erase(satSigId);
383 LOG_DATA(
"{}: Adding satellite [{}] for receiver {}", nameId, satSigId, receiverType);
384 if (!observations.
signals.contains(satSigId))
386 observations.
signals.insert(std::make_pair(satSigId,
389 observations.
signals.at(satSigId).recvObs.emplace(receiverType, recvData);
391 std::vector<SatSigId> sigToRemove;
392 for (
const auto& [satSigId, sigObs] : observations.signals)
394 if (sigObs.recvObs.size() != observations.receivers.size())
396 sigToRemove.push_back(satSigId);
399 for (
const auto& satSigId : sigToRemove)
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);
406 observations.recalcObservableCounts(nameId);
408#if LOG_LEVEL <= LOG_LEVEL_DATA
410 size_t nMeasTotal = 0;
411 std::string nMeasStr;
414 auto& nMeas = observations.nObservables.at(obsType);
418 if (nMeasStr.ends_with(
", ")) { nMeasStr = nMeasStr.erase(nMeasStr.length() - 2); }
420 LOG_DATA(
"{}: Using {} measurements ({}) from {} satellites", nameId, nMeasTotal, nMeasStr, observations.satellites.size());
424 for (
const auto& obs : observations.signals)
426 satData[obs.first.toSatId()].first |= obs.first.freq();
427 satData[obs.first.toSatId()].second |= obs.first.code;
430 if (std::ranges::all_of(obs.second.recvObs, [&obsType](
const auto& recvObs) {
431 return recvObs.second->obs.contains(static_cast<GnssObs::ObservationType>(obsType));
438 for ([[maybe_unused]]
const auto& [satId, freqCode] : satData)
440 LOG_DATA(
"{}: [{}] on frequencies [{}] with codes [{}]", nameId, satId, freqCode.first, freqCode.second);
441 for (
const auto& [satSigId, obs] : sigData)
443 if (satSigId.toSatId() != satId) {
continue; }
445 for (
const auto& o : obs)
447 if (!str.empty()) { str +=
", "; }
448 str += fmt::format(
"{}", o);
450 LOG_DATA(
"{}: [{}] has obs: {}", nameId, satSigId.code, str);
459 template<
typename ReceiverType>
462 bool changed =
false;
464 ImGui::SetNextItemWidth(itemWidth);
470 ImGui::SetNextItemWidth(itemWidth);
476 ImGui::SetNextItemWidth(itemWidth);
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))
487 LOG_DEBUG(
"{}: Elevation mask changed to {}°",
id, elevationMaskDeg);
491 for (
size_t i = 0; i <
_snrMask.size(); ++i)
498 if (
_snrMask.at(i).ShowGuiWidgets(fmt::format(
"{} SNR Mask",
static_cast<ReceiverType
>(i)).c_str()))
513 ImGui::BeginHorizontal(fmt::format(
"Observables##{}",
id).c_str(),
514 ImVec2(itemWidth - ImGui::GetStyle().ItemSpacing.x + ImGui::GetStyle().ItemInnerSpacing.x, 0.0F));
521 if (ImGui::Checkbox(fmt::format(
"{}##{}", obsType,
id).c_str(), &enabled))
523 LOG_DEBUG(
"{}: Using {}: {}",
id, obsType, enabled);
530 ImGui::EndHorizontal();
533 ImGui::TextUnformatted(
"Used observables");
574 if (count == 0) {
return; }
608 for (
auto& snrMask :
_snrMask) { snrMask.disable(); }
658 if (j.contains(
"frequencies"))
661 j.at(
"frequencies").get_to(value);
664 if (j.contains(
"codes")) { j.at(
"codes").get_to(obj.
_filterCode); }
665 if (j.contains(
"excludedSatellites"))
671 for (
const auto& satNum : satSys.getSatellites())
673 if (
SatId satId(satSys, satNum);
682 if (j.contains(
"elevationMask"))
687 if (j.contains(
"snrMask")) { j.at(
"snrMask").get_to(obj.
_snrMask); }
689 if (j.contains(
"usedObsTypes")) { j.at(
"usedObsTypes").get_to(obj.
_usedObsTypes); }
690 if (j.contains(
"neededObsTypes")) { j.at(
"neededObsTypes").get_to(obj.
_neededObsTypes); }
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)
#define LOG_DATA
All output which occurs repeatedly every time observations are received.
Observation data used for calculations.
Signal to Noise Ratio Mask.
Algorithms concerning the STL containers.
Structs identifying a unique satellite.
ankerl::unordered_dense::map< Key, T > unordered_map
Unordered map type.
Enumerate for GNSS Codes.
Frequency definition for different satellite systems.
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.
@ Doppler
Doppler (Pseudorange rate)
@ ObservationType_COUNT
Count.
@ Pseudorange
Pseudorange.
static constexpr double C
Speed of light [m/s].
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 & ....
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'.
std::string joinToString(const T &container, const char *delimiter=", ", const std::string &elementFormat="")
Joins the container to a string.
Frequency_
Enumerate for GNSS frequencies.
@ E07
Galileo E5b (1207.14 MHz).
@ E06
Galileo E6 (1278.75 MHz).
@ E01
Galileo, "E1" (1575.42 MHz).
@ E05
Galileo E5a (1176.45 MHz).
@ G02
GPS L2 (1227.6 MHz).
@ G01
GPS L1 (1575.42 MHz).
@ E08
Galileo E5 (E5a + E5b) (1191.795MHz).
@ G05
GPS L5 (1176.45 MHz).
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.
const Code Code_Default
Default selection for codes.
void move(std::vector< T > &v, size_t sourceIdx, size_t targetIdx)
Moves an element within a vector to a new position.
constexpr auto deg2rad(const T °)
Convert Degree to Radians.
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.
@ GLO
Globalnaja nawigazionnaja sputnikowaja sistema (GLONASS)
constexpr auto rad2deg(const T &rad)
Convert Radians to Degree.
Stores the satellites observations.
std::optional< Pseudorange > pseudorange
Pseudorange measurement [m].
std::optional< double > CN0
Carrier-to-Noise density [dBHz].
SatSigId satSigId
SignalId and satellite number.
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.
static std::vector< SatelliteSystem > GetAll()
Returns a list with all possible satellite systems.