mirror of
https://github.com/gnss-sdr/gnss-sdr
synced 2025-07-05 03:22:56 +00:00
gps almanac decoding
Signed-off-by: joebre <joel.brenner@saphyrion.ch>
This commit is contained in:
parent
deb127e177
commit
acae99cb5c
@ -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());
|
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));
|
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;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
// get almanac (if available)
|
if (d_nav.almanac_validation() == true)
|
||||||
// TODO: implement almanac reader in navigation_message
|
{
|
||||||
|
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:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -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}});
|
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
|
#endif // GNSS_SDR_GPS_L1_CA_H
|
||||||
|
@ -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));
|
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)
|
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)
|
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);
|
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_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));
|
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)
|
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)
|
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 = static_cast<int32_t>(read_navigation_unsigned(subframe_bits, T_OA));
|
||||||
i_Toa = i_Toa * T_OA_LSB;
|
i_Toa = i_Toa * T_OA_LSB;
|
||||||
i_WN_A = static_cast<int32_t>(read_navigation_unsigned(subframe_bits, WN_A));
|
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[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[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));
|
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 Gps_Navigation_Message::get_iono()
|
||||||
{
|
{
|
||||||
Gps_Iono iono;
|
Gps_Iono iono;
|
||||||
@ -490,3 +557,9 @@ bool Gps_Navigation_Message::satellite_validation()
|
|||||||
}
|
}
|
||||||
return flag_data_valid;
|
return flag_data_valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Gps_Navigation_Message::almanac_validation()
|
||||||
|
{
|
||||||
|
return flag_almanac_valid && (i_WN_A > 0);
|
||||||
|
}
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
#include "GPS_L1_CA.h"
|
#include "GPS_L1_CA.h"
|
||||||
#include "gps_ephemeris.h"
|
#include "gps_ephemeris.h"
|
||||||
|
#include "gps_almanac.h"
|
||||||
#include "gps_iono.h"
|
#include "gps_iono.h"
|
||||||
#include "gps_utc_model.h"
|
#include "gps_utc_model.h"
|
||||||
#include <bitset>
|
#include <bitset>
|
||||||
@ -61,7 +62,12 @@ public:
|
|||||||
Gps_Iono get_iono();
|
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();
|
Gps_Utc_Model get_utc_model();
|
||||||
|
|
||||||
@ -133,6 +139,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool satellite_validation();
|
bool satellite_validation();
|
||||||
|
bool almanac_validation();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint64_t read_navigation_unsigned(const std::bitset<GPS_SUBFRAME_BITS>& bits, const std::vector<std::pair<int32_t, int32_t>>& parameter) const;
|
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
|
// Almanac
|
||||||
int32_t i_Toa{}; // Almanac reference time [s]
|
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 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
|
// satellite identification info
|
||||||
int32_t i_channel_ID{};
|
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 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_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_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 true, enhanced level of integrity assurance.
|
||||||
*
|
*
|
||||||
* If false, indicates that the conveying signal is provided with the legacy level of integrity assurance.
|
* If false, indicates that the conveying signal is provided with the legacy level of integrity assurance.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user