1
0
mirror of https://github.com/gnss-sdr/gnss-sdr synced 2025-01-07 16:00:35 +00:00

Upgrading obsdiff tool features. Test and ref observables nomenclature changed to rover and base observables

This commit is contained in:
Javier 2020-03-04 10:48:55 +01:00
parent d4df7f9fe7
commit 8082935ae0
3 changed files with 187 additions and 152 deletions

View File

@ -65,18 +65,40 @@ This later option requires [BLAS](http://www.netlib.org/blas/),
### Usage ### Usage
Double differences (Pseudorange, Carrier Phase and Carrier Doppler) within Base and Rover receivers:
``` ```
$ obsdiff --ref_rinex_obs=reference.20o --test_rinex_obs=rover.20o $ obsdiff --base_rinex_obs=base.20o --rover_rinex_obs=rover.20o
``` ```
Double differences with receiver clock correction (Pseudorange, Carrier Phase and Carrier Doppler) within Base and Rover receivers:
```
$ obsdiff --base_rinex_obs=base.20o --rover_rinex_obs=rover.20o --rinex_nav=base.nav --remove_rx_clock_error=true
```
Single difference (Pseudorange, Carrier Phase and Carrier Doppler) with Base receiver only and a special duplicated satellites simulated scenario:
```
$ obsdiff --rover_rinex_obs=rover.20o --single_diff=true --dupli_sat=true --dupli_sat_prns=1,2,3,4
```
Where the list of duplicated satellites PRN pairs must be specified by --dupli_sat_prns flag (_i.e._, `1,2,3,4` indicates that the PRNs 1,2 share the same orbit. The same applies for PRNs 3,4)
Single difference of Pseudorange Rate vs. Carrier Phase rate for each satellite:
```
$ obsdiff --rover_rinex_obs=rover.20o --single_diff=true
```
There is some flexibility in how command-line flags may be specified. The There is some flexibility in how command-line flags may be specified. The
following examples are equivalent: following examples are equivalent:
``` ```
$ obsdiff -ref_rinex_obs=reference.20o $ obsdiff -base_rinex_obs=reference.20o
$ obsdiff --ref_rinex_obs=reference.20o $ obsdiff --base_rinex_obs=reference.20o
$ obsdiff -ref_rinex_obs reference.20o $ obsdiff -base_rinex_obs reference.20o
$ obsdiff --ref_rinex_obs reference.20o $ obsdiff --base_rinex_obs reference.20o
``` ```
For boolean flags, the possibilities are slightly different: For boolean flags, the possibilities are slightly different:
@ -105,9 +127,9 @@ Available command-line flags:
| `--compare_with_5X` | `false` | [`true`, `false`]: If `true`, the program compares the E5a Doppler and Carrier Phases with the E5 full Bw in RINEX (expect discrepancy due to the center frequencies difference). | | `--compare_with_5X` | `false` | [`true`, `false`]: If `true`, the program compares the E5a Doppler and Carrier Phases with the E5 full Bw in RINEX (expect discrepancy due to the center frequencies difference). |
| `--dupli_sat` | `false` | [`true`, `false`]: If `true`, this flag enables special observable test mode where the scenario contains duplicated satellite orbits. | | `--dupli_sat` | `false` | [`true`, `false`]: If `true`, this flag enables special observable test mode where the scenario contains duplicated satellite orbits. |
| `--dupli_sat_prns` | `1,2,3,4` | List of duplicated satellites PRN pairs (_i.e._, `1,2,3,4` indicates that the PRNs 1,2 share the same orbit. The same applies for PRNs 3,4). | | `--dupli_sat_prns` | `1,2,3,4` | List of duplicated satellites PRN pairs (_i.e._, `1,2,3,4` indicates that the PRNs 1,2 share the same orbit. The same applies for PRNs 3,4). |
| `--ref_rinex_obs` | `reference.obs` | Filename of reference RINEX observation file. | | `--base_rinex_obs` | `base.obs` | Filename of reference RINEX observation file. |
| `--test_rinex_obs` | `test.obs` | Filename of tested RINEX observation file. | | `--rover_rinex_obs` | `rover.obs` | Filename of tested RINEX observation file. |
| `--remove_rx_clock_error` | `false` | Compute and remove the receivers clock error prior to compute observable differences (requires a valid RINEX nav file for both receivers) | | `--remove_rx_clock_error` | `false` | Compute and remove the receivers clock error prior to compute observable differences (requires a valid RINEX nav file for both receivers) |
| `--rinex_nav` | `reference.nav` | Filename of reference RINEX navigation file. Only needed if `remove_rx_clock_error` is set to `true`. | | `--rinex_nav` | `base.nav` | Filename of reference RINEX navigation file. Only needed if `remove_rx_clock_error` is set to `true`. |
| `--show_plots` | `true` | [`true`, `false`]: If `true`, and if [gnuplot](http://www.gnuplot.info/) is found on the system, displays results plots on screen. Please set it to `false` for non-interactive testing. | | `--show_plots` | `true` | [`true`, `false`]: If `true`, and if [gnuplot](http://www.gnuplot.info/) is found on the system, displays results plots on screen. Please set it to `false` for non-interactive testing. |
<!-- prettier-ignore-end --> <!-- prettier-ignore-end -->

View File

@ -89,17 +89,17 @@ std::map<int, arma::mat> ReadRinexObs(const std::string& rinex_file, char system
std::cout << "Warning: RINEX Obs file " << rinex_file << " does not exist\n"; std::cout << "Warning: RINEX Obs file " << rinex_file << " does not exist\n";
return obs_map; return obs_map;
} }
// Open and read reference RINEX observables file // Open and read _baseerence RINEX observables file
try try
{ {
gpstk::Rinex3ObsStream r_ref(rinex_file); gpstk::Rinex3ObsStream r_base(rinex_file);
gpstk::Rinex3ObsData r_ref_data; gpstk::Rinex3ObsData r_base_data;
gpstk::Rinex3ObsHeader r_ref_header; gpstk::Rinex3ObsHeader r_base_header;
gpstk::RinexDatum dataobj; gpstk::RinexDatum dataobj;
r_ref >> r_ref_header; r_base >> r_base_header;
std::set<int> PRN_set; std::set<int> PRN_set;
gpstk::SatID prn; gpstk::SatID prn;
@ -119,17 +119,17 @@ std::map<int, arma::mat> ReadRinexObs(const std::string& rinex_file, char system
} }
std::cout << "Reading RINEX OBS file " << rinex_file << " ...\n"; std::cout << "Reading RINEX OBS file " << rinex_file << " ...\n";
while (r_ref >> r_ref_data) while (r_base >> r_base_data)
{ {
for (auto& prn_it : PRN_set) for (auto& prn_it : PRN_set)
{ {
prn.id = prn_it; prn.id = prn_it;
gpstk::CommonTime time = r_ref_data.time; gpstk::CommonTime time = r_base_data.time;
double sow(static_cast<gpstk::GPSWeekSecond>(time).sow); double sow(static_cast<gpstk::GPSWeekSecond>(time).sow);
auto pointer = r_ref_data.obs.find(prn); auto pointer = r_base_data.obs.find(prn);
if (pointer != r_ref_data.obs.end()) if (pointer != r_base_data.obs.end())
{ {
// insert next column // insert next column
try try
@ -147,51 +147,51 @@ std::map<int, arma::mat> ReadRinexObs(const std::string& rinex_file, char system
if (strcmp("1C\0", signal.c_str()) == 0) if (strcmp("1C\0", signal.c_str()) == 0)
{ {
obs_mat.at(obs_mat.n_rows - 1, 0) = sow; obs_mat.at(obs_mat.n_rows - 1, 0) = sow;
dataobj = r_ref_data.getObs(prn, "C1C", r_ref_header); dataobj = r_base_data.getObs(prn, "C1C", r_base_header);
obs_mat.at(obs_mat.n_rows - 1, 1) = dataobj.data; // C1C P1 (psudorange L1) obs_mat.at(obs_mat.n_rows - 1, 1) = dataobj.data; // C1C P1 (psudorange L1)
dataobj = r_ref_data.getObs(prn, "D1C", r_ref_header); dataobj = r_base_data.getObs(prn, "D1C", r_base_header);
obs_mat.at(obs_mat.n_rows - 1, 2) = dataobj.data; // D1C Carrier Doppler obs_mat.at(obs_mat.n_rows - 1, 2) = dataobj.data; // D1C Carrier Doppler
dataobj = r_ref_data.getObs(prn, "L1C", r_ref_header); dataobj = r_base_data.getObs(prn, "L1C", r_base_header);
obs_mat.at(obs_mat.n_rows - 1, 3) = dataobj.data; // L1C Carrier Phase obs_mat.at(obs_mat.n_rows - 1, 3) = dataobj.data; // L1C Carrier Phase
} }
else if (strcmp("1B\0", signal.c_str()) == 0) else if (strcmp("1B\0", signal.c_str()) == 0)
{ {
obs_mat.at(obs_mat.n_rows - 1, 0) = sow; obs_mat.at(obs_mat.n_rows - 1, 0) = sow;
dataobj = r_ref_data.getObs(prn, "C1B", r_ref_header); dataobj = r_base_data.getObs(prn, "C1B", r_base_header);
obs_mat.at(obs_mat.n_rows - 1, 1) = dataobj.data; obs_mat.at(obs_mat.n_rows - 1, 1) = dataobj.data;
dataobj = r_ref_data.getObs(prn, "D1B", r_ref_header); dataobj = r_base_data.getObs(prn, "D1B", r_base_header);
obs_mat.at(obs_mat.n_rows - 1, 2) = dataobj.data; obs_mat.at(obs_mat.n_rows - 1, 2) = dataobj.data;
dataobj = r_ref_data.getObs(prn, "L1B", r_ref_header); dataobj = r_base_data.getObs(prn, "L1B", r_base_header);
obs_mat.at(obs_mat.n_rows - 1, 3) = dataobj.data; obs_mat.at(obs_mat.n_rows - 1, 3) = dataobj.data;
} }
else if (strcmp("2S\0", signal.c_str()) == 0) // L2M else if (strcmp("2S\0", signal.c_str()) == 0) // L2M
{ {
obs_mat.at(obs_mat.n_rows - 1, 0) = sow; obs_mat.at(obs_mat.n_rows - 1, 0) = sow;
dataobj = r_ref_data.getObs(prn, "C2S", r_ref_header); dataobj = r_base_data.getObs(prn, "C2S", r_base_header);
obs_mat.at(obs_mat.n_rows - 1, 1) = dataobj.data; obs_mat.at(obs_mat.n_rows - 1, 1) = dataobj.data;
dataobj = r_ref_data.getObs(prn, "D2S", r_ref_header); dataobj = r_base_data.getObs(prn, "D2S", r_base_header);
obs_mat.at(obs_mat.n_rows - 1, 2) = dataobj.data; obs_mat.at(obs_mat.n_rows - 1, 2) = dataobj.data;
dataobj = r_ref_data.getObs(prn, "L2S", r_ref_header); dataobj = r_base_data.getObs(prn, "L2S", r_base_header);
obs_mat.at(obs_mat.n_rows - 1, 3) = dataobj.data; obs_mat.at(obs_mat.n_rows - 1, 3) = dataobj.data;
} }
else if (strcmp("L5\0", signal.c_str()) == 0) else if (strcmp("L5\0", signal.c_str()) == 0)
{ {
obs_mat.at(obs_mat.n_rows - 1, 0) = sow; obs_mat.at(obs_mat.n_rows - 1, 0) = sow;
dataobj = r_ref_data.getObs(prn, "C5I", r_ref_header); dataobj = r_base_data.getObs(prn, "C5I", r_base_header);
obs_mat.at(obs_mat.n_rows - 1, 1) = dataobj.data; obs_mat.at(obs_mat.n_rows - 1, 1) = dataobj.data;
dataobj = r_ref_data.getObs(prn, "D5I", r_ref_header); dataobj = r_base_data.getObs(prn, "D5I", r_base_header);
obs_mat.at(obs_mat.n_rows - 1, 2) = dataobj.data; obs_mat.at(obs_mat.n_rows - 1, 2) = dataobj.data;
dataobj = r_ref_data.getObs(prn, "L5I", r_ref_header); dataobj = r_base_data.getObs(prn, "L5I", r_base_header);
obs_mat.at(obs_mat.n_rows - 1, 3) = dataobj.data; obs_mat.at(obs_mat.n_rows - 1, 3) = dataobj.data;
} }
else if (strcmp("5X\0", signal.c_str()) == 0) // Simulator gives RINEX with E5a+E5b. Doppler and accumulated Carrier phase WILL differ else if (strcmp("5X\0", signal.c_str()) == 0) // Simulator gives RINEX with E5a+E5b. Doppler and accumulated Carrier phase WILL differ
{ {
obs_mat.at(obs_mat.n_rows - 1, 0) = sow; obs_mat.at(obs_mat.n_rows - 1, 0) = sow;
dataobj = r_ref_data.getObs(prn, "C8I", r_ref_header); dataobj = r_base_data.getObs(prn, "C8I", r_base_header);
obs_mat.at(obs_mat.n_rows - 1, 1) = dataobj.data; obs_mat.at(obs_mat.n_rows - 1, 1) = dataobj.data;
dataobj = r_ref_data.getObs(prn, "D8I", r_ref_header); dataobj = r_base_data.getObs(prn, "D8I", r_base_header);
obs_mat.at(obs_mat.n_rows - 1, 2) = dataobj.data; obs_mat.at(obs_mat.n_rows - 1, 2) = dataobj.data;
dataobj = r_ref_data.getObs(prn, "L8I", r_ref_header); dataobj = r_base_data.getObs(prn, "L8I", r_base_header);
obs_mat.at(obs_mat.n_rows - 1, 3) = dataobj.data; obs_mat.at(obs_mat.n_rows - 1, 3) = dataobj.data;
} }
else else
@ -858,10 +858,12 @@ void coderate_phaserate_consistence(
{ {
arma::vec measurement_time = measured_ch0.col(0); arma::vec measurement_time = measured_ch0.col(0);
arma::vec delta_time = measurement_time.subvec(1, measurement_time.n_elem - 1) - measurement_time.subvec(0, measurement_time.n_elem - 2); arma::vec delta_time = measurement_time.subvec(1, measurement_time.n_elem - 1) - measurement_time.subvec(0, measurement_time.n_elem - 2);
// Test 4 is for the pseudorange phase consistency // Test 4 is for the pseudorange phase consistency
// //
// 1) Checks for the value of the pseudoranges to be within a certain threshold. // 1) Checks for the value of the pseudoranges to be within a certain threshold.
arma::vec prange = measured_ch0.col(1); arma::vec prange = measured_ch0.col(1);
// todo: This code is only valid for L1/E1 carrier frequency. // todo: This code is only valid for L1/E1 carrier frequency.
arma::vec phase = measured_ch0.col(3) * (gpstk::C_MPS / gpstk::L1_FREQ_GPS); arma::vec phase = measured_ch0.col(3) * (gpstk::C_MPS / gpstk::L1_FREQ_GPS);
@ -881,7 +883,7 @@ void coderate_phaserate_consistence(
// 2) It checks that the pseduorange rate is within a certain threshold // 2) It checks that the pseduorange rate is within a certain threshold
// check code rate // check code rate
arma::vec coderate = prange.subvec(1, prange.n_elem - 1) - prange.subvec(0, prange.n_elem - 2) / delta_time; arma::vec coderate = (prange.subvec(1, prange.n_elem - 1) - prange.subvec(0, prange.n_elem - 2)) / delta_time;
// remove NaN // remove NaN
arma::uvec NaN_in_measured_data = arma::find_nonfinite(coderate); arma::uvec NaN_in_measured_data = arma::find_nonfinite(coderate);
@ -901,7 +903,7 @@ void coderate_phaserate_consistence(
} }
// 3) It checks that the phase rate is within a certain threshold // 3) It checks that the phase rate is within a certain threshold
arma::vec phaserate = phase.subvec(1, prange.n_elem - 1) - phase.subvec(0, prange.n_elem - 2) / delta_time; arma::vec phaserate = (phase.subvec(1, prange.n_elem - 1) - phase.subvec(0, prange.n_elem - 2)) / delta_time;
// remove NaN // remove NaN
NaN_in_measured_data = arma::find_nonfinite(phase); NaN_in_measured_data = arma::find_nonfinite(phase);
@ -924,6 +926,17 @@ void coderate_phaserate_consistence(
// check difference between code and phase rates // check difference between code and phase rates
arma::vec ratediff = phaserate - coderate; arma::vec ratediff = phaserate - coderate;
// debug
std::vector<double> tmp_time_vec(measurement_time.colptr(0),
measurement_time.colptr(0) + measurement_time.n_rows);
std::vector<double> tmp_vector_y6(phaserate.colptr(0),
phaserate.colptr(0) + phaserate.n_rows);
save_mat_xy(tmp_time_vec, tmp_vector_y6, std::string("phaserate_" + data_title));
std::vector<double> tmp_vector_y7(coderate.colptr(0),
coderate.colptr(0) + coderate.n_rows);
save_mat_xy(tmp_time_vec, tmp_vector_y7, std::string("coderate_" + data_title));
double maxratediff = 5; double maxratediff = 5;
idx = arma::find(ratediff > maxratediff); idx = arma::find(ratediff > maxratediff);
@ -958,7 +971,7 @@ void coderate_phaserate_consistence(
<< ", stdev = " << sqrt(error_var) << ", stdev = " << sqrt(error_var)
<< " (max,min) = " << max_error << " (max,min) = " << max_error
<< "," << min_error << "," << min_error
<< " [meters]" << std::endl; << " [m/s]" << std::endl;
std::cout.precision(ss); std::cout.precision(ss);
// plots // plots
@ -1291,8 +1304,8 @@ void RINEX_doublediff_dupli_sat()
{ {
// special test mode for duplicated satellites // special test mode for duplicated satellites
// read rinex receiver-under-test observations // read rinex receiver-under-test observations
std::map<int, arma::mat> test_obs = ReadRinexObs(FLAGS_test_rinex_obs, 'G', std::string("1C")); std::map<int, arma::mat> rover_obs = ReadRinexObs(FLAGS_rover_rinex_obs, 'G', std::string("1C"));
if (test_obs.empty()) if (rover_obs.empty())
{ {
return; return;
} }
@ -1300,12 +1313,12 @@ void RINEX_doublediff_dupli_sat()
double initial_transitory_s = FLAGS_skip_obs_transitory_s; double initial_transitory_s = FLAGS_skip_obs_transitory_s;
std::cout << "Skipping initial transitory of " << initial_transitory_s << " [s]" << std::endl; std::cout << "Skipping initial transitory of " << initial_transitory_s << " [s]" << std::endl;
arma::uvec index; arma::uvec index;
for (auto& test_ob : test_obs) for (auto& rover_ob : rover_obs)
{ {
index = arma::find(test_ob.second.col(0) >= (test_ob.second.col(0)(0) + initial_transitory_s), 1, "first"); index = arma::find(rover_ob.second.col(0) >= (rover_ob.second.col(0)(0) + initial_transitory_s), 1, "first");
if ((!index.empty()) and (index(0) > 0)) if ((!index.empty()) and (index(0) > 0))
{ {
test_ob.second.shed_rows(0, index(0)); rover_ob.second.shed_rows(0, index(0));
} }
} }
@ -1330,21 +1343,21 @@ void RINEX_doublediff_dupli_sat()
for (unsigned int n = 0; n < prn_pairs.size(); n = n + 2) for (unsigned int n = 0; n < prn_pairs.size(); n = n + 2)
{ {
// compute double differences // compute double differences
if (test_obs.find(prn_pairs.at(n)) != test_obs.end() and test_obs.find(prn_pairs.at(n + 1)) != test_obs.end()) if (rover_obs.find(prn_pairs.at(n)) != rover_obs.end() and rover_obs.find(prn_pairs.at(n + 1)) != rover_obs.end())
{ {
std::cout << "Computing single difference observables for duplicated SV pairs..." << std::endl; std::cout << "Computing single difference observables for duplicated SV pairs..." << std::endl;
std::cout << "SD = OBS_ROVER(SV" << prn_pairs.at(n) << ") - OBS_ROVER(SV" << prn_pairs.at(n + 1) << ")" << std::endl; std::cout << "SD = OBS_ROVER(SV" << prn_pairs.at(n) << ") - OBS_ROVER(SV" << prn_pairs.at(n + 1) << ")" << std::endl;
code_pseudorange_single_diff(test_obs.at(prn_pairs.at(n)), code_pseudorange_single_diff(rover_obs.at(prn_pairs.at(n)),
test_obs.at(prn_pairs.at(n + 1)), rover_obs.at(prn_pairs.at(n + 1)),
"SD = OBS(SV" + std::to_string(prn_pairs.at(n)) + ") - OBS(SV" + std::to_string(prn_pairs.at(n + 1)) + ") "); "SD = OBS(SV" + std::to_string(prn_pairs.at(n)) + ") - OBS(SV" + std::to_string(prn_pairs.at(n + 1)) + ") ");
carrier_phase_single_diff(test_obs.at(prn_pairs.at(n)), carrier_phase_single_diff(rover_obs.at(prn_pairs.at(n)),
test_obs.at(prn_pairs.at(n + 1)), rover_obs.at(prn_pairs.at(n + 1)),
"SD = OBS(SV" + std::to_string(prn_pairs.at(n)) + ") - OBS(SV" + std::to_string(prn_pairs.at(n + 1)) + ") "); "SD = OBS(SV" + std::to_string(prn_pairs.at(n)) + ") - OBS(SV" + std::to_string(prn_pairs.at(n + 1)) + ") ");
carrier_doppler_single_diff(test_obs.at(prn_pairs.at(n)), carrier_doppler_single_diff(rover_obs.at(prn_pairs.at(n)),
test_obs.at(prn_pairs.at(n + 1)), rover_obs.at(prn_pairs.at(n + 1)),
"SD = OBS(SV" + std::to_string(prn_pairs.at(n)) + ") - OBS(SV" + std::to_string(prn_pairs.at(n + 1)) + ") "); "SD = OBS(SV" + std::to_string(prn_pairs.at(n)) + ") - OBS(SV" + std::to_string(prn_pairs.at(n + 1)) + ") ");
} }
else else
@ -1358,56 +1371,56 @@ void RINEX_doublediff_dupli_sat()
void RINEX_doublediff(bool remove_rx_clock_error) void RINEX_doublediff(bool remove_rx_clock_error)
{ {
// read rinex reference observations // read rinex base observations
std::map<int, arma::mat> ref_obs = ReadRinexObs(FLAGS_ref_rinex_obs, FLAGS_system.c_str()[0], FLAGS_signal); std::map<int, arma::mat> base_obs = ReadRinexObs(FLAGS_base_rinex_obs, FLAGS_system.c_str()[0], FLAGS_signal);
// read rinex receiver-under-test observations // read rinex receiver-under-test (rover) observations
std::map<int, arma::mat> test_obs = ReadRinexObs(FLAGS_test_rinex_obs, FLAGS_system.c_str()[0], FLAGS_signal); std::map<int, arma::mat> rover_obs = ReadRinexObs(FLAGS_rover_rinex_obs, FLAGS_system.c_str()[0], FLAGS_signal);
if (ref_obs.empty() or test_obs.empty()) if (base_obs.empty() or rover_obs.empty())
{ {
return; return;
} }
// compute rx clock errors // compute rx clock errors
double ref_rx_clock_error_s = 0.0; double base_rx_clock_error_s = 0.0;
double test_rx_clock_error_s = 0.0; double rover_rx_clock_error_s = 0.0;
if (remove_rx_clock_error == true) if (remove_rx_clock_error == true)
{ {
ref_rx_clock_error_s = compute_rx_clock_error(FLAGS_rinex_nav, FLAGS_ref_rinex_obs); base_rx_clock_error_s = compute_rx_clock_error(FLAGS_rinex_nav, FLAGS_base_rinex_obs);
test_rx_clock_error_s = compute_rx_clock_error(FLAGS_rinex_nav, FLAGS_test_rinex_obs); rover_rx_clock_error_s = compute_rx_clock_error(FLAGS_rinex_nav, FLAGS_rover_rinex_obs);
} }
double common_clock_error_s = test_rx_clock_error_s - ref_rx_clock_error_s; double common_clock_error_s = rover_rx_clock_error_s - base_rx_clock_error_s;
// Cut measurement initial transitory of the measurements // Cut measurement initial transitory of the measurements
double initial_transitory_s = FLAGS_skip_obs_transitory_s; double initial_transitory_s = FLAGS_skip_obs_transitory_s;
std::cout << "Skipping initial transitory of " << initial_transitory_s << " [s]" << std::endl; std::cout << "Skipping initial transitory of " << initial_transitory_s << " [s]" << std::endl;
arma::uvec index; arma::uvec index;
for (auto& test_ob : test_obs) for (auto& rover_ob : rover_obs)
{ {
index = arma::find(test_ob.second.col(0) >= (test_ob.second.col(0)(0) + initial_transitory_s), 1, "first"); index = arma::find(rover_ob.second.col(0) >= (rover_ob.second.col(0)(0) + initial_transitory_s), 1, "first");
if ((!index.empty()) and (index(0) > 0)) if ((!index.empty()) and (index(0) > 0))
{ {
test_ob.second.shed_rows(0, index(0)); rover_ob.second.shed_rows(0, index(0));
} }
} }
// Cut observation vectors ends to the shortest one (base or rover) // Cut observation vectors ends to the shortest one (base or rover)
arma::colvec ref_obs_time = ref_obs.begin()->second.col(0); arma::colvec base_obs_time = base_obs.begin()->second.col(0);
arma::colvec test_obs_time = test_obs.begin()->second.col(0); arma::colvec rover_obs_time = rover_obs.begin()->second.col(0);
if (ref_obs_time.back() < test_obs_time.back()) if (base_obs_time.back() < rover_obs_time.back())
{ {
// there are more rover observations than base observations // there are more rover observations than base observations
// cut rover vector // cut rover vector
std::cout << "Cutting rover observations vector end.." << std::endl; std::cout << "Cutting rover observations vector end.." << std::endl;
arma::uvec index2; arma::uvec index2;
for (auto& test_ob : test_obs) for (auto& rover_ob : rover_obs)
{ {
index = arma::find(test_ob.second.col(0) >= ref_obs_time.back(), 1, "first"); index = arma::find(rover_ob.second.col(0) >= base_obs_time.back(), 1, "first");
if ((!index.empty()) and (index(0) > 0)) if ((!index.empty()) and (index(0) > 0))
{ {
test_ob.second.shed_rows(index(0), test_ob.second.n_rows - 1); rover_ob.second.shed_rows(index(0), rover_ob.second.n_rows - 1);
} }
} }
} }
@ -1416,124 +1429,124 @@ void RINEX_doublediff(bool remove_rx_clock_error)
// there are more base observations than rover observations // there are more base observations than rover observations
// cut base vector // cut base vector
std::cout << "Cutting base observations vector end.." << std::endl; std::cout << "Cutting base observations vector end.." << std::endl;
for (auto& ref_ob : ref_obs) for (auto& base_ob : base_obs)
{ {
index = arma::find(ref_ob.second.col(0) >= test_obs_time.back(), 1, "first"); index = arma::find(base_ob.second.col(0) >= rover_obs_time.back(), 1, "first");
if ((!index.empty()) and (index(0) > 0)) if ((!index.empty()) and (index(0) > 0))
{ {
ref_ob.second.shed_rows(index(0), ref_ob.second.n_rows - 1); base_ob.second.shed_rows(index(0), base_ob.second.n_rows - 1);
} }
} }
} }
// also skip last seconds of the observations (some artifacts are present in some RINEX endings) // also skip last seconds of the observations (some artifacts are present in some RINEX endings)
ref_obs_time = ref_obs.begin()->second.col(0); base_obs_time = base_obs.begin()->second.col(0);
test_obs_time = test_obs.begin()->second.col(0); rover_obs_time = rover_obs.begin()->second.col(0);
double skip_ends_s = FLAGS_skip_obs_ends_s; double skip_ends_s = FLAGS_skip_obs_ends_s;
std::cout << "Skipping last " << skip_ends_s << " [s] of observations" << std::endl; std::cout << "Skipping last " << skip_ends_s << " [s] of observations" << std::endl;
for (auto& test_ob : test_obs) for (auto& rover_ob : rover_obs)
{ {
index = arma::find(test_ob.second.col(0) >= (test_obs_time.back() - skip_ends_s), 1, "first"); index = arma::find(rover_ob.second.col(0) >= (rover_obs_time.back() - skip_ends_s), 1, "first");
if ((!index.empty()) and (index(0) > 0)) if ((!index.empty()) and (index(0) > 0))
{ {
test_ob.second.shed_rows(index(0), test_ob.second.n_rows - 1); rover_ob.second.shed_rows(index(0), rover_ob.second.n_rows - 1);
} }
} }
for (auto& ref_ob : ref_obs) for (auto& base_ob : base_obs)
{ {
index = arma::find(ref_ob.second.col(0) >= (ref_obs_time.back() - skip_ends_s), 1, "first"); index = arma::find(base_ob.second.col(0) >= (base_obs_time.back() - skip_ends_s), 1, "first");
if ((!index.empty()) and (index(0) > 0)) if ((!index.empty()) and (index(0) > 0))
{ {
ref_ob.second.shed_rows(index(0), ref_ob.second.n_rows - 1); base_ob.second.shed_rows(index(0), base_ob.second.n_rows - 1);
} }
} }
// Save observations in .mat files // Save observations in .mat files
std::cout << "Saving RAW observables inputs to .mat files...\n"; std::cout << "Saving RAW observables inputs to .mat files...\n";
for (auto& ref_ob : ref_obs) for (auto& base_ob : base_obs)
{ {
// std::cout << it->first << " => " << it->second.n_rows << '\n'; // std::cout << it->first << " => " << it->second.n_rows << '\n';
// std::cout << it->first << " has NaN values: " << it->second.has_nan() << '\n'; // std::cout << it->first << " has NaN values: " << it->second.has_nan() << '\n';
std::vector<double> tmp_time_vec(ref_ob.second.col(0).colptr(0), std::vector<double> tmp_time_vec(base_ob.second.col(0).colptr(0),
ref_ob.second.col(0).colptr(0) + ref_ob.second.n_rows); base_ob.second.col(0).colptr(0) + base_ob.second.n_rows);
std::vector<double> tmp_vector(ref_ob.second.col(2).colptr(0), std::vector<double> tmp_vector(base_ob.second.col(2).colptr(0),
ref_ob.second.col(2).colptr(0) + ref_ob.second.n_rows); base_ob.second.col(2).colptr(0) + base_ob.second.n_rows);
save_mat_xy(tmp_time_vec, tmp_vector, std::string("ref_doppler_sat" + std::to_string(ref_ob.first))); save_mat_xy(tmp_time_vec, tmp_vector, std::string("base_doppler_sat" + std::to_string(base_ob.first)));
std::vector<double> tmp_vector2(ref_ob.second.col(3).colptr(0), std::vector<double> tmp_vector2(base_ob.second.col(3).colptr(0),
ref_ob.second.col(3).colptr(0) + ref_ob.second.n_rows); base_ob.second.col(3).colptr(0) + base_ob.second.n_rows);
save_mat_xy(tmp_time_vec, tmp_vector2, std::string("ref_carrier_phase_sat" + std::to_string(ref_ob.first))); save_mat_xy(tmp_time_vec, tmp_vector2, std::string("base_carrier_phase_sat" + std::to_string(base_ob.first)));
std::vector<double> tmp_vector3(ref_ob.second.col(1).colptr(0), std::vector<double> tmp_vector3(base_ob.second.col(1).colptr(0),
ref_ob.second.col(1).colptr(0) + ref_ob.second.n_rows); base_ob.second.col(1).colptr(0) + base_ob.second.n_rows);
save_mat_xy(tmp_time_vec, tmp_vector3, std::string("ref_pseudorange_sat" + std::to_string(ref_ob.first))); save_mat_xy(tmp_time_vec, tmp_vector3, std::string("base_pseudorange_sat" + std::to_string(base_ob.first)));
} }
for (auto& test_ob : test_obs) for (auto& rover_ob : rover_obs)
{ {
// std::cout << it->first << " => " << it->second.n_rows << '\n'; // std::cout << it->first << " => " << it->second.n_rows << '\n';
// std::cout << it->first << " has NaN values: " << it->second.has_nan() << '\n'; // std::cout << it->first << " has NaN values: " << it->second.has_nan() << '\n';
std::vector<double> tmp_time_vec(test_ob.second.col(0).colptr(0), std::vector<double> tmp_time_vec(rover_ob.second.col(0).colptr(0),
test_ob.second.col(0).colptr(0) + test_ob.second.n_rows); rover_ob.second.col(0).colptr(0) + rover_ob.second.n_rows);
std::vector<double> tmp_vector(test_ob.second.col(2).colptr(0), std::vector<double> tmp_vector(rover_ob.second.col(2).colptr(0),
test_ob.second.col(2).colptr(0) + test_ob.second.n_rows); rover_ob.second.col(2).colptr(0) + rover_ob.second.n_rows);
save_mat_xy(tmp_time_vec, tmp_vector, std::string("measured_doppler_sat" + std::to_string(test_ob.first))); save_mat_xy(tmp_time_vec, tmp_vector, std::string("measured_doppler_sat" + std::to_string(rover_ob.first)));
std::vector<double> tmp_vector2(test_ob.second.col(3).colptr(0), std::vector<double> tmp_vector2(rover_ob.second.col(3).colptr(0),
test_ob.second.col(3).colptr(0) + test_ob.second.n_rows); rover_ob.second.col(3).colptr(0) + rover_ob.second.n_rows);
save_mat_xy(tmp_time_vec, tmp_vector2, std::string("measured_carrier_phase_sat" + std::to_string(test_ob.first))); save_mat_xy(tmp_time_vec, tmp_vector2, std::string("measured_carrier_phase_sat" + std::to_string(rover_ob.first)));
std::vector<double> tmp_vector3(test_ob.second.col(1).colptr(0), std::vector<double> tmp_vector3(rover_ob.second.col(1).colptr(0),
test_ob.second.col(1).colptr(0) + test_ob.second.n_rows); rover_ob.second.col(1).colptr(0) + rover_ob.second.n_rows);
save_mat_xy(tmp_time_vec, tmp_vector3, std::string("measured_pseudorange_sat" + std::to_string(test_ob.first))); save_mat_xy(tmp_time_vec, tmp_vector3, std::string("measured_pseudorange_sat" + std::to_string(rover_ob.first)));
} }
// select reference satellite // select reference satellite
std::set<int> PRN_set = available_gps_prn; std::set<int> PRN_set = available_gps_prn;
double min_range = std::numeric_limits<double>::max(); double min_range = std::numeric_limits<double>::max();
int ref_sat_id = 1; int reference_sat_id = 1;
for (auto& ref_prn_it : PRN_set) for (auto& base_prn_it : PRN_set)
{ {
if (ref_obs.find(ref_prn_it) != ref_obs.end() and test_obs.find(ref_prn_it) != test_obs.end()) if (base_obs.find(base_prn_it) != base_obs.end() and rover_obs.find(base_prn_it) != rover_obs.end())
{ {
if (test_obs.at(ref_prn_it).at(0, 1) < min_range) if (rover_obs.at(base_prn_it).at(0, 1) < min_range)
{ {
min_range = test_obs.at(ref_prn_it).at(0, 1); min_range = rover_obs.at(base_prn_it).at(0, 1);
ref_sat_id = ref_prn_it; reference_sat_id = base_prn_it;
} }
} }
} }
// compute double differences // compute double differences
if (ref_obs.find(ref_sat_id) != ref_obs.end() and test_obs.find(ref_sat_id) != test_obs.end()) if (base_obs.find(reference_sat_id) != base_obs.end() and rover_obs.find(reference_sat_id) != rover_obs.end())
{ {
std::cout << "Using reference satellite SV " << ref_sat_id << " with minimum range of " << min_range << " [meters]" << std::endl; std::cout << "Using reference satellite SV " << reference_sat_id << " with minimum range of " << min_range << " [meters]" << std::endl;
for (auto& current_sat_id : PRN_set) for (auto& current_sat_id : PRN_set)
{ {
if (current_sat_id != ref_sat_id) if (current_sat_id != reference_sat_id)
{ {
if (ref_obs.find(current_sat_id) != ref_obs.end() and test_obs.find(current_sat_id) != test_obs.end()) if (base_obs.find(current_sat_id) != base_obs.end() and rover_obs.find(current_sat_id) != rover_obs.end())
{ {
std::cout << "Computing double difference observables for SV " << current_sat_id << std::endl; std::cout << "Computing double difference observables for SV " << current_sat_id << std::endl;
std::cout << "DD = (OBS_ROVER(SV" << current_sat_id << ") - OBS_ROVER(SV" << ref_sat_id << "))" std::cout << "DD = (OBS_ROVER(SV" << current_sat_id << ") - OBS_ROVER(SV" << reference_sat_id << "))"
<< " - (OBS_BASE(SV" << current_sat_id << ") - OBS_BASE(SV" << ref_sat_id << "))" << std::endl; << " - (OBS_BASE(SV" << current_sat_id << ") - OBS_BASE(SV" << reference_sat_id << "))" << std::endl;
code_pseudorange_double_diff(ref_obs.at(ref_sat_id), code_pseudorange_double_diff(base_obs.at(reference_sat_id),
ref_obs.at(current_sat_id), base_obs.at(current_sat_id),
test_obs.at(ref_sat_id), rover_obs.at(reference_sat_id),
test_obs.at(current_sat_id), rover_obs.at(current_sat_id),
"PRN " + std::to_string(current_sat_id) + " ", common_clock_error_s); "PRN " + std::to_string(current_sat_id) + " ", common_clock_error_s);
carrier_phase_double_diff(ref_obs.at(ref_sat_id), carrier_phase_double_diff(base_obs.at(reference_sat_id),
ref_obs.at(current_sat_id), base_obs.at(current_sat_id),
test_obs.at(ref_sat_id), rover_obs.at(reference_sat_id),
test_obs.at(current_sat_id), rover_obs.at(current_sat_id),
"PRN " + std::to_string(current_sat_id) + " ", common_clock_error_s); "PRN " + std::to_string(current_sat_id) + " ", common_clock_error_s);
carrier_doppler_double_diff(ref_obs.at(ref_sat_id), carrier_doppler_double_diff(base_obs.at(reference_sat_id),
ref_obs.at(current_sat_id), base_obs.at(current_sat_id),
test_obs.at(ref_sat_id), rover_obs.at(reference_sat_id),
test_obs.at(current_sat_id), rover_obs.at(current_sat_id),
"PRN " + std::to_string(current_sat_id) + " ", common_clock_error_s); "PRN " + std::to_string(current_sat_id) + " ", common_clock_error_s);
} }
} }
@ -1541,16 +1554,16 @@ void RINEX_doublediff(bool remove_rx_clock_error)
} }
else else
{ {
std::cout << "Satellite ID " << ref_sat_id << " not found in both RINEX files\n"; std::cout << "Satellite ID " << reference_sat_id << " not found in both RINEX files\n";
} }
} }
void RINEX_singlediff() void RINEX_singlediff()
{ {
// read rinex receiver-under-test observations // read rinex receiver-under-test observations
std::map<int, arma::mat> test_obs = ReadRinexObs(FLAGS_test_rinex_obs, FLAGS_system.c_str()[0], FLAGS_signal); std::map<int, arma::mat> rover_obs = ReadRinexObs(FLAGS_rover_rinex_obs, FLAGS_system.c_str()[0], FLAGS_signal);
if (test_obs.empty()) if (rover_obs.empty())
{ {
return; return;
} }
@ -1559,49 +1572,49 @@ void RINEX_singlediff()
double initial_transitory_s = FLAGS_skip_obs_transitory_s; double initial_transitory_s = FLAGS_skip_obs_transitory_s;
std::cout << "Skipping initial transitory of " << initial_transitory_s << " [s]" << std::endl; std::cout << "Skipping initial transitory of " << initial_transitory_s << " [s]" << std::endl;
arma::uvec index; arma::uvec index;
for (auto& test_ob : test_obs) for (auto& rover_ob : rover_obs)
{ {
index = arma::find(test_ob.second.col(0) >= (test_ob.second.col(0)(0) + initial_transitory_s), 1, "first"); index = arma::find(rover_ob.second.col(0) >= (rover_ob.second.col(0)(0) + initial_transitory_s), 1, "first");
if ((!index.empty()) and (index(0) > 0)) if ((!index.empty()) and (index(0) > 0))
{ {
test_ob.second.shed_rows(0, index(0)); rover_ob.second.shed_rows(0, index(0));
} }
} }
// also skip last seconds of the observations (some artifacts are present in some RINEX endings) // also skip last seconds of the observations (some artifacts are present in some RINEX endings)
arma::colvec test_obs_time = test_obs.begin()->second.col(0); arma::colvec rover_obs_time = rover_obs.begin()->second.col(0);
double skip_ends_s = FLAGS_skip_obs_ends_s; double skip_ends_s = FLAGS_skip_obs_ends_s;
std::cout << "Skipping last " << skip_ends_s << " [s] of observations" << std::endl; std::cout << "Skipping last " << skip_ends_s << " [s] of observations" << std::endl;
for (auto& test_ob : test_obs) for (auto& rover_ob : rover_obs)
{ {
index = arma::find(test_ob.second.col(0) >= (test_obs_time.back() - skip_ends_s), 1, "first"); index = arma::find(rover_ob.second.col(0) >= (rover_obs_time.back() - skip_ends_s), 1, "first");
if ((!index.empty()) and (index(0) > 0)) if ((!index.empty()) and (index(0) > 0))
{ {
test_ob.second.shed_rows(index(0), test_ob.second.n_rows - 1); rover_ob.second.shed_rows(index(0), rover_ob.second.n_rows - 1);
} }
} }
// Save observations in .mat files // Save observations in .mat files
std::cout << "Saving RAW observables inputs to .mat files...\n"; std::cout << "Saving RAW observables inputs to .mat files...\n";
for (auto& test_ob : test_obs) for (auto& rover_ob : rover_obs)
{ {
// std::cout << it->first << " => " << it->second.n_rows << '\n'; // std::cout << it->first << " => " << it->second.n_rows << '\n';
// std::cout << it->first << " has NaN values: " << it->second.has_nan() << '\n'; // std::cout << it->first << " has NaN values: " << it->second.has_nan() << '\n';
std::vector<double> tmp_time_vec(test_ob.second.col(0).colptr(0), std::vector<double> tmp_time_vec(rover_ob.second.col(0).colptr(0),
test_ob.second.col(0).colptr(0) + test_ob.second.n_rows); rover_ob.second.col(0).colptr(0) + rover_ob.second.n_rows);
std::vector<double> tmp_vector(test_ob.second.col(2).colptr(0), std::vector<double> tmp_vector(rover_ob.second.col(2).colptr(0),
test_ob.second.col(2).colptr(0) + test_ob.second.n_rows); rover_ob.second.col(2).colptr(0) + rover_ob.second.n_rows);
save_mat_xy(tmp_time_vec, tmp_vector, std::string("measured_doppler_sat" + std::to_string(test_ob.first))); save_mat_xy(tmp_time_vec, tmp_vector, std::string("measured_doppler_sat" + std::to_string(rover_ob.first)));
std::vector<double> tmp_vector2(test_ob.second.col(3).colptr(0), std::vector<double> tmp_vector2(rover_ob.second.col(3).colptr(0),
test_ob.second.col(3).colptr(0) + test_ob.second.n_rows); rover_ob.second.col(3).colptr(0) + rover_ob.second.n_rows);
save_mat_xy(tmp_time_vec, tmp_vector2, std::string("measured_carrier_phase_sat" + std::to_string(test_ob.first))); save_mat_xy(tmp_time_vec, tmp_vector2, std::string("measured_carrier_phase_sat" + std::to_string(rover_ob.first)));
std::vector<double> tmp_vector3(test_ob.second.col(1).colptr(0), std::vector<double> tmp_vector3(rover_ob.second.col(1).colptr(0),
test_ob.second.col(1).colptr(0) + test_ob.second.n_rows); rover_ob.second.col(1).colptr(0) + rover_ob.second.n_rows);
save_mat_xy(tmp_time_vec, tmp_vector3, std::string("measured_pseudorange_sat" + std::to_string(test_ob.first))); save_mat_xy(tmp_time_vec, tmp_vector3, std::string("measured_pseudorange_sat" + std::to_string(rover_ob.first)));
} }
// compute single differences // compute single differences
@ -1609,10 +1622,10 @@ void RINEX_singlediff()
std::cout << "Computing Code Pseudorange rate vs. Carrier phase rate difference..." << std::endl; std::cout << "Computing Code Pseudorange rate vs. Carrier phase rate difference..." << std::endl;
for (auto& current_sat_id : PRN_set) for (auto& current_sat_id : PRN_set)
{ {
if (test_obs.find(current_sat_id) != test_obs.end()) if (rover_obs.find(current_sat_id) != rover_obs.end())
{ {
std::cout << "RateError = PR_rate(SV" << current_sat_id << ") - Phase_rate(SV" << current_sat_id << ")" << std::endl; std::cout << "RateError = PR_rate(SV" << current_sat_id << ") - Phase_rate(SV" << current_sat_id << ")" << std::endl;
coderate_phaserate_consistence(test_obs.at(current_sat_id), "PRN " + std::to_string(current_sat_id) + " "); coderate_phaserate_consistence(rover_obs.at(current_sat_id), "PRN " + std::to_string(current_sat_id) + " ");
} }
} }
} }

View File

@ -30,9 +30,9 @@ DEFINE_bool(compare_with_5X, false, "Compare the E5a Doppler and Carrier Phases
DEFINE_bool(dupli_sat, false, "Enable special observable test mode where the scenario contains duplicated satellite orbits"); DEFINE_bool(dupli_sat, false, "Enable special observable test mode where the scenario contains duplicated satellite orbits");
DEFINE_bool(single_diff, false, "Enable special observable test mode using only rover observables"); DEFINE_bool(single_diff, false, "Enable special observable test mode using only rover observables");
DEFINE_string(dupli_sat_prns, "1,2,3,4", "List of duplicated satellites PRN pairs (i.e. 1,2,3,4 indicates that the PRNs 1,2 share the same orbit. The same applies for PRNs 3,4)"); DEFINE_string(dupli_sat_prns, "1,2,3,4", "List of duplicated satellites PRN pairs (i.e. 1,2,3,4 indicates that the PRNs 1,2 share the same orbit. The same applies for PRNs 3,4)");
DEFINE_string(ref_rinex_obs, "reference.obs", "Filename of reference RINEX observation file"); DEFINE_string(base_rinex_obs, "base.obs", "Filename of reference RINEX observation file");
DEFINE_string(rinex_nav, "reference.nav", "Filename of reference RINEX navigation file"); DEFINE_string(rinex_nav, "base.nav", "Filename of reference RINEX navigation file");
DEFINE_string(test_rinex_obs, "test.obs", "Filename of test RINEX observation file"); DEFINE_string(rover_rinex_obs, "base.obs", "Filename of test RINEX observation file");
DEFINE_string(system, "G", "GNSS satellite system: G for GPS, E for Galileo"); DEFINE_string(system, "G", "GNSS satellite system: G for GPS, E for Galileo");
DEFINE_string(signal, "1C", "GNSS signal: 1C for GPS L1 CA, 1B for Galileo E1"); DEFINE_string(signal, "1C", "GNSS signal: 1C for GPS L1 CA, 1B for Galileo E1");
DEFINE_bool(remove_rx_clock_error, false, "Compute and remove the receivers clock error prior to compute observable differences (requires a valid RINEX nav file for both receivers)"); DEFINE_bool(remove_rx_clock_error, false, "Compute and remove the receivers clock error prior to compute observable differences (requires a valid RINEX nav file for both receivers)");