SUPL assistance support in progress:

- New SUPL parameters available in GNSS-SDR.conf
- Ephemeris assistance for real-time operation is now functional
- SUPL client now stores the received ephemeris in XML file. This file can be loaded on request to enable post-processing SUPL assistance and to enable SUPL assistance without internet connection. -> thowards a complete warm start GNSS-SDR.

BUG FIXES:
- GN3S driver firmware file copy operation in CmakeLists.txt had an error that mismatches the gn3s_firmware.ihx file location and prevents the correct firmware loading for GN3S SiGe USB dongles.


git-svn-id: https://svn.code.sf.net/p/gnss-sdr/code/trunk@351 64b25241-fba3-4117-9849-534c7e92360d
This commit is contained in:
Javier Arribas 2013-03-18 18:27:44 +00:00
parent 531ef5576a
commit 0bf9e44eb4
15 changed files with 472 additions and 223 deletions

View File

@ -206,7 +206,7 @@ set(Boost_ADDITIONAL_VERSIONS
)
set(Boost_USE_MULTITHREAD ON)
set(Boost_USE_STATIC_LIBS OFF)
find_package(Boost COMPONENTS date_time system filesystem thread REQUIRED)
find_package(Boost COMPONENTS date_time system filesystem thread serialization REQUIRED)
if(NOT Boost_FOUND)
message(FATAL_ERROR "Fatal error: Boost (version >=1.42.0) required.")
endif(NOT Boost_FOUND)

View File

@ -12,6 +12,18 @@ GNSS-SDR.internal_fs_hz=4000000
;######### CONTROL_THREAD CONFIG ############
ControlThread.wait_for_flowgraph=false
;######### SUPL RRLP GPS assistance configuration #####
GNSS-SDR.SUPL_gps_enabled=false
GNSS-SDR.SUPL_read_gps_assistance_xml=true
GNSS-SDR.SUPL_gps_ephemeris_server=supl.nokia.com
GNSS-SDR.SUPL_gps_ephemeris_port=7275
GNSS-SDR.SUPL_gps_acquisition_server=supl.google.com
GNSS-SDR.SUPL_gps_acquisition_port=7275
GNSS-SDR.SUPL_MCC=244
GNSS-SDR.SUPL_MNS=5
GNSS-SDR.SUPL_LAC=0x59e2
GNSS-SDR.SUPL_CI=0x31b0
;######### SIGNAL_SOURCE CONFIG ############
;#implementation: Use [File_Signal_Source] or [UHD_Signal_Source] or [GN3S_Signal_Source] (experimental)
SignalSource.implementation=File_Signal_Source
@ -292,7 +304,7 @@ Acquisition.sampled_ms=1
;#implementation: Acquisition algorithm selection for this channel: [GPS_L1_CA_PCPS_Acquisition]
Acquisition0.implementation=GPS_L1_CA_PCPS_Acquisition
;#threshold: Acquisition threshold
Acquisition0.threshold=70
Acquisition0.threshold=50
;#doppler_max: Maximum expected Doppler shift [Hz]
Acquisition0.doppler_max=10000
;#doppler_max: Doppler step in the grid search [Hz]
@ -302,28 +314,28 @@ Acquisition0.doppler_step=250
;######### ACQUISITION CH 1 CONFIG ############
Acquisition1.implementation=GPS_L1_CA_PCPS_Acquisition
Acquisition1.threshold=70
Acquisition1.threshold=50
Acquisition1.doppler_max=10000
Acquisition1.doppler_step=250
;######### ACQUISITION CH 2 CONFIG ############
Acquisition2.implementation=GPS_L1_CA_PCPS_Acquisition
Acquisition2.threshold=70
Acquisition2.threshold=50
Acquisition2.doppler_max=10000
Acquisition2.doppler_step=250
;######### ACQUISITION CH 3 CONFIG ############
Acquisition3.implementation=GPS_L1_CA_PCPS_Acquisition
Acquisition3.threshold=70
Acquisition3.threshold=50
Acquisition3.doppler_max=10000
Acquisition3.doppler_step=250
;######### ACQUISITION CH 4 CONFIG ############
Acquisition4.implementation=GPS_L1_CA_PCPS_Acquisition
Acquisition4.threshold=70
Acquisition4.threshold=50
Acquisition4.doppler_max=10000
Acquisition4.doppler_step=250
@ -337,21 +349,21 @@ Acquisition5.doppler_step=250
;######### ACQUISITION CH 6 CONFIG ############
Acquisition6.implementation=GPS_L1_CA_PCPS_Acquisition
Acquisition6.threshold=70
Acquisition6.threshold=50
Acquisition6.doppler_max=10000
Acquisition6.doppler_step=250
;######### ACQUISITION CH 7 CONFIG ############
Acquisition7.implementation=GPS_L1_CA_PCPS_Acquisition
Acquisition7.threshold=70
Acquisition7.threshold=50
Acquisition7.doppler_max=10000
Acquisition7.doppler_step=250
;######### ACQUISITION CH 8 CONFIG ############
Acquisition8.implementation=GPS_L1_CA_PCPS_Acquisition
Acquisition8.threshold=70
Acquisition8.threshold=50
Acquisition8.doppler_max=10000
Acquisition8.doppler_step=250

