mirror of
https://github.com/gnss-sdr/gnss-sdr
synced 2025-11-06 18:23:05 +00:00
Progress in Galileo E1:
Bug fix in galileo tracking Several improvements in Galileo telemetry decoder. Code cleaning in observables Galileo PVT is able to decode Galileo time and get satellite ECEF positions Galileo PVT soluton is still under development git-svn-id: https://svn.code.sf.net/p/gnss-sdr/code/trunk@432 64b25241-fba3-4117-9849-534c7e92360d
This commit is contained in:
@@ -104,7 +104,7 @@ galileo_e1_pvt_cc::galileo_e1_pvt_cc(unsigned int nchannels, boost::shared_ptr<g
|
||||
d_dump_file.open(d_dump_filename.c_str(), std::ios::out | std::ios::binary);
|
||||
std::cout << "PVT dump enabled Log file: " << d_dump_filename.c_str() << std::endl;
|
||||
}
|
||||
catch (std::ifstream::failure e)
|
||||
catch (const std::ifstream::failure& e)
|
||||
{
|
||||
std::cout << "Exception opening PVT dump file " << e.what() << std::endl;
|
||||
}
|
||||
@@ -169,14 +169,15 @@ int galileo_e1_pvt_cc::general_work (int noutput_items, gr_vector_int &ninput_it
|
||||
}
|
||||
|
||||
// ############ 2 COMPUTE THE PVT ################################
|
||||
// if (gnss_pseudoranges_map.size() > 0 and d_ls_pvt->gps_ephemeris_map.size() >0)
|
||||
// {
|
||||
// // compute on the fly PVT solution
|
||||
// //mod 8/4/2012 Set the PVT computation rate in this block
|
||||
// if ((d_sample_counter % d_output_rate_ms) == 0)
|
||||
// {
|
||||
// bool pvt_result;
|
||||
// pvt_result = d_ls_pvt->get_PVT(gnss_pseudoranges_map, d_rx_time, d_flag_averaging);
|
||||
if (gnss_pseudoranges_map.size() > 0 and d_ls_pvt->galileo_ephemeris_map.size() >0)
|
||||
{
|
||||
// compute on the fly PVT solution
|
||||
if ((d_sample_counter % d_output_rate_ms) == 0)
|
||||
{
|
||||
bool pvt_result;
|
||||
pvt_result = d_ls_pvt->get_PVT(gnss_pseudoranges_map, d_rx_time, d_flag_averaging);
|
||||
|
||||
//ToDo: Implement Galileo RINEX and Galileo NMEA outputs
|
||||
// if (pvt_result==true)
|
||||
// {
|
||||
// d_kml_dump.print_position(d_ls_pvt, d_flag_averaging);
|
||||
@@ -210,42 +211,41 @@ int galileo_e1_pvt_cc::general_work (int noutput_items, gr_vector_int &ninput_it
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // DEBUG MESSAGE: Display position in console output
|
||||
// if (((d_sample_counter % d_display_rate_ms) == 0) and d_ls_pvt->b_valid_position == true)
|
||||
// {
|
||||
// std::cout << "Position at " << boost::posix_time::to_simple_string(d_ls_pvt->d_position_UTC_time)
|
||||
// << " is Lat = " << d_ls_pvt->d_latitude_d << " [deg], Long = " << d_ls_pvt->d_longitude_d
|
||||
// << " [deg], Height= " << d_ls_pvt->d_height_m << " [m]" << std::endl;
|
||||
//
|
||||
// std::cout << "Dilution of Precision at " << boost::posix_time::to_simple_string(d_ls_pvt->d_position_UTC_time)
|
||||
// << " is HDOP = " << d_ls_pvt->d_HDOP << " VDOP = " <<
|
||||
// d_ls_pvt->d_VDOP <<" TDOP = " << d_ls_pvt->d_TDOP <<
|
||||
// " GDOP = " << d_ls_pvt->d_GDOP <<std::endl;
|
||||
// }
|
||||
}
|
||||
|
||||
// DEBUG MESSAGE: Display position in console output
|
||||
if (((d_sample_counter % d_display_rate_ms) == 0) and d_ls_pvt->b_valid_position == true)
|
||||
{
|
||||
std::cout << "Position at " << boost::posix_time::to_simple_string(d_ls_pvt->d_position_UTC_time)
|
||||
<< " is Lat = " << d_ls_pvt->d_latitude_d << " [deg], Long = " << d_ls_pvt->d_longitude_d
|
||||
<< " [deg], Height= " << d_ls_pvt->d_height_m << " [m]" << std::endl;
|
||||
|
||||
std::cout << "Dilution of Precision at " << boost::posix_time::to_simple_string(d_ls_pvt->d_position_UTC_time)
|
||||
<< " is HDOP = " << d_ls_pvt->d_HDOP << " VDOP = " <<
|
||||
d_ls_pvt->d_VDOP <<" TDOP = " << d_ls_pvt->d_TDOP <<
|
||||
" GDOP = " << d_ls_pvt->d_GDOP <<std::endl;
|
||||
}
|
||||
// // MULTIPLEXED FILE RECORDING - Record results to file
|
||||
// if(d_dump == true)
|
||||
// {
|
||||
// try
|
||||
// {
|
||||
// double tmp_double;
|
||||
// for (unsigned int i=0; i<d_nchannels ; i++)
|
||||
// {
|
||||
// tmp_double = in[i][0].Pseudorange_m;
|
||||
// d_dump_file.write((char*)&tmp_double, sizeof(double));
|
||||
// tmp_double = 0;
|
||||
// d_dump_file.write((char*)&tmp_double, sizeof(double));
|
||||
// d_dump_file.write((char*)&d_rx_time, sizeof(double));
|
||||
// }
|
||||
// }
|
||||
// catch (std::ifstream::failure e)
|
||||
// {
|
||||
// std::cout << "Exception writing observables dump file " << e.what() << std::endl;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
if(d_dump == true)
|
||||
{
|
||||
try
|
||||
{
|
||||
double tmp_double;
|
||||
for (unsigned int i=0; i<d_nchannels ; i++)
|
||||
{
|
||||
tmp_double = in[i][0].Pseudorange_m;
|
||||
d_dump_file.write((char*)&tmp_double, sizeof(double));
|
||||
tmp_double = 0;
|
||||
d_dump_file.write((char*)&tmp_double, sizeof(double));
|
||||
d_dump_file.write((char*)&d_rx_time, sizeof(double));
|
||||
}
|
||||
}
|
||||
catch (const std::ifstream::failure& e)
|
||||
{
|
||||
std::cout << "Exception writing observables dump file " << e.what() << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
consume_each(1); //one by one
|
||||
return 0;
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
#include <armadillo>
|
||||
#include "galileo_e1_ls_pvt.h"
|
||||
|
||||
#include "GPS_L1_CA.h"
|
||||
#include "Galileo_E1.h"
|
||||
#include <glog/log_severity.h>
|
||||
#include <glog/logging.h>
|
||||
#include "boost/date_time/posix_time/posix_time.hpp"
|
||||
@@ -181,7 +181,7 @@ arma::vec galileo_e1_ls_pvt::leastSquarePos(arma::mat satpos, arma::vec obs, arm
|
||||
(X(0, i) - pos(0)) + (X(1, i) - pos(1)) *
|
||||
(X(1, i) - pos(1)) + (X(2,i) - pos(2)) *
|
||||
(X(2,i) - pos(2));
|
||||
traveltime = sqrt(rho2) / GPS_C_m_s;
|
||||
traveltime = sqrt(rho2) / GALILEO_C_m_s;
|
||||
|
||||
//--- Correct satellite position (do to earth rotation) --------
|
||||
Rot_X = rotateSatellite(traveltime, X.col(i)); //armadillo
|
||||
@@ -230,254 +230,264 @@ arma::vec galileo_e1_ls_pvt::leastSquarePos(arma::mat satpos, arma::vec obs, arm
|
||||
|
||||
bool galileo_e1_ls_pvt::get_PVT(std::map<int,Gnss_Synchro> gnss_pseudoranges_map, double galileo_current_time, bool flag_averaging)
|
||||
{
|
||||
// std::map<int,Gnss_Synchro>::iterator gnss_pseudoranges_iter;
|
||||
// std::map<int,Galileo_Ephemeris>::iterator galileo_ephemeris_iter;
|
||||
// int valid_pseudoranges = gnss_pseudoranges_map.size();
|
||||
//
|
||||
// arma::mat W = arma::eye(valid_pseudoranges,valid_pseudoranges); //channels weights matrix
|
||||
// arma::vec obs = arma::zeros(valid_pseudoranges); // pseudoranges observation vector
|
||||
// arma::mat satpos = arma::zeros(3,valid_pseudoranges); //satellite positions matrix
|
||||
//
|
||||
// int GPS_week = 0;
|
||||
// double utc = 0;
|
||||
// double SV_clock_drift_s = 0;
|
||||
// double SV_relativistic_clock_corr_s = 0;
|
||||
// double TX_time_corrected_s;
|
||||
// double SV_clock_bias_s = 0;
|
||||
//
|
||||
// d_flag_averaging = flag_averaging;
|
||||
//
|
||||
// // ********************************************************************************
|
||||
// // ****** PREPARE THE LEAST SQUARES DATA (SV POSITIONS MATRIX AND OBS VECTORS) ****
|
||||
// // ********************************************************************************
|
||||
// int valid_obs = 0; //valid observations counter
|
||||
// int obs_counter = 0;
|
||||
// for(gnss_pseudoranges_iter = gnss_pseudoranges_map.begin();
|
||||
// gnss_pseudoranges_iter != gnss_pseudoranges_map.end();
|
||||
// gnss_pseudoranges_iter++)
|
||||
// {
|
||||
// // 1- find the ephemeris for the current SV observation. The SV PRN ID is the map key
|
||||
// gps_ephemeris_iter = gps_ephemeris_map.find(gnss_pseudoranges_iter->first);
|
||||
// if (gps_ephemeris_iter != gps_ephemeris_map.end())
|
||||
// {
|
||||
// /*!
|
||||
// * \todo Place here the satellite CN0 (power level, or weight factor)
|
||||
// */
|
||||
// W(obs_counter, obs_counter) = 1;
|
||||
//
|
||||
// // COMMON RX TIME PVT ALGORITHM MODIFICATION (Like RINEX files)
|
||||
// // first estimate of transmit time
|
||||
// double Rx_time = GPS_current_time;
|
||||
// double Tx_time = Rx_time - gnss_pseudoranges_iter->second.Pseudorange_m/GPS_C_m_s;
|
||||
//
|
||||
// // 2- compute the clock drift using the clock model (broadcast) for this SV
|
||||
// SV_clock_drift_s = gps_ephemeris_iter->second.sv_clock_drift(Tx_time);
|
||||
//
|
||||
// // 3- compute the relativistic clock drift using the clock model (broadcast) for this SV
|
||||
// SV_relativistic_clock_corr_s = gps_ephemeris_iter->second.sv_clock_relativistic_term(Tx_time);
|
||||
//
|
||||
// // 4- compute the current ECEF position for this SV using corrected TX time
|
||||
// SV_clock_bias_s = SV_clock_drift_s + SV_relativistic_clock_corr_s - gps_ephemeris_iter->second.d_TGD;
|
||||
// TX_time_corrected_s = Tx_time - SV_clock_bias_s;
|
||||
// gps_ephemeris_iter->second.satellitePosition(TX_time_corrected_s);
|
||||
//
|
||||
// satpos(0,obs_counter) = gps_ephemeris_iter->second.d_satpos_X;
|
||||
// satpos(1,obs_counter) = gps_ephemeris_iter->second.d_satpos_Y;
|
||||
// satpos(2,obs_counter) = gps_ephemeris_iter->second.d_satpos_Z;
|
||||
//
|
||||
// // 5- fill the observations vector with the corrected pseudorranges
|
||||
// obs(obs_counter) = gnss_pseudoranges_iter->second.Pseudorange_m + SV_clock_bias_s*GPS_C_m_s;
|
||||
// d_visible_satellites_IDs[valid_obs] = gps_ephemeris_iter->second.i_satellite_PRN;
|
||||
// d_visible_satellites_CN0_dB[valid_obs] = gnss_pseudoranges_iter->second.CN0_dB_hz;
|
||||
// valid_obs++;
|
||||
//
|
||||
// // SV ECEF DEBUG OUTPUT
|
||||
// DLOG(INFO) << "(new)ECEF satellite SV ID=" << gps_ephemeris_iter->second.i_satellite_PRN
|
||||
// << " X=" << gps_ephemeris_iter->second.d_satpos_X
|
||||
// << " [m] Y=" << gps_ephemeris_iter->second.d_satpos_Y
|
||||
// << " [m] Z=" << gps_ephemeris_iter->second.d_satpos_Z
|
||||
// << " [m] PR_obs=" << obs(obs_counter) << " [m]" << std::endl;
|
||||
//
|
||||
// // compute the UTC time for this SV (just to print the asociated UTC timestamp)
|
||||
// GPS_week = gps_ephemeris_iter->second.i_GPS_week;
|
||||
// utc = gps_utc_model.utc_time(TX_time_corrected_s, GPS_week);
|
||||
//
|
||||
// }
|
||||
// else // the ephemeris are not available for this SV
|
||||
// {
|
||||
// // no valid pseudorange for the current SV
|
||||
// W(obs_counter, obs_counter) = 0; // SV de-activated
|
||||
// obs(obs_counter) = 1; // to avoid algorithm problems (divide by zero)
|
||||
// DLOG(INFO) << "No ephemeris data for SV "<< gnss_pseudoranges_iter->first << std::endl;
|
||||
// }
|
||||
// obs_counter++;
|
||||
// }
|
||||
std::map<int,Gnss_Synchro>::iterator gnss_pseudoranges_iter;
|
||||
std::map<int,Galileo_Ephemeris>::iterator galileo_ephemeris_iter;
|
||||
int valid_pseudoranges = gnss_pseudoranges_map.size();
|
||||
|
||||
arma::mat W = arma::eye(valid_pseudoranges,valid_pseudoranges); //channels weights matrix
|
||||
arma::vec obs = arma::zeros(valid_pseudoranges); // pseudoranges observation vector
|
||||
arma::mat satpos = arma::zeros(3,valid_pseudoranges); //satellite positions matrix
|
||||
|
||||
int Galileo_week_number = 0;
|
||||
double utc = 0;
|
||||
double SV_clock_drift_s = 0;
|
||||
double SV_relativistic_clock_corr_s = 0;
|
||||
double TX_time_corrected_s;
|
||||
double SV_clock_bias_s = 0;
|
||||
|
||||
double GST=0;
|
||||
|
||||
d_flag_averaging = flag_averaging;
|
||||
|
||||
// ********************************************************************************
|
||||
// ****** PREPARE THE LEAST SQUARES DATA (SV POSITIONS MATRIX AND OBS VECTORS) ****
|
||||
// ********************************************************************************
|
||||
int valid_obs = 0; //valid observations counter
|
||||
int obs_counter = 0;
|
||||
for(gnss_pseudoranges_iter = gnss_pseudoranges_map.begin();
|
||||
gnss_pseudoranges_iter != gnss_pseudoranges_map.end();
|
||||
gnss_pseudoranges_iter++)
|
||||
{
|
||||
// 1- find the ephemeris for the current SV observation. The SV PRN ID is the map key
|
||||
galileo_ephemeris_iter = galileo_ephemeris_map.find(gnss_pseudoranges_iter->first);
|
||||
if (galileo_ephemeris_iter != galileo_ephemeris_map.end())
|
||||
{
|
||||
/*!
|
||||
* \todo Place here the satellite CN0 (power level, or weight factor)
|
||||
*/
|
||||
W(obs_counter, obs_counter) = 1;
|
||||
|
||||
// COMMON RX TIME PVT ALGORITHM MODIFICATION (Like RINEX files)
|
||||
// first estimate of transmit time
|
||||
double Rx_time = galileo_current_time;
|
||||
double Tx_time = Rx_time - gnss_pseudoranges_iter->second.Pseudorange_m/GALILEO_C_m_s;
|
||||
|
||||
// 2- compute the clock drift using the clock model (broadcast) for this SV
|
||||
SV_clock_drift_s = galileo_ephemeris_iter->second.sv_clock_drift(Tx_time);
|
||||
|
||||
// 3- compute the relativistic clock drift using the clock model (broadcast) for this SV
|
||||
SV_relativistic_clock_corr_s = galileo_ephemeris_iter->second.sv_clock_relativistic_term(Tx_time);
|
||||
|
||||
// 4- compute the current ECEF position for this SV using corrected TX time
|
||||
SV_clock_bias_s = SV_clock_drift_s + SV_relativistic_clock_corr_s;
|
||||
TX_time_corrected_s = Tx_time - SV_clock_bias_s;
|
||||
galileo_ephemeris_iter->second.satellitePosition(TX_time_corrected_s);
|
||||
|
||||
satpos(0,obs_counter) = galileo_ephemeris_iter->second.d_satpos_X;
|
||||
satpos(1,obs_counter) = galileo_ephemeris_iter->second.d_satpos_Y;
|
||||
satpos(2,obs_counter) = galileo_ephemeris_iter->second.d_satpos_Z;
|
||||
|
||||
// 5- fill the observations vector with the corrected pseudorranges
|
||||
obs(obs_counter) = gnss_pseudoranges_iter->second.Pseudorange_m + SV_clock_bias_s*GALILEO_C_m_s;
|
||||
d_visible_satellites_IDs[valid_obs] = galileo_ephemeris_iter->second.i_satellite_PRN;
|
||||
d_visible_satellites_CN0_dB[valid_obs] = gnss_pseudoranges_iter->second.CN0_dB_hz;
|
||||
valid_obs++;
|
||||
|
||||
Galileo_week_number = galileo_ephemeris_iter->second.WN_5;//for GST
|
||||
|
||||
//debug
|
||||
double GST=galileo_ephemeris_iter->second.Galileo_System_Time(Galileo_week_number,galileo_current_time);
|
||||
utc = galileo_utc_model.GST_to_UTC_time(GST, Galileo_week_number);
|
||||
// get time string gregorian calendar
|
||||
boost::posix_time::time_duration t = boost::posix_time::seconds(utc);
|
||||
// 22 August 1999 00:00 last Galileo start GST epoch (ICD sec 5.1.2)
|
||||
boost::posix_time::ptime p_time(boost::gregorian::date(1999, 8, 22), t);
|
||||
d_position_UTC_time = p_time;
|
||||
std::cout << "Galileo RX time at " << boost::posix_time::to_simple_string(p_time)<<std::endl;
|
||||
//end debug
|
||||
|
||||
// SV ECEF DEBUG OUTPUT
|
||||
DLOG(INFO) << "ECEF satellite SV ID=" << galileo_ephemeris_iter->second.i_satellite_PRN
|
||||
<< " X=" << galileo_ephemeris_iter->second.d_satpos_X
|
||||
<< " [m] Y=" << galileo_ephemeris_iter->second.d_satpos_Y
|
||||
<< " [m] Z=" << galileo_ephemeris_iter->second.d_satpos_Z
|
||||
<< " [m] PR_obs=" << obs(obs_counter) << " [m]" << std::endl;
|
||||
}
|
||||
else // the ephemeris are not available for this SV
|
||||
{
|
||||
// no valid pseudorange for the current SV
|
||||
W(obs_counter, obs_counter) = 0; // SV de-activated
|
||||
obs(obs_counter) = 1; // to avoid algorithm problems (divide by zero)
|
||||
DLOG(INFO) << "No ephemeris data for SV "<< gnss_pseudoranges_iter->first << std::endl;
|
||||
}
|
||||
obs_counter++;
|
||||
}
|
||||
//
|
||||
// // ********************************************************************************
|
||||
// // ****** SOLVE LEAST SQUARES******************************************************
|
||||
// // ********************************************************************************
|
||||
// d_valid_observations = valid_obs;
|
||||
// DLOG(INFO) << "(new)PVT: valid observations=" << valid_obs << std::endl;
|
||||
//
|
||||
// if (valid_obs >= 4)
|
||||
// {
|
||||
// arma::vec mypos;
|
||||
// DLOG(INFO) << "satpos=" << satpos << std::endl;
|
||||
// DLOG(INFO) << "obs="<< obs << std::endl;
|
||||
// DLOG(INFO) << "W=" << W <<std::endl;
|
||||
// mypos = leastSquarePos(satpos, obs, W);
|
||||
// DLOG(INFO) << "(new)Position at TOW=" << GPS_current_time << " in ECEF (X,Y,Z) = " << mypos << std::endl;
|
||||
// gps_l1_ca_ls_pvt::cart2geo(mypos(0), mypos(1), mypos(2), 4);
|
||||
// //ToDo: Find an Observables/PVT random bug with some satellite configurations that gives an erratic PVT solution (i.e. height>50 km)
|
||||
// if (d_height_m>50000)
|
||||
// {
|
||||
// b_valid_position=false;
|
||||
// return false; //erratic PVT
|
||||
// }
|
||||
// // Compute UTC time and print PVT solution
|
||||
// double secondsperweek = 604800.0; // number of seconds in one week (7*24*60*60)
|
||||
// boost::posix_time::time_duration t = boost::posix_time::seconds(utc + secondsperweek*(double)GPS_week);
|
||||
// // 22 August 1999 last GPS time roll over
|
||||
// boost::posix_time::ptime p_time(boost::gregorian::date(1999, 8, 22), t);
|
||||
// d_position_UTC_time = p_time;
|
||||
//
|
||||
// DLOG(INFO) << "(new)Position at " << boost::posix_time::to_simple_string(p_time)
|
||||
// << " is Lat = " << d_latitude_d << " [deg], Long = " << d_longitude_d
|
||||
// << " [deg], Height= " << d_height_m << " [m]" << std::endl;
|
||||
//
|
||||
// // ###### Compute DOPs ########
|
||||
//
|
||||
// // 1- Rotation matrix from ECEF coordinates to ENU coordinates
|
||||
// // ref: http://www.navipedia.net/index.php/Transformations_between_ECEF_and_ENU_coordinates
|
||||
//
|
||||
// arma::mat F=arma::zeros(3,3);
|
||||
// F(0,0)=-sin(GPS_TWO_PI*(d_longitude_d/360.0));
|
||||
// F(0,1)=-sin(GPS_TWO_PI*(d_latitude_d/360.0))*cos(GPS_TWO_PI*(d_longitude_d/360.0));
|
||||
// F(0,2)=cos(GPS_TWO_PI*(d_latitude_d/360.0))*cos(GPS_TWO_PI*(d_longitude_d/360.0));
|
||||
//
|
||||
// F(1,0)=cos((GPS_TWO_PI*d_longitude_d)/360.0);
|
||||
// F(1,1)=-sin((GPS_TWO_PI*d_latitude_d)/360.0)*sin((GPS_TWO_PI*d_longitude_d)/360.0);
|
||||
// F(1,2)=cos((GPS_TWO_PI*d_latitude_d/360.0))*sin((GPS_TWO_PI*d_longitude_d)/360.0);
|
||||
//
|
||||
// F(2,0)=0;
|
||||
// F(2,1)=cos((GPS_TWO_PI*d_latitude_d)/360.0);
|
||||
// F(2,2)=sin((GPS_TWO_PI*d_latitude_d/360.0));
|
||||
//
|
||||
// // 2- Apply the rotation to the latest covariance matrix (available in ECEF from LS)
|
||||
//
|
||||
// arma::mat Q_ECEF=d_Q.submat( 0, 0, 2, 2);
|
||||
// arma::mat DOP_ENU=arma::zeros(3,3);
|
||||
//
|
||||
// try
|
||||
// {
|
||||
// DOP_ENU=arma::htrans(F)*Q_ECEF*F;
|
||||
// d_GDOP = sqrt(arma::trace(DOP_ENU)); // Geometric DOP
|
||||
// d_PDOP = sqrt(DOP_ENU(0,0) + DOP_ENU(1,1) + DOP_ENU(2,2)); // PDOP
|
||||
// d_HDOP = sqrt(DOP_ENU(0,0) + DOP_ENU(1,1)); // HDOP
|
||||
// d_VDOP = sqrt(DOP_ENU(2,2)); // VDOP
|
||||
// d_TDOP = sqrt(d_Q(3,3)); // TDOP
|
||||
// }catch(std::exception& ex)
|
||||
// {
|
||||
// d_GDOP = -1; // Geometric DOP
|
||||
// d_PDOP = -1; // PDOP
|
||||
// d_HDOP = -1; // HDOP
|
||||
// d_VDOP = -1; // VDOP
|
||||
// d_TDOP = -1; // TDOP
|
||||
// }
|
||||
//
|
||||
// // ######## LOG FILE #########
|
||||
// if(d_flag_dump_enabled == true)
|
||||
// {
|
||||
// // MULTIPLEXED FILE RECORDING - Record results to file
|
||||
// try
|
||||
// {
|
||||
// double tmp_double;
|
||||
// // PVT GPS time
|
||||
// tmp_double = GPS_current_time;
|
||||
// d_dump_file.write((char*)&tmp_double, sizeof(double));
|
||||
// // ECEF User Position East [m]
|
||||
// tmp_double = mypos(0);
|
||||
// d_dump_file.write((char*)&tmp_double, sizeof(double));
|
||||
// // ECEF User Position North [m]
|
||||
// tmp_double = mypos(1);
|
||||
// d_dump_file.write((char*)&tmp_double, sizeof(double));
|
||||
// // ECEF User Position Up [m]
|
||||
// tmp_double = mypos(2);
|
||||
// d_dump_file.write((char*)&tmp_double, sizeof(double));
|
||||
// // User clock offset [s]
|
||||
// tmp_double = mypos(3);
|
||||
// d_dump_file.write((char*)&tmp_double, sizeof(double));
|
||||
// // GEO user position Latitude [deg]
|
||||
// tmp_double = d_latitude_d;
|
||||
// d_dump_file.write((char*)&tmp_double, sizeof(double));
|
||||
// // GEO user position Longitude [deg]
|
||||
// tmp_double = d_longitude_d;
|
||||
// d_dump_file.write((char*)&tmp_double, sizeof(double));
|
||||
// // GEO user position Height [m]
|
||||
// tmp_double = d_height_m;
|
||||
// d_dump_file.write((char*)&tmp_double, sizeof(double));
|
||||
// }
|
||||
// catch (std::ifstream::failure e)
|
||||
// {
|
||||
// std::cout << "Exception writing PVT LS dump file "<< e.what() << std::endl;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // MOVING AVERAGE PVT
|
||||
// if (flag_averaging == true)
|
||||
// {
|
||||
// if (d_hist_longitude_d.size() == (unsigned int)d_averaging_depth)
|
||||
// {
|
||||
// // Pop oldest value
|
||||
// d_hist_longitude_d.pop_back();
|
||||
// d_hist_latitude_d.pop_back();
|
||||
// d_hist_height_m.pop_back();
|
||||
// // Push new values
|
||||
// d_hist_longitude_d.push_front(d_longitude_d);
|
||||
// d_hist_latitude_d.push_front(d_latitude_d);
|
||||
// d_hist_height_m.push_front(d_height_m);
|
||||
//
|
||||
// d_avg_latitude_d = 0;
|
||||
// d_avg_longitude_d = 0;
|
||||
// d_avg_height_m = 0;
|
||||
// for (unsigned int i=0; i<d_hist_longitude_d.size(); i++)
|
||||
// {
|
||||
// d_avg_latitude_d = d_avg_latitude_d + d_hist_latitude_d.at(i);
|
||||
// d_avg_longitude_d = d_avg_longitude_d + d_hist_longitude_d.at(i);
|
||||
// d_avg_height_m = d_avg_height_m + d_hist_height_m.at(i);
|
||||
// }
|
||||
// d_avg_latitude_d = d_avg_latitude_d / (double)d_averaging_depth;
|
||||
// d_avg_longitude_d = d_avg_longitude_d / (double)d_averaging_depth;
|
||||
// d_avg_height_m = d_avg_height_m / (double)d_averaging_depth;
|
||||
// b_valid_position = true;
|
||||
// return true; //indicates that the returned position is valid
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// //int current_depth=d_hist_longitude_d.size();
|
||||
// // Push new values
|
||||
// d_hist_longitude_d.push_front(d_longitude_d);
|
||||
// d_hist_latitude_d.push_front(d_latitude_d);
|
||||
// d_hist_height_m.push_front(d_height_m);
|
||||
//
|
||||
// d_avg_latitude_d = d_latitude_d;
|
||||
// d_avg_longitude_d = d_longitude_d;
|
||||
// d_avg_height_m = d_height_m;
|
||||
// b_valid_position = false;
|
||||
// return false; //indicates that the returned position is not valid yet
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// b_valid_position = true;
|
||||
// return true; //indicates that the returned position is valid
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// b_valid_position = false;
|
||||
// return false;
|
||||
// }
|
||||
d_valid_observations = valid_obs;
|
||||
DLOG(INFO) << "Galileo PVT: valid observations=" << valid_obs << std::endl;
|
||||
|
||||
if (valid_obs >= 4)
|
||||
{
|
||||
arma::vec mypos;
|
||||
DLOG(INFO) << "satpos=" << satpos << std::endl;
|
||||
DLOG(INFO) << "obs="<< obs << std::endl;
|
||||
DLOG(INFO) << "W=" << W <<std::endl;
|
||||
mypos = leastSquarePos(satpos, obs, W);
|
||||
|
||||
// Compute GST and Gregorian time
|
||||
double GST=galileo_ephemeris_iter->second.Galileo_System_Time(Galileo_week_number,galileo_current_time);
|
||||
utc = galileo_utc_model.GST_to_UTC_time(GST, Galileo_week_number);
|
||||
// get time string gregorian calendar
|
||||
boost::posix_time::time_duration t = boost::posix_time::seconds(utc);
|
||||
// 22 August 1999 00:00 last Galileo start GST epoch (ICD sec 5.1.2)
|
||||
boost::posix_time::ptime p_time(boost::gregorian::date(1999, 8, 22), t);
|
||||
d_position_UTC_time = p_time;
|
||||
std::cout << "Galileo RX time at " << boost::posix_time::to_simple_string(p_time)<<std::endl;
|
||||
|
||||
DLOG(INFO) << "Galileo Position at TOW=" << galileo_current_time << " in ECEF (X,Y,Z) = " << mypos << std::endl;
|
||||
cart2geo((double)mypos(0), (double)mypos(1), (double)mypos(2), 4);
|
||||
// TODO: Compute UTC time and print PVT solution
|
||||
|
||||
DLOG(INFO) << "Galileo Position at " << boost::posix_time::to_simple_string(p_time)
|
||||
<< " is Lat = " << d_latitude_d << " [deg], Long = " << d_longitude_d
|
||||
<< " [deg], Height= " << d_height_m << " [m]" << std::endl;
|
||||
|
||||
// ###### Compute DOPs ########
|
||||
|
||||
// 1- Rotation matrix from ECEF coordinates to ENU coordinates
|
||||
// ref: http://www.navipedia.net/index.php/Transformations_between_ECEF_and_ENU_coordinates
|
||||
|
||||
arma::mat F=arma::zeros(3,3);
|
||||
F(0,0)=-sin(GPS_TWO_PI*(d_longitude_d/360.0));
|
||||
F(0,1)=-sin(GPS_TWO_PI*(d_latitude_d/360.0))*cos(GPS_TWO_PI*(d_longitude_d/360.0));
|
||||
F(0,2)=cos(GPS_TWO_PI*(d_latitude_d/360.0))*cos(GPS_TWO_PI*(d_longitude_d/360.0));
|
||||
|
||||
F(1,0)=cos((GPS_TWO_PI*d_longitude_d)/360.0);
|
||||
F(1,1)=-sin((GPS_TWO_PI*d_latitude_d)/360.0)*sin((GPS_TWO_PI*d_longitude_d)/360.0);
|
||||
F(1,2)=cos((GPS_TWO_PI*d_latitude_d/360.0))*sin((GPS_TWO_PI*d_longitude_d)/360.0);
|
||||
|
||||
F(2,0)=0;
|
||||
F(2,1)=cos((GPS_TWO_PI*d_latitude_d)/360.0);
|
||||
F(2,2)=sin((GPS_TWO_PI*d_latitude_d/360.0));
|
||||
|
||||
// 2- Apply the rotation to the latest covariance matrix (available in ECEF from LS)
|
||||
|
||||
arma::mat Q_ECEF=d_Q.submat( 0, 0, 2, 2);
|
||||
arma::mat DOP_ENU=arma::zeros(3,3);
|
||||
|
||||
try
|
||||
{
|
||||
DOP_ENU=arma::htrans(F)*Q_ECEF*F;
|
||||
d_GDOP = sqrt(arma::trace(DOP_ENU)); // Geometric DOP
|
||||
d_PDOP = sqrt(DOP_ENU(0,0) + DOP_ENU(1,1) + DOP_ENU(2,2)); // PDOP
|
||||
d_HDOP = sqrt(DOP_ENU(0,0) + DOP_ENU(1,1)); // HDOP
|
||||
d_VDOP = sqrt(DOP_ENU(2,2)); // VDOP
|
||||
d_TDOP = sqrt(d_Q(3,3)); // TDOP
|
||||
}catch(std::exception& ex)
|
||||
{
|
||||
d_GDOP = -1; // Geometric DOP
|
||||
d_PDOP = -1; // PDOP
|
||||
d_HDOP = -1; // HDOP
|
||||
d_VDOP = -1; // VDOP
|
||||
d_TDOP = -1; // TDOP
|
||||
}
|
||||
|
||||
// ######## LOG FILE #########
|
||||
if(d_flag_dump_enabled == true)
|
||||
{
|
||||
// MULTIPLEXED FILE RECORDING - Record results to file
|
||||
try
|
||||
{
|
||||
double tmp_double;
|
||||
// PVT GPS time
|
||||
tmp_double = galileo_current_time;
|
||||
d_dump_file.write((char*)&tmp_double, sizeof(double));
|
||||
// ECEF User Position East [m]
|
||||
tmp_double = mypos(0);
|
||||
d_dump_file.write((char*)&tmp_double, sizeof(double));
|
||||
// ECEF User Position North [m]
|
||||
tmp_double = mypos(1);
|
||||
d_dump_file.write((char*)&tmp_double, sizeof(double));
|
||||
// ECEF User Position Up [m]
|
||||
tmp_double = mypos(2);
|
||||
d_dump_file.write((char*)&tmp_double, sizeof(double));
|
||||
// User clock offset [s]
|
||||
tmp_double = mypos(3);
|
||||
d_dump_file.write((char*)&tmp_double, sizeof(double));
|
||||
// GEO user position Latitude [deg]
|
||||
tmp_double = d_latitude_d;
|
||||
d_dump_file.write((char*)&tmp_double, sizeof(double));
|
||||
// GEO user position Longitude [deg]
|
||||
tmp_double = d_longitude_d;
|
||||
d_dump_file.write((char*)&tmp_double, sizeof(double));
|
||||
// GEO user position Height [m]
|
||||
tmp_double = d_height_m;
|
||||
d_dump_file.write((char*)&tmp_double, sizeof(double));
|
||||
}
|
||||
catch (const std::ifstream::failure& e)
|
||||
{
|
||||
std::cout << "Exception writing PVT LS dump file "<< e.what() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
// MOVING AVERAGE PVT
|
||||
if (flag_averaging == true)
|
||||
{
|
||||
if (d_hist_longitude_d.size() == (unsigned int)d_averaging_depth)
|
||||
{
|
||||
// Pop oldest value
|
||||
d_hist_longitude_d.pop_back();
|
||||
d_hist_latitude_d.pop_back();
|
||||
d_hist_height_m.pop_back();
|
||||
// Push new values
|
||||
d_hist_longitude_d.push_front(d_longitude_d);
|
||||
d_hist_latitude_d.push_front(d_latitude_d);
|
||||
d_hist_height_m.push_front(d_height_m);
|
||||
|
||||
d_avg_latitude_d = 0;
|
||||
d_avg_longitude_d = 0;
|
||||
d_avg_height_m = 0;
|
||||
for (unsigned int i=0; i<d_hist_longitude_d.size(); i++)
|
||||
{
|
||||
d_avg_latitude_d = d_avg_latitude_d + d_hist_latitude_d.at(i);
|
||||
d_avg_longitude_d = d_avg_longitude_d + d_hist_longitude_d.at(i);
|
||||
d_avg_height_m = d_avg_height_m + d_hist_height_m.at(i);
|
||||
}
|
||||
d_avg_latitude_d = d_avg_latitude_d / (double)d_averaging_depth;
|
||||
d_avg_longitude_d = d_avg_longitude_d / (double)d_averaging_depth;
|
||||
d_avg_height_m = d_avg_height_m / (double)d_averaging_depth;
|
||||
b_valid_position = true;
|
||||
return true; //indicates that the returned position is valid
|
||||
}
|
||||
else
|
||||
{
|
||||
//int current_depth=d_hist_longitude_d.size();
|
||||
// Push new values
|
||||
d_hist_longitude_d.push_front(d_longitude_d);
|
||||
d_hist_latitude_d.push_front(d_latitude_d);
|
||||
d_hist_height_m.push_front(d_height_m);
|
||||
|
||||
d_avg_latitude_d = d_latitude_d;
|
||||
d_avg_longitude_d = d_longitude_d;
|
||||
d_avg_height_m = d_height_m;
|
||||
b_valid_position = false;
|
||||
return false; //indicates that the returned position is not valid yet
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
b_valid_position = true;
|
||||
return true; //indicates that the returned position is valid
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
b_valid_position = false;
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -80,7 +80,6 @@ public:
|
||||
// new iono storage
|
||||
Galileo_Iono galileo_iono;
|
||||
|
||||
//double d_GPS_current_time;
|
||||
double d_galileo_current_time;
|
||||
boost::posix_time::ptime d_position_UTC_time;
|
||||
|
||||
|
||||
@@ -93,9 +93,11 @@ GalileoE1PcpsAmbiguousAcquisition::GalileoE1PcpsAmbiguousAcquisition(
|
||||
/ (Galileo_E1_CODE_CHIP_RATE_HZ
|
||||
/ Galileo_E1_B_CODE_LENGTH_CHIPS));
|
||||
|
||||
vector_length_ = code_length_ * (int)(sampled_ms_/4);
|
||||
|
||||
int samples_per_ms = code_length_ / 4;
|
||||
|
||||
int samples_per_ms = round(code_length_ / 4.0);
|
||||
|
||||
vector_length_ = sampled_ms_ * samples_per_ms;
|
||||
|
||||
code_ = new gr_complex[vector_length_];
|
||||
|
||||
|
||||
@@ -186,7 +186,7 @@ int galileo_e1_observables_cc::general_work (int noutput_items, gr_vector_int &n
|
||||
d_dump_file.write((char*)&tmp_double, sizeof(double));
|
||||
tmp_double = current_gnss_synchro[i].Pseudorange_m;
|
||||
d_dump_file.write((char*)&tmp_double, sizeof(double));
|
||||
tmp_double = 0;
|
||||
tmp_double = (double)(current_gnss_synchro[i].Flag_valid_pseudorange==true);
|
||||
d_dump_file.write((char*)&tmp_double, sizeof(double));
|
||||
tmp_double = current_gnss_synchro[i].PRN;
|
||||
d_dump_file.write((char*)&tmp_double, sizeof(double));
|
||||
|
||||
@@ -182,13 +182,13 @@ int gps_l1_ca_observables_cc::general_work (int noutput_items, gr_vector_int &ni
|
||||
d_dump_file.write((char*)&tmp_double, sizeof(double));
|
||||
tmp_double = current_gnss_synchro[i].Pseudorange_m;
|
||||
d_dump_file.write((char*)&tmp_double, sizeof(double));
|
||||
tmp_double = 0;
|
||||
tmp_double = (double)(current_gnss_synchro[i].Flag_valid_pseudorange==true);
|
||||
d_dump_file.write((char*)&tmp_double, sizeof(double));
|
||||
tmp_double = current_gnss_synchro[i].PRN;
|
||||
d_dump_file.write((char*)&tmp_double, sizeof(double));
|
||||
}
|
||||
}
|
||||
catch (std::ifstream::failure e)
|
||||
catch (const std::ifstream::failure& e)
|
||||
{
|
||||
std::cout << "Exception writing observables dump file " << e.what() << std::endl;
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define CRC_ERROR_LIMIT 6
|
||||
|
||||
using google::LogMessage;
|
||||
|
||||
@@ -178,17 +179,94 @@ galileo_e1b_telemetry_decoder_cc::galileo_e1b_telemetry_decoder_cc(
|
||||
d_TOW_at_Preamble= 0;
|
||||
d_TOW_at_current_symbol = 0;
|
||||
|
||||
d_CRC_error_counter=0;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
galileo_e1b_telemetry_decoder_cc::~galileo_e1b_telemetry_decoder_cc()
|
||||
{
|
||||
delete d_preambles_symbols;
|
||||
d_dump_file.close();
|
||||
}
|
||||
|
||||
void galileo_e1b_telemetry_decoder_cc::decode_word(double *page_part_symbols,int frame_length)
|
||||
{
|
||||
double page_part_symbols_deint[frame_length];
|
||||
// 1. De-interleave
|
||||
deinterleaver(GALILEO_INAV_INTERLEAVER_ROWS,GALILEO_INAV_INTERLEAVER_COLS,page_part_symbols, page_part_symbols_deint);
|
||||
|
||||
// 2. Viterbi decoder
|
||||
// 2.1 Take into account the NOT gate in G2 polynomial (Galileo ICD Figure 13, FEC encoder)
|
||||
// 2.2 Take into account the possible inversion of the polarity due to PLL lock at 180º
|
||||
for (int i=0;i<frame_length;i++)
|
||||
{
|
||||
if ((i+1)%2==0)
|
||||
{
|
||||
page_part_symbols_deint[i]=-page_part_symbols_deint[i];
|
||||
}
|
||||
}
|
||||
|
||||
int page_part_bits[frame_length/2];
|
||||
viterbi_decoder(page_part_symbols_deint, page_part_bits);
|
||||
|
||||
// 3. Call the Galileo page decoder
|
||||
|
||||
std::string page_String;
|
||||
|
||||
for(int i=0; i < (frame_length/2); i++)
|
||||
{
|
||||
if (page_part_bits[i]>0)
|
||||
{
|
||||
page_String.push_back('1');
|
||||
}else{
|
||||
page_String.push_back('0');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//std::cout<<"ch["<<d_channel<<"] frame part bits: "<<page_String<<std::endl;
|
||||
if (page_part_bits[0]==1)
|
||||
{
|
||||
// DECODE COMPLETE WORD (even + odd) and TEST CRC
|
||||
d_nav.split_page(page_String, flag_even_word_arrived);
|
||||
if(d_nav.flag_CRC_test==true)
|
||||
{
|
||||
std::cout<<"Galileo CRC correct on channel "<<d_channel<<std::endl;
|
||||
}else{
|
||||
std::cout<<"Galileo CRC error on channel "<<d_channel<<std::endl;
|
||||
}
|
||||
flag_even_word_arrived=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// STORE HALF WORD (even page)
|
||||
d_nav.split_page(page_String.c_str(), flag_even_word_arrived);
|
||||
flag_even_word_arrived=1;
|
||||
}
|
||||
|
||||
// 4. Push the new navigation data to the queues
|
||||
|
||||
if (d_nav.have_new_ephemeris()==true)
|
||||
{
|
||||
// get ephemeris object for this SV
|
||||
Galileo_Ephemeris ephemeris=d_nav.get_ephemeris();//notice that the read operation will clear the valid flag
|
||||
//std::cout<<"New Galileo Ephemeris received for SV "<<d_satellite.get_PRN()<<std::endl;
|
||||
d_ephemeris_queue->push(ephemeris);
|
||||
}
|
||||
if (d_nav.have_new_iono_and_GST()==true)
|
||||
{
|
||||
Galileo_Iono iono=d_nav.get_iono(); //notice that the read operation will clear the valid flag
|
||||
//std::cout<<"New Galileo IONO model (and UTC) received for SV "<<d_satellite.get_PRN()<<std::endl;
|
||||
d_iono_queue->push(iono);
|
||||
}
|
||||
if (d_nav.have_new_utc_model()==true)
|
||||
{
|
||||
Galileo_Utc_Model utc_model=d_nav.get_utc_model(); //notice that the read operation will clear the valid flag
|
||||
//std::cout<<"New Galileo UTC model received for SV "<<d_satellite.get_PRN()<<std::endl;
|
||||
d_utc_model_queue->push(utc_model);
|
||||
}
|
||||
}
|
||||
int galileo_e1b_telemetry_decoder_cc::general_work (int noutput_items, gr_vector_int &ninput_items,
|
||||
gr_vector_const_void_star &input_items, gr_vector_void_star &output_items)
|
||||
{
|
||||
@@ -217,29 +295,42 @@ int galileo_e1b_telemetry_decoder_cc::general_work (int noutput_items, gr_vector
|
||||
d_flag_preamble = false;
|
||||
|
||||
//******* frame sync ******************
|
||||
if (abs(corr_value) >= d_symbols_per_preamble)
|
||||
{
|
||||
//std::cout << "Positive preamble correlation for Galileo SAT " << this->d_satellite << std::endl;
|
||||
if (d_stat == 0)
|
||||
if (d_stat == 0) //no preamble information
|
||||
{
|
||||
d_preamble_index = d_sample_counter;//record the preamble sample stamp
|
||||
std::cout << "Preamble detection for Galileo SAT " << this->d_satellite << std::endl;
|
||||
d_stat = 1; // enter into frame pre-detection status
|
||||
if (abs(corr_value) >= d_symbols_per_preamble)
|
||||
{
|
||||
d_preamble_index = d_sample_counter;//record the preamble sample stamp
|
||||
std::cout << "Preamble detection for Galileo SAT " << this->d_satellite << std::endl;
|
||||
d_stat = 1; // enter into frame pre-detection status
|
||||
}
|
||||
}
|
||||
else if (d_stat == 1) //check preamble separation
|
||||
else if (d_stat == 1) // posible preamble lock
|
||||
{
|
||||
preamble_diff = abs(d_sample_counter - d_preamble_index);
|
||||
//std::cout << "preamble_diff="<< preamble_diff <<" for Galileo SAT " << this->d_satellite << std::endl;
|
||||
if (abs(preamble_diff - GALILEO_INAV_PREAMBLE_PERIOD_SYMBOLS) < 1)
|
||||
{
|
||||
|
||||
//std::cout<<"d_sample_counter="<<d_sample_counter<<std::endl;
|
||||
//std::cout<<"corr_value="<<corr_value<<std::endl;
|
||||
if (abs(corr_value) >= d_symbols_per_preamble)
|
||||
{
|
||||
//check preamble separation
|
||||
preamble_diff = abs(d_sample_counter - d_preamble_index);
|
||||
if (abs(preamble_diff - GALILEO_INAV_PREAMBLE_PERIOD_SYMBOLS) == 0)
|
||||
{
|
||||
//try to decode frame
|
||||
std::cout<<"Starting page decoder for Galileo SAT " << this->d_satellite<<std::endl;
|
||||
d_preamble_index=d_sample_counter;//record the preamble sample stamp
|
||||
d_stat=2;
|
||||
}
|
||||
}else{
|
||||
if (preamble_diff>GALILEO_INAV_PREAMBLE_PERIOD_SYMBOLS)
|
||||
{
|
||||
d_stat=0; // start again
|
||||
}
|
||||
}
|
||||
}else if (d_stat==2)
|
||||
{
|
||||
if (d_sample_counter==d_preamble_index+GALILEO_INAV_PREAMBLE_PERIOD_SYMBOLS)
|
||||
{
|
||||
// NEW Galileo page part is received
|
||||
// 0. fetch the symbols into an array
|
||||
int frame_length=GALILEO_INAV_PAGE_PART_SYMBOLS-d_symbols_per_preamble;
|
||||
double page_part_symbols[frame_length];
|
||||
double page_part_symbols_deint[frame_length];
|
||||
|
||||
for (int i=0;i<frame_length;i++)
|
||||
{
|
||||
@@ -251,110 +342,45 @@ int galileo_e1b_telemetry_decoder_cc::general_work (int noutput_items, gr_vector
|
||||
page_part_symbols[i]=-in[0][i+d_symbols_per_preamble].Prompt_I; // because last symbol of the preamble is just received now!
|
||||
}
|
||||
}
|
||||
// 1. De-interleave
|
||||
deinterleaver(GALILEO_INAV_INTERLEAVER_ROWS,GALILEO_INAV_INTERLEAVER_COLS,page_part_symbols, page_part_symbols_deint);
|
||||
|
||||
// 2. Viterbi decoder
|
||||
// 2.1 Take into account the NOT gate in G2 polynomial (Galileo ICD Figure 13, FEC encoder)
|
||||
// 2.2 Take into account the possible inversion of the polarity due to PLL lock at 180º
|
||||
for (int i=0;i<frame_length;i++)
|
||||
//debug
|
||||
//std::cout<<"ch["<<d_channel<<"] Decoder call at preamble index "<<d_sample_counter<<std::endl;
|
||||
// std::cout<<"ch["<<d_channel<<"] frame symbols: ";
|
||||
// for (int j=0;j<frame_length;j++)
|
||||
// {
|
||||
// if (page_part_symbols[j]>0)
|
||||
// {
|
||||
// std::cout<<"1";
|
||||
// }else{
|
||||
// std::cout<<"0";
|
||||
// }
|
||||
// }
|
||||
// std::cout<<std::endl;
|
||||
//end debug
|
||||
//call the decoder
|
||||
decode_word(page_part_symbols,frame_length);
|
||||
if (d_nav.flag_CRC_test==true)
|
||||
{
|
||||
if ((i+1)%2==0)
|
||||
d_CRC_error_counter=0;
|
||||
d_flag_preamble = true; //valid preamble indicator (initialized to false every work())
|
||||
d_preamble_index = d_sample_counter; //record the preamble sample stamp (t_P)
|
||||
d_preamble_time_seconds = in[0][0].Tracking_timestamp_secs;// - d_preamble_duration_seconds; //record the PRN start sample index associated to the preamble
|
||||
if (!d_flag_frame_sync)
|
||||
{
|
||||
d_flag_frame_sync = true;
|
||||
std::cout <<" Frame sync SAT " << this->d_satellite << " with preamble start at " << d_preamble_time_seconds << " [s]" << std::endl;
|
||||
}
|
||||
}else{
|
||||
d_CRC_error_counter++;
|
||||
d_preamble_index = d_sample_counter; //record the preamble sample stamp
|
||||
if (d_CRC_error_counter>CRC_ERROR_LIMIT)
|
||||
{
|
||||
page_part_symbols_deint[i]=-page_part_symbols_deint[i];
|
||||
std::cout << "Lost of frame sync SAT " << this->d_satellite << std::endl;
|
||||
d_flag_frame_sync=false;
|
||||
d_stat=0;
|
||||
}
|
||||
}
|
||||
|
||||
int page_part_bits[frame_length/2];
|
||||
viterbi_decoder(page_part_symbols_deint, page_part_bits);
|
||||
|
||||
// 3. Call the Galileo page decoder
|
||||
|
||||
std::string page_String;
|
||||
|
||||
for(int i=0; i < (frame_length/2); i++)
|
||||
{
|
||||
if (page_part_bits[i]>0)
|
||||
{
|
||||
page_String.push_back('1');
|
||||
}else{
|
||||
page_String.push_back('0');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Galileo_Navigation_Message d_nav; // Now is a class member object, to store the intermediate results from call to call
|
||||
|
||||
if (page_part_bits[0]==1)
|
||||
{
|
||||
//std::cout<<"Page Odd"<<std::endl;
|
||||
d_nav.split_page(page_String.c_str(), flag_even_word_arrived);
|
||||
//decode_page.split_page(page_String, flag_even_word_arrived);
|
||||
flag_even_word_arrived=0;
|
||||
//std::cout << "page odd" << page_String << std::endl;
|
||||
DLOG(INFO) << "mara prova print page odd" << page_String;
|
||||
|
||||
//std::cout<<"Page type ="<< page_part_bits[1]<<std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
//std::cout<<"Page Even"<<std::endl;
|
||||
d_nav.split_page(page_String.c_str(), flag_even_word_arrived);
|
||||
flag_even_word_arrived=1;
|
||||
//std::cout << "page even" << std::endl << page_String << std::endl;
|
||||
DLOG(INFO) << "Page type =" << page_part_bits[1];
|
||||
//std::cout<<"Page type ="<< page_part_bits[1]<<std::endl;
|
||||
}
|
||||
|
||||
// 4. Push the new navigation data to the queues
|
||||
|
||||
if (d_nav.have_new_ephemeris()==true)
|
||||
{
|
||||
// get ephemeris object for this SV
|
||||
Galileo_Ephemeris ephemeris=d_nav.get_ephemeris();//notice that the read operation will clear the valid flag
|
||||
std::cout<<"New Galileo Ephemeris received for SV "<<d_satellite.get_PRN()<<std::endl;
|
||||
d_ephemeris_queue->push(ephemeris);
|
||||
}
|
||||
if (d_nav.have_new_iono_and_GST()==true)
|
||||
{
|
||||
Galileo_Iono iono=d_nav.get_iono(); //notice that the read operation will clear the valid flag
|
||||
std::cout<<"New Galileo IONO model (and UTC) received for SV "<<d_satellite.get_PRN()<<std::endl;
|
||||
d_iono_queue->push(iono);
|
||||
}
|
||||
if (d_nav.have_new_utc_model()==true)
|
||||
{
|
||||
Galileo_Utc_Model utc_model=d_nav.get_utc_model(); //notice that the read operation will clear the valid flag
|
||||
std::cout<<"New Galileo UTC model received for SV "<<d_satellite.get_PRN()<<std::endl;
|
||||
d_utc_model_queue->push(utc_model);
|
||||
}
|
||||
|
||||
d_flag_preamble = true;
|
||||
d_preamble_index = d_sample_counter; //record the preamble sample stamp (t_P)
|
||||
d_preamble_time_seconds = in[0][0].Tracking_timestamp_secs;// - d_preamble_duration_seconds; //record the PRN start sample index associated to the preamble
|
||||
|
||||
if (!d_flag_frame_sync)
|
||||
{
|
||||
d_flag_frame_sync = true;
|
||||
std::cout <<" Frame sync SAT " << this->d_satellite << " with preamble start at " << d_preamble_time_seconds << " [s]" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (d_stat == 1)
|
||||
{
|
||||
preamble_diff = d_sample_counter - d_preamble_index;
|
||||
if (preamble_diff > GALILEO_INAV_PREAMBLE_PERIOD_SYMBOLS)
|
||||
{
|
||||
std::cout << "Lost of frame sync SAT " << this->d_satellite << " preamble_diff= " << preamble_diff << std::endl;
|
||||
d_stat = 0; //lost of frame sync
|
||||
d_flag_frame_sync = false;
|
||||
//flag_TOW_set=false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
consume_each(1); //one by one
|
||||
// UPDATE GNSS SYNCHRO DATA
|
||||
Gnss_Synchro current_synchro_data; //structure to save the synchronization information and send the output object to the next block
|
||||
@@ -370,11 +396,9 @@ int galileo_e1b_telemetry_decoder_cc::general_work (int noutput_items, gr_vector
|
||||
{
|
||||
//std::cout<< "Using TOW_5 for timestamping" << std::endl;
|
||||
d_TOW_at_Preamble = d_nav.TOW_5+GALILEO_PAGE_SECONDS; //TOW_5 refers to the even preamble, but when we decode it we are in the odd part, so 1 second later
|
||||
std::cout << "d_TOW_at_Preamble="<< d_TOW_at_Preamble<< std::endl;
|
||||
/* 1 sec (GALILEO_INAV_PAGE_PART_SYMBOLS*GALIELO_E1_CODE_PERIOD) is added because if we have a TOW value it means that we are at the and of the odd page*/
|
||||
d_TOW_at_current_symbol = d_TOW_at_Preamble + GALILEO_INAV_PAGE_PART_SYMBOLS*GALIELO_E1_CODE_PERIOD;
|
||||
//std::cout << "d_TOW_at_current_symbol="<< d_TOW_at_current_symbol << std::endl;
|
||||
|
||||
d_nav.flag_TOW_5 = 0;
|
||||
}
|
||||
|
||||
@@ -473,7 +497,7 @@ void galileo_e1b_telemetry_decoder_cc::set_channel(int channel)
|
||||
d_dump_file.open(d_dump_filename.c_str(), std::ios::out | std::ios::binary);
|
||||
std::cout << "Telemetry decoder dump enabled on channel " << d_channel << " Log file: " << d_dump_filename.c_str() << std::endl;
|
||||
}
|
||||
catch (std::ifstream::failure e)
|
||||
catch (const std::ifstream::failure& e)
|
||||
{
|
||||
std::cout << "channel " << d_channel << " Exception opening trk dump file " << e.what() << std::endl;
|
||||
}
|
||||
|
||||
@@ -99,6 +99,8 @@ private:
|
||||
|
||||
void deinterleaver(int rows, int cols, double *in, double *out);
|
||||
|
||||
void decode_word(double *symbols,int frame_length);
|
||||
|
||||
unsigned short int d_preambles_bits[GALILEO_INAV_PREAMBLE_LENGTH_BITS];
|
||||
|
||||
signed int *d_preambles_symbols;
|
||||
@@ -112,6 +114,7 @@ private:
|
||||
|
||||
bool d_flag_parity;
|
||||
bool d_flag_preamble;
|
||||
int d_CRC_error_counter;
|
||||
|
||||
long d_fs_in;
|
||||
|
||||
|
||||
@@ -39,7 +39,6 @@
|
||||
#include "galileo_e1_signal_processing.h"
|
||||
#include "tracking_discriminators.h"
|
||||
#include "lock_detectors.h"
|
||||
#include "GPS_L1_CA.h"
|
||||
#include "Galileo_E1.h"
|
||||
#include "control_message_factory.h"
|
||||
#include <boost/lexical_cast.hpp>
|
||||
@@ -252,7 +251,7 @@ void galileo_e1_dll_pll_veml_tracking_cc::update_local_code()
|
||||
}
|
||||
memcpy(d_early_code, &d_very_early_code[very_early_late_spc_samples - early_late_spc_samples], d_current_prn_length_samples* sizeof(gr_complex));
|
||||
memcpy(d_prompt_code, &d_very_early_code[very_early_late_spc_samples], d_current_prn_length_samples* sizeof(gr_complex));
|
||||
memcpy(d_late_code, &d_very_early_code[2*very_early_late_spc_samples - early_late_spc_samples], d_current_prn_length_samples* sizeof(gr_complex));
|
||||
memcpy(d_late_code, &d_very_early_code[very_early_late_spc_samples + early_late_spc_samples], d_current_prn_length_samples* sizeof(gr_complex));
|
||||
memcpy(d_very_late_code, &d_very_early_code[2*very_early_late_spc_samples], d_current_prn_length_samples* sizeof(gr_complex));
|
||||
}
|
||||
|
||||
@@ -491,6 +490,7 @@ int galileo_e1_dll_pll_veml_tracking_cc::general_work (int noutput_items,gr_vect
|
||||
tmp_P = std::abs<float>(*d_Prompt);
|
||||
tmp_L = std::abs<float>(*d_Late);
|
||||
tmp_VL = std::abs<float>(*d_Very_Late);
|
||||
//std::cout<<"VE="<<tmp_VE<<",E="<<tmp_E<<",L="<<tmp_L<<",VL="<<tmp_VL<<std::endl;
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user