nav_library_orbital_data_provider.cpp
Go to the documentation of this file.
1 // SPDX-License-Identifier: BSD-3-Clause
2 // SPDX-FileCopyrightText: Czech Technical University in Prague
3 
4 #include <algorithm>
5 #include <ctime>
6 #include <list>
7 #include <memory>
8 #include <string>
9 #include <unordered_map>
10 #include <unordered_set>
11 #include <utility>
12 
13 #include <gnsstk/MultiFormatNavDataFactory.hpp>
14 #include <gnsstk/NavLibrary.hpp>
15 #include <gnsstk/Position.hpp>
16 
19 #include <gnsstk/OrbitData.hpp>
20 #include <gnss_info/cache.h>
21 #include <gnss_info/cache_index.h>
24 #include <gnsstk_ros/position.h>
25 #include <gnsstk_ros/time.h>
26 #include <ros/ros.h>
27 
28 
29 namespace gnss_info
30 {
31 
33 {
34  std::list<std::shared_ptr<NavLibraryDataSource>> sources;
35  std::pair<ros::Time, ros::Time> timeRange;
36  std::unordered_set<std::string> constellations;
39 
40  // Error of almanac positions is in the order of a few kilometers.
41  std::unordered_map<gnsstk::NavMessageType, double> posCov = {
42  {gnsstk::NavMessageType::Almanac, std::pow(2000.0, 2)},
43  {gnsstk::NavMessageType::Ephemeris, std::pow(2.0, 2)},
44  };
45  std::unordered_map<gnsstk::NavMessageType, double> velCov = {
46  {gnsstk::NavMessageType::Almanac, std::pow(1.0, 2)},
47  {gnsstk::NavMessageType::Ephemeris, std::pow(0.1, 2)},
48  };
49 };
50 
52 {
53  this->data->factory = std::make_shared<gnsstk::MultiFormatNavDataFactory>();
54  this->data->navLibrary.addFactory(this->data->factory);
55 }
56 
58 
59 void NavLibraryOrbitalDataProvider::addDataSource(const std::shared_ptr<NavLibraryDataSource>& source)
60 {
61  this->data->sources.push_back(source);
62 
63  for (const auto& s : this->data->sources)
64  {
65  const auto& range = s->getTimeRange();
66 
67  if (this->data->timeRange.first == ros::Time::ZERO)
68  this->data->timeRange.first = range.first;
69  else
70  this->data->timeRange.first = std::min(this->data->timeRange.first, range.first);
71 
72  if (this->data->timeRange.second == ros::Time::ZERO)
73  this->data->timeRange.second = range.second;
74  else
75  this->data->timeRange.second = std::max(this->data->timeRange.second, range.second);
76 
77  this->data->constellations.insert(s->getConstellations().begin(), s->getConstellations().end());
78  }
79 }
80 
81 std::pair<ros::Time, ros::Time> NavLibraryOrbitalDataProvider::getTimeRange() const
82 {
83  return this->data->timeRange;
84 }
85 
86 std::unordered_set<std::string> NavLibraryOrbitalDataProvider::getConstellations() const
87 {
88  return this->data->constellations;
89 }
90 
91 bool NavLibraryOrbitalDataProvider::load(const ros::Time& time, const cras::optional<bool>& precise)
92 {
93  bool success {false};
94  for (const auto& source : this->data->sources)
95  {
96  if (precise.has_value() && *precise && !source->isPrecise())
97  continue;
98  if (precise.has_value() && !*precise && !source->isApproximate())
99  continue;
100  success |= source->load(
101  time, [this](const std::string& file) {return this->data->factory->addDataSource(file);});
102  }
103  return success;
104 }
105 
106 bool NavLibraryOrbitalDataProvider::load(const ros::Time& startTime, const ros::Time& endTime,
107  const cras::optional<bool>& precise)
108 {
109  bool success {false};
110  for (const auto& source : this->data->sources)
111  {
112  if (precise.has_value() && *precise && !source->isPrecise())
113  continue;
114  if (precise.has_value() && !*precise && !source->isApproximate())
115  continue;
116  success |= source->load(startTime, endTime,
117  [this](const std::string& file) {return this->data->factory->addDataSource(file);});
118  }
119  return success;
120 }
121 
122 cras::expected<std::unordered_map<uint32_t, gnss_info_msgs::SatellitePosition>, std::string>
124  const ros::Time& time, const std::unordered_map<uint32_t, gnss_info_msgs::SatelliteInfo>& satellites)
125 {
126  const auto when = gnsstk_ros::convert(time);
127 
128  auto when1 = when, when2 = when;
129  when1.addSeconds(-ros::Duration::DAY.sec * 3.0);
130  when2.addSeconds(ros::Duration::DAY.sec * 3.0);
131  const auto availableSats = this->data->navLibrary.getAvailableSats(when1, when2);
132  if (availableSats.empty())
133  return cras::make_unexpected("No matching satellite data found.");
134 
135  std::unordered_map<uint32_t, gnss_info_msgs::SatellitePosition> positions;
136  if (satellites.empty())
137  return positions;
138 
139  std::list<std::string> errors;
140  for (const auto& [satcatID, info] : satellites)
141  {
142  const auto maybeSatID = gnsstk_ros::satelliteInfoToSatID(info);
143  if (!maybeSatID.has_value())
144  {
145  errors.push_back(cras::format("Failed to determine PRN of satellite %u (%s) at time %s.",
146  satcatID, info.name.c_str(), cras::to_string(time).c_str()));
147  continue;
148  }
149 
150  const gnsstk::NavSatelliteID navId{*maybeSatID};
151  if (availableSats.find(navId) == availableSats.cend())
152  continue;
153 
154  std::array<gnsstk::NavMessageID, 2> searchTerms {{
157  }};
159  gnsstk::NavMessageType foundMessageType;
160  bool success {false};
161  for (const auto& searchTerm : searchTerms)
162  {
163  if (this->data->navLibrary.find(searchTerm, when, navData,
165  {
166  success = true;
167  foundMessageType = searchTerm.messageType;
168  break;
169  }
170  }
171 
172  if (!success || navData == nullptr)
173  {
174  errors.push_back(cras::format("No position data for satellite %u (%s) at time %s.",
175  satcatID, info.name.c_str(), cras::to_string(time).c_str()));
176  continue;
177  }
178 
179  const auto orbitData = dynamic_cast<gnsstk::OrbitData*>(navData.get());
180  gnsstk::Xvt xvt;
181  success = orbitData->getXvt(when, xvt);
182 
183  if (!success)
184  {
185  errors.push_back(cras::format("Failed to compute ECEF position of satellite %u (%s) at time %s.",
186  satcatID, info.name.c_str(), cras::to_string(time).c_str()));
187  continue;
188  }
189  positions[satcatID] = gnsstk_ros::convert(
190  xvt, satcatID, this->data->posCov[foundMessageType], this->data->velCov[foundMessageType]);
191  }
192 
193  if (!errors.empty() && positions.empty())
194  return cras::make_unexpected(cras::join(errors, " "));
195  if (positions.empty())
196  return cras::make_unexpected("No matching satellite data found.");
197  if (!errors.empty())
198  ROS_WARN("%s", cras::join(errors, " ").c_str());
199 
200  return positions;
201 }
202 
203 cras::expected<std::unordered_map<uint32_t, gnss_info_msgs::SatelliteSkyPosition>, std::string>
205 const geographic_msgs::GeoPoint& position,
206  const std::unordered_map<uint32_t, gnss_info_msgs::SatellitePosition>& positions,
207  const double elevationMaskDeg)
208 {
209  gnsstk::Position recPos = gnsstk_ros::convert(position);
210  // all following computations use Cartesian internally
211  recPos.transformTo(gnsstk::Position::CoordinateSystem::Cartesian);
212 
213  std::unordered_map<uint32_t, gnss_info_msgs::SatelliteSkyPosition> skyView;
214  for (const auto& [satcatID, ecefPose] : positions)
215  {
216  const gnsstk::Position satPos = gnsstk_ros::convert(ecefPose.position);
217  const auto elDeg = recPos.elevation(satPos);
218  if (elDeg < elevationMaskDeg)
219  continue;
220  const auto azDeg = recPos.azimuth(satPos);
221  const auto distance = gnsstk::range(recPos, satPos);
222  auto& skyPosition = skyView[satcatID];
223  skyPosition.satcat_id = satcatID;
224  skyPosition.azimuth_deg = azDeg;
225  skyPosition.elevation_deg = elDeg;
226  skyPosition.distance = distance;
227  }
228 
229  return skyView;
230 }
231 
233 {
234  return std::any_of(this->data->sources.cbegin(), this->data->sources.cend(),
235  [](const std::shared_ptr<NavLibraryDataSource>& s) {return s->isPrecise();});
236 }
237 
239 {
240  return std::any_of(this->data->sources.cbegin(), this->data->sources.cend(),
241  [](const std::shared_ptr<NavLibraryDataSource>& s) {return s->isApproximate();});
242 }
243 
245 {
246  std::list<std::string> names;
247  std::transform(this->data->sources.cbegin(), this->data->sources.cend(),
248  std::back_inserter(names), [](auto s) {return s->getName();});
249  return "GNSSTk NavLibrary (" + cras::join(names, ", ") + ")";
250 }
251 
252 }
gnss_info::NavLibraryOrbitalDataProvider::getName
std::string getName() const override
Get human-readable name of the provider.
Definition: nav_library_orbital_data_provider.cpp:244
gnsstk::NavDataPtr
std::shared_ptr< NavData > NavDataPtr
gnss_info::NavLibraryOrbitalDataProvider::getECEFPositions
cras::expected< std::unordered_map< uint32_t, gnss_info_msgs::SatellitePosition >, std::string > getECEFPositions(const ros::Time &time, const std::unordered_map< uint32_t, gnss_info_msgs::SatelliteInfo > &satellites) override
Compute ECEF positions of the satellites at the given time.
Definition: nav_library_orbital_data_provider.cpp:123
gnss_info::NavLibraryOrbitalDataProviderPrivate::velCov
std::unordered_map< gnsstk::NavMessageType, double > velCov
Definition: nav_library_orbital_data_provider.cpp:45
file
page HOWTO subpage DoxygenGuide Documenting Your Code page DoxygenGuide Documenting Your Code todo Flesh out this document section doctips Tips for Documenting When defining make sure that the prototype is identical between the cpp and hpp file
gnsstk::Position::transformTo
Position & transformTo(CoordinateSystem sys) noexcept
gnss_info::NavLibraryOrbitalDataProviderPrivate::navLibrary
gnsstk::NavLibrary navLibrary
Definition: nav_library_orbital_data_provider.cpp:38
s
XmlRpcServer s
gnss_info::NavLibraryOrbitalDataProviderPrivate
Definition: nav_library_orbital_data_provider.cpp:32
ros.h
time.h
gnsstk::NavSatelliteID
cras::join
::std::string join(const T &strings, const ::std::string &delimiter)
DurationBase< Duration >::DAY
static const Duration DAY
gnsstk_ros::satelliteInfoToSatID
cras::optional< gnsstk::SatID > satelliteInfoToSatID(const gnss_info_msgs::SatelliteInfo &info)
gnss_info::NavLibraryOrbitalDataProviderPrivate::factory
gnsstk::NavDataFactoryPtr factory
Definition: nav_library_orbital_data_provider.cpp:37
gnsstk_ros::convert
gnsstk::Position convert(const geographic_msgs::GeoPoint &position)
gnss_info::NavLibraryOrbitalDataProvider::load
bool load(const ros::Time &time, const cras::optional< bool > &precise) override
Load data for the given time instant.
Definition: nav_library_orbital_data_provider.cpp:91
nav_library_orbital_data_provider.h
gnsstk::NavMessageType::Almanac
@ Almanac
constellations.h
gnss_info::NavLibraryOrbitalDataProviderPrivate::sources
std::list< std::shared_ptr< NavLibraryDataSource > > sources
Definition: nav_library_orbital_data_provider.cpp:34
gnsstk::NavSearchOrder::Nearest
@ Nearest
gnsstk::NavMessageType::Ephemeris
@ Ephemeris
data
data
gnsstk::Position::azimuth
double azimuth(const Position &Target) const
gnss_info::NavLibraryOrbitalDataProviderPrivate::constellations
std::unordered_set< std::string > constellations
Definition: nav_library_orbital_data_provider.cpp:36
gnsstk::NavDataFactoryPtr
std::shared_ptr< NavDataFactory > NavDataFactoryPtr
gnss_info::NavLibraryOrbitalDataProvider::~NavLibraryOrbitalDataProvider
~NavLibraryOrbitalDataProvider() override
gnss_info::NavLibraryOrbitalDataProvider::addDataSource
virtual void addDataSource(const std::shared_ptr< NavLibraryDataSource > &source)
Add data source.
Definition: nav_library_orbital_data_provider.cpp:59
string_utils.hpp
gnss_info::NavLibraryOrbitalDataProvider::getSkyView
cras::expected< std::unordered_map< uint32_t, gnss_info_msgs::SatelliteSkyPosition >, std::string > getSkyView(const geographic_msgs::GeoPoint &position, const std::unordered_map< uint32_t, gnss_info_msgs::SatellitePosition > &positions, double elevationMaskDeg) override
Compute sky view (azimuths, elevations and distances) of satellites from the given receiver position.
Definition: nav_library_orbital_data_provider.cpp:204
gnss_info::NavLibraryOrbitalDataProviderPrivate::posCov
std::unordered_map< gnsstk::NavMessageType, double > posCov
Definition: nav_library_orbital_data_provider.cpp:41
gnsstk::NavLibrary
time
time
TimeBase< Time, Duration >::ZERO
static const Time ZERO
gnss_info::NavLibraryOrbitalDataProviderPrivate::timeRange
std::pair< ros::Time, ros::Time > timeRange
Definition: nav_library_orbital_data_provider.cpp:35
ROS_WARN
#define ROS_WARN(...)
gnsstk::Xvt
gnss_info
Definition: cache.h:15
gnss_info::NavLibraryOrbitalDataProvider::getConstellations
std::unordered_set< std::string > getConstellations() const override
Get the constellations handled by this provider.
Definition: nav_library_orbital_data_provider.cpp:86
position.h
gnsstk::SVHealth::Any
@ Any
cache.h
gnss_info::NavLibraryOrbitalDataProvider::getTimeRange
std::pair< ros::Time, ros::Time > getTimeRange() const override
Get the time range in which this provider can provide information.
Definition: nav_library_orbital_data_provider.cpp:81
expected.hpp
gnsstk::NavValidityType::ValidOnly
@ ValidOnly
ros::Time
gnsstk::NavMessageType
NavMessageType
navData
navData
range
double range(const Position &A, const Position &B)
gnsstk::Position
gnsstk::OrbitData
gnss_info::NavLibraryOrbitalDataProvider::isApproximate
bool isApproximate() const override
Return whether this provider works with approximate orbit data.
Definition: nav_library_orbital_data_provider.cpp:238
cras::format
inline ::std::string format(::std::string format, ::va_list args)
gnss_info::NavLibraryOrbitalDataProvider::data
std::unique_ptr< NavLibraryOrbitalDataProviderPrivate > data
Private implementation data (PIMPL).
Definition: nav_library_orbital_data_provider.h:57
gnss_info::NavLibraryOrbitalDataProvider::NavLibraryOrbitalDataProvider
NavLibraryOrbitalDataProvider()
Definition: nav_library_orbital_data_provider.cpp:51
cache_index.h
gnsstk::Position::elevation
double elevation(const Position &Target) const
cras::to_string
inline ::std::string to_string(char *value)
gnss_info::NavLibraryOrbitalDataProvider::isPrecise
bool isPrecise() const override
Return whether this provider works with precise orbit data.
Definition: nav_library_orbital_data_provider.cpp:232


gnss_info
Author(s): Martin Pecka
autogenerated on Fri Nov 24 2023 03:50:35