View File

@ -7,7 +7,7 @@
;######### GLOBAL OPTIONS ##################
;internal_fs_hz: Internal signal sampling frequency after the signal conditioning stage [Hz].
GNSS-SDR.internal_fs_hz=2045950
GNSS-SDR.internal_fs_hz=2727933.33
;######### CONTROL_THREAD CONFIG ############
ControlThread.wait_for_flowgraph=false
@ -138,11 +138,12 @@ InputFilter.grid_density=16
;#InputFilter.IF is the intermediate frequency (in Hz) shifted down to zero Hz
; 8183800/5 = 1636760
; 8183800/4 = 2045950
; 8183800/4 = 2727933.33
; 8183800/3 = 2727933.33333333
InputFilter.sampling_frequency=8183800
InputFilter.IF=38400
InputFilter.decimation_factor=4
InputFilter.decimation_factor=3
@ -167,12 +168,12 @@ Resampler.item_type=gr_complex
Resampler.sample_freq_in=8183800
;#sample_freq_out: the desired sample frequency of the output signal
Resampler.sample_freq_out=1636760
Resampler.sample_freq_out=2727933.33
;######### CHANNELS GLOBAL CONFIG ############
;#count: Number of available satellite channels.
Channels.count=7
Channels.count=1
;#in_acquisition: Number of channels simultaneously acquiring
Channels.in_acquisition=1
@ -299,7 +300,7 @@ Acquisition.sampled_ms=1
;#implementation: Acquisition algorithm selection for this channel: [GPS_L1_CA_PCPS_Acquisition]
Acquisition0.implementation=GPS_L1_CA_PCPS_Acquisition
;#threshold: Acquisition threshold
Acquisition0.threshold=70
Acquisition0.threshold=50
;#doppler_max: Maximum expected Doppler shift [Hz]
Acquisition0.doppler_max=10000
;#doppler_max: Doppler step in the grid search [Hz]
@ -309,21 +310,21 @@ Acquisition0.doppler_step=250
;######### ACQUISITION CH 1 CONFIG ############
Acquisition1.implementation=GPS_L1_CA_PCPS_Acquisition
Acquisition1.threshold=70
Acquisition1.threshold=30
Acquisition1.doppler_max=10000
Acquisition1.doppler_step=250
;######### ACQUISITION CH 2 CONFIG ############
Acquisition2.implementation=GPS_L1_CA_PCPS_Acquisition
Acquisition2.threshold=70
Acquisition2.threshold=30
Acquisition2.doppler_max=10000
Acquisition2.doppler_step=250
;######### ACQUISITION CH 3 CONFIG ############
Acquisition3.implementation=GPS_L1_CA_PCPS_Acquisition
Acquisition3.threshold=70
Acquisition3.threshold=30
Acquisition3.doppler_max=10000
Acquisition3.doppler_step=250
@ -367,7 +368,7 @@ Acquisition8.doppler_step=250
;######### TRACKING GLOBAL CONFIG ############
;#implementation: Selected tracking algorithm: [GPS_L1_CA_DLL_PLL_Tracking] or [GPS_L1_CA_DLL_FLL_PLL_Tracking]
Tracking.implementation=GPS_L1_CA_DLL_PLL_Tracking
Tracking.implementation=GPS_L1_CA_DLL_PLL_Optim_Tracking
;#item_type: Type and resolution for each of the signal samples. Use only [gr_complex] in this version.
Tracking.item_type=gr_complex

View File

@ -12,6 +12,18 @@ GNSS-SDR.internal_fs_hz=4000000
;######### CONTROL_THREAD CONFIG ############
ControlThread.wait_for_flowgraph=false
;######### SUPL RRLP GPS assistance configuration #####
GNSS-SDR.SUPL_gps_enabled=false
GNSS-SDR.SUPL_read_gps_assistance_xml=true
GNSS-SDR.SUPL_gps_ephemeris_server=supl.nokia.com
GNSS-SDR.SUPL_gps_ephemeris_port=7275
GNSS-SDR.SUPL_gps_acquisition_server=supl.google.com
GNSS-SDR.SUPL_gps_acquisition_port=7275
GNSS-SDR.SUPL_MCC=244
GNSS-SDR.SUPL_MNS=5
GNSS-SDR.SUPL_LAC=0x59e2
GNSS-SDR.SUPL_CI=0x31b0
;######### SIGNAL_SOURCE CONFIG ############
;#implementation: Use [File_Signal_Source] or [UHD_Signal_Source] or [GN3S_Signal_Source] (experimental)
SignalSource.implementation=File_Signal_Source

