diff --git a/src/tests/common-files/gnuplot_i.h b/src/tests/common-files/gnuplot_i.h index 7417286cb..ef5dbb241 100644 --- a/src/tests/common-files/gnuplot_i.h +++ b/src/tests/common-files/gnuplot_i.h @@ -545,6 +545,9 @@ public: const unsigned int iHeight, const std::string &title = ""); + /// plot circle + Gnuplot& plot_circle(double east, double north, double radius, const std::string &label = ""); + //---------------------------------------------------------------------------------- ///\brief replot repeats the last plot or splot command. /// this can be useful for viewing a plot with different set options, @@ -937,7 +940,8 @@ Gnuplot::~Gnuplot() #elif defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__) if (pclose(gnucmd) == -1) #endif - throw GnuplotException("Problem closing communication to gnuplot"); + // throw GnuplotException("Problem closing communication to gnuplot"); + std::cout << "Gnuplot window left open." << std::endl; } @@ -1634,6 +1638,36 @@ Gnuplot& Gnuplot::plot_image(const unsigned char * ucPicBuf, } +Gnuplot& Gnuplot::plot_circle(double east, double north, double radius, const std::string &label) +{ + std::ostringstream cmdstr; + // + // command to be sent to gnuplot + // + cmdstr << "set object circle at " + std::to_string(east) + "," + std::to_string(north) + " size " + + std::to_string(radius) + " back\n"; + + if (label != "") + { + double east_label = (std::cos(M_PI / 3.0) * radius) * 1.1 + east; + double north_label = (std::sin(M_PI / 3.0) * radius) * 1.1 + north; + cmdstr << "set label \"" + label + "\" at first " + std::to_string(east_label) + + ", " + std::to_string(north_label) + " norotate back nopoint offset 0,0\n"; + } + if (nplots > 0) + cmdstr << "replot "; + else + cmdstr << "plot "; + + // + // Do the actual plot + // + cmd(cmdstr.str()); + + return *this; +} + + //------------------------------------------------------------------------------ // diff --git a/src/tests/system-tests/position_test.cc b/src/tests/system-tests/position_test.cc index 5b14d0e62..bf85b6b50 100644 --- a/src/tests/system-tests/position_test.cc +++ b/src/tests/system-tests/position_test.cc @@ -29,11 +29,13 @@ * ------------------------------------------------------------------------- */ +#include #include #include #include #include #include +#include #include #include #include @@ -43,10 +45,13 @@ #include "in_memory_configuration.h" #include "file_configuration.h" #include "MATH_CONSTANTS.h" +#include "gnuplot_i.h" +#include "test_flags.h" #include "signal_generator_flags.h" DEFINE_string(config_file_ptest, std::string(""), "File containing the configuration parameters for the position test."); +DEFINE_bool(plot_position_test, false, "Plots results of FFTLengthTest with gnuplot"); // For GPS NAVIGATION (L1) concurrent_queue global_gps_acq_assist_queue; @@ -73,6 +78,9 @@ public: int configure_receiver(); int run_receiver(); void check_results(); + void print_results(const std::vector & east, + const std::vector & north, + const std::vector & up); double compute_stdev_precision(const std::vector & vec); double compute_stdev_accuracy(const std::vector & vec, double ref); @@ -542,9 +550,78 @@ void StaticPositionSystemTest::check_results() // Sanity Check double precision_SEP = 0.51 * (sigma_E_2_precision + sigma_N_2_precision + sigma_U_2_precision); ASSERT_LT(precision_SEP, 20.0); + + if(FLAGS_plot_position_test == true) + { + print_results(pos_e, pos_n, pos_u); + } } +void StaticPositionSystemTest::print_results(const std::vector & east, + const std::vector & north, + const std::vector & up) +{ + const std::string gnuplot_executable(FLAGS_gnuplot_executable); + if(gnuplot_executable.empty()) + { + std::cout << "WARNING: Although the flag plot_position_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 + { + double sigma_E_2_precision = std::pow(compute_stdev_precision(east), 2.0); + double sigma_N_2_precision = std::pow(compute_stdev_precision(north), 2.0); + double sigma_U_2_precision = std::pow(compute_stdev_precision(up), 2.0); + + double mean_east = std::accumulate(east.begin(), east.end(), 0.0) / east.size(); + double mean_north = std::accumulate(north.begin(), north.end(), 0.0) / north.size(); + + auto it_max_east = std::max_element(std::begin(east), std::end(east)); + auto it_min_east = std::min_element(std::begin(east), std::end(east)); + auto it_max_north = std::max_element(std::begin(north), std::end(north)); + auto it_min_north = std::min_element(std::begin(north), std::end(north)); + + auto east_range = std::max(*it_max_east, std::abs(*it_min_east)); + auto north_range = std::max(*it_max_north, std::abs(*it_min_north)); + + double range = std::max(east_range, north_range) * 1.1; + + double two_drms = 2 * sqrt(sigma_E_2_precision + sigma_N_2_precision); + 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("points"); + g1.set_title("2D precision"); + g1.set_xlabel("East [m]"); + g1.set_ylabel("North [m]"); + g1.cmd("set size ratio -1"); + g1.cmd("set xrange [-" + std::to_string(range) + ":" + std::to_string(range) + "]"); + g1.cmd("set yrange [-" + std::to_string(range) + ":" + std::to_string(range) + "]"); + + g1.plot_xy(east, north, "2D Position Fixes"); + g1.set_style("lines").plot_circle(mean_east, mean_north, two_drms, "2DRMS"); + g1.set_style("lines").plot_circle(mean_east, mean_north, two_drms / 2.0, "DRMS"); + + g1.cmd("set grid front"); + g1.cmd("replot"); + + g1.savetops("Position_test_2D"); + g1.showonscreen(); // window output + } + catch (GnuplotException ge) + { + std::cout << ge.what() << std::endl; + } + } + +} + TEST_F(StaticPositionSystemTest, Position_system_test) { if(FLAGS_config_file_ptest.empty())