diff --git a/src/core/system_parameters/CMakeLists.txt b/src/core/system_parameters/CMakeLists.txt index 3e25387ed..a34944710 100644 --- a/src/core/system_parameters/CMakeLists.txt +++ b/src/core/system_parameters/CMakeLists.txt @@ -19,6 +19,7 @@ set(SYSTEM_PARAMETERS_SOURCES galileo_fnav_message.cc galileo_has_data.cc galileo_inav_message.cc + galileo_ism.cc galileo_reduced_ced.cc beidou_dnav_navigation_message.cc beidou_dnav_ephemeris.cc @@ -55,6 +56,7 @@ set(SYSTEM_PARAMETERS_HEADERS galileo_fnav_message.h galileo_has_data.h galileo_inav_message.h + galileo_ism.h galileo_reduced_ced.h sbas_ephemeris.h gps_cnav_ephemeris.h @@ -115,6 +117,7 @@ target_link_libraries(core_system_parameters Boost::date_time Boost::serialization PRIVATE + Boost::headers Gflags::gflags Glog::glog ) diff --git a/src/core/system_parameters/Galileo_INAV.h b/src/core/system_parameters/Galileo_INAV.h index 72222baf2..9c9f19315 100644 --- a/src/core/system_parameters/Galileo_INAV.h +++ b/src/core/system_parameters/Galileo_INAV.h @@ -274,6 +274,23 @@ constexpr int32_t BITS_IN_OCTET = 8; constexpr int32_t FIRST_RS_BIT = 7; constexpr int32_t FIRST_RS_BIT_AFTER_IODNAV = 17; +/* Page 22 */ +const std::vector> ISM_CONSTELLATION_ID_BIT({{7, 3}}); +const std::vector> ISM_SERVICE_LEVEL_ID_BIT({{10, 3}}); +const std::vector> ISM_WN_BIT({{13, 12}}); +const std::vector> ISM_T0_BIT({{25, 9}}); +const std::vector> ISM_MASK_MSB_BIT({{34, 1}}); +const std::vector> ISM_MASK_BIT({{35, 32}}); +const std::vector> ISM_PCONST_BIT({{67, 4}}); +const std::vector> ISM_PSAT_BIT({{71, 4}}); +const std::vector> ISM_URA_BIT({{75, 4}}); +const std::vector> ISM_URE_BIT({{79, 4}}); +const std::vector> ISM_BNOM_BIT({{83, 4}}); +const std::vector> ISM_TVALIDITY_BIT({{87, 4}}); +const std::vector> ISM_CRC_BIT({{97, 32}}); +constexpr int32_t GALILEO_ISM_CRC_DATA_BITS = 96; +constexpr int32_t GALILEO_ISM_CRC_DATA_BYTES = 12; + /* Page 0 */ const std::vector> TIME_0_BIT({{7, 2}}); const std::vector> WN_0_BIT({{97, 12}}); diff --git a/src/core/system_parameters/galileo_inav_message.cc b/src/core/system_parameters/galileo_inav_message.cc index 81c47c3bb..fb28d0adc 100644 --- a/src/core/system_parameters/galileo_inav_message.cc +++ b/src/core/system_parameters/galileo_inav_message.cc @@ -1315,6 +1315,40 @@ int32_t Galileo_Inav_Message::page_jk_decoder(const char* data_jk) break; } + case 22: // Word Type 22: ARAIM Integrity Support Message (ISM) + DLOG(INFO) << "Word type 22 arrived"; + ism_constellation_id = read_octet_unsigned(data_jk_bits, ISM_CONSTELLATION_ID_BIT); + ism_service_level_id = read_octet_unsigned(data_jk_bits, ISM_SERVICE_LEVEL_ID_BIT); + ism_crc = static_cast(read_navigation_unsigned(data_jk_bits, ISM_CRC_BIT)); + gal_ism.set_ism_crc(ism_crc); + if (gal_ism.check_ism_crc(data_jk_bits)) + { + DLOG(INFO) << "I/NAV ARAIM Integrity Support Message CRC OK"; + gal_ism.set_ism_constellation_id(ism_constellation_id); + gal_ism.set_ism_service_level_id(ism_service_level_id); + if (ism_constellation_id == 0) + { + DLOG(INFO) << "I/NAV ARAIM Integrity Support Message in Test"; + } + if (ism_constellation_id == 1) + { + if (ism_service_level_id == 2) + { + gal_ism.set_ism_wn(static_cast(read_navigation_unsigned(data_jk_bits, ISM_WN_BIT))); + gal_ism.set_ism_t0(static_cast(read_navigation_unsigned(data_jk_bits, ISM_T0_BIT))); + gal_ism.set_ism_mask_msb(read_navigation_bool(data_jk_bits, ISM_MASK_MSB_BIT)); + gal_ism.set_ism_mask(static_cast(read_navigation_unsigned(data_jk_bits, ISM_MASK_BIT))); + gal_ism.set_ism_pconst(read_octet_unsigned(data_jk_bits, ISM_PCONST_BIT)); + gal_ism.set_ism_psat(read_octet_unsigned(data_jk_bits, ISM_PSAT_BIT)); + gal_ism.set_ism_ura(read_octet_unsigned(data_jk_bits, ISM_URA_BIT)); + gal_ism.set_ism_ure(read_octet_unsigned(data_jk_bits, ISM_URE_BIT)); + gal_ism.set_ism_bnom(read_octet_unsigned(data_jk_bits, ISM_BNOM_BIT)); + gal_ism.set_ism_Tvalidity(read_octet_unsigned(data_jk_bits, ISM_TVALIDITY_BIT)); + } + } + } + break; + case 0: // Word type 0: I/NAV Spare Word Time_0 = static_cast(read_navigation_unsigned(data_jk_bits, TIME_0_BIT)); DLOG(INFO) << "Time_0= " << Time_0; @@ -1336,3 +1370,9 @@ int32_t Galileo_Inav_Message::page_jk_decoder(const char* data_jk) } return page_number; } + + +Galileo_ISM Galileo_Inav_Message::get_galileo_ism() const +{ + return gal_ism; +} \ No newline at end of file diff --git a/src/core/system_parameters/galileo_inav_message.h b/src/core/system_parameters/galileo_inav_message.h index 1b37e9083..3acacecdd 100644 --- a/src/core/system_parameters/galileo_inav_message.h +++ b/src/core/system_parameters/galileo_inav_message.h @@ -23,6 +23,7 @@ #include "galileo_almanac_helper.h" #include "galileo_ephemeris.h" #include "galileo_iono.h" +#include "galileo_ism.h" #include "galileo_utc_model.h" #include "gnss_sdr_make_unique.h" // for std::unique_ptr in C++11 #include @@ -114,6 +115,8 @@ public: */ Galileo_Ephemeris get_reduced_ced() const; + Galileo_ISM get_galileo_ism() const; + inline bool get_flag_CRC_test() const { return flag_CRC_test; @@ -236,6 +239,7 @@ private: std::bitset regenerate_page_3(const std::vector& decoded) const; std::bitset regenerate_page_4(const std::vector& decoded) const; + Galileo_ISM gal_ism{}; std::string page_Even{}; std::vector rs_buffer; // Reed-Solomon buffer @@ -399,6 +403,10 @@ private: uint8_t IODnav_LSB19{}; uint8_t IODnav_LSB20{}; + uint32_t ism_crc{}; + uint8_t ism_constellation_id{}; + uint8_t ism_service_level_id{}; + bool flag_CRC_test{}; bool flag_all_ephemeris{}; // Flag indicating that all words containing ephemeris have been received bool flag_ephemeris_1{}; // Flag indicating that ephemeris 1/4 (word 1) have been received diff --git a/src/core/system_parameters/galileo_ism.cc b/src/core/system_parameters/galileo_ism.cc new file mode 100644 index 000000000..847a4ecd6 --- /dev/null +++ b/src/core/system_parameters/galileo_ism.cc @@ -0,0 +1,196 @@ +/*! + * \file galileo_ism.cc + * \brief Interface of a Galileo Integrity Support Message + * \author Carles Fernandez, 2024. cfernandez(at)cttc.cat + * + * ----------------------------------------------------------------------------- + * + * GNSS-SDR is a Global Navigation Satellite System software-defined receiver. + * This file is part of GNSS-SDR. + * + * Copyright (C) 2010-2024 (see AUTHORS file for a list of contributors) + * SPDX-License-Identifier: GPL-3.0-or-later + * + * ----------------------------------------------------------------------------- + */ + +#include "galileo_ism.h" +#include +#include +#include +#include + +void Galileo_ISM::set_ism_constellation_id(uint8_t const_id) +{ + this->ism_constellation_id = const_id; +} + + +void Galileo_ISM::set_ism_service_level_id(uint8_t sl_id) +{ + this->ism_service_level_id = sl_id; +} + + +void Galileo_ISM::set_ism_wn(uint16_t wn_ism) +{ + this->ism_wn = wn_ism; +} + + +void Galileo_ISM::set_ism_t0(uint16_t t0) +{ + this->ism_t0 = t0; +} + + +void Galileo_ISM::set_ism_mask_msb(bool mask_msb) +{ + this->ism_mask_msb = mask_msb; +} + + +void Galileo_ISM::set_ism_mask(uint32_t mask) +{ + this->ism_mask = mask; +} + + +void Galileo_ISM::set_ism_pconst(uint8_t pconst) +{ + this->ism_pconst = pconst; +} + + +void Galileo_ISM::set_ism_psat(uint8_t psat) +{ + this->ism_psat = psat; +} + + +void Galileo_ISM::set_ism_ura(uint8_t ura) +{ + this->ism_ura = ura; +} + + +void Galileo_ISM::set_ism_ure(uint8_t ure) +{ + this->ism_ure = ure; +} + + +void Galileo_ISM::set_ism_bnom(uint8_t bnom) +{ + this->ism_bnom = bnom; +} + + +void Galileo_ISM::set_ism_Tvalidity(uint8_t tvalidity) +{ + this->ism_Tvalidity = tvalidity; +} + + +void Galileo_ISM::set_ism_crc(uint32_t crc) +{ + this->ism_crc = crc; +} + + +uint16_t Galileo_ISM::get_WN_ISM() const +{ + return this->ism_wn; +} + + +uint16_t Galileo_ISM::get_t0_ISM() const +{ + return (this->ism_t0 * 1800); +} + + +double Galileo_ISM::get_pconst_value() const +{ + auto it = ISM_PCONST_MAP.find(this->ism_pconst); + if (it == ISM_PCONST_MAP.end()) + { + return 0.0; + } + return it->second; +} + + +double Galileo_ISM::get_psat_value() const +{ + auto it = ISM_PSAT_MAP.find(this->ism_psat); + if (it == ISM_PSAT_MAP.end()) + { + return 0.0; + } + return it->second; +} + + +float Galileo_ISM::get_ura_m() const +{ + auto it = ISM_URA_MAP.find(this->ism_ura); + if (it == ISM_URA_MAP.end()) + { + return 0.0; + } + return it->second; +} + + +float Galileo_ISM::get_ure_m() const +{ + auto it = ISM_URE_MAP.find(this->ism_ure); + if (it == ISM_URE_MAP.end()) + { + return 0.0; + } + return it->second; +} + + +float Galileo_ISM::get_bnom_m() const +{ + auto it = ISM_BNOM_MAP.find(this->ism_bnom); + if (it == ISM_BNOM_MAP.end()) + { + return 5.0; // + } + return it->second; +} + + +uint16_t Galileo_ISM::get_Tvalidity_hours() const +{ + auto it = ISM_TVALIDITY_MAP.find(this->ism_Tvalidity); + if (it == ISM_TVALIDITY_MAP.end()) + { + return 0.0; + } + return it->second; +} + + +bool Galileo_ISM::check_ism_crc(const std::bitset& bits) const +{ + boost::dynamic_bitset frame_bits(bits.to_string().substr(0, GALILEO_ISM_CRC_DATA_BITS)); + + std::vector bytes; + boost::to_block_range(frame_bits, std::back_inserter(bytes)); + std::reverse(bytes.begin(), bytes.end()); + + boost::crc_32_type crc32_ism; + crc32_ism.process_bytes(bytes.data(), GALILEO_ISM_CRC_DATA_BYTES); + const uint32_t crc_computed = crc32_ism.checksum(); + if (this->ism_crc == crc_computed) + { + return true; + } + + return false; +} \ No newline at end of file diff --git a/src/core/system_parameters/galileo_ism.h b/src/core/system_parameters/galileo_ism.h new file mode 100644 index 000000000..12436a606 --- /dev/null +++ b/src/core/system_parameters/galileo_ism.h @@ -0,0 +1,205 @@ +/*! + * \file galileo_ism.h + * \brief Interface of a Galileo Integrity Support Message + * \author Carles Fernandez, 2024. cfernandez(at)cttc.es + * + * ----------------------------------------------------------------------------- + * + * GNSS-SDR is a Global Navigation Satellite System software-defined receiver. + * This file is part of GNSS-SDR. + * + * Copyright (C) 2010-2024 (see AUTHORS file for a list of contributors) + * SPDX-License-Identifier: GPL-3.0-or-later + * + * ----------------------------------------------------------------------------- + */ + + +#ifndef GNSS_SDR_GALILEO_ISM_H +#define GNSS_SDR_GALILEO_ISM_H + +#include "Galileo_INAV.h" +#include +#include +#include + +/** \addtogroup Core + * \{ */ +/** \addtogroup System_Parameters + * \{ */ + + +/*! + * \brief This class is a storage for the GALILEO Integrity Support Message as described + * in Galileo ICD paragraph 5.2 + * + * See https://www.gsc-europa.eu/sites/default/files/sites/all/files/Galileo_OS_SIS_ICD_v2.1.pdf + */ +class Galileo_ISM +{ +public: + /*! + * Default constructor + */ + Galileo_ISM() = default; + + void set_ism_constellation_id(uint8_t const_id); + void set_ism_service_level_id(uint8_t sl_id); + void set_ism_wn(uint16_t wn_ism); + void set_ism_t0(uint16_t t0); + void set_ism_mask_msb(bool mask_msb); + void set_ism_mask(uint32_t mask); + void set_ism_pconst(uint8_t pconst); + void set_ism_psat(uint8_t psat); + void set_ism_ura(uint8_t ura); + void set_ism_ure(uint8_t ure); + void set_ism_bnom(uint8_t bnom); + void set_ism_Tvalidity(uint8_t tvalidity); + void set_ism_crc(uint32_t crc); + + bool check_ism_crc(const std::bitset& bits) const; + + double get_pconst_value() const; + double get_psat_value() const; + float get_ura_m() const; + float get_ure_m() const; + float get_bnom_m() const; + uint16_t get_WN_ISM() const; + uint16_t get_t0_ISM() const; + uint16_t get_Tvalidity_hours() const; + +private: + // ICD 2.1 Table 97 + std::unordered_map ISM_PCONST_MAP = { + {0, 1.0e-8}, + {1, 1.0e-7}, + {2, 1.0e-6}, + {3, 3.0e-6}, + {4, 6.0e-6}, + {5, 8.0e-6}, + {6, 1.0e-5}, + {7, 2.0e-5}, + {8, 4.0e-5}, + {9, 6.0e-5}, + {10, 8.0e-5}, + {11, 1.0e-4}, + {12, 1.25e-4}, + {13, 1.5e-4}, + {14, 1.75e-4}, + {15, 2.0e-4}}; + + // ICD 2.1 Table 98 + std::unordered_map ISM_PSAT_MAP = { + {0, 1.0e-7}, + {1, 3.0e-7}, + {2, 6.0e-7}, + {3, 1.0e-6}, + {4, 2.0e-6}, + {5, 3.0e-6}, + {6, 5.0e-6}, + {7, 7.0e-6}, + {8, 1.0e-5}, + {9, 1.2e-5}, + {10, 1.4e-5}, + {11, 1.7e-5}, + {12, 2.05e-5}, + {13, 2.4e-5}, + {14, 2.8e-5}, + {15, 3.0e-5}}; + + // ICD 2.1 Table 99 + std::unordered_map ISM_URA_MAP = { + {0, 0.75}, + {1, 1.0}, + {2, 1.5}, + {3, 2.0}, + {4, 2.25}, + {5, 2.50}, + {6, 2.75}, + {7, 3.0}, + {8, 3.25}, + {9, 3.50}, + {10, 3.75}, + {11, 4.0}, + {12, 4.50}, + {13, 5.0}, + {14, 5.50}, + {15, 6.0}}; + + // ICD 2.1 Table 100 + std::unordered_map ISM_URE_MAP = { + {0, 0.25}, + {1, 0.50}, + {2, 0.75}, + {3, 1.00}, + {4, 1.25}, + {5, 1.50}, + {6, 1.75}, + {7, 2.0}, + {8, 2.25}, + {9, 2.50}, + {10, 2.75}, + {11, 3.0}, + {12, 3.25}, + {13, 3.50}, + {14, 3.75}, + {15, 4.00}}; + + + // ICD 2.1 Table 101 + std::unordered_map ISM_BNOM_MAP = { + {0, 0.0}, + {1, 0.10}, + {2, 0.20}, + {3, 0.30}, + {4, 0.40}, + {5, 0.50}, + {6, 0.60}, + {7, 0.75}, + {8, 0.85}, + {9, 1.0}, + {10, 1.20}, + {11, 1.40}, + {12, 1.60}, + {13, 1.80}, + {14, 2.0}, + {15, 2.4}}; + + + // ICD 2.1 Table 102 + std::unordered_map ISM_TVALIDITY_MAP = { + {0, 1}, + {1, 2}, + {2, 3}, + {3, 4}, + {4, 6}, + {5, 8}, + {6, 12}, + {7, 18}, + {8, 24}, + {9, 36}, + {10, 48}, + {11, 72}, + {12, 120}, + {13, 168}, + {14, 720}, + {15, 1440}}; + + uint32_t ism_crc{}; + uint32_t ism_mask{}; + uint16_t ism_wn{}; + uint16_t ism_t0{}; + uint8_t ism_constellation_id{}; + uint8_t ism_service_level_id{}; + uint8_t ism_pconst{}; + uint8_t ism_psat{}; + uint8_t ism_ura{}; + uint8_t ism_ure{}; + uint8_t ism_bnom{}; + uint8_t ism_Tvalidity{}; + bool ism_mask_msb{}; +}; + +/** \} */ +/** \} */ +#endif // GNSS_SDR_GALILEO_ISM_H \ No newline at end of file