Files
gnss-sdr/src/core/receiver/control_thread.h
T
joebre af366bef1b Add runtime satellite-visibility-aware acquisition search
Today, GNSSFlowgraph picks the next satellite to acquire on an idle
channel from a single FIFO queue per signal type. Visibility only ever
affects that queue's initial order, computed once at hot/warm start;
after that, every satellite -- visible or not -- is just a FIFO entry,
and a satellite that fails acquisition goes to the back of the same
queue. On a receiver with a large candidate PRN pool relative to the
satellites actually in view, this means channels keep grinding through
acquisition attempts against satellites that were never going to be
found, burning CPU that could go toward satellites actually overhead.

This adds continuous visibility tracking instead: as the receiver gets
a fix (or an AGNSS reference position) and as ephemeris/almanac data
arrives, satellites are classified into "visible" (elevation computable
and above GNSS-SDR.search_elevation_mask), "excluded" (elevation
computable and at/below the mask), or implicitly "maybe visible" (no
data yet -- still searched, just at lower priority). Classification is
re-evaluated whenever the fix becomes valid, new/updated ephemeris or
almanac data arrives for a PRN, the receiver moves significantly, a
periodic interval elapses, or classified data ages past its staleness
threshold -- not just once at startup.

A satellite that's actually acquired or tracking is never torn down
because of this classification: the search mask exists purely to avoid
wasting CPU on unlikely candidates, not as a correctness gate --
PVT.elevation_mask remains the real gate on whether a tracked
satellite's observations get used in the fix. Only the search layer
(picking new acquisitions, and not retrying a specific satellite after
a genuine loss of lock) is scoped by visibility.

Whole feature is gated behind GNSS-SDR.enable_visibility_aware_search,
default false -- disabled, every existing code path is untouched.

Key pieces:
- New SatelliteVisibility class (src/core/receiver/satellite_visibility.cc/.h):
  owns the classification state and the recompute logic, including a
  targeted-recompute path that only touches the satellite(s) whose data
  actually changed instead of the whole constellation, when nothing else
  that could affect every satellite's elevation (receiver position,
  elapsed time) has changed.
- GNSSFlowgraph: new visible/maybe-visible queue selection in
  search_next_signal(), ratio-controlled via
  GNSS-SDR.visible_vs_mayvisible_search_ratio, plus reclassification
  handling when a channel's assigned-but-not-yet-started satellite
  becomes known excluded.
- ControlThread: MaybeUpdateVisibility() is called unconditionally from
  event_dispatcher(), not just its idle branch -- the search layer's own
  acquisition churn keeps the control queue busy enough that an
  idle-only trigger would starve for the entire run right when
  reclassifying satellites out of "maybe visible" is what would reduce
  that churn.
- rtklib_conversions/rtklib_ephemeris: resolve_truncated_week() and
  reference-week-aware alm_to_rtklib() overloads, needed to correctly
  resolve Galileo's 2-bit and GPS's 8-bit truncated almanac week numbers
  against an arbitrary query time rather than only the receiver's own
  current time.
2026-09-07 15:07:08 +02:00

233 lines
7.6 KiB
C++