View File

@ -240,204 +240,191 @@ arma::vec gps_l1_ca_ls_pvt::leastSquarePos(arma::mat satpos, arma::vec obs, arma
bool gps_l1_ca_ls_pvt::get_PVT(std::map<int,Gnss_Synchro> gnss_pseudoranges_map, double GPS_current_time, bool flag_averaging)
{
std::map<int,Gnss_Synchro>::iterator gnss_pseudoranges_iter;
std::map<int,Gnss_Synchro>::iterator gnss_pseudoranges_iter;
std::map<int,Gps_Ephemeris>::iterator gps_ephemeris_iter;
int valid_pseudoranges=gnss_pseudoranges_map.size();
std::map<int,Gps_Ephemeris>::iterator gps_ephemeris_iter;
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 valid_pseudoranges=gnss_pseudoranges_map.size();
int GPS_week = 0;
double GPS_corrected_time = 0;
double utc = 0;
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
d_flag_averaging = flag_averaging;
int GPS_week = 0;
double GPS_corrected_time = 0;
double utc = 0;
// ********************************************************************************
// ****** 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())
{
d_flag_averaging = flag_averaging;
/*!
* \todo Place here the satellite CN0 (power level, or weight factor)
*/
W(obs_counter,obs_counter) = 1;
// 2- compute the clock error including relativistic effects for this SV
GPS_corrected_time = gps_ephemeris_iter->second.sv_clock_correction(GPS_current_time);
GPS_week = gps_ephemeris_iter->second.i_GPS_week;
// 3- compute the UTC time for this SV
//TODO: check if the utc time model is valid (or it is empty (not received yet!) and no corrections are available)
utc = gps_utc_model.utc_time(GPS_corrected_time,GPS_week);
// 4- compute the current ECEF position for this SV
gps_ephemeris_iter->second.satellitePosition(GPS_corrected_time);
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 + gps_ephemeris_iter->second.d_satClkCorr*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;
}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++;
}
// ********************************************************************************
// ****** 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())
{
// Ephemeris available in the ephemeris map
/*!
* \todo Place here the satellite CN0 (power level, or weight factor)
*/
W(obs_counter,obs_counter) = 1;
// ********************************************************************************
// ****** SOLVE LEAST SQUARES******************************************************
// ********************************************************************************
d_valid_observations = valid_obs;
DLOG(INFO) << "(new)PVT: valid observations=" << valid_obs << std::endl;
// 2- compute the clock error including relativistic effects for this SV
GPS_corrected_time = gps_ephemeris_iter->second.sv_clock_correction(GPS_current_time);
//DLOG(INFO)<<"pseudorranges SV "<<gps_ephemeris_iter->second.i_satellite_PRN
// << " tx_time-d_TOW="<<GPS_corrected_time-gnss_pseudoranges_iter->second.d_TOW<<std::endl;
//DLOG(INFO)<<"pseudorranges SV "<<gps_ephemeris_iter->second.i_satellite_PRN
// << " d_TOW_current_symbol="<<gnss_pseudoranges_iter->second.d_TOW_at_current_symbol<<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);
GPS_week = gps_ephemeris_iter->second.i_GPS_week;
// 3- compute the UTC time for this SV
//TODO: check if the utc time model is valid (or it is empty (not received yet!) and no corrections are available)
utc = gps_utc_model.utc_time(GPS_corrected_time,GPS_week);
//DLOG(INFO)<<"pseudorranges SV "<<gps_ephemeris_iter->second.i_satellite_PRN
// << " symbol_shift_from_preamble="<<gnss_pseudoranges_iter->second.Pseudorange_symbol_shift<<std::endl;
// 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;
GPS_current_time = GPS_corrected_time;
// 4- compute the current ECEF position for this SV
gps_ephemeris_iter->second.satellitePosition(GPS_corrected_time);
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 + gps_ephemeris_iter->second.d_satClkCorr*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;
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;
}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++;
// ######## 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);
// ********************************************************************************
// ****** SOLVE LEAST SQUARES******************************************************
// ********************************************************************************
d_valid_observations = valid_obs;
DLOG(INFO) << "(new)PVT: valid observations=" << valid_obs << std::endl;
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);
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);
// 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;
GPS_current_time = GPS_corrected_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;
// ######## 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_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;
}
}

