mirror of
				https://github.com/gnss-sdr/gnss-sdr
				synced 2025-10-31 07:13:03 +00:00 
			
		
		
		
	Improve error handling when the flow graph fails to start
Avoid segmentation faults due to some common inconsistencies in the configuration file E.g.: non-existing names for blocks implementation, some mismatched input/output item sizes Provide hints to the user on how to fix the configuration in case of failure when starting the flow graph
This commit is contained in:
		| @@ -28,6 +28,15 @@ SPDX-FileCopyrightText: 2011-2021 Carles Fernandez-Prades <carles.fernandez@cttc | ||||
| - Improved handling of change in GNU Radio 3.9 FFT API. | ||||
| - Improved handling of the filesystem library. | ||||
| - Do not apply clang-tidy fixes to protobuf-generated headers. | ||||
| - Refactored private implementation of flow graph connection and disconnection | ||||
|   for improved source code readability. | ||||
|  | ||||
| ### Improvements in Usability: | ||||
|  | ||||
| - Avoid segmentation faults in the flow graph connection and/or starting due to | ||||
|   some common inconsistencies in the configuration file. | ||||
| - Provide hints to the user in case of failed flow graph connection due to | ||||
|   inconsistencies in the configuration file. | ||||
|  | ||||
|   | ||||
|  | ||||
|   | ||||
| @@ -17,6 +17,7 @@ | ||||
|  | ||||
| #include "signal_conditioner.h" | ||||
| #include <glog/logging.h> | ||||
| #include <stdexcept> | ||||
| #include <utility> | ||||
|  | ||||
|  | ||||
| @@ -40,6 +41,18 @@ void SignalConditioner::connect(gr::top_block_sptr top_block) | ||||
|             LOG(WARNING) << "Signal conditioner already connected internally"; | ||||
|             return; | ||||
|         } | ||||
|     if (data_type_adapt_ == nullptr) | ||||
|         { | ||||
|             throw std::invalid_argument("DataTypeAdapter implementation not defined"); | ||||
|         } | ||||
|     if (in_filt_ == nullptr) | ||||
|         { | ||||
|             throw std::invalid_argument("InputFilter implementation not defined"); | ||||
|         } | ||||
|     if (res_ == nullptr) | ||||
|         { | ||||
|             throw std::invalid_argument("Resampler implementation not defined"); | ||||
|         } | ||||
|     data_type_adapt_->connect(top_block); | ||||
|     in_filt_->connect(top_block); | ||||
|     res_->connect(top_block); | ||||
|   | ||||
| @@ -300,7 +300,6 @@ int ControlThread::run() | ||||
|         } | ||||
|     else | ||||
|         { | ||||
|             LOG(ERROR) << "Unable to connect flowgraph"; | ||||
|             return 0; | ||||
|         } | ||||
|     // Start the flowgraph | ||||
| @@ -311,7 +310,6 @@ int ControlThread::run() | ||||
|         } | ||||
|     else | ||||
|         { | ||||
|             LOG(ERROR) << "Unable to start flowgraph"; | ||||
|             return 0; | ||||
|         } | ||||
|  | ||||
|   | ||||
| @@ -374,6 +374,7 @@ std::unique_ptr<GNSSBlockInterface> GNSSBlockFactory::GetChannel( | ||||
|     if (acq_item_type != trk_item_type) | ||||
|         { | ||||
|             LOG(ERROR) << "Acquisition and Tracking blocks must have the same input data type!"; | ||||
|             return nullptr; | ||||
|         } | ||||
|  | ||||
|     LOG(INFO) << "Instantiating Channel " << channel | ||||
| @@ -388,6 +389,11 @@ std::unique_ptr<GNSSBlockInterface> GNSSBlockFactory::GetChannel( | ||||
|     std::unique_ptr<TrackingInterface> trk_ = GetTrkBlock(configuration, "Tracking_" + signal + appendix2, 1, 1); | ||||
|     std::unique_ptr<TelemetryDecoderInterface> tlm_ = GetTlmBlock(configuration, "TelemetryDecoder_" + signal + appendix3, 1, 1); | ||||
|  | ||||
|     if (acq_ == nullptr or trk_ == nullptr or tlm_ == nullptr) | ||||
|         { | ||||
|             return nullptr; | ||||
|         } | ||||
|  | ||||
|     std::unique_ptr<GNSSBlockInterface> channel_ = std::make_unique<Channel>(configuration, channel, | ||||
|         std::move(acq_), | ||||
|         std::move(trk_), | ||||
| @@ -1320,8 +1326,7 @@ std::unique_ptr<GNSSBlockInterface> GNSSBlockFactory::GetBlock( | ||||
|  | ||||
|     else | ||||
|         { | ||||
|             // Log fatal. This causes execution to stop. | ||||
|             LOG(ERROR) << role << "." << implementation << ": Undefined implementation for block"; | ||||
|             LOG(ERROR) << role << " block: Undefined implementation " << implementation; | ||||
|         } | ||||
|     return block; | ||||
| } | ||||
| @@ -1515,8 +1520,7 @@ std::unique_ptr<AcquisitionInterface> GNSSBlockFactory::GetAcqBlock( | ||||
|  | ||||
|     else | ||||
|         { | ||||
|             // Log fatal. This causes execution to stop. | ||||
|             LOG(ERROR) << role << "." << implementation << ": Undefined implementation for block"; | ||||
|             LOG(ERROR) << role << " block: Undefined implementation " << implementation; | ||||
|         } | ||||
|     return block; | ||||
| } | ||||
| @@ -1671,8 +1675,7 @@ std::unique_ptr<TrackingInterface> GNSSBlockFactory::GetTrkBlock( | ||||
| #endif | ||||
|     else | ||||
|         { | ||||
|             // Log fatal. This causes execution to stop. | ||||
|             LOG(ERROR) << role << "." << implementation << ": Undefined implementation for block"; | ||||
|             LOG(ERROR) << role << " block: Undefined implementation " << implementation; | ||||
|         } | ||||
|     return block; | ||||
| } | ||||
| @@ -1764,8 +1767,7 @@ std::unique_ptr<TelemetryDecoderInterface> GNSSBlockFactory::GetTlmBlock( | ||||
|  | ||||
|     else | ||||
|         { | ||||
|             // Log fatal. This causes execution to stop. | ||||
|             LOG(ERROR) << role << "." << implementation << ": Undefined implementation for block"; | ||||
|             LOG(ERROR) << role << " block: Undefined implementation " << implementation; | ||||
|         } | ||||
|     return block; | ||||
| } | ||||
|   | ||||
| @@ -128,7 +128,10 @@ void GNSSFlowgraph::init() | ||||
|             // TODO: Create a class interface for SignalSources, derived from GNSSBlockInterface. | ||||
|             // Include GetRFChannels in the interface to avoid read config parameters here | ||||
|             // read the number of RF channels for each front-end | ||||
|             if (sig_source_.at(0) != nullptr) | ||||
|                 { | ||||
|                     RF_Channels = configuration_->property(sig_source_.at(0)->role() + ".RF_channels", 0); | ||||
|                 } | ||||
|             if (RF_Channels != 0) | ||||
|                 { | ||||
|                     for (int j = 0; j < RF_Channels; j++) | ||||
| @@ -265,6 +268,7 @@ void GNSSFlowgraph::start() | ||||
|     catch (const std::exception& e) | ||||
|         { | ||||
|             LOG(ERROR) << "Unable to start flowgraph: " << e.what(); | ||||
|             print_help(); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
| @@ -321,11 +325,15 @@ void GNSSFlowgraph::connect() | ||||
| #if ENABLE_FPGA | ||||
|     if (connect_fpga_flowgraph() != 0) | ||||
|         { | ||||
|             LOG(ERROR) << "Unable to connect flowgraph with FPFA off-loading"; | ||||
|             print_help(); | ||||
|             return; | ||||
|         } | ||||
| #else | ||||
|     if (connect_desktop_flowgraph() != 0) | ||||
|         { | ||||
|             LOG(ERROR) << "Unable to connect flowgraph"; | ||||
|             print_help(); | ||||
|             return; | ||||
|         } | ||||
| #endif | ||||
| @@ -342,7 +350,7 @@ void GNSSFlowgraph::disconnect() | ||||
|  | ||||
|     if (!connected_) | ||||
|         { | ||||
|             LOG(INFO) << "flowgraph was not connected"; | ||||
|             LOG(INFO) << "Flowgraph was not connected"; | ||||
|             return; | ||||
|         } | ||||
|     connected_ = false; | ||||
| @@ -539,6 +547,8 @@ int GNSSFlowgraph::connect_fpga_flowgraph() | ||||
|     DLOG(INFO) << "Blocks connected internally to the top_block"; | ||||
|  | ||||
|     // Connect the counter | ||||
|     if (sig_source_.at(0) != nullptr) | ||||
|         { | ||||
|             if (configuration_->property(sig_source_.at(0)->role() + ".enable_FPGA", false) == false) | ||||
|                 { | ||||
|                     if (connect_sample_counter() != 0) | ||||
| @@ -553,6 +563,13 @@ int GNSSFlowgraph::connect_fpga_flowgraph() | ||||
|                             return 1; | ||||
|                         } | ||||
|                 } | ||||
|         } | ||||
|     else | ||||
|         { | ||||
|             help_hint_ += " * Check implementation name for SignalSource block\n"; | ||||
|             help_hint_ += "   Signal Source block implementation for FPGA off-loading should be 'Ad9361_Fpga_Signal_Source'\n"; | ||||
|             return 1; | ||||
|         } | ||||
|  | ||||
|     if (connect_channels_to_observables() != 0) | ||||
|         { | ||||
| @@ -575,6 +592,9 @@ int GNSSFlowgraph::connect_fpga_flowgraph() | ||||
|         { | ||||
|             return 1; | ||||
|         } | ||||
|  | ||||
|     check_desktop_conf_in_fpga_env(); | ||||
|  | ||||
|     LOG(INFO) << "The GNU Radio flowgraph for the current GNSS-SDR configuration with FPGA off-loading has been successfully connected"; | ||||
|     return 0; | ||||
| } | ||||
| @@ -653,6 +673,8 @@ int GNSSFlowgraph::disconnect_fpga_flowgraph() | ||||
| int GNSSFlowgraph::connect_signal_sources() | ||||
| { | ||||
|     for (int i = 0; i < sources_count_; i++) | ||||
|         { | ||||
|             if (sig_source_.at(i) != nullptr) | ||||
|                 { | ||||
|                     try | ||||
|                         { | ||||
| @@ -665,6 +687,14 @@ int GNSSFlowgraph::connect_signal_sources() | ||||
|                             return 1; | ||||
|                         } | ||||
|                 } | ||||
|             else | ||||
|                 { | ||||
|                     help_hint_ += " * Check implementation name for SignalSource" + (i == 0 ? " " : (std::to_string(i) + " ")) + "block\n"; | ||||
|                     help_hint_ += "   Signal Source blocks documentation at https://gnss-sdr.org/docs/sp-blocks/signal-source/\n"; | ||||
|                     top_block_->disconnect_all(); | ||||
|                     return 1; | ||||
|                 } | ||||
|         } | ||||
|     DLOG(INFO) << "Signal Source blocks successfully connected to the top_block"; | ||||
|     return 0; | ||||
| } | ||||
| @@ -689,9 +719,76 @@ int GNSSFlowgraph::disconnect_signal_sources() | ||||
| } | ||||
|  | ||||
|  | ||||
| int GNSSFlowgraph::connect_signal_conditioners() | ||||
| { | ||||
|     for (auto& sig : sig_conditioner_) | ||||
|         { | ||||
|             try | ||||
|                 { | ||||
|                     sig->connect(top_block_); | ||||
|                 } | ||||
|             catch (const std::exception& e) | ||||
|                 { | ||||
|                     LOG(ERROR) << "Can't connect signal conditioner block internally: " << e.what(); | ||||
|                     top_block_->disconnect_all(); | ||||
|                     std::string reported_error(e.what()); | ||||
|                     if (std::string::npos != reported_error.find(std::string("itemsize mismatch"))) | ||||
|                         { | ||||
|                             std::string replace_me("copy"); | ||||
|                             size_t pos = reported_error.find(replace_me); | ||||
|                             size_t len = replace_me.length(); | ||||
|                             reported_error.replace(pos, len, "PassThrough"); | ||||
|                             help_hint_ += " * Blocks within the Signal Conditioner are connected with mismatched item size\n"; | ||||
|                             help_hint_ += "   Reported error: " + reported_error + '\n'; | ||||
|                             help_hint_ += "   Check the Signal Conditioner documentation at https://gnss-sdr.org/docs/sp-blocks/signal-conditioner/\n"; | ||||
|                         } | ||||
|                     if (std::string::npos != reported_error.find(std::string("DataTypeAdapter"))) | ||||
|                         { | ||||
|                             help_hint_ += " * The DataTypeAdapter implementation set in the configuration file does not exist\n"; | ||||
|                             help_hint_ += "   Check the DataTypeAdapter documentation at https://gnss-sdr.org/docs/sp-blocks/data-type-adapter/\n"; | ||||
|                         } | ||||
|                     if (std::string::npos != reported_error.find(std::string("InputFilter"))) | ||||
|                         { | ||||
|                             help_hint_ += " * The InputFilter implementation set in the configuration file does not exist\n"; | ||||
|                             help_hint_ += "   Check the InputFilter documentation at https://gnss-sdr.org/docs/sp-blocks/input-filter/\n"; | ||||
|                         } | ||||
|                     if (std::string::npos != reported_error.find(std::string("Resampler"))) | ||||
|                         { | ||||
|                             help_hint_ += " * The Resampler implementation set in the configuration file does not exist\n"; | ||||
|                             help_hint_ += "   Check the Resampler documentation at https://gnss-sdr.org/docs/sp-blocks/resampler/\n"; | ||||
|                         } | ||||
|                     return 1; | ||||
|                 } | ||||
|         } | ||||
|     DLOG(INFO) << "Signal Conditioner blocks successfully connected to the top_block"; | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
|  | ||||
| int GNSSFlowgraph::disconnect_signal_conditioners() | ||||
| { | ||||
|     for (auto& sig : sig_conditioner_) | ||||
|         { | ||||
|             try | ||||
|                 { | ||||
|                     sig->disconnect(top_block_); | ||||
|                 } | ||||
|             catch (const std::exception& e) | ||||
|                 { | ||||
|                     LOG(INFO) << "Can't disconnect signal conditioner block internally: " << e.what(); | ||||
|                     top_block_->disconnect_all(); | ||||
|                     return 1; | ||||
|                 } | ||||
|         } | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
|  | ||||
| int GNSSFlowgraph::connect_channels() | ||||
| { | ||||
|     for (int i = 0; i < channels_count_; i++) | ||||
|         { | ||||
|             if (channels_.at(i) != nullptr) | ||||
|                 { | ||||
|                     try | ||||
|                         { | ||||
| @@ -704,6 +801,17 @@ int GNSSFlowgraph::connect_channels() | ||||
|                             return 1; | ||||
|                         } | ||||
|                 } | ||||
|             else | ||||
|                 { | ||||
|                     LOG(ERROR) << "Can't connect channel " << i << " internally"; | ||||
|                     help_hint_ += " * Check implementation names for Channel" + std::to_string(i) + " inner blocks.\n"; | ||||
|                     help_hint_ += "   Acquisition blocks documentation at https://gnss-sdr.org/docs/sp-blocks/acquisition/\n"; | ||||
|                     help_hint_ += "   Tracking blocks documentation at https://gnss-sdr.org/docs/sp-blocks/tracking/\n"; | ||||
|                     help_hint_ += "   Telemetry Decoder blocks documentation at https://gnss-sdr.org/docs/sp-blocks/telemetry-decoder/\n"; | ||||
|                     top_block_->disconnect_all(); | ||||
|                     return 1; | ||||
|                 } | ||||
|         } | ||||
|     DLOG(INFO) << "Channel blocks successfully connected to the top_block"; | ||||
|     return 0; | ||||
| } | ||||
| @@ -730,6 +838,13 @@ int GNSSFlowgraph::disconnect_channels() | ||||
|  | ||||
| int GNSSFlowgraph::connect_observables() | ||||
| { | ||||
|     if (observables_ == nullptr) | ||||
|         { | ||||
|             help_hint_ += " * Check implementation name for the Observables block\n"; | ||||
|             help_hint_ += "   Observables block documentation at https://gnss-sdr.org/docs/sp-blocks/observables/\n"; | ||||
|             top_block_->disconnect_all(); | ||||
|             return 1; | ||||
|         } | ||||
|     try | ||||
|         { | ||||
|             observables_->connect(top_block_); | ||||
| @@ -763,6 +878,13 @@ int GNSSFlowgraph::disconnect_observables() | ||||
|  | ||||
| int GNSSFlowgraph::connect_pvt() | ||||
| { | ||||
|     if (pvt_ == nullptr) | ||||
|         { | ||||
|             help_hint_ += " * Check implementation name for the PVT block\n"; | ||||
|             help_hint_ += "   PVT block documentation at https://gnss-sdr.org/docs/sp-blocks/pvt/\n"; | ||||
|             top_block_->disconnect_all(); | ||||
|             return 1; | ||||
|         } | ||||
|     try | ||||
|         { | ||||
|             pvt_->connect(top_block_); | ||||
| @@ -840,6 +962,7 @@ int GNSSFlowgraph::disconnect_sample_counter() | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
|  | ||||
| #if ENABLE_FPGA | ||||
| int GNSSFlowgraph::connect_fpga_sample_counter() | ||||
| { | ||||
| @@ -918,6 +1041,8 @@ int GNSSFlowgraph::connect_signal_sources_to_signal_conditioners() | ||||
|                                     // GNURADIO max_streams=-1 means infinite ports! | ||||
|                                     DLOG(INFO) << "sig_source_.at(i)->get_right_block()->output_signature()->max_streams()=" << sig_source_.at(i)->get_right_block()->output_signature()->max_streams(); | ||||
|                                     DLOG(INFO) << "sig_conditioner_.at(signal_conditioner_ID)->get_left_block()->input_signature()=" << sig_conditioner_.at(signal_conditioner_ID)->get_left_block()->input_signature()->max_streams(); | ||||
|                                     size_t output_size = sig_source_.at(i)->item_size(); | ||||
|                                     size_t input_size = sig_conditioner_.at(signal_conditioner_ID)->get_left_block()->input_signature()->sizeof_stream_item(0); | ||||
|  | ||||
|                                     if (sig_source_.at(i)->get_right_block()->output_signature()->max_streams() > 1 or sig_source_.at(i)->get_right_block()->output_signature()->max_streams() == -1) | ||||
|                                         { | ||||
| @@ -943,12 +1068,28 @@ int GNSSFlowgraph::connect_signal_sources_to_signal_conditioners() | ||||
|                                                 } | ||||
|                                         } | ||||
|                                     signal_conditioner_ID++; | ||||
|                                     // Check configuration inconsistencies | ||||
|                                     if (output_size != input_size) | ||||
|                                         { | ||||
|                                             help_hint_ += " * The Signal Source implementation " + sig_source_.at(i)->implementation() + " has an output with an item size of " + std::to_string(output_size) + " bytes, but it is connected to the Signal Conditioner implementation " + sig_conditioner_.at(signal_conditioner_ID)->implementation() + " with input item size of " + std::to_string(input_size) + "bytes.\n"; | ||||
|                                             help_hint_ += "   Output ports must be connected to input ports with the same item size.\n"; | ||||
|                                         } | ||||
|                                 } | ||||
|                         } | ||||
|                 } | ||||
|             catch (const std::exception& e) | ||||
|                 { | ||||
|                     LOG(ERROR) << "Can't connect signal source " << i << " to signal conditioner " << i << ": " << e.what(); | ||||
|                     LOG(ERROR) << "Can't connect SignalSource" << (i == 0 ? " " : (std::to_string(i) + " ")) << "to SignalConditioner" << (i == 0 ? " " : (std::to_string(i) + " ")) << ": " << e.what(); | ||||
|                     std::string reported_error(e.what()); | ||||
|                     if (std::string::npos != reported_error.find(std::string("itemsize mismatch"))) | ||||
|                         { | ||||
|                             std::string replace_me("copy"); | ||||
|                             size_t pos = reported_error.find(replace_me); | ||||
|                             size_t len = replace_me.length(); | ||||
|                             reported_error.replace(pos, len, "PassThrough"); | ||||
|                             help_hint_ += " * The SignalSource output item size and the SignalConditioner input item size are mismatched\n"; | ||||
|                             help_hint_ += "   Reported error: " + reported_error + '\n'; | ||||
|                         } | ||||
|                     top_block_->disconnect_all(); | ||||
|                     return 1; | ||||
|                 } | ||||
| @@ -959,6 +1100,65 @@ int GNSSFlowgraph::connect_signal_sources_to_signal_conditioners() | ||||
| } | ||||
|  | ||||
|  | ||||
| int GNSSFlowgraph::disconnect_signal_sources_from_signal_conditioners() | ||||
| { | ||||
|     int RF_Channels = 0; | ||||
|     int signal_conditioner_ID = 0; | ||||
|     for (int i = 0; i < sources_count_; i++) | ||||
|         { | ||||
|             try | ||||
|                 { | ||||
|                     // TODO: Remove this array implementation and create generic multistream connector | ||||
|                     // (if a signal source has more than 1 stream, then connect it to the multistream signal conditioner) | ||||
|                     if (sig_source_.at(i)->implementation() == "Raw_Array_Signal_Source") | ||||
|                         { | ||||
|                             // Multichannel Array | ||||
|                             for (int j = 0; j < GNSS_SDR_ARRAY_SIGNAL_CONDITIONER_CHANNELS; j++) | ||||
|                                 { | ||||
|                                     top_block_->disconnect(sig_source_.at(i)->get_right_block(), j, sig_conditioner_.at(i)->get_left_block(), j); | ||||
|                                 } | ||||
|                         } | ||||
|                     else | ||||
|                         { | ||||
|                             // TODO: Create a class interface for SignalSources, derived from GNSSBlockInterface. | ||||
|                             // Include GetRFChannels in the interface to avoid read config parameters here | ||||
|                             // read the number of RF channels for each front-end | ||||
|                             RF_Channels = configuration_->property(sig_source_.at(i)->role() + ".RF_channels", 1); | ||||
|  | ||||
|                             for (int j = 0; j < RF_Channels; j++) | ||||
|                                 { | ||||
|                                     if (sig_source_.at(i)->get_right_block()->output_signature()->max_streams() > 1 or sig_source_.at(i)->get_right_block()->output_signature()->max_streams() == -1) | ||||
|                                         { | ||||
|                                             top_block_->disconnect(sig_source_.at(i)->get_right_block(), j, sig_conditioner_.at(signal_conditioner_ID)->get_left_block(), 0); | ||||
|                                         } | ||||
|                                     else | ||||
|                                         { | ||||
|                                             if (j == 0) | ||||
|                                                 { | ||||
|                                                     // RF_channel 0 backward compatibility with single channel sources | ||||
|                                                     top_block_->disconnect(sig_source_.at(i)->get_right_block(), 0, sig_conditioner_.at(signal_conditioner_ID)->get_left_block(), 0); | ||||
|                                                 } | ||||
|                                             else | ||||
|                                                 { | ||||
|                                                     // Multiple channel sources using multiple output blocks of single channel (requires RF_channel selector in call) | ||||
|                                                     top_block_->disconnect(sig_source_.at(i)->get_right_block(j), 0, sig_conditioner_.at(signal_conditioner_ID)->get_left_block(), 0); | ||||
|                                                 } | ||||
|                                         } | ||||
|                                     signal_conditioner_ID++; | ||||
|                                 } | ||||
|                         } | ||||
|                 } | ||||
|             catch (const std::exception& e) | ||||
|                 { | ||||
|                     LOG(INFO) << "Can't disconnect signal source " << i << " to signal conditioner " << i << ": " << e.what(); | ||||
|                     top_block_->disconnect_all(); | ||||
|                     return 1; | ||||
|                 } | ||||
|         } | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
|  | ||||
| int GNSSFlowgraph::connect_signal_conditioners_to_channels() | ||||
| { | ||||
|     for (int i = 0; i < channels_count_; i++) | ||||
| @@ -1096,7 +1296,7 @@ int GNSSFlowgraph::connect_signal_conditioners_to_channels() | ||||
|                 } | ||||
|  | ||||
|             signal_conditioner_connected_.at(selected_signal_conditioner_ID) = true;  // annotate that this signal conditioner is connected | ||||
|             DLOG(INFO) << "signal conditioner " << selected_signal_conditioner_ID << " successfully connected to channel " << i; | ||||
|             DLOG(INFO) << "Signal conditioner " << selected_signal_conditioner_ID << " successfully connected to channel " << i; | ||||
|         } | ||||
|     return 0; | ||||
| } | ||||
| @@ -1349,104 +1549,6 @@ int GNSSFlowgraph::disconnect_monitors() | ||||
| } | ||||
|  | ||||
|  | ||||
| int GNSSFlowgraph::connect_signal_conditioners() | ||||
| { | ||||
|     for (auto& sig : sig_conditioner_) | ||||
|         { | ||||
|             try | ||||
|                 { | ||||
|                     sig->connect(top_block_); | ||||
|                 } | ||||
|             catch (const std::exception& e) | ||||
|                 { | ||||
|                     LOG(ERROR) << "Can't connect signal conditioner block internally: " << e.what(); | ||||
|                     top_block_->disconnect_all(); | ||||
|                     return 1; | ||||
|                 } | ||||
|         } | ||||
|     DLOG(INFO) << "Signal Conditioner blocks successfully connected to the top_block"; | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
|  | ||||
| int GNSSFlowgraph::disconnect_signal_conditioners() | ||||
| { | ||||
|     for (auto& sig : sig_conditioner_) | ||||
|         { | ||||
|             try | ||||
|                 { | ||||
|                     sig->disconnect(top_block_); | ||||
|                 } | ||||
|             catch (const std::exception& e) | ||||
|                 { | ||||
|                     LOG(INFO) << "Can't disconnect signal conditioner block internally: " << e.what(); | ||||
|                     top_block_->disconnect_all(); | ||||
|                     return 1; | ||||
|                 } | ||||
|         } | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
|  | ||||
| int GNSSFlowgraph::disconnect_signal_sources_from_signal_conditioners() | ||||
| { | ||||
|     int RF_Channels = 0; | ||||
|     int signal_conditioner_ID = 0; | ||||
|     for (int i = 0; i < sources_count_; i++) | ||||
|         { | ||||
|             try | ||||
|                 { | ||||
|                     // TODO: Remove this array implementation and create generic multistream connector | ||||
|                     // (if a signal source has more than 1 stream, then connect it to the multistream signal conditioner) | ||||
|                     if (sig_source_.at(i)->implementation() == "Raw_Array_Signal_Source") | ||||
|                         { | ||||
|                             // Multichannel Array | ||||
|                             for (int j = 0; j < GNSS_SDR_ARRAY_SIGNAL_CONDITIONER_CHANNELS; j++) | ||||
|                                 { | ||||
|                                     top_block_->disconnect(sig_source_.at(i)->get_right_block(), j, sig_conditioner_.at(i)->get_left_block(), j); | ||||
|                                 } | ||||
|                         } | ||||
|                     else | ||||
|                         { | ||||
|                             // TODO: Create a class interface for SignalSources, derived from GNSSBlockInterface. | ||||
|                             // Include GetRFChannels in the interface to avoid read config parameters here | ||||
|                             // read the number of RF channels for each front-end | ||||
|                             RF_Channels = configuration_->property(sig_source_.at(i)->role() + ".RF_channels", 1); | ||||
|  | ||||
|                             for (int j = 0; j < RF_Channels; j++) | ||||
|                                 { | ||||
|                                     if (sig_source_.at(i)->get_right_block()->output_signature()->max_streams() > 1 or sig_source_.at(i)->get_right_block()->output_signature()->max_streams() == -1) | ||||
|                                         { | ||||
|                                             top_block_->disconnect(sig_source_.at(i)->get_right_block(), j, sig_conditioner_.at(signal_conditioner_ID)->get_left_block(), 0); | ||||
|                                         } | ||||
|                                     else | ||||
|                                         { | ||||
|                                             if (j == 0) | ||||
|                                                 { | ||||
|                                                     // RF_channel 0 backward compatibility with single channel sources | ||||
|                                                     top_block_->disconnect(sig_source_.at(i)->get_right_block(), 0, sig_conditioner_.at(signal_conditioner_ID)->get_left_block(), 0); | ||||
|                                                 } | ||||
|                                             else | ||||
|                                                 { | ||||
|                                                     // Multiple channel sources using multiple output blocks of single channel (requires RF_channel selector in call) | ||||
|                                                     top_block_->disconnect(sig_source_.at(i)->get_right_block(j), 0, sig_conditioner_.at(signal_conditioner_ID)->get_left_block(), 0); | ||||
|                                                 } | ||||
|                                         } | ||||
|                                     signal_conditioner_ID++; | ||||
|                                 } | ||||
|                         } | ||||
|                 } | ||||
|             catch (const std::exception& e) | ||||
|                 { | ||||
|                     LOG(INFO) << "Can't disconnect signal source " << i << " to signal conditioner " << i << ": " << e.what(); | ||||
|                     top_block_->disconnect_all(); | ||||
|                     return 1; | ||||
|                 } | ||||
|         } | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
|  | ||||
| void GNSSFlowgraph::check_signal_conditioners() | ||||
| { | ||||
|     // check for unconnected signal conditioners and connect null_sinks | ||||
| @@ -1597,6 +1699,35 @@ void GNSSFlowgraph::assign_channels() | ||||
| } | ||||
|  | ||||
|  | ||||
| void GNSSFlowgraph::print_help() | ||||
| { | ||||
|     if (!help_hint_.empty()) | ||||
|         { | ||||
|             std::cerr << "It seems that your configuration file is not well defined.\n"; | ||||
|             std::cerr << "A hint to fix your configuration file:\n"; | ||||
|             std::cerr << help_hint_; | ||||
|         } | ||||
| } | ||||
|  | ||||
|  | ||||
| void GNSSFlowgraph::check_desktop_conf_in_fpga_env() | ||||
| { | ||||
|     int number_of_fpga_acq_channels = 0; | ||||
|     for (int i = 0; i < channels_count_; i++) | ||||
|         { | ||||
|             if (channels_.at(i)->get_left_block_acq() == nullptr) | ||||
|                 { | ||||
|                     number_of_fpga_acq_channels++; | ||||
|                 } | ||||
|         } | ||||
|     if (number_of_fpga_acq_channels != channels_count_) | ||||
|         { | ||||
|             help_hint_ += " * The Acquisition block implementation is not suitable for GNSS-SDR flowgraph with FPGA off-loading\n"; | ||||
|             help_hint_ += "   If you want to use this configuration in an environment without FPGA, please rebuild GNSS-SDR with CMake option '-DENABLE_FPGA=OFF'\n"; | ||||
|         } | ||||
| } | ||||
|  | ||||
|  | ||||
| bool GNSSFlowgraph::send_telemetry_msg(const pmt::pmt_t& msg) | ||||
| { | ||||
|     // Push ephemeris to PVT telemetry msg in port using a channel out port | ||||
|   | ||||
| @@ -216,6 +216,8 @@ private: | ||||
|  | ||||
|     void push_back_signal(const Gnss_Signal& gs); | ||||
|     void remove_signal(const Gnss_Signal& gs); | ||||
|     void print_help(); | ||||
|     void check_desktop_conf_in_fpga_env(); | ||||
|  | ||||
|     double project_doppler(const std::string& searched_signal, double primary_freq_doppler_hz); | ||||
|     bool is_multiband() const; | ||||
| @@ -279,6 +281,7 @@ private: | ||||
|     std::map<std::string, StringValue> mapStringValues_; | ||||
|  | ||||
|     std::string config_file_; | ||||
|     std::string help_hint_; | ||||
|  | ||||
|     std::mutex signal_list_mutex_; | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Carles Fernandez
					Carles Fernandez