1
0
mirror of https://github.com/gnss-sdr/gnss-sdr synced 2024-10-31 23:26:22 +00:00

bugreport: Time managment with boost posix time

Need to fix bug in time duration with posix time and deal with day
offsets in the code. Something seems off with day duration for long
periods of time.
This commit is contained in:
Damian Miralles 2017-10-24 08:51:38 -06:00
commit c9fba22307
17 changed files with 324 additions and 207 deletions

View File

@ -271,7 +271,7 @@ endif(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE} CACHE STRING "")
# Append -O2 optimization flag for Debug builds
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O2")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0")
# allow 'large' files in 32 bit builds
if(UNIX)

View File

@ -13,7 +13,7 @@ ControlThread.wait_for_flowgraph=false
;######### SIGNAL_SOURCE CONFIG ############
SignalSource.implementation=File_Signal_Source
SignalSource.filename=/Users/carlesfernandez/Documents/workspace/code2/trunk/data/2013_04_04_GNSS_SIGNAL_at_CTTC_SPAIN.dat ;/datalogger/signals/CTTC/2013_04_04_GNSS_SIGNAL_at_CTTC_SPAIN/2013_04_04_GNSS_SIGNAL_at_CTTC_SPAIN.dat ; <- PUT YOUR FILE HERE
SignalSource.filename=/archive/2013_04_04_GNSS_SIGNAL_at_CTTC_SPAIN.dat ;/datalogger/signals/CTTC/2013_04_04_GNSS_SIGNAL_at_CTTC_SPAIN/2013_04_04_GNSS_SIGNAL_at_CTTC_SPAIN.dat ; <- PUT YOUR FILE HERE
SignalSource.item_type=ishort
SignalSource.sampling_frequency=4000000
SignalSource.freq=1575420000

View File

