diff --git a/include/gnss/processor/processor_tracker_gnss.h b/include/gnss/processor/processor_tracker_gnss.h index ca6eb0de5bd92cda2bdd2b39952a01fcfabe4e2c..b8ee8b385adb6c6e736d416b4a21f4949e0759e0 100644 --- a/include/gnss/processor/processor_tracker_gnss.h +++ b/include/gnss/processor/processor_tracker_gnss.h @@ -17,7 +17,7 @@ struct ParamsProcessorTrackerGnss : public ParamsProcessorTrackerFeature GnssUtils::Options gnss_opt; GnssUtils::Options fix_opt{GnssUtils::default_options}; double max_time_span; - bool remove_outliers; + bool remove_outliers, remove_outliers_tdcp; double outlier_residual_th; bool init_frames; @@ -52,18 +52,19 @@ struct ParamsProcessorTrackerGnss : public ParamsProcessorTrackerFeature gnss_opt.tdcp.enabled = _server.getParam<bool>(prefix + _unique_name + "/gnss/tdcp/enabled"); if (gnss_opt.tdcp.enabled) { - gnss_opt.tdcp.corr_iono = _server.getParam<bool> (prefix + _unique_name + "/gnss/tdcp/corr_iono"); - gnss_opt.tdcp.corr_tropo = _server.getParam<bool> (prefix + _unique_name + "/gnss/tdcp/corr_tropo"); - gnss_opt.tdcp.loss_function = _server.getParam<bool> (prefix + _unique_name + "/gnss/tdcp/loss_function"); - gnss_opt.tdcp.time_window = _server.getParam<double>(prefix + _unique_name + "/gnss/tdcp/time_window"); - gnss_opt.tdcp.sigma_atm = _server.getParam<double>(prefix + _unique_name + "/gnss/tdcp/sigma_atm"); - gnss_opt.tdcp.sigma_carrier = _server.getParam<double>(prefix + _unique_name + "/gnss/tdcp/sigma_carrier"); - gnss_opt.tdcp.multi_freq = _server.getParam<bool> (prefix + _unique_name + "/gnss/tdcp/multi_freq"); + remove_outliers_tdcp = _server.getParam<bool> (prefix + _unique_name + "/gnss/tdcp/remove_outliers"); + gnss_opt.tdcp.corr_iono = _server.getParam<bool> (prefix + _unique_name + "/gnss/tdcp/corr_iono"); + gnss_opt.tdcp.corr_tropo = _server.getParam<bool> (prefix + _unique_name + "/gnss/tdcp/corr_tropo"); + gnss_opt.tdcp.loss_function = _server.getParam<bool> (prefix + _unique_name + "/gnss/tdcp/loss_function"); + gnss_opt.tdcp.time_window = _server.getParam<double>(prefix + _unique_name + "/gnss/tdcp/time_window"); + gnss_opt.tdcp.sigma_atm = _server.getParam<double>(prefix + _unique_name + "/gnss/tdcp/sigma_atm"); + gnss_opt.tdcp.sigma_carrier = _server.getParam<double>(prefix + _unique_name + "/gnss/tdcp/sigma_carrier"); + gnss_opt.tdcp.multi_freq = _server.getParam<bool> (prefix + _unique_name + "/gnss/tdcp/multi_freq"); } // COMPUTE FIX OPTIONS (RAIM) fix_opt.elmin = 0; - fix_opt.maxgdop = 10; + fix_opt.maxgdop = 30; } std::string print() const @@ -121,6 +122,8 @@ class ProcessorTrackerGnss : public ProcessorTrackerFeature SensorGnssPtr sensor_gnss_; std::map<int, FeatureGnssSatellitePtr> untracked_incoming_features_, untracked_last_features_; GnssUtils::ComputePosOutput fix_incoming_, fix_last_; + unsigned int outliers_pseudorange_, outliers_tdcp_, inliers_pseudorange_, inliers_tdcp_; + std::map<int, unsigned int> sat_outliers_; /** \brief Track provided features in \b _capture * \param _features_in input list of features in \b last to track @@ -212,7 +215,7 @@ class ProcessorTrackerGnss : public ProcessorTrackerFeature void advanceDerived() override; void resetDerived() override; - void removeOutliers(FactorBasePtrList fac_list, CaptureBasePtr cap) const; + void removeOutliers(FactorBasePtrList fac_list, CaptureBasePtr cap); }; inline ProcessorTrackerGnss::~ProcessorTrackerGnss() diff --git a/src/processor/processor_tracker_gnss.cpp b/src/processor/processor_tracker_gnss.cpp index 67389a4d2efdd058e5324ffee666a840a251478c..35be5420d280579442d2aef6d97a18233e7474d9 100644 --- a/src/processor/processor_tracker_gnss.cpp +++ b/src/processor/processor_tracker_gnss.cpp @@ -10,7 +10,11 @@ namespace wolf ProcessorTrackerGnss::ProcessorTrackerGnss(ParamsProcessorTrackerGnssPtr _params_tracker_gnss) : ProcessorTrackerFeature("ProcessorTrackerGnss", 3, _params_tracker_gnss), - params_tracker_gnss_(_params_tracker_gnss) + params_tracker_gnss_(_params_tracker_gnss), + outliers_pseudorange_(0), + outliers_tdcp_(0), + inliers_pseudorange_(0), + inliers_tdcp_(0) { } @@ -20,7 +24,7 @@ void ProcessorTrackerGnss::preProcess() GnssUtils::SnapshotPtr inc_snapshot = std::static_pointer_cast<CaptureGnss>(incoming_ptr_)->getSnapshot(); - WOLF_DEBUG("preprocess: initial observations: ", inc_snapshot->getObservations()->size()); + WOLF_INFO("preprocess: initial observations: ", inc_snapshot->getObservations()->size()); // compute satellites positions if (!inc_snapshot ->satellitesComputed()) @@ -39,13 +43,13 @@ void ProcessorTrackerGnss::preProcess() // Set ECEF-ENU if (!sensor_gnss_->isEnuDefined() and sensor_gnss_->isEnuModeAuto() and fix_incoming_.stat != 0) { - WOLF_DEBUG("setting ECEF-ENU: ", fix_incoming_.pos.transpose()); + WOLF_INFO("setting ECEF-ENU: ", fix_incoming_.pos.transpose()); sensor_gnss_->setEcefEnu(fix_incoming_.pos, true); } WOLF_DEBUG("TS: ", incoming_ptr_->getTimeStamp(), " - Fix solution (ECEF): ", fix_incoming_.pos.transpose(), " - Fix solution (GEO): ", fix_incoming_.lat_lon.transpose()); - WOLF_DEBUG("preprocess: RTKLIB excluded observations: ", fix_incoming_.discarded_sats.size()); + WOLF_INFO("preprocess: RTKLIB excluded observations: ", fix_incoming_.discarded_sats.size()); // filter observations (available ephemeris, constellations and elevation&SNR) inc_snapshot->filterObservations(fix_incoming_.discarded_sats, // discarded sats fix_incoming_.sat_azel, @@ -53,7 +57,7 @@ void ProcessorTrackerGnss::preProcess() false, // check carrier phase params_tracker_gnss_->gnss_opt); - WOLF_DEBUG("preprocess: filtered observations: ", inc_snapshot->getObservations()->size()); + WOLF_INFO("preprocess: filtered observations: ", inc_snapshot->getObservations()->size()); // compute corrected Ranges inc_snapshot->computeRanges(fix_incoming_.sat_azel, @@ -71,7 +75,7 @@ void ProcessorTrackerGnss::preProcess() untracked_incoming_features_[feat->satNumber()] = feat; } - WOLF_DEBUG("preprocess: untracked incoming features: ", untracked_incoming_features_.size()); + WOLF_INFO("preprocess: untracked incoming features: ", untracked_incoming_features_.size()); } unsigned int ProcessorTrackerGnss::trackFeatures(const FeatureBasePtrList& _features_in, @@ -79,7 +83,10 @@ unsigned int ProcessorTrackerGnss::trackFeatures(const FeatureBasePtrList& _feat FeatureBasePtrList& _features_out, FeatureMatchMap& _feature_correspondences) { - WOLF_DEBUG("tracking " , _features_in.size() , " features..."); + if (_features_in.empty()) + return 0; + + WOLF_INFO("tracking " , _features_in.size() , " features..."); assert(_capture == incoming_ptr_); @@ -100,27 +107,28 @@ unsigned int ProcessorTrackerGnss::trackFeatures(const FeatureBasePtrList& _feat } } - WOLF_DEBUG("Tracked features: " , _features_out.size()); + WOLF_INFO("Tracked features: " , _features_out.size()); return _features_out.size(); } bool ProcessorTrackerGnss::voteForKeyFrame() const { - //WOLF_DEBUG("ProcessorTrackerGnss::voteForKeyFrame"); + //WOLF_INFO("ProcessorTrackerGnss::voteForKeyFrame"); // too old origin if (origin_ptr_== nullptr or (last_ptr_->getTimeStamp() - origin_ptr_->getTimeStamp()) > params_tracker_gnss_->max_time_span ) { - WOLF_DEBUG( "Vote for KF because of time span or null origin" ); + WOLF_INFO( "Vote for KF because of time span or null origin" ); return true; } // known features WOLF_DEBUG("Nbr. of active feature tracks: " , known_features_incoming_.size() ); - if (known_features_incoming_.size() < params_tracker_feature_->min_features_for_keyframe) + if (known_features_incoming_.size() < params_tracker_feature_->min_features_for_keyframe + and !untracked_last_features_.empty()) { - WOLF_DEBUG( "Vote for KF because of too less known_features_incoming" ); + WOLF_INFO( "Vote for KF because of too less known_features_incoming and not empty untracked in last" ); return true; } @@ -185,7 +193,7 @@ void ProcessorTrackerGnss::establishFactors() last_ptr_->addStateBlock("TG", std::make_shared<StateBlock>(Eigen::Vector1d(CLIGHT*fix_last_.rcv_bias(1)), true), getProblem()); last_ptr_->addStateBlock("TE", std::make_shared<StateBlock>(Eigen::Vector1d(CLIGHT*fix_last_.rcv_bias(2)), true), getProblem()); last_ptr_->addStateBlock("TC", std::make_shared<StateBlock>(Eigen::Vector1d(CLIGHT*fix_last_.rcv_bias(3)), true), getProblem()); - //WOLF_DEBUG("last clock bias set: ", last_ptr_->getStateBlock("T")->getState()); + //WOLF_INFO("last clock bias set: ", last_ptr_->getStateBlock("T")->getState()); } // Initialize clock bias stateblocks in capture else if (!last_clock_bias_init) @@ -194,7 +202,7 @@ void ProcessorTrackerGnss::establishFactors() last_ptr_->getStateBlock("TG")->setState(Eigen::Vector1d(CLIGHT*fix_last_.rcv_bias(1))); last_ptr_->getStateBlock("TE")->setState(Eigen::Vector1d(CLIGHT*fix_last_.rcv_bias(2))); last_ptr_->getStateBlock("TC")->setState(Eigen::Vector1d(CLIGHT*fix_last_.rcv_bias(3))); - //WOLF_DEBUG("last clock bias initialized: ", last_ptr_->getStateBlock("T")->getState()); + //WOLF_INFO("last clock bias initialized: ", last_ptr_->getStateBlock("T")->getState()); last_clock_bias_init = true; } @@ -241,14 +249,21 @@ void ProcessorTrackerGnss::establishFactors() auto ftr_r = std::dynamic_pointer_cast<FeatureGnssSatellite>(ts_ftr_r_it->second); assert(ftr_r != nullptr); + // dt + double dt = ftr_k->getCapture()->getTimeStamp() - ts_ftr_r_it->first; + // discard incomming-last and last-last - if (ftr_k->getCapture()->getTimeStamp() < ts_ftr_r_it->first or ftr_k == ftr_r) + if (dt < 0 or ftr_k == ftr_r) continue; // within time window - if (ftr_k->getCapture()->getTimeStamp() - ts_ftr_r_it->first > params_tracker_gnss_->gnss_opt.tdcp.time_window) + if (dt > params_tracker_gnss_->gnss_opt.tdcp.time_window) break; + // discard removing Frame/capture/feature + if (ftr_r->isRemoving() or ftr_r->getCapture()->isRemoving() or ftr_r->getCapture()->getFrame()->isRemoving()) + continue; + // check valid measurement if (ftr_r->getObservation().L[0] < 1e-12) // TODO: move to GnssUtils::isValid(double, Combination) continue; @@ -266,8 +281,9 @@ void ProcessorTrackerGnss::establishFactors() } // emplace tdcp factor + double var_tdcp = dt * std::pow(params_tracker_gnss_->gnss_opt.tdcp.sigma_atm,2) + std::pow(params_tracker_gnss_->gnss_opt.tdcp.sigma_carrier,2); auto new_fac = FactorBase::emplace<FactorGnssTdcp>(ftr_k, - 0.1, // TODO: compute from params and dt + sqrt(var_tdcp), ftr_r, ftr_k, sensor_gnss_, @@ -275,7 +291,7 @@ void ProcessorTrackerGnss::establishFactors() params_tracker_gnss_->gnss_opt.tdcp.loss_function); new_factors.push_back(new_fac); - // WOLF_DEBUG( "Factor: track: " , feature_in_last->trackId(), + // WOLF_INFO( "Factor: track: " , feature_in_last->trackId(), // " origin: " , feature_in_origin->id() , // " from last: " , feature_in_last->id() ); } @@ -284,7 +300,7 @@ void ProcessorTrackerGnss::establishFactors() } // remove outliers - if (!new_factors.empty() and params_tracker_gnss_->remove_outliers) + if (!new_factors.empty() and (params_tracker_gnss_->remove_outliers or params_tracker_gnss_->remove_outliers_tdcp)) removeOutliers(new_factors, last_ptr_); //getProblem()->print(4, 1, 1, 1); @@ -313,32 +329,77 @@ void ProcessorTrackerGnss::postProcess() } -void ProcessorTrackerGnss::removeOutliers(FactorBasePtrList fac_list, CaptureBasePtr cap) const +void ProcessorTrackerGnss::removeOutliers(FactorBasePtrList fac_list, CaptureBasePtr cap) { WOLF_DEBUG("ProcessorTrackerGnss::removeOutliers"); FactorBasePtrList remove_fac; - //WOLF_DEBUG( "PR ", getName()," rejectOutlier..."); - // copy states - Eigen::Vector3d x(cap->getFrame()->getP()->getState()); - Eigen::Vector4d o(cap->getFrame()->getO()->getState()); + //WOLF_INFO( "PR ", getName()," rejectOutlier..."); + + // PseudoRange states + Eigen::Vector3d x; + Eigen::Vector4d o; + Eigen::Vector1d clock_bias; + Eigen::Vector1d clock_bias_glo; + Eigen::Vector1d clock_bias_gal; + Eigen::Vector1d clock_bias_cmp; + Eigen::Vector3d x_antena_pr; + + + // state for pseudoranges is fix solution if OK + if (cap == last_ptr_ and fix_last_.stat != 0) + { + WOLF_DEBUG("OUTLIERS COMPUTED USING fix_last"); + x = sensor_gnss_->getREnuMap().transpose() * (sensor_gnss_->getREnuEcef() * fix_last_.pos + sensor_gnss_->gettEnuEcef() - sensor_gnss_->gettEnuMap()); + o << 0,0,0,1; + clock_bias << CLIGHT * fix_last_.rcv_bias(0); + clock_bias_glo << CLIGHT * fix_last_.rcv_bias(1); + clock_bias_gal << CLIGHT * fix_last_.rcv_bias(2); + clock_bias_cmp << CLIGHT * fix_last_.rcv_bias(3); + x_antena_pr = Eigen::Vector3d::Zero(); + + //std::cout << "x: " << x.transpose() << std::endl; + //std::cout << "o: " << o.transpose() << std::endl; + //std::cout << "clock_bias: " << clock_bias << std::endl; + //std::cout << "clock_bias_glo: " << clock_bias_glo << std::endl; + //std::cout << "clock_bias_gal: " << clock_bias_gal << std::endl; + //std::cout << "clock_bias_cmp: " << clock_bias_cmp << std::endl; + //std::cout << "x_antena_pr: " << x_antena_pr.transpose() << std::endl; + //std::cout << "frame p: " << cap->getFrame()->getP()->getState().transpose() << std::endl; + //std::cout << "frame o: " << cap->getFrame()->getO()->getState().transpose() << std::endl; + //std::cout << "sb clock: " << cap->getStateBlock("T")->getState() << std::endl; + //std::cout << "sb clock glo: " << cap->getStateBlock("TG")->getState() << std::endl; + //std::cout << "sb clock gal: " << cap->getStateBlock("TE")->getState() << std::endl; + //std::cout << "sb clock cmp: " << cap->getStateBlock("TC")->getState() << std::endl; + //std::cout << "sb antena: " << sensor_gnss_->getP()->getState().transpose() << std::endl; + } + else + { + x = cap->getFrame()->getP()->getState(); + o = cap->getFrame()->getO()->getState(); + clock_bias = cap->getStateBlock("T")->getState(); + clock_bias_glo = cap->getStateBlock("TG")->getState(); + clock_bias_gal = cap->getStateBlock("TE")->getState(); + clock_bias_cmp = cap->getStateBlock("TC")->getState(); + x_antena_pr = sensor_gnss_->getP()->getState(); + } + + // TDCP states + Eigen::Vector3d x_k(cap->getFrame()->getP()->getState()); + Eigen::Vector4d o_k(cap->getFrame()->getO()->getState()); Eigen::Vector3d x_r(cap->getFrame()->getP()->getState()); Eigen::Vector4d o_r(cap->getFrame()->getO()->getState()); - Eigen::Vector1d clock_bias(cap->getStateBlock("T")->getState()); - Eigen::Vector1d clock_bias_glo(cap->getStateBlock("TG")->getState()); - Eigen::Vector1d clock_bias_gal(cap->getStateBlock("TE")->getState()); - Eigen::Vector1d clock_bias_cmp(cap->getStateBlock("TC")->getState()); + Eigen::Vector1d clock_bias_k(cap->getStateBlock("T")->getState()); + Eigen::Vector1d clock_bias_r(cap->getStateBlock("T")->getState()); Eigen::Vector3d x_antena(sensor_gnss_->getP()->getState()); + + // Common states Eigen::Vector3d t_ENU_map(sensor_gnss_->getEnuMapTranslation()->getState()); Eigen::Vector1d roll_ENU_map(sensor_gnss_->getEnuMapRoll()->getState()); Eigen::Vector1d pitch_ENU_map(sensor_gnss_->getEnuMapPitch()->getState()); Eigen::Vector1d yaw_ENU_map(sensor_gnss_->getEnuMapYaw()->getState()); - //std::cout << "Frame p: " << x.transpose() << std::endl; - //std::cout << "Frame o: " << o.transpose() << std::endl; - //std::cout << "clock_bias: " << clock_bias << std::endl; - //std::cout << "x_antena: " << x_antena.transpose() << std::endl; //std::cout << "t_ENU_map: " << t_ENU_map.transpose() << std::endl; //std::cout << "roll_ENU_map: " << roll_ENU_map << std::endl; //std::cout << "pitch_ENU_map: " << pitch_ENU_map << std::endl; @@ -349,7 +410,7 @@ void ProcessorTrackerGnss::removeOutliers(FactorBasePtrList fac_list, CaptureBas o.data(), clock_bias.data(), clock_bias_glo.data(), - x_antena.data(), + x_antena_pr.data(), t_ENU_map.data(), roll_ENU_map.data(), pitch_ENU_map.data(), @@ -358,7 +419,7 @@ void ProcessorTrackerGnss::removeOutliers(FactorBasePtrList fac_list, CaptureBas o.data(), clock_bias.data(), clock_bias_gal.data(), - x_antena.data(), + x_antena_pr.data(), t_ENU_map.data(), roll_ENU_map.data(), pitch_ENU_map.data(), @@ -367,17 +428,17 @@ void ProcessorTrackerGnss::removeOutliers(FactorBasePtrList fac_list, CaptureBas o.data(), clock_bias.data(), clock_bias_cmp.data(), - x_antena.data(), + x_antena_pr.data(), t_ENU_map.data(), roll_ENU_map.data(), pitch_ENU_map.data(), yaw_ENU_map.data()}; double* parameters_tdcp[11] = {x_r.data(), o_r.data(), - clock_bias.data(), - x.data(), - o.data(), - clock_bias.data(), + clock_bias_r.data(), + x_k.data(), + o_k.data(), + clock_bias_k.data(), x_antena.data(), t_ENU_map.data(), roll_ENU_map.data(), @@ -391,10 +452,13 @@ void ProcessorTrackerGnss::removeOutliers(FactorBasePtrList fac_list, CaptureBas { // PSEUDO RANGE FACTORS auto fac_pr = std::dynamic_pointer_cast<FactorGnssPseudoRange>(fac); + auto ftr_sat = std::static_pointer_cast<FeatureGnssSatellite>(fac->getFeature()); + int sat = ftr_sat->satNumber(); + if (fac_pr) { // evaluate the factor in this state - switch (std::static_pointer_cast<FeatureGnssSatellite>(fac->getFeature())->getSatellite().sys) + switch (ftr_sat->getSatellite().sys) { case SYS_GLO: fac_pr->evaluate(parameters_glo_pr, &residual, nullptr); @@ -410,53 +474,82 @@ void ProcessorTrackerGnss::removeOutliers(FactorBasePtrList fac_list, CaptureBas break; } - // RTKLIB FIX error //int sat = std::static_pointer_cast<FeatureGnssSatellite>(fac->getFeature())->getSatellite().sat; //assert(fix_last_.prange_residuals.count(sat) && "sat not used when computing fix!"); - //WOLF_DEBUG("FactorGnssPseudoRange error = ", fac->getMeasurementSquareRootInformationUpper().inverse()*residual); - //WOLF_DEBUG("RTKLIB pntpos error = ", fix_last_.prange_residuals.at(sat)); + //WOLF_INFO("FactorGnssPseudoRange error = ", fac->getMeasurementSquareRootInformationUpper().inverse()*residual); + //WOLF_INFO("RTKLIB pntpos error = ", fix_last_.prange_residuals.at(sat)); // discard if residual too high evaluated at the current estimation if (std::abs(residual) > params_tracker_gnss_->outlier_residual_th) { - WOLF_WARN("Discarding FactorGnssPseudoRange, considered OUTLIER"); - WOLF_TRACE("Feature: ", fac->getMeasurement(),"\nError: ",fac->getMeasurementSquareRootInformationUpper().inverse()*residual); + //WOLF_WARN("Discarding FactorGnssPseudoRange, considered OUTLIER"); + //WOLF_TRACE("Feature: ", fac->getMeasurement(),"\nError: ",fac->getMeasurementSquareRootInformationUpper().inverse()*residual); remove_fac.push_back(fac_pr); + // store for statistics + outliers_pseudorange_++; + if (not sat_outliers_.count(sat)) + sat_outliers_.emplace(sat, 1); + else + sat_outliers_[sat]++; + } + else + inliers_pseudorange_++; } // TDCP FACTORS auto fac_tdcp = std::dynamic_pointer_cast<FactorGnssTdcp>(fac); - if (fac_tdcp) + if (fac_tdcp and params_tracker_gnss_->remove_outliers_tdcp) { // update ref frame x_r = fac_tdcp->getCaptureOther()->getFrame()->getP()->getState(); o_r = fac_tdcp->getCaptureOther()->getFrame()->getO()->getState(); + clock_bias_r = fac_tdcp->getCaptureOther()->getStateBlock("T")->getState(); parameters_tdcp[0] = x_r.data(); parameters_tdcp[1] = o_r.data(); + parameters_tdcp[2] = clock_bias_r.data(); // evaluate fac_tdcp->evaluate(parameters_tdcp, &residual, nullptr); - WOLF_DEBUG("FactorGnssTdcp with residual = ", residual); + //WOLF_INFO("FactorGnssTdcp with residual = ", residual); // discard if residual too high evaluated at the current estimation if (std::abs(residual) > params_tracker_gnss_->outlier_residual_th) { - WOLF_WARN("Discarding FactorGnssPseudoRange, considered OUTLIER"); - WOLF_TRACE("Residual: ", residual,"\nError: ",fac->getMeasurementSquareRootInformationUpper().inverse()*residual); + //WOLF_WARN("Discarding FactorGnssPseudoRange, considered OUTLIER"); + //WOLF_TRACE("Residual: ", residual,"\nError: ",fac->getMeasurementSquareRootInformationUpper().inverse()*residual); remove_fac.push_back(fac_tdcp); + // store for statistics + outliers_tdcp_++; + if (not sat_outliers_.count(sat)) + sat_outliers_.emplace(sat, 1); + else + sat_outliers_[sat]++; } + else + inliers_tdcp_++; } } // remove outliers for (auto fac : remove_fac) { - assert(false); + //assert(false); fac->remove(); } - WOLF_DEBUG("ProcessorTrackerGnss::removeOutliers done"); + WOLF_INFO("ProcessorTrackerGnss::removeOutliers:", + "\n\tPseudorange: ", outliers_pseudorange_, "\t( ", (100.0 * outliers_pseudorange_)/(outliers_pseudorange_+inliers_pseudorange_), " %)", + "\n\tTDCP: ", outliers_tdcp_, "\t( ", (100.0 * outliers_tdcp_)/(outliers_tdcp_+inliers_tdcp_), " %)", + "\n\tsats:"); + std::string sat_out_str(""); + for (auto sat_out : sat_outliers_) + { + const int& sat = sat_out.first; + int sys = satsys(sat,NULL); + const unsigned int& outliers = sat_out.second; + std::cout << "\t\tsat " << sat << "(" << sys << "): " << outliers << std::endl; + } } } // namespace wolf