Fix bug in GLONASS year computation (Fixes: #347)

This commit is contained in:
Carles Fernandez 2020-07-19 14:44:18 +02:00
parent 52980978f5
commit 4ab7690085
No known key found for this signature in database
GPG Key ID: 4C583C52B0C3877D
5 changed files with 212 additions and 31 deletions

View File

@ -70,6 +70,7 @@ SPDX-FileCopyrightText: 2011-2020 Carles Fernandez-Prades <carles.fernandez@cttc
### Improvements in Reliability:
- Fixed a bug in GLONASS GNAV CRC computation.
- Fixed a bug in GLONASS time year.
- Fixed a possible buffer overflow in the generation of RTCM messages.
- Fixed bugs which could cause a random crash on receiver stopping.

View File

@ -11982,6 +11982,23 @@ boost::posix_time::ptime Rinex_Printer::compute_UTC_time(const Glonass_Gnav_Ephe
const double glot2utc = 3 * 3600;
double obs_time_glot = 0.0;
int32_t i = 0;
int J = 0;
if (eph.d_N_T >= 1 && eph.d_N_T <= 366)
{
J = 1;
}
else if (eph.d_N_T >= 367 && eph.d_N_T <= 731)
{
J = 2;
}
else if (eph.d_N_T >= 732 && eph.d_N_T <= 1096)
{
J = 3;
}
else if (eph.d_N_T >= 1097 && eph.d_N_T <= 1461)
{
J = 4;
}
// Get observation time in nearly GLONASS time. Correction for leap seconds done at the end
obs_time_glot = obs_time + glot2utc;
@ -11991,7 +12008,7 @@ boost::posix_time::ptime Rinex_Printer::compute_UTC_time(const Glonass_Gnav_Ephe
// Form date and time duration types
const boost::posix_time::time_duration t1(0, 0, tod);
const boost::gregorian::date d1(eph.d_yr, 1, 1);
const boost::gregorian::date d1(eph.d_yr - J + 1.0, 1, 1);
const boost::gregorian::days d2(eph.d_N_T - 1);
const boost::posix_time::ptime glo_time(d1 + d2, t1);
@ -12024,6 +12041,23 @@ double Rinex_Printer::get_leap_second(const Glonass_Gnav_Ephemeris& eph, const d
double obs_time_glot = 0.0;
int32_t i = 0;
double leap_second = 0;
int J = 0;
if (eph.d_N_T >= 1 && eph.d_N_T <= 366)
{
J = 1;
}
else if (eph.d_N_T >= 367 && eph.d_N_T <= 731)
{
J = 2;
}
else if (eph.d_N_T >= 732 && eph.d_N_T <= 1096)
{
J = 3;
}
else if (eph.d_N_T >= 1097 && eph.d_N_T <= 1461)
{
J = 4;
}
// Get observation time in nearly GLONASS time. Correction for leap seconds done at the end
obs_time_glot = gps_obs_time + glot2utc;
@ -12033,7 +12067,7 @@ double Rinex_Printer::get_leap_second(const Glonass_Gnav_Ephemeris& eph, const d
// Form date and time duration types
const boost::posix_time::time_duration t1(0, 0, tod);
const boost::gregorian::date d1(eph.d_yr, 1, 1);
const boost::gregorian::date d1(eph.d_yr - J + 1.0, 1, 1);
const boost::gregorian::days d2(eph.d_N_T - 1);
const boost::posix_time::ptime glo_time(d1 + d2, t1);

View File

@ -27,11 +27,29 @@
#include <string>
boost::posix_time::ptime Glonass_Gnav_Ephemeris::compute_GLONASS_time(const double offset_time) const
boost::posix_time::ptime Glonass_Gnav_Ephemeris::compute_GLONASS_time(double offset_time) const
{
boost::posix_time::time_duration t(0, 0, offset_time + d_tau_c + d_tau_n);
boost::gregorian::date d1(d_yr, 1, 1);
boost::gregorian::days d2(d_N_T - 1);
int J = 0;
if (d_N_T >= 1 && d_N_T <= 366)
{
J = 1;
}
else if (d_N_T >= 367 && d_N_T <= 731)
{
J = 2;
}
else if (d_N_T >= 732 && d_N_T <= 1096)
{
J = 3;
}
else if (d_N_T >= 1097 && d_N_T <= 1461)
{
J = 4;
}
const boost::posix_time::time_duration t(0, 0, offset_time + d_tau_c + d_tau_n);
const boost::gregorian::date d1(d_yr - J + 1.0, 1, 1);
const boost::gregorian::days d2(d_N_T - 1);
boost::posix_time::ptime glonass_time(d1 + d2, t);
return glonass_time;
@ -40,13 +58,29 @@ boost::posix_time::ptime Glonass_Gnav_Ephemeris::compute_GLONASS_time(const doub
boost::posix_time::ptime Glonass_Gnav_Ephemeris::glot_to_utc(const double offset_time, const double glot2utc_corr) const
{
double tod = 0.0;
double glot2utc = 3 * 3600;
const double glot2utc = 3 * 3600;
int J = 0;
if (d_N_T >= 1 && d_N_T <= 366)
{
J = 1;
}
else if (d_N_T >= 367 && d_N_T <= 731)
{
J = 2;
}
else if (d_N_T >= 732 && d_N_T <= 1096)
{
J = 3;
}
else if (d_N_T >= 1097 && d_N_T <= 1461)
{
J = 4;
}
tod = offset_time - glot2utc + glot2utc_corr + d_tau_n;
boost::posix_time::time_duration t(0, 0, tod);
boost::gregorian::date d1(d_yr, 1, 1);
boost::gregorian::days d2(d_N_T - 1);
const double tod = offset_time - glot2utc + glot2utc_corr + d_tau_n;
const boost::posix_time::time_duration t(0, 0, tod);
const boost::gregorian::date d1(d_yr - J + 1.0, 1, 1);
const boost::gregorian::days d2(d_N_T - 1);
boost::posix_time::ptime utc_time(d1 + d2, t);
return utc_time;
@ -55,32 +89,48 @@ boost::posix_time::ptime Glonass_Gnav_Ephemeris::glot_to_utc(const double offset
void Glonass_Gnav_Ephemeris::glot_to_gpst(double tod_offset, double glot2utc_corr, double glot2gpst_corr, int32_t* wn, double* tow) const
{
double tod = 0.0;
double glot2utc = 3 * 3600;
const double glot2utc = 3 * 3600;
double days = 0.0;
double total_sec = 0.0;
double sec_of_day = 0.0;
int i = 0;
int J = 0;
if (d_N_T >= 1 && d_N_T <= 366)
{
J = 1;
}
else if (d_N_T >= 367 && d_N_T <= 731)
{
J = 2;
}
else if (d_N_T >= 732 && d_N_T <= 1096)
{
J = 3;
}
else if (d_N_T >= 1097 && d_N_T <= 1461)
{
J = 4;
}
boost::gregorian::date gps_epoch{1980, 1, 6};
const boost::gregorian::date gps_epoch{1980, 1, 6};
// tk is relative to UTC(SU) + 3.00 hrs, so we need to convert to utc and add corrections
// tk plus 10 sec is the true tod since get_TOW is called when in str5
tod = tod_offset - glot2utc;
const double tod = tod_offset - glot2utc;
boost::posix_time::time_duration t(0, 0, tod);
boost::gregorian::date d1(d_yr, 1, 1);
boost::gregorian::days d2(d_N_T - 1);
boost::posix_time::ptime utc_time(d1 + d2, t);
boost::gregorian::date utc_date = utc_time.date();
const boost::posix_time::time_duration t(0, 0, tod);
const boost::gregorian::date d1(d_yr - J + 1.0, 1, 1);
const boost::gregorian::days d2(d_N_T - 1);
const boost::posix_time::ptime utc_time(d1 + d2, t);
const boost::gregorian::date utc_date = utc_time.date();
boost::posix_time::ptime gps_time;
// Adjust for leap second correction
for (i = 0; GLONASS_LEAP_SECONDS[i][0] > 0; i++)
{
boost::posix_time::time_duration t3(GLONASS_LEAP_SECONDS[i][3], GLONASS_LEAP_SECONDS[i][4], GLONASS_LEAP_SECONDS[i][5]);
boost::gregorian::date d3(GLONASS_LEAP_SECONDS[i][0], GLONASS_LEAP_SECONDS[i][1], GLONASS_LEAP_SECONDS[i][2]);
boost::posix_time::ptime ls_time(d3, t3);
const boost::posix_time::time_duration t3(GLONASS_LEAP_SECONDS[i][3], GLONASS_LEAP_SECONDS[i][4], GLONASS_LEAP_SECONDS[i][5]);
const boost::gregorian::date d3(GLONASS_LEAP_SECONDS[i][0], GLONASS_LEAP_SECONDS[i][1], GLONASS_LEAP_SECONDS[i][2]);
const boost::posix_time::ptime ls_time(d3, t3);
if (utc_time >= ls_time)
{
// We add the leap second when going from utc to gpst
@ -90,7 +140,6 @@ void Glonass_Gnav_Ephemeris::glot_to_gpst(double tod_offset, double glot2utc_cor
}
// Total number of days
std::string fdat = boost::posix_time::to_simple_string(gps_time);
days = static_cast<double>((utc_date - gps_epoch).days());
// Total number of seconds
@ -109,9 +158,8 @@ void Glonass_Gnav_Ephemeris::glot_to_gpst(double tod_offset, double glot2utc_cor
double Glonass_Gnav_Ephemeris::check_t(double time)
{
double corrTime;
double half_day = 43200.0; // seconds
corrTime = time;
const double half_day = 43200.0; // seconds
double corrTime = time;
if (time > half_day)
{
corrTime = time - 2.0 * half_day;
@ -128,8 +176,7 @@ double Glonass_Gnav_Ephemeris::check_t(double time)
// 20.3.3.3.3.1 User Algorithm for SV Clock Correction.
double Glonass_Gnav_Ephemeris::sv_clock_drift(double transmitTime, double timeCorrUTC)
{
double dt;
dt = check_t(transmitTime - d_t_b);
const double dt = check_t(transmitTime - d_t_b);
d_satClkDrift = -(d_tau_n + timeCorrUTC - d_gamma_n * dt);
// Correct satellite group delay and missing relativistic term here
// d_satClkDrift-=d_TGD;

View File

@ -24,6 +24,7 @@
#define GNSS_SDR_GLONASS_GNAV_EPHEMERIS_H
#include "glonass_gnav_utc_model.h"
#include <boost/date_time/posix_time/ptime.hpp> // for ptime
#include <boost/serialization/nvp.hpp>
#include <cstdint>
@ -94,7 +95,7 @@ public:
* \brief Computes the GLONASS System Time and returns a boost::posix_time::ptime object
* \ param offset_time Is the start of day offset to compute the time
*/
boost::posix_time::ptime compute_GLONASS_time(const double offset_time) const;
boost::posix_time::ptime compute_GLONASS_time(double offset_time) const;
/*!
* \brief Converts from GLONASST to UTC

View File

@ -51,6 +51,60 @@ TEST(GlonassGnavEphemerisTest, ComputeGlonassTime)
}
TEST(GlonassGnavEphemerisTest, ComputeGlonassTime2019)
{
Glonass_Gnav_Ephemeris gnav_eph;
gnav_eph.d_yr = 2019;
gnav_eph.d_N_T = 1366;
boost::posix_time::time_duration t(0, 0, 7560);
boost::gregorian::date d(gnav_eph.d_yr, 1, 1);
boost::gregorian::days d2(gnav_eph.d_N_T);
d = d + d2;
boost::gregorian::date expected_gdate;
boost::posix_time::time_duration expected_gtime;
boost::posix_time::ptime gtime = gnav_eph.compute_GLONASS_time(7560);
expected_gdate = gtime.date();
expected_gtime = gtime.time_of_day();
// Perform assertions of decoded fields
ASSERT_TRUE(expected_gdate.year() - d.year() < FLT_EPSILON);
ASSERT_TRUE(expected_gdate.month() - d.month() < FLT_EPSILON);
ASSERT_TRUE(expected_gdate.day() - d.day() < FLT_EPSILON);
ASSERT_TRUE(expected_gtime.hours() - t.hours() < FLT_EPSILON);
ASSERT_TRUE(expected_gtime.minutes() - t.minutes() < FLT_EPSILON);
ASSERT_TRUE(expected_gtime.seconds() - t.seconds() < FLT_EPSILON);
}
TEST(GlonassGnavEphemerisTest, ComputeGlonassTime2020)
{
Glonass_Gnav_Ephemeris gnav_eph;
gnav_eph.d_yr = 2020;
gnav_eph.d_N_T = 62;
boost::posix_time::time_duration t(0, 0, 7560);
boost::gregorian::date d(gnav_eph.d_yr, 1, 1);
boost::gregorian::days d2(gnav_eph.d_N_T);
d = d + d2;
boost::gregorian::date expected_gdate;
boost::posix_time::time_duration expected_gtime;
boost::posix_time::ptime gtime = gnav_eph.compute_GLONASS_time(7560);
expected_gdate = gtime.date();
expected_gtime = gtime.time_of_day();
// Perform assertions of decoded fields
ASSERT_TRUE(expected_gdate.year() - d.year() < FLT_EPSILON);
ASSERT_TRUE(expected_gdate.month() - d.month() < FLT_EPSILON);
ASSERT_TRUE(expected_gdate.day() - d.day() < FLT_EPSILON);
ASSERT_TRUE(expected_gtime.hours() - t.hours() < FLT_EPSILON);
ASSERT_TRUE(expected_gtime.minutes() - t.minutes() < FLT_EPSILON);
ASSERT_TRUE(expected_gtime.seconds() - t.seconds() < FLT_EPSILON);
}
/*!
* \brief Testing conversion from GLONASST to GPST
* \test Tests scenario for N_T when greater than 365 days. Possible values here from 1 to 365*4
@ -127,3 +181,47 @@ TEST(GlonassGnavEphemerisTest, ConvertGlonassT2GpsT3)
ASSERT_TRUE(week - true_week < FLT_EPSILON);
ASSERT_TRUE(tow - true_tow < FLT_EPSILON);
}
TEST(GlonassGnavEphemerisTest, ConvertGlonassT2GpsT4)
{
Glonass_Gnav_Ephemeris gnav_eph;
gnav_eph.d_yr = 2019;
gnav_eph.d_N_T = 1366;
double glo2utc = 3600 * 3;
double tod = 7560;
int week = 0.0;
double tow = 0.0;
double true_leap_sec = 18;
double true_week = 2072;
double true_tow = 447120 + true_leap_sec + tod;
gnav_eph.glot_to_gpst(tod + glo2utc, 0.0, 0.0, &week, &tow);
// Perform assertions of decoded fields
ASSERT_TRUE(week - true_week < FLT_EPSILON);
ASSERT_TRUE(tow - true_tow < FLT_EPSILON);
}
TEST(GlonassGnavEphemerisTest, ConvertGlonassT2GpsT5)
{
Glonass_Gnav_Ephemeris gnav_eph;
gnav_eph.d_yr = 2020;
gnav_eph.d_N_T = 62;
double glo2utc = 3600 * 3;
double tod = 7560;
int week = 0.0;
double tow = 0.0;
double true_leap_sec = 18;
double true_week = 2095;
double true_tow = 259200 + true_leap_sec + tod;
gnav_eph.glot_to_gpst(tod + glo2utc, 0.0, 0.0, &week, &tow);
// Perform assertions of decoded fields
ASSERT_TRUE(week - true_week < FLT_EPSILON);
ASSERT_TRUE(tow - true_tow < FLT_EPSILON);
}