GNSS.cpp
Go to the documentation of this file.
1 /*+-------------------------------------------------------------------------+
2  | MultiVehicle simulator (libmvsim) |
3  | |
4  | Copyright (C) 2014-2024 Jose Luis Blanco Claraco |
5  | Copyright (C) 2017 Borys Tymchenko (Odessa Polytechnic University) |
6  | Distributed under 3-clause BSD License |
7  | See COPYING |
8  +-------------------------------------------------------------------------+ */
9 
10 #include <mrpt/core/lock_helper.h>
11 #include <mrpt/opengl/stock_objects.h>
12 #include <mrpt/topography/conversions.h>
13 #include <mrpt/version.h>
14 #include <mvsim/Sensors/GNSS.h>
15 #include <mvsim/VehicleBase.h>
16 #include <mvsim/World.h>
17 
18 #include "xml_utils.h"
19 
20 #if defined(MVSIM_HAS_ZMQ) && defined(MVSIM_HAS_PROTOBUF)
21 // #include <mvsim/mvsim-msgs/ObservationXXX.pb.h>
22 #endif
23 
24 using namespace mvsim;
25 using namespace rapidxml;
26 
28 {
30 }
31 
33 
35 {
38 
39  TParameterDefinitions params;
40  params["pose"] = TParamEntry("%pose2d_ptr3d", &obs_model_.sensorPose);
41  params["pose_3d"] = TParamEntry("%pose3d", &obs_model_.sensorPose);
42  params["sensor_period"] = TParamEntry("%lf", &sensor_period_);
43  params["horizontal_std_noise"] = TParamEntry("%lf", &horizontal_std_noise_);
44  params["vertical_std_noise"] = TParamEntry("%lf", &vertical_std_noise_);
45 
46  // Parse XML params:
48 
49  // Pass params to the template obj:
50  obs_model_.sensorLabel = name_;
51 
52  // Init ENU covariance:
53  auto& C = obs_model_.covariance_enu.emplace();
54  const double var_xy = mrpt::square(horizontal_std_noise_);
55  const double var_z = mrpt::square(vertical_std_noise_);
56 
57  C.setDiagonal(std::vector<double>{var_xy, var_xy, var_z});
58 }
59 
61  const mrpt::optional_ref<mrpt::opengl::COpenGLScene>& viz,
62  [[maybe_unused]] const mrpt::optional_ref<mrpt::opengl::COpenGLScene>& physical,
63  [[maybe_unused]] bool childrenOnly)
64 {
65  // 1st time?
66  if (!gl_sensor_origin_ && viz)
67  {
68  gl_sensor_origin_ = mrpt::opengl::CSetOfObjects::Create();
69 #if MRPT_VERSION >= 0x270
70  gl_sensor_origin_->castShadows(false);
71 #endif
72  gl_sensor_origin_corner_ = mrpt::opengl::stock_objects::CornerXYZSimple(0.15f);
73 
75 
76  gl_sensor_origin_->setVisibility(false);
77  viz->get().insert(gl_sensor_origin_);
79  }
80 
81  const mrpt::poses::CPose3D p = vehicle_.getCPose3D() + obs_model_.sensorPose;
82  const auto pp = parent()->applyWorldRenderOffset(p);
83 
84  if (gl_sensor_origin_) gl_sensor_origin_->setPose(pp);
85  if (glCustomVisual_) glCustomVisual_->setPose(pp);
86 }
87 
88 void GNSS::simul_pre_timestep([[maybe_unused]] const TSimulContext& context) {}
89 
90 // Simulate sensor AFTER timestep, with the updated vehicle dynamical state:
92 {
94 
96  {
97  internal_simulate_gnss(context);
98  }
99 
100  // Keep sensor global pose up-to-date:
101  const auto& p = vehicle_.getPose();
102  const auto globalSensorPose = p + obs_model_.sensorPose.asTPose();
103  Simulable::setPose(globalSensorPose, false /*do not notify*/);
104 }
105 
107 {
108  using mrpt::obs::CObservationGPS;
109 
110  auto tle = mrpt::system::CTimeLoggerEntry(world_->getTimeLogger(), "sensor.GNSS");
111 
112  auto outObs = CObservationGPS::Create(obs_model_);
113 
114  outObs->timestamp = world_->get_simul_timestamp();
115  outObs->sensorLabel = name_;
116 
117  // noise:
118  const mrpt::math::TPoint3D noise = {
119  rng_.drawGaussian1D(0.0, horizontal_std_noise_),
120  rng_.drawGaussian1D(0.0, horizontal_std_noise_),
121  rng_.drawGaussian1D(0.0, vertical_std_noise_)};
122 
123  // Where the GPS sensor is in the world frame:
124  const auto& georef = world()->georeferenceOptions();
125 
126  const auto worldRotation =
127  mrpt::poses::CPose3D::FromYawPitchRoll(georef.world_to_enu_rotation, .0, .0);
128 
129  mrpt::poses::CPose3D vehPoseInWorld = vehicle().getCPose3D();
130 
131  if (georef.world_is_utm)
132  {
133  auto posLocal = vehPoseInWorld.translation() - georef.utmRef;
134 
135  vehPoseInWorld.x(posLocal.x);
136  vehPoseInWorld.y(posLocal.y);
137  vehPoseInWorld.z(posLocal.z);
138  }
139 
140  const mrpt::math::TPoint3D sensorPt =
141  (worldRotation + (vehPoseInWorld + outObs->sensorPose)).translation() + noise;
142 
143  // convert from ENU (world coordinates) to geodetic:
144  const thread_local auto WGS84 = mrpt::topography::TEllipsoid::Ellipsoid_WGS84();
145 
146  const mrpt::topography::TGeodeticCoords& georefCoord = georef.georefCoord;
147 
148  // Warn the user if settings not set:
149  if (georefCoord.lat.decimal_value == 0 && georefCoord.lon.decimal_value == 0)
150  {
151  thread_local bool once = false;
152  if (!once)
153  {
154  once = true;
155  world()->logStr(
156  mrpt::system::LVL_WARN,
157  "World <georeference> parameters are not set, and they are required for "
158  "properly define GNSS sensor simulation");
159  }
160  return;
161  }
162 
163  mrpt::topography::TGeocentricCoords gcPt;
164  mrpt::topography::ENUToGeocentric(sensorPt, georefCoord, gcPt, WGS84);
165 
166  mrpt::topography::TGeodeticCoords ptCoords;
167  mrpt::topography::geocentricToGeodetic(gcPt, ptCoords, WGS84);
168 
169  // Fill in observation:
170  mrpt::obs::gnss::Message_NMEA_GGA msgGGA;
171  auto& f = msgGGA.fields;
172  f.thereis_HDOP = true;
173  f.HDOP = horizontal_std_noise_ / 5.0; // approximation
174 
175  mrpt::system::TTimeParts tp;
176  mrpt::system::timestampToParts(outObs->timestamp, tp);
177  f.UTCTime.hour = tp.hour;
178  f.UTCTime.minute = tp.minute;
179  f.UTCTime.sec = tp.second;
180  f.fix_quality = 2; // DGPS fix
181 
182  f.latitude_degrees = ptCoords.lat.decimal_value;
183  f.longitude_degrees = ptCoords.lon.decimal_value;
184 
185  f.altitude_meters = ptCoords.height;
186  f.orthometric_altitude = ptCoords.height;
187  f.corrected_orthometric_altitude = ptCoords.height;
188  f.satellitesUsed = 7; // How to simulate this? :-)
189 
190  outObs->setMsg(msgGGA);
191 
192  // Save:
193  {
194  std::lock_guard<std::mutex> csl(last_obs_cs_);
195  last_obs_ = std::move(outObs);
196  }
197 
198  // publish as generic Protobuf (mrpt serialized) object:
200 }
201 
202 void GNSS::notifySimulableSetPose(const mrpt::math::TPose3D&)
203 {
204  // The editor has moved the sensor in global coordinates.
205  // Convert back to local:
206  // const auto& p = vehicle_.getPose();
207  // sensor_params_.sensorPose = mrpt::poses::CPose3D(newPose - p);
208 }
209 
211 {
212  using namespace std::string_literals;
213 
215 
216 #if defined(MVSIM_HAS_ZMQ) && defined(MVSIM_HAS_PROTOBUF)
217  // Topic:
218  if (!publishTopic_.empty())
219  {
220  // c.advertiseTopic<mvsim_msgs::ObservationIMU>(publishTopic_ +
221  // "_scan"s);
222  }
223 #endif
224 }
mvsim::VisualObject::parent
World * parent()
Definition: VisualObject.h:51
mvsim
Definition: Client.h:21
mvsim::GNSS::horizontal_std_noise_
double horizontal_std_noise_
[m]
Definition: GNSS.h:56
mvsim::VisualObject::world_
World * world_
Definition: VisualObject.h:73
mvsim::SensorBase::make_sure_we_have_a_name
void make_sure_we_have_a_name(const std::string &prefix)
Assign a sensible default name/sensor label if none is provided:
Definition: SensorBase.cpp:252
mvsim::SensorBase::varValues_
std::map< std::string, std::string > varValues_
Filled in by SensorBase::loadConfigFrom()
Definition: SensorBase.h:97
mvsim::SensorBase::reportNewObservation
void reportNewObservation(const std::shared_ptr< mrpt::obs::CObservation > &obs, const TSimulContext &context)
Definition: SensorBase.cpp:159
mvsim::GNSS::internalGuiUpdate
void internalGuiUpdate(const mrpt::optional_ref< mrpt::opengl::COpenGLScene > &viz, [[maybe_unused]] const mrpt::optional_ref< mrpt::opengl::COpenGLScene > &physical, [[maybe_unused]] bool childrenOnly) override
Definition: GNSS.cpp:60
mvsim::GNSS::loadConfigFrom
virtual void loadConfigFrom(const rapidxml::xml_node< char > *root) override
Definition: GNSS.cpp:34
mvsim::GNSS::vertical_std_noise_
double vertical_std_noise_
[m]
Definition: GNSS.h:57
mvsim::GNSS::GNSS
GNSS(Simulable &parent, const rapidxml::xml_node< char > *root)
Definition: GNSS.cpp:27
mvsim::TParamEntry
Definition: TParameterDefinitions.h:38
mvsim::parse_xmlnode_children_as_param
void parse_xmlnode_children_as_param(const rapidxml::xml_node< char > &xml_node, const TParameterDefinitions &params, const std::map< std::string, std::string > &variableNamesValues={}, const char *functionNameContext="", mrpt::system::COutputLogger *logger=nullptr)
Definition: xml_utils.cpp:215
mvsim::GNSS::obs_model_
mrpt::obs::CObservationGPS obs_model_
Definition: GNSS.h:61
mvsim::GNSS::gl_sensor_origin_
mrpt::opengl::CSetOfObjects::Ptr gl_sensor_origin_
Definition: GNSS.h:68
mvsim::World::applyWorldRenderOffset
mrpt::math::TPose3D applyWorldRenderOffset(mrpt::math::TPose3D p) const
Definition: World.h:631
World.h
mvsim::Simulable::getCPose3D
mrpt::poses::CPose3D getCPose3D() const
Alternative to getPose()
Definition: Simulable.cpp:157
mvsim::GNSS::last_obs_
mrpt::obs::CObservationGPS::Ptr last_obs_
Definition: GNSS.h:66
mvsim::Client
Definition: Client.h:48
mvsim::SensorBase::vehicle_
Simulable & vehicle_
The vehicle this sensor is attached to.
Definition: SensorBase.h:82
mvsim::SensorBase
Virtual base class for all sensors.
Definition: SensorBase.h:34
mvsim::SensorBase::registerOnServer
void registerOnServer(mvsim::Client &c) override
Definition: SensorBase.cpp:220
xml_utils.h
mvsim::GNSS::~GNSS
virtual ~GNSS()
Definition: GNSS.cpp:32
f
f
mvsim::SensorBase::should_simulate_sensor
bool should_simulate_sensor(const TSimulContext &context)
Definition: SensorBase.cpp:262
VehicleBase.h
mvsim::GNSS::last_obs_cs_
std::mutex last_obs_cs_
Definition: GNSS.h:63
mvsim::SensorBase::world
World * world()
Definition: SensorBase.h:84
mvsim::GNSS::notifySimulableSetPose
void notifySimulableSetPose(const mrpt::math::TPose3D &newPose) override
Definition: GNSS.cpp:202
rapidxml
Definition: rapidxml.hpp:57
mvsim::TSimulContext
Definition: basic_types.h:58
mvsim::GNSS::simul_post_timestep
virtual void simul_post_timestep(const TSimulContext &context) override
Definition: GNSS.cpp:91
mvsim::World::georeferenceOptions
const GeoreferenceOptions & georeferenceOptions() const
Definition: World.h:624
mvsim::World::get_simul_timestamp
mrpt::Clock::time_point get_simul_timestamp() const
Definition: World.h:137
mvsim::TParameterDefinitions
std::map< std::string, TParamEntry > TParameterDefinitions
Definition: TParameterDefinitions.h:64
mvsim::Simulable::simul_post_timestep
virtual void simul_post_timestep(const TSimulContext &context)
Definition: Simulable.cpp:64
mvsim::Simulable::name_
std::string name_
Definition: Simulable.h:145
mvsim::GNSS::registerOnServer
void registerOnServer(mvsim::Client &c) override
Definition: GNSS.cpp:210
mvsim::SensorBase::sensor_period_
double sensor_period_
Definition: SensorBase.h:88
mvsim::SensorBase::vehicle
Simulable & vehicle()
Definition: SensorBase.h:68
mvsim::GNSS::simul_pre_timestep
virtual void simul_pre_timestep(const TSimulContext &context) override
Definition: GNSS.cpp:88
mvsim::SensorBase::publishTopic_
std::string publishTopic_
Definition: SensorBase.h:94
mvsim::Simulable::setPose
void setPose(const mrpt::math::TPose3D &p, bool notifyChange=true) const
Definition: Simulable.cpp:474
rapidxml::xml_node< char >
mvsim::Simulable
Definition: Simulable.h:39
mvsim::SensorBase::loadConfigFrom
virtual void loadConfigFrom(const rapidxml::xml_node< char > *root)
Definition: SensorBase.cpp:231
mvsim::Simulable::getPose
mrpt::math::TPose3D getPose() const
Definition: Simulable.cpp:490
mvsim::GNSS::rng_
mrpt::random::CRandomGenerator rng_
Definition: GNSS.h:70
mvsim::World::getTimeLogger
mrpt::system::CTimeLogger & getTimeLogger()
Definition: World.h:321
root
root
GNSS.h
mvsim::VisualObject::glCustomVisual_
std::shared_ptr< mrpt::opengl::CSetOfObjects > glCustomVisual_
Definition: VisualObject.h:77
mvsim::GNSS::internal_simulate_gnss
void internal_simulate_gnss(const TSimulContext &context)
Definition: GNSS.cpp:106
mvsim::GNSS::gl_sensor_origin_corner_
mrpt::opengl::CSetOfObjects::Ptr gl_sensor_origin_corner_
Definition: GNSS.h:68
mvsim::SensorBase::RegisterSensorOriginViz
static void RegisterSensorOriginViz(const std::shared_ptr< mrpt::opengl::CSetOfObjects > &o)
Definition: SensorBase.cpp:78


mvsim
Author(s):
autogenerated on Wed May 28 2025 02:13:07