[hamradio-commits] [gnss-sdr] 33/126: Refactoring PVT solution library and adding a GeoJSON format printer

Carles Fernandez carles_fernandez-guest at moszumanska.debian.org
Sat Dec 26 18:37:58 UTC 2015


This is an automated email from the git hooks/post-receive script.

carles_fernandez-guest pushed a commit to branch next
in repository gnss-sdr.

commit f68a1fe9bccfb0f8962bebf4d773d49d763668b7
Author: Carles Fernandez <carles.fernandez at gmail.com>
Date:   Sat Nov 14 20:41:28 2015 +0100

    Refactoring PVT solution library and adding a GeoJSON format printer
---
 .../PVT/gnuradio_blocks/galileo_e1_pvt_cc.cc       |  13 +-
 .../PVT/gnuradio_blocks/galileo_e1_pvt_cc.h        |   3 +
 .../PVT/gnuradio_blocks/gps_l1_ca_pvt_cc.cc        |  14 +-
 .../PVT/gnuradio_blocks/gps_l1_ca_pvt_cc.h         |   4 +-
 .../PVT/gnuradio_blocks/hybrid_pvt_cc.cc           |  13 +-
 src/algorithms/PVT/gnuradio_blocks/hybrid_pvt_cc.h |   3 +
 src/algorithms/PVT/libs/CMakeLists.txt             |   1 +
 src/algorithms/PVT/libs/galileo_e1_ls_pvt.cc       |  52 +--
 src/algorithms/PVT/libs/geojson_printer.cc         |  37 +-
 src/algorithms/PVT/libs/geojson_printer.h          |   6 +-
 src/algorithms/PVT/libs/gps_l1_ca_ls_pvt.cc        |  63 +--
 src/algorithms/PVT/libs/hybrid_ls_pvt.cc           |  68 +---
 src/algorithms/PVT/libs/kml_printer.cc             |   4 +-
 src/algorithms/PVT/libs/kml_printer.h              |   4 +-
 src/algorithms/PVT/libs/ls_pvt.cc                  | 453 +--------------------
 src/algorithms/PVT/libs/ls_pvt.h                   | 127 +-----
 src/algorithms/PVT/libs/nmea_printer.cc            |   4 +-
 src/algorithms/PVT/libs/nmea_printer.h             |   6 +-
 .../PVT/libs/{ls_pvt.cc => pvt_solution.cc}        | 203 ++++-----
 src/algorithms/PVT/libs/pvt_solution.h             | 170 ++++++++
 20 files changed, 353 insertions(+), 895 deletions(-)

diff --git a/src/algorithms/PVT/gnuradio_blocks/galileo_e1_pvt_cc.cc b/src/algorithms/PVT/gnuradio_blocks/galileo_e1_pvt_cc.cc
index bd13684..310866d 100644
--- a/src/algorithms/PVT/gnuradio_blocks/galileo_e1_pvt_cc.cc
+++ b/src/algorithms/PVT/gnuradio_blocks/galileo_e1_pvt_cc.cc
@@ -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->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
     d_nmea_printer = std::make_shared<Nmea_Printer>(nmea_dump_filename, flag_nmea_tty_port, nmea_dump_devname);
     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)
                         {
                             d_kml_dump->print_position(d_ls_pvt, d_flag_averaging);
-                            //ToDo: Implement Galileo RINEX and Galileo NMEA outputs
-                            //   d_nmea_printer->Print_Nmea_Line(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);
+
                             if (!b_rinex_header_writen)
                                 {
                                     std::map<int,Galileo_Ephemeris>::iterator galileo_ephemeris_iter;
diff --git a/src/algorithms/PVT/gnuradio_blocks/galileo_e1_pvt_cc.h b/src/algorithms/PVT/gnuradio_blocks/galileo_e1_pvt_cc.h
index 02b910f..993c5ad 100644
--- a/src/algorithms/PVT/gnuradio_blocks/galileo_e1_pvt_cc.h
+++ b/src/algorithms/PVT/gnuradio_blocks/galileo_e1_pvt_cc.h
@@ -46,6 +46,7 @@
 #include "nmea_printer.h"
 #include "kml_printer.h"
 #include "rinex_printer.h"
+#include "geojson_printer.h"
 #include "galileo_e1_ls_pvt.h"
 #include "Galileo_E1.h"
 
@@ -108,6 +109,8 @@ private:
     long unsigned int d_last_sample_nav_output;
     std::shared_ptr<Kml_Printer> d_kml_dump;
     std::shared_ptr<Nmea_Printer> d_nmea_printer;
+    std::shared_ptr<GeoJSON_Printer> d_geojson_printer;
+
     double d_rx_time;
     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);
diff --git a/src/algorithms/PVT/gnuradio_blocks/gps_l1_ca_pvt_cc.cc b/src/algorithms/PVT/gnuradio_blocks/gps_l1_ca_pvt_cc.cc
index 7ad3e2d..9fa67eb 100644
--- a/src/algorithms/PVT/gnuradio_blocks/gps_l1_ca_pvt_cc.cc
+++ b/src/algorithms/PVT/gnuradio_blocks/gps_l1_ca_pvt_cc.cc
@@ -87,8 +87,15 @@ gps_l1_ca_pvt_cc::gps_l1_ca_pvt_cc(unsigned int nchannels,
     std::string kml_dump_filename;
     kml_dump_filename = d_dump_filename;
     kml_dump_filename.append(".kml");
-    d_kml_dump = std::make_shared<Kml_Printer>();
-    d_kml_dump->set_headers(kml_dump_filename);
+    d_kml_printer = std::make_shared<Kml_Printer>();
+    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
     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);
                     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);
 
                             if (!b_rinex_header_writen)
