| 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 | /// @file SatelliteIdentifier.hpp | ||
| 10 | /// @brief Structs identifying a unique satellite | ||
| 11 | /// @author T. Topp (topp@ins.uni-stuttgart.de) | ||
| 12 | /// @date 2022-04-29 | ||
| 13 | |||
| 14 | #pragma once | ||
| 15 | |||
| 16 | #include <cstdint> | ||
| 17 | #include <string> | ||
| 18 | #include <vector> | ||
| 19 | #include <nlohmann/json.hpp> | ||
| 20 | using json = nlohmann::json; ///< json namespace | ||
| 21 | #include <fmt/format.h> | ||
| 22 | |||
| 23 | #include "SatelliteSystem.hpp" | ||
| 24 | #include "Frequency.hpp" | ||
| 25 | #include "Code.hpp" | ||
| 26 | |||
| 27 | #include "util/Container/STL.hpp" | ||
| 28 | |||
| 29 | namespace NAV | ||
| 30 | { | ||
| 31 | |||
| 32 | /// @brief Identifies a satellite (satellite system and number) | ||
| 33 | struct SatId | ||
| 34 | { | ||
| 35 | /// @brief Constructor | ||
| 36 | /// @param[in] satSys Satellite system | ||
| 37 | /// @param[in] satNum Number of the satellite | ||
| 38 | 11521503 | SatId(SatelliteSystem satSys, uint16_t satNum) | |
| 39 | 11521503 | : satSys(satSys), satNum(satNum) {} | |
| 40 | |||
| 41 | /// Default constructor | ||
| 42 | 571742 | SatId() = default; | |
| 43 | |||
| 44 | /// @brief Constructor from String representation | ||
| 45 | /// @param[in] str SatId as string | ||
| 46 | 364 | explicit SatId(const std::string& str) | |
| 47 |
2/4✓ Branch 1 taken 364 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 364 times.
✗ Branch 6 not taken.
|
364 | : satSys(SatelliteSystem::fromChar(str.substr(0, 1).front())), |
| 48 |
2/4✓ Branch 1 taken 364 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 364 times.
✗ Branch 5 not taken.
|
364 | satNum(static_cast<uint16_t>(std::stoul(str.substr(1)))) {} |
| 49 | |||
| 50 | SatelliteSystem satSys = SatSys_None; ///< Satellite system (GPS, GLONASS, GALILEO, QZSS, BDS, IRNSS, SBAS) | ||
| 51 | uint16_t satNum = 0; ///< Number of the satellite | ||
| 52 | |||
| 53 | /// @brief Equal comparison (needed for unordered_map) | ||
| 54 | /// @param[in] rhs Right hand side of the operator | ||
| 55 | /// @return True if the elements are equal | ||
| 56 |
4/4✓ Branch 1 taken 15952485 times.
✓ Branch 2 taken 32575256 times.
✓ Branch 3 taken 4247293 times.
✓ Branch 4 taken 11705192 times.
|
48510418 | constexpr bool operator==(const SatId& rhs) const { return satSys == rhs.satSys && satNum == rhs.satNum; } |
| 57 | |||
| 58 | /// @brief Less than comparison (needed for map) | ||
| 59 | /// @param[in] rhs Right hand side of the operator | ||
| 60 | /// @return True if lhs < rhs | ||
| 61 | 856711 | constexpr bool operator<(const SatId& rhs) const | |
| 62 | { | ||
| 63 |
2/2✓ Branch 1 taken 571185 times.
✓ Branch 2 taken 285526 times.
|
856711 | return satSys == rhs.satSys ? satNum < rhs.satNum |
| 64 | 856711 | : satSys < rhs.satSys; | |
| 65 | } | ||
| 66 | |||
| 67 | /// Checks if the satellite is geostationary | ||
| 68 | [[nodiscard]] bool isGeo() const; | ||
| 69 | }; | ||
| 70 | |||
| 71 | /// @brief Identifies a satellite signal (satellite frequency and number) | ||
| 72 | struct SatSigId | ||
| 73 | { | ||
| 74 | /// @brief Constructor | ||
| 75 | /// @param[in] code Signal code | ||
| 76 | /// @param[in] satNum Number of the satellite | ||
| 77 | 228226844 | SatSigId(Code code, uint16_t satNum) | |
| 78 | 228226844 | : code(code), satNum(satNum) {} | |
| 79 | |||
| 80 | /// Default constructor | ||
| 81 | 177785 | SatSigId() = default; | |
| 82 | |||
| 83 | /// @brief Constructor from String representation | ||
| 84 | /// @param[in] str SatSigId as string | ||
| 85 | 14 | explicit SatSigId(const std::string& str) | |
| 86 |
2/4✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 14 times.
✗ Branch 5 not taken.
|
14 | : code(str.substr(0, 3)), |
| 87 |
2/4✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 14 times.
✗ Branch 5 not taken.
|
14 | satNum(static_cast<uint16_t>(std::stoul(str.substr(4)))) {} |
| 88 | |||
| 89 | Code code = Code::None; ///< Code | ||
| 90 | uint16_t satNum = 0; ///< Number of the satellite | ||
| 91 | |||
| 92 | /// @brief Equal comparison (needed for unordered_map) | ||
| 93 | /// @param[in] rhs Right hand side of the operator | ||
| 94 | /// @return True if the elements are equal | ||
| 95 |
4/4✓ Branch 1 taken 39993731 times.
✓ Branch 2 taken 1130468956 times.
✓ Branch 3 taken 10870519 times.
✓ Branch 4 taken 29123212 times.
|
1165162925 | bool operator==(const SatSigId& rhs) const { return code == rhs.code && satNum == rhs.satNum; } |
| 96 | |||
| 97 | /// @brief Less than comparison (needed for map) | ||
| 98 | /// @param[in] rhs Right hand side of the operator | ||
| 99 | /// @return True if lhs < rhs | ||
| 100 | 2234096 | bool operator<(const SatSigId& rhs) const | |
| 101 | { | ||
| 102 |
4/6✓ Branch 1 taken 2234096 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2234096 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1876524 times.
✓ Branch 8 taken 357572 times.
|
2234096 | if (toSatId().satSys == rhs.toSatId().satSys) |
| 103 | { | ||
| 104 |
2/2✓ Branch 0 taken 582330 times.
✓ Branch 1 taken 1294194 times.
|
1876524 | if (satNum == rhs.satNum) |
| 105 | { | ||
| 106 |
1/2✓ Branch 3 taken 582330 times.
✗ Branch 4 not taken.
|
582330 | return Code::Set(code) < Code::Set(rhs.code); |
| 107 | } | ||
| 108 | 1294194 | return satNum < rhs.satNum; | |
| 109 | } | ||
| 110 |
2/4✓ Branch 1 taken 357572 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 357572 times.
✗ Branch 5 not taken.
|
357572 | return toSatId().satSys < rhs.toSatId().satSys; |
| 111 | } | ||
| 112 | |||
| 113 | /// @brief Returns a satellite identifier for the satellite signal | ||
| 114 | 8316426 | [[nodiscard]] SatId toSatId() const | |
| 115 | { | ||
| 116 |
2/4✓ Branch 1 taken 8316194 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8316239 times.
✗ Branch 5 not taken.
|
8316426 | return { code.getFrequency().getSatSys(), satNum }; |
| 117 | } | ||
| 118 | |||
| 119 | /// @brief Returns the frequency of the satellite signal | ||
| 120 | 2367538 | [[nodiscard]] Frequency freq() const | |
| 121 | { | ||
| 122 | 2367538 | return code.getFrequency(); | |
| 123 | } | ||
| 124 | }; | ||
| 125 | |||
| 126 | /// @brief Less than comparison from string representation | ||
| 127 | /// @param[in] lhs Left hand side of the operator | ||
| 128 | /// @param[in] rhs Right hand side of the operator | ||
| 129 | /// @return True if lhs < rhs | ||
| 130 | bool lessCompareSatSigId(const std::string& lhs, const std::string& rhs); | ||
| 131 | |||
| 132 | /// @brief Converts the provided link into a json object | ||
| 133 | /// @param[out] j Json object which gets filled with the info | ||
| 134 | /// @param[in] data Data to convert into json | ||
| 135 | void to_json(json& j, const SatId& data); | ||
| 136 | /// @brief Converts the provided json object into a link object | ||
| 137 | /// @param[in] j Json object with the needed values | ||
| 138 | /// @param[out] data Object to fill from the json | ||
| 139 | void from_json(const json& j, SatId& data); | ||
| 140 | |||
| 141 | /// @brief Converts the provided link into a json object | ||
| 142 | /// @param[out] j Json object which gets filled with the info | ||
| 143 | /// @param[in] data Object to convert into json | ||
| 144 | void to_json(json& j, const SatSigId& data); | ||
| 145 | /// @brief Converts the provided json object into a link object | ||
| 146 | /// @param[in] j Json object with the needed values | ||
| 147 | /// @param[out] data Object to fill from the json | ||
| 148 | void from_json(const json& j, SatSigId& data); | ||
| 149 | |||
| 150 | /// @brief Shows a ComboBox to select satellites | ||
| 151 | /// @param[in] label Label to show beside the combo box. This has to be a unique id for ImGui. | ||
| 152 | /// @param[in, out] satellites Reference to the SatId vector to select | ||
| 153 | /// @param[in] filterSys Enable/Disable GUI elements according to this filter | ||
| 154 | /// @param[in] displayOnlyNumber Display only the number, not the system | ||
| 155 | bool ShowSatelliteSelector(const char* label, std::vector<SatId>& satellites, SatelliteSystem filterSys = SatSys_All, bool displayOnlyNumber = false); | ||
| 156 | |||
| 157 | /// @brief Shows a ComboBox to select a single satellite | ||
| 158 | /// @param[in] label Label to show beside the combo box. This has to be a unique id for ImGui. | ||
| 159 | /// @param[in, out] satellite Reference to the SatId to select | ||
| 160 | /// @param[in] filterSys Enable/Disable GUI elements according to this filter | ||
| 161 | /// @param[in] displayOnlyNumber Display only the number, not the system | ||
| 162 | bool ShowSatelliteSelector(const char* label, SatId& satellite, SatelliteSystem filterSys = SatSys_All, bool displayOnlyNumber = false); | ||
| 163 | |||
| 164 | } // namespace NAV | ||
| 165 | |||
| 166 | /// @brief Stream insertion operator overload | ||
| 167 | /// @param[in, out] os Output stream object to stream the time into | ||
| 168 | /// @param[in] obj Object to print | ||
| 169 | /// @return Returns the output stream object in order to chain stream insertions | ||
| 170 | std::ostream& operator<<(std::ostream& os, const NAV::SatId& obj); | ||
| 171 | |||
| 172 | /// @brief Stream insertion operator overload | ||
| 173 | /// @param[in, out] os Output stream object to stream the time into | ||
| 174 | /// @param[in] obj Object to print | ||
| 175 | /// @return Returns the output stream object in order to chain stream insertions | ||
| 176 | std::ostream& operator<<(std::ostream& os, const NAV::SatSigId& obj); | ||
| 177 | |||
| 178 | #ifndef DOXYGEN_IGNORE | ||
| 179 | |||
| 180 | /// @brief Formatter for SatId | ||
| 181 | template<> | ||
| 182 | struct fmt::formatter<NAV::SatId> | ||
| 183 | { | ||
| 184 | /// @brief Parse function to make the struct formattable | ||
| 185 | /// @param[in] ctx Parser context | ||
| 186 | /// @return Beginning of the context | ||
| 187 | 220433 | static constexpr auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) | |
| 188 | { | ||
| 189 | 220433 | return ctx.begin(); | |
| 190 | } | ||
| 191 | |||
| 192 | /// @brief Defines how to format SatId structs | ||
| 193 | /// @param[in] satId Struct to format | ||
| 194 | /// @param[in, out] ctx Format context | ||
| 195 | /// @return Output iterator | ||
| 196 | template<typename FormatContext> | ||
| 197 | 220433 | auto format(const NAV::SatId& satId, FormatContext& ctx) const -> decltype(ctx.out()) | |
| 198 | { | ||
| 199 |
2/4✓ Branch 1 taken 220433 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 220433 times.
✗ Branch 5 not taken.
|
440866 | return fmt::format_to(ctx.out(), "{0}{1:02d}", char(satId.satSys), satId.satNum); |
| 200 | } | ||
| 201 | }; | ||
| 202 | |||
| 203 | /// @brief Formatter for SatSigId | ||
| 204 | template<> | ||
| 205 | struct fmt::formatter<NAV::SatSigId> | ||
| 206 | { | ||
| 207 | /// @brief Parse function to make the struct formattable | ||
| 208 | /// @param[in] ctx Parser context | ||
| 209 | /// @return Beginning of the context | ||
| 210 | 672503 | static constexpr auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) | |
| 211 | { | ||
| 212 | 672503 | return ctx.begin(); | |
| 213 | } | ||
| 214 | |||
| 215 | /// @brief Defines how to format SatSigId structs | ||
| 216 | /// @param[in] satSigId Struct to format | ||
| 217 | /// @param[in, out] ctx Format context | ||
| 218 | /// @return Output iterator | ||
| 219 | template<typename FormatContext> | ||
| 220 | 672503 | auto format(const NAV::SatSigId& satSigId, FormatContext& ctx) const | |
| 221 | { | ||
| 222 | 1345006 | return fmt::format_to(ctx.out(), "{0}-{1:02d}", satSigId.code, satSigId.satNum); | |
| 223 | } | ||
| 224 | }; | ||
| 225 | |||
| 226 | #endif | ||
| 227 | |||
| 228 | namespace std | ||
| 229 | { | ||
| 230 | /// @brief Hash function for SatId (needed for unordered_map) | ||
| 231 | template<> | ||
| 232 | struct hash<NAV::SatId> | ||
| 233 | { | ||
| 234 | /// @brief Hash function for SatId | ||
| 235 | /// @param[in] f Satellite identifier | ||
| 236 | 2556254 | std::size_t operator()(const NAV::SatId& f) const | |
| 237 | { | ||
| 238 | 2556254 | auto hash1 = std::hash<NAV::SatelliteSystem_>{}(NAV::SatelliteSystem_(f.satSys)); | |
| 239 | 2556245 | auto hash2 = static_cast<size_t>(f.satNum); | |
| 240 | |||
| 241 | 2556245 | return hash1 | (hash2 << 10); | |
| 242 | } | ||
| 243 | }; | ||
| 244 | /// @brief Hash function for SatSigId (needed for unordered_map) | ||
| 245 | template<> | ||
| 246 | struct hash<NAV::SatSigId> | ||
| 247 | { | ||
| 248 | /// @brief Hash function for SatSigId | ||
| 249 | /// @param[in] f Satellite signal identifier | ||
| 250 | 11223764 | std::size_t operator()(const NAV::SatSigId& f) const | |
| 251 | { | ||
| 252 | 11223764 | auto hash1 = static_cast<size_t>(f.code.getEnumValue()); | |
| 253 | 11222643 | auto hash2 = static_cast<size_t>(f.satNum); | |
| 254 | |||
| 255 | 11222643 | return hash1 | (hash2 << 8); | |
| 256 | } | ||
| 257 | }; | ||
| 258 | } // namespace std | ||
| 259 |