1
0
mirror of https://github.com/gnss-sdr/gnss-sdr synced 2025-02-07 06:30:11 +00:00

gps almanac decoding

Signed-off-by: joebre <joel.brenner@saphyrion.ch>
This commit is contained in:
joebre 2025-01-15 14:02:04 +01:00 committed by Carles Fernandez
parent deb127e177
commit acae99cb5c
4 changed files with 131 additions and 7 deletions

View File

@ -396,10 +396,19 @@ bool gps_l1_ca_telemetry_decoder_gs::decode_subframe(double cn0, bool flag_inver
const std::shared_ptr<Gps_Utc_Model> tmp_obj = std::make_shared<Gps_Utc_Model>(d_nav.get_utc_model());
this->message_port_pub(pmt::mp("telemetry"), pmt::make_any(tmp_obj));
}
if (d_nav.almanac_validation() == true)
{
const std::shared_ptr<Gps_Almanac> tmp_obj = std::make_shared<Gps_Almanac>(d_nav.get_almanac());
this->message_port_pub(pmt::mp("telemetry"), pmt::make_any(tmp_obj));
}
break;
case 5:
// get almanac (if available)
// TODO: implement almanac reader in navigation_message
if (d_nav.almanac_validation() == true)
{
const std::shared_ptr<Gps_Almanac> tmp_obj = std::make_shared<Gps_Almanac>(d_nav.get_almanac());
this->message_port_pub(pmt::mp("telemetry"), pmt::make_any(tmp_obj));
}
break;
default:
break;
}

View File

@ -226,6 +226,29 @@ const std::vector<std::pair<int32_t, int32_t>> HEALTH_SV23({{253, 6}});
const std::vector<std::pair<int32_t, int32_t>> HEALTH_SV24({{259, 6}});
// Almanac
const std::vector<std::pair<int32_t, int32_t>> ALM_ECC({{69, 16}});
constexpr double ALM_ECC_LSB = TWO_N21;
const std::vector<std::pair<int32_t, int32_t>> ALM_TOA({{91, 8}});
constexpr int32_t ALM_TOA_LSB = static_cast<int32_t>(TWO_P12);
const std::vector<std::pair<int32_t, int32_t>> ALM_DELTAI({{99, 16}});
constexpr double ALM_DELTAI_LSB = TWO_N19;
const std::vector<std::pair<int32_t, int32_t>> ALM_OMEGADOT({{121, 16}});
constexpr double ALM_OMEGADOT_LSB = TWO_N38;
const std::vector<std::pair<int32_t, int32_t>> ALM_SVHEALTH({{137, 8}});
const std::vector<std::pair<int32_t, int32_t>> ALM_SQUAREA({{151, 24}});
constexpr double ALM_SQUAREA_LSB = TWO_N11;
const std::vector<std::pair<int32_t, int32_t>> ALM_OMEGAZERO({{181, 24}});
constexpr double ALM_OMEGAZERO_LSB = TWO_N23;
const std::vector<std::pair<int32_t, int32_t>> ALM_OMEGA({{211, 24}});
constexpr double ALM_OMEGA_LSB = TWO_N23;
const std::vector<std::pair<int32_t, int32_t>> ALM_MZERO({{241, 24}});
constexpr double ALM_MZERO_LSB = TWO_N23;
const std::vector<std::pair<int32_t, int32_t>> ALM_AF0({{271, 8}, {290, 3}});
constexpr double ALM_AF0_LSB = TWO_N20;
const std::vector<std::pair<int32_t, int32_t>> ALM_AF1({{279, 11}});
constexpr double ALM_AF1_LSB = TWO_N38;
/** \} */
/** \} */
#endif // GNSS_SDR_GPS_L1_CA_H

View File

