Merge branch 'next' of https://github.com/gnss-sdr/gnss-sdr into glonass

This commit is contained in:
Carles Fernandez 2017-11-11 11:02:21 +01:00
commit 46a96775e4
9 changed files with 1187 additions and 157 deletions

View File

@ -0,0 +1,11 @@
:+1::tada: Hello, and thanks for contributing to [GNSS-SDR](http://gnss-sdr.org)! :tada::+1:
Before submitting your pull request, please make sure the following is done:
1. You undertake the [Contributor Covenant Code of Conduct](https://github.com/gnss-sdr/gnss-sdr/blob/master/CODE_OF_CONDUCT.md).
2. If you are a first-time contributor, after your pull request you will be asked to sign an Individual Contributor License Agreement ([CLA](https://en.wikipedia.org/wiki/Contributor_License_Agreement)) before your code gets accepted into `master`. This license is for your protection as a Contributor as well as for the protection of [CTTC](http://www.cttc.es/); it does not change your rights to use your own contributions for any other purpose. Except for the license granted therein to CTTC and recipients of software distributed by CTTC, you reserve all right, title, and interest in and to your contributions. The information you provide in that CLA will be maintained in accordance with [CTTC's privacy policy](http://www.cttc.es/privacy/).
3. You have read the [Contributing Guidelines](https://github.com/gnss-sdr/gnss-sdr/blob/master/CONTRIBUTING.md).
4. You have read the [coding style guide](http://gnss-sdr.org/coding-style/).
5. You have forked the [gnss-sdr upstream repository](https://github.com/gnss-sdr/gnss-sdr) and have created your branch from `next` (or any other currently living branch in the upstream repository).
6. Please include a description of your changes here.
**Please feel free to delete this line and the above text once you have read it and in case you want to go on with your pull request.**

View File

@ -419,8 +419,6 @@ void Rinex_Printer::rinex_nav_header(std::fstream& out, const Glonass_Gnav_Utc_M
{
if(glonass_gnav_almanac.i_satellite_freq_channel){}
std::string line;
stringVersion = "3.02";
version = 3;
// -------- Line 1
line = std::string(5, ' ');
@ -643,8 +641,6 @@ void Rinex_Printer::rinex_nav_header(std::fstream& out, const Galileo_Iono& gali
//Avoid compiler warning, there is not time system correction between Galileo and GLONASS
if(galileo_almanac.A_0G_10){}
std::string line;
stringVersion = "3.02";
version = 3;
// -------- Line 1
line = std::string(5, ' ');
@ -753,8 +749,6 @@ void Rinex_Printer::rinex_nav_header(std::fstream& out, const Galileo_Iono& gali
void Rinex_Printer::rinex_nav_header(std::fstream& out, const Galileo_Iono& iono, const Galileo_Utc_Model& utc_model, const Galileo_Almanac& galileo_almanac)
{
std::string line;
stringVersion = "3.02";
version = 3;
// -------- Line 1
line = std::string(5, ' ');
@ -1159,8 +1153,6 @@ void Rinex_Printer::rinex_nav_header(std::fstream& out, const Gps_Iono& iono, co
void Rinex_Printer::rinex_nav_header(std::fstream& out, const Gps_Iono& gps_iono, const Gps_Utc_Model& gps_utc_model, const Galileo_Iono& galileo_iono, const Galileo_Utc_Model& galileo_utc_model, const Galileo_Almanac& galileo_almanac)
{
std::string line;
stringVersion = "3.02";
version = 3;
// -------- Line 1
line = std::string(5, ' ');
@ -5198,6 +5190,7 @@ void Rinex_Printer::rinex_obs_header(std::fstream& out, const Gps_Ephemeris& gps
out << line << std::endl;
}
void Rinex_Printer::update_obs_header(std::fstream& out, const Glonass_Gnav_Utc_Model& utc_model)
{
if(utc_model.d_N_4)
@ -5585,7 +5578,6 @@ void Rinex_Printer::log_rinex_obs(std::fstream& out, const Glonass_Gnav_Ephemeri
}
line += Rinex_Printer::rightJustify(boost::lexical_cast<std::string>(numSatellitesObserved), 3);
// Receiver clock offset (optional)
//line += rightJustify(asString(clockOffset, 12), 15);
@ -5655,6 +5647,9 @@ void Rinex_Printer::log_rinex_obs(std::fstream& out, const Glonass_Gnav_Ephemeri
}
void Rinex_Printer::log_rinex_obs(std::fstream& out, const Gps_Ephemeris& gps_eph, const Glonass_Gnav_Ephemeris& glonass_gnav_eph, double gps_obs_time, const std::map<int,Gnss_Synchro>& observables)
{
if(glonass_gnav_eph.d_m){} // avoid warning, not needed

View File

@ -1,11 +1,12 @@
/*!
* \file freq_xlating_fir_filter.cc
* \brief Adapts a gnuradio gr_freq_xlating_fir_filter designed with gr_remez
* \brief Adapts a gnuradio gr_freq_xlating_fir_filter designed with gr_remez or gr_firdes
* \author Luis Esteve, 2012. luis(at)epsilon-formacion.com
* Antonio Ramos, 2017. antonio.ramos(at)cttc.es
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
* Copyright (C) 2010-2017 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
@ -32,6 +33,7 @@
#include <boost/lexical_cast.hpp>
#include <gnuradio/blocks/file_sink.h>
#include <gnuradio/filter/pm_remez.h>
#include <gnuradio/filter/firdes.h>
#include <glog/logging.h>
#include <volk/volk.h>
#include "configuration_interface.h"
@ -343,8 +345,8 @@ void FreqXlatingFirFilter::init()
std::string default_output_item_type = "gr_complex";
std::string default_taps_item_type = "float";
std::string default_dump_filename = "../data/input_filter.dat";
double default_intermediate_freq = 0;
double default_sampling_freq = 4000000;
double default_intermediate_freq = 0.0;
double default_sampling_freq = 4000000.0;
int default_number_of_taps = 6;
unsigned int default_number_of_bands = 2;
std::vector<double> default_bands = { 0.0, 0.4, 0.6, 1.0 };
@ -364,46 +366,54 @@ void FreqXlatingFirFilter::init()
sampling_freq_ = config_->property(role_ + ".sampling_frequency", default_sampling_freq);
int number_of_taps = config_->property(role_ + ".number_of_taps", default_number_of_taps);
unsigned int number_of_bands = config_->property(role_ + ".number_of_bands", default_number_of_bands);
std::vector<double> bands;
std::vector<double> ampl;
std::vector<double> error_w;
std::string option;
double option_value;
for (unsigned int i = 0; i < number_of_bands; i++)
{
option = ".band" + boost::lexical_cast<std::string>(i + 1) + "_begin";
option_value = config_->property(role_ + option, default_bands[i]);
bands.push_back(option_value);
option = ".band" + boost::lexical_cast<std::string>(i + 1) + "_end";
option_value = config_->property(role_ + option, default_bands[i]);
bands.push_back(option_value);
option = ".ampl" + boost::lexical_cast<std::string>(i + 1) + "_begin";
option_value = config_->property(role_ + option, default_bands[i]);
ampl.push_back(option_value);
option = ".ampl" + boost::lexical_cast<std::string>(i + 1) + "_end";
option_value = config_->property(role_ + option, default_bands[i]);
ampl.push_back(option_value);
option = ".band" + boost::lexical_cast<std::string>(i + 1) + "_error";
option_value = config_->property(role_ + option, default_bands[i]);
error_w.push_back(option_value);
}
std::string filter_type = config_->property(role_ + ".filter_type", default_filter_type);
int grid_density = config_->property(role_ + ".grid_density", default_grid_density);
std::vector<double> taps_d = gr::filter::pm_remez(number_of_taps - 1, bands, ampl,
error_w, filter_type, grid_density);
taps_.reserve(taps_d.size());
for (std::vector<double>::iterator it = taps_d.begin(); it != taps_d.end(); it++)
if(filter_type.compare("lowpass") != 0)
{
taps_.push_back(float(*it));
//std::cout<<"TAP="<<float(*it)<<std::endl;
std::vector<double> taps_d;
std::vector<double> bands;
std::vector<double> ampl;
std::vector<double> error_w;
std::string option;
double option_value;
for (unsigned int i = 0; i < number_of_bands; i++)
{
option = ".band" + boost::lexical_cast<std::string>(i + 1) + "_begin";
option_value = config_->property(role_ + option, default_bands[i]);
bands.push_back(option_value);
option = ".band" + boost::lexical_cast<std::string>(i + 1) + "_end";
option_value = config_->property(role_ + option, default_bands[i]);
bands.push_back(option_value);
option = ".ampl" + boost::lexical_cast<std::string>(i + 1) + "_begin";
option_value = config_->property(role_ + option, default_bands[i]);
ampl.push_back(option_value);
option = ".ampl" + boost::lexical_cast<std::string>(i + 1) + "_end";
option_value = config_->property(role_ + option, default_bands[i]);
ampl.push_back(option_value);
option = ".band" + boost::lexical_cast<std::string>(i + 1) + "_error";
option_value = config_->property(role_ + option, default_bands[i]);
error_w.push_back(option_value);
}
int grid_density = config_->property(role_ + ".grid_density", default_grid_density);
taps_d = gr::filter::pm_remez(number_of_taps - 1, bands, ampl, error_w, filter_type, grid_density);
taps_.reserve(taps_d.size());
for (std::vector<double>::iterator it = taps_d.begin(); it != taps_d.end(); it++)
{
taps_.push_back(static_cast<float>(*it));
}
}
else
{
double default_bw = 2000000.0;
double bw_ = config_->property(role_ + ".bw", default_bw);
double default_tw = bw_ / 10.0;
double tw_ = config_->property(role_ + ".tw", default_tw);
taps_ = gr::filter::firdes::low_pass(1.0, sampling_freq_, bw_, tw_);
}
}

View File

@ -28,10 +28,13 @@
* -------------------------------------------------------------------------
*/
#include "pulse_blanking_filter.h"
#include <boost/lexical_cast.hpp>
#include <vector>
#include <cmath>
#include <glog/logging.h>
#include <gnuradio/filter/firdes.h>
#include "configuration_interface.h"
#include "pulse_blanking_filter.h"
using google::LogMessage;
@ -41,6 +44,7 @@ PulseBlankingFilter::PulseBlankingFilter(ConfigurationInterface* configuration,
out_streams_(out_streams)
{
size_t item_size;
xlat_ = false;
std::string default_input_item_type = "gr_complex";
std::string default_output_item_type = "gr_complex";
std::string default_dump_filename = "../data/input_filter.dat";
@ -71,7 +75,21 @@ PulseBlankingFilter::PulseBlankingFilter(ConfigurationInterface* configuration,
item_size = sizeof(gr_complex); //avoids uninitialization
input_size_ = sizeof(gr_complex); //avoids uninitialization
}
double default_if = 0.0;
double if_aux = config_->property(role_ + ".if", default_if);
double if_ = config_->property(role_ + ".IF", if_aux);
if (std::abs(if_) > 1.0)
{
xlat_ = true;
double default_sampling_freq = 4000000.0;
double sampling_freq_ = config_->property(role_ + ".sampling_frequency", default_sampling_freq);
double default_bw = 2000000.0;
double bw_ = config_->property(role_ + ".bw", default_bw);
double default_tw = bw_ / 10.0;
double tw_ = config_->property(role_ + ".tw", default_tw);
const std::vector<float> taps = gr::filter::firdes::low_pass(1.0, sampling_freq_, bw_ , tw_);
freq_xlating_ = gr::filter::freq_xlating_fir_filter_ccf::make(1, taps, if_, sampling_freq_);
}
if (dump_)
{
DLOG(INFO) << "Dumping output into file " << dump_filename_;
@ -95,6 +113,10 @@ void PulseBlankingFilter::connect(gr::top_block_sptr top_block)
{
top_block->connect(pulse_blanking_cc_, 0, file_sink_, 0);
}
if (xlat_)
{
top_block->connect(freq_xlating_, 0, pulse_blanking_cc_, 0);
}
}
else
@ -113,6 +135,10 @@ void PulseBlankingFilter::disconnect(gr::top_block_sptr top_block)
{
top_block->disconnect(pulse_blanking_cc_, 0, file_sink_, 0);
}
if (xlat_)
{
top_block->disconnect(freq_xlating_, 0, pulse_blanking_cc_, 0);
}
}
else
{
@ -125,7 +151,14 @@ gr::basic_block_sptr PulseBlankingFilter::get_left_block()
{
if (input_item_type_.compare("gr_complex") == 0)
{
return pulse_blanking_cc_;
if (xlat_)
{
return freq_xlating_;
}
else
{
return pulse_blanking_cc_;
}
}
else
{

View File

@ -33,8 +33,8 @@
#define GNSS_SDR_PULSE_BLANKING_FILTER_H_
#include <string>
#include <vector>
#include <gnuradio/blocks/file_sink.h>
#include <gnuradio/filter/freq_xlating_fir_filter_ccf.h>
#include "gnss_block_interface.h"
#include "pulse_blanking_cc.h"
@ -73,6 +73,7 @@ public:
private:
ConfigurationInterface* config_;
bool dump_;
bool xlat_;
std::string dump_filename_;
std::string input_item_type_;
size_t input_size_;
@ -82,6 +83,7 @@ private:
unsigned int out_streams_;
gr::blocks::file_sink::sptr file_sink_;
pulse_blanking_cc_sptr pulse_blanking_cc_;
gr::filter::freq_xlating_fir_filter_ccf::sptr freq_xlating_;
};
#endif // GNSS_SDR_PULSE_BLANKING_FILTER_H_

View File

@ -414,13 +414,20 @@ if(ENABLE_SYSTEM_TESTING)
set(HOST_SYSTEM "MacOS")
endif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
add_definitions(-DHOST_SYSTEM="${HOST_SYSTEM}")
add_executable(ttff
${CMAKE_CURRENT_SOURCE_DIR}/system-tests/ttff_gps_l1.cc )
set(TTFF_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/system-tests/ttff_gps_l1.cc)
# Ensure that ttff is rebuilt if it was previously built and then removed
if(NOT EXISTS ${CMAKE_SOURCE_DIR}/install/ttff)
execute_process(COMMAND ${CMAKE_COMMAND} -E touch ${TTFF_SOURCES})
endif(NOT EXISTS ${CMAKE_SOURCE_DIR}/install/ttff)
add_executable(ttff ${TTFF_SOURCES} )
if(NOT ${GTEST_DIR_LOCAL})
add_dependencies(ttff gtest-${GNSSSDR_GTEST_LOCAL_VERSION})
else(NOT ${GTEST_DIR_LOCAL})
add_dependencies(ttff gtest)
endif(NOT ${GTEST_DIR_LOCAL})
target_link_libraries(ttff
${Boost_LIBRARIES}
${GFlags_LIBS}
@ -448,8 +455,12 @@ if(ENABLE_SYSTEM_TESTING)
endif(ENABLE_INSTALL_TESTS)
if(ENABLE_SYSTEM_TESTING_EXTRA)
add_executable(position_test
${CMAKE_CURRENT_SOURCE_DIR}/system-tests/position_test.cc )
set(POSITION_TEST_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/system-tests/position_test.cc)
# Ensure that position_test is rebuilt if it was previously built and then removed
if(NOT EXISTS ${CMAKE_SOURCE_DIR}/install/position_test)
execute_process(COMMAND ${CMAKE_COMMAND} -E touch ${POSITION_TEST_SOURCES})
endif(NOT EXISTS ${CMAKE_SOURCE_DIR}/install/position_test)
add_executable(position_test ${POSITION_TEST_SOURCES})
if(NOT ${GTEST_DIR_LOCAL})
add_dependencies(position_test gtest-${GNSSSDR_GTEST_LOCAL_VERSION})
else(NOT ${GTEST_DIR_LOCAL})
@ -482,11 +493,26 @@ if(ENABLE_SYSTEM_TESTING)
endif(ENABLE_INSTALL_TESTS)
if(GPSTK_FOUND OR OWN_GPSTK)
add_executable(obs_gps_l1_system_test ${CMAKE_CURRENT_SOURCE_DIR}/system-tests/obs_gps_l1_system_test.cc)
set(OBS_GPS_L1_TEST_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/system-tests/obs_gps_l1_system_test.cc)
# Ensure that obs_gps_l1_system_test is rebuilt if it was previously built and then removed
if(NOT EXISTS ${CMAKE_SOURCE_DIR}/install/obs_gps_l1_system_test)
execute_process(COMMAND ${CMAKE_COMMAND} -E touch ${OBS_GPS_L1_TEST_SOURCES})
endif(NOT EXISTS ${CMAKE_SOURCE_DIR}/install/obs_gps_l1_system_test)
add_executable(obs_gps_l1_system_test ${OBS_GPS_L1_TEST_SOURCES})
set(OBS_SYSTEM_TEST_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/system-tests/obs_system_test.cc)
# Ensure that obs_system_test is rebuilt if it was previously built and then removed
if(NOT EXISTS ${CMAKE_SOURCE_DIR}/install/obs_system_test)
execute_process(COMMAND ${CMAKE_COMMAND} -E touch ${OBS_SYSTEM_TEST_SOURCES})
endif(NOT EXISTS ${CMAKE_SOURCE_DIR}/install/obs_system_test)
add_executable(obs_system_test ${OBS_SYSTEM_TEST_SOURCES})
if(NOT ${GTEST_DIR_LOCAL})
add_dependencies(obs_gps_l1_system_test gtest-${GNSSSDR_GTEST_LOCAL_VERSION} )
add_dependencies(obs_system_test gtest-${GNSSSDR_GTEST_LOCAL_VERSION} )
else(NOT ${GTEST_DIR_LOCAL})
add_dependencies(obs_gps_l1_system_test gtest)
add_dependencies(obs_system_test gtest)
endif(NOT ${GTEST_DIR_LOCAL})
include_directories(${GPSTK_INCLUDE_DIRS} ${GPSTK_INCLUDE_DIRS}/gpstk)
target_link_libraries(obs_gps_l1_system_test ${GFlags_LIBS}
@ -495,20 +521,60 @@ if(ENABLE_SYSTEM_TESTING)
gnss_sp_libs
gnss_rx
${gpstk_libs})
target_link_libraries(obs_system_test ${GFlags_LIBS}
${GLOG_LIBRARIES}
${GTEST_LIBRARIES}
gnss_sp_libs
gnss_rx
${gpstk_libs})
if(ENABLE_INSTALL_TESTS)
if(EXISTS ${CMAKE_SOURCE_DIR}/install/obs_gps_l1_system_test)
file(REMOVE ${CMAKE_SOURCE_DIR}/install/obs_gps_l1_system_test)
endif(EXISTS ${CMAKE_SOURCE_DIR}/install/obs_gps_l1_system_test)
install(TARGETS obs_gps_l1_system_test RUNTIME DESTINATION bin COMPONENT "obs_gps_l1_system_test")
if(EXISTS ${CMAKE_SOURCE_DIR}/install/obs_system_test)
file(REMOVE ${CMAKE_SOURCE_DIR}/install/obs_system_test)
endif(EXISTS ${CMAKE_SOURCE_DIR}/install/obs_system_test)
install(TARGETS obs_system_test RUNTIME DESTINATION bin COMPONENT "obs_system_test")
else(ENABLE_INSTALL_TESTS)
add_custom_command(TARGET obs_gps_l1_system_test POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:obs_gps_l1_system_test>
${CMAKE_SOURCE_DIR}/install/$<TARGET_FILE_NAME:obs_gps_l1_system_test> )
add_custom_command(TARGET obs_system_test POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:obs_system_test>
${CMAKE_SOURCE_DIR}/install/$<TARGET_FILE_NAME:obs_system_test> )
endif(ENABLE_INSTALL_TESTS)
endif(GPSTK_FOUND OR OWN_GPSTK)
else(ENABLE_SYSTEM_TESTING_EXTRA)
# Avoid working with old executables if they were switched ON and then OFF
if(EXISTS ${CMAKE_SOURCE_DIR}/install/position_test)
file(REMOVE ${CMAKE_SOURCE_DIR}/install/position_test)
endif(EXISTS ${CMAKE_SOURCE_DIR}/install/position_test)
if(EXISTS ${CMAKE_SOURCE_DIR}/install/obs_gps_l1_system_test)
file(REMOVE ${CMAKE_SOURCE_DIR}/install/obs_gps_l1_system_test)
endif(EXISTS ${CMAKE_SOURCE_DIR}/install/obs_gps_l1_system_test)
if(EXISTS ${CMAKE_SOURCE_DIR}/install/obs_system_test)
file(REMOVE ${CMAKE_SOURCE_DIR}/install/obs_system_test)
endif(EXISTS ${CMAKE_SOURCE_DIR}/install/obs_system_test)
endif(ENABLE_SYSTEM_TESTING_EXTRA)
else(ENABLE_SYSTEM_TESTING)
# Avoid working with old executables if they were switched ON and then OFF
if(EXISTS ${CMAKE_SOURCE_DIR}/install/ttff)
file(REMOVE ${CMAKE_SOURCE_DIR}/install/ttff)
endif(EXISTS ${CMAKE_SOURCE_DIR}/install/ttff)
if(EXISTS ${CMAKE_SOURCE_DIR}/install/position_test)
file(REMOVE ${CMAKE_SOURCE_DIR}/install/position_test)
endif(EXISTS ${CMAKE_SOURCE_DIR}/install/position_test)
if(EXISTS ${CMAKE_SOURCE_DIR}/install/obs_gps_l1_system_test)
file(REMOVE ${CMAKE_SOURCE_DIR}/install/obs_gps_l1_system_test)
endif(EXISTS ${CMAKE_SOURCE_DIR}/install/obs_gps_l1_system_test)
if(EXISTS ${CMAKE_SOURCE_DIR}/install/obs_system_test)
file(REMOVE ${CMAKE_SOURCE_DIR}/install/obs_system_test)
endif(EXISTS ${CMAKE_SOURCE_DIR}/install/obs_system_test)
endif(ENABLE_SYSTEM_TESTING)

View File

@ -0,0 +1,939 @@
/*!
* \file obs_system_test.cc
* \brief This class implements a test for the validation of generated observables.
* \author Carles Fernandez-Prades, 2016. cfernandez(at)cttc.es
* Antonio Ramos, 2017. antonio.ramos(at)cttc.es
*
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2017 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#include <algorithm>
#include <chrono>
#include <boost/filesystem.hpp>
#include <cstdlib>
#include <exception>
#include <iostream>
#include <numeric>
#include <string>
#include <thread>
#include <unistd.h>
#include <armadillo>
#include <gflags/gflags.h>
#include <glog/logging.h>
#include <gtest/gtest.h>
#include <gpstk/RinexUtilities.hpp>
#include <gpstk/Rinex3ObsBase.hpp>
#include <gpstk/Rinex3ObsData.hpp>
#include <gpstk/Rinex3ObsHeader.hpp>
#include <gpstk/Rinex3ObsStream.hpp>
#include "gnuplot_i.h"
#include "test_flags.h"
#include "concurrent_map.h"
#include "concurrent_queue.h"
#include "control_thread.h"
#include "file_configuration.h"
// For GPS NAVIGATION (L1)
concurrent_queue<Gps_Acq_Assist> global_gps_acq_assist_queue;
concurrent_map<Gps_Acq_Assist> global_gps_acq_assist_map;
DEFINE_string(configuration_file, "./default_configuration.conf", "Path of configuration file");
DEFINE_string(filename_rinex_true, "./default_rinex.txt", "Path of RINEX true observations");
DEFINE_string(filename_rinex_obs, "default_string", "Path of RINEX true observations");
DEFINE_double(pr_error_mean_max, 25.0, "Maximum mean error in pseudorange");
DEFINE_double(pr_error_std_max, 5.0, "Maximum standard deviation in pseudorange");
DEFINE_double(cp_error_mean_max, 5.0, "Maximum mean error in carrier phase");
DEFINE_double(cp_error_std_max, 2.5, "Maximum standard deviation in carrier phase");
DEFINE_double(dp_error_mean_max, 75.0, "Maximum mean error in Doppler frequency");
DEFINE_double(dp_error_std_max, 25.0, "Maximum standard deviation in Doppler frequency");
DEFINE_bool(plot_obs_sys_test, false, "Plots results of ObsSystemTest with gnuplot");
class ObsSystemTest: public ::testing::Test
{
public:
int configure_receiver();
int run_receiver();
void check_results();
bool check_valid_rinex_obs(std::string filename, int rinex_ver); // return true if the file is a valid Rinex observation file.
void read_rinex_files(
std::vector<arma::mat>& pseudorange_ref,
std::vector<arma::mat>& carrierphase_ref,
std::vector<arma::mat>& doppler_ref,
std::vector<arma::mat>& pseudorange_meas,
std::vector<arma::mat>& carrierphase_meas,
std::vector<arma::mat>& doppler_meas,
arma::mat& sow_prn_ref,
int signal_type);
void time_alignment_diff(
std::vector<arma::mat>& ref,
std::vector<arma::mat>& meas,
std::vector<arma::vec>& diff);
void time_alignment_diff_cp(
std::vector<arma::mat>& ref,
std::vector<arma::mat>& meas,
std::vector<arma::vec>& diff);
void time_alignment_diff_pr(
std::vector<arma::mat>& ref,
std::vector<arma::mat>& meas,
std::vector<arma::vec>& diff,
arma::mat& sow_prn_ref);
void compute_pseudorange_error(std::vector<arma::vec>& diff,
double error_th_mean, double error_th_std,
std::string signal_name);
void compute_carrierphase_error(
std::vector<arma::vec>& diff,
double error_th_mean, double error_th_std,
std::string signal_name);
void compute_doppler_error(
std::vector<arma::vec>& diff,
double error_th_mean, double error_th_std,
std::string signal_name);
std::string filename_rinex_obs = FLAGS_filename_rinex_true;
std::string generated_rinex_obs = FLAGS_filename_rinex_obs;
std::string configuration_file_ = FLAGS_configuration_file;
std::shared_ptr<FileConfiguration> config;
bool gps_1C = false;
bool gps_L5 = false;
bool gal_1B = false;
bool gal_E5a = false;
bool internal_rinex_generation = false;
/****************/
const int num_prn_gps = 33;
const int num_prn_gal = 31;
double pseudorange_error_th_mean = FLAGS_pr_error_mean_max;
double pseudorange_error_th_std= FLAGS_pr_error_std_max;
double carrierphase_error_th_mean = FLAGS_cp_error_mean_max;
double carrierphase_error_th_std = FLAGS_cp_error_std_max;
double doppler_error_th_mean = FLAGS_dp_error_mean_max;
double doppler_error_th_std = FLAGS_dp_error_std_max;
};
bool ObsSystemTest::check_valid_rinex_obs(std::string filename, int rinex_ver)
{
bool res = false;
if(rinex_ver == 2)
{
res = gpstk::isRinexObsFile(filename);
}
if(rinex_ver == 3)
{
res = gpstk::isRinex3ObsFile(filename);
}
return res;
}
void ObsSystemTest::read_rinex_files(
std::vector<arma::mat>& pseudorange_ref,
std::vector<arma::mat>& carrierphase_ref,
std::vector<arma::mat>& doppler_ref,
std::vector<arma::mat>& pseudorange_meas,
std::vector<arma::mat>& carrierphase_meas,
std::vector<arma::mat>& doppler_meas,
arma::mat& sow_prn_ref,
int signal_type)
{
bool ref_exist = false;
bool meas_exist = false;
gpstk::SatID::SatelliteSystem sat_type = gpstk::SatID::systemUnknown;
int max_prn = 0;
std::string pr_string;
std::string cp_string;
std::string dp_string;
std::string signal_type_string;
sow_prn_ref.reset();
switch(signal_type)
{
case 0: //GPS L1
sat_type = gpstk::SatID::systemGPS;
max_prn = num_prn_gps;
pr_string = "C1C";
cp_string = "L1C";
dp_string = "D1C";
signal_type_string = "GPS L1 C/A";
break;
case 1: //Galileo E1B
sat_type = gpstk::SatID::systemGalileo;
max_prn = num_prn_gal;
pr_string = "C1B";
cp_string = "L1B";
dp_string = "D1B";
signal_type_string = "Galileo E1B";
break;
case 2: //GPS L5
sat_type = gpstk::SatID::systemGPS;
max_prn = num_prn_gps;
pr_string = "C5X";
cp_string = "L5X";
dp_string = "D5X";
signal_type_string = "GPS L5";
break;
case 3: //Galileo E5a
sat_type = gpstk::SatID::systemGalileo;
max_prn = num_prn_gal;
pr_string = "C5X";
cp_string = "L5X";
dp_string = "D5X";
signal_type_string = "Galileo E5a";
break;
}
// Open and read reference RINEX observables file
std::cout << "Read: RINEX " << signal_type_string << " True" << std::endl;
try
{
gpstk::Rinex3ObsStream r_ref(filename_rinex_obs);
r_ref.exceptions(std::ios::failbit);
gpstk::Rinex3ObsData r_ref_data;
gpstk::Rinex3ObsHeader r_ref_header;
gpstk::RinexDatum dataobj;
r_ref >> r_ref_header;
while (r_ref >> r_ref_data)
{
for (int myprn = 1; myprn < max_prn; myprn++)
{
gpstk::SatID prn( myprn, sat_type);
gpstk::CommonTime time = r_ref_data.time;
double sow(static_cast<gpstk::GPSWeekSecond>(time).sow);
gpstk::Rinex3ObsData::DataMap::iterator pointer = r_ref_data.obs.find(prn);
if( pointer == r_ref_data.obs.end() )
{
// PRN not present; do nothing
}
else
{
dataobj = r_ref_data.getObs(prn, pr_string, r_ref_header);
double P1 = dataobj.data;
pseudorange_ref.at(myprn).insert_rows(pseudorange_ref.at(myprn).n_rows, arma::rowvec({sow, P1}));
dataobj = r_ref_data.getObs(prn, cp_string, r_ref_header);
double L1 = dataobj.data;
carrierphase_ref.at(myprn).insert_rows(carrierphase_ref.at(myprn).n_rows, arma::rowvec({sow, L1}));
dataobj = r_ref_data.getObs(prn, dp_string, r_ref_header);
double D1 = dataobj.data;
doppler_ref.at(myprn).insert_rows(doppler_ref.at(myprn).n_rows, arma::rowvec({sow, D1}));
ref_exist = true;
} // End of 'if( pointer == roe.obs.end() )'
} // end for
} // end while
} // End of 'try' block
catch(const gpstk::FFStreamError& e)
{
std::cout << e;
exit(1);
}
catch(const gpstk::Exception& e)
{
std::cout << e;
exit(1);
}
catch (...)
{
std::cout << "unknown error. I don't feel so well..." << std::endl;
exit(1);
}
// Open and read measured RINEX observables file
std::cout << "Read: RINEX "<< signal_type_string << " measures" << std::endl;
try
{
std::string arg2_gen;
if(internal_rinex_generation)
{
arg2_gen = std::string("./") + generated_rinex_obs;
}
else
{
arg2_gen = generated_rinex_obs;
}
gpstk::Rinex3ObsStream r_meas(arg2_gen);
r_meas.exceptions(std::ios::failbit);
gpstk::Rinex3ObsData r_meas_data;
gpstk::Rinex3ObsHeader r_meas_header;
gpstk::RinexDatum dataobj;
r_meas >> r_meas_header;
while (r_meas >> r_meas_data)
{
double pr_min = 0.0;
double sow_insert = 0.0;
double prn_min = 0.0;
bool set_pr_min = true;
for (int myprn = 1; myprn < max_prn; myprn++)
{
gpstk::SatID prn( myprn, sat_type);
gpstk::CommonTime time = r_meas_data.time;
double sow(static_cast<gpstk::GPSWeekSecond>(time).sow);
gpstk::Rinex3ObsData::DataMap::iterator pointer = r_meas_data.obs.find(prn);
if( pointer == r_meas_data.obs.end() )
{
// PRN not present; do nothing
}
else
{
dataobj = r_meas_data.getObs(prn, pr_string, r_meas_header);
double P1 = dataobj.data;
pseudorange_meas.at(myprn).insert_rows(pseudorange_meas.at(myprn).n_rows, arma::rowvec({sow, P1}));
if(set_pr_min || (P1 < pr_min))
{
set_pr_min = false;
pr_min = P1;
sow_insert = sow;
prn_min = static_cast<double>(myprn);
}
dataobj = r_meas_data.getObs(prn, cp_string, r_meas_header);
double L1 = dataobj.data;
carrierphase_meas.at(myprn).insert_rows(carrierphase_meas.at(myprn).n_rows, arma::rowvec({sow, L1}));
dataobj = r_meas_data.getObs(prn, dp_string, r_meas_header);
double D1 = dataobj.data;
doppler_meas.at(myprn).insert_rows(doppler_meas.at(myprn).n_rows, arma::rowvec({sow, D1}));
meas_exist = true;
} // End of 'if( pointer == roe.obs.end() )'
} // end for
sow_prn_ref.insert_rows(sow_prn_ref.n_rows, arma::rowvec({sow_insert, pr_min, prn_min}));
} // end while
} // End of 'try' block
catch(const gpstk::FFStreamError& e)
{
std::cout << e;
exit(1);
}
catch(const gpstk::Exception& e)
{
std::cout << e;
exit(1);
}
catch (...)
{
std::cout << "unknown error. I don't feel so well..." << std::endl;
exit(1);
}
EXPECT_TRUE(ref_exist) << "RINEX reference file does not contain " << signal_type_string << " information";
EXPECT_TRUE(meas_exist) << "RINEX generated file does not contain " << signal_type_string << " information";
}
void ObsSystemTest::time_alignment_diff(
std::vector<arma::mat>& ref,
std::vector<arma::mat>& meas,
std::vector<arma::vec>& diff)
{
std::vector<arma::mat>::iterator iter_ref;
std::vector<arma::mat>::iterator iter_meas;
std::vector<arma::vec>::iterator iter_diff;
arma::mat mat_aux;
iter_ref = ref.begin();
iter_diff = diff.begin();
for(iter_meas = meas.begin(); iter_meas != meas.end(); iter_meas++)
{
if( !iter_meas->is_empty() && !iter_ref->is_empty() )
{
arma::uvec index_ = arma::find(iter_meas->col(0) > iter_ref->at(0, 0));
arma::uword index_min = arma::min(index_);
index_ = arma::find(iter_meas->col(0) < iter_ref->at(iter_ref->n_rows - 1, 0));
arma::uword index_max = arma::max(index_);
mat_aux = iter_meas->rows(index_min, index_max);
arma::vec ref_aligned;
arma::interp1(iter_ref->col(0), iter_ref->col(1), mat_aux.col(0), ref_aligned);
*iter_diff = ref_aligned - mat_aux.col(1);
}
iter_ref++;
iter_diff++;
}
}
void ObsSystemTest::time_alignment_diff_cp(
std::vector<arma::mat>& ref,
std::vector<arma::mat>& meas,
std::vector<arma::vec>& diff)
{
std::vector<arma::mat>::iterator iter_ref;
std::vector<arma::mat>::iterator iter_meas;
std::vector<arma::vec>::iterator iter_diff;
arma::mat mat_aux;
iter_ref = ref.begin();
iter_diff = diff.begin();
for(iter_meas = meas.begin(); iter_meas != meas.end(); iter_meas++)
{
if( !iter_meas->is_empty() && !iter_ref->is_empty() )
{
arma::uvec index_ = arma::find(iter_meas->col(0) > iter_ref->at(0, 0));
arma::uword index_min = arma::min(index_);
index_ = arma::find(iter_meas->col(0) < iter_ref->at(iter_ref->n_rows - 1, 0));
arma::uword index_max = arma::max(index_);
mat_aux = iter_meas->rows(index_min, index_max);
mat_aux.col(1) -= arma::min(mat_aux.col(1));
arma::vec ref_aligned;
arma::interp1(iter_ref->col(0), iter_ref->col(1), mat_aux.col(0), ref_aligned);
ref_aligned -= arma::min(ref_aligned);
*iter_diff = ref_aligned - mat_aux.col(1);
}
iter_ref++;
iter_diff++;
}
}
void ObsSystemTest::time_alignment_diff_pr(
std::vector<arma::mat>& ref,
std::vector<arma::mat>& meas,
std::vector<arma::vec>& diff,
arma::mat& sow_prn_ref)
{
std::vector<arma::mat>::iterator iter_ref;
std::vector<arma::mat>::iterator iter_meas;
std::vector<arma::vec>::iterator iter_diff;
arma::mat mat_aux;
arma::vec subtraction_meas;
arma::vec subtraction_ref;
arma::mat subtraction_pr_ref = sow_prn_ref;
arma::vec::iterator iter_vec0 = subtraction_pr_ref.begin_col(0);
arma::vec::iterator iter_vec1 = subtraction_pr_ref.begin_col(1);
arma::vec::iterator iter_vec2 = subtraction_pr_ref.begin_col(2);
for(iter_vec1 = subtraction_pr_ref.begin_col(1); iter_vec1 != subtraction_pr_ref.end_col(1); iter_vec1++)
{
arma::vec aux_pr; //vector with only 1 element
arma::vec aux_sow = {*iter_vec0}; //vector with only 1 element
arma::interp1(ref.at(static_cast<int>(*iter_vec2)).col(0),
ref.at(static_cast<int>(*iter_vec2)).col(1),
aux_sow,
aux_pr);
*iter_vec1 = aux_pr(0);
iter_vec0++;
iter_vec2++;
}
iter_ref = ref.begin();
iter_diff = diff.begin();
for(iter_meas = meas.begin(); iter_meas != meas.end(); iter_meas++)
{
if( !iter_meas->is_empty() && !iter_ref->is_empty() )
{
arma::uvec index_ = arma::find(iter_meas->col(0) > iter_ref->at(0, 0));
arma::uword index_min = arma::min(index_);
index_ = arma::find(iter_meas->col(0) < iter_ref->at(iter_ref->n_rows - 1, 0));
arma::uword index_max = arma::max(index_);
mat_aux = iter_meas->rows(index_min, index_max);
arma::interp1(sow_prn_ref.col(0), sow_prn_ref.col(1), mat_aux.col(0), subtraction_meas);
mat_aux.col(1) -= subtraction_meas;
arma::vec ref_aligned;
arma::interp1(iter_ref->col(0), iter_ref->col(1), mat_aux.col(0), ref_aligned);
arma::interp1(subtraction_pr_ref.col(0), subtraction_pr_ref.col(1), mat_aux.col(0), subtraction_ref);
ref_aligned -= subtraction_ref;
*iter_diff = ref_aligned - mat_aux.col(1);
}
iter_ref++;
iter_diff++;
}
}
int ObsSystemTest::configure_receiver()
{
config = std::make_shared<FileConfiguration>(configuration_file_);
if( config->property("Channels_1C.count", 0) > 0 )
{gps_1C = true;}
if( config->property("Channels_1B.count", 0) > 0 )
{gal_1B = true;}
if( config->property("Channels_5X.count", 0) > 0 )
{gal_E5a = true;}
if( config->property("Channels_7X.count", 0) > 0 ) //NOT DEFINITIVE!!!!!
{gps_L5 = true;}
return 0;
}
int ObsSystemTest::run_receiver()
{
std::shared_ptr<ControlThread> control_thread;
control_thread = std::make_shared<ControlThread>(config);
// start receiver
try
{
control_thread->run();
}
catch(const boost::exception & e)
{
std::cout << "Boost exception: " << boost::diagnostic_information(e);
}
catch(const std::exception & ex)
{
std::cout << "STD exception: " << ex.what();
}
// Get the name of the RINEX obs file generated by the receiver
std::this_thread::sleep_for(std::chrono::milliseconds(2000));
FILE *fp;
std::string argum2 = std::string("/bin/ls *O | grep GSDR | tail -1");
char buffer[1035];
fp = popen(&argum2[0], "r");
if (fp == NULL)
{
std::cout << "Failed to run command: " << argum2 << std::endl;
return -1;
}
while (fgets(buffer, sizeof(buffer), fp) != NULL)
{
std::string aux = std::string(buffer);
generated_rinex_obs = aux.erase(aux.length() - 1, 1);
internal_rinex_generation = true;
}
pclose(fp);
return 0;
}
void ObsSystemTest::compute_pseudorange_error(
std::vector<arma::vec>& diff,
double error_th_mean, double error_th_std,
std::string signal_name)
{
int prn_id = 0;
std::vector<arma::vec>::iterator iter_diff;
std::vector<double> means;
std::vector<double> stddevs;
std::vector<double> prns;
for(iter_diff = diff.begin(); iter_diff != diff.end(); iter_diff++)
{
if(!iter_diff->is_empty())
{
double d_mean = std::sqrt(arma::mean(arma::square(*iter_diff)));
means.push_back(d_mean);
double d_stddev = arma::stddev(*iter_diff);
stddevs.push_back(d_stddev);
prns.push_back(static_cast<double>(prn_id));
std::cout << "-- RMS pseudorange difference for sat " << prn_id << ": " << d_mean;
std::cout << " +/- " << d_stddev;
std::cout << " [m]" << std::endl;
EXPECT_LT(d_mean, error_th_mean);
EXPECT_LT(d_stddev, error_th_std);
}
prn_id++;
}
if(FLAGS_plot_obs_sys_test == true)
{
const std::string gnuplot_executable(FLAGS_gnuplot_executable);
if(gnuplot_executable.empty())
{
std::cout << "WARNING: Although the flag plot_obs_sys_test has been set to TRUE," << std::endl;
std::cout << "gnuplot has not been found in your system." << std::endl;
std::cout << "Test results will not be plotted." << std::endl;
}
else
{
try
{
boost::filesystem::path p(gnuplot_executable);
boost::filesystem::path dir = p.parent_path();
std::string gnuplot_path = dir.native();
Gnuplot::set_GNUPlotPath(gnuplot_path);
Gnuplot g1("linespoints");
g1.set_title(signal_name + " Pseudorange error");
g1.set_grid();
g1.set_xlabel("PRN");
g1.set_ylabel("Pseudorange error [m]");
g1.plot_xy(prns, means, "RMS error");
g1.plot_xy(prns, stddevs, "Standard deviation");
//g1.savetops("FFT_execution_times_extended");
//g1.savetopdf("FFT_execution_times_extended", 18);
g1.showonscreen(); // window output
}
catch (const GnuplotException & ge)
{
std::cout << ge.what() << std::endl;
}
}
}
}
void ObsSystemTest::compute_carrierphase_error(
std::vector<arma::vec>& diff,
double error_th_mean, double error_th_std,
std::string signal_name)
{
int prn_id = 0;
std::vector<double> means;
std::vector<double> stddevs;
std::vector<double> prns;
std::vector<arma::vec>::iterator iter_diff;
for(iter_diff = diff.begin(); iter_diff != diff.end(); iter_diff++)
{
if(!iter_diff->is_empty())
{
double d_mean = std::sqrt(arma::mean(arma::square(*iter_diff)));
means.push_back(d_mean);
double d_stddev = arma::stddev(*iter_diff);
stddevs.push_back(d_stddev);
prns.push_back(static_cast<double>(prn_id));
std::cout << "-- RMS carrier phase difference for sat " << prn_id << ": " << d_mean;
std::cout << " +/- " << d_stddev;
std::cout << " whole cycles" << std::endl;
EXPECT_LT(d_mean, error_th_mean);
EXPECT_LT(d_stddev, error_th_std);
}
prn_id++;
}
if(FLAGS_plot_obs_sys_test == true)
{
const std::string gnuplot_executable(FLAGS_gnuplot_executable);
if(gnuplot_executable.empty())
{
std::cout << "WARNING: Although the flag plot_obs_sys_test has been set to TRUE," << std::endl;
std::cout << "gnuplot has not been found in your system." << std::endl;
std::cout << "Test results will not be plotted." << std::endl;
}
else
{
try
{
boost::filesystem::path p(gnuplot_executable);
boost::filesystem::path dir = p.parent_path();
std::string gnuplot_path = dir.native();
Gnuplot::set_GNUPlotPath(gnuplot_path);
Gnuplot g1("linespoints");
g1.set_title(signal_name + " Carrier phase error");
g1.set_grid();
g1.set_xlabel("PRN");
g1.set_ylabel("Carrier phase error [whole cycles]");
g1.plot_xy(prns, means, "RMS error");
g1.plot_xy(prns, stddevs, "Standard deviation");
//g1.savetops("FFT_execution_times_extended");
//g1.savetopdf("FFT_execution_times_extended", 18);
g1.showonscreen(); // window output
}
catch (const GnuplotException & ge)
{
std::cout << ge.what() << std::endl;
}
}
}
}
void ObsSystemTest::compute_doppler_error(
std::vector<arma::vec>& diff,
double error_th_mean, double error_th_std,
std::string signal_name)
{
int prn_id = 0;
std::vector<double> means;
std::vector<double> stddevs;
std::vector<double> prns;
std::vector<arma::vec>::iterator iter_diff;
for(iter_diff = diff.begin(); iter_diff != diff.end(); iter_diff++)
{
if(!iter_diff->is_empty())
{
double d_mean = std::sqrt(arma::mean(arma::square(*iter_diff)));
means.push_back(d_mean);
double d_stddev = arma::stddev(*iter_diff);
stddevs.push_back(d_stddev);
prns.push_back(static_cast<double>(prn_id));
std::cout << "-- RMS Doppler difference for sat " << prn_id << ": " << d_mean;
std::cout << " +/- " << d_stddev;
std::cout << " [Hz]" << std::endl;
EXPECT_LT(d_mean, error_th_mean);
EXPECT_LT(d_stddev, error_th_std);
}
prn_id++;
}
if(FLAGS_plot_obs_sys_test == true)
{
const std::string gnuplot_executable(FLAGS_gnuplot_executable);
if(gnuplot_executable.empty())
{
std::cout << "WARNING: Although the flag plot_obs_sys_test has been set to TRUE," << std::endl;
std::cout << "gnuplot has not been found in your system." << std::endl;
std::cout << "Test results will not be plotted." << std::endl;
}
else
{
try
{
boost::filesystem::path p(gnuplot_executable);
boost::filesystem::path dir = p.parent_path();
std::string gnuplot_path = dir.native();
Gnuplot::set_GNUPlotPath(gnuplot_path);
Gnuplot g1("linespoints");
g1.set_title(signal_name + " Doppler error");
g1.set_grid();
g1.set_xlabel("PRN");
g1.set_ylabel("Doppler error [Hz]");
g1.plot_xy(prns, means, "RMS error");
g1.plot_xy(prns, stddevs, "Standard deviation");
//g1.savetops("FFT_execution_times_extended");
//g1.savetopdf("FFT_execution_times_extended", 18);
g1.showonscreen(); // window output
}
catch (const GnuplotException & ge)
{
std::cout << ge.what() << std::endl;
}
}
}
}
void ObsSystemTest::check_results()
{
arma::mat sow_prn_ref;
if(gps_1C)
{
std::vector<arma::mat> pseudorange_ref(num_prn_gps);
std::vector<arma::mat> carrierphase_ref(num_prn_gps);
std::vector<arma::mat> doppler_ref(num_prn_gps);
std::vector<arma::mat> pseudorange_meas(num_prn_gps);
std::vector<arma::mat> carrierphase_meas(num_prn_gps);
std::vector<arma::mat> doppler_meas(num_prn_gps);
read_rinex_files(pseudorange_ref, carrierphase_ref, doppler_ref, pseudorange_meas, carrierphase_meas, doppler_meas, sow_prn_ref, 0);
// Time alignment and difference computation
std::vector<arma::vec> pr_diff(num_prn_gps);
std::vector<arma::vec> cp_diff(num_prn_gps);
std::vector<arma::vec> dp_diff(num_prn_gps);
time_alignment_diff_pr(pseudorange_ref, pseudorange_meas, pr_diff, sow_prn_ref);
time_alignment_diff_cp(carrierphase_ref, carrierphase_meas, cp_diff);
time_alignment_diff(doppler_ref, doppler_meas, dp_diff);
// Results
std::cout << std::endl;
std::cout << std::endl;
std::cout << "GPS L1 C/A obs. results" << std::endl;
// Compute pseudorange error
compute_pseudorange_error(pr_diff, pseudorange_error_th_mean, pseudorange_error_th_std, "GPS L1 C/A");
// Compute carrier phase error
compute_carrierphase_error(cp_diff, carrierphase_error_th_mean, carrierphase_error_th_std, "GPS L1 C/A");
// Compute Doppler error
compute_doppler_error(dp_diff, doppler_error_th_mean, doppler_error_th_std, "GPS L1 C/A");
}
if(gps_L5)
{
std::vector<arma::mat> pseudorange_ref(num_prn_gps);
std::vector<arma::mat> carrierphase_ref(num_prn_gps);
std::vector<arma::mat> doppler_ref(num_prn_gps);
std::vector<arma::mat> pseudorange_meas(num_prn_gps);
std::vector<arma::mat> carrierphase_meas(num_prn_gps);
std::vector<arma::mat> doppler_meas(num_prn_gps);
read_rinex_files(pseudorange_ref, carrierphase_ref, doppler_ref, pseudorange_meas, carrierphase_meas, doppler_meas, sow_prn_ref, 2);
// Time alignment and difference computation
std::vector<arma::vec> pr_diff(num_prn_gps);
std::vector<arma::vec> cp_diff(num_prn_gps);
std::vector<arma::vec> dp_diff(num_prn_gps);
time_alignment_diff_pr(pseudorange_ref, pseudorange_meas, pr_diff, sow_prn_ref);
time_alignment_diff_cp(carrierphase_ref, carrierphase_meas, cp_diff);
time_alignment_diff(doppler_ref, doppler_meas, dp_diff);
// Results
std::cout << std::endl;
std::cout << std::endl;
std::cout << "GPS L5 obs. results" << std::endl;
// Compute pseudorange error
compute_pseudorange_error(pr_diff, pseudorange_error_th_mean, pseudorange_error_th_std, "GPS L5");
// Compute carrier phase error
compute_carrierphase_error(cp_diff, carrierphase_error_th_mean, carrierphase_error_th_std, "GPS L5");
// Compute Doppler error
compute_doppler_error(dp_diff, doppler_error_th_mean, doppler_error_th_std, "GPS L5");
}
if(gal_1B)
{
std::vector<arma::mat> pseudorange_ref(num_prn_gal);
std::vector<arma::mat> carrierphase_ref(num_prn_gal);
std::vector<arma::mat> doppler_ref(num_prn_gal);
std::vector<arma::mat> pseudorange_meas(num_prn_gal);
std::vector<arma::mat> carrierphase_meas(num_prn_gal);
std::vector<arma::mat> doppler_meas(num_prn_gal);
read_rinex_files(pseudorange_ref, carrierphase_ref, doppler_ref, pseudorange_meas, carrierphase_meas, doppler_meas, sow_prn_ref, 1);
// Time alignment and difference computation
std::vector<arma::vec> pr_diff(num_prn_gal);
std::vector<arma::vec> cp_diff(num_prn_gal);
std::vector<arma::vec> dp_diff(num_prn_gal);
time_alignment_diff_pr(pseudorange_ref, pseudorange_meas, pr_diff, sow_prn_ref);
time_alignment_diff_cp(carrierphase_ref, carrierphase_meas, cp_diff);
time_alignment_diff(doppler_ref, doppler_meas, dp_diff);
// Results
std::cout << std::endl;
std::cout << std::endl;
std::cout << "Galileo E1B obs. results" << std::endl;
// Compute pseudorange error
compute_pseudorange_error(pr_diff, pseudorange_error_th_mean, pseudorange_error_th_std, "Galileo E1B");
// Compute carrier phase error
compute_carrierphase_error(cp_diff, carrierphase_error_th_mean, carrierphase_error_th_std, "Galileo E1B");
// Compute Doppler error
compute_doppler_error(dp_diff, doppler_error_th_mean, doppler_error_th_std, "Galileo E1B");
}
if(gal_E5a)
{
std::vector<arma::mat> pseudorange_ref(num_prn_gal);
std::vector<arma::mat> carrierphase_ref(num_prn_gal);
std::vector<arma::mat> doppler_ref(num_prn_gal);
std::vector<arma::mat> pseudorange_meas(num_prn_gal);
std::vector<arma::mat> carrierphase_meas(num_prn_gal);
std::vector<arma::mat> doppler_meas(num_prn_gal);
read_rinex_files(pseudorange_ref, carrierphase_ref, doppler_ref, pseudorange_meas, carrierphase_meas, doppler_meas, sow_prn_ref, 3);
// Time alignment and difference computation
std::vector<arma::vec> pr_diff(num_prn_gal);
std::vector<arma::vec> cp_diff(num_prn_gal);
std::vector<arma::vec> dp_diff(num_prn_gal);
time_alignment_diff_pr(pseudorange_ref, pseudorange_meas, pr_diff, sow_prn_ref);
time_alignment_diff_cp(carrierphase_ref, carrierphase_meas, cp_diff);
time_alignment_diff(doppler_ref, doppler_meas, dp_diff);
// Results
std::cout << std::endl;
std::cout << std::endl;
std::cout << "Galileo E5a obs. results" << std::endl;
// Compute pseudorange error
compute_pseudorange_error(pr_diff, pseudorange_error_th_mean, pseudorange_error_th_std, "Galileo E5a");
// Compute carrier phase error
compute_carrierphase_error(cp_diff, carrierphase_error_th_mean, carrierphase_error_th_std, "Galileo E5a");
// Compute Doppler error
compute_doppler_error(dp_diff, doppler_error_th_mean, doppler_error_th_std, "Galileo E5a");
}
}
TEST_F(ObsSystemTest, Observables_system_test)
{
std::cout << "Validating input RINEX obs (TRUE) file: " << filename_rinex_obs << " ..." << std::endl;
bool is_rinex_obs_valid = check_valid_rinex_obs(filename_rinex_obs, 3);
ASSERT_EQ(true, is_rinex_obs_valid) << "The RINEX observation file " << filename_rinex_obs << " is not well formed. Only RINEX v. 3.00 files are allowed";
std::cout << "The file is valid." << std::endl;
// Configure receiver
configure_receiver();
if(generated_rinex_obs.compare("default_string") == 0)
{
// Run the receiver
ASSERT_EQ( run_receiver(), 0) << "Problem executing the software-defined signal generator";
}
std::cout << "Validating RINEX obs file obtained by GNSS-SDR: " << generated_rinex_obs << " ..." << std::endl;
bool is_gen_rinex_obs_valid = false;
if(internal_rinex_generation)
{
is_gen_rinex_obs_valid = check_valid_rinex_obs( "./" + generated_rinex_obs, config->property("PVT.rinex_version", 3));
}
else
{
is_gen_rinex_obs_valid = check_valid_rinex_obs(generated_rinex_obs, config->property("PVT.rinex_version", 3));
}
ASSERT_EQ(true, is_gen_rinex_obs_valid) << "The RINEX observation file " << generated_rinex_obs << ", generated by GNSS-SDR, is not well formed.";
std::cout << "The file is valid." << std::endl;
// Check results
check_results();
}
int main(int argc, char **argv)
{
std::cout << "Running GNSS-SDR in Space Observables validation test..." << std::endl;
int res = 0;
try
{
testing::InitGoogleTest(&argc, argv);
}
catch(...) {} // catch the "testing::internal::<unnamed>::ClassUniqueToAlwaysTrue" from gtest
google::ParseCommandLineFlags(&argc, &argv, true);
google::InitGoogleLogging(argv[0]);
// Run the Tests
try
{
res = RUN_ALL_TESTS();
}
catch(...)
{
LOG(WARNING) << "Unexpected catch";
}
google::ShutDownCommandLineFlags();
return res;
}

View File

@ -60,6 +60,13 @@ concurrent_map<Gps_Acq_Assist> global_gps_acq_assist_map;
class StaticPositionSystemTest: public ::testing::Test
{
public:
int configure_generator();
int generate_signal();
int configure_receiver();
int run_receiver();
void check_results();
private:
std::string generator_binary;
std::string p1;
std::string p2;
@ -72,12 +79,6 @@ public:
std::string filename_rinex_obs = FLAGS_filename_rinex_obs;
std::string filename_raw_data = FLAGS_filename_raw_data;
int configure_generator();
int generate_signal();
int configure_receiver();
int run_receiver();
void check_results();
void print_results(const std::vector<double> & east,
const std::vector<double> & north,
const std::vector<double> & up);
@ -88,13 +89,12 @@ public:
void geodetic2Enu(const double latitude, const double longitude, const double altitude,
double* east, double* north, double* up);
void geodetic2Ecef(const double latitude, const double longitude, const double altitude,
double* x, double* y, double* z);
std::shared_ptr<InMemoryConfiguration> config;
std::shared_ptr<FileConfiguration> config_f;
std::string generated_kml_file;
private:
void geodetic2Ecef(const double latitude, const double longitude, const double altitude,
double* x, double* y, double* z);
};
@ -521,29 +521,41 @@ void StaticPositionSystemTest::check_results()
double sum__u = std::accumulate(pos_u.begin(), pos_u.end(), 0.0);
double mean__u = sum__u / pos_u.size();
std::stringstream stm;
std::ofstream position_test_file;
if(FLAGS_config_file_ptest.empty())
{
std::cout << "---- ACCURACY ----" << std::endl;
std::cout << "2DRMS = " << 2 * sqrt(sigma_E_2_accuracy + sigma_N_2_accuracy) << " [m]" << std::endl;
std::cout << "DRMS = " << sqrt(sigma_E_2_accuracy + sigma_N_2_accuracy) << " [m]" << std::endl;
std::cout << "CEP = " << 0.62 * compute_stdev_accuracy(pos_n, 0.0) + 0.56 * compute_stdev_accuracy(pos_e, 0.0) << " [m]" << std::endl;
std::cout << "99% SAS = " << 1.122 * (sigma_E_2_accuracy + sigma_N_2_accuracy + sigma_U_2_accuracy) << " [m]" << std::endl;
std::cout << "90% SAS = " << 0.833 * (sigma_E_2_accuracy + sigma_N_2_accuracy + sigma_U_2_accuracy) << " [m]" << std::endl;
std::cout << "MRSE = " << sqrt(sigma_E_2_accuracy + sigma_N_2_accuracy + sigma_U_2_accuracy) << " [m]" << std::endl;
std::cout << "SEP = " << 0.51 * (sigma_E_2_accuracy + sigma_N_2_accuracy + sigma_U_2_accuracy) << " [m]" << std::endl;
std::cout << "Bias 2D = " << sqrt(std::pow(mean__e, 2.0) + std::pow(mean__n, 2.0)) << " [m]" << std::endl;
std::cout << "Bias 3D = " << sqrt(std::pow(mean__e, 2.0) + std::pow(mean__n, 2.0) + std::pow(mean__u, 2.0)) << " [m]" << std::endl;
std::cout << std::endl;
stm << "---- ACCURACY ----" << std::endl;
stm << "2DRMS = " << 2 * sqrt(sigma_E_2_accuracy + sigma_N_2_accuracy) << " [m]" << std::endl;
stm << "DRMS = " << sqrt(sigma_E_2_accuracy + sigma_N_2_accuracy) << " [m]" << std::endl;
stm << "CEP = " << 0.62 * compute_stdev_accuracy(pos_n, 0.0) + 0.56 * compute_stdev_accuracy(pos_e, 0.0) << " [m]" << std::endl;
stm << "99% SAS = " << 1.122 * (sigma_E_2_accuracy + sigma_N_2_accuracy + sigma_U_2_accuracy) << " [m]" << std::endl;
stm << "90% SAS = " << 0.833 * (sigma_E_2_accuracy + sigma_N_2_accuracy + sigma_U_2_accuracy) << " [m]" << std::endl;
stm << "MRSE = " << sqrt(sigma_E_2_accuracy + sigma_N_2_accuracy + sigma_U_2_accuracy) << " [m]" << std::endl;
stm << "SEP = " << 0.51 * (sigma_E_2_accuracy + sigma_N_2_accuracy + sigma_U_2_accuracy) << " [m]" << std::endl;
stm << "Bias 2D = " << sqrt(std::pow(mean__e, 2.0) + std::pow(mean__n, 2.0)) << " [m]" << std::endl;
stm << "Bias 3D = " << sqrt(std::pow(mean__e, 2.0) + std::pow(mean__n, 2.0) + std::pow(mean__u, 2.0)) << " [m]" << std::endl;
stm << std::endl;
}
std::cout << "---- PRECISION ----" << std::endl;
std::cout << "2DRMS = " << 2 * sqrt(sigma_E_2_precision + sigma_N_2_precision) << " [m]" << std::endl;
std::cout << "DRMS = " << sqrt(sigma_E_2_precision + sigma_N_2_precision) << " [m]" << std::endl;
std::cout << "CEP = " << 0.62 * compute_stdev_precision(pos_n) + 0.56 * compute_stdev_precision(pos_e) << " [m]" << std::endl;
std::cout << "99% SAS = " << 1.122 * (sigma_E_2_precision + sigma_N_2_precision + sigma_U_2_precision) << " [m]" << std::endl;
std::cout << "90% SAS = " << 0.833 * (sigma_E_2_precision + sigma_N_2_precision + sigma_U_2_precision) << " [m]" << std::endl;
std::cout << "MRSE = " << sqrt(sigma_E_2_precision + sigma_N_2_precision + sigma_U_2_precision) << " [m]" << std::endl;
std::cout << "SEP = " << 0.51 * (sigma_E_2_precision + sigma_N_2_precision + sigma_U_2_precision) << " [m]" << std::endl;
stm << "---- PRECISION ----" << std::endl;
stm << "2DRMS = " << 2 * sqrt(sigma_E_2_precision + sigma_N_2_precision) << " [m]" << std::endl;
stm << "DRMS = " << sqrt(sigma_E_2_precision + sigma_N_2_precision) << " [m]" << std::endl;
stm << "CEP = " << 0.62 * compute_stdev_precision(pos_n) + 0.56 * compute_stdev_precision(pos_e) << " [m]" << std::endl;
stm << "99% SAS = " << 1.122 * (sigma_E_2_precision + sigma_N_2_precision + sigma_U_2_precision) << " [m]" << std::endl;
stm << "90% SAS = " << 0.833 * (sigma_E_2_precision + sigma_N_2_precision + sigma_U_2_precision) << " [m]" << std::endl;
stm << "MRSE = " << sqrt(sigma_E_2_precision + sigma_N_2_precision + sigma_U_2_precision) << " [m]" << std::endl;
stm << "SEP = " << 0.51 * (sigma_E_2_precision + sigma_N_2_precision + sigma_U_2_precision) << " [m]" << std::endl;
std::cout << stm.rdbuf();
std::string output_filename = "position_test_output_" + StaticPositionSystemTest::generated_kml_file.erase(StaticPositionSystemTest::generated_kml_file.length() - 3,3) + "txt";
position_test_file.open(output_filename.c_str());
if(position_test_file.is_open())
{
position_test_file << stm.str();
position_test_file.close();
}
// Sanity Check
double precision_SEP = 0.51 * (sigma_E_2_precision + sigma_N_2_precision + sigma_U_2_precision);

View File

@ -359,96 +359,58 @@ void TfttGpsL1CATest::print_TTFF_report(const std::vector<double> & ttff_v, std:
std::string default_str = "default";
source = config_->property("SignalSource.implementation", default_str);
if (ttff_report_file.is_open())
{
ttff_report_file << "---------------------------" << std::endl;
ttff_report_file << " Time-To-First-Fix Report" << std::endl;
ttff_report_file << "---------------------------" << std::endl;
ttff_report_file << "Initial receiver status: ";
if (read_ephemeris)
{
ttff_report_file << "Hot start." << std::endl;
}
else
{
ttff_report_file << "Cold start." << std::endl;
}
ttff_report_file << "A-GNSS: ";
if (agnss && read_ephemeris)
{
ttff_report_file << "Enabled." << std::endl;
}
else
{
ttff_report_file << "Disabled." << std::endl;
}
ttff_report_file << "Valid measurements (" << ttff.size() << "/" << FLAGS_num_measurements << "): ";
for(double ttff_ : ttff) ttff_report_file << ttff_ << " ";
ttff_report_file << std::endl;
ttff_report_file << "TTFF mean: " << mean << " [s]" << std::endl;
if (ttff.size() > 0)
{
ttff_report_file << "TTFF max: " << *max_ttff << " [s]" << std::endl;
ttff_report_file << "TTFF min: " << *min_ttff << " [s]" << std::endl;
}
ttff_report_file << "TTFF stdev: " << stdev << " [s]" << std::endl;
ttff_report_file << "Operating System: " << std::string(HOST_SYSTEM) << std::endl;
ttff_report_file << "Navigation mode: " << "3D" << std::endl;
std::stringstream stm;
if(source.compare("UHD_Signal_Source"))
{
ttff_report_file << "Source: File" << std::endl;
}
else
{
ttff_report_file << "Source: Live" << std::endl;
}
ttff_report_file << "---------------------------" << std::endl;
}
ttff_report_file.close();
std::cout << "---------------------------" << std::endl;
std::cout << " Time-To-First-Fix Report" << std::endl;
std::cout << "---------------------------" << std::endl;
std::cout << "Initial receiver status: ";
stm << "---------------------------" << std::endl;
stm << " Time-To-First-Fix Report" << std::endl;
stm << "---------------------------" << std::endl;
stm << "Initial receiver status: ";
if (read_ephemeris)
{
std::cout << "Hot start." << std::endl;
stm << "Hot start." << std::endl;
}
else
{
std::cout << "Cold start." << std::endl;
stm << "Cold start." << std::endl;
}
std::cout << "A-GNSS: ";
stm << "A-GNSS: ";
if (agnss && read_ephemeris)
{
std::cout << "Enabled." << std::endl;
stm << "Enabled." << std::endl;
}
else
{
std::cout << "Disabled." << std::endl;
stm << "Disabled." << std::endl;
}
std::cout << "Valid measurements (" << ttff.size() << "/" << FLAGS_num_measurements << "): ";
for(double ttff_ : ttff) std::cout << ttff_ << " ";
std::cout << std::endl;
std::cout << "TTFF mean: " << mean << " [s]" << std::endl;
stm << "Valid measurements (" << ttff.size() << "/" << FLAGS_num_measurements << "): ";
for(double ttff_ : ttff) stm << ttff_ << " ";
stm << std::endl;
stm << "TTFF mean: " << mean << " [s]" << std::endl;
if (ttff.size() > 0)
{
std::cout << "TTFF max: " << *max_ttff << " [s]" << std::endl;
std::cout << "TTFF min: " << *min_ttff << " [s]" << std::endl;
stm << "TTFF max: " << *max_ttff << " [s]" << std::endl;
stm << "TTFF min: " << *min_ttff << " [s]" << std::endl;
}
std::cout << "TTFF stdev: " << stdev << " [s]" << std::endl;
std::cout << "Operating System: " << std::string(HOST_SYSTEM) << std::endl;
std::cout << "Navigation mode: " << "3D" << std::endl;
stm << "TTFF stdev: " << stdev << " [s]" << std::endl;
stm << "Operating System: " << std::string(HOST_SYSTEM) << std::endl;
stm << "Navigation mode: " << "3D" << std::endl;
if(source.compare("UHD_Signal_Source"))
{
std::cout << "Source: File" << std::endl;
stm << "Source: File" << std::endl;
}
else
{
std::cout << "Source: Live" << std::endl;
stm << "Source: Live" << std::endl;
}
stm << "---------------------------" << std::endl;
std::cout << stm.rdbuf();
if (ttff_report_file.is_open())
{
ttff_report_file << stm.str();
ttff_report_file.close();
}
std::cout << "---------------------------" << std::endl;
}