diff --git a/include/gnss_utils/gnss_utils.h b/include/gnss_utils/gnss_utils.h index c10e5e4de876e40bc0c163022ab15c9bad7714e4..9e29038544ed6edc5fdef4620223c86e47ab27e8 100644 --- a/include/gnss_utils/gnss_utils.h +++ b/include/gnss_utils/gnss_utils.h @@ -23,9 +23,11 @@ class Observations; class Navigation; class Snapshot; class Satellite; +class PseudoRange; // Typedefs typedef std::map<int,Satellite> Satellites; +typedef std::map<int,PseudoRange> PseudoRanges; // pointer typedefs typedef std::shared_ptr<Observations> ObservationsPtr; diff --git a/include/gnss_utils/observations.h b/include/gnss_utils/observations.h index ab2a5d21bc9c90c20f89e3587897dd59e907e770..189c8798f6a6b52332d682e8fddc2ccffb538838 100644 --- a/include/gnss_utils/observations.h +++ b/include/gnss_utils/observations.h @@ -5,6 +5,7 @@ namespace GnssUtils { + class Observations { public: @@ -45,6 +46,9 @@ public: const Satellites& sats, const snrmask_t& snrmask, const double& elmin); + std::set<int> filterByElevationSnr(const std::map<int,double>& elevations, + const snrmask_t& snrmask, + const double& elmin); std::set<int> filter(const Satellites& sats, const std::set<int>& discarded_sats, const Eigen::Vector3d& x_r, @@ -59,7 +63,22 @@ public: const int& navsys, const snrmask_t& snrmask, const double& elmin); - + std::set<int> filter(const Satellites& sats, + const std::set<int>& discarded_sats, + const std::map<int,double>& elevations, + const bool& check_code, + const bool& check_carrier_phase, + const prcopt_t& opt); + std::set<int> filter(const Satellites& sats, + const std::set<int>& discarded_sats, + const std::map<int,double>& elevations, + const bool& check_code, + const bool& check_carrier_phase, + const int& navsys, + const snrmask_t& snrmask, + const double& elmin); + + // Others static std::set<int> findCommonObservations(const Observations& obs_1, const Observations& obs_2); bool operator==(const Observations& other_obs) const; @@ -104,13 +123,13 @@ inline const obsd_t& Observations::getObservationBySat(const unsigned char& sat_ inline obsd_t& Observations::getObservationByIdx(const int& idx) { - assert(obs_.size() > idx); + assert(obs_.size() > idx && idx >= 0); return obs_.at(idx); } inline const obsd_t& Observations::getObservationByIdx(const int& idx) const { - assert(obs_.size() > idx); + assert(obs_.size() > idx && idx >= 0); return obs_.at(idx); } diff --git a/include/gnss_utils/snapshot.h b/include/gnss_utils/snapshot.h index 065abc92201cb0d3e84cda4e82f27e85acdd47cc..7c65853fdaabf4fd31cd3aedb731793062619169 100644 --- a/include/gnss_utils/snapshot.h +++ b/include/gnss_utils/snapshot.h @@ -14,6 +14,12 @@ namespace GnssUtils { +struct PseudoRange +{ + double prange = -1; + double var = -1; +}; + class Snapshot { @@ -44,6 +50,15 @@ public: const bool &check_carrier_phase, const prcopt_t &opt); + // Pseudo-ranges + PseudoRanges& getPseudoRanges(); + const PseudoRanges& getPseudoRanges() const; + bool pseudoRangesComputed() const; + void computePseudoRanges(const std::map<int,Eigen::Vector2d> azel, + const Eigen::Vector3d latlonalt, + const double rcv_clock_bias, + const prcopt_t& opt); + void print(); private: @@ -51,6 +66,7 @@ private: Satellites sats_; ObservationsPtr obs_; NavigationPtr nav_; + PseudoRanges pranges_; // Private methods }; @@ -110,5 +126,20 @@ inline std::set<int> Snapshot::filterObservations(const std::set<int> &discarded return obs_->filter(sats_, discarded_sats, x_r, check_code, check_carrier_phase, opt); } +inline const PseudoRanges& Snapshot::getPseudoRanges() const +{ + return pranges_; +} + +inline PseudoRanges& Snapshot::getPseudoRanges() +{ + return pranges_; +} + +inline bool Snapshot::pseudoRangesComputed() const +{ + return !pranges_.empty(); +} + } // namespace GnssUtils #endif // INCLUDE_GNSS_UTILS_SNAPSHOT_H_ diff --git a/include/gnss_utils/utils/rcv_position.h b/include/gnss_utils/utils/rcv_position.h index 9755c14f8f453758df77e432ad30d40b740d9441..13357a8930025db21c98e3525743e0ea25b418d0 100644 --- a/include/gnss_utils/utils/rcv_position.h +++ b/include/gnss_utils/utils/rcv_position.h @@ -36,6 +36,8 @@ struct ComputePosOutput int pos_stat; // return from pntpos Eigen::Vector3d lat_lon; // latitude_longitude_altitude + + std::map<int,Eigen::Vector2d> sat_azel; // azimuth and elevation of each satellite provided }; ComputePosOutput computePos(const Observations& _observations, Navigation& _navigation, const prcopt_t& _prcopt); @@ -62,4 +64,4 @@ int estposOwn(const obsd_t* obs, double* resp, char* msg); } // namespace GnssUtils -#endif // INCLUDE_GNSS_UTILS_UTILS_RCV_POSITION_H_ \ No newline at end of file +#endif // INCLUDE_GNSS_UTILS_UTILS_RCV_POSITION_H_ diff --git a/include/gnss_utils/utils/satellite.h b/include/gnss_utils/utils/satellite.h index 14ab5397af16d392634a08b8fd3ea76fe0a4e03a..64aa5c3fa09094f25863219ec62c5e8b3f73059d 100644 --- a/include/gnss_utils/utils/satellite.h +++ b/include/gnss_utils/utils/satellite.h @@ -29,25 +29,28 @@ namespace GnssUtils struct Satellite { - int sat_; - Eigen::Vector3d pos_; - Eigen::Vector3d vel_; - double var_; - double clock_bias_; - double clock_drift_; - - Satellite(const int& _sat, + int sys; + int sat; + Eigen::Vector3d pos; + Eigen::Vector3d vel; + double var; + double clock_bias; + double clock_drift; + + Satellite(const int& _sys, + const int& _sat, const Eigen::Vector3d& _pos, const Eigen::Vector3d& _vel, const double& _var, const double& _clock_bias, const double& _clock_drift) : - sat_(_sat), - pos_(_pos), - vel_(_vel), - var_(_var), - clock_bias_(_clock_bias), - clock_drift_(_clock_drift) + sys(_sys), + sat(_sat), + pos(_pos), + vel(_vel), + var(_var), + clock_bias(_clock_bias), + clock_drift(_clock_drift) { }; }; diff --git a/src/observations.cpp b/src/observations.cpp index bbc0e86c87c8741947462382390a2ff5ff4540cd..733f20366dbaf5b1eeb5dc6e9f13442b233a9d9f 100644 --- a/src/observations.cpp +++ b/src/observations.cpp @@ -1,4 +1,5 @@ #include "gnss_utils/observations.h" +#include "gnss_utils/navigation.h" #include "gnss_utils/utils/satellite.h" using namespace GnssUtils; @@ -173,10 +174,10 @@ std::set<int> Observations::filterByEphemeris(const Satellites& sats) remove_sats.insert(sat_number); } // bad satellite position (satellite is not included in the discarded list) - if (sats.at(sat_number).pos_.isApprox(Eigen::Vector3d::Zero(), 1e-3) or - sats.at(sat_number).pos_.norm() < 2.5e7) + if (sats.at(sat_number).pos.isApprox(Eigen::Vector3d::Zero(), 1e-3) or + sats.at(sat_number).pos.norm() < 2.5e7) { - std::cout << "Discarding sat " << sat_number << ": wrong satellite position: \n\t" << sats.at(sat_number).pos_.transpose() << std::endl; + std::cout << "Discarding sat " << sat_number << ": wrong satellite position: \n\t" << sats.at(sat_number).pos.transpose() << std::endl; remove_sats.insert(sat_number); } } @@ -303,6 +304,44 @@ std::set<int> Observations::filterByConstellations(const int& navsys) return remove_sats; } +std::set<int> Observations::filterByElevationSnr(const std::map<int,double>& elevations, + 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 + if (elevations.at(sat_number) < 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, elevations.at(sat_number), 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::filterByElevationSnr(const Eigen::Vector3d& x_r, const Satellites& sats, const snrmask_t& snrmask, @@ -316,7 +355,7 @@ std::set<int> Observations::filterByElevationSnr(const Eigen::Vector3d& x_r, const int& sat_number = obs_sat.sat; // check elevation - double elevation = computeSatElevation(x_r, sats.at(sat_number).pos_); + double elevation = computeSatElevation(x_r, sats.at(sat_number).pos); if (elevation < elmin) { //std::cout << "Discarding sat " << sat_number << ": low elevation " << elevation << " - min: " << elmin << std::endl; @@ -405,6 +444,66 @@ std::set<int> Observations::filter(const Satellites& sats, // std::cout << "final size: " << obs_.size() << std::endl; } +std::set<int> Observations::filter(const Satellites& sats, + const std::set<int>& discarded_sats, + const std::map<int,double>& elevations, + const bool& check_code, + const bool& check_carrier_phase, + const prcopt_t& opt) +{ + return filter(sats, + discarded_sats, + elevations, + check_code, + check_carrier_phase, + opt.navsys, + opt.snrmask, + opt.elmin); +} + +std::set<int> Observations::filter(const Satellites& sats, + const std::set<int>& discarded_sats, + const std::map<int,double>& elevations, + const bool& check_code, + const bool& check_carrier_phase, + const int& navsys, + const snrmask_t& snrmask, + const double& elmin) +{ + //std::cout << "filter: initial size: " << obs_.size() << std::endl; + // Ephemeris + std::set<int> remove_sats = filterByEphemeris(sats); + + // Discarded sats + std::set<int> remove_sats_discarded = filterBySatellites(discarded_sats); + remove_sats.insert(remove_sats_discarded.begin(), remove_sats_discarded.end()); + + // Code + if (check_code) + { + std::set<int> remove_sats_code = filterByCode(); + remove_sats.insert(remove_sats_code.begin(), remove_sats_code.end()); + } + + // Carrier phase + if (check_carrier_phase) + { + std::set<int> remove_sats_carrier = filterByCarrierPhase(); + remove_sats.insert(remove_sats_carrier.begin(), remove_sats_carrier.end()); + } + + // Constellations + std::set<int> remove_sats_constellations = filterByConstellations(navsys); + remove_sats.insert(remove_sats_constellations.begin(), remove_sats_constellations.end()); + + // Elevation and SNR + std::set<int> remove_sats_elevation = filterByElevationSnr(elevations, snrmask, elmin); + remove_sats.insert(remove_sats_elevation.begin(), remove_sats_elevation.end()); + + return remove_sats; + // std::cout << "final size: " << obs_.size() << std::endl; +} + std::set<int> Observations::findCommonObservations(const Observations& obs_1, const Observations& obs_2) { diff --git a/src/snapshot.cpp b/src/snapshot.cpp index 26a7251a76f7c9be4010cb32d1b59ff74e226e57..c98807f10ca6936f45eb030e6d85ba0e99d2d0cd 100644 --- a/src/snapshot.cpp +++ b/src/snapshot.cpp @@ -30,3 +30,48 @@ void Snapshot::computeSatellites(const int& eph_opt) sats_ = GnssUtils::computeSatellites(*obs_, *nav_, eph_opt); } + +void Snapshot::computePseudoRanges(const std::map<int,Eigen::Vector2d> azel, + const Eigen::Vector3d latlonalt, + const double rcv_clock_bias, + const prcopt_t& opt) +{ + assert(pranges_.empty() && "pseudo ranges already computed!"); + + double dion,dtrp,vmeas,vion,vtrp,P,lam_L1; + + for (auto i = 0; i<obs_->size(); i++) + { + + const obsd_t& obs_i(obs_->getObservationByIdx(i)); + int sat = obs_i.sat; + const Satellite& sat_i(sats_.at(sat)); + assert(azel.count(sat) != 0 && "azimuth and elevation not provided for this satellite"); + double azel_i[2] = {azel.at(sat)(0),azel.at(sat)(1)}; + + // initialize with error values + pranges_.emplace(sat,PseudoRange()); + + /* psudorange with code bias correction */ + if ((P=prange(&obs_i,&nav_->getNavigation(),azel_i,1,&opt,&vmeas))==0.0) + continue; + + /* ionospheric corrections */ + if (!ionocorr(obs_i.time,&nav_->getNavigation(),sat,latlonalt.data(),azel_i, opt.ionoopt,&dion,&vion)) + continue; + + /* GPS-L1 -> L1/B1 */ + if ((lam_L1=nav_->getNavigation().lam[sat-1][0])>0.0) + dion*=std::pow(lam_L1/lam_carr[0],2); + + /* tropospheric corrections */ + if (!tropcorr(obs_i.time,&nav_->getNavigation(),latlonalt.data(),azel_i,opt.tropopt,&dtrp,&vtrp)) + continue; + + /* pseudorange corrected */ + pranges_.at(sat).prange = P-(rcv_clock_bias-CLIGHT*sat_i.clock_bias+dion+dtrp); + + /* error variance */ + pranges_.at(sat).var = varerr(&opt,azel_i[1],opt.err[5],sat_i.sys)+sat_i.var+vmeas+vion+vtrp; + } +} diff --git a/src/tdcp.cpp b/src/tdcp.cpp index 9a230ef599e9c2c5bf5da5d84a5df2c3e4110c77..cd1b82c09aa9dc438f136d38e4e87ad63332477e 100644 --- a/src/tdcp.cpp +++ b/src/tdcp.cpp @@ -210,8 +210,8 @@ bool Tdcp(SnapshotPtr snapshot_r, auto nav_k = snapshot_k->getNavigation()->getNavigation(); // Satellite's positions - s_r.col(row) = snapshot_r->getSatellites().at(sat_number).pos_; - s_k.col(row) = snapshot_r->getSatellites().at(sat_number).pos_; + s_r.col(row) = snapshot_r->getSatellites().at(sat_number).pos; + s_k.col(row) = snapshot_r->getSatellites().at(sat_number).pos; nav_k.ion_gps; if (sd_params.use_carrier_phase) // TODO: add iono and tropo corrections (optionally) diff --git a/src/utils/rcv_position.cpp b/src/utils/rcv_position.cpp index da0d1320b1ef8dd16c89b3ddc1016590f8053428..77fa3130f39d28ec65f200558703b89189b23e76 100644 --- a/src/utils/rcv_position.cpp +++ b/src/utils/rcv_position.cpp @@ -28,13 +28,13 @@ ComputePosOutput computePos(const GnssUtils::Observations& _observations, sol_t sol; sol = { { 0 } }; + std::vector<double> sat_elevations(2*_observations.size()); + output.pos_stat = pntpos( - _observations.data(), _observations.size(), &(_navigation.getNavigation()), &_prcopt, &sol, NULL, NULL, msg); + _observations.data(), _observations.size(), &(_navigation.getNavigation()), &_prcopt, &sol, sat_elevations.data(), NULL, msg); if (output.pos_stat == 0) - { std::cout << "computePos: error in computing positioning, message: " << msg << "\n"; - } output.time = sol.time.time; output.sec = sol.time.sec; @@ -44,13 +44,8 @@ ComputePosOutput computePos(const GnssUtils::Observations& _observations, // std::cout << "Compute pos: " << output.pos.transpose() << "\n"; // std::cout << "Covariance:\n" << output.pos_covar << "\n"; - // XXX: segmentation fault here. if (sol.dtr != NULL) - { output.rcv_bias = (Eigen::Matrix<double,6,1>() << sol.dtr[0], sol.dtr[1], sol.dtr[2], sol.dtr[3], sol.dtr[4], sol.dtr[5]).finished(); - //output.rcv_bias = Eigen::Matrix<double, 6,1>(sol.dtr[0], sol.dtr[1], sol.dtr[2], sol.dtr[3], sol.dtr[4], sol.dtr[5]); - //output.rcv_bias << sol.dtr[0], sol.dtr[1], sol.dtr[2], sol.dtr[3], sol.dtr[4], sol.dtr[5]; - } output.type = sol.type; output.stat = sol.stat; output.ns = sol.ns; @@ -58,6 +53,9 @@ ComputePosOutput computePos(const GnssUtils::Observations& _observations, output.ratio = sol.ratio; output.lat_lon = ecefToLatLonAlt(output.pos); + for (auto i = 0; i < _observations.size(); i++) + output.sat_azel.emplace(_observations.getObservationByIdx(i).sat,Eigen::Vector2d(sat_elevations.at(2*i),sat_elevations.at(2*i+1))); + return output; } diff --git a/src/utils/satellite.cpp b/src/utils/satellite.cpp index 51266efa1e254909fe392a287a985813006da22c..c3c4d27b0225cddb3449a0bad16709e033b772c3 100644 --- a/src/utils/satellite.cpp +++ b/src/utils/satellite.cpp @@ -56,7 +56,8 @@ Satellites computeSatellites(const Observations& obs, for (int i = 0; i < obs.size(); i++) { auto sat_pair = sats.emplace(obs.getObservationByIdx(i).sat, // Key - Satellite(obs.getObservationByIdx(i).sat, // Constructor... + Satellite(satsys(obs.getObservationByIdx(i).sat,NULL), + obs.getObservationByIdx(i).sat, // Constructor... (Eigen::Vector3d() << rs[6*i], rs[6*i+1], rs[6*i+2]).finished(), (Eigen::Vector3d() << rs[6*i+3], rs[6*i+4], rs[6*i+5]).finished(), var[i], @@ -67,12 +68,12 @@ Satellites computeSatellites(const Observations& obs, const Satellite& sat_i(sat_pair.first->second); - std::cout << "\tsat: " << sat_i.sat_ << ": " - << "\t\tpos: " << sat_i.pos_.transpose() - << "\t\tvel: " << sat_i.vel_.transpose() - << "\t\tvar: " << sat_i.var_ - << "\t\tclock bias: " << sat_i.clock_bias_ - << "\t\tclock drift: " << sat_i.clock_drift_ << std::endl; + std::cout << "\tsat: " << sat_i.sat << std::endl + << "\t\tpos: " << sat_i.pos.transpose() << std::endl + << "\t\tvel: " << sat_i.vel.transpose() << std::endl + << "\t\tvar: " << sat_i.var << std::endl + << "\t\tclock bias: " << sat_i.clock_bias << std::endl + << "\t\tclock drift: " << sat_i.clock_drift << std::endl; // if (sat_i.pos_ == Eigen::Vector3d::Zero()) // std::cout << "ephemeris not available for sat " << sat_i.sat_ << std::endl; }