26 std::vector<Result> cycleSlips;
27 std::vector<SatSigId> resetThisEpoch;
29 auto searchCycleSlipAlreadyFound = [&cycleSlips](
const SatSigId& satSigId) {
30 return std::ranges::find_if(cycleSlips, [&](
const Result& cycleSlip) {
31 if (
const auto* s = std::get_if<CycleSlipLossOfLockIndicator>(&cycleSlip)) {
return s->signal == satSigId; }
32 if (
const auto* s = std::get_if<CycleSlipSingleFrequency>(&cycleSlip)) {
return s->signal == satSigId; }
37 for (
const auto& obs : satObs)
40 for (
const auto& signal : obs.signals)
42 if (!signals.empty()) { signals +=
", "; }
43 signals += fmt::format(
"{}",
SatSigId(signal.code, obs.satId.satNum));
48 for (
const auto& obs : satObs)
51 for (
const auto& signal : obs.signals)
53 auto satSigId =
SatSigId(signal.code, obs.satId.satNum);
56 if (signal.measurement.LLI)
58 LOG_DATA(
"{}: [{}] Cycle-slip detected, due to LLI set", nameId, satSigId);
64 LOG_DATA(
"{}: [{}] LLI check passed", nameId,
SatSigId(signal.code, obs.satId.satNum));
67 auto lambda =
InsConst::C / satSigId.freq().getFrequency(obs.freqNum);
70 signal.measurement.value * lambda,
74 if (searchCycleSlipAlreadyFound(satSigId) == cycleSlips.end())
76 LOG_DATA(
"{}: [{}] Cycle-slip detected, due to single frequency check", nameId, satSigId);
78 resetThisEpoch.push_back(satSigId);
82 LOG_DATA(
"{}: [{}] Cycle-slip detected, due to single frequency check, but already found due to LLI.", nameId, satSigId);
87 LOG_DATA(
"{}: [{}] Single Frequency check passed", nameId, satSigId);
91 LOG_DATA(
"{}: [{}] Single Frequency check skipped, because not enough data", nameId, satSigId);
95 if (obs.signals.size() >= 2)
99 return s1.code.getFrequency().getFrequency(obs.freqNum) < s2.code.getFrequency().getFrequency(obs.freqNum);
102 for (
const auto& signal2 : obs.signals)
104 if (signal1->code.getFrequency() == signal2.code.getFrequency()) {
continue; }
106 auto satSigId1 =
SatSigId(signal1->code, obs.satId.satNum);
107 auto satSigId2 =
SatSigId(signal2.code, obs.satId.satNum);
110 auto lambda1 =
InsConst::C / satSigId1.freq().getFrequency(obs.freqNum);
111 auto lambda2 =
InsConst::C / satSigId2.freq().getFrequency(obs.freqNum);
114 signal1->measurement.value * lambda1 - signal2.measurement.value * lambda2,
118 auto sat1Slip = searchCycleSlipAlreadyFound(satSigId1);
119 auto sat2Slip = searchCycleSlipAlreadyFound(satSigId2);
120 if ((sat1Slip == cycleSlips.end() && sat2Slip != cycleSlips.end())
121 || (sat1Slip != cycleSlips.end() && sat2Slip == cycleSlips.end()))
123 auto satSigIdSlip = sat1Slip == cycleSlips.end() ? satSigId2 : satSigId1;
124 LOG_DATA(
"{}: [{} / {}] Cycle-slip detected, due to dual frequency check. But slip was already found in [{}]. Assuming not both slipped.",
125 nameId, satSigId1, satSigId2, satSigIdSlip);
127 resetThisEpoch.push_back(satSigIdSlip);
128 std::erase(resetThisEpoch, satSigIdSlip);
130 sat1Slip == cycleSlips.end() ? signal2.measurement.value * lambda2 : signal1->measurement.value * lambda1);
132 else if (sat1Slip != cycleSlips.end() && sat2Slip != cycleSlips.end())
134 LOG_DATA(
"{}: [{} / {}] Cycle-slip detected, due to dual frequency check. But both slips were already found.",
135 nameId, satSigId1, satSigId2);
138 std::erase(resetThisEpoch, satSigId1);
139 std::erase(resetThisEpoch, satSigId2);
145 LOG_DATA(
"{}: [{} / {}] Cycle-slip detected, due to dual frequency check", nameId, satSigId1, satSigId2);
149 std::erase(resetThisEpoch, satSigId1);
150 std::erase(resetThisEpoch, satSigId2);
154 _dualFrequencyDetector.addMeasurement(key, insTime, signal1->measurement.value * lambda1 - signal2.measurement.value * lambda2);
158 if (
auto slip = searchCycleSlipAlreadyFound(satSigId1);
159 slip != cycleSlips.end())
161 LOG_DATA(
"{}: [{}] Cycle-slip detected, but dual frequency check could not detect it. Removing previous detection.", nameId, satSigId1);
162 cycleSlips.erase(slip);
163 std::erase(resetThisEpoch, satSigId1);
165 if (
auto slip = searchCycleSlipAlreadyFound(satSigId2);
166 slip != cycleSlips.end())
168 LOG_DATA(
"{}: [{}] Cycle-slip detected, but dual frequency check could not detect it. Removing previous detection.", nameId, satSigId2);
169 cycleSlips.erase(slip);
170 std::erase(resetThisEpoch, satSigId2);
172 LOG_DATA(
"{}: [{} / {}] Dual Frequency check passed", nameId, satSigId1, satSigId2);
176 LOG_DATA(
"{}: [{} / {}] Dual Frequency check skipped, because not enough data", nameId, satSigId1, satSigId2);
180 for (
const auto& signal : obs.signals)
182 auto satSigId =
SatSigId(signal.code, obs.satId.satNum);
183 auto iter = std::ranges::find(resetThisEpoch, satSigId);
184 if (iter != resetThisEpoch.end())
187 auto lambda =
InsConst::C / satSigId.freq().getFrequency(obs.freqNum);
213 bool changed =
false;
214 if (ImGui::Checkbox(fmt::format(
"LLI check##{}", label).c_str(), &cycleSlipDetector.
_enableLLICheck))
219 if (!cycleSlipDetector.
_singleFrequencyDetector.isEnabled()) { ImGui::PushStyleColor(ImGuiCol_Button, ImGui::GetStyle().Colors[ImGuiCol_TextDisabled]); }
220 if (ImGui::Button(fmt::format(
"Single Frequency detector##{}", label).c_str()))
222 ImGui::OpenPopup(fmt::format(
"Single Frequency detector##Popup - {}", label).c_str());
226 if (ImGui::BeginPopup(fmt::format(
"Single Frequency detector##Popup - {}", label).c_str()))
233 ImGui::SetNextItemWidth(width);
235 ImGui::DragDouble(fmt::format(
"Threshold##single {}", label).c_str(), &val, 1.0F,
236 1.0, std::numeric_limits<double>::max(),
"%.2f %%"))
247 if (!dualFrequencyAvailable || !cycleSlipDetector.
_dualFrequencyDetector.isEnabled()) { ImGui::PushStyleColor(ImGuiCol_Button, ImGui::GetStyle().Colors[ImGuiCol_TextDisabled]); }
248 if (ImGui::Button(fmt::format(
"Dual Frequency detector##{}", label).c_str()))
250 ImGui::OpenPopup(fmt::format(
"Dual Frequency detector##Popup - {}", label).c_str());
252 if (!dualFrequencyAvailable && ImGui::IsItemHovered()) { ImGui::SetTooltip(
"Dual frequency not available due to filter settings."); }
253 if (!dualFrequencyAvailable || !cycleSlipDetector.
_dualFrequencyDetector.isEnabled()) { ImGui::PopStyleColor(); }
254 if (ImGui::BeginPopup(fmt::format(
"Dual Frequency detector##Popup - {}", label).c_str()))
261 ImGui::SetNextItemWidth(width);
264 1.0, std::numeric_limits<double>::max(),
"%.2f %%"))