diff --git a/src/algorithms/PVT/gnuradio_blocks/gps_l1_ca_pvt_cc.h b/src/algorithms/PVT/gnuradio_blocks/gps_l1_ca_pvt_cc.h
index 645760e..9764046 100644
--- a/src/algorithms/PVT/gnuradio_blocks/gps_l1_ca_pvt_cc.h
+++ b/src/algorithms/PVT/gnuradio_blocks/gps_l1_ca_pvt_cc.h
@@ -45,6 +45,7 @@
 #include "nmea_printer.h"
 #include "kml_printer.h"
 #include "rinex_printer.h"
+#include "geojson_printer.h"
 #include "gps_l1_ca_ls_pvt.h"
 #include "GPS_L1_CA.h"
 
@@ -107,8 +108,9 @@ private:
     int d_display_rate_ms;
     long unsigned int d_sample_counter;
     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<GeoJSON_Printer> d_geojson_printer;
     double d_rx_time;
     std::shared_ptr<gps_l1_ca_ls_pvt> d_ls_pvt;
 
diff --git a/src/algorithms/PVT/gnuradio_blocks/hybrid_pvt_cc.cc b/src/algorithms/PVT/gnuradio_blocks/hybrid_pvt_cc.cc
index 601919e..cfa5fa4 100644
--- a/src/algorithms/PVT/gnuradio_blocks/hybrid_pvt_cc.cc
+++ b/src/algorithms/PVT/gnuradio_blocks/hybrid_pvt_cc.cc
@@ -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->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
     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)
                         {
                             d_kml_dump->print_position(d_ls_pvt, d_flag_averaging);
-                            //ToDo: Implement Galileo RINEX and Galileo NMEA outputs
-                            //   d_nmea_printer->Print_Nmea_Line(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);
+
                             if (!b_rinex_header_writen) //  & we have utc data in nav message!
                                 {
                                     std::map<int, Galileo_Ephemeris>::iterator galileo_ephemeris_iter;
diff --git a/src/algorithms/PVT/gnuradio_blocks/hybrid_pvt_cc.h b/src/algorithms/PVT/gnuradio_blocks/hybrid_pvt_cc.h
index 2ac6b1e..777c388 100644
--- a/src/algorithms/PVT/gnuradio_blocks/hybrid_pvt_cc.h
+++ b/src/algorithms/PVT/gnuradio_blocks/hybrid_pvt_cc.h
@@ -49,7 +49,9 @@
 #include "gps_iono.h"
 #include "nmea_printer.h"
 #include "kml_printer.h"
+#include "geojson_printer.h"
 #include "rinex_printer.h"
+#include "nmea_printer.h"
 #include "hybrid_ls_pvt.h"
 #include "GPS_L1_CA.h"
 #include "Galileo_E1.h"
@@ -113,6 +115,7 @@ private:
     long unsigned int d_last_sample_nav_output;
     std::shared_ptr<Kml_Printer> d_kml_dump;
     std::shared_ptr<Nmea_Printer> d_nmea_printer;
+    std::shared_ptr<GeoJSON_Printer> d_geojson_printer;
     double d_rx_time;
     double d_TOW_at_curr_symbol_constellation;
     std::shared_ptr<hybrid_ls_pvt> d_ls_pvt;
diff --git a/src/algorithms/PVT/libs/CMakeLists.txt b/src/algorithms/PVT/libs/CMakeLists.txt
index 47b2b16..e64975e 100644
--- a/src/algorithms/PVT/libs/CMakeLists.txt
+++ b/src/algorithms/PVT/libs/CMakeLists.txt
@@ -19,6 +19,7 @@
 add_definitions( -DGNSS_SDR_VERSION="${VERSION}" )
 
 set(PVT_LIB_SOURCES 
+     pvt_solution.cc
      ls_pvt.cc
      gps_l1_ca_ls_pvt.cc
      galileo_e1_ls_pvt.cc
diff --git a/src/algorithms/PVT/libs/galileo_e1_ls_pvt.cc b/src/algorithms/PVT/libs/galileo_e1_ls_pvt.cc
index 9dde4c9..157c034 100644
--- a/src/algorithms/PVT/libs/galileo_e1_ls_pvt.cc
+++ b/src/algorithms/PVT/libs/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
-            if (flag_averaging == true)
-                {
-                    if (d_hist_longitude_d.size() == (unsigned int)d_averaging_depth)
-                        {
-                            // Pop oldest value
-                            d_hist_longitude_d.pop_back();
-                            d_hist_latitude_d.pop_back();
-                            d_hist_height_m.pop_back();
-                            // Push new values
-                            d_hist_longitude_d.push_front(d_longitude_d);
-                            d_hist_latitude_d.push_front(d_latitude_d);
-                            d_hist_height_m.push_front(d_height_m);
-
-                            d_avg_latitude_d = 0;
-                            d_avg_longitude_d = 0;
-                            d_avg_height_m = 0;
-                            for (unsigned int i = 0; i < d_hist_longitude_d.size(); i++)
-                                {
-                                    d_avg_latitude_d = d_avg_latitude_d + d_hist_latitude_d.at(i);
-                                    d_avg_longitude_d = d_avg_longitude_d + d_hist_longitude_d.at(i);
-                                    d_avg_height_m  = d_avg_height_m + d_hist_height_m.at(i);
-                                }
-                            d_avg_latitude_d = d_avg_latitude_d / 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
-                }
+            galileo_e1_ls_pvt::pos_averaging(flag_averaging);
         }
     else
         {
             b_valid_position = false;
-            return false;
         }
-    return false;
+    return b_valid_position;
 }
 
diff --git a/src/algorithms/PVT/libs/geojson_printer.cc b/src/algorithms/PVT/libs/geojson_printer.cc
index eaef9ea..8668d1c 100644
--- a/src/algorithms/PVT/libs/geojson_printer.cc
+++ b/src/algorithms/PVT/libs/geojson_printer.cc
@@ -48,16 +48,26 @@ GeoJSON_Printer::~GeoJSON_Printer ()
 bool GeoJSON_Printer::set_headers(std::string filename)
 {
     geojson_file.open(filename.c_str());
+    filename_ = filename;
+    first_pos = true;
     if (geojson_file.is_open())
         {
             DLOG(INFO) << "GeoJSON printer writing on " << filename.c_str();
+
             // Set iostream numeric format and precision
             geojson_file.setf(geojson_file.fixed, geojson_file.floatfield);
             geojson_file << std::setprecision(14);
+
+            // Writing the header
             geojson_file << "{" << 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 << "    \"type\": \"MultiPoint\"," << std::endl;
+            geojson_file << "      \"type\": \"MultiPoint\"," << std::endl;
             geojson_file << "      \"coordinates\": [" << std::endl;
 
             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 longitude;
     double height;
 
-    std::shared_ptr<Ls_Pvt> position_ = position;
+    std::shared_ptr<Pvt_Solution> position_ = position;
 
     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())
         {
-            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;
         }
     else
@@ -108,10 +127,18 @@ bool GeoJSON_Printer::close_file()
 {
     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.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;
         }
     else
diff --git a/src/algorithms/PVT/libs/geojson_printer.h b/src/algorithms/PVT/libs/geojson_printer.h
index aabc994..3c15883 100644
--- a/src/algorithms/PVT/libs/geojson_printer.h
+++ b/src/algorithms/PVT/libs/geojson_printer.h
@@ -37,7 +37,7 @@
 #include <fstream>
 #include <memory>
 #include <string>
-#include "ls_pvt.h"
+#include "pvt_solution.h"
 
 
 /*!
@@ -49,11 +49,13 @@ class GeoJSON_Printer
 {
 private:
     std::ofstream geojson_file;
+    bool first_pos;
+    std::string filename_;
 public:
     GeoJSON_Printer();
     ~GeoJSON_Printer();
     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();
 };
 
diff --git a/src/algorithms/PVT/libs/gps_l1_ca_ls_pvt.cc b/src/algorithms/PVT/libs/gps_l1_ca_ls_pvt.cc
index e0e83be..5598f96 100644
--- a/src/algorithms/PVT/libs/gps_l1_ca_ls_pvt.cc
+++ b/src/algorithms/PVT/libs/gps_l1_ca_ls_pvt.cc
@@ -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);
             //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)
-            {
-            	b_valid_position = false;
-            	return false;
-            }
+                {
+                    b_valid_position = false;
+                    return false;
+                }
             // Compute UTC time and print PVT solution
             double secondsperweek = 604800.0; // number of seconds in one week (7*24*60*60)
             boost::posix_time::time_duration t = boost::posix_time::seconds(utc + secondsperweek * 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;
 
             LOG(INFO) << "(new)Position at " << boost::posix_time::to_simple_string(p_time)
-                      << " is Lat = " << d_latitude_d << " [deg], Long = " << d_longitude_d
-                      << " [deg], Height= " << d_height_m << " [m]";
+            << " is Lat = " << d_latitude_d << " [deg], Long = " << d_longitude_d
+            << " [deg], Height= " << d_height_m << " [m]";
 
             // ###### Compute DOPs ########
             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
-            if (flag_averaging == true)
-                {
-                    if (d_hist_longitude_d.size() == (unsigned int)d_averaging_depth)
-                        {
-                            // Pop oldest value
-                            d_hist_longitude_d.pop_back();
-                            d_hist_latitude_d.pop_back();
-                            d_hist_height_m.pop_back();
-                            // Push new values
-                            d_hist_longitude_d.push_front(d_longitude_d);
-                            d_hist_latitude_d.push_front(d_latitude_d);
-                            d_hist_height_m.push_front(d_height_m);
-
-                            d_avg_latitude_d = 0;
-                            d_avg_longitude_d = 0;
-                            d_avg_height_m = 0;
-                            for (unsigned int i = 0; i < d_hist_longitude_d.size(); i++)
-                                {
-                                    d_avg_latitude_d = d_avg_latitude_d + d_hist_latitude_d.at(i);
-                                    d_avg_longitude_d = d_avg_longitude_d + d_hist_longitude_d.at(i);
-                                    d_avg_height_m  = d_avg_height_m + d_hist_height_m.at(i);
-                                }
-                            d_avg_latitude_d = d_avg_latitude_d / 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
-                }
+            gps_l1_ca_ls_pvt::pos_averaging(flag_averaging);
         }
     else
         {
             b_valid_position = false;
-            return false;
         }
+    return b_valid_position;
 }
 
 
diff --git a/src/algorithms/PVT/libs/hybrid_ls_pvt.cc b/src/algorithms/PVT/libs/hybrid_ls_pvt.cc
index 41d2801..e387a18 100644
--- a/src/algorithms/PVT/libs/hybrid_ls_pvt.cc
+++ b/src/algorithms/PVT/libs/hybrid_ls_pvt.cc
@@ -172,10 +172,10 @@ bool hybrid_ls_pvt::get_PVT(std::map<int,Gnss_Synchro> gnss_pseudoranges_map, do
 
                             // SV ECEF DEBUG OUTPUT
                             DLOG(INFO) << "ECEF satellite SV ID=" << galileo_ephemeris_iter->second.i_satellite_PRN
-                                      << " X=" << galileo_ephemeris_iter->second.d_satpos_X
-                                      << " [m] Y=" << galileo_ephemeris_iter->second.d_satpos_Y
-                                      << " [m] Z=" << galileo_ephemeris_iter->second.d_satpos_Z
-                                      << " [m] PR_obs=" << obs(obs_counter) << " [m]";
+                                    << " X=" << galileo_ephemeris_iter->second.d_satpos_X
+                                    << " [m] Y=" << galileo_ephemeris_iter->second.d_satpos_Y
+                                    << " [m] Z=" << galileo_ephemeris_iter->second.d_satpos_Z
+                                    << " [m] PR_obs=" << obs(obs_counter) << " [m]";
                         }
 
                     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;
                     LOG(INFO) << "Hybrid Position at " << boost::posix_time::to_simple_string(p_time)
-                              << " is Lat = " << d_latitude_d << " [deg], Long = " << d_longitude_d
-                              << " [deg], Height= " << d_height_m << " [m]";
+                    << " is Lat = " << d_latitude_d << " [deg], Long = " << d_longitude_d
+                    << " [deg], Height= " << d_height_m << " [m]";
 
                     //std::cout << "Hybrid Position at " << boost::posix_time::to_simple_string(p_time)
                     //          << " 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)
-                      << " is Lat = " << d_latitude_d << " [deg], Long = " << d_longitude_d
-                      << " [deg], Height= " << d_height_m << " [m]";
+            << " is Lat = " << d_latitude_d << " [deg], Long = " << d_longitude_d
+            << " [deg], Height= " << d_height_m << " [m]";
 
 
             // ###### Compute DOPs ########
@@ -331,60 +331,12 @@ bool hybrid_ls_pvt::get_PVT(std::map<int,Gnss_Synchro> gnss_pseudoranges_map, do
                 }
 
             // MOVING AVERAGE PVT
-            if (flag_averaging == true)
-                {
-                    if (d_hist_longitude_d.size() == (unsigned int)d_averaging_depth)
-                        {
-                            // Pop oldest value
-                            d_hist_longitude_d.pop_back();
-                            d_hist_latitude_d.pop_back();
-                            d_hist_height_m.pop_back();
-                            // Push new values
-                            d_hist_longitude_d.push_front(d_longitude_d);
-                            d_hist_latitude_d.push_front(d_latitude_d);
-                            d_hist_height_m.push_front(d_height_m);
-
-                            d_avg_latitude_d = 0;
-                            d_avg_longitude_d = 0;
-                            d_avg_height_m = 0;
-                            for (unsigned int i = 0; i < d_hist_longitude_d.size(); i++)
-                                {
-                                    d_avg_latitude_d = d_avg_latitude_d + d_hist_latitude_d.at(i);
-                                    d_avg_longitude_d = d_avg_longitude_d + d_hist_longitude_d.at(i);
-                                    d_avg_height_m  = d_avg_height_m + d_hist_height_m.at(i);
-                                }
-                            d_avg_latitude_d = d_avg_latitude_d / 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
-                }
+            hybrid_ls_pvt::pos_averaging(flag_averaging);
         }
     else
         {
             b_valid_position = false;
-            return false;
         }
-    return false;
+    return b_valid_position;
 }
 
diff --git a/src/algorithms/PVT/libs/kml_printer.cc b/src/algorithms/PVT/libs/kml_printer.cc
index c74ba24..2482dde 100644
--- a/src/algorithms/PVT/libs/kml_printer.cc
+++ b/src/algorithms/PVT/libs/kml_printer.cc
@@ -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 longitude;
     double height;
 
-    std::shared_ptr<Ls_Pvt> position_ = position;
+    std::shared_ptr<Pvt_Solution> position_ = position;
 
     if (print_average_values == false)
         {
diff --git a/src/algorithms/PVT/libs/kml_printer.h b/src/algorithms/PVT/libs/kml_printer.h
index 6f90d73..5fb8522 100644
--- a/src/algorithms/PVT/libs/kml_printer.h
+++ b/src/algorithms/PVT/libs/kml_printer.h
@@ -37,7 +37,7 @@
 #include <fstream>
 #include <memory>
 #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)
@@ -52,7 +52,7 @@ public:
     Kml_Printer();
     ~Kml_Printer();
     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();
 };
 
diff --git a/src/algorithms/PVT/libs/ls_pvt.cc b/src/algorithms/PVT/libs/ls_pvt.cc
index b78d198..a618692 100644
--- a/src/algorithms/PVT/libs/ls_pvt.cc
+++ b/src/algorithms/PVT/libs/ls_pvt.cc
@@ -1,5 +1,5 @@
 /*!
- * \file ls_pvt.h
+ * \file ls_pvt.cc
  * \brief Implementation of a base class for Least Squares PVT solutions
  * \author Carles Fernandez-Prades, 2015. cfernandez(at)cttc.es
  *
@@ -38,30 +38,15 @@
 
 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_y_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)
@@ -173,435 +158,3 @@ arma::vec Ls_Pvt::leastSquarePos(const arma::mat & satpos, const arma::vec & obs
     }
     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;
-}
diff --git a/src/algorithms/PVT/libs/ls_pvt.h b/src/algorithms/PVT/libs/ls_pvt.h
index eb923f2..385d6e4 100644
--- a/src/algorithms/PVT/libs/ls_pvt.h
+++ b/src/algorithms/PVT/libs/ls_pvt.h
@@ -33,144 +33,21 @@
 #define GNSS_SDR_LS_PVT_H_
 
 
-#include <deque>
-#include <armadillo>
-#include <boost/date_time/posix_time/posix_time.hpp>
-
-#define PVT_MAX_CHANNELS 24
+#include "pvt_solution.h"
 
 /*!
  * \brief Base class for the Least Squares PVT solution
  *
  */
-class Ls_Pvt
+class Ls_Pvt : public Pvt_Solution
 {
 public:
     Ls_Pvt();
 
     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_y_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
diff --git a/src/algorithms/PVT/libs/nmea_printer.cc b/src/algorithms/PVT/libs/nmea_printer.cc
index ceda216..c3213b9 100644
--- a/src/algorithms/PVT/libs/nmea_printer.cc
+++ b/src/algorithms/PVT/libs/nmea_printer.cc
@@ -39,7 +39,7 @@
 #include <boost/date_time/posix_time/posix_time.hpp>
 #include <glog/logging.h>
 #include <gflags/gflags.h>
-#include "GPS_L1_CA.h"
+
 
 
 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 GPGGA;
diff --git a/src/algorithms/PVT/libs/nmea_printer.h b/src/algorithms/PVT/libs/nmea_printer.h
index b613d45..115ab07 100644
--- a/src/algorithms/PVT/libs/nmea_printer.h
+++ b/src/algorithms/PVT/libs/nmea_printer.h
@@ -40,7 +40,7 @@
 #include <iostream>
 #include <fstream>
 #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
      */
-    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.
@@ -72,7 +72,7 @@ private:
     std::ofstream nmea_file_descriptor; // Output file stream for NMEA log file
     std::string nmea_devname;
     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
     void close_serial();
     std::string get_GPGGA(); // fix data
diff --git a/src/algorithms/PVT/libs/ls_pvt.cc b/src/algorithms/PVT/libs/pvt_solution.cc
similarity index 73%
copy from src/algorithms/PVT/libs/ls_pvt.cc
copy to src/algorithms/PVT/libs/pvt_solution.cc
index b78d198..fd2edc4 100644
--- a/src/algorithms/PVT/libs/ls_pvt.cc
+++ b/src/algorithms/PVT/libs/pvt_solution.cc
@@ -1,6 +1,6 @@
 /*!
- * \file ls_pvt.h
- * \brief Implementation of a base class for Least Squares PVT solutions
+ * \file pvt_solution.cc
+ * \brief Implementation of a base class for a PVT solution
  * \author Carles Fernandez-Prades, 2015. cfernandez(at)cttc.es
  *
  *
@@ -29,7 +29,7 @@
  * -------------------------------------------------------------------------
  */
 
-#include "ls_pvt.h"
+#include "pvt_solution.h"
 #include <exception>
 #include "GPS_L1_CA.h"
 #include <gflags/gflags.h>
@@ -40,20 +40,14 @@ using google::LogMessage;
 
 DEFINE_bool(tropo, true, "Apply tropospheric correction");
 
-
-
-Ls_Pvt::Ls_Pvt()
+Pvt_Solution::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_y_m = 0.0;
-    d_z_m = 0.0;
     d_GDOP = 0.0;
     d_PDOP = 0.0;
     d_HDOP = 0.0;
@@ -62,121 +56,10 @@ Ls_Pvt::Ls_Pvt()
     d_flag_averaging = false;
     b_valid_position = false;
     d_averaging_depth = 0;
+    d_valid_observations = 0;
 }
 
-arma::vec Ls_Pvt::leastSquarePos(const arma::mat & satpos, const arma::vec & obs, const arma::mat & w)
-{
-    /* Computes the Least Squares Solution.
-     *   Inputs:
-     *       satpos      - Satellites positions in ECEF system: [X; Y; Z;]
-     *       obs         - Observations - the pseudorange measurements to each satellite
-     *       w           - weigths vector
-     *
-     *   Returns:
-     *       pos         - receiver position and receiver clock error
-     *                   (in ECEF system: [X, Y, Z, dt])
-     */
-
-    //=== Initialization =======================================================
-    int nmbOfIterations = 10; // TODO: include in config
-    int nmbOfSatellites;
-    nmbOfSatellites = satpos.n_cols;    //Armadillo
-    arma::vec pos = "0.0 0.0 0.0 0.0";
-    arma::mat A;
-    arma::mat omc;
-    arma::mat az;
-    arma::mat el;
-    A = arma::zeros(nmbOfSatellites, 4);
-    omc = arma::zeros(nmbOfSatellites, 1);
-    az = arma::zeros(1, nmbOfSatellites);
-    el = arma::zeros(1, nmbOfSatellites);
-    arma::mat X = satpos;
-    arma::vec Rot_X;
-    double rho2;
-    double traveltime;
-    double trop = 0.0;
-    double dlambda;
-    double dphi;
-    double h;
-    arma::mat mat_tmp;
-    arma::vec x;
-
-    //=== Iteratively find receiver position ===================================
-    for (int iter = 0; iter < nmbOfIterations; iter++)
-        {
-            for (int i = 0; i < nmbOfSatellites; i++)
-                {
-                    if (iter == 0)
-                        {
-                            //--- Initialize variables at the first iteration --------------
-                            Rot_X = X.col(i); //Armadillo
-                            trop = 0.0;
-                        }
-                    else
-                        {
-                            //--- Update equations -----------------------------------------
-                            rho2 = (X(0, i) - pos(0)) *
-                                   (X(0, i) - pos(0)) + (X(1, i) - pos(1)) *
-                                   (X(1, i) - pos(1)) + (X(2, i) - pos(2)) *
-                                   (X(2, i) - pos(2));
-                            traveltime = sqrt(rho2) / GPS_C_m_s;
-
-                            //--- Correct satellite position (do to earth rotation) --------
-                            Rot_X = Ls_Pvt::rotateSatellite(traveltime, X.col(i)); //armadillo
-
-                            //--- Find DOA and range of satellites
-                            Ls_Pvt::topocent(&d_visible_satellites_Az[i],
-                                     &d_visible_satellites_El[i],
-                                     &d_visible_satellites_Distance[i],
-                                     pos.subvec(0,2),
-                                     Rot_X - pos.subvec(0, 2));
-                            if(traveltime < 0.1 && nmbOfSatellites > 3)
-                                {
-                                    //--- Find receiver's height
-                                    Ls_Pvt::togeod(&dphi, &dlambda, &h, 6378137.0, 298.257223563, pos(0), pos(1), pos(2));
-
-                                    //--- Find delay due to troposphere (in meters)
-                                    Ls_Pvt::tropo(&trop, sin(d_visible_satellites_El[i] * GPS_PI / 180.0), h / 1000.0, 1013.0, 293.0, 50.0, 0.0, 0.0, 0.0);
-                                    if(trop > 50.0 ) trop = 0.0;
-                                }
-                        }
-                    //--- Apply the corrections ----------------------------------------
-                    omc(i) = (obs(i) - norm(Rot_X - pos.subvec(0, 2), 2) - pos(3) - trop); // Armadillo
-
-                    //--- Construct the A matrix ---------------------------------------
-                    //Armadillo
-                    A(i,0) = (-(Rot_X(0) - pos(0))) / obs(i);
-                    A(i,1) = (-(Rot_X(1) - pos(1))) / obs(i);
-                    A(i,2) = (-(Rot_X(2) - pos(2))) / obs(i);
-                    A(i,3) = 1.0;
-                }
-
-            //--- Find position update ---------------------------------------------
-            x = arma::solve(w*A, w*omc); // Armadillo
-
-            //--- Apply position update --------------------------------------------
-            pos = pos + x;
-            if (arma::norm(x,2) < 1e-4)
-            {
-                break; // exit the loop because we assume that the LS algorithm has converged (err < 0.1 cm)
-            }
-        }
-
-    try
-    {
-            //-- compute the Dilution Of Precision values
-            d_Q = arma::inv(arma::htrans(A)*A);
-    }
-    catch(std::exception& e)
-    {
-            d_Q = arma::zeros(4,4);
-    }
-    return pos;
-}
-
-
-
-arma::vec Ls_Pvt::rotateSatellite(double const traveltime, const arma::vec & X_sat)
+arma::vec Pvt_Solution::rotateSatellite(double const traveltime, const arma::vec & X_sat)
 {
     /*
      *  Returns rotated satellite ECEF coordinates due to Earth
@@ -213,7 +96,7 @@ arma::vec Ls_Pvt::rotateSatellite(double const traveltime, const arma::vec & X_s
 }
 
 
-void Ls_Pvt::cart2geo(double X, double Y, double Z, int elipsoid_selection)
+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.
@@ -255,10 +138,11 @@ void Ls_Pvt::cart2geo(double X, double Y, double Z, int elipsoid_selection)
     d_latitude_d = phi * 180.0 / GPS_PI;
     d_longitude_d = lambda * 180.0 / GPS_PI;
     d_height_m = h;
+    return 0;
 }
 
 
-void Ls_Pvt::togeod(double *dphi, double *dlambda, double *h, double a, double finv, double X, double Y, double Z)
+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
@@ -334,7 +218,7 @@ void Ls_Pvt::togeod(double *dphi, double *dlambda, double *h, double a, double f
     if (r < 1.0E-20)
         {
             *h = 0;
-            return;
+            return 1;
         }
 
     *h = r - a * (1 - sinphi * sinphi/finv);
@@ -373,10 +257,11 @@ void Ls_Pvt::togeod(double *dphi, double *dlambda, double *h, double a, double f
                 }
         }
     *dphi = (*dphi) * rtd;
+    return 0;
 }
 
 
-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)
+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
@@ -474,9 +359,10 @@ void Ls_Pvt::tropo(double *ddr_m, double sinel, double hsta_km, double p_mb, dou
             htop    = 1.1385e-5 * (1255 / tksea + 0.05) / refsea;
             ref     = refsea * e0sea * pow(((htop - hsta_km) / htop), 4);
         }
+    return 0;
 }
 
-void Ls_Pvt::topocent(double *Az, double *El, double *D, const arma::vec & x, const arma::vec & dx)
+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
@@ -500,7 +386,7 @@ void Ls_Pvt::topocent(double *Az, double *El, double *D, const arma::vec & x, co
     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));
+    Pvt_Solution::togeod(&phi, &lambda, &h, a, finv, x(0), x(1), x(2));
 
     double cl = cos(lambda * dtr);
     double sl = sin(lambda * dtr);
@@ -549,11 +435,12 @@ void Ls_Pvt::topocent(double *Az, double *El, double *D, const arma::vec & x, co
         }
 
     *D = sqrt(dx(0) * dx(0) + dx(1) * dx(1) + dx(2) * dx(2));
+    return 0;
 }
 
 
 
-int Ls_Pvt::compute_DOP()
+int Pvt_Solution::compute_DOP()
 {
     // ###### Compute DOPs ########
 
@@ -600,8 +487,62 @@ int Ls_Pvt::compute_DOP()
 
 
 
-int Ls_Pvt::set_averaging_depth(int depth)
+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;
+}
+
diff --git a/src/algorithms/PVT/libs/pvt_solution.h b/src/algorithms/PVT/libs/pvt_solution.h
new file mode 100644
index 0000000..7adec71
--- /dev/null
+++ b/src/algorithms/PVT/libs/pvt_solution.h
@@ -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

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-hamradio/gnss-sdr.git



More information about the pkg-hamradio-commits mailing list