@ -201,9 +201,31 @@ int32_t Gps_Navigation_Message::subframe_decoder(const char* subframe)
SV_page = static_cast<int32_t>(read_navigation_unsigned(subframe_bits, SV_PAGE));
if (SV_page > 24 && SV_page < 33) // Page 4 (from Table 20-V. Data IDs and SV IDs in Subframes 4 and 5, IS-GPS-200M)
{
//! \TODO read almanac
if (SV_data_ID != 0)
{
a_M_0 = static_cast<double>(read_navigation_signed(subframe_bits, ALM_MZERO));
a_M_0 = a_M_0 * ALM_MZERO_LSB;
a_ecc = static_cast<double>(read_navigation_unsigned(subframe_bits, ALM_ECC));
a_ecc = a_ecc *ALM_ECC_LSB;
a_sqrtA = static_cast<double>(read_navigation_unsigned(subframe_bits, ALM_SQUAREA));
a_sqrtA = a_sqrtA *ALM_SQUAREA_LSB;
a_OMEGA_0 = static_cast<double>(read_navigation_signed(subframe_bits, ALM_OMEGAZERO));
a_OMEGA_0 = a_OMEGA_0 * ALM_OMEGAZERO_LSB;
a_omega = static_cast<double>(read_navigation_signed(subframe_bits, ALM_OMEGA));
a_omega = a_omega * ALM_OMEGA_LSB;
a_OMEGAdot = static_cast<double>(read_navigation_signed(subframe_bits, ALM_OMEGADOT));
a_OMEGAdot = a_OMEGAdot *ALM_OMEGADOT_LSB;
a_delta_i = static_cast<double>(read_navigation_signed(subframe_bits, ALM_DELTAI));
a_delta_i = a_delta_i * ALM_DELTAI_LSB;
a_af0 = static_cast<double>(read_navigation_signed(subframe_bits, ALM_AF0));
a_af0 = a_af0 * ALM_AF0_LSB;
a_af1 = static_cast<double>(read_navigation_signed(subframe_bits, ALM_AF1));
a_af1 = a_af1* ALM_AF1_LSB;
a_PRN = SV_page;
i_Toa = static_cast<int32_t>(read_navigation_unsigned(subframe_bits, ALM_TOA));
i_Toa = i_Toa * ALM_TOA_LSB;
flag_almanac_valid = true ;
}
}
@ -276,11 +298,34 @@ int32_t Gps_Navigation_Message::subframe_decoder(const char* subframe)
b_antispoofing_flag = read_navigation_bool(subframe_bits, ANTI_SPOOFING_FLAG);
SV_data_ID_5 = static_cast<int32_t>(read_navigation_unsigned(subframe_bits, SV_DATA_ID));
SV_page_5 = static_cast<int32_t>(read_navigation_unsigned(subframe_bits, SV_PAGE));
if (SV_page_5 < 25)
if ((SV_page_5 > 0) && (SV_page_5 < 25))
{
//! \TODO read almanac
if (SV_data_ID_5 != 0)
{
a_M_0 = static_cast<double>(read_navigation_signed(subframe_bits, ALM_MZERO));
a_M_0 = a_M_0 * ALM_MZERO_LSB;
a_ecc = static_cast<double>(read_navigation_unsigned(subframe_bits, ALM_ECC));
a_ecc = a_ecc *ALM_ECC_LSB;
a_sqrtA = static_cast<double>(read_navigation_unsigned(subframe_bits, ALM_SQUAREA));
a_sqrtA = a_sqrtA *ALM_SQUAREA_LSB;
a_OMEGA_0 = static_cast<double>(read_navigation_signed(subframe_bits, ALM_OMEGAZERO));
a_OMEGA_0 = a_OMEGA_0 * ALM_OMEGAZERO_LSB;
a_omega = static_cast<double>(read_navigation_signed(subframe_bits, ALM_OMEGA));
a_omega = a_omega * ALM_OMEGA_LSB;
a_OMEGAdot = static_cast<double>(read_navigation_signed(subframe_bits, ALM_OMEGADOT));
a_OMEGAdot = a_OMEGAdot *ALM_OMEGADOT_LSB;
a_delta_i = static_cast<double>(read_navigation_signed(subframe_bits, ALM_DELTAI));
a_delta_i = a_delta_i * ALM_DELTAI_LSB;
a_af0 = static_cast<double>(read_navigation_signed(subframe_bits, ALM_AF0));
a_af0 = a_af0 * ALM_AF0_LSB;
a_af1 = static_cast<double>(read_navigation_signed(subframe_bits, ALM_AF1));
a_af1 = a_af1* ALM_AF1_LSB;
a_PRN = SV_page_5;
i_Toa = static_cast<int32_t>(read_navigation_unsigned(subframe_bits, ALM_TOA));
i_Toa = i_Toa * ALM_TOA_LSB;
SV_Health = static_cast<int32_t>(read_navigation_unsigned(subframe_bits, ALM_SVHEALTH));
flag_almanac_valid = true;
}
}
if (SV_page_5 == 51) // Page 25 (from Table 20-V. Data IDs and SV IDs in Subframes 4 and 5, IS-GPS-200M)
@ -288,6 +333,7 @@ int32_t Gps_Navigation_Message::subframe_decoder(const char* subframe)
i_Toa = static_cast<int32_t>(read_navigation_unsigned(subframe_bits, T_OA));
i_Toa = i_Toa * T_OA_LSB;
i_WN_A = static_cast<int32_t>(read_navigation_unsigned(subframe_bits, WN_A));
flag_almanac_week_valid = true;
almanacHealth[1] = static_cast<int32_t>(read_navigation_unsigned(subframe_bits, HEALTH_SV1));
almanacHealth[2] = static_cast<int32_t>(read_navigation_unsigned(subframe_bits, HEALTH_SV2));
almanacHealth[3] = static_cast<int32_t>(read_navigation_unsigned(subframe_bits, HEALTH_SV3));
@ -435,6 +481,27 @@ Gps_Ephemeris Gps_Navigation_Message::get_ephemeris() const
}
Gps_Almanac Gps_Navigation_Message::get_almanac()
{
Gps_Almanac almanac;
almanac.SV_health = SV_Health;
almanac.PRN = a_PRN;
almanac.delta_i = a_delta_i;
almanac.toa = i_Toa;
almanac.WNa = i_WN_A;
almanac.M_0 = a_M_0;
almanac.ecc = a_ecc;
almanac.sqrtA = a_sqrtA;
almanac.OMEGA_0 = a_OMEGA_0;
almanac.omega = a_omega;
almanac.OMEGAdot = a_OMEGAdot;
almanac.af0 = a_af0;
almanac.af1 = a_af1;
flag_almanac_valid = false;
return almanac;
}
Gps_Iono Gps_Navigation_Message::get_iono()
{
Gps_Iono iono;
@ -490,3 +557,9 @@ bool Gps_Navigation_Message::satellite_validation()
}
return flag_data_valid;
}
bool Gps_Navigation_Message::almanac_validation()
{
return flag_almanac_valid && (i_WN_A > 0);
}