@ -190,8 +190,8 @@ void rtklib_pvt_cc::msg_handler_telemetry(pmt::pmt_t msg)
// TODO Add GLONASS with gps week number and tow,
// insert new ephemeris record
DLOG(INFO) << "GLONASS GNAV New Ephemeris record inserted in global map with TOW =" << glonass_gnav_eph->d_TOW
<< ", GLONASS GNAV Week Number =" << glonass_gnav_eph->d_WN
<< " and Ephemeris IOD = " << glonass_gnav_eph->compute_GLONASS_time(glonass_gnav_eph->d_t_b)
<< ", Week Number =" << glonass_gnav_eph->d_WN
<< " and Ephemeris IOD in UTC = " << glonass_gnav_eph->compute_GLONASS_time(glonass_gnav_eph->d_t_b)
<< " from SV = " << glonass_gnav_eph->i_satellite_slot_number;
// update/insert new ephemeris record to the global ephemeris map
d_ls_pvt->glonass_gnav_ephemeris_map[glonass_gnav_eph->i_satellite_PRN] = *glonass_gnav_eph;
@ -542,7 +542,7 @@ int rtklib_pvt_cc::work (int noutput_items, gr_vector_const_void_star &input_ite
std::map<int,Gps_Ephemeris>::const_iterator tmp_eph_iter_gps = d_ls_pvt->gps_ephemeris_map.find(in[i][epoch].PRN);
std::map<int,Galileo_Ephemeris>::const_iterator tmp_eph_iter_gal = d_ls_pvt->galileo_ephemeris_map.find(in[i][epoch].PRN);
std::map<int,Gps_CNAV_Ephemeris>::const_iterator tmp_eph_iter_cnav = d_ls_pvt->gps_cnav_ephemeris_map.find(in[i][epoch].PRN);
std::map<int,Glonass_Gnav_Ephemeris>::const_iterator tmp_eph_iter_glo_gnav = d_ls_pvt->glonass_gnav_ephemeris_map.find(in[i][epoch].PRN);
std::map<int,Glonass_Gnav_Ephemeris>::const_iterator tmp_eph_iter_glo_gnav = d_ls_pvt->glonass_gnav_ephemeris_map.find(in[i][epoch].PRN);
if(((tmp_eph_iter_gps->second.i_satellite_PRN == in[i][epoch].PRN) && (std::string(in[i][epoch].Signal).compare("1C") == 0))
|| ((tmp_eph_iter_cnav->second.i_satellite_PRN == in[i][epoch].PRN) && (std::string(in[i][epoch].Signal).compare("2S") == 0))
|| ((tmp_eph_iter_gal->second.i_satellite_PRN == in[i][epoch].PRN) && (std::string(in[i][epoch].Signal).compare("1B") == 0))

View File

@ -116,6 +116,7 @@ bool rtklib_solver::get_PVT(const std::map<int,Gnss_Synchro> & gnss_observables_
std::map<int,Gps_Ephemeris>::const_iterator gps_ephemeris_iter;
std::map<int,Gps_CNAV_Ephemeris>::const_iterator gps_cnav_ephemeris_iter;
std::map<int,Glonass_Gnav_Ephemeris>::const_iterator glonass_gnav_ephemeris_iter;
const Glonass_Gnav_Utc_Model gnav_utc = this->glonass_gnav_utc_model;
this->set_averaging_flag(flag_averaging);
@ -279,75 +280,75 @@ bool rtklib_solver::get_PVT(const std::map<int,Gnss_Synchro> & gnss_observables_
}
break;
}
case 'R': //TODO This should be using rtk lib nomenclature
{
std::string sig_(gnss_observables_iter->second.Signal);
// GLONASS GNAV L1
if(sig_.compare("1G") == 0)
{
// 1 Glo - find the ephemeris for the current GLONASS SV observation. The SV Slot Number (PRN ID) is the map key
glonass_gnav_ephemeris_iter = glonass_gnav_ephemeris_map.find(gnss_observables_iter->second.PRN);
if (glonass_gnav_ephemeris_iter != glonass_gnav_ephemeris_map.cend())
{
//convert ephemeris from GNSS-SDR class to RTKLIB structure
geph_data[glo_valid_obs] = eph_to_rtklib(glonass_gnav_ephemeris_iter->second);
//convert observation from GNSS-SDR class to RTKLIB structure
obsd_t newobs = {{0,0}, '0', '0', {}, {}, {}, {}, {}, {}};
obs_data[glo_valid_obs] = insert_obs_to_rtklib(newobs,
gnss_observables_iter->second,
glonass_gnav_ephemeris_iter->second.d_WN,
0);//Band 0 (L1)
glo_valid_obs++;
}
else // the ephemeris are not available for this SV
{
DLOG(INFO) << "No ephemeris data for SV " << gnss_observables_iter->second.PRN;
}
case 'R': //TODO This should be using rtk lib nomenclature
{
std::string sig_(gnss_observables_iter->second.Signal);
// GLONASS GNAV L1
if(sig_.compare("1G") == 0)
{
// 1 Glo - find the ephemeris for the current GLONASS SV observation. The SV Slot Number (PRN ID) is the map key
glonass_gnav_ephemeris_iter = glonass_gnav_ephemeris_map.find(gnss_observables_iter->second.PRN);
if (glonass_gnav_ephemeris_iter != glonass_gnav_ephemeris_map.cend())
{
//convert ephemeris from GNSS-SDR class to RTKLIB structure
geph_data[glo_valid_obs] = eph_to_rtklib(glonass_gnav_ephemeris_iter->second, gnav_utc);
//convert observation from GNSS-SDR class to RTKLIB structure
obsd_t newobs = {{0,0}, '0', '0', {}, {}, {}, {}, {}, {}};
obs_data[glo_valid_obs] = insert_obs_to_rtklib(newobs,
gnss_observables_iter->second,
glonass_gnav_ephemeris_iter->second.d_WN,
0);//Band 0 (L1)
glo_valid_obs++;
}
else // the ephemeris are not available for this SV
{
DLOG(INFO) << "No ephemeris data for SV " << gnss_observables_iter->second.PRN;
}
}
// GLONASS GNAV L2
if(sig_.compare("2G") == 0)
{
// 1 GLONASS - find the ephemeris for the current GLONASS SV observation. The SV PRN ID is the map key
glonass_gnav_ephemeris_iter = glonass_gnav_ephemeris_map.find(gnss_observables_iter->second.PRN);
if (glonass_gnav_ephemeris_iter != glonass_gnav_ephemeris_map.cend())
{
bool found_L1_obs=false;
for (int i = 0; i < glo_valid_obs; i++)
{
if (geph_data[i].sat == (static_cast<int>(gnss_observables_iter->second.PRN+NSATGPS)))
{
obs_data[i] = insert_obs_to_rtklib(obs_data[i],
gnss_observables_iter->second,
glonass_gnav_ephemeris_iter->second.d_WN,
1);//Band 1 (L2)
found_L1_obs=true;
break;
}
}
if (!found_L1_obs)
}
// GLONASS GNAV L2
if(sig_.compare("2G") == 0)
{
// 1 GLONASS - find the ephemeris for the current GLONASS SV observation. The SV PRN ID is the map key
glonass_gnav_ephemeris_iter = glonass_gnav_ephemeris_map.find(gnss_observables_iter->second.PRN);
if (glonass_gnav_ephemeris_iter != glonass_gnav_ephemeris_map.cend())
{
bool found_L1_obs=false;
for (int i = 0; i < glo_valid_obs; i++)
{
if (geph_data[i].sat == (static_cast<int>(gnss_observables_iter->second.PRN+NSATGPS)))
{
//insert GLONASS GNAV L2 obs as new obs and also insert its ephemeris
//convert ephemeris from GNSS-SDR class to RTKLIB structure
geph_data[glo_valid_obs] = eph_to_rtklib(glonass_gnav_ephemeris_iter->second);
//convert observation from GNSS-SDR class to RTKLIB structure
obsd_t newobs = {{0,0}, '0', '0', {}, {}, {}, {}, {}, {}};
obs_data[glo_valid_obs] = insert_obs_to_rtklib(newobs,
obs_data[i] = insert_obs_to_rtklib(obs_data[i],
gnss_observables_iter->second,
glonass_gnav_ephemeris_iter->second.d_WN,
1); //Band 1 (L2)
glo_valid_obs++;
1);//Band 1 (L2)
found_L1_obs=true;
break;
}
}
else // the ephemeris are not available for this SV
{
DLOG(INFO) << "No ephemeris data for SV " << gnss_observables_iter->second.PRN;
}
}
if (!found_L1_obs)
{
//insert GLONASS GNAV L2 obs as new obs and also insert its ephemeris
//convert ephemeris from GNSS-SDR class to RTKLIB structure
geph_data[glo_valid_obs] = eph_to_rtklib(glonass_gnav_ephemeris_iter->second, gnav_utc);
//convert observation from GNSS-SDR class to RTKLIB structure
obsd_t newobs = {{0,0}, '0', '0', {}, {}, {}, {}, {}, {}};
obs_data[glo_valid_obs] = insert_obs_to_rtklib(newobs,
gnss_observables_iter->second,
glonass_gnav_ephemeris_iter->second.d_WN,
1); //Band 1 (L2)
glo_valid_obs++;
}
break;
}
}
else // the ephemeris are not available for this SV
{
DLOG(INFO) << "No ephemeris data for SV " << gnss_observables_iter->second.PRN;
}
}
break;
}
default :
DLOG(INFO) << "Hybrid observables: Unknown GNSS";
break;

View File

@ -87,7 +87,7 @@ public:
std::map<int,Galileo_Ephemeris> galileo_ephemeris_map; //!< Map storing new Galileo_Ephemeris
std::map<int,Gps_Ephemeris> gps_ephemeris_map; //!< Map storing new GPS_Ephemeris
std::map<int,Gps_CNAV_Ephemeris> gps_cnav_ephemeris_map; //!< Map storing new GPS_CNAV_Ephemeris
std::map<int,Glonass_Gnav_Ephemeris> glonass_gnav_ephemeris_map; //!< Map storing new GLONASS GNAV Ephmeris
std::map<int,Glonass_Gnav_Ephemeris> glonass_gnav_ephemeris_map; //!< Map storing new GLONASS GNAV Ephmeris
Galileo_Utc_Model galileo_utc_model;
Galileo_Iono galileo_iono;

View File

@ -45,18 +45,18 @@ obsd_t insert_obs_to_rtklib(obsd_t & rtklib_obs, const Gnss_Synchro & gnss_synch
//Galileo is the third satellite system for RTKLIB, so, add the required offset to discriminate Galileo ephemeris
switch(gnss_synchro.System)
{
case 'G':
rtklib_obs.sat = gnss_synchro.PRN;
break;
case 'E':
rtklib_obs.sat = gnss_synchro.PRN+NSATGPS+NSATGLO;
break;
case 'R':
rtklib_obs.sat = gnss_synchro.PRN+NSATGPS;
break;
case 'G':
rtklib_obs.sat = gnss_synchro.PRN;
break;
case 'E':
rtklib_obs.sat = gnss_synchro.PRN+NSATGPS+NSATGLO;
break;
case 'R':
rtklib_obs.sat = gnss_synchro.PRN+NSATGPS;
break;
default:
rtklib_obs.sat = gnss_synchro.PRN;
default:
rtklib_obs.sat = gnss_synchro.PRN;
}
rtklib_obs.time = gpst2time(adjgpsweek(week), gnss_synchro.RX_time);
rtklib_obs.rcv = 1;
@ -64,14 +64,12 @@ obsd_t insert_obs_to_rtklib(obsd_t & rtklib_obs, const Gnss_Synchro & gnss_synch
return rtklib_obs;
}
geph_t eph_to_rtklib(const Glonass_Gnav_Ephemeris & glonass_gnav_eph)
geph_t eph_to_rtklib(const Glonass_Gnav_Ephemeris & glonass_gnav_eph, const Glonass_Gnav_Utc_Model & gnav_clock_model)
{
int week;
double week, sec;
int adj_week;
geph_t rtklib_sat = {0, 0, 0, 0, 0, 0, {0, 0}, {0, 0}, {0.0, 0.0, 0.0}, {0.0, 0.0,
0.0}, {0.0, 0.0, 0.0}, 0.0, 0.0, 0.0};
gtime_t t_utc;
struct tm utcinfo;
0.0}, {0.0, 0.0, 0.0}, 0.0, 0.0, 0.0};
rtklib_sat.sat = glonass_gnav_eph.i_satellite_slot_number + NSATGPS; /* satellite number */
rtklib_sat.iode = static_cast<int>(glonass_gnav_eph.d_t_b); /* IODE (0-6 bit of tb field) */
@ -92,25 +90,15 @@ geph_t eph_to_rtklib(const Glonass_Gnav_Ephemeris & glonass_gnav_eph)
rtklib_sat.gamn = glonass_gnav_eph.d_gamma_n; /* SV relative freq bias */
rtklib_sat.age = static_cast<int>(glonass_gnav_eph.d_Delta_tau_n); /* delay between L1 and L2 (s) */
utcinfo.tm_mon = 0;
utcinfo.tm_mday = glonass_gnav_eph.d_N_T;
utcinfo.tm_year = glonass_gnav_eph.d_yr - 1900;
utcinfo.tm_hour = -6;
utcinfo.tm_min = 0;
utcinfo.tm_sec = glonass_gnav_eph.d_tod;
t_utc.time = mktime(&utcinfo);
t_utc.sec = glonass_gnav_eph.d_tau_c;
rtklib_sat.toe = utc2gpst(t_utc); /* message frame time (gpst) */
// Time expressed in GPS Time but using RTKLib format
glonass_gnav_eph.glot_to_gpst(glonass_gnav_eph.d_tod, gnav_clock_model.d_tau_c, gnav_clock_model.d_tau_gps, &week, &sec);
adj_week = adjgpsweek(static_cast<int>(week));
rtklib_sat.toe = gpst2time(adj_week, sec);
utcinfo.tm_mon = 0;
utcinfo.tm_mday = glonass_gnav_eph.d_N_T;
utcinfo.tm_year = glonass_gnav_eph.d_yr - 1900;
utcinfo.tm_hour = -6;
utcinfo.tm_min = 0;
utcinfo.tm_sec = glonass_gnav_eph.d_t_k;
t_utc.time = mktime(&utcinfo);
t_utc.sec = glonass_gnav_eph.d_tau_c;
rtklib_sat.tof = utc2gpst(t_utc); /* message frame time (gpst) */
// Time expressed in GPS Time but using RTKLib format
glonass_gnav_eph.glot_to_gpst(glonass_gnav_eph.d_t_k, gnav_clock_model.d_tau_c, gnav_clock_model.d_tau_gps, &week, &sec);
adj_week = adjgpsweek(static_cast<int>(week));
rtklib_sat.tof = gpst2time(adj_week, sec);
return rtklib_sat;
}
@ -119,7 +107,7 @@ geph_t eph_to_rtklib(const Glonass_Gnav_Ephemeris & glonass_gnav_eph)
eph_t eph_to_rtklib(const Galileo_Ephemeris & gal_eph)
{
eph_t rtklib_sat = {0, 0, 0, 0, 0, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, {}, 0.0, 0.0 };
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, {}, 0.0, 0.0 };
//Galileo is the third satellite system for RTKLIB, so, add the required offset to discriminate Galileo ephemeris
rtklib_sat.sat = gal_eph.i_satellite_PRN+NSATGPS+NSATGLO;
rtklib_sat.A = gal_eph.A_1 * gal_eph.A_1;
@ -169,7 +157,7 @@ eph_t eph_to_rtklib(const Galileo_Ephemeris & gal_eph)
eph_t eph_to_rtklib(const Gps_Ephemeris & gps_eph)
{
eph_t rtklib_sat = {0, 0, 0, 0, 0, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, {}, 0.0, 0.0 };
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, {}, 0.0, 0.0 };
rtklib_sat.sat = gps_eph.i_satellite_PRN;
rtklib_sat.A = gps_eph.d_sqrt_A * gps_eph.d_sqrt_A;
rtklib_sat.M0 = gps_eph.d_M_0;
@ -220,7 +208,7 @@ eph_t eph_to_rtklib(const Gps_Ephemeris & gps_eph)
eph_t eph_to_rtklib(const Gps_CNAV_Ephemeris & gps_cnav_eph)
{
eph_t rtklib_sat = {0, 0, 0, 0, 0, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, {}, 0.0, 0.0 };
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, {}, 0.0, 0.0 };
rtklib_sat.sat = gps_cnav_eph.i_satellite_PRN;
const double A_REF = 26559710.0; // See IS-GPS-200H, pp. 170
rtklib_sat.A = A_REF + gps_cnav_eph.d_DELTA_A;

View File

@ -37,6 +37,7 @@
#include "gps_ephemeris.h"
#include "gps_cnav_ephemeris.h"
#include "glonass_gnav_ephemeris.h"
#include "glonass_gnav_utc_model.h"
eph_t eph_to_rtklib(const Galileo_Ephemeris & gal_eph);
eph_t eph_to_rtklib(const Gps_Ephemeris & gps_eph);
@ -46,7 +47,7 @@ eph_t eph_to_rtklib(const Gps_CNAV_Ephemeris & gps_cnav_eph);
* \param glonass_gnav_eph GLONASS GNAV Ephemeris structure
* \return Ephemeris structure for RTKLIB parsing
*/
geph_t eph_to_rtklib(const Glonass_Gnav_Ephemeris & glonass_gnav_eph);
geph_t eph_to_rtklib(const Glonass_Gnav_Ephemeris & glonass_gnav_eph, const Glonass_Gnav_Utc_Model & gnav_clock_model);
obsd_t insert_obs_to_rtklib(obsd_t & rtklib_obs, const Gnss_Synchro & gnss_synchro, int week, int band);

View File

@ -221,7 +221,8 @@ void glonass_l1_ca_telemetry_decoder_cc::decode_string(double *frame_symbols,int
if(d_nav.flag_update_slot_number == true)
{
LOG(INFO) << "GLONASS GNAV Slot Number Identified on channel " << d_channel;
d_satellite.what_block(d_satellite.get_system(), d_nav.get_ephemeris().d_n);
d_satellite.update_PRN(d_nav.gnav_ephemeris.d_n);
d_satellite.what_block(d_satellite.get_system(), d_nav.gnav_ephemeris.d_n);
d_nav.flag_update_slot_number = false;
}
}
@ -354,7 +355,8 @@ int glonass_l1_ca_telemetry_decoder_cc::general_work (int noutput_items __attrib
if (this->d_flag_preamble == true and d_nav.flag_TOW_new == true)
//update TOW at the preamble instant
{
d_TOW_at_current_symbol = floor((d_nav.d_TOW - GLONASS_GNAV_PREAMBLE_DURATION_S)*1000.0)/1000.0;
double dummy_dtow = d_nav.get_TOW() - GLONASS_GNAV_PREAMBLE_DURATION_S;
d_TOW_at_current_symbol = d_nav.gnav_ephemeris.d_TOW - GLONASS_GNAV_PREAMBLE_DURATION_S;
d_nav.flag_TOW_new = false;
}

View File

@ -91,8 +91,6 @@ const int GLONASS_L1_CA_NBR_SATS = 24; // STRING DATA WITHOUT PREAMB
//FIXME Probably should use leap seconds definitions of rtklib
const double GLONASS_LEAP_SECONDS[21][7] = { /* leap seconds (y,m,d,h,m,s,utc-gpst) */
{2019, 1, 1, 0, 0, 0, -20},
{2018, 1, 1, 0, 0, 0, -19},
{2017, 1, 1, 0, 0, 0, -18},
{2015, 7, 1, 0, 0, 0, -17},
{2012, 7, 1, 0, 0, 0, -16},
@ -149,7 +147,7 @@ const int GLONASS_L1_CA_HISTORY_DEEP = 100;
// NAVIGATION MESSAGE DEMODULATION AND DECODING
#define GLONASS_GNAV_PREAMBLE {1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0}
const double GLONASS_GNAV_PREAMBLE_DURATION_S = 0.3;
const double GLONASS_GNAV_PREAMBLE_DURATION_S = 0.300;
const int GLONASS_GNAV_PREAMBLE_LENGTH_BITS = 30;
const int GLONASS_GNAV_PREAMBLE_LENGTH_SYMBOLS = 300;
const int GLONASS_GNAV_PREAMBLE_PERIOD_SYMBOLS = 2000;

View File

@ -79,20 +79,94 @@ Glonass_Gnav_Ephemeris::Glonass_Gnav_Ephemeris()
d_tau_c = 0.0;
d_TOW = 0.0; // tow of the start of frame
d_WN = 0.0; // week number of the start of frame
d_tod = 0.0;
}
boost::posix_time::ptime Glonass_Gnav_Ephemeris::compute_GLONASS_time(const double offset_time) const
{
boost::posix_time::time_duration t(0, 0, offset_time + d_tau_c);
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);
boost::gregorian::days d2(d_N_T - 1);
boost::posix_time::ptime glonass_time(d1+d2, t);
return glonass_time;
}
boost::posix_time::ptime Glonass_Gnav_Ephemeris::glot_to_utc(const double offset_time, const double glot2utc_corr) const
{
double tod = 0.0;
double utcsu2utc = 3*3600;
double glot2utcsu = 3*3600;
tod = offset_time - glot2utcsu - utcsu2utc + 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);
boost::posix_time::ptime utc_time(d1+d2, t);
return utc_time;
}
void Glonass_Gnav_Ephemeris::glot_to_gpst(double tod_offset, double glot2utc_corr, double glot2gpst_corr, double * wn, double * tow) const
{
double tod = 0.0;
double dayofweek = 0.0;
double utcsu2utc = 3*3600;
double glot2utcsu = 3*3600;
double days = 0.0;
double total_sec = 0.0, sec_of_day = 0.0;
int i = 0;
boost::gregorian::days d3(0);
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 - glot2utcsu - utcsu2utc;
boost::posix_time::time_duration t(0, 0, tod);
boost::gregorian::date d1(d_yr, 1, 1);
boost::gregorian::days d2(d_N_T);
if(tod < 0)
{
d3 = boost::gregorian::days(-1);
}
boost::posix_time::ptime glonass_time(d1+d2+d3, t);
boost::gregorian::date utc_date = glonass_time.date();
// Total number of days
std::string fdat = boost::posix_time::to_simple_string(glonass_time);
days = static_cast<double>((utc_date - gps_epoch).days());
// Total number of seconds
sec_of_day = static_cast<double>((glonass_time.time_of_day()).total_seconds());
total_sec = days*86400 + sec_of_day;
for (i = 0; GLONASS_LEAP_SECONDS[i][0]>0; i++)
{
if (d_yr >= GLONASS_LEAP_SECONDS[i][0])
{
// We add the leap second when going from utc to gpst
total_sec += fabs(GLONASS_LEAP_SECONDS[i][6]);
break;
}
}
// Compute Week number
*wn = floor(total_sec/604800);
// Compute the arithmetic modules to wrap around range
*tow = total_sec - 604800*floor(total_sec/604800);
// Perform corrections from fractional seconds
*tow += glot2utc_corr + glot2gpst_corr;
}
double Glonass_Gnav_Ephemeris::check_t(double time)
{
double corrTime;

View File

@ -159,6 +159,17 @@ public:
*/
boost::posix_time::ptime compute_GLONASS_time(const double offset_time) const;
/*!
* \brief Converts from GLONASST to UTC
* \ param [I]
* \ param offset_time Is the start of day offset to compute the time
* \ returns UTC time as a boost::posix_time::ptime object
*/
boost::posix_time::ptime glot_to_utc(const double offset_time, const double glot2utc_corr) const;
void glot_to_gpst(double tod_offset, double glot2utc_corr, double glot2gpst_corr, double * WN, double * TOW) const;
/*!
* Default constructor
*/

View File

@ -43,6 +43,7 @@
void Glonass_Gnav_Navigation_Message::reset()
{
//!< Satellite Identification
i_satellite_PRN = 0;
i_alm_satellite_slot_number = 0; //!< SV Orbit Slot Number
flag_update_slot_number = false;
@ -74,7 +75,6 @@ void Glonass_Gnav_Navigation_Message::reset()
//broadcast orbit 1
flag_TOW_set = false;
flag_TOW_new = false;
d_TOW = 0.0; //!< Time of GPS Week of the ephemeris set (taken from subframes TOW) [s]
flag_CRC_test = false;
d_frame_ID = 0;
@ -325,7 +325,7 @@ double Glonass_Gnav_Navigation_Message::get_WN()
boost::gregorian::date gps_epoch { 1980, 1, 6 };
// Map to UTC
boost::gregorian::date glo_date(gnav_ephemeris.d_yr, 1, 1);
boost::gregorian::days d2(gnav_ephemeris.d_N_T);
boost::gregorian::days d2(gnav_ephemeris.d_N_T-1);
glo_date = glo_date + d2;
@ -363,7 +363,7 @@ double Glonass_Gnav_Navigation_Message::get_TOW()
// 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 = (gnav_ephemeris.d_t_k + 10) - glot2utcsu - utcsu2utc + gnav_utc_model.d_tau_c + gnav_utc_model.d_tau_gps;
TOD = (gnav_ephemeris.d_t_k + 10) - glot2utcsu - utcsu2utc;// + gnav_utc_model.d_tau_c + gnav_utc_model.d_tau_gps;
boost::gregorian::date glo_date(gnav_ephemeris.d_yr, 1, 1);
@ -375,10 +375,10 @@ double Glonass_Gnav_Navigation_Message::get_TOW()
for (i = 0; GLONASS_LEAP_SECONDS[i][0]>0; i++)
{
if (GLONASS_LEAP_SECONDS[i][0] == gnav_ephemeris.d_yr)
if (gnav_ephemeris.d_yr >= GLONASS_LEAP_SECONDS[i][0])
{
// We add the leap second when going from utc to gpst
TOW += GLONASS_LEAP_SECONDS[i][6];
TOW += fabs(GLONASS_LEAP_SECONDS[i][6]);
}
}
// Compute the arithmetic modules to wrap around range
@ -513,18 +513,18 @@ int Glonass_Gnav_Navigation_Message::string_decoder(std::string frame_string)
// 3). Set TOW once the year has been defined, it helps with leap second determination
if (flag_ephemeris_str_1 == true)
{
d_TOW = get_TOW();
gnav_ephemeris.d_TOW = d_TOW;
gnav_ephemeris.d_WN = get_WN();
flag_TOW_set = true;
flag_TOW_new = true;
}
{
gnav_ephemeris.glot_to_gpst(gnav_ephemeris.d_t_k+10, gnav_utc_model.d_tau_c, gnav_utc_model.d_tau_gps, &gnav_ephemeris.d_WN, &gnav_ephemeris.d_TOW);
flag_TOW_set = true;
flag_TOW_new = true;
}
// 4) Set time of day (tod) when ephemeris data is complety decoded
gnav_ephemeris.d_tod = gnav_ephemeris.d_t_k + 2*d_string_ID;
}
break;
case 6:
@ -573,8 +573,8 @@ int Glonass_Gnav_Navigation_Message::string_decoder(std::string frame_string)
flag_almanac_str_7 = true;
}
break;
break;
case 8:
// --- It is string 8 ----------------------------------------------
i_alm_satellite_slot_number = static_cast<unsigned int>(read_navigation_unsigned(string_bits, n_A));
@ -594,7 +594,6 @@ int Glonass_Gnav_Navigation_Message::string_decoder(std::string frame_string)
flag_almanac_str_8 = true;
break;
case 9:
// --- It is string 9 ----------------------------------------------
if (flag_almanac_str_8 == true)
@ -617,7 +616,6 @@ int Glonass_Gnav_Navigation_Message::string_decoder(std::string frame_string)
flag_almanac_str_9 = true;
}
break;
case 10:
// --- It is string 10 ---------------------------------------------
i_alm_satellite_slot_number = static_cast<unsigned int>(read_navigation_unsigned(string_bits, n_A));
@ -660,7 +658,6 @@ int Glonass_Gnav_Navigation_Message::string_decoder(std::string frame_string)
flag_almanac_str_11 = true;
}
break;
case 12:
// --- It is string 12 ---------------------------------------------
i_alm_satellite_slot_number = static_cast<unsigned int>(read_navigation_unsigned(string_bits, n_A));
@ -702,7 +699,6 @@ int Glonass_Gnav_Navigation_Message::string_decoder(std::string frame_string)
flag_almanac_str_13 = true;
}
break;
case 14:
// --- It is string 14 ---------------------------------------------
if (d_frame_ID == 5)
@ -750,14 +746,15 @@ int Glonass_Gnav_Navigation_Message::string_decoder(std::string frame_string)
flag_almanac_str_15 = true;
}
break;
default:
LOG(INFO) << "GLONASS GNAV: Invalid String ID of received. Received " << d_string_ID
<< ", but acceptable range is from 1-15";
break;
} // switch string ID ...
return d_string_ID;
}