View File

@ -180,5 +180,6 @@ void FreqXlatingFirFilter::init()
for (std::vector<double>::iterator it = taps_d.begin(); it != taps_d.end(); it++)
{
taps_.push_back(float(*it));
std::cout<<"TAP="<<float(*it)<<std::endl;
}
}

View File

@ -47,7 +47,7 @@ if($ENV{GN3S_DRIVER})
# Copy GN3S firmware binary file to install folder
message(STATUS "Copying the GN3S firmware binary file to install folder")
file(COPY ${CMAKE_SOURCE_DIR}/firmware/GN3S_v2/bin/gn3s_firmware.ihx
DESTINATION ${CMAKE_SOURCE_DIR}/install/gn3s_firmware.ihx
DESTINATION ${CMAKE_SOURCE_DIR}/install/
)
endif($ENV{GN3S_DRIVER})

View File

@ -244,6 +244,14 @@ void gnss_sdr_supl_client::read_supl_data()
gps_ephemeris_map.insert(std::pair<int,Gps_Ephemeris>(e->prn, gps_eph));
gps_eph_iterator=this->gps_ephemeris_map.find(e->prn);
}
if (gps_time.valid)
{
gps_eph_iterator->second.i_GPS_week=assist.time.gps_week;
gps_eph_iterator->second.d_TOW=assist.time.gps_tow;
}else{
gps_eph_iterator->second.i_GPS_week=0;
gps_eph_iterator->second.d_TOW=0;
}
gps_eph_iterator->second.i_satellite_PRN=e->prn;
// SV navigation model
gps_eph_iterator->second.i_code_on_L2=e->bits;
@ -307,3 +315,36 @@ void gnss_sdr_supl_client::read_supl_data()
}
}
}
bool gnss_sdr_supl_client::load_ephemeris_xml(const std::string file_name)
{
try {
std::ifstream ifs(file_name.c_str(), std::ifstream::binary | std::ifstream::in);
boost::archive::xml_iarchive xml(ifs);
gps_ephemeris_map.clear();
xml >> boost::serialization::make_nvp("GNSS-SDR_ephemeris_map", gps_ephemeris_map);
ifs.close();
}catch (std::exception& e)
{
LOG_AT_LEVEL(ERROR)<< e.what() << "File: "<< file_name<<std::endl;
return false;
}
return true;
}
bool gnss_sdr_supl_client::save_ephemeris_xml(const std::string file_name)
{
try {
std::ofstream ofs(file_name.c_str(), std::ofstream::trunc | std::ofstream::out);
boost::archive::xml_oarchive xml(ofs);
xml << boost::serialization::make_nvp("GNSS-SDR_ephemeris_map", gps_ephemeris_map);
ofs.close();
}catch (std::exception& e)
{
LOG_AT_LEVEL(ERROR)<< e.what() << std::endl;
return false;
}
return true;
}

View File