View File

@ -22,6 +22,7 @@
#include "GPS_L1_CA.h"
#include "gps_ephemeris.h"
#include "gps_almanac.h"
#include "gps_iono.h"
#include "gps_utc_model.h"
#include <bitset>
@ -61,7 +62,12 @@ public:
Gps_Iono get_iono();
/*!
* \brief Obtain a GPS UTC model parameters class filled with current SV data
* \brief Obtain a GPS almanac class filled with current SV data
*/
Gps_Almanac get_almanac();
/*!
* \brief Obtain a GPS Almanac model parameters class filled with current SV data
*/
Gps_Utc_Model get_utc_model();
@ -133,6 +139,7 @@ public:
}
bool satellite_validation();
bool almanac_validation();
private:
uint64_t read_navigation_unsigned(const std::bitset<GPS_SUBFRAME_BITS>& bits, const std::vector<std::pair<int32_t, int32_t>>& parameter) const;
@ -194,6 +201,17 @@ private:
// Almanac
int32_t i_Toa{}; // Almanac reference time [s]
int32_t i_WN_A{}; // Modulo 256 of the GPS week number to which the almanac reference time (i_Toa) is referenced
int32_t SV_Health{}; // Almanac SV healt
uint32_t a_PRN; // Almanac PRN
double a_delta_i{}; // Inclination Angle at Reference Time (relative to i_0 = 0.30 semi-circles)
double a_M_0{}; // Mean Anomaly at Reference Time [semi-circles]
double a_ecc{}; // Eccentricity [dimensionless]
double a_sqrtA{}; // Square Root of the Semi-Major Axis [sqrt(m)]
double a_OMEGA_0{}; // Longitude of Ascending Node of Orbit Plane at Weekly Epoch [semi-circles]
double a_omega{}; // Argument of Perigee [semi-cicles]
double a_OMEGAdot{}; // Rate of Right Ascension [semi-circles/s]
double a_af0{}; // Coefficient 0 of code phase offset model [s]
double a_af1{}; // Coefficient 1 of code phase offset model [s/s]
// satellite identification info
int32_t i_channel_ID{};
@ -224,7 +242,8 @@ private:
bool b_valid_ephemeris_set_flag{}; // flag indicating that this ephemeris set have passed the validation check
bool flag_iono_valid{}; // If set, it indicates that the ionospheric parameters are filled (page 18 has arrived and decoded)
bool flag_utc_model_valid{}; // If set, it indicates that the UTC model parameters are filled
bool flag_almanac_valid{}; // If set, it indicates that the almanac is filled
bool flag_almanac_week_valid{}; // If set, it indicates that the almanac week is valid
/* If true, enhanced level of integrity assurance.
*
* If false, indicates that the conveying signal is provided with the legacy level of integrity assurance.