View File

@ -65,6 +65,10 @@ public:
unsigned int d_string_ID;
bool flag_update_slot_number;
// satellite identification info
int i_channel_ID;
unsigned int i_satellite_PRN;
Glonass_Gnav_Ephemeris gnav_ephemeris; //!< Ephemeris information decoded
Glonass_Gnav_Utc_Model gnav_utc_model; //!< UTC model information
Glonass_Gnav_Almanac gnav_almanac[GLONASS_L1_CA_NBR_SATS]; //!< Almanac information for all 24 satellites
@ -97,7 +101,6 @@ public:
bool flag_TOW_set; //!< Flag indicating when the TOW has been set
bool flag_TOW_new; //!< Flag indicating when a new TOW has been computed
double d_TOW; //!< Time of GPS Week of the ephemeris set (taken from subframes TOW) [s]
// Clock terms
double d_satClkCorr; // Satellite clock error

View File

@ -135,6 +135,27 @@ void Gnss_Satellite::set_system(const std::string& system_)
}
void Gnss_Satellite::update_PRN(unsigned int PRN_)
{
if (system.compare("Glonass") != 0)
{
DLOG(INFO) << "Trying to update PRN for not GLONASS system";
PRN = 0;
}
else
{
if (PRN_ < 1 or PRN_ > 24)
{
DLOG(INFO) << "This PRN is not defined";
// Adjusting for PRN 26, now used in
PRN = PRN_;
}
else
{
PRN = PRN_;
}
}
}
void Gnss_Satellite::set_PRN(unsigned int PRN_)

