diff --git a/CMakeLists.txt b/CMakeLists.txt index 3c6cd3802f06a76c8dc5f9aff1cea5d460897a66..b3beddcb57454472c4f278701a5db658da2e4ae9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -80,9 +80,10 @@ SET(SOURCES src/utils/utils.cpp src/utils/transformations.cpp src/utils/rcv_position.cpp - src/utils/sat_position.cpp + src/utils/satellite.cpp src/observations.cpp src/navigation.cpp + src/snapshot.cpp src/tdcp.cpp src/ublox_raw.cpp) diff --git a/include/gnss_utils/gnss_utils.h b/include/gnss_utils/gnss_utils.h index 4d9f83f2bd6ab7a7a70fa1b63e8c3d577be4011b..0c32ca8f6361c8dfba86dced6134eff2fb49e6a9 100644 --- a/include/gnss_utils/gnss_utils.h +++ b/include/gnss_utils/gnss_utils.h @@ -5,4 +5,38 @@ extern "C" { #include "rtklib.h" } -#endif \ No newline at end of file +// std includes +#include <set> +#include <map> +#include <vector> +#include <iostream> +#include <memory> +#include <cassert> +// eigen +#include <eigen3/Eigen/Dense> + +namespace GnssUtils +{ + +// forward declarations +class Observations; +class Navigation; +class Snapshot; + +// Typedefs +typedef std::map<int,Eigen::Vector3d> SatellitesPositions; + +// pointer typedefs +typedef std::shared_ptr<Observations> ObservationsPtr; +typedef std::shared_ptr<const Observations> ObservationsConstPtr; + +typedef std::shared_ptr<Navigation> NavigationPtr; +typedef std::shared_ptr<const Navigation> NavigationConstPtr; + +typedef std::shared_ptr<Snapshot> SnapshotPtr; +typedef std::shared_ptr<const Snapshot> SnapshotConstPtr; + + +} + +#endif diff --git a/include/gnss_utils/navigation.h b/include/gnss_utils/navigation.h index ccd1ac812fcd829e5ffcca14021d0fc15c65e595..f47a7bc0617c1250f2a99233c83d67e58f81f048 100644 --- a/include/gnss_utils/navigation.h +++ b/include/gnss_utils/navigation.h @@ -1,18 +1,11 @@ #ifndef INCLUDE_GNSS_UTILS_NAVIGATION_H_ #define INCLUDE_GNSS_UTILS_NAVIGATION_H_ -#include <vector> -#include <iostream> -#include <memory> - #include "gnss_utils/gnss_utils.h" #include "gnss_utils/utils/utils.h" namespace GnssUtils { -class Navigation; -typedef std::shared_ptr<Navigation> NavigationPtr; -typedef std::shared_ptr<const Navigation> NavigationConstPtr; class Navigation { diff --git a/include/gnss_utils/observations.h b/include/gnss_utils/observations.h index 7e6328607715cb44088428bfb9bc0a3e4f9625f2..cd6bea585de5766dc43bf2f912e2000f635efc84 100644 --- a/include/gnss_utils/observations.h +++ b/include/gnss_utils/observations.h @@ -1,20 +1,10 @@ #ifndef INCLUDE_GNSS_UTILS_OBSERVATIONS_H_ #define INCLUDE_GNSS_UTILS_OBSERVATIONS_H_ -#include <vector> -#include <map> -#include <iostream> -#include <memory> -#include <cassert> - #include "gnss_utils/gnss_utils.h" -#include "gnss_utils/utils/utils.h" namespace GnssUtils { -class Observations; -typedef std::shared_ptr<Observations> ObservationsPtr; -typedef std::shared_ptr<const Observations> ObservationsConstPtr; class Observations { @@ -54,10 +44,25 @@ public: void printByIdx(const int& _idx); void print(); - static void findCommonObservations(const Observations& obs_1, - const Observations& obs_2, - Observations& common_obs_1, - Observations& common_obs_2); + // Filter observations + std::set<int> filterByEphemeris(const SatellitesPositions& sats_pos); + std::set<int> filterBySatellites(const std::set<int>& discarded_sats); + std::set<int> filterByCode(); + std::set<int> filterByCarrierPhase(); + std::set<int> filterByConstellations(const int& navsys); + std::set<int> filterByElevationSnr(const Eigen::Vector3d& x_r, + const SatellitesPositions& sats_pos, + const snrmask_t& snrmask, + const double& elmin); + std::set<int> filter(const SatellitesPositions& sats_pos, + const std::set<int>& discarded_sats, + const Eigen::Vector3d& x_r, + const bool& check_code, + const bool& check_carrier_phase, + const prcopt_t& opt); + + static std::set<int> findCommonObservations(const Observations& obs_1, + const Observations& obs_2); bool operator==(const Observations& other_obs) const; bool operator !=(const Observations &other_obs) const; @@ -71,6 +76,15 @@ private: // Private methods }; +} // namespace GnssUtils + +// IMPLEMENTATION +#include "gnss_utils/utils/utils.h" +#include "gnss_utils/utils/satellite.h" + +namespace GnssUtils +{ + inline const std::vector<obsd_t>& Observations::getObservations() const { return this->obs_; diff --git a/include/gnss_utils/snapshot.h b/include/gnss_utils/snapshot.h new file mode 100644 index 0000000000000000000000000000000000000000..6d8f1dc36afd69cfb5a8af2f1c2312427bc3c634 --- /dev/null +++ b/include/gnss_utils/snapshot.h @@ -0,0 +1,114 @@ +#ifndef INCLUDE_GNSS_UTILS_SNAPSHOT_H_ +#define INCLUDE_GNSS_UTILS_SNAPSHOT_H_ + +#include <map> +#include <set> +#include <iostream> +#include <memory> +#include <cassert> + +#include <eigen3/Eigen/Dense> + +#include "gnss_utils/gnss_utils.h" + +namespace GnssUtils +{ + +class Snapshot +{ + +public: + // Constructor & Destructor + Snapshot(); + Snapshot(ObservationsPtr obs, NavigationPtr nav); + ~Snapshot(){}; + + // Public objects + + // Public methods + void loadFromRinex(const std::string& rnx_file, gtime_t t_start, gtime_t t_end, double dt = 0.0, const char* opt = ""); + + ObservationsPtr getObservations() const; + NavigationPtr getNavigation() const; + const SatellitesPositions& getSatellitesPositions() const; + SatellitesPositions& getSatellitesPositions(); + void setObservations(ObservationsPtr obs); + void setNavigation(NavigationPtr nav); + + void computeSatellitesPositions(const int& eph_opt); // see rtklib.h L396); + bool satellitesPositionsComputed() const; + + std::set<int> filterObservations(std::set<int> &discarded_sats, + const Eigen::Vector3d &x_r, + const bool &check_code, + const bool &check_carrier_phase, + const prcopt_t &opt); + + void print(); + +private: + // Private objects + SatellitesPositions sats_pos_; //< key: sat number + ObservationsPtr obs_; + NavigationPtr nav_; + + // Private methods +}; + +} // namespace GnssUtils + +// IMPLEMENTATION +#include "gnss_utils/utils/satellite.h" +#include "gnss_utils/observations.h" +#include "gnss_utils/navigation.h" +#include "gnss_utils/utils/utils.h" + +namespace GnssUtils +{ + +inline GnssUtils::ObservationsPtr Snapshot::getObservations() const +{ + return obs_; +} + +inline GnssUtils::NavigationPtr Snapshot::getNavigation() const +{ + return nav_; +} + +inline SatellitesPositions& Snapshot::getSatellitesPositions() +{ + return sats_pos_; +} + +inline const SatellitesPositions& Snapshot::getSatellitesPositions() const +{ + return sats_pos_; +} + +inline void Snapshot::setObservations(ObservationsPtr obs) +{ + obs_ = obs; +} + +inline void Snapshot::setNavigation(NavigationPtr nav) +{ + nav_ = nav; +} + +inline bool Snapshot::satellitesPositionsComputed() const +{ + return !sats_pos_.empty(); +} + +inline std::set<int> Snapshot::filterObservations(std::set<int> &discarded_sats, + const Eigen::Vector3d &x_r, + const bool &check_code, + const bool &check_carrier_phase, + const prcopt_t &opt) +{ + return obs_->filter(sats_pos_, discarded_sats, x_r, check_code, check_carrier_phase, opt); +} + +} // namespace GnssUtils +#endif // INCLUDE_GNSS_UTILS_SNAPSHOT_H_ diff --git a/include/gnss_utils/tdcp.h b/include/gnss_utils/tdcp.h index 6d64e885bec90541f3fd4f3cc29fcc605576f277..45504e0dcd1c78d2ed34d0f56224eeb5427cb859 100644 --- a/include/gnss_utils/tdcp.h +++ b/include/gnss_utils/tdcp.h @@ -1,20 +1,9 @@ -/* - * tdcp.h - * - * Created on: Dec 4, 2019 - * Author: jvallve - */ - #ifndef INCLUDE_GNSS_UTILS_TDCP_H_ #define INCLUDE_GNSS_UTILS_TDCP_H_ -#define GNSS_UTILS_TDCP_DEBUG 0 +#define GNSS_UTILS_TDCP_DEBUG 1 -#include <set> -#include "gnss_utils/utils/rcv_position.h" -#include "gnss_utils/utils/sat_position.h" -#include "gnss_utils/observations.h" -#include "gnss_utils/navigation.h" +#include "gnss_utils/gnss_utils.h" namespace GnssUtils { @@ -36,51 +25,36 @@ struct TdcpParams double time_window; }; -bool Tdcp(const Observations& obs_r, - Navigation& nav_r, - const Observations& obs_k, - const Navigation& nav_k, - Eigen::Vector4d& d, - Eigen::Matrix4d& cov_d, - double& residual, - std::set<int>& discarded_sats, - const TdcpParams& sd_opt, - const prcopt_t& opt); - -bool Tdcp(const Observations& obs_r, - const Navigation& nav_r, +bool Tdcp(SnapshotPtr snapshot_r, + SnapshotPtr snapshot_k, + Eigen::Vector4d& d, + Eigen::Matrix4d& cov_d, + double& residual, + const std::set<int>& discarded_sats, + std::set<int>& raim_discarded_sats, + const TdcpParams& sd_opt, + const prcopt_t& opt); + +bool Tdcp(SnapshotPtr snapshot_r, + SnapshotPtr snapshot_k, const Eigen::Vector3d& x_r, - const Observations& obs_k, - const Navigation& nav_k, Eigen::Vector4d& d, Eigen::Matrix4d& cov_d, double& residual, - std::set<int>& discarded_sats, - const TdcpParams& sd_opt, + const std::set<int>& discarded_sats, + std::set<int>& raim_discarded_sats, + const TdcpParams& sd_params, const prcopt_t& opt); -bool Tdcp(const Observations& common_obs_r, - const Navigation& nav_r, - const std::map<int, Eigen::Vector3d>& common_sats_pos_r, - const Eigen::Vector3d& x_r, - const Observations& common_obs_k, - const Navigation& nav_k, - const std::map<int, Eigen::Vector3d>& common_sats_pos_k, - Eigen::Vector4d& d, - Eigen::Matrix4d& cov_d, - double& residual, - std::set<int>& discarded_sats, - const TdcpParams& sd_opt); - -void filterCommonSatellites(Observations& common_obs_r, - std::map<int, Eigen::Vector3d>& common_sats_pos_r, - Observations& common_obs_k, - std::map<int, Eigen::Vector3d>& common_sats_pos_k, - std::set<int>& discarded_sats, - const Eigen::Vector3d& x_r, - const TdcpParams& sd_params, - const prcopt_t& opt); - +bool Tdcp(SnapshotPtr snapshot_r, + SnapshotPtr snapshot_k, + const Eigen::Vector3d& x_r, + const std::set<int> common_sats, + Eigen::Vector4d& d, + Eigen::Matrix4d& cov_d, + double& residual, + std::set<int> raim_discarded_sats, + const TdcpParams& sd_params); } // namespace GnssUtils #endif /* INCLUDE_GNSS_UTILS_Tdcp_H_ */ diff --git a/include/gnss_utils/ublox_raw.h b/include/gnss_utils/ublox_raw.h index ecee80c79c836464b482ec686b264e7c4d87235c..f03bb73188d98b53f011b72e0cd1dd6932e76b70 100644 --- a/include/gnss_utils/ublox_raw.h +++ b/include/gnss_utils/ublox_raw.h @@ -44,12 +44,12 @@ private: void updateObservations(); }; -inline const GnssUtils::Observations& UBloxRaw::getObservations() +inline const Observations& UBloxRaw::getObservations() { return obs_; } -inline const GnssUtils::Navigation& UBloxRaw::getNavigation() +inline const Navigation& UBloxRaw::getNavigation() { return nav_; } diff --git a/include/gnss_utils/utils/sat_position.h b/include/gnss_utils/utils/sat_position.h deleted file mode 100644 index 3e90436c2caea89e3e77fd57e99acbe8ce727813..0000000000000000000000000000000000000000 --- a/include/gnss_utils/utils/sat_position.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * sat_position.h - * - * Created on: April 3, 2020 - * Author: Joan Vallvé, Pep MartÃ-Saumell - */ - -#ifndef INCLUDE_GNSS_UTILS_UTILS_SAT_POSITION_H_ -#define INCLUDE_GNSS_UTILS_UTILS_SAT_POSITION_H_ - -#include <eigen3/Eigen/Dense> -#include <eigen3/Eigen/Geometry> -#include <eigen3/Eigen/Sparse> - -#include "gnss_utils/observations.h" -#include "gnss_utils/navigation.h" -#include "gnss_utils/utils/transformations.h" -#include "gnss_utils/gnss_utils.h" - -namespace GnssUtils -{ -double computeSatElevation(const Eigen::Vector3d& receiver_ecef, const Eigen::Vector3d& sat_ecef); - -void computeSatellitesPositions(const Observations& obs, - const Navigation& nav, - const prcopt_t& opt, - std::map<int, Eigen::Vector3d>& sats_pos); -} // namespace GnssUtils -#endif // INCLUDE_GNSS_UTILS_UTILS_SAT_POSITION_H_ \ No newline at end of file diff --git a/include/gnss_utils/utils/satellite.h b/include/gnss_utils/utils/satellite.h new file mode 100644 index 0000000000000000000000000000000000000000..8ca85f3aaf937a36146e3d8dd02cfe65b6a641b6 --- /dev/null +++ b/include/gnss_utils/utils/satellite.h @@ -0,0 +1,34 @@ +/* + * sat_position.h + * + * Created on: April 3, 2020 + * Author: Joan Vallvé, Pep MartÃ-Saumell + */ + +#ifndef INCLUDE_GNSS_UTILS_UTILS_SAT_POSITION_H_ +#define INCLUDE_GNSS_UTILS_UTILS_SAT_POSITION_H_ + +#include <eigen3/Eigen/Dense> +#include <eigen3/Eigen/Geometry> + +#include <set> +#include <map> + + +namespace GnssUtils +{ + // forward declarations + class Observations; + class Navigation; + + typedef std::map<int,Eigen::Vector3d> SatellitesPositions; + + double computeSatElevation(const Eigen::Vector3d& receiver_ecef, const Eigen::Vector3d& sat_ecef); + + void computeSatellitesPositions(const Observations& obs, + const Navigation& nav, + const int& eph_opt, // see rtklib.h L396 + std::map<int, Eigen::Vector3d>& sats_pos); + +} // namespace GnssUtils +#endif // INCLUDE_GNSS_UTILS_UTILS_SAT_POSITION_H_ diff --git a/include/gnss_utils/utils/transformations.h b/include/gnss_utils/utils/transformations.h index caa22c473af8509cda43970bf7f98cdef05ed99f..10ddc0ac8462d9bd8636dc9a42d273cfcaed9a81 100644 --- a/include/gnss_utils/utils/transformations.h +++ b/include/gnss_utils/utils/transformations.h @@ -17,8 +17,8 @@ namespace GnssUtils { Eigen::Vector3d ecefToLatLonAlt(const Eigen::Vector3d& _ecef); Eigen::Vector3d latLonAltToEcef(const Eigen::Vector3d& _latlon); -Eigen::Matrix3d ecefToEnuCov(const Eigen::Vector3d& _latlon, const Eigen::Matrix3d _cov_ecef); -Eigen::Matrix3d enuToEcefCov(const Eigen::Vector3d& _latlon, const Eigen::Matrix3d _cov_enu); +Eigen::Matrix3d ecefToEnuCov(const Eigen::Vector3d& _latlon, const Eigen::Matrix3d& _cov_ecef); +Eigen::Matrix3d enuToEcefCov(const Eigen::Vector3d& _latlon, const Eigen::Matrix3d& _cov_enu); void computeEnuEcefFromEcef(const Eigen::Vector3d& _t_ECEF_ENU, Eigen::Matrix3d& R_ENU_ECEF, @@ -28,4 +28,4 @@ void computeEnuEcefFromLatLonAlt(const Eigen::Vector3d& _ENU_latlonalt, Eigen::Vector3d& t_ENU_ECEF); } // namespace GnssUtils -#endif // INCLUDE_GNSS_UTILS_UTILS_TRANSFORMATIONS_H_ \ No newline at end of file +#endif // INCLUDE_GNSS_UTILS_UTILS_TRANSFORMATIONS_H_ diff --git a/src/observations.cpp b/src/observations.cpp index f9d1e9393c8e0e34bbaa7ae53824c299676ef233..956c13f5b8b07b954f6e34a6ab0e84a3e158e63e 100644 --- a/src/observations.cpp +++ b/src/observations.cpp @@ -1,4 +1,5 @@ #include "gnss_utils/observations.h" +#include "gnss_utils/utils/satellite.h" using namespace GnssUtils; @@ -191,15 +192,216 @@ void Observations::print() } } -void Observations::findCommonObservations(const Observations& obs_1, - const Observations& obs_2, - Observations& common_obs_1, - Observations& common_obs_2) +std::set<int> Observations::filterByEphemeris(const SatellitesPositions& sats_pos) { - // clear and reserve - common_obs_1.clearObservations(); - common_obs_2.clearObservations(); + std::set<int> remove_sats; + for (int obs_i = 0; obs_i < obs_.size(); obs_i++) + { + auto&& obs_sat = getObservationByIdx(obs_i); + const int& sat_number = obs_sat.sat; + + // bad or inexistent satellite position (satellite is not included in the discarded list) + if (sats_pos.count(sat_number) == 0 or + sats_pos.at(sat_number).isApprox(Eigen::Vector3d::Zero(), 1e-3) or + sats_pos.at(sat_number).isApprox(Eigen::Vector3d::Zero(), 1e-3)) + { + std::cout << "Discarding sat " << sat_number << ": wrong satellite position: \n\t" << sats_pos.at(sat_number).transpose() << std::endl; + remove_sats.insert(sat_number); + } + } + + // remove sats + // std::cout << "removing: " << remove_sats.size() << " satellites" << std::endl; + for (auto sat : remove_sats) + { + assert(hasSatellite(sat)); + removeObservationBySat(sat); + } + + return remove_sats; +} + +std::set<int> Observations::filterBySatellites(const std::set<int>& discarded_sats) +{ + std::set<int> remove_sats; + + for (int obs_i = 0; obs_i < obs_.size(); obs_i++) + { + auto&& obs_sat = getObservationByIdx(obs_i); + const int& sat_number = obs_sat.sat; + + // discard sats + if (discarded_sats.count(sat_number) != 0) + remove_sats.insert(sat_number); + } + + // remove sats + // std::cout << "removing: " << remove_sats.size() << " satellites" << std::endl; + for (auto sat : remove_sats) + { + assert(hasSatellite(sat)); + removeObservationBySat(sat); + } + + return remove_sats; +} + +std::set<int> Observations::filterByCode() +{ + std::set<int> remove_sats; + + for (int obs_i = 0; obs_i < obs_.size(); obs_i++) + { + auto&& obs_sat = getObservationByIdx(obs_i); + const int& sat_number = obs_sat.sat; + + // wrong data + if (std::abs(obs_sat.P[0]) < 1e-12) + { + std::cout << "Discarding sat " << sat_number << ": wrong code data: " << obs_sat.P[0] << std::endl; + remove_sats.insert(sat_number); + } + } + + // remove sats + // std::cout << "removing: " << remove_sats.size() << " satellites" << std::endl; + for (auto sat : remove_sats) + { + assert(hasSatellite(sat)); + removeObservationBySat(sat); + } + + return remove_sats; +} + +std::set<int> Observations::filterByCarrierPhase() +{ + std::set<int> remove_sats; + + for (int obs_i = 0; obs_i < obs_.size(); obs_i++) + { + auto&& obs_sat = getObservationByIdx(obs_i); + const int& sat_number = obs_sat.sat; + + // wrong data + if (std::abs(obs_sat.L[0]) < 1e-12) + { + std::cout << "Discarding sat " << sat_number << ": wrong carrier phase data: " << obs_sat.L[0] << std::endl; + remove_sats.insert(sat_number); + } + } + + // remove sats + // std::cout << "removing: " << remove_sats.size() << " satellites" << std::endl; + for (auto sat : remove_sats) + { + assert(hasSatellite(sat)); + removeObservationBySat(sat); + } + + return remove_sats; +} + +std::set<int> Observations::filterByConstellations(const int& navsys) +{ + std::set<int> remove_sats; + + for (int obs_i = 0; obs_i < obs_.size(); obs_i++) + { + auto&& obs_sat = getObservationByIdx(obs_i); + const int& sat_number = obs_sat.sat; + + // constellation + int sys = satsys(obs_sat.sat, NULL); + if (!(sys & navsys)) + { + std::cout << "Discarding sat " << sat_number << ": not selected constellation " << sys << " - mask: " << navsys << std::endl; + remove_sats.insert(sat_number); + continue; + } + } + + // remove sats + // std::cout << "removing: " << remove_sats.size() << " satellites" << std::endl; + for (auto sat : remove_sats) + { + assert(hasSatellite(sat)); + removeObservationBySat(sat); + } + + return remove_sats; +} + +std::set<int> Observations::filterByElevationSnr(const Eigen::Vector3d& x_r, + const SatellitesPositions& sats_pos, + const snrmask_t& snrmask, + const double& elmin) +{ + std::set<int> remove_sats; + + for (int obs_i = 0; obs_i < obs_.size(); obs_i++) + { + auto&& obs_sat = getObservationByIdx(obs_i); + const int& sat_number = obs_sat.sat; + + // check elevation + double elevation = computeSatElevation(x_r, sats_pos.at(sat_number)); + if (elevation < elmin) + { + std::cout << "Discarding sat " << sat_number << ": low elevation " << elevation << " - min: " << elmin << std::endl; + remove_sats.insert(sat_number); + continue; + } + + // snr TODO: multifrequency (2nd param and 3rd idx) + if (testsnr(0, 0, elevation, obs_sat.SNR[0] * 0.25, &snrmask) == 1) + { + std::cout << "Discarding sat " << sat_number << ": snr test " << std::endl; + remove_sats.insert(sat_number); + } + } + + // remove sats + // std::cout << "removing: " << remove_sats.size() << " satellites" << std::endl; + for (auto sat : remove_sats) + { + assert(hasSatellite(sat)); + removeObservationBySat(sat); + } + + return remove_sats; +} + +std::set<int> Observations::filter(const SatellitesPositions& sats_pos, + const std::set<int>& discarded_sats, + const Eigen::Vector3d& x_r, + const bool& check_code, + const bool& check_carrier_phase, + const prcopt_t& opt) +{ + //std::cout << "filter: initial size: " << obs_.size() << std::endl; + + std::set<int> remove_sats_1 = filterByEphemeris(sats_pos); + std::set<int> remove_sats_2 = filterBySatellites(discarded_sats); + std::set<int> remove_sats_3 = filterByCode(); + std::set<int> remove_sats_4 = filterByCarrierPhase(); + std::set<int> remove_sats_5 = filterByConstellations(opt.navsys); + std::set<int> remove_sats_6 = filterByElevationSnr(x_r, sats_pos, opt.snrmask, opt.elmin); + + remove_sats_1.insert(remove_sats_2.begin(), remove_sats_2.end()); + remove_sats_1.insert(remove_sats_3.begin(), remove_sats_3.end()); + remove_sats_1.insert(remove_sats_4.begin(), remove_sats_4.end()); + remove_sats_1.insert(remove_sats_5.begin(), remove_sats_5.end()); + remove_sats_1.insert(remove_sats_6.begin(), remove_sats_6.end()); + + return remove_sats_1; + // std::cout << "final size: " << obs_.size() << std::endl; +} + +std::set<int> Observations::findCommonObservations(const Observations& obs_1, + const Observations& obs_2) +{ // std::cout << "obs 1 sats: "; // for (auto&& obs_1_ref : obs_1.getObservations()) // std::cout << (int)obs_1_ref.sat << " "; @@ -209,20 +411,22 @@ void Observations::findCommonObservations(const Observations& obs_1, // std::cout << (int)obs_2_ref.sat << " "; // std::cout << std::endl; + std::set<int> common_sats; + // iterate 1 for (auto&& obs_1_ref : obs_1.getObservations()) if (obs_2.hasSatellite(obs_1_ref.sat)) - { - common_obs_1.addObservation(obs_1_ref); - common_obs_2.addObservation(obs_2.getObservationBySat(obs_1_ref.sat)); - } + common_sats.insert(obs_1_ref.sat); // std::cout << "common sats: "; - // for (auto&& obs_2_ref : common_obs_1.getObservations()) - // std::cout << (int)obs_2_ref.sat << " "; + // for (auto sat : common_sats) + // std::cout << sat << " "; // std::cout << std::endl; + + return common_sats; } + bool Observations::operator ==(const Observations &other_obs) const { diff --git a/src/snapshot.cpp b/src/snapshot.cpp new file mode 100644 index 0000000000000000000000000000000000000000..87a08ede1ce51e16b1dd3809aeb2039d553d9c23 --- /dev/null +++ b/src/snapshot.cpp @@ -0,0 +1,32 @@ +#include "gnss_utils/snapshot.h" +#include "gnss_utils/utils/satellite.h" + +using namespace GnssUtils; + +Snapshot::Snapshot() + : obs_(nullptr) + , nav_(nullptr) +{ + // +} + +Snapshot::Snapshot(ObservationsPtr obs, NavigationPtr nav) + : obs_(obs) + , nav_(nav) +{ + // +} + +void Snapshot::loadFromRinex(const std::string& rnx_file, gtime_t t_start, gtime_t t_end, double dt, const char* opt) +{ + throw std::runtime_error("not implemented!"); +} + +void Snapshot::computeSatellitesPositions(const int& eph_opt) +{ + assert(obs_!=nullptr && "null obs"); + assert(nav_!=nullptr && "null nav"); + assert(!satellitesPositionsComputed() && "satellites positions already computed"); + + GnssUtils::computeSatellitesPositions(*obs_, *nav_, eph_opt, sats_pos_); +} diff --git a/src/tdcp.cpp b/src/tdcp.cpp index b38f9e26bd0924f693d045437f3477245af4810d..e105a695def616b479c87357d16db09d56da8e91 100644 --- a/src/tdcp.cpp +++ b/src/tdcp.cpp @@ -1,579 +1,470 @@ -/* - * tdcp.cpp - * - * Created on: Dec 4, 2019 - * Author: jvallve - */ - #include "gnss_utils/tdcp.h" +#include "gnss_utils/utils/rcv_position.h" +#include "gnss_utils/utils/satellite.h" +#include "gnss_utils/snapshot.h" namespace GnssUtils { -bool Tdcp(const Observations& obs_r, - Navigation& nav_r, - const Observations& obs_k, - const Navigation& nav_k, +bool Tdcp(SnapshotPtr snapshot_r, + SnapshotPtr snapshot_k, Eigen::Vector4d& d, Eigen::Matrix4d& cov_d, double& residual, - std::set<int>& discarded_sats, + const std::set<int>& discarded_sats, + std::set<int>& raim_discarded_sats, const TdcpParams& sd_params, const prcopt_t& opt) { - // COMPUTE SINGLE DIFFERENCES - return Tdcp(obs_r, - nav_r, - computePos(obs_r, nav_r, opt).pos, - obs_k, - nav_k, - d, - cov_d, - residual, - discarded_sats, - sd_params, - opt); + return Tdcp(snapshot_r, + snapshot_k, + computePos(*snapshot_r->getObservations(), *snapshot_r->getNavigation(), opt).pos, + d, + cov_d, + residual, + discarded_sats, + raim_discarded_sats, + sd_params, + opt); } -bool Tdcp(const Observations& obs_r, - const Navigation& nav_r, +bool Tdcp(SnapshotPtr snapshot_r, + SnapshotPtr snapshot_k, const Eigen::Vector3d& x_r, - const Observations& obs_k, - const Navigation& nav_k, Eigen::Vector4d& d, Eigen::Matrix4d& cov_d, double& residual, - std::set<int>& discarded_sats, + const std::set<int>& discarded_sats, + std::set<int>& raim_discarded_sats, const TdcpParams& sd_params, const prcopt_t& opt) { - // FIND COMMON SATELLITES OBSERVATIONS - Observations common_obs_r, common_obs_k; - Observations::findCommonObservations(obs_r, obs_k, common_obs_r, common_obs_k); - int n_common_sats = common_obs_r.getObservations().size(); - - // COMPUTE COMMON SATELLITES POSITION - std::map<int, Eigen::Vector3d> common_sats_pos_r, common_sats_pos_k; - computeSatellitesPositions(common_obs_r, nav_r, opt, common_sats_pos_r); - computeSatellitesPositions(common_obs_k, sd_params.use_old_nav ? nav_r : nav_k, opt, common_sats_pos_k); - - // FILTER SATELLITES (ALREADY DISCARDED, CORRUPTED DATA, WRONG POSITION, CONSTELLATION, ELEVATION and SNR) - filterCommonSatellites( - common_obs_r, common_sats_pos_r, common_obs_k, common_sats_pos_k, discarded_sats, x_r, sd_params, opt); - - // COMPUTE SINGLE DIFFERENCES - return Tdcp(common_obs_r, - nav_r, - common_sats_pos_r, - x_r, - common_obs_k, - nav_k, - common_sats_pos_k, - d, - cov_d, - residual, - discarded_sats, - sd_params); -} - -bool Tdcp(const Observations& common_obs_r, - const Navigation& nav_r, - const std::map<int, Eigen::Vector3d>& common_sats_pos_r, - const Eigen::Vector3d& x_r, - const Observations& common_obs_k, - const Navigation& nav_k, - const std::map<int, Eigen::Vector3d>& common_sats_pos_k, - Eigen::Vector4d& d, - Eigen::Matrix4d& cov_d, - double& residual, - std::set<int>& discarded_sats, - const TdcpParams& sd_params) -{ - assert(common_obs_r.size() == common_obs_k.size()); - assert(common_obs_r.size() == common_sats_pos_r.size()); - assert(common_obs_k.size() == common_sats_pos_k.size()); - - double tr(common_obs_r.getObservations().front().time.time + common_obs_r.getObservations().front().time.sec); - double tk(common_obs_k.getObservations().front().time.time + common_obs_k.getObservations().front().time.sec); - - int required_n_sats(std::max(sd_params.min_common_sats + sd_params.raim_n, 4 + sd_params.raim_n)); - int n_common_sats = common_sats_pos_k.size(); - - if (n_common_sats < required_n_sats) - { -#if GNSS_UTILS_TDCP_DEBUG == 1 - printf("Tdcp: NOT ENOUGH COMMON SATS"); - printf("Tdcp: %i common sats available, %i sats are REQUIRED. [ SKIPPING Tdcp ]", n_common_sats, required_n_sats); -#endif - return false; - } - - // MULTI-FREQUENCY - std::map<int, std::pair<int, int>> row_2_sat_freq; - int row = 0; - for (auto obs_idx = 0; obs_idx < common_obs_k.size(); obs_idx++) - { - auto&& obs_r = common_obs_r.getObservationByIdx(obs_idx); - auto&& obs_k = common_obs_k.getObservationByIdx(obs_idx); - - const int& sat_number = obs_k.sat; - - if (sd_params.use_carrier_phase) + // If use old nav temporary change navigation to (re)compute satellites positions + auto nav_k = snapshot_k->getNavigation(); + if (sd_params.use_old_nav) { - // L1/E1 - if (std::abs(obs_r.L[0]) > 1e-12 and std::abs(obs_k.L[0]) > 1e-12) - { - row_2_sat_freq[row] = std::make_pair(sat_number, 0); - row++; - } - if (!sd_params.use_multi_freq) - continue; - - // L2 (GPS/GLO/QZS) - int sys = satsys(sat_number, NULL); - if (NFREQ >= 2 and (sys & (SYS_GPS | SYS_GLO | SYS_QZS)) and std::abs(obs_r.L[1]) > 1e-12 and - std::abs(obs_k.L[1]) > 1e-12) - { - row_2_sat_freq[row] = std::make_pair(sat_number, 1); - row++; - } - // E5 (GAL) - else if (NFREQ >= 3 and (sys & SYS_GAL) and std::abs(obs_r.L[2]) > 1e-12 and std::abs(obs_k.L[2]) > 1e-12) - { - row_2_sat_freq[row] = std::make_pair(sat_number, 2); - row++; - } + snapshot_k->getSatellitesPositions().clear(); + snapshot_k->setNavigation(snapshot_r->getNavigation()); } - else - // L1/E1 - if (std::abs(obs_r.P[0]) > 1e-12 and std::abs(obs_k.P[0]) > 1e-12) + + // COMPUTE SATELLITES POSITION + if (!snapshot_r->satellitesPositionsComputed()) + snapshot_r->computeSatellitesPositions(opt.sateph); + if (!snapshot_k->satellitesPositionsComputed()) + snapshot_k->computeSatellitesPositions(opt.sateph); + + // FILTER SATELLITES (ALREADY DISCARDED, CORRUPTED DATA, WRONG POSITION, CONSTELLATION, ELEVATION and SNR) + snapshot_r->getObservations()->filter(snapshot_r->getSatellitesPositions(), + discarded_sats, + x_r, + !sd_params.use_carrier_phase, + sd_params.use_carrier_phase, + opt); + snapshot_k->getObservations()->filter(snapshot_k->getSatellitesPositions(), + discarded_sats, + x_r, + !sd_params.use_carrier_phase, + sd_params.use_carrier_phase, + opt); + + // FIND COMMON SATELLITES OBSERVATIONS + std::set<int> common_sats = Observations::findCommonObservations(*snapshot_r->getObservations(), + *snapshot_k->getObservations()); + + // COMPUTE TDCP + bool tdcp_ok = Tdcp(snapshot_r, + snapshot_k, + x_r, + common_sats, + d, + cov_d, + residual, + raim_discarded_sats, + sd_params); + + // UNDO temporary change navigation + if (sd_params.use_old_nav) { - row_2_sat_freq[row] = std::make_pair(sat_number, 0); - row++; + snapshot_k->setNavigation(nav_k); + snapshot_k->computeSatellitesPositions(opt.sateph); } - } - int n_differences = row_2_sat_freq.size(); - - // Initial guess - Eigen::Vector4d d_0(d), delta_d(Eigen::Vector4d::Zero()); - -#if GNSS_UTILS_TDCP_DEBUG == 1 - std::cout << "Receiver at t_r: " << x_r.transpose() << std::endl; - std::cout << "d initial guess: " << d_0.transpose() << std::endl; - std::cout << "common sats: "; - for (auto row_sat_freq_it : row_2_sat_freq) - std::cout << row_sat_freq_it.second.first << " "; - std::cout << std::endl; - std::cout << "discarded_sats: "; - for (auto sat : discarded_sats) - std::cout << sat << " "; - std::cout << std::endl; -#endif - - // FILL SATELLITES POSITIONS AND MEASUREMENTS ======================================================================= - Eigen::Matrix<double, Eigen::Dynamic, 4> A(Eigen::Matrix<double, Eigen::Dynamic, 4>::Zero(n_differences, 4)); - Eigen::VectorXd r(Eigen::VectorXd::Zero(n_differences)); - Eigen::VectorXd drho_m(Eigen::VectorXd::Zero(n_differences)); - Eigen::Matrix<double, 3, Eigen::Dynamic> s_k(Eigen::Matrix<double, 3, Eigen::Dynamic>::Zero(3, n_differences)); - Eigen::Matrix<double, 3, Eigen::Dynamic> s_r(Eigen::Matrix<double, 3, Eigen::Dynamic>::Zero(3, n_differences)); - int sat_i = 0; - - for (auto row_sat_freq_it : row_2_sat_freq) - { - const int& row = row_sat_freq_it.first; - const int& sat_number = row_sat_freq_it.second.first; - const int& freq = row_sat_freq_it.second.second; - - auto obs_r = common_obs_r.getObservationBySat(sat_number); - auto obs_k = common_obs_k.getObservationBySat(sat_number); - - // excluded satellite - if (discarded_sats.count(sat_number) != 0) + + return tdcp_ok; +} + +bool Tdcp(SnapshotPtr snapshot_r, + SnapshotPtr snapshot_k, + const Eigen::Vector3d& x_r, + const std::set<int> common_sats, + Eigen::Vector4d& d, + Eigen::Matrix4d& cov_d, + double& residual, + std::set<int> raim_discarded_sats, + const TdcpParams& sd_params) +{ + // Checks + assert(snapshot_r->satellitesPositionsComputed() && "this TDCP assumes satellites already computed"); + assert(snapshot_k->satellitesPositionsComputed() && "this TDCP assumes satellites already computed"); + assert(snapshot_r->getSatellitesPositions().size() > snapshot_r->getObservations()->size() && "Satellites without position not filtered"); + assert(snapshot_k->getSatellitesPositions().size() > snapshot_k->getObservations()->size() && "Satellites without position not filtered"); + assert(snapshot_r->getSatellitesPositions().size() > common_sats.size() && "Too many common sats"); + assert(snapshot_k->getSatellitesPositions().size() > common_sats.size() && "Too many common sats"); + assert(raim_discarded_sats.empty() && "just output param"); + + for (auto sat : common_sats) { -#if GNSS_UTILS_TDCP_DEBUG == 1 - std::cout << "\tdiscarded sat" << std::endl; -#endif - continue; + assert(snapshot_r->getObservations()->hasSatellite(sat) && "wrong common sat"); + assert(snapshot_k->getObservations()->hasSatellite(sat) && "wrong common sat"); + assert(snapshot_r->getSatellitesPositions().count(sat) && "common sat without position"); + assert(snapshot_k->getSatellitesPositions().count(sat) && "common sat without position"); } - // Satellite's positions - s_r.col(row) = common_sats_pos_r.at(sat_number); - s_k.col(row) = common_sats_pos_k.at(sat_number); - nav_k.getNavigation().ion_gps; - - if (sd_params.use_carrier_phase) // TODO: add iono and tropo corrections (optionally) - drho_m(row) = (obs_k.L[freq] * nav_k.getNavigation().lam[sat_number - 1][freq]) - - (obs_r.L[freq] * nav_r.getNavigation().lam[sat_number - 1][freq]); - else - drho_m(row) = obs_k.P[freq] - obs_r.P[freq]; - -#if GNSS_UTILS_TDCP_DEBUG == 1 - // std::cout << "\tsat " << sat_number << " frequency " << freq << " wavelength = " << - // nav_r.getNavigation().lam[sat_number-1][freq] << std::endl; std::cout << "\tpositions:\n\t\tt_r: " << - // s_r.col(row).transpose() << "\n\t\tt_k: " << s_k.col(row).transpose() << std::endl; std::cout << "\tobs_r.L: " - // << obs_r.L[freq] << std::endl; std::cout << "\tobs_k.L: " << obs_k.L[freq] << std::endl; std::cout << - // "\tnav_r.getNavigation().lam[sat_number-1][freq]: " << nav_r.getNavigation().lam[sat_number-1][freq] << - // std::endl; std::cout << "\tnav_k.getNavigation().lam[sat_number-1][freq]: " << - // nav_k.getNavigation().lam[sat_number-1][freq] << std::endl; std::cout << "\trho_r: " << obs_r.L[freq] * - // nav_r.getNavigation().lam[sat_number-1][freq] << std::endl; std::cout << "\trho_k: " << obs_k.L[freq] * - // nav_k.getNavigation().lam[sat_number-1][freq] << std::endl; std::cout << "\tdrho_m: " << drho_m(row) << - // std::endl; -#endif - - if (!sd_params.relinearize_jacobian) + int n_common_sats = common_sats.size(); + int required_n_sats(std::max(sd_params.min_common_sats + sd_params.raim_n, 4 + sd_params.raim_n)); + if (n_common_sats < required_n_sats) { - // Unit vectors from receivers to satellites - Eigen::Vector3d u_k = (s_k.col(row) - x_r - d.head(3)).normalized(); - - // Fill Jacobian matrix - A(row, 0) = u_k(0); - A(row, 1) = u_k(1); - A(row, 2) = u_k(2); - A(row, 3) = -1.0; + #if GNSS_UTILS_TDCP_DEBUG == 1 + printf("Tdcp: NOT ENOUGH COMMON SATS"); + printf("Tdcp: %i common sats available, %i sats are REQUIRED. [ SKIPPING Tdcp ]", n_common_sats, required_n_sats); + #endif + return false; } - } - // LEAST SQUARES SOLUTION ======================================================================= - for (int j = 0; j < sd_params.max_iterations; j++) - { - // fill A and r - for (int row = 0; row < A.rows(); row++) + // Times + double tr(-1), tk(-1); + + // MULTI-FREQUENCY + std::map<int, std::pair<int, int>> row_2_sat_freq; + int row = 0; + for (auto sat : common_sats) { - // Evaluate r - r(row) = drho_m(row) - (s_k.col(row) - x_r - d.head(3)).norm() + (s_r.col(row) - x_r).norm() - d(3); - - // Evaluate A - if (sd_params.relinearize_jacobian) - { - // Unit vectors from rcvrs to sats - Eigen::Vector3d u_k = (s_k.col(row) - x_r - d.head(3)).normalized(); - - // Fill Jacobian matrix - A(row, 0) = u_k(0); - A(row, 1) = u_k(1); - A(row, 2) = u_k(2); - A(row, 3) = -1.0; - } + assert(snapshot_r->getObservations()->hasSatellite(sat)); + assert(snapshot_k->getObservations()->hasSatellite(sat)); + + auto&& obs_r = snapshot_r->getObservations()->getObservationBySat(sat); + auto&& obs_k = snapshot_k->getObservations()->getObservationBySat(sat); + + // fill times + if (tr < 0) + { + tr = obs_r.time.time + obs_r.time.sec; + tk = obs_k.time.time + obs_k.time.sec; + } + + // Carrier phase + if (sd_params.use_carrier_phase) + { + // L1/E1 + if (std::abs(obs_r.L[0]) > 1e-12 and std::abs(obs_k.L[0]) > 1e-12) + row_2_sat_freq[row++] = std::make_pair(sat, 0); + + if (!sd_params.use_multi_freq) + continue; + + // L2 (GPS/GLO/QZS) + int sys = satsys(sat, NULL); + if (NFREQ >= 2 and (sys & (SYS_GPS | SYS_GLO | SYS_QZS)) and std::abs(obs_r.L[1]) > 1e-12 and + std::abs(obs_k.L[1]) > 1e-12) + row_2_sat_freq[row++] = std::make_pair(sat, 1); + + // E5 (GAL) + else if (NFREQ >= 3 and (sys & SYS_GAL) and std::abs(obs_r.L[2]) > 1e-12 and std::abs(obs_k.L[2]) > 1e-12) + row_2_sat_freq[row++] = std::make_pair(sat, 2); + } + // Code + else + // L1/E1 + if (std::abs(obs_r.P[0]) > 1e-12 and std::abs(obs_k.P[0]) > 1e-12) + row_2_sat_freq[row++] = std::make_pair(sat, 0); } + int n_differences = row_2_sat_freq.size(); - // Solve - cov_d = (A.transpose() * A).inverse(); - delta_d = -cov_d * A.transpose() * r; - d += delta_d; + // Initial guess + Eigen::Vector4d d_0(d), delta_d(Eigen::Vector4d::Zero()); + + #if GNSS_UTILS_TDCP_DEBUG == 1 + std::cout << "Receiver at t_r: " << x_r.transpose() << std::endl; + std::cout << "d initial guess: " << d_0.transpose() << std::endl; + std::cout << "common sats: "; + for (auto row_sat_freq_it : row_2_sat_freq) + std::cout << row_sat_freq_it.second.first << " "; + std::cout << std::endl; + #endif - // wrong solution - if (d.array().isNaN().any()) + // FILL SATELLITES POSITIONS AND MEASUREMENTS ======================================================================= + Eigen::Matrix<double, Eigen::Dynamic, 4> A(Eigen::Matrix<double, Eigen::Dynamic, 4>::Zero(n_differences, 4)); + Eigen::VectorXd r(Eigen::VectorXd::Zero(n_differences)); + Eigen::VectorXd drho_m(Eigen::VectorXd::Zero(n_differences)); + Eigen::Matrix<double, 3, Eigen::Dynamic> s_k(Eigen::Matrix<double, 3, Eigen::Dynamic>::Zero(3, n_differences)); + Eigen::Matrix<double, 3, Eigen::Dynamic> s_r(Eigen::Matrix<double, 3, Eigen::Dynamic>::Zero(3, n_differences)); + int sat_i = 0; + + for (auto row_sat_freq_it : row_2_sat_freq) { - std::cout << "Tdcp: LSM DID NOT WORK. NAN values appeared. ABORTING!!" << std::endl; - return false; + const int& row = row_sat_freq_it.first; + const int& sat_number = row_sat_freq_it.second.first; + const int& freq = row_sat_freq_it.second.second; + + auto obs_r = snapshot_r->getObservations()->getObservationBySat(sat_number); + auto obs_k = snapshot_k->getObservations()->getObservationBySat(sat_number); + auto nav_r = snapshot_r->getNavigation()->getNavigation(); + auto nav_k = snapshot_k->getNavigation()->getNavigation(); + + // Satellite's positions + s_r.col(row) = snapshot_r->getSatellitesPositions().at(sat_number); + s_k.col(row) = snapshot_r->getSatellitesPositions().at(sat_number); + nav_k.ion_gps; + + if (sd_params.use_carrier_phase) // TODO: add iono and tropo corrections (optionally) + drho_m(row) = (obs_k.L[freq] * nav_k.lam[sat_number - 1][freq]) - + (obs_r.L[freq] * nav_r.lam[sat_number - 1][freq]); + else + drho_m(row) = obs_k.P[freq] - obs_r.P[freq]; + + #if GNSS_UTILS_TDCP_DEBUG == 1 + // std::cout << "\tsat " << sat_number << " frequency " << freq << " wavelength = " << + // nav_r.getNavigation().lam[sat_number-1][freq] << std::endl; std::cout << "\tpositions:\n\t\tt_r: " << + // s_r.col(row).transpose() << "\n\t\tt_k: " << s_k.col(row).transpose() << std::endl; std::cout << "\tobs_r.L: " + // << obs_r.L[freq] << std::endl; std::cout << "\tobs_k.L: " << obs_k.L[freq] << std::endl; std::cout << + // "\tnav_r.getNavigation().lam[sat_number-1][freq]: " << nav_r.getNavigation().lam[sat_number-1][freq] << + // std::endl; std::cout << "\tnav_k.getNavigation().lam[sat_number-1][freq]: " << + // nav_k.getNavigation().lam[sat_number-1][freq] << std::endl; std::cout << "\trho_r: " << obs_r.L[freq] * + // nav_r.getNavigation().lam[sat_number-1][freq] << std::endl; std::cout << "\trho_k: " << obs_k.L[freq] * + // nav_k.getNavigation().lam[sat_number-1][freq] << std::endl; std::cout << "\tdrho_m: " << drho_m(row) << + // std::endl; + #endif + + if (!sd_params.relinearize_jacobian) + { + // Unit vectors from receivers to satellites + Eigen::Vector3d u_k = (s_k.col(row) - x_r - d.head(3)).normalized(); + + // Fill Jacobian matrix + A(row, 0) = u_k(0); + A(row, 1) = u_k(1); + A(row, 2) = u_k(2); + A(row, 3) = -1.0; + } } - // residual - // residual = sqrt((r - A * delta_d).squaredNorm() / A.rows()); - residual = (r + A * delta_d).norm(); - // std::cout << "residual = " << residual << std::endl; - // std::cout << "Tdcp2: r-A*delta_d = " << (r + A * delta_d).transpose() << std::endl; - -#if GNSS_UTILS_TDCP_DEBUG == 1 - std::cout << "Displacement vector =" << d.head<3>().transpose() << std::endl; - std::cout << "Displacement update =" << delta_d.head<3>().transpose() << std::endl; - printf("Ref distance = %7.3f m\n", d_0.norm()); - printf("Computed distance = %7.3f m\n", d.head<3>().norm()); - printf("Tdcp: residual = %13.10f\n", residual); - printf("Tdcp: row = %i\n", r.rows()); - std::cout << "Tdcp: drho = " << r.transpose() << std::endl; - std::cout << "Tdcp: drho_m = " << drho_m.transpose() << std::endl; - std::cout << "Tdcp: H = \n" << A << std::endl; - printf("Tdcp: dT = %8.3f secs\n", d(3)); -#endif - - // RAIM ====================================== (only at first iteration) RAIM WITH SATELLITES, not ROWS - int input_discarded_sats = discarded_sats.size(); - if (j == 0 and sd_params.raim_n > 0 and residual > sd_params.raim_min_residual) + // LEAST SQUARES SOLUTION ======================================================================= + for (int j = 0; j < sd_params.max_iterations; j++) { - int worst_sat_row = -1; - double best_residual = 1e12; - Eigen::Vector4d best_d; - int n_removed_rows = 1; - - // remove some satellites - while (discarded_sats.size() - input_discarded_sats < sd_params.raim_n) - { - auto A_raim = A; - auto r_raim = r; - - // solve removing each satellite - for (int row_removed = 0; row_removed < A_raim.rows(); row_removed++) + // fill A and r + for (int row = 0; row < A.rows(); row++) { - int sat_removed = row_2_sat_freq.at(row_removed).first; - - // Multi-freq: some rows for the same satellite - n_removed_rows = 1; - if (sd_params.use_multi_freq) - while (row_removed + n_removed_rows < A_raim.rows() and - row_2_sat_freq.at(row_removed + n_removed_rows).first == sat_removed) - n_removed_rows++; - - // remove satellite rows - for (auto r = 0; r < n_removed_rows; r++) - { - A_raim.row(row_removed + r) = Eigen::Vector4d::Zero().transpose(); - r_raim(row_removed + r) = 0; // not necessary - } - - // solve - Eigen::Vector4d delta_d_raim = -(A_raim.transpose() * A_raim).inverse() * A_raim.transpose() * r_raim; - Eigen::Vector4d d_raim = d_0 + delta_d_raim; - - // no NaN - if (!d_raim.array().isNaN().any()) - { - // residual - residual = (r_raim + A_raim * delta_d_raim).norm() / (A_raim.rows() - 1); - // residual = sqrt((r_raim + A_raim * delta_d_raim).squaredNorm() / A_raim.rows()); - -#if GNSS_UTILS_TDCP_DEBUG == 1 - std::cout << "RAIM excluding sat " << sat_removed << " - row " << row_removed << "(n_rows " - << n_removed_rows << ")" << std::endl; - std::cout << "Displacement vector =" << d_raim.head<3>().transpose() << std::endl; - std::cout << "Displacement update =" << delta_d_raim.head<3>().transpose() << std::endl; - printf("Ref distance = %7.3f m\n", d_0.norm()); - printf("Computed distance = %7.3f m\n", d_raim.head<3>().norm()); - printf("Tdcp: residual = %13.10f\n", residual); - std::cout << "Tdcp: drho = " << r_raim.transpose() << std::endl; - std::cout << "Tdcp: H = \n" << A_raim << std::endl; - printf("Tdcp: dT = %8.3f secs\n", d_raim(3)); -#endif - // store if best residual - if (residual < best_residual) + // Evaluate r + r(row) = drho_m(row) - (s_k.col(row) - x_r - d.head(3)).norm() + (s_r.col(row) - x_r).norm() - d(3); + + // Evaluate A + if (sd_params.relinearize_jacobian) { - worst_sat_row = row_removed; - best_residual = residual; - best_d = d_raim; + // Unit vectors from rcvrs to sats + Eigen::Vector3d u_k = (s_k.col(row) - x_r - d.head(3)).normalized(); + + // Fill Jacobian matrix + A(row, 0) = u_k(0); + A(row, 1) = u_k(1); + A(row, 2) = u_k(2); + A(row, 3) = -1.0; } - } - // restore initial A and r - for (auto row = 0; row < n_removed_rows; row++) - { - A_raim.row(row_removed + row) = A.row(row_removed + row); - r_raim(row_removed + row) = r(row_removed + row); - } - row_removed += (n_removed_rows - 1); } - // No successful RAIM solution - if (worst_sat_row == -1) + // Solve + cov_d = (A.transpose() * A).inverse(); + delta_d = -cov_d * A.transpose() * r; + d += delta_d; + + // wrong solution + if (d.array().isNaN().any()) { - printf("Tdcp: LS after RAIM DID NOT WORK. NAN values appeared. ABORTING!!"); - return false; + std::cout << "Tdcp: LSM DID NOT WORK. NAN values appeared. ABORTING!!" << std::endl; + return false; } - // store removed sat - discarded_sats.insert(row_2_sat_freq[worst_sat_row].first); - - // decrease n_common_sats - n_differences -= n_removed_rows; - n_common_sats--; - - // Remove selected satellite from problem - std::cout << "resizing problem..." << std::endl; - auto A_aux = A; - auto r_aux = r; - auto drho_m_aux = drho_m; - auto s_r_aux = s_r; - auto s_k_aux = s_k; - A.conservativeResize(n_differences, Eigen::NoChange); - r.conservativeResize(n_differences); - drho_m.conservativeResize(n_differences); - s_r.conservativeResize(Eigen::NoChange, n_differences); - s_k.conservativeResize(Eigen::NoChange, n_differences); - - int back_elements_changing = A_aux.rows() - worst_sat_row - n_removed_rows; - if (back_elements_changing != 0) // if last satelite removed, conservative resize did the job + // residual + // residual = sqrt((r - A * delta_d).squaredNorm() / A.rows()); + residual = (r + A * delta_d).norm(); + // std::cout << "residual = " << residual << std::endl; + // std::cout << "Tdcp2: r-A*delta_d = " << (r + A * delta_d).transpose() << std::endl; + + #if GNSS_UTILS_TDCP_DEBUG == 1 + std::cout << "Displacement vector =" << d.head<3>().transpose() << std::endl; + std::cout << "Displacement update =" << delta_d.head<3>().transpose() << std::endl; + printf("Ref distance = %7.3f m\n", d_0.norm()); + printf("Computed distance = %7.3f m\n", d.head<3>().norm()); + printf("Tdcp: residual = %13.10f\n", residual); + printf("Tdcp: row = %lu\n", r.rows()); + std::cout << "Tdcp: drho = " << r.transpose() << std::endl; + std::cout << "Tdcp: drho_m = " << drho_m.transpose() << std::endl; + std::cout << "Tdcp: H = \n" << A << std::endl; + printf("Tdcp: dT = %8.3f secs\n", d(3)); + #endif + + // RAIM ====================================== (only at first iteration) RAIM WITH SATELLITES, not ROWS + if (j == 0 and sd_params.raim_n > 0 and residual > sd_params.raim_min_residual) { - A.bottomRows(back_elements_changing) = A_aux.bottomRows(back_elements_changing); - s_r.rightCols(back_elements_changing) = s_r_aux.rightCols(back_elements_changing); - s_k.rightCols(back_elements_changing) = s_k_aux.rightCols(back_elements_changing); - r.tail(back_elements_changing) = r_aux.tail(back_elements_changing); - drho_m.tail(back_elements_changing) = drho_m_aux.tail(back_elements_changing); - } + int worst_sat_row = -1; + double best_residual = 1e12; + Eigen::Vector4d best_d; + int n_removed_rows = 1; + + // remove some satellites + while (raim_discarded_sats.size() < sd_params.raim_n) + { + auto A_raim = A; + auto r_raim = r; + + // solve removing each satellite + for (int row_removed = 0; row_removed < A_raim.rows(); row_removed++) + { + int sat_removed = row_2_sat_freq.at(row_removed).first; + + // Multi-freq: some rows for the same satellite + n_removed_rows = 1; + if (sd_params.use_multi_freq) + while (row_removed + n_removed_rows < A_raim.rows() and + row_2_sat_freq.at(row_removed + n_removed_rows).first == sat_removed) + n_removed_rows++; + + // remove satellite rows + for (auto r = 0; r < n_removed_rows; r++) + { + A_raim.row(row_removed + r) = Eigen::Vector4d::Zero().transpose(); + r_raim(row_removed + r) = 0; // not necessary + } + + // solve + Eigen::Vector4d delta_d_raim = -(A_raim.transpose() * A_raim).inverse() * A_raim.transpose() * r_raim; + Eigen::Vector4d d_raim = d_0 + delta_d_raim; + + // no NaN + if (!d_raim.array().isNaN().any()) + { + // residual + residual = (r_raim + A_raim * delta_d_raim).norm() / (A_raim.rows() - 1); + // residual = sqrt((r_raim + A_raim * delta_d_raim).squaredNorm() / A_raim.rows()); + + #if GNSS_UTILS_TDCP_DEBUG == 1 + std::cout << "RAIM excluding sat " << sat_removed << " - row " << row_removed << "(n_rows " + << n_removed_rows << ")" << std::endl; + std::cout << "Displacement vector =" << d_raim.head<3>().transpose() << std::endl; + std::cout << "Displacement update =" << delta_d_raim.head<3>().transpose() << std::endl; + printf("Ref distance = %7.3f m\n", d_0.norm()); + printf("Computed distance = %7.3f m\n", d_raim.head<3>().norm()); + printf("Tdcp: residual = %13.10f\n", residual); + std::cout << "Tdcp: drho = " << r_raim.transpose() << std::endl; + std::cout << "Tdcp: H = \n" << A_raim << std::endl; + printf("Tdcp: dT = %8.3f secs\n", d_raim(3)); + #endif + + // store if best residual + if (residual < best_residual) + { + worst_sat_row = row_removed; + best_residual = residual; + best_d = d_raim; + } + } + // restore initial A and r + for (auto row = 0; row < n_removed_rows; row++) + { + A_raim.row(row_removed + row) = A.row(row_removed + row); + r_raim(row_removed + row) = r(row_removed + row); + } + row_removed += (n_removed_rows - 1); + } + + // No successful RAIM solution + if (worst_sat_row == -1) + { + printf("Tdcp: LS after RAIM DID NOT WORK. NAN values appeared. ABORTING!!"); + return false; + } + + // store removed sat + raim_discarded_sats.insert(row_2_sat_freq[worst_sat_row].first); + + // decrease n_common_sats + n_differences -= n_removed_rows; + n_common_sats--; + + // Remove selected satellite from problem + std::cout << "resizing problem..." << std::endl; + auto A_aux = A; + auto r_aux = r; + auto drho_m_aux = drho_m; + auto s_r_aux = s_r; + auto s_k_aux = s_k; + A.conservativeResize(n_differences, Eigen::NoChange); + r.conservativeResize(n_differences); + drho_m.conservativeResize(n_differences); + s_r.conservativeResize(Eigen::NoChange, n_differences); + s_k.conservativeResize(Eigen::NoChange, n_differences); + + int back_elements_changing = A_aux.rows() - worst_sat_row - n_removed_rows; + if (back_elements_changing != 0) // if last satelite removed, conservative resize did the job + { + A.bottomRows(back_elements_changing) = A_aux.bottomRows(back_elements_changing); + s_r.rightCols(back_elements_changing) = s_r_aux.rightCols(back_elements_changing); + s_k.rightCols(back_elements_changing) = s_k_aux.rightCols(back_elements_changing); + r.tail(back_elements_changing) = r_aux.tail(back_elements_changing); + drho_m.tail(back_elements_changing) = drho_m_aux.tail(back_elements_changing); + } + + // apply the RAIM solution + d = best_d; + cov_d = (A.transpose() * A).inverse(); + + #if GNSS_UTILS_TDCP_DEBUG == 1 + std::cout << "Tdcp After RAIM iteration" << std::endl; + std::cout << "\tExcluded sats : "; + std::cout << "\tCommon sats : " << n_common_sats << std::endl; + std::cout << "\tRows : " << n_differences << std::endl; + std::cout << "\tInitial guess = " << d_0.transpose() << " (" << d_0.head<3>().norm() << "m)" << std::endl; + std::cout << "\tSolution = " << d.transpose() << " (" << d.head<3>().norm() << "m)" << std::endl; + std::cout << "\tClock offset = " << d(3) << std::endl; + std::cout << "\tResidual = " << best_residual << std::endl; + #endif + } - // apply the RAIM solution - d = best_d; - cov_d = (A.transpose() * A).inverse(); + #if GNSS_UTILS_TDCP_DEBUG == 1 + std::cout << "Tdcp After RAIM " << std::endl; + std::cout << "\tExcluded sats : "; + std::cout << "\tCommon sats : " << n_common_sats << std::endl; + std::cout << "\tRows : " << n_differences << std::endl; + std::cout << "\tInitial guess = " << d_0.transpose() << " (" << d_0.head<3>().norm() << "m)" << std::endl; + std::cout << "\tSolution = " << d.transpose() << " (" << d.head<3>().norm() << "m)" << std::endl; + std::cout << "\tClock offset = " << d(3) << std::endl; + std::cout << "\tResidual = " << best_residual << std::endl; + #endif + } -#if GNSS_UTILS_TDCP_DEBUG == 1 - std::cout << "Tdcp After RAIM iteration" << std::endl; + #if GNSS_UTILS_TDCP_DEBUG == 1 + std::cout << "Tdcp iteration " << j << std::endl; std::cout << "\tExcluded sats : "; - for (auto dsat : discarded_sats) - std::cout << (int)dsat << " "; - std::cout << std::endl; - std::cout << "\tCommon sats : " << n_common_sats << std::endl; + std::cout << "\tCommon sats : " << common_sats.size() << std::endl; std::cout << "\tRows : " << n_differences << std::endl; std::cout << "\tInitial guess = " << d_0.transpose() << " (" << d_0.head<3>().norm() << "m)" << std::endl; std::cout << "\tSolution = " << d.transpose() << " (" << d.head<3>().norm() << "m)" << std::endl; std::cout << "\tClock offset = " << d(3) << std::endl; - std::cout << "\tResidual = " << best_residual << std::endl; -#endif - } - -#if GNSS_UTILS_TDCP_DEBUG == 1 - std::cout << "Tdcp After RAIM " << std::endl; - std::cout << "\tExcluded sats : "; - for (auto dsat : discarded_sats) - std::cout << (int)dsat << " "; - std::cout << std::endl; - std::cout << "\tCommon sats : " << n_common_sats << std::endl; - std::cout << "\tRows : " << n_differences << std::endl; - std::cout << "\tInitial guess = " << d_0.transpose() << " (" << d_0.head<3>().norm() << "m)" << std::endl; - std::cout << "\tSolution = " << d.transpose() << " (" << d.head<3>().norm() << "m)" << std::endl; - std::cout << "\tClock offset = " << d(3) << std::endl; - std::cout << "\tResidual = " << best_residual << std::endl; -#endif + std::cout << "\tResidual = " << residual << std::endl; + #endif } -#if GNSS_UTILS_TDCP_DEBUG == 1 - std::cout << "Tdcp iteration " << j << std::endl; - std::cout << "\tExcluded sats : "; - for (auto dsat : discarded_sats) - std::cout << (int)dsat << " "; - std::cout << std::endl; - std::cout << "\tCommon sats : " << n_common_sats << std::endl; - std::cout << "\tRows : " << n_differences << std::endl; - std::cout << "\tInitial guess = " << d_0.transpose() << " (" << d_0.head<3>().norm() << "m)" << std::endl; - std::cout << "\tSolution = " << d.transpose() << " (" << d.head<3>().norm() << "m)" << std::endl; - std::cout << "\tClock offset = " << d(3) << std::endl; - std::cout << "\tResidual = " << residual << std::endl; -#endif - } - - // weight covariance with the measurement noise (proportional to time) - double sq_sigma_Tdcp = (tk - tr) * sd_params.sigma_atm * sd_params.sigma_atm + - 2 * (sd_params.use_carrier_phase ? sd_params.sigma_carrier * sd_params.sigma_carrier : - sd_params.sigma_code * sd_params.sigma_code); - cov_d *= sq_sigma_Tdcp; - // residual = (r - A * d).norm() / A.rows(); - - // Computing error on measurement space - for (int row = 0; row < n_differences; row++) - { - r(row) = drho_m(row) - (s_k.col(row) - x_r - d.head(3)).norm() + (s_r.col(row) - x_r).norm() - d(3); - } - residual = sqrt(r.squaredNorm() / r.size()); - - return true; -} + // weight covariance with the measurement noise (proportional to time) + double sq_sigma_Tdcp = (tk - tr) * sd_params.sigma_atm * sd_params.sigma_atm + + 2 * (sd_params.use_carrier_phase ? sd_params.sigma_carrier * sd_params.sigma_carrier : + sd_params.sigma_code * sd_params.sigma_code); + cov_d *= sq_sigma_Tdcp; + // residual = (r - A * d).norm() / A.rows(); -void filterCommonSatellites(Observations& common_obs_r, - std::map<int, Eigen::Vector3d>& common_sats_pos_r, - Observations& common_obs_k, - std::map<int, Eigen::Vector3d>& common_sats_pos_k, - std::set<int>& discarded_sats, - const Eigen::Vector3d& x_r, - const TdcpParams& sd_params, - const prcopt_t& opt) -{ - assert(&common_obs_r != &common_obs_k); - assert(&common_sats_pos_r != &common_sats_pos_k); - assert(common_obs_r.size() == common_obs_k.size()); - assert(common_obs_r.size() == common_sats_pos_r.size()); - assert(common_obs_r.size() == common_sats_pos_k.size()); + // Computing error on measurement space + for (int row = 0; row < n_differences; row++) + r(row) = drho_m(row) - (s_k.col(row) - x_r - d.head(3)).norm() + (s_r.col(row) - x_r).norm() - d(3); - // std::cout << "filterCommonSatellites: initial size: " << common_obs_k.size() << std::endl; + residual = sqrt(r.squaredNorm() / r.size()); - std::set<int> remove_sats; - - for (int obs_i = 0; obs_i < common_obs_r.size(); obs_i++) - { - auto&& obs_r = common_obs_r.getObservationByIdx(obs_i); - auto&& obs_k = common_obs_k.getObservationByIdx(obs_i); - assert(obs_r.sat == obs_k.sat && "common satellites observations have to be ordered equally"); - const int& sat_number = obs_r.sat; - - // already discarded sats - if (discarded_sats.count(sat_number) != 0) - { - remove_sats.insert(sat_number); - continue; - } - - // wrong data (satellite is not included in the discarded list) - if (sd_params.use_carrier_phase and (std::abs(obs_r.L[0]) < 1e-12 or std::abs(obs_k.L[0]) < 1e-12)) - { - // std::cout << "Discarding sat " << sat_number << ": wrong carrier phase data: " << obs_r.L[0] << " " << - // obs_k.L[0] << std::endl; - remove_sats.insert(sat_number); - continue; - } - if (!sd_params.use_carrier_phase and (std::abs(obs_r.P[0]) < 1e-12 or std::abs(obs_k.L[0]) < 1e-12)) - { - // std::cout << "Discarding sat " << sat_number << ": wrong carrier phase data: " << obs_r.P[0] << " " << - // obs_k.P[0] << std::endl; - remove_sats.insert(sat_number); - continue; - } - - // bad satellite position (satellite is not included in the discarded list) - if (common_sats_pos_r[sat_number].isApprox(Eigen::Vector3d::Zero(), 1e-3) or - common_sats_pos_r[sat_number].isApprox(Eigen::Vector3d::Zero(), 1e-3)) - { - // std::cout << "Discarding sat " << sat_number << ": bad satellite position: \n\t" << - // common_sats_pos_r[sat_number].transpose() << "\n\t" << common_sats_pos_k[sat_number].transpose() << std::endl; - remove_sats.insert(sat_number); - continue; - } - - // constellation - int sys = satsys(obs_r.sat, NULL); - if (!(sys & opt.navsys)) - { - // std::cout << "Discarding sat " << sat_number << ": not selected constellation " << sys << " - mask: " << - // opt.navsys << std::endl; - discarded_sats.insert(sat_number); - remove_sats.insert(sat_number); - continue; - } - - // check both elevations - double elevation = std::min(computeSatElevation(x_r, common_sats_pos_r[sat_number]), - computeSatElevation(x_r, common_sats_pos_k[sat_number])); - if (elevation < opt.elmin) - { - // std::cout << "Discarding sat " << sat_number << ": low elevation " << elevation << " - min: " << opt.elmin << - // std::endl; - discarded_sats.insert(sat_number); - remove_sats.insert(sat_number); - continue; - } - - // snr TODO: multifrequency (2nd param and 3rd idx) - if (testsnr(0, 0, elevation, obs_r.SNR[0] * 0.25, &opt.snrmask) == 1) - { - // std::cout << "Discarding sat " << sat_number << ": snr test " << std::endl; - discarded_sats.insert(sat_number); - remove_sats.insert(sat_number); - continue; - } - } - - // remove sats - // std::cout << "removing: " << remove_sats.size() << " satellites" << std::endl; - for (auto sat : remove_sats) - { - assert(common_obs_r.hasSatellite(sat)); - assert(common_obs_k.hasSatellite(sat)); - assert(common_sats_pos_r.count(sat)); - assert(common_sats_pos_k.count(sat)); - common_obs_r.removeObservationBySat(sat); - common_obs_k.removeObservationBySat(sat); - common_sats_pos_r.erase(sat); - common_sats_pos_k.erase(sat); - } - - assert(common_obs_r.size() == common_obs_k.size()); - assert(common_obs_r.size() == common_sats_pos_r.size()); - assert(common_obs_r.size() == common_sats_pos_k.size()); - - // std::cout << "final size: " << common_obs_k.size() << std::endl; + return true; } } // namespace GnssUtils diff --git a/src/utils/sat_position.cpp b/src/utils/satellite.cpp similarity index 63% rename from src/utils/sat_position.cpp rename to src/utils/satellite.cpp index 750441eb04f8e94d998664dda1c121985248a678..878719e31a574b338217438e8b5549217b87b64e 100644 --- a/src/utils/sat_position.cpp +++ b/src/utils/satellite.cpp @@ -5,9 +5,12 @@ * Author: Joan Vallvé, Pep MartÃ-Saumell */ -#include "gnss_utils/utils/sat_position.h" +#include "gnss_utils/utils/satellite.h" -using namespace GnssUtils; +#include "gnss_utils/observations.h" +#include "gnss_utils/navigation.h" +#include "gnss_utils/utils/transformations.h" +#include "gnss_utils/gnss_utils.h" namespace GnssUtils { @@ -33,31 +36,31 @@ double computeSatElevation(const Eigen::Vector3d& receiver_ecef, const Eigen::Ve void computeSatellitesPositions(const Observations& obs, const Navigation& nav, - const prcopt_t& opt, + const int& eph_opt, std::map<int, Eigen::Vector3d>& sats_pos) { double rs[6 * obs.size()], dts[2 * obs.size()], var[obs.size()]; int svh[obs.size()]; - // std::cout << "computing sats position from sats: "; - // for (auto&& obs_ref : obs.getObservations()) - // std::cout << (int)obs_ref.sat << " "; - // std::cout << std::endl; +// std::cout << "computing position of sats: "; +// for (auto&& obs_ref : obs.getObservations()) +// std::cout << (int)obs_ref.sat << " "; +// std::cout << std::endl; // compute positions satposs( - obs.getObservations().front().time, obs.data(), obs.size(), &nav.getNavigation(), opt.sateph, rs, dts, var, svh); + obs.getObservations().front().time, obs.data(), obs.size(), &nav.getNavigation(), eph_opt, rs, dts, var, svh); // store positions // std::cout << "filling sats positions: \n"; for (int i = 0; i < obs.size(); i++) { - if (svh[i] < 0) // ephemeris unavailable - sats_pos[obs.getObservationByIdx(i).sat] = Eigen::Vector3d::Zero(); - else sats_pos[obs.getObservationByIdx(i).sat] << rs[6 * i], rs[6 * i + 1], rs[6 * i + 2]; - // std::cout << "\tsat: " << (int)obs.getObservationByIdx(i).sat << ": " << - // sats_pos[obs.getObservationByIdx(i).sat].transpose() << std::endl; + // std::cout << "\tsat: " << (int)obs.getObservationByIdx(i).sat << ": " << + // sats_pos[obs.getObservationByIdx(i).sat].transpose() << std::endl; + // if (sats_pos[obs.getObservationByIdx(i).sat] == Eigen::Vector3d::Zero()) + // std::cout << "ephemeris not available for sat " << int(obs.getObservationByIdx(i).sat) << std::endl; } } -} // namespace GnssUtils \ No newline at end of file + +} // namespace GnssUtils diff --git a/src/utils/transformations.cpp b/src/utils/transformations.cpp index 38097f55678579cb819ccf01ab0fc1a0cbbd6bfe..81639674696ff9fc38c742cb8f433164529d0814 100644 --- a/src/utils/transformations.cpp +++ b/src/utils/transformations.cpp @@ -21,7 +21,7 @@ Eigen::Vector3d latLonAltToEcef(const Eigen::Vector3d& _latlon) return ecef; } -Eigen::Matrix3d ecefToEnuCov(const Eigen::Vector3d& _latlon, const Eigen::Matrix3d _cov_ecef) +Eigen::Matrix3d ecefToEnuCov(const Eigen::Vector3d& _latlon, const Eigen::Matrix3d& _cov_ecef) { Eigen::Matrix3d cov_enu; @@ -38,7 +38,7 @@ Eigen::Matrix3d ecefToEnuCov(const Eigen::Vector3d& _latlon, const Eigen::Matrix return cov_enu; } -Eigen::Matrix3d enuToEcefCov(const Eigen::Vector3d& _latlon, const Eigen::Matrix3d _cov_enu) +Eigen::Matrix3d enuToEcefCov(const Eigen::Vector3d& _latlon, const Eigen::Matrix3d& _cov_enu) { Eigen::Matrix3d cov_ecef; @@ -149,4 +149,4 @@ void computeEnuEcefFromLatLonAlt(const Eigen::Vector3d& _ENU_latlonalt, t_ENU_ECEF = -R_ENU_ECEF * t_ECEF_ENU; } -} // namespace GnssUtils \ No newline at end of file +} // namespace GnssUtils diff --git a/test/gtest_observations.cpp b/test/gtest_observations.cpp index 422a28c68d9be9fbf3798422328a058db8219a24..cbb25d72d1863ea094dd2bd83cc28c3a8f60a5d6 100644 --- a/test/gtest_observations.cpp +++ b/test/gtest_observations.cpp @@ -134,14 +134,15 @@ TEST(ObservationsTest, FindCommonObservations) ASSERT_TRUE(observations1 == observations2); - Observations common1; - Observations common2; + std::set<int> common_sats = Observations::findCommonObservations(observations1, observations2); - Observations::findCommonObservations(observations1, observations2, common1, common2); - - ASSERT_TRUE(common1 == common2); - ASSERT_TRUE(observations1 == common1); - ASSERT_TRUE(observations2 == common2); + ASSERT_TRUE(common_sats.size() == observations1.size()); + ASSERT_TRUE(common_sats.size() == observations2.size()); + for (auto sat : common_sats) + { + ASSERT_TRUE(observations1.hasSatellite(sat)); + ASSERT_TRUE(observations2.hasSatellite(sat)); + } } TEST(ObservationsTest, FindCommonObservationsRemoved) @@ -151,16 +152,18 @@ TEST(ObservationsTest, FindCommonObservationsRemoved) Observations observations2(observations1); // Remove first observation of observations2 - observations2.removeObservationByIdx(0); - - Observations common1; - Observations common2; + int sat_removed = observations2.getObservationByIdx(0).sat; + observations2.removeObservationBySat(sat_removed); - Observations::findCommonObservations(observations1, observations2, common1, common2); + std::set<int> common_sats = Observations::findCommonObservations(observations1, observations2); - ASSERT_TRUE(common1 == common2); - ASSERT_FALSE(observations1 == common1); - ASSERT_TRUE(observations2 == common2); + ASSERT_FALSE(common_sats.size() == observations1.size()); + ASSERT_TRUE(common_sats.size() == observations2.size()); + for (auto sat : common_sats) + { + ASSERT_TRUE(observations1.hasSatellite(sat)); + ASSERT_TRUE(observations2.hasSatellite(sat)); + } } TEST(ObservationsTest, FindCommonObservationsChangeTime) @@ -175,37 +178,14 @@ TEST(ObservationsTest, FindCommonObservationsChangeTime) obs.time.sec += 10; } - Observations common1; - Observations common2; - - Observations::findCommonObservations(observations1, observations2, common1, common2); - - ASSERT_FALSE(common1 == common2); - ASSERT_TRUE(observations1 == common1); - ASSERT_TRUE(observations2 == common2); + std::set<int> common_sats = Observations::findCommonObservations(observations1, observations2); - for (auto obs = common1.getObservations().begin(); obs != common1.getObservations().end(); ++obs) + ASSERT_TRUE(common_sats.size() == observations1.size()); + ASSERT_TRUE(common_sats.size() == observations2.size()); + for (auto sat : common_sats) { - const obsd_t& obs1 = common1.getObservationBySat(obs->sat); - const obsd_t& obs2 = common2.getObservationBySat(obs->sat); - - ASSERT_FALSE(obs1.time == obs2.time); - ASSERT_TRUE(obs1.eventime == obs2.eventime); - ASSERT_TRUE(obs1.timevalid == obs2.timevalid); - ASSERT_TRUE(obs1.sat == obs2.sat); - ASSERT_TRUE(obs1.rcv == obs2.rcv); - ASSERT_TRUE(memcmp(obs1.SNR, obs2.SNR, sizeof(obs1.SNR)) == 0); - ASSERT_TRUE(memcmp(obs1.LLI, obs2.LLI, sizeof(obs1.LLI)) == 0); - ASSERT_TRUE(memcmp(obs1.code, obs2.code, sizeof(obs1.code)) == 0); - ASSERT_TRUE(memcmp(obs1.qualL, obs2.qualL, sizeof(obs1.qualL)) == 0); - ASSERT_TRUE(memcmp(obs1.qualP, obs2.qualP, sizeof(obs1.qualP)) == 0); - ASSERT_TRUE(obs1.freq == obs2.freq); - ASSERT_TRUE( - equalArray<double>(obs1.L, obs2.L, sizeof(obs1.L) / sizeof(obs1.L[0]), sizeof(obs2.L) / sizeof(obs2.L[0]))); - ASSERT_TRUE( - equalArray<double>(obs1.P, obs2.P, sizeof(obs1.P) / sizeof(obs1.P[0]), sizeof(obs2.P) / sizeof(obs2.P[0]))); - ASSERT_TRUE( - equalArray<float>(obs1.D, obs2.D, sizeof(obs1.D) / sizeof(obs1.D[0]), sizeof(obs2.D) / sizeof(obs2.D[0]))); + ASSERT_TRUE(observations1.hasSatellite(sat)); + ASSERT_TRUE(observations2.hasSatellite(sat)); } } diff --git a/test/gtest_transformations.cpp b/test/gtest_transformations.cpp index 22f7831647c1b7ebd043de0e737459556f60a284..cf5a3b05838cc18dff9fe057688c74bd2338104c 100644 --- a/test/gtest_transformations.cpp +++ b/test/gtest_transformations.cpp @@ -1,5 +1,6 @@ #include "gtest/utils_gtest.h" -#include "gnss_utils/utils/sat_position.h" +#include "gnss_utils/utils/satellite.h" +#include "gnss_utils/utils/transformations.h" // Geodetic system parameters static double kSemimajorAxis = 6378137;