@ -35,6 +35,12 @@
#define GNSS_SDR_SUPL_CLIENT_H_
#include <iostream>
#include <fstream>
#include <boost/archive/xml_oarchive.hpp>
#include <boost/archive/xml_iarchive.hpp>
#include <boost/serialization/map.hpp>
#include <glog/log_severity.h>
#include <glog/logging.h>
extern "C" {
#include "supl.h"
@ -101,6 +107,17 @@ public:
*
*/
void read_supl_data();
/*!
* \brief Read ephemeris map from XML file
*/
bool load_ephemeris_xml(const std::string file_name);
/*!
* \brief Save ephemeris map to XML file.
*/
bool save_ephemeris_xml(const std::string file_name);
/*
* Prints SUPL data to std::cout. Use it for debug purposes only.
*/

View File

@ -421,7 +421,7 @@ static int pdu_make_ulp_pos_init(supl_ctx_t *ctx, supl_ulp_t *pdu) {
case 1: // request Navigation Model (Ephemeris)
req_adata->acquisitionAssistanceRequested = 0; // 1
req_adata->navigationModelRequested = 1; // 1
req_adata->referenceTimeRequested = 0;
req_adata->referenceTimeRequested = 1;
req_adata->utcModelRequested = 0; //1
req_adata->ionosphericModelRequested = 0; // 1
req_adata->referenceLocationRequested = 0;

View File

@ -59,5 +59,11 @@ include_directories(
)
link_directories(${Boost_LIBRARY_DIR})
#Enable GN3S module if the driver is present
if( $ENV{GN3S_DRIVER} )
message( "Precompiler GN3S_DRIVER enabled" )
add_definitions(-DGN3S_DRIVER)
endif($ENV{GN3S_DRIVER} )
add_library(gnss_rx ${GNSS_RECEIVER_SOURCES})
target_link_libraries(gnss_rx ${Boost_LIBRARIES} ${ARMADILLO_LIBRARIES} ${GNURADIO_CORE_LIBRARIES} gnss_system_parameters gnss_sp_libs signal_source_adapters datatype_adapters input_filter_adapters conditioner_adapters resampler_adapters acq_adapters tracking_lib tracking_adapters channel_adapters telemetry_decoder_adapters obs_adapters pvt_adapters pvt_lib out_adapters rx_core_lib)

View File

@ -163,6 +163,27 @@ void ControlThread::set_control_queue(gr_msg_queue_sptr control_queue)
bool ControlThread::read_assistance_from_XML()
{
std::string eph_xml_filename="gps_ephemeris.xml";
std::cout<< "SUPL: Try read GPS ephemeris from XML file "<<eph_xml_filename<<std::endl;
if (supl_client_ephemeris_.load_ephemeris_xml(eph_xml_filename)==true)
{
std::map<int,Gps_Ephemeris>::iterator gps_eph_iter;
for(gps_eph_iter = supl_client_ephemeris_.gps_ephemeris_map.begin();
gps_eph_iter != supl_client_ephemeris_.gps_ephemeris_map.end();
gps_eph_iter++)
{
std::cout<<"SUPL: Read XML Ephemeris for GPS SV "<<gps_eph_iter->first<<std::endl;
global_gps_ephemeris_queue.push(gps_eph_iter->second);
}
return false;
}else{
std::cout<< "ERROR: SUPL client error reading XML"<<std::endl;
std::cout<< "Disabling SUPL assistance.."<<std::endl;
return false;
}
}
void ControlThread::init()
{
// Instantiates a control queue, a GNSS flowgraph, and a control message factory
@ -174,50 +195,106 @@ void ControlThread::init()
applied_actions_ = 0;
// GNSS Assistance configuration
bool enable_gps_supl_assistance=configuration_->property("SUPL_gps_enabled",false);
bool enable_gps_supl_assistance=configuration_->property("GNSS-SDR.SUPL_gps_enabled",false);
if (enable_gps_supl_assistance==true)
//SUPL SERVER TEST. Not operational yet!
{
std::cout<< "SUPL RRLP GPS assistance enabled!"<<std::endl;
std::string default_acq_server="supl.nokia.com";
std::string default_eph_server="supl.google.com";
supl_client_ephemeris_.server_name=configuration_->property("SUPL_ephemeris_server",default_acq_server);
supl_client_acquisition_.server_name=configuration_->property("SUPL_acquisition_server",default_eph_server);
supl_client_ephemeris_.server_port=configuration_->property("SUPL_ephemeris_port",7275);
supl_client_acquisition_.server_port=configuration_->property("SUPL_acquisition_server",7275);
supl_client_ephemeris_.server_name=configuration_->property("GNSS-SDR.SUPL_gps_ephemeris_server",default_acq_server);
supl_client_acquisition_.server_name=configuration_->property("GNSS-SDR.SUPL_gps_acquisition_server",default_eph_server);
supl_client_ephemeris_.server_port=configuration_->property("GNSS-SDR.SUPL_gps_ephemeris_port",7275);
supl_client_acquisition_.server_port=configuration_->property("GNSS-SDR.SUPL_gps_acquisition_port",7275);
supl_mcc=configuration_->property("SUPL_MCC",244);
supl_mns=configuration_->property("SUPL_MNS",5);
supl_mcc=configuration_->property("GNSS-SDR.SUPL_MCC",244);
supl_mns=configuration_->property("GNSS-SDR.SUPL_MNS",5);
std::string default_lac="0x59e2";
std::string default_ci="0x31b0";
try {
supl_lac = boost::lexical_cast<int>(configuration_->property("SUPL_LAC",default_lac));
supl_lac = boost::lexical_cast<int>(configuration_->property("GNSS-SDR.SUPL_LAC",default_lac));
} catch(boost::bad_lexical_cast &) {
supl_lac=0x59e2;
}
try {
supl_ci = boost::lexical_cast<int>(configuration_->property("SUPL_CI",default_ci));
supl_ci = boost::lexical_cast<int>(configuration_->property("GNSS-SDR.SUPL_CI",default_ci));
} catch(boost::bad_lexical_cast &) {
supl_ci=0x31b0;
}
supl_client_ephemeris_.request=0;
int error=supl_client_ephemeris_.get_assistance(supl_mcc,supl_mns,supl_lac,supl_ci);
bool SUPL_read_gps_assistance_xml=configuration_->property("GNSS-SDR.SUPL_read_gps_assistance_xml",false);
if (SUPL_read_gps_assistance_xml==true)
{
// read assistance from file
read_assistance_from_XML();
}else{
// Request ephemeris from SUPL server
int error;
supl_client_ephemeris_.request=1;
std::cout<< "SUPL: Try read GPS ephemeris from SUPL server.."<<std::endl;
error=supl_client_ephemeris_.get_assistance(supl_mcc,supl_mns,supl_lac,supl_ci);
if (error==0)
{
std::cout<< "Try read ephemeris from GPS ephemeris data queue"<<std::endl;
std::map<int,Gps_Ephemeris>::iterator gps_eph_iter;
for(gps_eph_iter = supl_client_ephemeris_.gps_ephemeris_map.begin();
gps_eph_iter != supl_client_ephemeris_.gps_ephemeris_map.end();
gps_eph_iter++)
{
std::cout<<"Received Ephemeris for SV "<<gps_eph_iter->first<<std::endl;
std::cout<<"OMEGA="<<gps_eph_iter->second.d_OMEGA<<std::endl;
std::cout<<"SUPL: Received Ephemeris for GPS SV "<<gps_eph_iter->first<<std::endl;
global_gps_ephemeris_queue.push(gps_eph_iter->second);
}
//Save ephemeris to XML file
std::string eph_xml_filename="gps_ephemeris.xml";
if (supl_client_ephemeris_.save_ephemeris_xml(eph_xml_filename)==true)
{
std::cout<<"SUPL: XML Ephemeris file created"<<std::endl;
}
}else{
std::cout<< "SUPL client for Ephemeris returned "<<error<<std::endl;
std::cout<< "ERROR: SUPL client for Ephemeris returned "<<error<<std::endl;
std::cout<< "Please check internet connection and SUPL server configuration"<<error<<std::endl;
std::cout<< "Trying to read ephemeris from XML file"<<std::endl;
if (read_assistance_from_XML()==false)
{
std::cout<< "ERROR: Could not read Ephemeris file: Disabling SUPL assistance.."<<std::endl;
enable_gps_supl_assistance=false;
stop_=true;
}
}
// Request almanac , IONO and UTC Model
supl_client_ephemeris_.request=0;
std::cout<< "SUPL: Try read Almanac, Iono, Utc Model, Ref Time and Ref Location from SUPL server.."<<std::endl;
error=supl_client_ephemeris_.get_assistance(supl_mcc,supl_mns,supl_lac,supl_ci);
if (error==0)
{
std::map<int,Gps_Almanac>::iterator gps_alm_iter;
for(gps_alm_iter = supl_client_ephemeris_.gps_almanac_map.begin();
gps_alm_iter != supl_client_ephemeris_.gps_almanac_map.end();
gps_alm_iter++)
{
std::cout<<"SUPL: Received Almanac for GPS SV "<<gps_alm_iter->first<<std::endl;
global_gps_almanac_queue.push(gps_alm_iter->second);
}
if (supl_client_ephemeris_.gps_iono.valid==true)
{
std::cout<<"SUPL: Received GPS Iono"<<std::endl;
global_gps_iono_queue.push(supl_client_ephemeris_.gps_iono);
}
if (supl_client_ephemeris_.gps_utc.valid==true)
{
std::cout<<"SUPL: Received GPS UTC Model"<<std::endl;
global_gps_utc_model_queue.push(supl_client_ephemeris_.gps_utc);
}
}else{
std::cout<< "ERROR: SUPL client for Almanac returned "<<error<<std::endl;
std::cout<< "Please check internet connection and SUPL server configuration"<<error<<std::endl;
std::cout<< "Disabling SUPL assistance.."<<std::endl;
enable_gps_supl_assistance=false;
stop_=true;
}
}
}
}
@ -292,7 +369,7 @@ void ControlThread::gps_ephemeris_data_collector()
global_gps_ephemeris_queue.wait_and_pop(gps_eph);
// DEBUG MESSAGE
std::cout << "New ephemeris record has arrived from SAT ID "
std::cout << "Ephemeris record has arrived from SAT ID "
<< gps_eph.i_satellite_PRN << " (Block "
<< gps_eph.satelliteBlock[gps_eph.i_satellite_PRN]
<< ")" << std::endl;
@ -302,18 +379,21 @@ void ControlThread::gps_ephemeris_data_collector()
// Check the EPHEMERIS timestamp. If it is newer, then update the ephemeris
if (gps_eph.i_GPS_week > gps_eph_old.i_GPS_week)
{
std::cout << "Ephemeris record updated (GPS week="<<gps_eph.i_GPS_week<<std::endl;
global_gps_ephemeris_map.write(gps_eph.i_satellite_PRN,gps_eph);
}else{
if (gps_eph.d_TOW>gps_eph_old.d_TOW)
if (gps_eph.d_Toe>gps_eph_old.d_Toe)
{
std::cout << "Ephemeris record updated (Toe="<<gps_eph.d_Toe<<std::endl;
global_gps_ephemeris_map.write(gps_eph.i_satellite_PRN,gps_eph);
}else{
std::cout<<"not updating the existing ephemeris"<<std::endl;
std::cout<<"Not updating the existing ephemeris"<<std::endl;
}
}
}else{
// insert new ephemeris record
std::cout << "New Ephemeris record inserted with Toe="<<gps_eph.d_Toe<<" and GPS Week="<<gps_eph.i_GPS_week<<std::endl;
global_gps_ephemeris_map.write(gps_eph.i_satellite_PRN,gps_eph);
}
}