View File

@ -50,6 +50,7 @@ public:
Gnss_Satellite(); //!< Default Constructor.
Gnss_Satellite(const std::string& system_, unsigned int PRN_); //!< Concrete GNSS satellite Constructor.
~Gnss_Satellite(); //!< Default Destructor.
void update_PRN(unsigned int PRN); //!< Updates the PRN Number when information is decoded, only applies to GLONASS GNAV messages
unsigned int get_PRN() const; //!< Gets satellite's PRN
std::string get_system() const; //!< Gets the satellite system {"GPS", "GLONASS", "SBAS", "Galileo", "Beidou"}
std::string get_system_short() const; //!< Gets the satellite system {"G", "R", "SBAS", "E", "C"}

View File

@ -63,3 +63,23 @@ TEST(GlonassGnavEphemerisTest, ComputeGlonassTime)
ASSERT_TRUE(expected_gtime.minutes() - t.minutes() < FLT_EPSILON );
ASSERT_TRUE(expected_gtime.seconds() - t.seconds() < FLT_EPSILON );
}
TEST(GlonassGnavEphemerisTest, ConvertGlonassT2GpsT)
{
Glonass_Gnav_Ephemeris gnav_eph;
gnav_eph.d_yr = 2005;
gnav_eph.d_N_T = 32;
double tod = 70200;
double week = 0.0;
double tow = 0.0;
double true_leap_sec = 13;
double true_week = 1307;
double true_tow = 480600+true_leap_sec;
gnav_eph.glot_to_gpst(tod, 0.0, 0.0, &week, &tow);
// Perform assertions of decoded fields
ASSERT_TRUE(week - true_week < FLT_EPSILON );
ASSERT_TRUE(tow - true_week < FLT_EPSILON );
}

