mirror of
https://github.com/gnss-sdr/gnss-sdr
synced 2026-10-22 07:22:36 +00:00
Make the Monitor report channels without a valid time reference
The Monitor block is fed from the Observables output, which only produced data for channels with a decoded time of week. Galileo E6 channels cannot obtain the TOW from HAS pages alone, so E6-only configurations never produced any Monitor output. When Monitor.enable_monitor=true, the Observables block now emits every epoch, filling channels without valid observables with their latest tracking data (C/N0, Doppler, carrier phase), flagged as invalid so that the PVT engine and other consumers keep ignoring them. Fixes #1018
This commit is contained in:
@@ -109,6 +109,13 @@ All notable changes to GNSS-SDR will be documented in this file.
|
||||
Their generation can be disabled by setting `Observables.enable_E6=false`.
|
||||
This setting is now independent of `PVT.use_e6_for_pvt`, which keeps
|
||||
controlling whether E6 observables are used in the PVT solution.
|
||||
- The Monitor (`Monitor.enable_monitor=true`) now also reports channels that are
|
||||
tracking a signal but do not have a valid time reference yet, filling their
|
||||
entries with the latest raw tracking data (C/N0, Doppler, carrier phase) while
|
||||
keeping their observable validity flags unset. This makes the Monitor usable
|
||||
in Galileo E6-only configurations, where the time of week cannot be obtained
|
||||
from HAS pages, as well as during the initial seconds of operation, before the
|
||||
telemetry decoders attain synchronization.
|
||||
- Reworked the Python plotting utilities under `utils/python` (acquisition,
|
||||
tracking, telemetry, observables, and PVT diagnostics). Each script now
|
||||
exposes a command-line interface (run with `--help`) and can be executed from
|
||||
|
||||
@@ -50,6 +50,7 @@ HybridObservables::HybridObservables(const ConfigurationInterface* configuration
|
||||
conf.enable_carrier_smoothing = configuration->property(role + ".enable_carrier_smoothing", conf.enable_carrier_smoothing);
|
||||
conf.always_output_gs = configuration->property("PVT.an_output_enabled", conf.always_output_gs) || configuration->property(role + ".always_output_gs", conf.always_output_gs);
|
||||
conf.enable_E6 = configuration->property(role + ".enable_E6", conf.enable_E6);
|
||||
conf.enable_monitor = configuration->property("Monitor.enable_monitor", conf.enable_monitor);
|
||||
|
||||
#if USE_GLOG_AND_GFLAGS
|
||||
if (FLAGS_carrier_smoothing_factor == DEFAULT_CARRIER_SMOOTHING_FACTOR)
|
||||
|
||||
@@ -106,6 +106,7 @@ hybrid_observables_gs::hybrid_observables_gs(const Obs_Conf &conf_)
|
||||
d_channel_last_pseudorange_smooth = std::vector<double>(d_nchannels_out, 0.0);
|
||||
d_channel_last_carrier_phase_rads = std::vector<double>(d_nchannels_out, 0.0);
|
||||
d_channel_last_rx_time_valid = std::vector<bool>(d_nchannels_out, false);
|
||||
d_last_trk_data = std::vector<Gnss_Synchro>(d_nchannels_out);
|
||||
|
||||
d_SourceTagTimestamps = std::vector<std::queue<GnssTime>>(d_nchannels_out);
|
||||
|
||||
@@ -512,6 +513,19 @@ void hybrid_observables_gs::forecast(int noutput_items __attribute__((unused)),
|
||||
}
|
||||
|
||||
|
||||
bool hybrid_observables_gs::has_fresh_trk_data(uint32_t ch, uint64_t rx_clock) const
|
||||
{
|
||||
const Gnss_Synchro &trk = d_last_trk_data[ch];
|
||||
if (trk.fs <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// the interpolation epoch lags the latest tracking data, so a negative age is expected
|
||||
const auto age_samples = static_cast<int64_t>(rx_clock) - static_cast<int64_t>(trk.Tracking_sample_counter);
|
||||
return age_samples < trk.fs; // tracking data not older than one second
|
||||
}
|
||||
|
||||
|
||||
void hybrid_observables_gs::update_TOW(const std::vector<Gnss_Synchro> &data)
|
||||
{
|
||||
// 1. Set the TOW using the latest TOW in the observables.
|
||||
@@ -888,6 +902,12 @@ int hybrid_observables_gs::general_work(int noutput_items __attribute__((unused)
|
||||
// ************ end time tags **************
|
||||
for (int32_t m = 0; m < ninput_items[n]; m++)
|
||||
{
|
||||
if (d_conf.enable_monitor)
|
||||
{
|
||||
// Keep the latest tracking data so that channels without a
|
||||
// valid time reference can be reported through the Monitor
|
||||
d_last_trk_data[n] = in[n][m];
|
||||
}
|
||||
// Push the valid tracking Gnss_Synchros to their corresponding deque
|
||||
if (in[n][m].Flag_valid_word)
|
||||
{
|
||||
@@ -919,6 +939,7 @@ int hybrid_observables_gs::general_work(int noutput_items __attribute__((unused)
|
||||
{
|
||||
std::vector<Gnss_Synchro> epoch_data(d_nchannels_out);
|
||||
int32_t n_valid = 0;
|
||||
int32_t n_trk_only = 0;
|
||||
for (uint32_t n = 0; n < d_nchannels_out; n++)
|
||||
{
|
||||
Gnss_Synchro interpolated_gnss_synchro{};
|
||||
@@ -926,6 +947,14 @@ int hybrid_observables_gs::general_work(int noutput_items __attribute__((unused)
|
||||
{
|
||||
// Produce an empty observation
|
||||
interpolated_gnss_synchro = Gnss_Synchro();
|
||||
if (d_conf.enable_monitor && has_fresh_trk_data(n, d_Rx_clock_buffer.front()))
|
||||
{
|
||||
// Report the latest tracking data (e.g., C/N0, Doppler) for
|
||||
// channels lacking a valid time reference, such as Galileo E6
|
||||
// when no I/NAV or F/NAV channel provides the time of week
|
||||
interpolated_gnss_synchro = d_last_trk_data[n];
|
||||
n_trk_only++;
|
||||
}
|
||||
interpolated_gnss_synchro.Flag_valid_pseudorange = false;
|
||||
interpolated_gnss_synchro.Flag_valid_word = false;
|
||||
interpolated_gnss_synchro.Flag_valid_acquisition = false;
|
||||
@@ -1017,7 +1046,7 @@ int hybrid_observables_gs::general_work(int noutput_items __attribute__((unused)
|
||||
}
|
||||
}
|
||||
|
||||
if (n_valid > 0)
|
||||
if (n_valid > 0 || n_trk_only > 0)
|
||||
{
|
||||
// LOG(INFO) << "OBS: diff time: " << out[0][0].RX_time * 1000.0 - old_time_debug;
|
||||
// old_time_debug = out[0][0].RX_time * 1000.0;
|
||||
|
||||
@@ -74,6 +74,7 @@ private:
|
||||
void msg_handler_pvt_to_observables(const pmt::pmt_t& msg);
|
||||
double compute_T_rx_s(const Gnss_Synchro& a) const;
|
||||
bool interp_trk_obs(Gnss_Synchro& interpolated_obs, uint32_t ch, uint64_t rx_clock) const;
|
||||
bool has_fresh_trk_data(uint32_t ch, uint64_t rx_clock) const;
|
||||
void update_TOW(const std::vector<Gnss_Synchro>& data);
|
||||
void compute_pranges(std::vector<Gnss_Synchro>& data) const;
|
||||
void smooth_pseudoranges(std::vector<Gnss_Synchro>& data);
|
||||
@@ -101,6 +102,7 @@ private:
|
||||
std::vector<double> d_channel_last_pseudorange_smooth;
|
||||
std::vector<double> d_channel_last_carrier_phase_rads;
|
||||
std::vector<bool> d_channel_last_rx_time_valid;
|
||||
std::vector<Gnss_Synchro> d_last_trk_data; // latest tracking data per channel, for the Monitor
|
||||
|
||||
std::string d_dump_filename;
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@ public:
|
||||
bool dump{false};
|
||||
bool dump_mat{false};
|
||||
bool enable_E6{true};
|
||||
bool enable_monitor{false};
|
||||
};
|
||||
|
||||
/** \} */
|
||||
|
||||
Reference in New Issue
Block a user