World.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 #include <mrpt/core/lock_helper.h>
10 #include <mrpt/math/TTwist2D.h>
11 #include <mrpt/obs/CObservationOdometry.h>
12 #include <mrpt/poses/CPose3DQuat.h>
13 #include <mrpt/serialization/CArchive.h>
14 #include <mrpt/system/filesystem.h> // filePathSeparatorsToNative()
15 #include <mrpt/version.h>
16 #include <mvsim/World.h>
17 
18 #include <map>
19 
20 using namespace mvsim;
21 using namespace std;
22 
23 // Default ctor: inits empty world.
24 World::World() : mrpt::system::COutputLogger("mvsim::World") { this->clear_all(); }
25 
26 // Dtor.
28 {
29  if (gui_thread_.joinable())
30  {
31  MRPT_LOG_DEBUG("Dtor: Waiting for GUI thread to quit...");
33  gui_thread_.join();
34  MRPT_LOG_DEBUG("Dtor: GUI thread shut down successful.");
35  }
36  else
37  {
38  MRPT_LOG_DEBUG("Dtor: GUI thread already shut down.");
39  }
40 
41  this->clear_all();
42  box2d_world_.reset();
43 }
44 
45 // Resets the entire simulation environment to an empty world.
47 {
48  auto lck = mrpt::lockHelper(world_cs_);
49 
50  // Reset params:
52 
53  // (B2D) World contents:
54  // ---------------------------------------------
55  box2d_world_ = std::make_unique<b2World>(b2Vec2_zero);
56 
57  // Define the ground body.
58  b2BodyDef groundBodyDef;
59  b2_ground_body_ = box2d_world_->CreateBody(&groundBodyDef);
60 
61  // Clear lists of objs:
62  // ---------------------------------------------
63  vehicles_.clear();
64  worldElements_.clear();
65  blocks_.clear();
66 }
67 
69 {
70  ASSERT_(!initialized_);
71  ASSERT_(worldVisual_);
72 
73 #if MRPT_VERSION >= 0x270
74  worldVisual_->getViewport()->lightParameters().ambient = lightOptions_.light_ambient;
75 #else
76  worldVisual_->getViewport()->lightParameters().ambient = {
78  1.0f};
79 #endif
80  // Physical world light = visual world lights:
81  worldPhysical_.getViewport()->lightParameters() =
82  worldVisual_->getViewport()->lightParameters();
83 
84  // Create group for sensor viz:
85  {
86  auto glVizSensors = mrpt::opengl::CSetOfObjects::Create();
87  glVizSensors->setName("group_sensors_viz");
88  glVizSensors->setVisibility(guiOptions_.show_sensor_points);
89  worldVisual_->insert(glVizSensors);
90  }
91 
92  getTimeLogger().setMinLoggingLevel(this->getMinLoggingLevel());
93  remoteResources_.setMinLoggingLevel(this->getMinLoggingLevel());
94 
95  initialized_ = true;
96 }
97 
98 std::string World::xmlPathToActualPath(const std::string& modelURI) const
99 {
100  std::string actualFileName = remoteResources_.resolve_path(modelURI);
101  return local_to_abs_path(actualFileName);
102 }
103 
106 std::string World::local_to_abs_path(const std::string& s_in) const
107 {
108  std::string ret;
109  const std::string s = mrpt::system::trim(s_in);
110 
111  // Relative path? It's not if:
112  // "X:\*", "/*"
113  // -------------------
114  bool is_relative = true;
115  if (s.size() > 2 && s[1] == ':' && (s[2] == '/' || s[2] == '\\')) is_relative = false;
116  if (s.size() > 0 && (s[0] == '/' || s[0] == '\\')) is_relative = false;
117  if (is_relative)
118  ret = mrpt::system::pathJoin({basePath_, s});
119  else
120  ret = s;
121 
122  return mrpt::system::toAbsolutePath(ret);
123 }
124 
126 {
127  for (auto& veh : vehicles_)
128  if (veh.second) v(*veh.second);
129 }
130 
132 {
133  for (auto& we : worldElements_)
134  if (we) v(*we);
135 }
136 
138 {
139  for (auto& b : blocks_)
140  if (b.second) v(*b.second);
141 }
142 
144 {
145 #if defined(MVSIM_HAS_ZMQ) && defined(MVSIM_HAS_PROTOBUF)
146  //
147  client_.setVerbosityLevel(this->getMinLoggingLevel());
148  client_.serverHostAddress(serverAddress_);
149  client_.connect();
150 
151  // Let objects register topics / services:
152  auto lckListObjs = mrpt::lockHelper(simulableObjectsMtx_);
153 
154  for (auto& o : simulableObjects_)
155  {
156  ASSERT_(o.second);
157  o.second->registerOnServer(client_);
158  }
159  lckListObjs.unlock();
160 
161  // global services:
163 #endif
164 }
165 
166 void World::insertBlock(const Block::Ptr& block)
167 {
168  // Assign each block an "index" number
169  block->setBlockIndex(blocks_.size());
170 
171  // make sure the name is not duplicated:
172  blocks_.insert(BlockList::value_type(block->getName(), block));
173 
174  auto lckListObjs = mrpt::lockHelper(simulableObjectsMtx_);
175 
176  simulableObjects_.insert(
177  simulableObjects_.end(),
178  std::make_pair(block->getName(), std::dynamic_pointer_cast<Simulable>(block)));
179 }
180 
182 {
183  auto lck = mrpt::lockHelper(worldPhysicalMtx_);
184 
185  worldPhysical_.clear();
186  worldVisual_->clear();
187 
189 }
190 
192 {
193  // If we have a GUI, reuse that context:
194  if (!headless()) return false;
195 
196  // otherwise, just the first time:
197  static bool first = true;
198  bool ret = first;
199  first = false;
200  return ret;
201 }
202 
203 std::optional<mvsim::TJoyStickEvent> World::getJoystickState() const
204 {
205  if (!joystickEnabled_) return {};
206 
207  if (!joystick_)
208  {
209  joystick_.emplace();
210  const auto nJoy = joystick_->getJoysticksCount();
211  if (!nJoy)
212  {
213  MRPT_LOG_WARN(
214  "[World::getJoystickState()] No Joystick found, disabling "
215  "joystick-based controllers.");
216  joystickEnabled_ = false;
217  joystick_.reset();
218  return {};
219  }
220  }
221 
222  const int nJoy = 0; // TODO: Expose param for multiple joysticks?
223  mvsim::Joystick::State joyState;
224 
225  joystick_->getJoystickPosition(nJoy, joyState);
226 
228  js.axes = joyState.axes;
229  js.buttons = joyState.buttons;
230 
231  const size_t JOY_AXIS_AZIMUTH = 3;
232 
233  if (js.axes.size() > JOY_AXIS_AZIMUTH && gui_.gui_win)
234  {
235  auto lck = mrpt::lockHelper(gui_.gui_win->background_scene_mtx);
236  auto& cam = gui_.gui_win->camera();
237  cam.setAzimuthDegrees(cam.getAzimuthDegrees() - js.axes[JOY_AXIS_AZIMUTH]);
238  }
239 
240  return js;
241 }
242 
243 void World::dispatchOnObservation(const Simulable& veh, const mrpt::obs::CObservation::Ptr& obs)
244 {
245  internalOnObservation(veh, obs);
246  for (const auto& cb : callbacksOnObservation_) cb(veh, obs);
247 }
248 
249 void World::internalOnObservation(const Simulable& veh, const mrpt::obs::CObservation::Ptr& obs)
250 {
251  using namespace std::string_literals;
252 
253  // Save to .rawlog, if enabled:
254  if (save_to_rawlog_.empty() || vehicles_.empty()) return;
255 
256  auto lck = mrpt::lockHelper(rawlog_io_mtx_);
257  if (rawlog_io_per_veh_.empty())
258  {
259  for (const auto& v : vehicles_)
260  {
261  const std::string fileName =
262  mrpt::system::fileNameChangeExtension(save_to_rawlog_, v.first + ".rawlog"s);
263 
264  MRPT_LOG_INFO_STREAM("Creating dataset file: " << fileName);
265 
266  rawlog_io_per_veh_[v.first] = std::make_shared<mrpt::io::CFileGZOutputStream>(fileName);
267  }
268  }
269 
270  // Store:
271  auto arch = mrpt::serialization::archiveFrom(*rawlog_io_per_veh_.at(veh.getName()));
272  arch << *obs;
273 }
274 
275 std::set<float> World::getElevationsAt(const mrpt::math::TPoint2D& worldXY) const
276 {
277  // Assumption: getListOfSimulableObjectsMtx() is already adquired by all possible call paths?
278  std::set<float> ret;
279 
280  // Optimized search for potential objects that influence this query:
281  // 1) world elements: assuming they are few, visit them all.
282  for (const auto& obj : worldElements_)
283  {
284  const auto optZ = obj->getElevationAt(worldXY);
285  if (optZ) ret.insert(*optZ);
286  }
287 
288  // 2) blocks: by hashed 2D LUT.
289  const World::LUTCache& lut = getLUTCacheOfObjects();
290  const auto lutCoord = xy_to_lut_coords(worldXY);
291  if (auto it = lut.find(lutCoord); it != lut.end())
292  {
293  for (const auto& obj : it->second)
294  {
295  if (!obj) continue;
296  const auto optZ = obj->getElevationAt(worldXY);
297  if (optZ) ret.insert(*optZ);
298  }
299  }
300 
301  // if none:
302  if (ret.empty()) ret.insert(.0f);
303 
304  return ret;
305 }
306 
307 float World::getHighestElevationUnder(const mrpt::math::TPoint3Df& pt) const
308 {
309  const auto zs = getElevationsAt({pt.x, pt.y});
310 
311  float prevZ = .0f;
312  for (float z : zs)
313  {
314  if (z > pt.z) break;
315  prevZ = z;
316  }
317  return prevZ;
318 }
mvsim
Definition: Client.h:21
mvsim::World::worldVisual_
mrpt::opengl::COpenGLScene::Ptr worldVisual_
Definition: World.h:767
fileName
static const char * fileName
Definition: settings.cpp:28
mvsim::World::simulableObjectsMtx_
std::mutex simulableObjectsMtx_
Definition: World.h:677
mvsim::World::getLUTCacheOfObjects
const LUTCache & getLUTCacheOfObjects() const
Ensure the cache is built and up-to-date, then return it:
Definition: World_simul.cpp:582
mvsim::Simulable::getName
const std::string & getName() const
Definition: Simulable.h:107
mvsim::World::connectToServer
void connectToServer()
Definition: World.cpp:143
b2Vec2_zero
const B2_API b2Vec2 b2Vec2_zero
Useful constant.
mvsim::World::joystickEnabled_
bool joystickEnabled_
Definition: World.h:439
mvsim::World::dispatchOnObservation
void dispatchOnObservation(const Simulable &veh, const mrpt::obs::CObservation::Ptr &obs)
Definition: World.cpp:243
s
XmlRpcServer s
mvsim::World::xy_to_lut_coords
static lut_2d_coordinates_t xy_to_lut_coords(const mrpt::math::TPoint2Df &p)
Definition: World_simul.cpp:589
mvsim::VisualObject::FreeOpenGLResources
static void FreeOpenGLResources()
Definition: VisualObject.cpp:153
mvsim::World::guiOptions_
TGUI_Options guiOptions_
Definition: World.h:544
mvsim::World::~World
~World()
Dtor.
Definition: World.cpp:27
World.h
mvsim::Joystick::State::buttons
std::vector< bool > buttons
Definition: Joystick.h:73
mvsim::World::getHighestElevationUnder
float getHighestElevationUnder(const mrpt::math::TPoint3Df &queryPt) const
Definition: World.cpp:307
mvsim::World::clear_all
void clear_all()
Definition: World.cpp:46
mvsim::World::initialized_
bool initialized_
Definition: World.h:671
mvsim::World::internalOnObservation
void internalOnObservation(const Simulable &veh, const mrpt::obs::CObservation::Ptr &obs)
Definition: World.cpp:249
mrpt
Definition: basic_types.h:36
mvsim::World::save_to_rawlog_
std::string save_to_rawlog_
Definition: World.h:451
mvsim::World::sensor_has_to_create_egl_context
bool sensor_has_to_create_egl_context()
Definition: World.cpp:191
f
f
mvsim::World::world_element_visitor_t
std::function< void(WorldElementBase &)> world_element_visitor_t
Definition: World.h:342
mvsim::World::force_set_simul_time
void force_set_simul_time(double newSimulatedTime)
Normally should not be called by users, for internal use only.
Definition: World.h:126
mvsim::World::block_visitor_t
std::function< void(Block &)> block_visitor_t
Definition: World.h:343
mvsim::Joystick::State
Definition: Joystick.h:71
mvsim::Joystick::State::axes
std::vector< float > axes
Definition: Joystick.h:74
mvsim::World::simulableObjects_
SimulableList simulableObjects_
Definition: World.h:676
mvsim::World::TGUI_Options::show_sensor_points
bool show_sensor_points
Definition: World.h:506
mvsim::World::GUI::gui_win
mrpt::gui::CDisplayWindowGUI::Ptr gui_win
Definition: World.h:734
mvsim::World::gui_thread_
std::thread gui_thread_
Definition: World.h:246
mvsim::World::worldPhysicalMtx_
std::recursive_mutex worldPhysicalMtx_
Definition: World.h:775
mvsim::World::local_to_abs_path
std::string local_to_abs_path(const std::string &in_path) const
Definition: World.cpp:106
mvsim::World::serverAddress_
std::string serverAddress_
Definition: World.h:448
mvsim::World::xmlPathToActualPath
std::string xmlPathToActualPath(const std::string &modelURI) const
Definition: World.cpp:98
mvsim::TJoyStickEvent::buttons
std::vector< bool > buttons
Definition: basic_types.h:73
mvsim::World::World
World()
Default ctor: inits an empty world.
Definition: World.cpp:24
mvsim::TJoyStickEvent
Definition: basic_types.h:70
mvsim::RemoteResourcesManager::resolve_path
std::string resolve_path(const std::string &uri)
Definition: RemoteResourcesManager.cpp:29
mvsim::World::callbacksOnObservation_
std::vector< on_observation_callback_t > callbacksOnObservation_
Definition: World.h:426
mvsim::World::b2_ground_body_
b2Body * b2_ground_body_
Definition: World.h:665
mvsim::World::runVisitorOnVehicles
void runVisitorOnVehicles(const vehicle_visitor_t &v)
Definition: World.cpp:125
mvsim::trim
std::string trim(const std::string &s)
Definition: parse_utils.cpp:251
mvsim::World::rawlog_io_per_veh_
std::map< std::string, std::shared_ptr< mrpt::io::CFileGZOutputStream > > rawlog_io_per_veh_
Definition: World.h:875
mvsim::World::lightOptions_
LightOptions lightOptions_
Definition: World.h:589
mvsim::World::blocks_
BlockList blocks_
Definition: World.h:669
b2BodyDef
Definition: b2_body.h:52
mvsim::World::vehicles_
VehicleList vehicles_
Definition: World.h:667
mvsim::World::runVisitorOnBlocks
void runVisitorOnBlocks(const block_visitor_t &v)
Definition: World.cpp:137
mvsim::World::insertBlock
void insertBlock(const Block::Ptr &block)
Definition: World.cpp:166
mvsim::World::internal_advertiseServices
void internal_advertiseServices()
Definition: World_services.cpp:182
mvsim::World::LUTCache
std::unordered_map< lut_2d_coordinates_t, std::vector< Simulable::Ptr >, LutIndexHash > LUTCache
Definition: World.h:719
mvsim::TJoyStickEvent::axes
std::vector< float > axes
Definition: basic_types.h:72
mvsim::World::free_opengl_resources
void free_opengl_resources()
Definition: World.cpp:181
mvsim::World::worldPhysical_
mrpt::opengl::COpenGLScene worldPhysical_
Definition: World.h:774
mvsim::World::worldElements_
WorldElementList worldElements_
Definition: World.h:668
mvsim::World::remoteResources_
RemoteResourcesManager remoteResources_
Definition: World.h:867
mvsim::World::rawlog_io_mtx_
std::mutex rawlog_io_mtx_
Definition: World.h:874
mvsim::World::headless
bool headless() const
Definition: World.h:385
mvsim::World::vehicle_visitor_t
std::function< void(VehicleBase &)> vehicle_visitor_t
Definition: World.h:341
mvsim::Simulable
Definition: Simulable.h:39
mvsim::World::getJoystickState
std::optional< mvsim::TJoyStickEvent > getJoystickState() const
Definition: World.cpp:203
std
mvsim::World::internal_initialize
void internal_initialize()
Definition: World.cpp:68
mvsim::Block::Ptr
std::shared_ptr< Block > Ptr
Definition: Block.h:53
mvsim::World::getElevationsAt
std::set< float > getElevationsAt(const mrpt::math::TPoint2D &worldXY) const
Definition: World.cpp:275
mvsim::World::LightOptions::light_ambient
float light_ambient
Definition: World.h:566
mvsim::World::basePath_
std::string basePath_
Definition: World.h:491
mvsim::World::getTimeLogger
mrpt::system::CTimeLogger & getTimeLogger()
Definition: World.h:321
mvsim::World::box2d_world_
std::unique_ptr< b2World > box2d_world_
Definition: World.h:662
mvsim::World::simulator_must_close
bool simulator_must_close() const
Definition: World.h:252
mvsim::World::runVisitorOnWorldElements
void runVisitorOnWorldElements(const world_element_visitor_t &v)
Definition: World.cpp:131
mvsim::World::gui_
GUI gui_
gui state
Definition: World.h:762
mvsim::World::world_cs_
std::recursive_mutex world_cs_
Definition: World.h:659
mvsim::World::joystick_
std::optional< Joystick > joystick_
Definition: World.h:440


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