View File

@ -41,76 +41,76 @@ title('Doppler frequency')
xlabel('TOW [s]')
ylabel('[Hz]');
%read true obs from simulator (optional)
GPS_STARTOFFSET_s = 68.802e-3;
true_observables_log_path='/home/javier/git/gnss-sdr/build/obs_out.bin';
GNSS_true_observables= read_true_sim_observables_dump(true_observables_log_path);
%correct the clock error using true values (it is not possible for a receiver to correct
%the receiver clock offset error at the observables level because it is required the
%decoding of the ephemeris data and solve the PVT equations)
SPEED_OF_LIGHT_M_S = 299792458.0;
%find the reference satellite
[~,ref_sat_ch]=min(GNSS_observables.Pseudorange_m(:,min_idx+1));
shift_time_s=GNSS_true_observables.Pseudorange_m(ref_sat_ch,:)/SPEED_OF_LIGHT_M_S-GPS_STARTOFFSET_s;
%Compute deltas if required and interpolate to measurement time
delta_true_psudorange_m=GNSS_true_observables.Pseudorange_m(1,:)-GNSS_true_observables.Pseudorange_m(2,:);
delta_true_interp_psudorange_m=interp1(GNSS_true_observables.RX_time(1,:)-shift_time_s, ...
delta_true_psudorange_m,GNSS_observables.RX_time(1,min_idx+1:end),'lineal','extrap');
true_interp_acc_carrier_phase_ch1_hz=interp1(GNSS_true_observables.RX_time(1,:)-shift_time_s, ...
GNSS_true_observables.Carrier_phase_hz(1,:),GNSS_observables.RX_time(1,min_idx+1:end),'lineal','extrap');
true_interp_acc_carrier_phase_ch2_hz=interp1(GNSS_true_observables.RX_time(1,:)-shift_time_s, ...
GNSS_true_observables.Carrier_phase_hz(2,:),GNSS_observables.RX_time(2,min_idx+1:end),'lineal','extrap');
%Compute measurement errors
delta_measured_psudorange_m=GNSS_observables.Pseudorange_m(1,min_idx+1:end)-GNSS_observables.Pseudorange_m(2,min_idx+1:end);
psudorange_error_m=delta_measured_psudorange_m-delta_true_interp_psudorange_m;
psudorange_rms_m=sqrt(sum(psudorange_error_m.^2)/length(psudorange_error_m))
acc_carrier_error_ch1_hz=GNSS_observables.Carrier_phase_hz(1,min_idx+1:end)-true_interp_acc_carrier_phase_ch1_hz...
-GNSS_observables.Carrier_phase_hz(1,min_idx+1)+true_interp_acc_carrier_phase_ch1_hz(1);
acc_phase_rms_ch1_hz=sqrt(sum(acc_carrier_error_ch1_hz.^2)/length(acc_carrier_error_ch1_hz))
acc_carrier_error_ch2_hz=GNSS_observables.Carrier_phase_hz(2,min_idx+1:end)-true_interp_acc_carrier_phase_ch2_hz...
-GNSS_observables.Carrier_phase_hz(2,min_idx+1)+true_interp_acc_carrier_phase_ch2_hz(1);
acc_phase_rms_ch2_hz=sqrt(sum(acc_carrier_error_ch2_hz.^2)/length(acc_carrier_error_ch2_hz))
%plot results
figure;
plot(GNSS_true_observables.RX_time(1,:),delta_true_psudorange_m,'g');
hold on;
plot(GNSS_observables.RX_time(1,min_idx+1:end),delta_measured_psudorange_m,'b');
title('TRUE vs. measured Pseudoranges [m]')
xlabel('TOW [s]')
ylabel('[m]');
figure;
plot(GNSS_observables.RX_time(1,min_idx+1:end),psudorange_error_m)
title('Pseudoranges error [m]')
xlabel('TOW [s]')
ylabel('[m]');
figure;
plot(GNSS_observables.RX_time(1,min_idx+1:end),acc_carrier_error_ch1_hz)
title('Accumulated carrier phase error CH1 [hz]')
xlabel('TOW [s]')
ylabel('[hz]');
figure;
plot(GNSS_observables.RX_time(1,min_idx+1:end),acc_carrier_error_ch2_hz)
title('Accumulated carrier phase error CH2 [hz]')
xlabel('TOW [s]')
ylabel('[hz]');
%
% %read true obs from simulator (optional)
% GPS_STARTOFFSET_s = 68.802e-3;
%
% true_observables_log_path='/home/javier/git/gnss-sdr/build/obs_out.bin';
% GNSS_true_observables= read_true_sim_observables_dump(true_observables_log_path);
%
% %correct the clock error using true values (it is not possible for a receiver to correct
% %the receiver clock offset error at the observables level because it is required the
% %decoding of the ephemeris data and solve the PVT equations)
%
% SPEED_OF_LIGHT_M_S = 299792458.0;
%
% %find the reference satellite
% [~,ref_sat_ch]=min(GNSS_observables.Pseudorange_m(:,min_idx+1));
% shift_time_s=GNSS_true_observables.Pseudorange_m(ref_sat_ch,:)/SPEED_OF_LIGHT_M_S-GPS_STARTOFFSET_s;
%
%
% %Compute deltas if required and interpolate to measurement time
% delta_true_psudorange_m=GNSS_true_observables.Pseudorange_m(1,:)-GNSS_true_observables.Pseudorange_m(2,:);
% delta_true_interp_psudorange_m=interp1(GNSS_true_observables.RX_time(1,:)-shift_time_s, ...
% delta_true_psudorange_m,GNSS_observables.RX_time(1,min_idx+1:end),'lineal','extrap');
% true_interp_acc_carrier_phase_ch1_hz=interp1(GNSS_true_observables.RX_time(1,:)-shift_time_s, ...
% GNSS_true_observables.Carrier_phase_hz(1,:),GNSS_observables.RX_time(1,min_idx+1:end),'lineal','extrap');
% true_interp_acc_carrier_phase_ch2_hz=interp1(GNSS_true_observables.RX_time(1,:)-shift_time_s, ...
% GNSS_true_observables.Carrier_phase_hz(2,:),GNSS_observables.RX_time(2,min_idx+1:end),'lineal','extrap');
%
% %Compute measurement errors
%
% delta_measured_psudorange_m=GNSS_observables.Pseudorange_m(1,min_idx+1:end)-GNSS_observables.Pseudorange_m(2,min_idx+1:end);
% psudorange_error_m=delta_measured_psudorange_m-delta_true_interp_psudorange_m;
% psudorange_rms_m=sqrt(sum(psudorange_error_m.^2)/length(psudorange_error_m))
%
% acc_carrier_error_ch1_hz=GNSS_observables.Carrier_phase_hz(1,min_idx+1:end)-true_interp_acc_carrier_phase_ch1_hz...
% -GNSS_observables.Carrier_phase_hz(1,min_idx+1)+true_interp_acc_carrier_phase_ch1_hz(1);
%
% acc_phase_rms_ch1_hz=sqrt(sum(acc_carrier_error_ch1_hz.^2)/length(acc_carrier_error_ch1_hz))
%
% acc_carrier_error_ch2_hz=GNSS_observables.Carrier_phase_hz(2,min_idx+1:end)-true_interp_acc_carrier_phase_ch2_hz...
% -GNSS_observables.Carrier_phase_hz(2,min_idx+1)+true_interp_acc_carrier_phase_ch2_hz(1);
% acc_phase_rms_ch2_hz=sqrt(sum(acc_carrier_error_ch2_hz.^2)/length(acc_carrier_error_ch2_hz))
%
%
% %plot results
% figure;
% plot(GNSS_true_observables.RX_time(1,:),delta_true_psudorange_m,'g');
% hold on;
% plot(GNSS_observables.RX_time(1,min_idx+1:end),delta_measured_psudorange_m,'b');
% title('TRUE vs. measured Pseudoranges [m]')
% xlabel('TOW [s]')
% ylabel('[m]');
%
% figure;
% plot(GNSS_observables.RX_time(1,min_idx+1:end),psudorange_error_m)
% title('Pseudoranges error [m]')
% xlabel('TOW [s]')
% ylabel('[m]');
%
% figure;
% plot(GNSS_observables.RX_time(1,min_idx+1:end),acc_carrier_error_ch1_hz)
% title('Accumulated carrier phase error CH1 [hz]')
% xlabel('TOW [s]')
% ylabel('[hz]');
%
% figure;
% plot(GNSS_observables.RX_time(1,min_idx+1:end),acc_carrier_error_ch2_hz)
% title('Accumulated carrier phase error CH2 [hz]')
% xlabel('TOW [s]')
% ylabel('[hz]');
%
%
%
%