View File

@ -117,6 +117,7 @@ private:
int supl_ci; // Cell Identity (16 bits, 0-65535 are valid values).
void init();
bool read_assistance_from_XML();
void read_control_messages();
void process_control_messages();
void gps_ephemeris_data_collector();

View File

@ -35,6 +35,47 @@
Gps_Ephemeris::Gps_Ephemeris()
{
i_satellite_PRN=0;
d_TOW=0;
d_Crs=0;
d_Delta_n=0;
d_M_0=0;
d_Cuc=0;
d_e_eccentricity=0;
d_Cus=0;
d_sqrt_A=0;
d_Toe=0;
d_Toc=0;
d_Cic=0;
d_OMEGA0=0;
d_Cis=0;
d_i_0=0;
d_Crc=0;
d_OMEGA=0;
d_OMEGA_DOT=0;
d_IDOT=0;
i_code_on_L2=0;
i_GPS_week=0;
b_L2_P_data_flag=false;
i_SV_accuracy=0;
i_SV_health=0;
d_TGD=0; //!< Estimated Group Delay Differential: L1-L2 correction term only for the benefit of "L1 P(Y)" or "L2 P(Y)" s users [s]
d_IODC=0; //!< Issue of Data, Clock
i_AODO=0; //!< Age of Data Offset (AODO) term for the navigation message correction table (NMCT) contained in subframe 4 (reference paragraph 20.3.3.5.1.9) [s]
b_fit_interval_flag=false;//!< indicates the curve-fit interval used by the CS (Block II/IIA/IIR/IIR-M/IIF) and SS (Block IIIA) in determining the ephemeris parameters, as follows: 0 = 4 hours, 1 = greater than 4 hours.
d_spare1=0;
d_spare2=0;
d_A_f0=0; //!< Coefficient 0 of code phase offset model [s]
d_A_f1=0; //!< Coefficient 1 of code phase offset model [s/s]
d_A_f2=0; //!< Coefficient 2 of code phase offset model [s/s^2]
b_integrity_status_flag=false;
b_alert_flag=false; //!< If true, indicates that the SV URA may be worse than indicated in d_SV_accuracy, use that SV at our own risk.
b_antispoofing_flag=false; //!< If true, the AntiSpoofing mode is ON in that SV
//Plane A (info from http://www.navcen.uscg.gov/?Do=constellationStatus)
satelliteBlock[9] = "IIA";
satelliteBlock[31] = "IIR-M";

View File

@ -35,6 +35,7 @@
#include <iostream>
#include <map>
#include "boost/assign.hpp"
#include <boost/serialization/nvp.hpp>
#include "GPS_L1_CA.h"
@ -131,6 +132,55 @@ public:
std::map<int,std::string> satelliteBlock; //!< Map that stores to which block the PRN belongs http://www.navcen.uscg.gov/?Do=constellationStatus
template<class Archive>
/*
* \brief Serialize is a boost standard method to be called by the boost XML serialization. Here is used to save the ephemeris data on disk file.
*/
void serialize(Archive& archive, const unsigned int version)
{
using boost::serialization::make_nvp;
archive & make_nvp("i_satellite_PRN",i_satellite_PRN); // SV PRN NUMBER
archive & make_nvp("d_TOW",d_TOW); //!< Time of GPS Week of the ephemeris set (taken from subframes TOW) [s]
archive & make_nvp("d_Crs",d_Crs); //!< Amplitude of the Sine Harmonic Correction Term to the Orbit Radius [m]
archive & make_nvp("d_Delta_n",d_Delta_n); //!< Mean Motion Difference From Computed Value [semi-circles/s]
archive & make_nvp("d_M_0",d_M_0); //!< Mean Anomaly at Reference Time [semi-circles]
archive & make_nvp("d_Cuc",d_Cuc); //!< Amplitude of the Cosine Harmonic Correction Term to the Argument of Latitude [rad]
archive & make_nvp("d_e_eccentricity",d_e_eccentricity); //!< Eccentricity [dimensionless]
archive & make_nvp("d_Cus",d_Cus); //!< Amplitude of the Sine Harmonic Correction Term to the Argument of Latitude [rad]
archive & make_nvp("d_sqrt_A",d_sqrt_A); //!< Square Root of the Semi-Major Axis [sqrt(m)]
archive & make_nvp("d_Toe",d_Toe); //!< Ephemeris data reference time of week (Ref. 20.3.3.4.3 IS-GPS-200E) [s]
archive & make_nvp("d_Toc",d_Toe); //!< clock data reference time (Ref. 20.3.3.3.3.1 IS-GPS-200E) [s]
archive & make_nvp("d_Cic",d_Cic); //!< Amplitude of the Cosine Harmonic Correction Term to the Angle of Inclination [rad]
archive & make_nvp("d_OMEGA0",d_OMEGA0); //!< Longitude of Ascending Node of Orbit Plane at Weekly Epoch [semi-circles]
archive & make_nvp("d_Cis",d_Cis); //!< Amplitude of the Sine Harmonic Correction Term to the Angle of Inclination [rad]
archive & make_nvp("d_i_0",d_i_0); //!< Inclination Angle at Reference Time [semi-circles]
archive & make_nvp("d_Crc",d_Crc); //!< Amplitude of the Cosine Harmonic Correction Term to the Orbit Radius [m]
archive & make_nvp("d_OMEGA",d_OMEGA); //!< Argument of Perigee [semi-cicles]
archive & make_nvp("d_OMEGA_DOT",d_OMEGA_DOT); //!< Rate of Right Ascension [semi-circles/s]
archive & make_nvp("d_IDOT",d_IDOT); //!< Rate of Inclination Angle [semi-circles/s]
archive & make_nvp("i_code_on_L2",i_code_on_L2); //!< If 1, P code ON in L2; if 2, C/A code ON in L2;
archive & make_nvp("i_GPS_week",i_GPS_week); //!< GPS week number, aka WN [week]
archive & make_nvp("b_L2_P_data_flag",b_L2_P_data_flag); //!< When true, indicates that the NAV data stream was commanded OFF on the P-code of the L2 channel
archive & make_nvp("i_SV_accuracy",i_SV_accuracy); //!< User Range Accuracy (URA) index of the SV (reference paragraph 6.2.1) for the standard positioning service user (Ref 20.3.3.3.1.3 IS-GPS-200E)
archive & make_nvp("i_SV_health",i_SV_health);
archive & make_nvp("d_TGD",d_TGD); //!< Estimated Group Delay Differential: L1-L2 correction term only for the benefit of "L1 P(Y)" or "L2 P(Y)" s users [s]
archive & make_nvp("d_IODC",d_IODC); //!< Issue of Data, Clock
archive & make_nvp("i_AODO",i_AODO); //!< Age of Data Offset (AODO) term for the navigation message correction table (NMCT) contained in subframe 4 (reference paragraph 20.3.3.5.1.9) [s]
archive & make_nvp("b_fit_interval_flag",b_fit_interval_flag);//!< indicates the curve-fit interval used by the CS (Block II/IIA/IIR/IIR-M/IIF) and SS (Block IIIA) in determining the ephemeris parameters, as follows: 0 = 4 hours, 1 = greater than 4 hours.
archive & make_nvp("d_spare1",d_spare1);
archive & make_nvp("d_spare2",d_spare2);
archive & make_nvp("d_A_f0",d_A_f0); //!< Coefficient 0 of code phase offset model [s]
archive & make_nvp("d_A_f1",d_A_f1); //!< Coefficient 1 of code phase offset model [s/s]
archive & make_nvp("d_A_f2",d_A_f2); //!< Coefficient 2 of code phase offset model [s/s^2]
archive & make_nvp("b_integrity_status_flag",b_integrity_status_flag);
archive & make_nvp("b_alert_flag",b_alert_flag); //!< If true, indicates that the SV URA may be worse than indicated in d_SV_accuracy, use that SV at our own risk.
archive & make_nvp("b_antispoofing_flag",b_antispoofing_flag); //!< If true, the AntiSpoofing mode is ON in that SV
}
/*!
* \brief Compute the ECEF SV coordinates and ECEF velocity
* Implementation of Table 20-IV (IS-GPS-200E)