diff --git a/src/algorithms/PVT/adapters/rtklib_pvt.cc b/src/algorithms/PVT/adapters/rtklib_pvt.cc index be1c9bd8d..e04dd0765 100644 --- a/src/algorithms/PVT/adapters/rtklib_pvt.cc +++ b/src/algorithms/PVT/adapters/rtklib_pvt.cc @@ -141,14 +141,17 @@ RtklibPvt::RtklibPvt(ConfigurationInterface* configuration, */ int gps_1C_count = configuration->property("Channels_1C.count", 0); int gps_2S_count = configuration->property("Channels_2S.count", 0); + int gps_L5_count = configuration->property("Channels_L5.count", 0); int gal_1B_count = configuration->property("Channels_1B.count", 0); int gal_E5a_count = configuration->property("Channels_5X.count", 0); // GPS L5 or Galileo E5a ? int gal_E5b_count = configuration->property("Channels_7X.count", 0); unsigned int type_of_receiver = 0; + // *******************WARNING!!!!!!!*********** + // GPS L5 only configurable for single frequency, single system at the moment!!!!!! if( (gps_1C_count != 0) && (gps_2S_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0)) type_of_receiver = 1; if( (gps_1C_count == 0) && (gps_2S_count != 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0)) type_of_receiver = 2; - + if( (gps_1C_count == 0) && (gps_2S_count == 0) && (gps_L5_count != 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0)) type_of_receiver = 3; if( (gps_1C_count == 0) && (gps_2S_count == 0) && (gal_1B_count != 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0)) type_of_receiver = 4; if( (gps_1C_count == 0) && (gps_2S_count == 0) && (gal_1B_count == 0) && (gal_E5a_count != 0) && (gal_E5b_count == 0)) type_of_receiver = 5; if( (gps_1C_count == 0) && (gps_2S_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count != 0)) type_of_receiver = 6; @@ -194,7 +197,7 @@ RtklibPvt::RtklibPvt(ConfigurationInterface* configuration, int num_bands = 0; if ((gps_1C_count > 0) || (gal_1B_count > 0)) num_bands = 1; if (gps_2S_count > 0) num_bands = 2; - if ((gal_E5a_count > 0) || (gal_E5b_count > 0)) num_bands = 3; + if ((gal_E5a_count > 0) || (gal_E5b_count > 0) || (gps_L5_count > 0)) num_bands = 3; int number_of_frequencies = configuration->property(role + ".num_bands", num_bands); /* (1:L1, 2:L1+L2, 3:L1+L2+L5) */ if( (number_of_frequencies < 1) || (number_of_frequencies > 3) ) { @@ -272,7 +275,7 @@ RtklibPvt::RtklibPvt(ConfigurationInterface* configuration, int earth_tide = configuration->property(role + ".earth_tide", 0); int nsys = 0; - if ((gps_1C_count > 0) || (gps_2S_count > 0)) nsys += SYS_GPS; + if ((gps_1C_count > 0) || (gps_2S_count > 0) || (gps_L5_count > 0)) nsys += SYS_GPS; if ((gal_1B_count > 0) || (gal_E5a_count > 0) || (gal_E5b_count > 0)) nsys += SYS_GAL; int navigation_system = configuration->property(role + ".navigation_system", nsys); /* (SYS_XXX) see src/algorithms/libs/rtklib/rtklib.h */ if( (navigation_system < 1) || (navigation_system > 255) ) /* GPS: 1 SBAS: 2 GPS+SBAS: 3 Galileo: 8 Galileo+GPS: 9 GPS+SBAS+Galileo: 11 All: 255 */ diff --git a/src/algorithms/PVT/gnuradio_blocks/rtklib_pvt_cc.cc b/src/algorithms/PVT/gnuradio_blocks/rtklib_pvt_cc.cc index 152fc6f1d..4c1f4bf5d 100644 --- a/src/algorithms/PVT/gnuradio_blocks/rtklib_pvt_cc.cc +++ b/src/algorithms/PVT/gnuradio_blocks/rtklib_pvt_cc.cc @@ -345,7 +345,7 @@ rtklib_pvt_cc::~rtklib_pvt_cc() boost::archive::xml_oarchive xml(ofs); xml << boost::serialization::make_nvp("GNSS-SDR_ephemeris_map", d_ls_pvt->gps_cnav_ephemeris_map); ofs.close(); - LOG(INFO) << "Saved GPS L2CM Ephemeris map data"; + LOG(INFO) << "Saved GPS L2CM or L5 Ephemeris map data"; } catch (const std::exception & e) { @@ -354,7 +354,7 @@ rtklib_pvt_cc::~rtklib_pvt_cc() } else { - LOG(WARNING) << "Failed to save GPS L2CM Ephemeris, map is empty"; + LOG(WARNING) << "Failed to save GPS L2CM or L5 Ephemeris, map is empty"; } //save GPS L1 CA ephemeris to XML file @@ -647,6 +647,15 @@ int rtklib_pvt_cc::work (int noutput_items, gr_vector_const_void_star &input_ite b_rinex_header_written = true; // do not write header anymore } } + if(type_of_rx == 3) // GPS L5 only + { + if (gps_cnav_ephemeris_iter != d_ls_pvt->gps_cnav_ephemeris_map.cend()) + { + rp->rinex_obs_header(rp->obsFile, gps_cnav_ephemeris_iter->second, d_rx_time); + rp->rinex_nav_header(rp->navFile, d_ls_pvt->gps_cnav_iono, d_ls_pvt->gps_cnav_utc_model); + b_rinex_header_written = true; // do not write header anymore + } + } if(type_of_rx == 4) // Galileo E1B only { if (galileo_ephemeris_iter != d_ls_pvt->galileo_ephemeris_map.cend()) @@ -749,6 +758,10 @@ int rtklib_pvt_cc::work (int noutput_items, gr_vector_const_void_star &input_ite { rp->log_rinex_nav(rp->navFile, d_ls_pvt->gps_cnav_ephemeris_map); } + if(type_of_rx == 3) // GPS L5 only + { + rp->log_rinex_nav(rp->navFile, d_ls_pvt->gps_cnav_ephemeris_map); + } if( (type_of_rx == 4) || (type_of_rx == 5) || (type_of_rx == 6) ) // Galileo { rp->log_rinex_nav(rp->navGalFile, d_ls_pvt->galileo_ephemeris_map); @@ -799,6 +812,19 @@ int rtklib_pvt_cc::work (int noutput_items, gr_vector_const_void_star &input_ite b_rinex_header_updated = true; } } + if(type_of_rx == 3) // GPS L5 + { + if (gps_cnav_ephemeris_iter != d_ls_pvt->gps_cnav_ephemeris_map.end()) + { + rp->log_rinex_obs(rp->obsFile, gps_cnav_ephemeris_iter->second, d_rx_time, gnss_observables_map); + } + if (!b_rinex_header_updated && (d_ls_pvt->gps_cnav_utc_model.d_A0 != 0)) + { + rp->update_obs_header(rp->obsFile, d_ls_pvt->gps_cnav_utc_model); + rp->update_nav_header(rp->navFile, d_ls_pvt->gps_cnav_utc_model, d_ls_pvt->gps_cnav_iono); + b_rinex_header_updated = true; + } + } if(type_of_rx == 4) // Galileo E1B only { if (galileo_ephemeris_iter != d_ls_pvt->galileo_ephemeris_map.end()) diff --git a/src/core/receiver/gnss_block_factory.cc b/src/core/receiver/gnss_block_factory.cc index db0103fc6..8248de9a2 100644 --- a/src/core/receiver/gnss_block_factory.cc +++ b/src/core/receiver/gnss_block_factory.cc @@ -523,6 +523,74 @@ std::unique_ptr GNSSBlockFactory::GetChannel_5X( return channel_; } +//********* GPS L5 CHANNEL ***************** +std::unique_ptr GNSSBlockFactory::GetChannel_L5( + std::shared_ptr configuration, + std::string acq, std::string trk, std::string tlm, int channel, + boost::shared_ptr queue) +{ + std::stringstream stream; + stream << channel; + std::string id = stream.str(); + LOG(INFO) << "Instantiating Channel " << id << " with Acquisition Implementation: " + << acq << ", Tracking Implementation: " << trk << ", Telemetry Decoder implementation: " << tlm; + std::string aux = configuration->property("Acquisition_L5" + boost::lexical_cast(channel) + ".implementation", std::string("W")); + std::string appendix1; + if(aux.compare("W") != 0) + { + appendix1 = boost::lexical_cast(channel); + } + else + { + appendix1 = ""; + } + aux = configuration->property("Tracking_L5" + boost::lexical_cast(channel) + ".implementation", std::string("W")); + std::string appendix2; + if(aux.compare("W") != 0) + { + appendix2 = boost::lexical_cast(channel); + } + else + { + appendix2 = ""; + } + aux = configuration->property("TelemetryDecoder_L5" + boost::lexical_cast(channel) + ".implementation", std::string("W")); + std::string appendix3; + if(aux.compare("W") != 0) + { + appendix3 = boost::lexical_cast(channel); + } + else + { + appendix3 = ""; + } + // Automatically detect input data type + std::shared_ptr config; + config = std::make_shared(); + std::string default_item_type = "gr_complex"; + std::string acq_item_type = configuration->property("Acquisition_L5" + appendix1 + ".item_type", default_item_type); + std::string trk_item_type = configuration->property("Tracking_L5" + appendix2 + ".item_type", default_item_type); + if(acq_item_type.compare(trk_item_type)) + { + LOG(ERROR) << "Acquisition and Tracking blocks must have the same input data type!"; + } + config->set_property("Channel.item_type", acq_item_type); + + std::unique_ptr pass_through_ = GetBlock(configuration, "Channel", "Pass_Through", 1, 1, queue); + std::unique_ptr acq_ = GetAcqBlock(configuration, "Acquisition_L5" + appendix1, acq, 1, 0); + std::unique_ptr trk_ = GetTrkBlock(configuration, "Tracking_L5" + appendix2, trk, 1, 1); + std::unique_ptr tlm_ = GetTlmBlock(configuration, "TelemetryDecoder_L5" + appendix3, tlm, 1, 1); + + std::unique_ptr channel_(new Channel(configuration.get(), channel, std::move(pass_through_), + std::move(acq_), + std::move(trk_), + std::move(tlm_), + "Channel", "L5", queue)); + + return channel_; +} + + std::unique_ptr>> GNSSBlockFactory::GetChannels( std::shared_ptr configuration, boost::shared_ptr queue) @@ -538,11 +606,13 @@ std::unique_ptr>> GNSSBlockFacto unsigned int Channels_2S_count = configuration->property("Channels_2S.count", 0); unsigned int Channels_1B_count = configuration->property("Channels_1B.count", 0); unsigned int Channels_5X_count = configuration->property("Channels_5X.count", 0); + unsigned int Channels_L5_count = configuration->property("Channels_L5.count", 0); unsigned int total_channels = Channels_1C_count + Channels_2S_count + Channels_1B_count + - Channels_5X_count; + Channels_5X_count + + Channels_L5_count; std::unique_ptr>> channels(new std::vector>(total_channels)); //**************** GPS L1 C/A CHANNELS ********************** @@ -605,7 +675,34 @@ std::unique_ptr>> GNSSBlockFacto queue)); channel_absolute_id++; } + //**************** GPS L5 CHANNELS ********************** + LOG(INFO)<< "Getting " << Channels_L5_count << " GPS L5 channels"; + tracking_implementation = configuration->property("Tracking_L5.implementation", default_implementation); + telemetry_decoder_implementation = configuration->property("TelemetryDecoder_L5.implementation", default_implementation); + acquisition_implementation = configuration->property("Acquisition_L5.implementation", default_implementation); + for (unsigned int i = 0; i < Channels_L5_count; i++) + { + //(i.e. Acquisition_1C0.implementation=xxxx) + std::string acquisition_implementation_specific = configuration->property( + "Acquisition_L5" + boost::lexical_cast(channel_absolute_id) + ".implementation", + acquisition_implementation); + //(i.e. Tracking_1C0.implementation=xxxx) + std::string tracking_implementation_specific = configuration->property( + "Tracking_L5" + boost::lexical_cast(channel_absolute_id) + ".implementation", + tracking_implementation); + std::string telemetry_decoder_implementation_specific = configuration->property( + "TelemetryDecoder_L5" + boost::lexical_cast(channel_absolute_id) + ".implementation", + telemetry_decoder_implementation); + // Push back the channel to the vector of channels + channels->at(channel_absolute_id) = std::move(GetChannel_L5(configuration, + acquisition_implementation_specific, + tracking_implementation_specific, + telemetry_decoder_implementation_specific, + channel_absolute_id, + queue)); + channel_absolute_id++; + } //**************** GALILEO E1 B (I/NAV OS) CHANNELS ********************** LOG(INFO) << "Getting " << Channels_1B_count << " GALILEO E1 B (I/NAV OS) channels"; diff --git a/src/core/receiver/gnss_block_factory.h b/src/core/receiver/gnss_block_factory.h index 13c614ee8..516b9e8e9 100644 --- a/src/core/receiver/gnss_block_factory.h +++ b/src/core/receiver/gnss_block_factory.h @@ -94,6 +94,10 @@ private: std::string acq, std::string trk, std::string tlm, int channel, boost::shared_ptr queue); + std::unique_ptr GetChannel_L5(std::shared_ptr configuration, + std::string acq, std::string trk, std::string tlm, int channel, + boost::shared_ptr queue); + std::unique_ptr GetAcqBlock( std::shared_ptr configuration, std::string role, diff --git a/src/core/receiver/gnss_flowgraph.cc b/src/core/receiver/gnss_flowgraph.cc index cf1788cc0..ed505b5f9 100644 --- a/src/core/receiver/gnss_flowgraph.cc +++ b/src/core/receiver/gnss_flowgraph.cc @@ -579,7 +579,8 @@ void GNSSFlowgraph::set_signals_list() unsigned int total_channels = configuration_->property("Channels_1C.count", 0) + configuration_->property("Channels_2S.count", 0) + configuration_->property("Channels_1B.count", 0) + - configuration_->property("Channels_5X.count", 0); + configuration_->property("Channels_5X.count", 0) + + configuration_->property("Channels_L5.count", 0); /* * Loop to create the list of GNSS Signals @@ -672,6 +673,19 @@ void GNSSFlowgraph::set_signals_list() } } + if (configuration_->property("Channels_L5.count", 0) > 0) + { + /* + * Loop to create GPS L5 signals + */ + for (available_gnss_prn_iter = available_gps_prn.cbegin(); + available_gnss_prn_iter != available_gps_prn.cend(); + available_gnss_prn_iter++) + { + available_GNSS_signals_.push_back(Gnss_Signal(Gnss_Satellite(std::string("GPS"), + *available_gnss_prn_iter), std::string("L5"))); + } + } if (configuration_->property("Channels_SBAS.count", 0) > 0) { /* @@ -725,7 +739,7 @@ void GNSSFlowgraph::set_signals_list() { std::string gnss_signal = (configuration_->property("Channel" + boost::lexical_cast(i) + ".signal", std::string("1C"))); std::string gnss_system; - if((gnss_signal.compare("1C") == 0) or (gnss_signal.compare("2S") == 0) ) gnss_system = "GPS"; + if((gnss_signal.compare("1C") == 0) or (gnss_signal.compare("2S") == 0) or (gnss_signal.compare("L5") == 0)) gnss_system = "GPS"; if((gnss_signal.compare("1B") == 0) or (gnss_signal.compare("5X") == 0) ) gnss_system = "Galileo"; unsigned int sat = configuration_->property("Channel" + boost::lexical_cast(i) + ".satellite", 0); LOG(INFO) << "Channel " << i << " system " << gnss_system << ", signal " << gnss_signal <<", sat "<