/*!
* \file control_thread.h
* \brief Interface of the receiver control plane
* \author Carlos Aviles, 2010. carlos.avilesr(at)googlemail.com
*
* GNSS Receiver Control Plane: connects the flowgraph, starts running it,
* and while it does not stop, reads the control messages generated by the blocks,
* processes them, and applies the corresponding actions.
*
* -----------------------------------------------------------------------------
*
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
* This file is part of GNSS-SDR.
*
* Copyright (C) 2010-2020 (see AUTHORS file for a list of contributors)
* SPDX-License-Identifier: GPL-3.0-or-later
*
* -----------------------------------------------------------------------------
*/
#ifndef GNSS_SDR_CONTROL_THREAD_H
#define GNSS_SDR_CONTROL_THREAD_H
#include "agnss_ref_location.h" // for Agnss_Ref_Location
#include "agnss_ref_time.h" // for Agnss_Ref_Time
#include "channel_event.h" // for channel_event_sptr
#include "command_event.h" // for command_event_sptr
#include "concurrent_queue.h" // for Concurrent_Queue
#include "gnss_sdr_supl_client.h" // for Gnss_Sdr_Supl_Client
#include "tcp_cmd_interface.h" // for TcpCmdInterface
#include <pmt/pmt.h>
#include <array> // for array
#include <cstddef> // for size_t
#include <cstdint> // for int32_t
#include <memory> // for shared_ptr
#include <string> // for string
#include <thread> // for std::thread
#include <typeinfo> // for std::type_info, typeid
#include <utility> // for pair
#include <vector> // for vector
#ifdef ENABLE_FPGA
#include <boost/thread.hpp> // for boost::thread
#endif
/** \addtogroup Core Core GNSS Receiver
* Core GNSS Receiver.
* \{ */
/** \addtogroup Core_Receiver
* Classes for the core GNSS receiver.
* \{ */
class ConfigurationInterface;
class GNSSFlowgraph;
class Gnss_Satellite;
/*!
* \brief This class represents the main thread of the application, so the name is ControlThread.
* This is the GNSS Receiver Control Plane: it connects the flowgraph, starts running it,
* and while it does not stop, reads the control messages generated by the blocks,
* processes them, and applies the corresponding actions.
*/
class ControlThread
{
public:
static ControlThread *me;
/*!
* \brief Default constructor
*/
ControlThread();
/*!
* \brief Constructor that initializes the class with parameters
*
* \param[in] configuration Pointer to a ConfigurationInterface
*/
explicit ControlThread(std::shared_ptr<ConfigurationInterface> configuration);
/*!
* \brief Destructor
*/
~ControlThread();
/*! \brief Runs the control thread
*
* This is the main loop that reads and process the control messages:
*
* - Connect the GNSS receiver flowgraph;
*
* - Start the GNSS receiver flowgraph;
*
* while (flowgraph_->running() && !stop_){
*
* - Read control messages and process them; }
*/
int run();
/*!
* \brief Sets the control_queue
*
* \param[in] std::shared_ptr<Concurrent_Queue<pmt::pmt_t>> control_queue
*/
void set_control_queue(std::shared_ptr<Concurrent_Queue<pmt::pmt_t>> control_queue);
unsigned int processed_control_messages() const
{
return processed_control_messages_;
}
unsigned int applied_actions() const
{
return applied_actions_;
}
/*!
* \brief Instantiates a flowgraph
*
* \return Returns a smart pointer to a flowgraph object
*/
std::shared_ptr<GNSSFlowgraph> flowgraph()
{
return flowgraph_;
}
private:
/*
* Callback function for handling signals.
* sig identifier of signal
*/
static void handle_signal(int sig);
void init();
void apply_action(unsigned int what);
/*
* New receiver event dispatcher
*/
void event_dispatcher(bool &valid_event, pmt::pmt_t &msg);
// Read {ephemeris, iono, utc, ref loc, ref time} assistance from a local XML file previously recorded
bool read_assistance_from_XML();
/*
* Blocking function that reads the GPS assistance queue
*/
void gps_acq_assist_data_collector() const;
/*
* Compute elevations for the specified time and position for all the available satellites in ephemeris and almanac queues
* returns a vector filled with the available satellites ordered from high elevation to low elevation angle.
*/
std::vector<std::pair<int, Gnss_Satellite>> get_visible_sats(time_t rx_utc_time, const std::array<float, 3> &LLH);
/*
* Read initial GNSS assistance from SUPL server or local XML files
*/
void assist_GNSS();
void telecommand_listener();
void keyboard_listener();
void message_queue_listener();
void print_help_at_exit() const;
// default filename for assistance data
const std::string eph_default_xml_filename_ = "./gps_ephemeris.xml";
const std::string utc_default_xml_filename_ = "./gps_utc_model.xml";
const std::string iono_default_xml_filename_ = "./gps_iono.xml";
const std::string ref_time_default_xml_filename_ = "./gps_ref_time.xml";
const std::string ref_location_default_xml_filename_ = "./gps_ref_location.xml";
const std::string eph_gal_default_xml_filename_ = "./gal_ephemeris.xml";
const std::string eph_cnav_default_xml_filename_ = "./gps_cnav_ephemeris.xml";
const std::string gal_iono_default_xml_filename_ = "./gal_iono.xml";
const std::string gal_utc_default_xml_filename_ = "./gal_utc_model.xml";
const std::string cnav_utc_default_xml_filename_ = "./gps_cnav_utc_model.xml";
const std::string eph_glo_gnav_default_xml_filename_ = "./glo_gnav_ephemeris.xml";
const std::string glo_utc_default_xml_filename_ = "./glo_utc_model.xml";
const std::string gal_almanac_default_xml_filename_ = "./gal_almanac.xml";
const std::string gps_almanac_default_xml_filename_ = "./gps_almanac.xml";
const std::string control_message_queue_name_ = "receiver_control_queue";
const size_t channel_event_type_hash_code_ = typeid(channel_event_sptr).hash_code();
const size_t command_event_type_hash_code_ = typeid(command_event_sptr).hash_code();
std::shared_ptr<ConfigurationInterface> configuration_;
std::shared_ptr<Concurrent_Queue<pmt::pmt_t>> control_queue_;
std::shared_ptr<GNSSFlowgraph> flowgraph_;
std::thread cmd_interface_thread_;
std::thread keyboard_thread_;
std::thread message_queue_thread_;
std::thread gps_acq_assist_data_collector_thread_;
#ifdef ENABLE_FPGA
boost::thread fpga_helper_thread_;
#endif
TcpCmdInterface cmd_interface_;
// SUPL assistance classes
Gnss_Sdr_Supl_Client supl_client_acquisition_;
Gnss_Sdr_Supl_Client supl_client_ephemeris_;
int supl_mcc_; // Current network MCC (Mobile country code), 3 digits.
int supl_mns_; // Current network MNC (Mobile Network code), 2 or 3 digits.
int supl_lac_; // Current network LAC (Location area code),16 bits, 1-65520 are valid values.
int supl_ci_; // Cell Identity (16 bits, 0-65535 are valid values).
Agnss_Ref_Location agnss_ref_location_;
Agnss_Ref_Time agnss_ref_time_;
unsigned int processed_control_messages_;
unsigned int applied_actions_;
bool well_formatted_configuration_;
bool conf_file_has_section_;
bool conf_file_has_mandatory_globals_;
bool conf_has_signal_sources_;
bool conf_has_observables_;
bool conf_has_pvt_;
bool receiver_on_standby_;
bool stop_;
bool restart_;
bool telecommand_enabled_;
};
/** \} */
/** \} */
#endif // GNSS_SDR_CONTROL_THREAD_H