mirror of
https://github.com/gnss-sdr/gnss-sdr
synced 2024-12-14 12:10:34 +00:00
Refactoring PVT solution library and adding a GeoJSON format printer
This commit is contained in:
parent
4aac371bbf
commit
f68a1fe9bc
@ -77,6 +77,13 @@ galileo_e1_pvt_cc::galileo_e1_pvt_cc(unsigned int nchannels, boost::shared_ptr<g
|
|||||||
d_kml_dump = std::make_shared<Kml_Printer>();
|
d_kml_dump = std::make_shared<Kml_Printer>();
|
||||||
d_kml_dump->set_headers(kml_dump_filename);
|
d_kml_dump->set_headers(kml_dump_filename);
|
||||||
|
|
||||||
|
//initialize geojson_printer
|
||||||
|
std::string geojson_dump_filename;
|
||||||
|
geojson_dump_filename = d_dump_filename;
|
||||||
|
geojson_dump_filename.append(".geojson");
|
||||||
|
d_geojson_printer = std::make_shared<GeoJSON_Printer>();
|
||||||
|
d_geojson_printer->set_headers(geojson_dump_filename);
|
||||||
|
|
||||||
//initialize nmea_printer
|
//initialize nmea_printer
|
||||||
d_nmea_printer = std::make_shared<Nmea_Printer>(nmea_dump_filename, flag_nmea_tty_port, nmea_dump_devname);
|
d_nmea_printer = std::make_shared<Nmea_Printer>(nmea_dump_filename, flag_nmea_tty_port, nmea_dump_devname);
|
||||||
d_dump_filename.append("_raw.dat");
|
d_dump_filename.append("_raw.dat");
|
||||||
@ -223,9 +230,9 @@ int galileo_e1_pvt_cc::general_work (int noutput_items, gr_vector_int &ninput_it
|
|||||||
if (pvt_result == true)
|
if (pvt_result == true)
|
||||||
{
|
{
|
||||||
d_kml_dump->print_position(d_ls_pvt, d_flag_averaging);
|
d_kml_dump->print_position(d_ls_pvt, d_flag_averaging);
|
||||||
//ToDo: Implement Galileo RINEX and Galileo NMEA outputs
|
d_geojson_printer->print_position(d_ls_pvt, d_flag_averaging);
|
||||||
// d_nmea_printer->Print_Nmea_Line(d_ls_pvt, d_flag_averaging);
|
d_nmea_printer->Print_Nmea_Line(d_ls_pvt, d_flag_averaging);
|
||||||
//
|
|
||||||
if (!b_rinex_header_writen)
|
if (!b_rinex_header_writen)
|
||||||
{
|
{
|
||||||
std::map<int,Galileo_Ephemeris>::iterator galileo_ephemeris_iter;
|
std::map<int,Galileo_Ephemeris>::iterator galileo_ephemeris_iter;
|
||||||
|
@ -46,6 +46,7 @@
|
|||||||
#include "nmea_printer.h"
|
#include "nmea_printer.h"
|
||||||
#include "kml_printer.h"
|
#include "kml_printer.h"
|
||||||
#include "rinex_printer.h"
|
#include "rinex_printer.h"
|
||||||
|
#include "geojson_printer.h"
|
||||||
#include "galileo_e1_ls_pvt.h"
|
#include "galileo_e1_ls_pvt.h"
|
||||||
#include "Galileo_E1.h"
|
#include "Galileo_E1.h"
|
||||||
|
|
||||||
@ -108,6 +109,8 @@ private:
|
|||||||
long unsigned int d_last_sample_nav_output;
|
long unsigned int d_last_sample_nav_output;
|
||||||
std::shared_ptr<Kml_Printer> d_kml_dump;
|
std::shared_ptr<Kml_Printer> d_kml_dump;
|
||||||
std::shared_ptr<Nmea_Printer> d_nmea_printer;
|
std::shared_ptr<Nmea_Printer> d_nmea_printer;
|
||||||
|
std::shared_ptr<GeoJSON_Printer> d_geojson_printer;
|
||||||
|
|
||||||
double d_rx_time;
|
double d_rx_time;
|
||||||
std::shared_ptr<galileo_e1_ls_pvt> d_ls_pvt;
|
std::shared_ptr<galileo_e1_ls_pvt> d_ls_pvt;
|
||||||
bool pseudoranges_pairCompare_min(const std::pair<int,Gnss_Synchro>& a, const std::pair<int,Gnss_Synchro>& b);
|
bool pseudoranges_pairCompare_min(const std::pair<int,Gnss_Synchro>& a, const std::pair<int,Gnss_Synchro>& b);
|
||||||
|
@ -87,8 +87,15 @@ gps_l1_ca_pvt_cc::gps_l1_ca_pvt_cc(unsigned int nchannels,
|
|||||||
std::string kml_dump_filename;
|
std::string kml_dump_filename;
|
||||||
kml_dump_filename = d_dump_filename;
|
kml_dump_filename = d_dump_filename;
|
||||||
kml_dump_filename.append(".kml");
|
kml_dump_filename.append(".kml");
|
||||||
d_kml_dump = std::make_shared<Kml_Printer>();
|
d_kml_printer = std::make_shared<Kml_Printer>();
|
||||||
d_kml_dump->set_headers(kml_dump_filename);
|
d_kml_printer->set_headers(kml_dump_filename);
|
||||||
|
|
||||||
|
//initialize geojson_printer
|
||||||
|
std::string geojson_dump_filename;
|
||||||
|
geojson_dump_filename = d_dump_filename;
|
||||||
|
geojson_dump_filename.append(".geojson");
|
||||||
|
d_geojson_printer = std::make_shared<GeoJSON_Printer>();
|
||||||
|
d_geojson_printer->set_headers(geojson_dump_filename);
|
||||||
|
|
||||||
//initialize nmea_printer
|
//initialize nmea_printer
|
||||||
d_nmea_printer = std::make_shared<Nmea_Printer>(nmea_dump_filename, flag_nmea_tty_port, nmea_dump_devname);
|
d_nmea_printer = std::make_shared<Nmea_Printer>(nmea_dump_filename, flag_nmea_tty_port, nmea_dump_devname);
|
||||||
@ -261,7 +268,8 @@ int gps_l1_ca_pvt_cc::general_work (int noutput_items, gr_vector_int &ninput_ite
|
|||||||
pvt_result = d_ls_pvt->get_PVT(gnss_pseudoranges_map, d_rx_time, d_flag_averaging);
|
pvt_result = d_ls_pvt->get_PVT(gnss_pseudoranges_map, d_rx_time, d_flag_averaging);
|
||||||
if (pvt_result == true)
|
if (pvt_result == true)
|
||||||
{
|
{
|
||||||
d_kml_dump->print_position(d_ls_pvt, d_flag_averaging);
|
d_kml_printer->print_position(d_ls_pvt, d_flag_averaging);
|
||||||
|
d_geojson_printer->print_position(d_ls_pvt, d_flag_averaging);
|
||||||
d_nmea_printer->Print_Nmea_Line(d_ls_pvt, d_flag_averaging);
|
d_nmea_printer->Print_Nmea_Line(d_ls_pvt, d_flag_averaging);
|
||||||
|
|
||||||
if (!b_rinex_header_writen)
|
if (!b_rinex_header_writen)
|
||||||
|
@ -45,6 +45,7 @@
|
|||||||
#include "nmea_printer.h"
|
#include "nmea_printer.h"
|
||||||
#include "kml_printer.h"
|
#include "kml_printer.h"
|
||||||
#include "rinex_printer.h"
|
#include "rinex_printer.h"
|
||||||
|
#include "geojson_printer.h"
|
||||||
#include "gps_l1_ca_ls_pvt.h"
|
#include "gps_l1_ca_ls_pvt.h"
|
||||||
#include "GPS_L1_CA.h"
|
#include "GPS_L1_CA.h"
|
||||||
|
|
||||||
@ -107,8 +108,9 @@ private:
|
|||||||
int d_display_rate_ms;
|
int d_display_rate_ms;
|
||||||
long unsigned int d_sample_counter;
|
long unsigned int d_sample_counter;
|
||||||
long unsigned int d_last_sample_nav_output;
|
long unsigned int d_last_sample_nav_output;
|
||||||
std::shared_ptr<Kml_Printer> d_kml_dump;
|
std::shared_ptr<Kml_Printer> d_kml_printer;
|
||||||
std::shared_ptr<Nmea_Printer> d_nmea_printer;
|
std::shared_ptr<Nmea_Printer> d_nmea_printer;
|
||||||
|
std::shared_ptr<GeoJSON_Printer> d_geojson_printer;
|
||||||
double d_rx_time;
|
double d_rx_time;
|
||||||
std::shared_ptr<gps_l1_ca_ls_pvt> d_ls_pvt;
|
std::shared_ptr<gps_l1_ca_ls_pvt> d_ls_pvt;
|
||||||
|
|
||||||
|
@ -81,6 +81,13 @@ hybrid_pvt_cc::hybrid_pvt_cc(unsigned int nchannels, boost::shared_ptr<gr::msg_q
|
|||||||
d_kml_dump = std::make_shared<Kml_Printer>();
|
d_kml_dump = std::make_shared<Kml_Printer>();
|
||||||
d_kml_dump->set_headers(kml_dump_filename);
|
d_kml_dump->set_headers(kml_dump_filename);
|
||||||
|
|
||||||
|
//initialize geojson_printer
|
||||||
|
std::string geojson_dump_filename;
|
||||||
|
geojson_dump_filename = d_dump_filename;
|
||||||
|
geojson_dump_filename.append(".geojson");
|
||||||
|
d_geojson_printer = std::make_shared<GeoJSON_Printer>();
|
||||||
|
d_geojson_printer->set_headers(geojson_dump_filename);
|
||||||
|
|
||||||
//initialize nmea_printer
|
//initialize nmea_printer
|
||||||
d_nmea_printer = std::make_shared<Nmea_Printer>(nmea_dump_filename, flag_nmea_tty_port, nmea_dump_devname);
|
d_nmea_printer = std::make_shared<Nmea_Printer>(nmea_dump_filename, flag_nmea_tty_port, nmea_dump_devname);
|
||||||
|
|
||||||
@ -279,9 +286,9 @@ int hybrid_pvt_cc::general_work (int noutput_items, gr_vector_int &ninput_items,
|
|||||||
if (pvt_result == true)
|
if (pvt_result == true)
|
||||||
{
|
{
|
||||||
d_kml_dump->print_position(d_ls_pvt, d_flag_averaging);
|
d_kml_dump->print_position(d_ls_pvt, d_flag_averaging);
|
||||||
//ToDo: Implement Galileo RINEX and Galileo NMEA outputs
|
d_geojson_printer->print_position(d_ls_pvt, d_flag_averaging);
|
||||||
// d_nmea_printer->Print_Nmea_Line(d_ls_pvt, d_flag_averaging);
|
d_nmea_printer->Print_Nmea_Line(d_ls_pvt, d_flag_averaging);
|
||||||
//
|
|
||||||
if (!b_rinex_header_writen) // & we have utc data in nav message!
|
if (!b_rinex_header_writen) // & we have utc data in nav message!
|
||||||
{
|
{
|
||||||
std::map<int, Galileo_Ephemeris>::iterator galileo_ephemeris_iter;
|
std::map<int, Galileo_Ephemeris>::iterator galileo_ephemeris_iter;
|
||||||
|
@ -49,7 +49,9 @@
|
|||||||
#include "gps_iono.h"
|
#include "gps_iono.h"
|
||||||
#include "nmea_printer.h"
|
#include "nmea_printer.h"
|
||||||
#include "kml_printer.h"
|
#include "kml_printer.h"
|
||||||
|
#include "geojson_printer.h"
|
||||||
#include "rinex_printer.h"
|
#include "rinex_printer.h"
|
||||||
|
#include "nmea_printer.h"
|
||||||
#include "hybrid_ls_pvt.h"
|
#include "hybrid_ls_pvt.h"
|
||||||
#include "GPS_L1_CA.h"
|
#include "GPS_L1_CA.h"
|
||||||
#include "Galileo_E1.h"
|
#include "Galileo_E1.h"
|
||||||
@ -113,6 +115,7 @@ private:
|
|||||||
long unsigned int d_last_sample_nav_output;
|
long unsigned int d_last_sample_nav_output;
|
||||||
std::shared_ptr<Kml_Printer> d_kml_dump;
|
std::shared_ptr<Kml_Printer> d_kml_dump;
|
||||||
std::shared_ptr<Nmea_Printer> d_nmea_printer;
|
std::shared_ptr<Nmea_Printer> d_nmea_printer;
|
||||||
|
std::shared_ptr<GeoJSON_Printer> d_geojson_printer;
|
||||||
double d_rx_time;
|
double d_rx_time;
|
||||||
double d_TOW_at_curr_symbol_constellation;
|
double d_TOW_at_curr_symbol_constellation;
|
||||||
std::shared_ptr<hybrid_ls_pvt> d_ls_pvt;
|
std::shared_ptr<hybrid_ls_pvt> d_ls_pvt;
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
add_definitions( -DGNSS_SDR_VERSION="${VERSION}" )
|
add_definitions( -DGNSS_SDR_VERSION="${VERSION}" )
|
||||||
|
|
||||||
set(PVT_LIB_SOURCES
|
set(PVT_LIB_SOURCES
|
||||||
|
pvt_solution.cc
|
||||||
ls_pvt.cc
|
ls_pvt.cc
|
||||||
gps_l1_ca_ls_pvt.cc
|
gps_l1_ca_ls_pvt.cc
|
||||||
galileo_e1_ls_pvt.cc
|
galileo_e1_ls_pvt.cc
|
||||||
|
@ -251,60 +251,12 @@ bool galileo_e1_ls_pvt::get_PVT(std::map<int,Gnss_Synchro> gnss_pseudoranges_map
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MOVING AVERAGE PVT
|
// MOVING AVERAGE PVT
|
||||||
if (flag_averaging == true)
|
galileo_e1_ls_pvt::pos_averaging(flag_averaging);
|
||||||
{
|
|
||||||
if (d_hist_longitude_d.size() == (unsigned int)d_averaging_depth)
|
|
||||||
{
|
|
||||||
// Pop oldest value
|
|
||||||
d_hist_longitude_d.pop_back();
|
|
||||||
d_hist_latitude_d.pop_back();
|
|
||||||
d_hist_height_m.pop_back();
|
|
||||||
// Push new values
|
|
||||||
d_hist_longitude_d.push_front(d_longitude_d);
|
|
||||||
d_hist_latitude_d.push_front(d_latitude_d);
|
|
||||||
d_hist_height_m.push_front(d_height_m);
|
|
||||||
|
|
||||||
d_avg_latitude_d = 0;
|
|
||||||
d_avg_longitude_d = 0;
|
|
||||||
d_avg_height_m = 0;
|
|
||||||
for (unsigned int i = 0; i < d_hist_longitude_d.size(); i++)
|
|
||||||
{
|
|
||||||
d_avg_latitude_d = d_avg_latitude_d + d_hist_latitude_d.at(i);
|
|
||||||
d_avg_longitude_d = d_avg_longitude_d + d_hist_longitude_d.at(i);
|
|
||||||
d_avg_height_m = d_avg_height_m + d_hist_height_m.at(i);
|
|
||||||
}
|
|
||||||
d_avg_latitude_d = d_avg_latitude_d / static_cast<double>(d_averaging_depth);
|
|
||||||
d_avg_longitude_d = d_avg_longitude_d / static_cast<double>(d_averaging_depth);
|
|
||||||
d_avg_height_m = d_avg_height_m / static_cast<double>(d_averaging_depth);
|
|
||||||
b_valid_position = true;
|
|
||||||
return true; //indicates that the returned position is valid
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// int current_depth=d_hist_longitude_d.size();
|
|
||||||
// Push new values
|
|
||||||
d_hist_longitude_d.push_front(d_longitude_d);
|
|
||||||
d_hist_latitude_d.push_front(d_latitude_d);
|
|
||||||
d_hist_height_m.push_front(d_height_m);
|
|
||||||
|
|
||||||
d_avg_latitude_d = d_latitude_d;
|
|
||||||
d_avg_longitude_d = d_longitude_d;
|
|
||||||
d_avg_height_m = d_height_m;
|
|
||||||
b_valid_position = false;
|
|
||||||
return false; //indicates that the returned position is not valid yet
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
b_valid_position = true;
|
|
||||||
return true; //indicates that the returned position is valid
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
b_valid_position = false;
|
b_valid_position = false;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
return false;
|
return b_valid_position;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,16 +48,26 @@ GeoJSON_Printer::~GeoJSON_Printer ()
|
|||||||
bool GeoJSON_Printer::set_headers(std::string filename)
|
bool GeoJSON_Printer::set_headers(std::string filename)
|
||||||
{
|
{
|
||||||
geojson_file.open(filename.c_str());
|
geojson_file.open(filename.c_str());
|
||||||
|
filename_ = filename;
|
||||||
|
first_pos = true;
|
||||||
if (geojson_file.is_open())
|
if (geojson_file.is_open())
|
||||||
{
|
{
|
||||||
DLOG(INFO) << "GeoJSON printer writing on " << filename.c_str();
|
DLOG(INFO) << "GeoJSON printer writing on " << filename.c_str();
|
||||||
|
|
||||||
// Set iostream numeric format and precision
|
// Set iostream numeric format and precision
|
||||||
geojson_file.setf(geojson_file.fixed, geojson_file.floatfield);
|
geojson_file.setf(geojson_file.fixed, geojson_file.floatfield);
|
||||||
geojson_file << std::setprecision(14);
|
geojson_file << std::setprecision(14);
|
||||||
|
|
||||||
|
// Writing the header
|
||||||
geojson_file << "{" << std::endl;
|
geojson_file << "{" << std::endl;
|
||||||
geojson_file << " \"type\": \"Feature\"," << std::endl;
|
geojson_file << " \"type\": \"Feature\"," << std::endl;
|
||||||
|
geojson_file << " \"properties\": {" << std::endl;
|
||||||
|
geojson_file << " \"name\": \"Locations generated by GNSS-SDR\" " << std::endl;
|
||||||
|
geojson_file << " }," << std::endl;
|
||||||
|
|
||||||
|
|
||||||
geojson_file << " \"geometry\": {" << std::endl;
|
geojson_file << " \"geometry\": {" << std::endl;
|
||||||
geojson_file << " \"type\": \"MultiPoint\"," << std::endl;
|
geojson_file << " \"type\": \"MultiPoint\"," << std::endl;
|
||||||
geojson_file << " \"coordinates\": [" << std::endl;
|
geojson_file << " \"coordinates\": [" << std::endl;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -70,13 +80,13 @@ bool GeoJSON_Printer::set_headers(std::string filename)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool GeoJSON_Printer::print_position(const std::shared_ptr<Ls_Pvt>& position, bool print_average_values)
|
bool GeoJSON_Printer::print_position(const std::shared_ptr<Pvt_Solution>& position, bool print_average_values)
|
||||||
{
|
{
|
||||||
double latitude;
|
double latitude;
|
||||||
double longitude;
|
double longitude;
|
||||||
double height;
|
double height;
|
||||||
|
|
||||||
std::shared_ptr<Ls_Pvt> position_ = position;
|
std::shared_ptr<Pvt_Solution> position_ = position;
|
||||||
|
|
||||||
if (print_average_values == false)
|
if (print_average_values == false)
|
||||||
{
|
{
|
||||||
@ -93,7 +103,16 @@ bool GeoJSON_Printer::print_position(const std::shared_ptr<Ls_Pvt>& position, bo
|
|||||||
|
|
||||||
if (geojson_file.is_open())
|
if (geojson_file.is_open())
|
||||||
{
|
{
|
||||||
geojson_file << " [" << longitude << ", " << latitude << ", " << height << "]," << std::endl;
|
if (first_pos == true)
|
||||||
|
{
|
||||||
|
geojson_file << " [" << longitude << ", " << latitude << ", " << height << "]";
|
||||||
|
first_pos = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
geojson_file << "," << std::endl;
|
||||||
|
geojson_file << " [" << longitude << ", " << latitude << ", " << height << "]";
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -108,10 +127,18 @@ bool GeoJSON_Printer::close_file()
|
|||||||
{
|
{
|
||||||
if (geojson_file.is_open())
|
if (geojson_file.is_open())
|
||||||
{
|
{
|
||||||
|
geojson_file << std::endl;
|
||||||
geojson_file << " ]" << std::endl;
|
geojson_file << " ]" << std::endl;
|
||||||
geojson_file << " }" << std::endl;
|
geojson_file << " }" << std::endl;
|
||||||
geojson_file << "}" << std::endl;
|
geojson_file << "}" << std::endl;
|
||||||
geojson_file.close();
|
geojson_file.close();
|
||||||
|
|
||||||
|
// if nothing is written, erase the file
|
||||||
|
if (first_pos == true)
|
||||||
|
{
|
||||||
|
if(remove(filename_.c_str()) != 0) LOG(INFO) << "Error deleting temporary file";
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -37,7 +37,7 @@
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "ls_pvt.h"
|
#include "pvt_solution.h"
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -49,11 +49,13 @@ class GeoJSON_Printer
|
|||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
std::ofstream geojson_file;
|
std::ofstream geojson_file;
|
||||||
|
bool first_pos;
|
||||||
|
std::string filename_;
|
||||||
public:
|
public:
|
||||||
GeoJSON_Printer();
|
GeoJSON_Printer();
|
||||||
~GeoJSON_Printer();
|
~GeoJSON_Printer();
|
||||||
bool set_headers(std::string filename);
|
bool set_headers(std::string filename);
|
||||||
bool print_position(const std::shared_ptr<Ls_Pvt>& position, bool print_average_values);
|
bool print_position(const std::shared_ptr<Pvt_Solution>& position, bool print_average_values);
|
||||||
bool close_file();
|
bool close_file();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -171,10 +171,10 @@ bool gps_l1_ca_ls_pvt::get_PVT(std::map<int,Gnss_Synchro> gnss_pseudoranges_map,
|
|||||||
gps_l1_ca_ls_pvt::cart2geo(mypos(0), mypos(1), mypos(2), 4);
|
gps_l1_ca_ls_pvt::cart2geo(mypos(0), mypos(1), mypos(2), 4);
|
||||||
//ToDo: Find an Observables/PVT random bug with some satellite configurations that gives an erratic PVT solution (i.e. height>50 km)
|
//ToDo: Find an Observables/PVT random bug with some satellite configurations that gives an erratic PVT solution (i.e. height>50 km)
|
||||||
if (d_height_m > 50000)
|
if (d_height_m > 50000)
|
||||||
{
|
{
|
||||||
b_valid_position = false;
|
b_valid_position = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Compute UTC time and print PVT solution
|
// Compute UTC time and print PVT solution
|
||||||
double secondsperweek = 604800.0; // number of seconds in one week (7*24*60*60)
|
double secondsperweek = 604800.0; // number of seconds in one week (7*24*60*60)
|
||||||
boost::posix_time::time_duration t = boost::posix_time::seconds(utc + secondsperweek * static_cast<double>(GPS_week));
|
boost::posix_time::time_duration t = boost::posix_time::seconds(utc + secondsperweek * static_cast<double>(GPS_week));
|
||||||
@ -183,8 +183,8 @@ bool gps_l1_ca_ls_pvt::get_PVT(std::map<int,Gnss_Synchro> gnss_pseudoranges_map,
|
|||||||
d_position_UTC_time = p_time;
|
d_position_UTC_time = p_time;
|
||||||
|
|
||||||
LOG(INFO) << "(new)Position at " << boost::posix_time::to_simple_string(p_time)
|
LOG(INFO) << "(new)Position at " << boost::posix_time::to_simple_string(p_time)
|
||||||
<< " is Lat = " << d_latitude_d << " [deg], Long = " << d_longitude_d
|
<< " is Lat = " << d_latitude_d << " [deg], Long = " << d_longitude_d
|
||||||
<< " [deg], Height= " << d_height_m << " [m]";
|
<< " [deg], Height= " << d_height_m << " [m]";
|
||||||
|
|
||||||
// ###### Compute DOPs ########
|
// ###### Compute DOPs ########
|
||||||
gps_l1_ca_ls_pvt::compute_DOP();
|
gps_l1_ca_ls_pvt::compute_DOP();
|
||||||
@ -228,60 +228,13 @@ bool gps_l1_ca_ls_pvt::get_PVT(std::map<int,Gnss_Synchro> gnss_pseudoranges_map,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MOVING AVERAGE PVT
|
// MOVING AVERAGE PVT
|
||||||
if (flag_averaging == true)
|
gps_l1_ca_ls_pvt::pos_averaging(flag_averaging);
|
||||||
{
|
|
||||||
if (d_hist_longitude_d.size() == (unsigned int)d_averaging_depth)
|
|
||||||
{
|
|
||||||
// Pop oldest value
|
|
||||||
d_hist_longitude_d.pop_back();
|
|
||||||
d_hist_latitude_d.pop_back();
|
|
||||||
d_hist_height_m.pop_back();
|
|
||||||
// Push new values
|
|
||||||
d_hist_longitude_d.push_front(d_longitude_d);
|
|
||||||
d_hist_latitude_d.push_front(d_latitude_d);
|
|
||||||
d_hist_height_m.push_front(d_height_m);
|
|
||||||
|
|
||||||
d_avg_latitude_d = 0;
|
|
||||||
d_avg_longitude_d = 0;
|
|
||||||
d_avg_height_m = 0;
|
|
||||||
for (unsigned int i = 0; i < d_hist_longitude_d.size(); i++)
|
|
||||||
{
|
|
||||||
d_avg_latitude_d = d_avg_latitude_d + d_hist_latitude_d.at(i);
|
|
||||||
d_avg_longitude_d = d_avg_longitude_d + d_hist_longitude_d.at(i);
|
|
||||||
d_avg_height_m = d_avg_height_m + d_hist_height_m.at(i);
|
|
||||||
}
|
|
||||||
d_avg_latitude_d = d_avg_latitude_d / static_cast<double>(d_averaging_depth);
|
|
||||||
d_avg_longitude_d = d_avg_longitude_d / static_cast<double>(d_averaging_depth);
|
|
||||||
d_avg_height_m = d_avg_height_m / static_cast<double>(d_averaging_depth);
|
|
||||||
b_valid_position = true;
|
|
||||||
return true; //indicates that the returned position is valid
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//int current_depth=d_hist_longitude_d.size();
|
|
||||||
// Push new values
|
|
||||||
d_hist_longitude_d.push_front(d_longitude_d);
|
|
||||||
d_hist_latitude_d.push_front(d_latitude_d);
|
|
||||||
d_hist_height_m.push_front(d_height_m);
|
|
||||||
|
|
||||||
d_avg_latitude_d = d_latitude_d;
|
|
||||||
d_avg_longitude_d = d_longitude_d;
|
|
||||||
d_avg_height_m = d_height_m;
|
|
||||||
b_valid_position = false;
|
|
||||||
return false; //indicates that the returned position is not valid yet
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
b_valid_position = true;
|
|
||||||
return true; //indicates that the returned position is valid
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
b_valid_position = false;
|
b_valid_position = false;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
return b_valid_position;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -172,10 +172,10 @@ bool hybrid_ls_pvt::get_PVT(std::map<int,Gnss_Synchro> gnss_pseudoranges_map, do
|
|||||||
|
|
||||||
// SV ECEF DEBUG OUTPUT
|
// SV ECEF DEBUG OUTPUT
|
||||||
DLOG(INFO) << "ECEF satellite SV ID=" << galileo_ephemeris_iter->second.i_satellite_PRN
|
DLOG(INFO) << "ECEF satellite SV ID=" << galileo_ephemeris_iter->second.i_satellite_PRN
|
||||||
<< " X=" << galileo_ephemeris_iter->second.d_satpos_X
|
<< " X=" << galileo_ephemeris_iter->second.d_satpos_X
|
||||||
<< " [m] Y=" << galileo_ephemeris_iter->second.d_satpos_Y
|
<< " [m] Y=" << galileo_ephemeris_iter->second.d_satpos_Y
|
||||||
<< " [m] Z=" << galileo_ephemeris_iter->second.d_satpos_Z
|
<< " [m] Z=" << galileo_ephemeris_iter->second.d_satpos_Z
|
||||||
<< " [m] PR_obs=" << obs(obs_counter) << " [m]";
|
<< " [m] PR_obs=" << obs(obs_counter) << " [m]";
|
||||||
}
|
}
|
||||||
|
|
||||||
else // the ephemeris are not available for this SV
|
else // the ephemeris are not available for this SV
|
||||||
@ -275,8 +275,8 @@ bool hybrid_ls_pvt::get_PVT(std::map<int,Gnss_Synchro> gnss_pseudoranges_map, do
|
|||||||
{
|
{
|
||||||
b_valid_position = false;
|
b_valid_position = false;
|
||||||
LOG(INFO) << "Hybrid Position at " << boost::posix_time::to_simple_string(p_time)
|
LOG(INFO) << "Hybrid Position at " << boost::posix_time::to_simple_string(p_time)
|
||||||
<< " is Lat = " << d_latitude_d << " [deg], Long = " << d_longitude_d
|
<< " is Lat = " << d_latitude_d << " [deg], Long = " << d_longitude_d
|
||||||
<< " [deg], Height= " << d_height_m << " [m]";
|
<< " [deg], Height= " << d_height_m << " [m]";
|
||||||
|
|
||||||
//std::cout << "Hybrid Position at " << boost::posix_time::to_simple_string(p_time)
|
//std::cout << "Hybrid Position at " << boost::posix_time::to_simple_string(p_time)
|
||||||
// << " is Lat = " << d_latitude_d << " [deg], Long = " << d_longitude_d
|
// << " is Lat = " << d_latitude_d << " [deg], Long = " << d_longitude_d
|
||||||
@ -285,8 +285,8 @@ bool hybrid_ls_pvt::get_PVT(std::map<int,Gnss_Synchro> gnss_pseudoranges_map, do
|
|||||||
}
|
}
|
||||||
|
|
||||||
LOG(INFO) << "Hybrid Position at " << boost::posix_time::to_simple_string(p_time)
|
LOG(INFO) << "Hybrid Position at " << boost::posix_time::to_simple_string(p_time)
|
||||||
<< " is Lat = " << d_latitude_d << " [deg], Long = " << d_longitude_d
|
<< " is Lat = " << d_latitude_d << " [deg], Long = " << d_longitude_d
|
||||||
<< " [deg], Height= " << d_height_m << " [m]";
|
<< " [deg], Height= " << d_height_m << " [m]";
|
||||||
|
|
||||||
|
|
||||||
// ###### Compute DOPs ########
|
// ###### Compute DOPs ########
|
||||||
@ -331,60 +331,12 @@ bool hybrid_ls_pvt::get_PVT(std::map<int,Gnss_Synchro> gnss_pseudoranges_map, do
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MOVING AVERAGE PVT
|
// MOVING AVERAGE PVT
|
||||||
if (flag_averaging == true)
|
hybrid_ls_pvt::pos_averaging(flag_averaging);
|
||||||
{
|
|
||||||
if (d_hist_longitude_d.size() == (unsigned int)d_averaging_depth)
|
|
||||||
{
|
|
||||||
// Pop oldest value
|
|
||||||
d_hist_longitude_d.pop_back();
|
|
||||||
d_hist_latitude_d.pop_back();
|
|
||||||
d_hist_height_m.pop_back();
|
|
||||||
// Push new values
|
|
||||||
d_hist_longitude_d.push_front(d_longitude_d);
|
|
||||||
d_hist_latitude_d.push_front(d_latitude_d);
|
|
||||||
d_hist_height_m.push_front(d_height_m);
|
|
||||||
|
|
||||||
d_avg_latitude_d = 0;
|
|
||||||
d_avg_longitude_d = 0;
|
|
||||||
d_avg_height_m = 0;
|
|
||||||
for (unsigned int i = 0; i < d_hist_longitude_d.size(); i++)
|
|
||||||
{
|
|
||||||
d_avg_latitude_d = d_avg_latitude_d + d_hist_latitude_d.at(i);
|
|
||||||
d_avg_longitude_d = d_avg_longitude_d + d_hist_longitude_d.at(i);
|
|
||||||
d_avg_height_m = d_avg_height_m + d_hist_height_m.at(i);
|
|
||||||
}
|
|
||||||
d_avg_latitude_d = d_avg_latitude_d / static_cast<double>(d_averaging_depth);
|
|
||||||
d_avg_longitude_d = d_avg_longitude_d / static_cast<double>(d_averaging_depth);
|
|
||||||
d_avg_height_m = d_avg_height_m / static_cast<double>(d_averaging_depth);
|
|
||||||
b_valid_position = true;
|
|
||||||
return true; //indicates that the returned position is valid
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// int current_depth=d_hist_longitude_d.size();
|
|
||||||
// Push new values
|
|
||||||
d_hist_longitude_d.push_front(d_longitude_d);
|
|
||||||
d_hist_latitude_d.push_front(d_latitude_d);
|
|
||||||
d_hist_height_m.push_front(d_height_m);
|
|
||||||
|
|
||||||
d_avg_latitude_d = d_latitude_d;
|
|
||||||
d_avg_longitude_d = d_longitude_d;
|
|
||||||
d_avg_height_m = d_height_m;
|
|
||||||
b_valid_position = false;
|
|
||||||
return false; //indicates that the returned position is not valid yet
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
b_valid_position = true;
|
|
||||||
return true; //indicates that the returned position is valid
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
b_valid_position = false;
|
b_valid_position = false;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
return false;
|
return b_valid_position;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,13 +82,13 @@ bool Kml_Printer::set_headers(std::string filename)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool Kml_Printer::print_position(const std::shared_ptr<Ls_Pvt>& position, bool print_average_values)
|
bool Kml_Printer::print_position(const std::shared_ptr<Pvt_Solution>& position, bool print_average_values)
|
||||||
{
|
{
|
||||||
double latitude;
|
double latitude;
|
||||||
double longitude;
|
double longitude;
|
||||||
double height;
|
double height;
|
||||||
|
|
||||||
std::shared_ptr<Ls_Pvt> position_ = position;
|
std::shared_ptr<Pvt_Solution> position_ = position;
|
||||||
|
|
||||||
if (print_average_values == false)
|
if (print_average_values == false)
|
||||||
{
|
{
|
||||||
|
@ -37,7 +37,7 @@
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "ls_pvt.h"
|
#include "pvt_solution.h"
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Prints PVT information to OGC KML format file (can be viewed with Google Earth)
|
* \brief Prints PVT information to OGC KML format file (can be viewed with Google Earth)
|
||||||
@ -52,7 +52,7 @@ public:
|
|||||||
Kml_Printer();
|
Kml_Printer();
|
||||||
~Kml_Printer();
|
~Kml_Printer();
|
||||||
bool set_headers(std::string filename);
|
bool set_headers(std::string filename);
|
||||||
bool print_position(const std::shared_ptr<Ls_Pvt>& position, bool print_average_values);
|
bool print_position(const std::shared_ptr<Pvt_Solution>& position, bool print_average_values);
|
||||||
bool close_file();
|
bool close_file();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*!
|
/*!
|
||||||
* \file ls_pvt.h
|
* \file ls_pvt.cc
|
||||||
* \brief Implementation of a base class for Least Squares PVT solutions
|
* \brief Implementation of a base class for Least Squares PVT solutions
|
||||||
* \author Carles Fernandez-Prades, 2015. cfernandez(at)cttc.es
|
* \author Carles Fernandez-Prades, 2015. cfernandez(at)cttc.es
|
||||||
*
|
*
|
||||||
@ -38,30 +38,15 @@
|
|||||||
|
|
||||||
using google::LogMessage;
|
using google::LogMessage;
|
||||||
|
|
||||||
DEFINE_bool(tropo, true, "Apply tropospheric correction");
|
//DEFINE_bool(tropo, true, "Apply tropospheric correction");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Ls_Pvt::Ls_Pvt()
|
Ls_Pvt::Ls_Pvt() : Pvt_Solution()
|
||||||
{
|
{
|
||||||
d_valid_observations = 0;
|
|
||||||
d_latitude_d = 0.0;
|
|
||||||
d_longitude_d = 0.0;
|
|
||||||
d_height_m = 0.0;
|
|
||||||
d_avg_latitude_d = 0.0;
|
|
||||||
d_avg_longitude_d = 0.0;
|
|
||||||
d_avg_height_m = 0.0;
|
|
||||||
d_x_m = 0.0;
|
d_x_m = 0.0;
|
||||||
d_y_m = 0.0;
|
d_y_m = 0.0;
|
||||||
d_z_m = 0.0;
|
d_z_m = 0.0;
|
||||||
d_GDOP = 0.0;
|
|
||||||
d_PDOP = 0.0;
|
|
||||||
d_HDOP = 0.0;
|
|
||||||
d_VDOP = 0.0;
|
|
||||||
d_TDOP = 0.0;
|
|
||||||
d_flag_averaging = false;
|
|
||||||
b_valid_position = false;
|
|
||||||
d_averaging_depth = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
arma::vec Ls_Pvt::leastSquarePos(const arma::mat & satpos, const arma::vec & obs, const arma::mat & w)
|
arma::vec Ls_Pvt::leastSquarePos(const arma::mat & satpos, const arma::vec & obs, const arma::mat & w)
|
||||||
@ -173,435 +158,3 @@ arma::vec Ls_Pvt::leastSquarePos(const arma::mat & satpos, const arma::vec & obs
|
|||||||
}
|
}
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
arma::vec Ls_Pvt::rotateSatellite(double const traveltime, const arma::vec & X_sat)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Returns rotated satellite ECEF coordinates due to Earth
|
|
||||||
* rotation during signal travel time
|
|
||||||
*
|
|
||||||
* Inputs:
|
|
||||||
* travelTime - signal travel time
|
|
||||||
* X_sat - satellite's ECEF coordinates
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* X_sat_rot - rotated satellite's coordinates (ECEF)
|
|
||||||
*/
|
|
||||||
|
|
||||||
//--- Find rotation angle --------------------------------------------------
|
|
||||||
double omegatau;
|
|
||||||
omegatau = OMEGA_EARTH_DOT * traveltime;
|
|
||||||
|
|
||||||
//--- Build a rotation matrix ----------------------------------------------
|
|
||||||
arma::mat R3 = arma::zeros(3,3);
|
|
||||||
R3(0, 0) = cos(omegatau);
|
|
||||||
R3(0, 1) = sin(omegatau);
|
|
||||||
R3(0, 2) = 0.0;
|
|
||||||
R3(1, 0) = -sin(omegatau);
|
|
||||||
R3(1, 1) = cos(omegatau);
|
|
||||||
R3(1, 2) = 0.0;
|
|
||||||
R3(2, 0) = 0.0;
|
|
||||||
R3(2, 1) = 0.0;
|
|
||||||
R3(2, 2) = 1;
|
|
||||||
|
|
||||||
//--- Do the rotation ------------------------------------------------------
|
|
||||||
arma::vec X_sat_rot;
|
|
||||||
X_sat_rot = R3 * X_sat;
|
|
||||||
return X_sat_rot;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Ls_Pvt::cart2geo(double X, double Y, double Z, int elipsoid_selection)
|
|
||||||
{
|
|
||||||
/* Conversion of Cartesian coordinates (X,Y,Z) to geographical
|
|
||||||
coordinates (latitude, longitude, h) on a selected reference ellipsoid.
|
|
||||||
|
|
||||||
Choices of Reference Ellipsoid for Geographical Coordinates
|
|
||||||
0. International Ellipsoid 1924
|
|
||||||
1. International Ellipsoid 1967
|
|
||||||
2. World Geodetic System 1972
|
|
||||||
3. Geodetic Reference System 1980
|
|
||||||
4. World Geodetic System 1984
|
|
||||||
*/
|
|
||||||
|
|
||||||
const double a[5] = {6378388.0, 6378160.0, 6378135.0, 6378137.0, 6378137.0};
|
|
||||||
const double f[5] = {1.0 / 297.0, 1.0 / 298.247, 1.0 / 298.26, 1.0 / 298.257222101, 1.0 / 298.257223563};
|
|
||||||
|
|
||||||
double lambda = atan2(Y, X);
|
|
||||||
double ex2 = (2.0 - f[elipsoid_selection]) * f[elipsoid_selection] / ((1.0 - f[elipsoid_selection]) * (1.0 - f[elipsoid_selection]));
|
|
||||||
double c = a[elipsoid_selection] * sqrt(1.0 + ex2);
|
|
||||||
double phi = atan(Z / ((sqrt(X * X + Y * Y) * (1.0 - (2.0 - f[elipsoid_selection])) * f[elipsoid_selection])));
|
|
||||||
|
|
||||||
double h = 0.1;
|
|
||||||
double oldh = 0.0;
|
|
||||||
double N;
|
|
||||||
int iterations = 0;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
oldh = h;
|
|
||||||
N = c / sqrt(1 + ex2 * (cos(phi) * cos(phi)));
|
|
||||||
phi = atan(Z / ((sqrt(X * X + Y * Y) * (1.0 - (2.0 - f[elipsoid_selection]) * f[elipsoid_selection] * N / (N + h) ))));
|
|
||||||
h = sqrt(X * X + Y * Y) / cos(phi) - N;
|
|
||||||
iterations = iterations + 1;
|
|
||||||
if (iterations > 100)
|
|
||||||
{
|
|
||||||
LOG(WARNING) << "Failed to approximate h with desired precision. h-oldh= " << h - oldh;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while (std::abs(h - oldh) > 1.0e-12);
|
|
||||||
d_latitude_d = phi * 180.0 / GPS_PI;
|
|
||||||
d_longitude_d = lambda * 180.0 / GPS_PI;
|
|
||||||
d_height_m = h;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Ls_Pvt::togeod(double *dphi, double *dlambda, double *h, double a, double finv, double X, double Y, double Z)
|
|
||||||
{
|
|
||||||
/* Subroutine to calculate geodetic coordinates latitude, longitude,
|
|
||||||
height given Cartesian coordinates X,Y,Z, and reference ellipsoid
|
|
||||||
values semi-major axis (a) and the inverse of flattening (finv).
|
|
||||||
|
|
||||||
The output units of angular quantities will be in decimal degrees
|
|
||||||
(15.5 degrees not 15 deg 30 min). The output units of h will be the
|
|
||||||
same as the units of X,Y,Z,a.
|
|
||||||
|
|
||||||
Inputs:
|
|
||||||
a - semi-major axis of the reference ellipsoid
|
|
||||||
finv - inverse of flattening of the reference ellipsoid
|
|
||||||
X,Y,Z - Cartesian coordinates
|
|
||||||
|
|
||||||
Outputs:
|
|
||||||
dphi - latitude
|
|
||||||
dlambda - longitude
|
|
||||||
h - height above reference ellipsoid
|
|
||||||
|
|
||||||
Based in a Matlab function by Kai Borre
|
|
||||||
*/
|
|
||||||
|
|
||||||
*h = 0;
|
|
||||||
double tolsq = 1.e-10; // tolerance to accept convergence
|
|
||||||
int maxit = 10; // max number of iterations
|
|
||||||
double rtd = 180.0 / GPS_PI;
|
|
||||||
|
|
||||||
// compute square of eccentricity
|
|
||||||
double esq;
|
|
||||||
if (finv < 1.0E-20)
|
|
||||||
{
|
|
||||||
esq = 0.0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
esq = (2.0 - 1.0 / finv) / finv;
|
|
||||||
}
|
|
||||||
|
|
||||||
// first guess
|
|
||||||
double P = sqrt(X * X + Y * Y); // P is distance from spin axis
|
|
||||||
|
|
||||||
//direct calculation of longitude
|
|
||||||
if (P > 1.0E-20)
|
|
||||||
{
|
|
||||||
*dlambda = atan2(Y, X) * rtd;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*dlambda = 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// correct longitude bound
|
|
||||||
if (*dlambda < 0)
|
|
||||||
{
|
|
||||||
*dlambda = *dlambda + 360.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
double r = sqrt(P * P + Z * Z); // r is distance from origin (0,0,0)
|
|
||||||
|
|
||||||
double sinphi;
|
|
||||||
if (r > 1.0E-20)
|
|
||||||
{
|
|
||||||
sinphi = Z/r;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sinphi = 0.0;
|
|
||||||
}
|
|
||||||
*dphi = asin(sinphi);
|
|
||||||
|
|
||||||
// initial value of height = distance from origin minus
|
|
||||||
// approximate distance from origin to surface of ellipsoid
|
|
||||||
if (r < 1.0E-20)
|
|
||||||
{
|
|
||||||
*h = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
*h = r - a * (1 - sinphi * sinphi/finv);
|
|
||||||
|
|
||||||
// iterate
|
|
||||||
double cosphi;
|
|
||||||
double N_phi;
|
|
||||||
double dP;
|
|
||||||
double dZ;
|
|
||||||
double oneesq = 1.0 - esq;
|
|
||||||
|
|
||||||
for (int i = 0; i < maxit; i++)
|
|
||||||
{
|
|
||||||
sinphi = sin(*dphi);
|
|
||||||
cosphi = cos(*dphi);
|
|
||||||
|
|
||||||
// compute radius of curvature in prime vertical direction
|
|
||||||
N_phi = a / sqrt(1 - esq * sinphi * sinphi);
|
|
||||||
|
|
||||||
// compute residuals in P and Z
|
|
||||||
dP = P - (N_phi + (*h)) * cosphi;
|
|
||||||
dZ = Z - (N_phi * oneesq + (*h)) * sinphi;
|
|
||||||
|
|
||||||
// update height and latitude
|
|
||||||
*h = *h + (sinphi * dZ + cosphi * dP);
|
|
||||||
*dphi = *dphi + (cosphi * dZ - sinphi * dP)/(N_phi + (*h));
|
|
||||||
|
|
||||||
// test for convergence
|
|
||||||
if ((dP * dP + dZ * dZ) < tolsq)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (i == (maxit - 1))
|
|
||||||
{
|
|
||||||
LOG(WARNING) << "The computation of geodetic coordinates did not converge";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*dphi = (*dphi) * rtd;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Ls_Pvt::tropo(double *ddr_m, double sinel, double hsta_km, double p_mb, double t_kel, double hum, double hp_km, double htkel_km, double hhum_km)
|
|
||||||
{
|
|
||||||
/* Inputs:
|
|
||||||
sinel - sin of elevation angle of satellite
|
|
||||||
hsta_km - height of station in km
|
|
||||||
p_mb - atmospheric pressure in mb at height hp_km
|
|
||||||
t_kel - surface temperature in degrees Kelvin at height htkel_km
|
|
||||||
hum - humidity in % at height hhum_km
|
|
||||||
hp_km - height of pressure measurement in km
|
|
||||||
htkel_km - height of temperature measurement in km
|
|
||||||
hhum_km - height of humidity measurement in km
|
|
||||||
|
|
||||||
Outputs:
|
|
||||||
ddr_m - range correction (meters)
|
|
||||||
|
|
||||||
Reference
|
|
||||||
Goad, C.C. & Goodman, L. (1974) A Modified Hopfield Tropospheric
|
|
||||||
Refraction Correction Model. Paper presented at the
|
|
||||||
American Geophysical Union Annual Fall Meeting, San
|
|
||||||
Francisco, December 12-17
|
|
||||||
|
|
||||||
Translated to C++ by Carles Fernandez from a Matlab implementation by Kai Borre
|
|
||||||
*/
|
|
||||||
|
|
||||||
const double a_e = 6378.137; // semi-major axis of earth ellipsoid
|
|
||||||
const double b0 = 7.839257e-5;
|
|
||||||
const double tlapse = -6.5;
|
|
||||||
const double em = -978.77 / (2.8704e6 * tlapse * 1.0e-5);
|
|
||||||
|
|
||||||
double tkhum = t_kel + tlapse * (hhum_km - htkel_km);
|
|
||||||
double atkel = 7.5 * (tkhum - 273.15) / (237.3 + tkhum - 273.15);
|
|
||||||
double e0 = 0.0611 * hum * pow(10, atkel);
|
|
||||||
double tksea = t_kel - tlapse * htkel_km;
|
|
||||||
double tkelh = tksea + tlapse * hhum_km;
|
|
||||||
double e0sea = e0 * pow((tksea / tkelh), (4 * em));
|
|
||||||
double tkelp = tksea + tlapse * hp_km;
|
|
||||||
double psea = p_mb * pow((tksea / tkelp), em);
|
|
||||||
|
|
||||||
if(sinel < 0) { sinel = 0.0; }
|
|
||||||
|
|
||||||
double tropo_delay = 0.0;
|
|
||||||
bool done = false;
|
|
||||||
double refsea = 77.624e-6 / tksea;
|
|
||||||
double htop = 1.1385e-5 / refsea;
|
|
||||||
refsea = refsea * psea;
|
|
||||||
double ref = refsea * pow(((htop - hsta_km) / htop), 4);
|
|
||||||
|
|
||||||
double a;
|
|
||||||
double b;
|
|
||||||
double rtop;
|
|
||||||
|
|
||||||
while(1)
|
|
||||||
{
|
|
||||||
rtop = pow((a_e + htop), 2) - pow((a_e + hsta_km), 2) * (1 - pow(sinel, 2));
|
|
||||||
|
|
||||||
// check to see if geometry is crazy
|
|
||||||
if(rtop < 0) { rtop = 0; }
|
|
||||||
|
|
||||||
rtop = sqrt(rtop) - (a_e + hsta_km) * sinel;
|
|
||||||
|
|
||||||
a = -sinel / (htop - hsta_km);
|
|
||||||
b = -b0 * (1 - pow(sinel,2)) / (htop - hsta_km);
|
|
||||||
|
|
||||||
arma::vec rn = arma::vec(8);
|
|
||||||
rn.zeros();
|
|
||||||
|
|
||||||
for(int i = 0; i<8; i++)
|
|
||||||
{
|
|
||||||
rn(i) = pow(rtop, (i+1+1));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
arma::rowvec alpha = {2 * a, 2 * pow(a, 2) + 4 * b /3, a * (pow(a, 2) + 3 * b),
|
|
||||||
pow(a, 4)/5 + 2.4 * pow(a, 2) * b + 1.2 * pow(b, 2), 2 * a * b * (pow(a, 2) + 3 * b)/3,
|
|
||||||
pow(b, 2) * (6 * pow(a, 2) + 4 * b) * 1.428571e-1, 0, 0};
|
|
||||||
|
|
||||||
if(pow(b, 2) > 1.0e-35)
|
|
||||||
{
|
|
||||||
alpha(6) = a * pow(b, 3) /2;
|
|
||||||
alpha(7) = pow(b, 4) / 9;
|
|
||||||
}
|
|
||||||
|
|
||||||
double dr = rtop;
|
|
||||||
arma::mat aux_ = alpha * rn;
|
|
||||||
dr = dr + aux_(0, 0);
|
|
||||||
tropo_delay = tropo_delay + dr * ref * 1000;
|
|
||||||
|
|
||||||
if(done == true)
|
|
||||||
{
|
|
||||||
*ddr_m = tropo_delay;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
done = true;
|
|
||||||
refsea = (371900.0e-6 / tksea - 12.92e-6) / tksea;
|
|
||||||
htop = 1.1385e-5 * (1255 / tksea + 0.05) / refsea;
|
|
||||||
ref = refsea * e0sea * pow(((htop - hsta_km) / htop), 4);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Ls_Pvt::topocent(double *Az, double *El, double *D, const arma::vec & x, const arma::vec & dx)
|
|
||||||
{
|
|
||||||
/* Transformation of vector dx into topocentric coordinate
|
|
||||||
system with origin at x
|
|
||||||
Inputs:
|
|
||||||
x - vector origin coordinates (in ECEF system [X; Y; Z;])
|
|
||||||
dx - vector ([dX; dY; dZ;]).
|
|
||||||
|
|
||||||
Outputs:
|
|
||||||
D - vector length. Units like the input
|
|
||||||
Az - azimuth from north positive clockwise, degrees
|
|
||||||
El - elevation angle, degrees
|
|
||||||
|
|
||||||
Based on a Matlab function by Kai Borre
|
|
||||||
*/
|
|
||||||
|
|
||||||
double lambda;
|
|
||||||
double phi;
|
|
||||||
double h;
|
|
||||||
double dtr = GPS_PI / 180.0;
|
|
||||||
double a = 6378137.0; // semi-major axis of the reference ellipsoid WGS-84
|
|
||||||
double finv = 298.257223563; // inverse of flattening of the reference ellipsoid WGS-84
|
|
||||||
|
|
||||||
// Transform x into geodetic coordinates
|
|
||||||
Ls_Pvt::togeod(&phi, &lambda, &h, a, finv, x(0), x(1), x(2));
|
|
||||||
|
|
||||||
double cl = cos(lambda * dtr);
|
|
||||||
double sl = sin(lambda * dtr);
|
|
||||||
double cb = cos(phi * dtr);
|
|
||||||
double sb = sin(phi * dtr);
|
|
||||||
|
|
||||||
arma::mat F = arma::zeros(3,3);
|
|
||||||
|
|
||||||
F(0,0) = -sl;
|
|
||||||
F(0,1) = -sb * cl;
|
|
||||||
F(0,2) = cb * cl;
|
|
||||||
|
|
||||||
F(1,0) = cl;
|
|
||||||
F(1,1) = -sb * sl;
|
|
||||||
F(1,2) = cb * sl;
|
|
||||||
|
|
||||||
F(2,0) = 0;
|
|
||||||
F(2,1) = cb;
|
|
||||||
F(2,2) = sb;
|
|
||||||
|
|
||||||
arma::vec local_vector;
|
|
||||||
|
|
||||||
local_vector = arma::htrans(F) * dx;
|
|
||||||
|
|
||||||
double E = local_vector(0);
|
|
||||||
double N = local_vector(1);
|
|
||||||
double U = local_vector(2);
|
|
||||||
|
|
||||||
double hor_dis;
|
|
||||||
hor_dis = sqrt(E * E + N * N);
|
|
||||||
|
|
||||||
if (hor_dis < 1.0E-20)
|
|
||||||
{
|
|
||||||
*Az = 0;
|
|
||||||
*El = 90;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*Az = atan2(E, N) / dtr;
|
|
||||||
*El = atan2(U, hor_dis) / dtr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*Az < 0)
|
|
||||||
{
|
|
||||||
*Az = *Az + 360.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
*D = sqrt(dx(0) * dx(0) + dx(1) * dx(1) + dx(2) * dx(2));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int Ls_Pvt::compute_DOP()
|
|
||||||
{
|
|
||||||
// ###### Compute DOPs ########
|
|
||||||
|
|
||||||
// 1- Rotation matrix from ECEF coordinates to ENU coordinates
|
|
||||||
// ref: http://www.navipedia.net/index.php/Transformations_between_ECEF_and_ENU_coordinates
|
|
||||||
arma::mat F = arma::zeros(3,3);
|
|
||||||
F(0,0) = -sin(GPS_TWO_PI * (d_longitude_d/360.0));
|
|
||||||
F(0,1) = -sin(GPS_TWO_PI * (d_latitude_d/360.0)) * cos(GPS_TWO_PI * (d_longitude_d/360.0));
|
|
||||||
F(0,2) = cos(GPS_TWO_PI * (d_latitude_d/360.0)) * cos(GPS_TWO_PI * (d_longitude_d/360.0));
|
|
||||||
|
|
||||||
F(1,0) = cos((GPS_TWO_PI * d_longitude_d)/360.0);
|
|
||||||
F(1,1) = -sin((GPS_TWO_PI * d_latitude_d)/360.0) * sin((GPS_TWO_PI * d_longitude_d)/360.0);
|
|
||||||
F(1,2) = cos((GPS_TWO_PI * d_latitude_d/360.0)) * sin((GPS_TWO_PI * d_longitude_d)/360.0);
|
|
||||||
|
|
||||||
F(2,0) = 0;
|
|
||||||
F(2,1) = cos((GPS_TWO_PI * d_latitude_d)/360.0);
|
|
||||||
F(2,2) = sin((GPS_TWO_PI * d_latitude_d/360.0));
|
|
||||||
|
|
||||||
// 2- Apply the rotation to the latest covariance matrix (available in ECEF from LS)
|
|
||||||
arma::mat Q_ECEF = d_Q.submat(0, 0, 2, 2);
|
|
||||||
arma::mat DOP_ENU = arma::zeros(3, 3);
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
DOP_ENU = arma::htrans(F) * Q_ECEF * F;
|
|
||||||
d_GDOP = sqrt(arma::trace(DOP_ENU)); // Geometric DOP
|
|
||||||
d_PDOP = sqrt(DOP_ENU(0, 0) + DOP_ENU(1, 1) + DOP_ENU(2, 2));// PDOP
|
|
||||||
d_HDOP = sqrt(DOP_ENU(0, 0) + DOP_ENU(1, 1)); // HDOP
|
|
||||||
d_VDOP = sqrt(DOP_ENU(2, 2)); // VDOP
|
|
||||||
d_TDOP = sqrt(d_Q(3, 3)); // TDOP
|
|
||||||
}
|
|
||||||
catch(std::exception& ex)
|
|
||||||
{
|
|
||||||
d_GDOP = -1; // Geometric DOP
|
|
||||||
d_PDOP = -1; // PDOP
|
|
||||||
d_HDOP = -1; // HDOP
|
|
||||||
d_VDOP = -1; // VDOP
|
|
||||||
d_TDOP = -1; // TDOP
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int Ls_Pvt::set_averaging_depth(int depth)
|
|
||||||
{
|
|
||||||
d_averaging_depth = depth;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
@ -33,144 +33,21 @@
|
|||||||
#define GNSS_SDR_LS_PVT_H_
|
#define GNSS_SDR_LS_PVT_H_
|
||||||
|
|
||||||
|
|
||||||
#include <deque>
|
#include "pvt_solution.h"
|
||||||
#include <armadillo>
|
|
||||||
#include <boost/date_time/posix_time/posix_time.hpp>
|
|
||||||
|
|
||||||
#define PVT_MAX_CHANNELS 24
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Base class for the Least Squares PVT solution
|
* \brief Base class for the Least Squares PVT solution
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
class Ls_Pvt
|
class Ls_Pvt : public Pvt_Solution
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Ls_Pvt();
|
Ls_Pvt();
|
||||||
|
|
||||||
arma::vec leastSquarePos(const arma::mat & satpos, const arma::vec & obs, const arma::mat & w);
|
arma::vec leastSquarePos(const arma::mat & satpos, const arma::vec & obs, const arma::mat & w);
|
||||||
arma::vec rotateSatellite(double traveltime, const arma::vec & X_sat);
|
|
||||||
|
|
||||||
int d_valid_observations; //!< Number of valid pseudorange observations (valid satellites)
|
|
||||||
int d_visible_satellites_IDs[PVT_MAX_CHANNELS]; //!< Array with the IDs of the valid satellites
|
|
||||||
double d_visible_satellites_El[PVT_MAX_CHANNELS]; //!< Array with the LOS Elevation of the valid satellites
|
|
||||||
double d_visible_satellites_Az[PVT_MAX_CHANNELS]; //!< Array with the LOS Azimuth of the valid satellites
|
|
||||||
double d_visible_satellites_Distance[PVT_MAX_CHANNELS]; //!< Array with the LOS Distance of the valid satellites
|
|
||||||
double d_visible_satellites_CN0_dB[PVT_MAX_CHANNELS]; //!< Array with the IDs of the valid satellites
|
|
||||||
|
|
||||||
boost::posix_time::ptime d_position_UTC_time;
|
|
||||||
|
|
||||||
bool b_valid_position;
|
|
||||||
|
|
||||||
double d_latitude_d; //!< Latitude in degrees
|
|
||||||
double d_longitude_d; //!< Longitude in degrees
|
|
||||||
double d_height_m; //!< Height [m]
|
|
||||||
|
|
||||||
//averaging
|
|
||||||
int d_averaging_depth; //!< Length of averaging window
|
|
||||||
std::deque<double> d_hist_latitude_d;
|
|
||||||
std::deque<double> d_hist_longitude_d;
|
|
||||||
std::deque<double> d_hist_height_m;
|
|
||||||
|
|
||||||
double d_avg_latitude_d; //!< Averaged latitude in degrees
|
|
||||||
double d_avg_longitude_d; //!< Averaged longitude in degrees
|
|
||||||
double d_avg_height_m; //!< Averaged height [m]
|
|
||||||
|
|
||||||
double d_x_m;
|
double d_x_m;
|
||||||
double d_y_m;
|
double d_y_m;
|
||||||
double d_z_m;
|
double d_z_m;
|
||||||
|
|
||||||
// DOP estimations
|
|
||||||
arma::mat d_Q;
|
|
||||||
double d_GDOP;
|
|
||||||
double d_PDOP;
|
|
||||||
double d_HDOP;
|
|
||||||
double d_VDOP;
|
|
||||||
double d_TDOP;
|
|
||||||
int compute_DOP(); //!< Compute Dilution Of Precision
|
|
||||||
|
|
||||||
bool d_flag_averaging;
|
|
||||||
|
|
||||||
int set_averaging_depth(int depth);
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Conversion of Cartesian coordinates (X,Y,Z) to geographical
|
|
||||||
* coordinates (d_latitude_d, d_longitude_d, d_height_m) on a selected reference ellipsoid.
|
|
||||||
*
|
|
||||||
* \param[in] X [m] Cartesian coordinate
|
|
||||||
* \param[in] Y [m] Cartesian coordinate
|
|
||||||
* \param[in] Z [m] Cartesian coordinate
|
|
||||||
* \param[in] elipsoid_selection. Choices of Reference Ellipsoid for Geographical Coordinates:
|
|
||||||
* 0 - International Ellipsoid 1924.
|
|
||||||
* 1 - International Ellipsoid 1967.
|
|
||||||
* 2 - World Geodetic System 1972.
|
|
||||||
* 3 - Geodetic Reference System 1980.
|
|
||||||
* 4 - World Geodetic System 1984.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void cart2geo(double X, double Y, double Z, int elipsoid_selection);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Transformation of vector dx into topocentric coordinate system with origin at x
|
|
||||||
*
|
|
||||||
* \param[in] x Vector origin coordinates (in ECEF system [X; Y; Z;])
|
|
||||||
* \param[in] dx Vector ([dX; dY; dZ;]).
|
|
||||||
*
|
|
||||||
* \param[out] D Vector length. Units like the input
|
|
||||||
* \param[out] Az Azimuth from north positive clockwise, degrees
|
|
||||||
* \param[out] El Elevation angle, degrees
|
|
||||||
*
|
|
||||||
* Based on a Matlab function by Kai Borre
|
|
||||||
*/
|
|
||||||
void topocent(double *Az, double *El, double *D, const arma::vec & x, const arma::vec & dx);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Subroutine to calculate geodetic coordinates latitude, longitude,
|
|
||||||
* height given Cartesian coordinates X,Y,Z, and reference ellipsoid
|
|
||||||
* values semi-major axis (a) and the inverse of flattening (finv).
|
|
||||||
*
|
|
||||||
* The output units of angular quantities will be in decimal degrees
|
|
||||||
* (15.5 degrees not 15 deg 30 min). The output units of h will be the
|
|
||||||
* same as the units of X,Y,Z,a.
|
|
||||||
*
|
|
||||||
* \param[in] a - semi-major axis of the reference ellipsoid
|
|
||||||
* \param[in] finv - inverse of flattening of the reference ellipsoid
|
|
||||||
* \param[in] X,Y,Z - Cartesian coordinates
|
|
||||||
*:
|
|
||||||
* \param[out] dphi - latitude
|
|
||||||
* \param[out] dlambda - longitude
|
|
||||||
* \param[out] h - height above reference ellipsoid
|
|
||||||
*
|
|
||||||
* Based in a Matlab function by Kai Borre
|
|
||||||
*/
|
|
||||||
void togeod(double *dphi, double *dlambda, double *h, double a, double finv, double X, double Y, double Z);
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Tropospheric correction
|
|
||||||
*
|
|
||||||
* \param[in] sinel - sin of elevation angle of satellite
|
|
||||||
* \param[in] hsta_km - height of station in km
|
|
||||||
* \param[in] p_mb - atmospheric pressure in mb at height hp_km
|
|
||||||
* \param[in] t_kel - surface temperature in degrees Kelvin at height htkel_km
|
|
||||||
* \param[in] hum - humidity in % at height hhum_km
|
|
||||||
* \param[in] hp_km - height of pressure measurement in km
|
|
||||||
* \param[in] htkel_km - height of temperature measurement in km
|
|
||||||
* \param[in] hhum_km - height of humidity measurement in km
|
|
||||||
*
|
|
||||||
* \param[out] ddr_m - range correction (meters)
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Reference:
|
|
||||||
* Goad, C.C. & Goodman, L. (1974) A Modified Hopfield Tropospheric
|
|
||||||
* Refraction Correction Model. Paper presented at the
|
|
||||||
* American Geophysical Union Annual Fall Meeting, San
|
|
||||||
* Francisco, December 12-17
|
|
||||||
*
|
|
||||||
* Translated to C++ by Carles Fernandez from a Matlab implementation by Kai Borre
|
|
||||||
*/
|
|
||||||
void tropo(double *ddr_m, double sinel, double hsta_km, double p_mb, double t_kel, double hum, double hp_km, double htkel_km, double hhum_km);
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -39,7 +39,7 @@
|
|||||||
#include <boost/date_time/posix_time/posix_time.hpp>
|
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||||
#include <glog/logging.h>
|
#include <glog/logging.h>
|
||||||
#include <gflags/gflags.h>
|
#include <gflags/gflags.h>
|
||||||
#include "GPS_L1_CA.h"
|
|
||||||
|
|
||||||
|
|
||||||
using google::LogMessage;
|
using google::LogMessage;
|
||||||
@ -132,7 +132,7 @@ void Nmea_Printer::close_serial ()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Nmea_Printer::Print_Nmea_Line(const std::shared_ptr<Ls_Pvt>& pvt_data, bool print_average_values)
|
bool Nmea_Printer::Print_Nmea_Line(const std::shared_ptr<Pvt_Solution>& pvt_data, bool print_average_values)
|
||||||
{
|
{
|
||||||
std::string GPRMC;
|
std::string GPRMC;
|
||||||
std::string GPGGA;
|
std::string GPGGA;
|
||||||
|
@ -40,7 +40,7 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "ls_pvt.h"
|
#include "pvt_solution.h"
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -60,7 +60,7 @@ public:
|
|||||||
/*!
|
/*!
|
||||||
* \brief Print NMEA PVT and satellite info to the initialized device
|
* \brief Print NMEA PVT and satellite info to the initialized device
|
||||||
*/
|
*/
|
||||||
bool Print_Nmea_Line(const std::shared_ptr<Ls_Pvt>& position, bool print_average_values);
|
bool Print_Nmea_Line(const std::shared_ptr<Pvt_Solution>& position, bool print_average_values);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Default destructor.
|
* \brief Default destructor.
|
||||||
@ -72,7 +72,7 @@ private:
|
|||||||
std::ofstream nmea_file_descriptor; // Output file stream for NMEA log file
|
std::ofstream nmea_file_descriptor; // Output file stream for NMEA log file
|
||||||
std::string nmea_devname;
|
std::string nmea_devname;
|
||||||
int nmea_dev_descriptor; // NMEA serial device descriptor (i.e. COM port)
|
int nmea_dev_descriptor; // NMEA serial device descriptor (i.e. COM port)
|
||||||
std::shared_ptr<Ls_Pvt> d_PVT_data;
|
std::shared_ptr<Pvt_Solution> d_PVT_data;
|
||||||
int init_serial(std::string serial_device); //serial port control
|
int init_serial(std::string serial_device); //serial port control
|
||||||
void close_serial();
|
void close_serial();
|
||||||
std::string get_GPGGA(); // fix data
|
std::string get_GPGGA(); // fix data
|
||||||
|
548
src/algorithms/PVT/libs/pvt_solution.cc
Normal file
548
src/algorithms/PVT/libs/pvt_solution.cc
Normal file
@ -0,0 +1,548 @@
|
|||||||
|
/*!
|
||||||
|
* \file pvt_solution.cc
|
||||||
|
* \brief Implementation of a base class for a PVT solution
|
||||||
|
* \author Carles Fernandez-Prades, 2015. cfernandez(at)cttc.es
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* -------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010-2015 (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 "pvt_solution.h"
|
||||||
|
#include <exception>
|
||||||
|
#include "GPS_L1_CA.h"
|
||||||
|
#include <gflags/gflags.h>
|
||||||
|
#include <glog/logging.h>
|
||||||
|
|
||||||
|
|
||||||
|
using google::LogMessage;
|
||||||
|
|
||||||
|
DEFINE_bool(tropo, true, "Apply tropospheric correction");
|
||||||
|
|
||||||
|
Pvt_Solution::Pvt_Solution()
|
||||||
|
{
|
||||||
|
d_latitude_d = 0.0;
|
||||||
|
d_longitude_d = 0.0;
|
||||||
|
d_height_m = 0.0;
|
||||||
|
d_avg_latitude_d = 0.0;
|
||||||
|
d_avg_longitude_d = 0.0;
|
||||||
|
d_avg_height_m = 0.0;
|
||||||
|
d_GDOP = 0.0;
|
||||||
|
d_PDOP = 0.0;
|
||||||
|
d_HDOP = 0.0;
|
||||||
|
d_VDOP = 0.0;
|
||||||
|
d_TDOP = 0.0;
|
||||||
|
d_flag_averaging = false;
|
||||||
|
b_valid_position = false;
|
||||||
|
d_averaging_depth = 0;
|
||||||
|
d_valid_observations = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
arma::vec Pvt_Solution::rotateSatellite(double const traveltime, const arma::vec & X_sat)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Returns rotated satellite ECEF coordinates due to Earth
|
||||||
|
* rotation during signal travel time
|
||||||
|
*
|
||||||
|
* Inputs:
|
||||||
|
* travelTime - signal travel time
|
||||||
|
* X_sat - satellite's ECEF coordinates
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* X_sat_rot - rotated satellite's coordinates (ECEF)
|
||||||
|
*/
|
||||||
|
|
||||||
|
//--- Find rotation angle --------------------------------------------------
|
||||||
|
double omegatau;
|
||||||
|
omegatau = OMEGA_EARTH_DOT * traveltime;
|
||||||
|
|
||||||
|
//--- Build a rotation matrix ----------------------------------------------
|
||||||
|
arma::mat R3 = arma::zeros(3,3);
|
||||||
|
R3(0, 0) = cos(omegatau);
|
||||||
|
R3(0, 1) = sin(omegatau);
|
||||||
|
R3(0, 2) = 0.0;
|
||||||
|
R3(1, 0) = -sin(omegatau);
|
||||||
|
R3(1, 1) = cos(omegatau);
|
||||||
|
R3(1, 2) = 0.0;
|
||||||
|
R3(2, 0) = 0.0;
|
||||||
|
R3(2, 1) = 0.0;
|
||||||
|
R3(2, 2) = 1;
|
||||||
|
|
||||||
|
//--- Do the rotation ------------------------------------------------------
|
||||||
|
arma::vec X_sat_rot;
|
||||||
|
X_sat_rot = R3 * X_sat;
|
||||||
|
return X_sat_rot;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int Pvt_Solution::cart2geo(double X, double Y, double Z, int elipsoid_selection)
|
||||||
|
{
|
||||||
|
/* Conversion of Cartesian coordinates (X,Y,Z) to geographical
|
||||||
|
coordinates (latitude, longitude, h) on a selected reference ellipsoid.
|
||||||
|
|
||||||
|
Choices of Reference Ellipsoid for Geographical Coordinates
|
||||||
|
0. International Ellipsoid 1924
|
||||||
|
1. International Ellipsoid 1967
|
||||||
|
2. World Geodetic System 1972
|
||||||
|
3. Geodetic Reference System 1980
|
||||||
|
4. World Geodetic System 1984
|
||||||
|
*/
|
||||||
|
|
||||||
|
const double a[5] = {6378388.0, 6378160.0, 6378135.0, 6378137.0, 6378137.0};
|
||||||
|
const double f[5] = {1.0 / 297.0, 1.0 / 298.247, 1.0 / 298.26, 1.0 / 298.257222101, 1.0 / 298.257223563};
|
||||||
|
|
||||||
|
double lambda = atan2(Y, X);
|
||||||
|
double ex2 = (2.0 - f[elipsoid_selection]) * f[elipsoid_selection] / ((1.0 - f[elipsoid_selection]) * (1.0 - f[elipsoid_selection]));
|
||||||
|
double c = a[elipsoid_selection] * sqrt(1.0 + ex2);
|
||||||
|
double phi = atan(Z / ((sqrt(X * X + Y * Y) * (1.0 - (2.0 - f[elipsoid_selection])) * f[elipsoid_selection])));
|
||||||
|
|
||||||
|
double h = 0.1;
|
||||||
|
double oldh = 0.0;
|
||||||
|
double N;
|
||||||
|
int iterations = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
oldh = h;
|
||||||
|
N = c / sqrt(1 + ex2 * (cos(phi) * cos(phi)));
|
||||||
|
phi = atan(Z / ((sqrt(X * X + Y * Y) * (1.0 - (2.0 - f[elipsoid_selection]) * f[elipsoid_selection] * N / (N + h) ))));
|
||||||
|
h = sqrt(X * X + Y * Y) / cos(phi) - N;
|
||||||
|
iterations = iterations + 1;
|
||||||
|
if (iterations > 100)
|
||||||
|
{
|
||||||
|
LOG(WARNING) << "Failed to approximate h with desired precision. h-oldh= " << h - oldh;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (std::abs(h - oldh) > 1.0e-12);
|
||||||
|
d_latitude_d = phi * 180.0 / GPS_PI;
|
||||||
|
d_longitude_d = lambda * 180.0 / GPS_PI;
|
||||||
|
d_height_m = h;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int Pvt_Solution::togeod(double *dphi, double *dlambda, double *h, double a, double finv, double X, double Y, double Z)
|
||||||
|
{
|
||||||
|
/* Subroutine to calculate geodetic coordinates latitude, longitude,
|
||||||
|
height given Cartesian coordinates X,Y,Z, and reference ellipsoid
|
||||||
|
values semi-major axis (a) and the inverse of flattening (finv).
|
||||||
|
|
||||||
|
The output units of angular quantities will be in decimal degrees
|
||||||
|
(15.5 degrees not 15 deg 30 min). The output units of h will be the
|
||||||
|
same as the units of X,Y,Z,a.
|
||||||
|
|
||||||
|
Inputs:
|
||||||
|
a - semi-major axis of the reference ellipsoid
|
||||||
|
finv - inverse of flattening of the reference ellipsoid
|
||||||
|
X,Y,Z - Cartesian coordinates
|
||||||
|
|
||||||
|
Outputs:
|
||||||
|
dphi - latitude
|
||||||
|
dlambda - longitude
|
||||||
|
h - height above reference ellipsoid
|
||||||
|
|
||||||
|
Based in a Matlab function by Kai Borre
|
||||||
|
*/
|
||||||
|
|
||||||
|
*h = 0;
|
||||||
|
double tolsq = 1.e-10; // tolerance to accept convergence
|
||||||
|
int maxit = 10; // max number of iterations
|
||||||
|
double rtd = 180.0 / GPS_PI;
|
||||||
|
|
||||||
|
// compute square of eccentricity
|
||||||
|
double esq;
|
||||||
|
if (finv < 1.0E-20)
|
||||||
|
{
|
||||||
|
esq = 0.0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
esq = (2.0 - 1.0 / finv) / finv;
|
||||||
|
}
|
||||||
|
|
||||||
|
// first guess
|
||||||
|
double P = sqrt(X * X + Y * Y); // P is distance from spin axis
|
||||||
|
|
||||||
|
//direct calculation of longitude
|
||||||
|
if (P > 1.0E-20)
|
||||||
|
{
|
||||||
|
*dlambda = atan2(Y, X) * rtd;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*dlambda = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// correct longitude bound
|
||||||
|
if (*dlambda < 0)
|
||||||
|
{
|
||||||
|
*dlambda = *dlambda + 360.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
double r = sqrt(P * P + Z * Z); // r is distance from origin (0,0,0)
|
||||||
|
|
||||||
|
double sinphi;
|
||||||
|
if (r > 1.0E-20)
|
||||||
|
{
|
||||||
|
sinphi = Z/r;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sinphi = 0.0;
|
||||||
|
}
|
||||||
|
*dphi = asin(sinphi);
|
||||||
|
|
||||||
|
// initial value of height = distance from origin minus
|
||||||
|
// approximate distance from origin to surface of ellipsoid
|
||||||
|
if (r < 1.0E-20)
|
||||||
|
{
|
||||||
|
*h = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*h = r - a * (1 - sinphi * sinphi/finv);
|
||||||
|
|
||||||
|
// iterate
|
||||||
|
double cosphi;
|
||||||
|
double N_phi;
|
||||||
|
double dP;
|
||||||
|
double dZ;
|
||||||
|
double oneesq = 1.0 - esq;
|
||||||
|
|
||||||
|
for (int i = 0; i < maxit; i++)
|
||||||
|
{
|
||||||
|
sinphi = sin(*dphi);
|
||||||
|
cosphi = cos(*dphi);
|
||||||
|
|
||||||
|
// compute radius of curvature in prime vertical direction
|
||||||
|
N_phi = a / sqrt(1 - esq * sinphi * sinphi);
|
||||||
|
|
||||||
|
// compute residuals in P and Z
|
||||||
|
dP = P - (N_phi + (*h)) * cosphi;
|
||||||
|
dZ = Z - (N_phi * oneesq + (*h)) * sinphi;
|
||||||
|
|
||||||
|
// update height and latitude
|
||||||
|
*h = *h + (sinphi * dZ + cosphi * dP);
|
||||||
|
*dphi = *dphi + (cosphi * dZ - sinphi * dP)/(N_phi + (*h));
|
||||||
|
|
||||||
|
// test for convergence
|
||||||
|
if ((dP * dP + dZ * dZ) < tolsq)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i == (maxit - 1))
|
||||||
|
{
|
||||||
|
LOG(WARNING) << "The computation of geodetic coordinates did not converge";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*dphi = (*dphi) * rtd;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int Pvt_Solution::tropo(double *ddr_m, double sinel, double hsta_km, double p_mb, double t_kel, double hum, double hp_km, double htkel_km, double hhum_km)
|
||||||
|
{
|
||||||
|
/* Inputs:
|
||||||
|
sinel - sin of elevation angle of satellite
|
||||||
|
hsta_km - height of station in km
|
||||||
|
p_mb - atmospheric pressure in mb at height hp_km
|
||||||
|
t_kel - surface temperature in degrees Kelvin at height htkel_km
|
||||||
|
hum - humidity in % at height hhum_km
|
||||||
|
hp_km - height of pressure measurement in km
|
||||||
|
htkel_km - height of temperature measurement in km
|
||||||
|
hhum_km - height of humidity measurement in km
|
||||||
|
|
||||||
|
Outputs:
|
||||||
|
ddr_m - range correction (meters)
|
||||||
|
|
||||||
|
Reference
|
||||||
|
Goad, C.C. & Goodman, L. (1974) A Modified Hopfield Tropospheric
|
||||||
|
Refraction Correction Model. Paper presented at the
|
||||||
|
American Geophysical Union Annual Fall Meeting, San
|
||||||
|
Francisco, December 12-17
|
||||||
|
|
||||||
|
Translated to C++ by Carles Fernandez from a Matlab implementation by Kai Borre
|
||||||
|
*/
|
||||||
|
|
||||||
|
const double a_e = 6378.137; // semi-major axis of earth ellipsoid
|
||||||
|
const double b0 = 7.839257e-5;
|
||||||
|
const double tlapse = -6.5;
|
||||||
|
const double em = -978.77 / (2.8704e6 * tlapse * 1.0e-5);
|
||||||
|
|
||||||
|
double tkhum = t_kel + tlapse * (hhum_km - htkel_km);
|
||||||
|
double atkel = 7.5 * (tkhum - 273.15) / (237.3 + tkhum - 273.15);
|
||||||
|
double e0 = 0.0611 * hum * pow(10, atkel);
|
||||||
|
double tksea = t_kel - tlapse * htkel_km;
|
||||||
|
double tkelh = tksea + tlapse * hhum_km;
|
||||||
|
double e0sea = e0 * pow((tksea / tkelh), (4 * em));
|
||||||
|
double tkelp = tksea + tlapse * hp_km;
|
||||||
|
double psea = p_mb * pow((tksea / tkelp), em);
|
||||||
|
|
||||||
|
if(sinel < 0) { sinel = 0.0; }
|
||||||
|
|
||||||
|
double tropo_delay = 0.0;
|
||||||
|
bool done = false;
|
||||||
|
double refsea = 77.624e-6 / tksea;
|
||||||
|
double htop = 1.1385e-5 / refsea;
|
||||||
|
refsea = refsea * psea;
|
||||||
|
double ref = refsea * pow(((htop - hsta_km) / htop), 4);
|
||||||
|
|
||||||
|
double a;
|
||||||
|
double b;
|
||||||
|
double rtop;
|
||||||
|
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
rtop = pow((a_e + htop), 2) - pow((a_e + hsta_km), 2) * (1 - pow(sinel, 2));
|
||||||
|
|
||||||
|
// check to see if geometry is crazy
|
||||||
|
if(rtop < 0) { rtop = 0; }
|
||||||
|
|
||||||
|
rtop = sqrt(rtop) - (a_e + hsta_km) * sinel;
|
||||||
|
|
||||||
|
a = -sinel / (htop - hsta_km);
|
||||||
|
b = -b0 * (1 - pow(sinel,2)) / (htop - hsta_km);
|
||||||
|
|
||||||
|
arma::vec rn = arma::vec(8);
|
||||||
|
rn.zeros();
|
||||||
|
|
||||||
|
for(int i = 0; i<8; i++)
|
||||||
|
{
|
||||||
|
rn(i) = pow(rtop, (i+1+1));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
arma::rowvec alpha = {2 * a, 2 * pow(a, 2) + 4 * b /3, a * (pow(a, 2) + 3 * b),
|
||||||
|
pow(a, 4)/5 + 2.4 * pow(a, 2) * b + 1.2 * pow(b, 2), 2 * a * b * (pow(a, 2) + 3 * b)/3,
|
||||||
|
pow(b, 2) * (6 * pow(a, 2) + 4 * b) * 1.428571e-1, 0, 0};
|
||||||
|
|
||||||
|
if(pow(b, 2) > 1.0e-35)
|
||||||
|
{
|
||||||
|
alpha(6) = a * pow(b, 3) /2;
|
||||||
|
alpha(7) = pow(b, 4) / 9;
|
||||||
|
}
|
||||||
|
|
||||||
|
double dr = rtop;
|
||||||
|
arma::mat aux_ = alpha * rn;
|
||||||
|
dr = dr + aux_(0, 0);
|
||||||
|
tropo_delay = tropo_delay + dr * ref * 1000;
|
||||||
|
|
||||||
|
if(done == true)
|
||||||
|
{
|
||||||
|
*ddr_m = tropo_delay;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
done = true;
|
||||||
|
refsea = (371900.0e-6 / tksea - 12.92e-6) / tksea;
|
||||||
|
htop = 1.1385e-5 * (1255 / tksea + 0.05) / refsea;
|
||||||
|
ref = refsea * e0sea * pow(((htop - hsta_km) / htop), 4);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Pvt_Solution::topocent(double *Az, double *El, double *D, const arma::vec & x, const arma::vec & dx)
|
||||||
|
{
|
||||||
|
/* Transformation of vector dx into topocentric coordinate
|
||||||
|
system with origin at x
|
||||||
|
Inputs:
|
||||||
|
x - vector origin coordinates (in ECEF system [X; Y; Z;])
|
||||||
|
dx - vector ([dX; dY; dZ;]).
|
||||||
|
|
||||||
|
Outputs:
|
||||||
|
D - vector length. Units like the input
|
||||||
|
Az - azimuth from north positive clockwise, degrees
|
||||||
|
El - elevation angle, degrees
|
||||||
|
|
||||||
|
Based on a Matlab function by Kai Borre
|
||||||
|
*/
|
||||||
|
|
||||||
|
double lambda;
|
||||||
|
double phi;
|
||||||
|
double h;
|
||||||
|
double dtr = GPS_PI / 180.0;
|
||||||
|
double a = 6378137.0; // semi-major axis of the reference ellipsoid WGS-84
|
||||||
|
double finv = 298.257223563; // inverse of flattening of the reference ellipsoid WGS-84
|
||||||
|
|
||||||
|
// Transform x into geodetic coordinates
|
||||||
|
Pvt_Solution::togeod(&phi, &lambda, &h, a, finv, x(0), x(1), x(2));
|
||||||
|
|
||||||
|
double cl = cos(lambda * dtr);
|
||||||
|
double sl = sin(lambda * dtr);
|
||||||
|
double cb = cos(phi * dtr);
|
||||||
|
double sb = sin(phi * dtr);
|
||||||
|
|
||||||
|
arma::mat F = arma::zeros(3,3);
|
||||||
|
|
||||||
|
F(0,0) = -sl;
|
||||||
|
F(0,1) = -sb * cl;
|
||||||
|
F(0,2) = cb * cl;
|
||||||
|
|
||||||
|
F(1,0) = cl;
|
||||||
|
F(1,1) = -sb * sl;
|
||||||
|
F(1,2) = cb * sl;
|
||||||
|
|
||||||
|
F(2,0) = 0;
|
||||||
|
F(2,1) = cb;
|
||||||
|
F(2,2) = sb;
|
||||||
|
|
||||||
|
arma::vec local_vector;
|
||||||
|
|
||||||
|
local_vector = arma::htrans(F) * dx;
|
||||||
|
|
||||||
|
double E = local_vector(0);
|
||||||
|
double N = local_vector(1);
|
||||||
|
double U = local_vector(2);
|
||||||
|
|
||||||
|
double hor_dis;
|
||||||
|
hor_dis = sqrt(E * E + N * N);
|
||||||
|
|
||||||
|
if (hor_dis < 1.0E-20)
|
||||||
|
{
|
||||||
|
*Az = 0;
|
||||||
|
*El = 90;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*Az = atan2(E, N) / dtr;
|
||||||
|
*El = atan2(U, hor_dis) / dtr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*Az < 0)
|
||||||
|
{
|
||||||
|
*Az = *Az + 360.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
*D = sqrt(dx(0) * dx(0) + dx(1) * dx(1) + dx(2) * dx(2));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int Pvt_Solution::compute_DOP()
|
||||||
|
{
|
||||||
|
// ###### Compute DOPs ########
|
||||||
|
|
||||||
|
// 1- Rotation matrix from ECEF coordinates to ENU coordinates
|
||||||
|
// ref: http://www.navipedia.net/index.php/Transformations_between_ECEF_and_ENU_coordinates
|
||||||
|
arma::mat F = arma::zeros(3,3);
|
||||||
|
F(0,0) = -sin(GPS_TWO_PI * (d_longitude_d/360.0));
|
||||||
|
F(0,1) = -sin(GPS_TWO_PI * (d_latitude_d/360.0)) * cos(GPS_TWO_PI * (d_longitude_d/360.0));
|
||||||
|
F(0,2) = cos(GPS_TWO_PI * (d_latitude_d/360.0)) * cos(GPS_TWO_PI * (d_longitude_d/360.0));
|
||||||
|
|
||||||
|
F(1,0) = cos((GPS_TWO_PI * d_longitude_d)/360.0);
|
||||||
|
F(1,1) = -sin((GPS_TWO_PI * d_latitude_d)/360.0) * sin((GPS_TWO_PI * d_longitude_d)/360.0);
|
||||||
|
F(1,2) = cos((GPS_TWO_PI * d_latitude_d/360.0)) * sin((GPS_TWO_PI * d_longitude_d)/360.0);
|
||||||
|
|
||||||
|
F(2,0) = 0;
|
||||||
|
F(2,1) = cos((GPS_TWO_PI * d_latitude_d)/360.0);
|
||||||
|
F(2,2) = sin((GPS_TWO_PI * d_latitude_d/360.0));
|
||||||
|
|
||||||
|
// 2- Apply the rotation to the latest covariance matrix (available in ECEF from LS)
|
||||||
|
arma::mat Q_ECEF = d_Q.submat(0, 0, 2, 2);
|
||||||
|
arma::mat DOP_ENU = arma::zeros(3, 3);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
DOP_ENU = arma::htrans(F) * Q_ECEF * F;
|
||||||
|
d_GDOP = sqrt(arma::trace(DOP_ENU)); // Geometric DOP
|
||||||
|
d_PDOP = sqrt(DOP_ENU(0, 0) + DOP_ENU(1, 1) + DOP_ENU(2, 2));// PDOP
|
||||||
|
d_HDOP = sqrt(DOP_ENU(0, 0) + DOP_ENU(1, 1)); // HDOP
|
||||||
|
d_VDOP = sqrt(DOP_ENU(2, 2)); // VDOP
|
||||||
|
d_TDOP = sqrt(d_Q(3, 3)); // TDOP
|
||||||
|
}
|
||||||
|
catch(std::exception& ex)
|
||||||
|
{
|
||||||
|
d_GDOP = -1; // Geometric DOP
|
||||||
|
d_PDOP = -1; // PDOP
|
||||||
|
d_HDOP = -1; // HDOP
|
||||||
|
d_VDOP = -1; // VDOP
|
||||||
|
d_TDOP = -1; // TDOP
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int Pvt_Solution::set_averaging_depth(int depth)
|
||||||
|
{
|
||||||
|
d_averaging_depth = depth;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int Pvt_Solution::pos_averaging(bool flag_averaring)
|
||||||
|
{
|
||||||
|
// MOVING AVERAGE PVT
|
||||||
|
bool avg = flag_averaring;
|
||||||
|
if (avg == true)
|
||||||
|
{
|
||||||
|
if (d_hist_longitude_d.size() == (unsigned int)d_averaging_depth)
|
||||||
|
{
|
||||||
|
// Pop oldest value
|
||||||
|
d_hist_longitude_d.pop_back();
|
||||||
|
d_hist_latitude_d.pop_back();
|
||||||
|
d_hist_height_m.pop_back();
|
||||||
|
// Push new values
|
||||||
|
d_hist_longitude_d.push_front(d_longitude_d);
|
||||||
|
d_hist_latitude_d.push_front(d_latitude_d);
|
||||||
|
d_hist_height_m.push_front(d_height_m);
|
||||||
|
|
||||||
|
d_avg_latitude_d = 0;
|
||||||
|
d_avg_longitude_d = 0;
|
||||||
|
d_avg_height_m = 0;
|
||||||
|
for (unsigned int i = 0; i < d_hist_longitude_d.size(); i++)
|
||||||
|
{
|
||||||
|
d_avg_latitude_d = d_avg_latitude_d + d_hist_latitude_d.at(i);
|
||||||
|
d_avg_longitude_d = d_avg_longitude_d + d_hist_longitude_d.at(i);
|
||||||
|
d_avg_height_m = d_avg_height_m + d_hist_height_m.at(i);
|
||||||
|
}
|
||||||
|
d_avg_latitude_d = d_avg_latitude_d / static_cast<double>(d_averaging_depth);
|
||||||
|
d_avg_longitude_d = d_avg_longitude_d / static_cast<double>(d_averaging_depth);
|
||||||
|
d_avg_height_m = d_avg_height_m / static_cast<double>(d_averaging_depth);
|
||||||
|
b_valid_position = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//int current_depth=d_hist_longitude_d.size();
|
||||||
|
// Push new values
|
||||||
|
d_hist_longitude_d.push_front(d_longitude_d);
|
||||||
|
d_hist_latitude_d.push_front(d_latitude_d);
|
||||||
|
d_hist_height_m.push_front(d_height_m);
|
||||||
|
|
||||||
|
d_avg_latitude_d = d_latitude_d;
|
||||||
|
d_avg_longitude_d = d_longitude_d;
|
||||||
|
d_avg_height_m = d_height_m;
|
||||||
|
b_valid_position = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
b_valid_position = true;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
170
src/algorithms/PVT/libs/pvt_solution.h
Normal file
170
src/algorithms/PVT/libs/pvt_solution.h
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
/*!
|
||||||
|
* \file pvt_solution.h
|
||||||
|
* \brief Interface of a base class for a PVT solution
|
||||||
|
* \author Carles Fernandez-Prades, 2015. cfernandez(at)cttc.es
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* -------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010-2015 (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/>.
|
||||||
|
*
|
||||||
|
* -------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GNSS_SDR_PVT_SOLUTION_H_
|
||||||
|
#define GNSS_SDR_PVT_SOLUTION_H_
|
||||||
|
|
||||||
|
|
||||||
|
#include <deque>
|
||||||
|
#include <armadillo>
|
||||||
|
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||||
|
|
||||||
|
#define PVT_MAX_CHANNELS 24
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Base class for a PVT solution
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class Pvt_Solution
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Pvt_Solution();
|
||||||
|
|
||||||
|
double d_latitude_d;
|
||||||
|
double d_longitude_d;
|
||||||
|
double d_height_m;
|
||||||
|
|
||||||
|
boost::posix_time::ptime d_position_UTC_time;
|
||||||
|
|
||||||
|
bool b_valid_position;
|
||||||
|
|
||||||
|
int d_valid_observations; //!< Number of valid pseudorange observations (valid satellites)
|
||||||
|
int d_visible_satellites_IDs[PVT_MAX_CHANNELS] = {}; //!< Array with the IDs of the valid satellites
|
||||||
|
double d_visible_satellites_El[PVT_MAX_CHANNELS] = {}; //!< Array with the LOS Elevation of the valid satellites
|
||||||
|
double d_visible_satellites_Az[PVT_MAX_CHANNELS] = {}; //!< Array with the LOS Azimuth of the valid satellites
|
||||||
|
double d_visible_satellites_Distance[PVT_MAX_CHANNELS] = {}; //!< Array with the LOS Distance of the valid satellites
|
||||||
|
double d_visible_satellites_CN0_dB[PVT_MAX_CHANNELS] = {}; //!< Array with the IDs of the valid satellites
|
||||||
|
|
||||||
|
//averaging
|
||||||
|
int d_averaging_depth; //!< Length of averaging window
|
||||||
|
std::deque<double> d_hist_latitude_d;
|
||||||
|
std::deque<double> d_hist_longitude_d;
|
||||||
|
std::deque<double> d_hist_height_m;
|
||||||
|
|
||||||
|
double d_avg_latitude_d; //!< Averaged latitude in degrees
|
||||||
|
double d_avg_longitude_d; //!< Averaged longitude in degrees
|
||||||
|
double d_avg_height_m; //!< Averaged height [m]
|
||||||
|
int pos_averaging(bool flag_averaging);
|
||||||
|
|
||||||
|
// DOP estimations
|
||||||
|
arma::mat d_Q;
|
||||||
|
double d_GDOP;
|
||||||
|
double d_PDOP;
|
||||||
|
double d_HDOP;
|
||||||
|
double d_VDOP;
|
||||||
|
double d_TDOP;
|
||||||
|
int compute_DOP(); //!< Compute Dilution Of Precision
|
||||||
|
|
||||||
|
bool d_flag_averaging;
|
||||||
|
|
||||||
|
int set_averaging_depth(int depth);
|
||||||
|
|
||||||
|
arma::vec rotateSatellite(double traveltime, const arma::vec & X_sat);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Conversion of Cartesian coordinates (X,Y,Z) to geographical
|
||||||
|
* coordinates (d_latitude_d, d_longitude_d, d_height_m) on a selected reference ellipsoid.
|
||||||
|
*
|
||||||
|
* \param[in] X [m] Cartesian coordinate
|
||||||
|
* \param[in] Y [m] Cartesian coordinate
|
||||||
|
* \param[in] Z [m] Cartesian coordinate
|
||||||
|
* \param[in] elipsoid_selection. Choices of Reference Ellipsoid for Geographical Coordinates:
|
||||||
|
* 0 - International Ellipsoid 1924.
|
||||||
|
* 1 - International Ellipsoid 1967.
|
||||||
|
* 2 - World Geodetic System 1972.
|
||||||
|
* 3 - Geodetic Reference System 1980.
|
||||||
|
* 4 - World Geodetic System 1984.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int cart2geo(double X, double Y, double Z, int elipsoid_selection);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Transformation of vector dx into topocentric coordinate system with origin at x
|
||||||
|
*
|
||||||
|
* \param[in] x Vector origin coordinates (in ECEF system [X; Y; Z;])
|
||||||
|
* \param[in] dx Vector ([dX; dY; dZ;]).
|
||||||
|
*
|
||||||
|
* \param[out] D Vector length. Units like the input
|
||||||
|
* \param[out] Az Azimuth from north positive clockwise, degrees
|
||||||
|
* \param[out] El Elevation angle, degrees
|
||||||
|
*
|
||||||
|
* Based on a Matlab function by Kai Borre
|
||||||
|
*/
|
||||||
|
int topocent(double *Az, double *El, double *D, const arma::vec & x, const arma::vec & dx);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Subroutine to calculate geodetic coordinates latitude, longitude,
|
||||||
|
* height given Cartesian coordinates X,Y,Z, and reference ellipsoid
|
||||||
|
* values semi-major axis (a) and the inverse of flattening (finv).
|
||||||
|
*
|
||||||
|
* The output units of angular quantities will be in decimal degrees
|
||||||
|
* (15.5 degrees not 15 deg 30 min). The output units of h will be the
|
||||||
|
* same as the units of X,Y,Z,a.
|
||||||
|
*
|
||||||
|
* \param[in] a - semi-major axis of the reference ellipsoid
|
||||||
|
* \param[in] finv - inverse of flattening of the reference ellipsoid
|
||||||
|
* \param[in] X,Y,Z - Cartesian coordinates
|
||||||
|
*
|
||||||
|
* \param[out] dphi - latitude
|
||||||
|
* \param[out] dlambda - longitude
|
||||||
|
* \param[out] h - height above reference ellipsoid
|
||||||
|
*
|
||||||
|
* Based in a Matlab function by Kai Borre
|
||||||
|
*/
|
||||||
|
int togeod(double *dphi, double *dlambda, double *h, double a, double finv, double X, double Y, double Z);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Tropospheric correction
|
||||||
|
*
|
||||||
|
* \param[in] sinel - sin of elevation angle of satellite
|
||||||
|
* \param[in] hsta_km - height of station in km
|
||||||
|
* \param[in] p_mb - atmospheric pressure in mb at height hp_km
|
||||||
|
* \param[in] t_kel - surface temperature in degrees Kelvin at height htkel_km
|
||||||
|
* \param[in] hum - humidity in % at height hhum_km
|
||||||
|
* \param[in] hp_km - height of pressure measurement in km
|
||||||
|
* \param[in] htkel_km - height of temperature measurement in km
|
||||||
|
* \param[in] hhum_km - height of humidity measurement in km
|
||||||
|
*
|
||||||
|
* \param[out] ddr_m - range correction (meters)
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Reference:
|
||||||
|
* Goad, C.C. & Goodman, L. (1974) A Modified Hopfield Tropospheric
|
||||||
|
* Refraction Correction Model. Paper presented at the
|
||||||
|
* American Geophysical Union Annual Fall Meeting, San
|
||||||
|
* Francisco, December 12-17
|
||||||
|
*
|
||||||
|
* Translated to C++ by Carles Fernandez from a Matlab implementation by Kai Borre
|
||||||
|
*/
|
||||||
|
int tropo(double *ddr_m, double sinel, double hsta_km, double p_mb, double t_kel, double hum, double hp_km, double htkel_km, double hhum_km);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user