0.2.0
Loading...
Searching...
No Matches
PolynomialCycleSlipDetector.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
13
14#pragma once
15
16#include <vector>
17#include <utility>
18#include <optional>
19
25
28
29namespace NAV
30{
31
33class GnssAnalyzer;
35class CycleSlipDetector;
36
45
47template<typename Key>
49{
50 public:
55 explicit PolynomialCycleSlipDetector(size_t windowSize, size_t polyDegree, bool enabled = true)
56 : _enabled(enabled), _windowSize(windowSize), _polyDegree(polyDegree) {}
57
64 [[nodiscard]] PolynomialCycleSlipDetectorResult checkForCycleSlip(const Key& key, InsTime insTime, double measurementDifference, double threshold)
65 {
66 if (!_enabled) { return PolynomialCycleSlipDetectorResult::Disabled; }
67 if (!_detectors.contains(key))
68 {
69 addMeasurement(key, insTime, measurementDifference);
70 return PolynomialCycleSlipDetectorResult::LessDataThanWindowSize;
71 }
72
73 const auto& detector = _detectors.at(key);
74 if (!detector.polyReg.windowSizeReached())
75 {
76 addMeasurement(key, insTime, measurementDifference);
77 return PolynomialCycleSlipDetectorResult::LessDataThanWindowSize;
78 }
79
80 auto polynomial = detector.polyReg.calcPolynomial();
81 auto predictedValue = polynomial.f(calcRelativeTime(insTime, detector));
82
83 if (std::abs(measurementDifference - predictedValue) > threshold)
84 {
85 reset(key);
86 addMeasurement(key, insTime, measurementDifference);
87 return PolynomialCycleSlipDetectorResult::CycleSlip;
88 }
89 addMeasurement(key, insTime, measurementDifference);
90 return PolynomialCycleSlipDetectorResult::NoCycleSlip;
91 }
92
94 void clear()
95 {
96 _detectors.clear();
97 }
98
101 void reset(const Key& key)
102 {
103 if (_detectors.contains(key))
104 {
105 _detectors.erase(key);
106 }
107 }
108
110 [[nodiscard]] bool isEnabled() const
111 {
112 return _enabled;
113 }
116 void setEnabled(bool enabled)
117 {
118 _enabled = enabled;
119 }
120
122 [[nodiscard]] size_t getWindowSize() const { return _windowSize; }
125 void setWindowSize(size_t windowSize)
126 {
127 _windowSize = windowSize;
128 for (auto& detector : _detectors)
129 {
130 detector.second.polyReg.setWindowSize(windowSize);
131 }
132 }
133
135 [[nodiscard]] size_t getPolynomialDegree() const { return _polyDegree; }
138 void setPolynomialDegree(size_t polyDegree)
139 {
140 _polyDegree = polyDegree;
141 for (auto& detector : _detectors)
142 {
143 detector.second.polyReg.setPolynomialDegree(polyDegree);
144 }
145 }
146
149
151 [[nodiscard]] Strategy getFitStrategy() const { return _strategy; }
155 {
156 _strategy = strategy;
157 for (auto& detector : _detectors)
158 {
159 detector.second.polyReg.setStrategy(strategy);
160 }
161 }
162
163 private:
165 struct SignalDetector
166 {
172 SignalDetector(InsTime startTime, size_t windowSize, size_t polyDegree, Strategy strategy)
173 : startTime(startTime), polyReg(polyDegree, windowSize, strategy) {}
174
175 InsTime startTime;
176 PolynomialRegressor<double> polyReg;
177 };
178
179 bool _enabled = true;
180 size_t _windowSize;
181 size_t _polyDegree = 2;
182 Strategy _strategy = Strategy::HouseholderQR;
184
188 [[nodiscard]] static double calcRelativeTime(const InsTime& insTime, const SignalDetector& detector)
189 {
190 return static_cast<double>((insTime - detector.startTime).count());
191 }
195 [[nodiscard]] std::optional<double> calcRelativeTime(const Key& key, const InsTime& insTime) const
196 {
197 if (!_detectors.contains(key)) { return {}; }
198
199 return calcRelativeTime(insTime, _detectors.at(key));
200 }
201
205 [[nodiscard]] std::optional<double> predictValue(const Key& key, const InsTime& insTime) const
206 {
207 if (!_detectors.contains(key)) { return {}; }
208
209 const auto& detector = _detectors.at(key);
210
211 auto polynomial = detector.polyReg.calcPolynomial();
212 return polynomial.f(calcRelativeTime(insTime, detector));
213 }
214
217 [[nodiscard]] std::optional<Polynomial<double>> calcPolynomial(const Key& key) const
218 {
219 if (!_detectors.contains(key)) { return {}; }
220
221 return _detectors.at(key).polyReg.calcPolynomial();
222 }
223
228 void addMeasurement(const Key& key, InsTime insTime, double measurementDifference)
229 {
230 if (!_enabled) { return; }
231 auto& detector = _detectors.insert({ key, SignalDetector(insTime, _windowSize, _polyDegree, _strategy) }).first->second;
232
233 detector.polyReg.push_back(calcRelativeTime(insTime, detector), measurementDifference);
234 }
235
236 friend class GnssAnalyzer;
237 friend class CycleSlipDetector;
238};
239
244template<typename Key>
245bool PolynomialCycleSlipDetectorGui(const char* label, PolynomialCycleSlipDetector<Key>& polynomialCycleSlipDetector, float width = 0.0F)
246{
247 bool changed = false;
248
249 bool enabled = polynomialCycleSlipDetector.isEnabled();
250 if (ImGui::Checkbox(fmt::format("Enabled##{}", label).c_str(), &enabled))
251 {
252 changed = true;
253 polynomialCycleSlipDetector.setEnabled(enabled);
254 }
255
256 if (!enabled) { ImGui::BeginDisabled(); }
257
258 ImGui::SetNextItemWidth(width);
259 if (int windowSize = static_cast<int>(polynomialCycleSlipDetector.getWindowSize());
260 ImGui::InputIntL(fmt::format("Window size##{}", label).c_str(), &windowSize,
261 std::max(1, static_cast<int>(polynomialCycleSlipDetector.getPolynomialDegree()) + 1)))
262 {
263 changed = true;
264 polynomialCycleSlipDetector.setWindowSize(static_cast<size_t>(windowSize));
265 }
266
267 ImGui::SetNextItemWidth(width);
268 if (int polyDegree = static_cast<int>(polynomialCycleSlipDetector.getPolynomialDegree());
269 ImGui::InputIntL(fmt::format("Polynomial Degree##{}", label).c_str(), &polyDegree,
270 0, std::min(static_cast<int>(polynomialCycleSlipDetector.getWindowSize()) - 1, std::numeric_limits<int>::max())))
271 {
272 changed = true;
273 polynomialCycleSlipDetector.setPolynomialDegree(static_cast<size_t>(polyDegree));
274 }
275
276 ImGui::SetNextItemWidth(width);
277 if (auto strategy = polynomialCycleSlipDetector.getFitStrategy();
278 gui::widgets::EnumCombo(fmt::format("Strategy##{}", label).c_str(), strategy))
279 {
280 changed = true;
281 polynomialCycleSlipDetector.setFitStrategy(strategy);
282 }
283
284 if (!enabled) { ImGui::EndDisabled(); }
285
286 return changed;
287}
288
292template<typename Key>
294{
295 j = json{
296 { "enabled", data.isEnabled() },
297 { "windowSize", data.getWindowSize() },
298 { "polynomialDegree", data.getPolynomialDegree() },
299 { "strategy", data.getFitStrategy() },
300 };
301}
305template<typename Key>
307{
308 if (j.contains("enabled"))
309 {
310 auto enabled = j.at("enabled").get<bool>();
311 data.setEnabled(enabled);
312 }
313 if (j.contains("windowSize"))
314 {
315 auto windowSize = j.at("windowSize").get<size_t>();
316 data.setWindowSize(windowSize);
317 }
318 if (j.contains("polynomialDegree"))
319 {
320 auto polynomialDegree = j.at("polynomialDegree").get<size_t>();
321 data.setPolynomialDegree(polynomialDegree);
322 }
323 if (j.contains("strategy"))
324 {
325 auto strategy = j.at("strategy").get<size_t>();
326 data.setFitStrategy(static_cast<typename PolynomialCycleSlipDetector<Key>::Strategy>(strategy));
327 }
328}
329
330} // namespace NAV
Combo representing an enumeration.
nlohmann::json json
json namespace
Definition FlowManager.hpp:21
The class is responsible for all time-related tasks.
void from_json(const json &j, ImColor &color)
Converts the provided json object into a color.
void to_json(json &j, const ImColor &color)
Converts the provided color into a json object.
Utility functions for std::pair.
bool PolynomialCycleSlipDetectorGui(const char *label, PolynomialCycleSlipDetector< Key > &polynomialCycleSlipDetector, float width=0.0F)
Shows a GUI for advanced configuration of the PolynomialCycleSlipDetector.
Definition PolynomialCycleSlipDetector.hpp:245
PolynomialCycleSlipDetectorResult
Cycle-slip detection result type.
Definition PolynomialCycleSlipDetector.hpp:39
@ LessDataThanWindowSize
Less data than the specified window size (cannot predict cycle-slip yet)
@ Disabled
The cycle-slip detector is disabled.
Polynomial curve fitting.
Structs identifying a unique satellite.
Unordered map wrapper.
ankerl::unordered_dense::map< Key, T > unordered_map
Unordered map type.
Definition Unordered_map.hpp:34
The class is responsible for all time-related tasks.
Definition InsTime.hpp:667
Cycle-slip detection.
Definition PolynomialCycleSlipDetector.hpp:49
size_t getPolynomialDegree() const
Get the degree of the polynomial which is used for fitting.
Definition PolynomialCycleSlipDetector.hpp:135
void setFitStrategy(Strategy strategy)
Sets the strategy used for fitting.
Definition PolynomialCycleSlipDetector.hpp:154
void setWindowSize(size_t windowSize)
Sets the amount of points used for the fit (sliding window)
Definition PolynomialCycleSlipDetector.hpp:125
void setEnabled(bool enabled)
Sets the enabled state.
Definition PolynomialCycleSlipDetector.hpp:116
PolynomialRegressor<>::Strategy Strategy
Strategies for fitting.
Definition PolynomialCycleSlipDetector.hpp:148
bool isEnabled() const
Is the cycle-slip detector enabled?
Definition PolynomialCycleSlipDetector.hpp:110
void setPolynomialDegree(size_t polyDegree)
Sets the degree of the polynomial which is used for fitting.
Definition PolynomialCycleSlipDetector.hpp:138
size_t getWindowSize() const
Get the window size for the polynomial fit.
Definition PolynomialCycleSlipDetector.hpp:122
PolynomialCycleSlipDetectorResult checkForCycleSlip(const Key &key, InsTime insTime, double measurementDifference, double threshold)
Checks for a cycle slip.
Definition PolynomialCycleSlipDetector.hpp:64
Strategy getFitStrategy() const
Get the strategy used for fitting.
Definition PolynomialCycleSlipDetector.hpp:151
void reset(const Key &key)
Reset the polynomial for the given combination.
Definition PolynomialCycleSlipDetector.hpp:101
PolynomialCycleSlipDetector(size_t windowSize, size_t polyDegree, bool enabled=true)
Constructor.
Definition PolynomialCycleSlipDetector.hpp:55
void clear()
Empties the collected polynomials.
Definition PolynomialCycleSlipDetector.hpp:94
Strategy
Possible Fit strategies.
Definition PolynomialRegressor.hpp:43
ImGui extensions.