World.cpp
Go to the documentation of this file.
1 /*+-------------------------------------------------------------------------+
2  | MultiVehicle simulator (libmvsim) |
3  | |
4  | Copyright (C) 2014-2020 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/system/filesystem.h> // filePathSeparatorsToNative()
11 #include <mvsim/World.h>
12 
13 #include <algorithm> // count()
14 #include <map>
15 #include <stdexcept>
16 
17 #include "GenericAnswer.pb.h"
18 #include "SrvGetPose.pb.h"
19 #include "SrvGetPoseAnswer.pb.h"
20 #include "SrvSetPose.pb.h"
21 #include "SrvSetPoseAnswer.pb.h"
22 
23 using namespace mvsim;
24 using namespace std;
25 
26 // Default ctor: inits empty world.
27 World::World() : mrpt::system::COutputLogger("mvsim::World")
28 {
29  this->clear_all();
30 }
31 
32 // Dtor.
34 {
35  if (m_gui_thread.joinable())
36  {
37  MRPT_LOG_DEBUG("Waiting for GUI thread to quit...");
39  m_gui_thread.join();
40  MRPT_LOG_DEBUG("GUI thread shut down successful.");
41  }
42 
43  this->clear_all();
44  m_box2d_world.reset();
45 }
46 
47 // Resets the entire simulation environment to an empty world.
49 {
50  auto lck = mrpt::lockHelper(m_world_cs);
51 
52  // Reset params:
53  m_simul_time = 0.0;
54 
55  // (B2D) World contents:
56  // ---------------------------------------------
57  m_box2d_world = std::make_unique<b2World>(b2Vec2_zero);
58 
59  // Define the ground body.
60  b2BodyDef groundBodyDef;
61  m_b2_ground_body = m_box2d_world->CreateBody(&groundBodyDef);
62 
63  // Clear lists of objs:
64  // ---------------------------------------------
65  m_vehicles.clear();
66  m_world_elements.clear();
67  m_blocks.clear();
68 }
69 
71 void World::run_simulation(double dt)
72 {
73  const double t0 = mrpt::Clock::toDouble(mrpt::Clock::now());
74 
75  m_timlogger.registerUserMeasure("run_simulation.dt", dt);
76 
77  // sanity checks:
78  ASSERT_(dt > 0);
80 
81  // Run in time steps:
82  const double end_time = m_simul_time + dt;
83  // tolerance for rounding errors summing time steps
84  const double timetol = 1e-6;
85  while (m_simul_time < (end_time - timetol))
86  {
87  // Timestep: always "simul_step" for the sake of repeatibility
89  }
90 
91  const double t1 = mrpt::Clock::toDouble(mrpt::Clock::now());
92 
93  m_timlogger.registerUserMeasure("run_simulation.cpu_dt", t1 - t0);
94 }
95 
98 {
99  std::lock_guard<std::mutex> lck(m_simulationStepRunningMtx);
100 
101  m_timer_iteration.Tic();
102 
103  TSimulContext context;
104  context.world = this;
105  context.b2_world = m_box2d_world.get();
106  context.simul_time = m_simul_time;
107  context.dt = dt;
108 
109  // 1) Pre-step
110  {
111  mrpt::system::CTimeLoggerEntry tle(m_timlogger, "timestep.0.prestep");
112 
113  for (auto& e : m_simulableObjects)
114  if (e.second) e.second->simul_pre_timestep(context);
115  }
116 
117  // 2) Run dynamics
118  {
119  mrpt::system::CTimeLoggerEntry tle(
120  m_timlogger, "timestep.1.dynamics_integrator");
121 
123  m_simul_time += dt; // Avance time
124  }
125 
126  // 3) Save dynamical state and post-step processing:
127  {
128  mrpt::system::CTimeLoggerEntry tle(
129  m_timlogger, "timestep.3.save_dynstate");
130 
131  for (auto& e : m_simulableObjects)
132  if (e.second) e.second->simul_post_timestep(context);
133  }
134 
135  const double ts = m_timer_iteration.Tac();
136  m_timlogger.registerUserMeasure("timestep", ts);
137  if (ts > dt) m_timlogger.registerUserMeasure("timestep_too_slow_alert", ts);
138 }
139 
140 std::string World::xmlPathToActualPath(const std::string& modelURI) const
141 {
142  std::string localFileName;
143  if (modelURI.substr(0, 7) == "http://" ||
144  modelURI.substr(0, 8) == "https://")
145  {
146  MRPT_TODO("Retrieve models from online sources");
147  THROW_EXCEPTION("To do: online models");
148  // localFileName = xx;
149  }
150  else if (modelURI.substr(0, 7) == "file://")
151  {
152  localFileName = modelURI.substr(7);
153  }
154  else
155  localFileName = modelURI;
156 
157  return resolvePath(localFileName);
158 }
159 
162 std::string World::resolvePath(const std::string& s_in) const
163 {
164  std::string ret;
165  const std::string s = mrpt::system::trim(s_in);
166 
167  // Relative path? It's not if:
168  // "X:\*", "/*"
169  // -------------------
170  bool is_relative = true;
171  if (s.size() > 2 && s[1] == ':' && (s[2] == '/' || s[2] == '\\'))
172  is_relative = false;
173  if (s.size() > 0 && (s[0] == '/' || s[0] == '\\')) is_relative = false;
174  if (is_relative)
175  {
176  ret = m_base_path;
177  if (!ret.empty() && ret[ret.size() - 1] != '/' &&
178  ret[ret.size() - 1] != '\\')
179  ret += string("/");
180  ret += s;
181  }
182  else
183  ret = s;
184 
185  // Expand macros: (TODO)
186  // -------------------
187 
189 }
190 
193 {
194  for (auto& veh : m_vehicles)
195  if (veh.second) v(*veh.second);
196 }
197 
200 {
201  for (auto& we : m_world_elements)
202  if (we) v(*we);
203 }
204 
206 {
207  //
208  MRPT_TODO("Allow changing server IP from xml?");
209  m_client.setVerbosityLevel(this->getMinLoggingLevel());
210  m_client.connect();
211 
212  // Let objects register topics / services:
213  for (auto& o : m_simulableObjects)
214  {
215  ASSERT_(o.second);
216  o.second->registerOnServer(m_client);
217  }
218 
219  // global services:
220  m_client
221  .advertiseService<mvsim_msgs::SrvSetPose, mvsim_msgs::SrvSetPoseAnswer>(
222  "set_pose",
223  std::function<mvsim_msgs::SrvSetPoseAnswer(
224  const mvsim_msgs::SrvSetPose&)>(
225  [this](const mvsim_msgs::SrvSetPose& req) {
226  std::lock_guard<std::mutex> lck(m_simulationStepRunningMtx);
227 
228  mvsim_msgs::SrvSetPoseAnswer ans;
229  ans.set_objectisincollision(false);
230 
231  const auto sId = req.objectid();
232 
233  if (auto itV = m_simulableObjects.find(sId);
234  itV != m_simulableObjects.end())
235  {
236  if (req.has_relativeincrement() &&
237  req.relativeincrement())
238  {
239  auto p =
240  mrpt::poses::CPose3D(itV->second->getPose());
241  p = p + mrpt::poses::CPose3D(
242  req.pose().x(), req.pose().y(),
243  req.pose().z(), req.pose().yaw(),
244  req.pose().pitch(), req.pose().roll());
245  itV->second->setPose(p.asTPose());
246 
247  auto* absPose = ans.mutable_objectglobalpose();
248  absPose->set_x(p.x());
249  absPose->set_y(p.y());
250  absPose->set_z(p.z());
251  absPose->set_yaw(p.yaw());
252  absPose->set_pitch(p.pitch());
253  absPose->set_roll(p.roll());
254  }
255  else
256  {
257  itV->second->setPose(
258  {req.pose().x(), req.pose().y(), req.pose().z(),
259  req.pose().yaw(), req.pose().pitch(),
260  req.pose().roll()});
261  }
262  ans.set_success(true);
263  ans.set_objectisincollision(
264  itV->second->hadCollision());
265  itV->second->resetCollisionFlag();
266  }
267  else
268  {
269  ans.set_success(false);
270  }
271  return ans;
272  }));
273 
274  m_client
275  .advertiseService<mvsim_msgs::SrvGetPose, mvsim_msgs::SrvGetPoseAnswer>(
276  "get_pose",
277  std::function<mvsim_msgs::SrvGetPoseAnswer(
278  const mvsim_msgs::SrvGetPose&)>(
279  [this](const mvsim_msgs::SrvGetPose& req) {
280  std::lock_guard<std::mutex> lck(m_simulationStepRunningMtx);
281 
282  mvsim_msgs::SrvGetPoseAnswer ans;
283  const auto sId = req.objectid();
284  ans.set_objectisincollision(false);
285 
286  if (auto itV = m_simulableObjects.find(sId);
287  itV != m_simulableObjects.end())
288  {
289  ans.set_success(true);
290  const mrpt::math::TPose3D p = itV->second->getPose();
291  auto* po = ans.mutable_pose();
292  po->set_x(p.x);
293  po->set_y(p.y);
294  po->set_z(p.z);
295  po->set_yaw(p.yaw);
296  po->set_pitch(p.pitch);
297  po->set_roll(p.roll);
298 
299  ans.set_objectisincollision(
300  itV->second->hadCollision());
301  itV->second->resetCollisionFlag();
302  }
303  else
304  {
305  ans.set_success(false);
306  }
307  return ans;
308  }));
309 }
310 
311 void World::insertBlock(const Block::Ptr& block)
312 {
313  // Assign each block an "index" number
314  block->setBlockIndex(m_blocks.size());
315 
316  // make sure the name is not duplicated:
317  m_blocks.insert(BlockList::value_type(block->getName(), block));
318  m_simulableObjects.insert(
319  m_simulableObjects.end(),
320  std::make_pair(
321  block->getName(), std::dynamic_pointer_cast<Simulable>(block)));
322 }
const GLdouble * v
const b2Vec2 b2Vec2_zero(0.0f, 0.0f)
Useful constant.
mvsim::Client m_client
Definition: World.h:254
SimulableList m_simulableObjects
Definition: World.h:331
int m_b2d_pos_iters
Definition: World.h:265
std::recursive_mutex m_world_cs
first time the GUI window is created.
Definition: World.h:316
~World()
Dtor.
Definition: World.cpp:33
WorldElementList m_world_elements
Definition: World.h:325
mrpt::system::CTicTac m_timer_iteration
Definition: World.h:376
#define THROW_EXCEPTION(msg)
std::string xmlPathToActualPath(const std::string &modelURI) const
Definition: World.cpp:140
double m_simul_time
Definition: World.h:276
mrpt::system::TTimeStamp now()
double simul_time
Current time in the simulated world.
Definition: basic_types.h:60
double roll() const
mrpt::system::CTimeLogger m_timlogger
Definition: World.h:375
void runVisitorOnWorldElements(const world_element_visitor_t &v)
Definition: World.cpp:199
#define MRPT_LOG_DEBUG(_STRING)
std::shared_ptr< Block > Ptr
Definition: Block.h:36
std::function< void(VehicleBase &)> vehicle_visitor_t
Definition: World.h:222
VehicleList m_vehicles
Definition: World.h:324
void internal_one_timestep(double dt)
Definition: World.cpp:97
std::unique_ptr< b2World > m_box2d_world
Definition: World.h:319
MRPT_TODO("Modify ping to run on Windows + Test this")
void insertBlock(const Block::Ptr &block)
Definition: World.cpp:311
void advertiseService(const std::string &serviceName, const std::function< OUTPUT_MSG_T(const INPUT_MSG_T &)> &callback)
Definition: Client.h:164
GLdouble s
void clear_all()
Definition: World.cpp:48
double dt
timestep
Definition: basic_types.h:61
std::string BASE_IMPEXP filePathSeparatorsToNative(const std::string &filePath)
std::mutex m_simulationStepRunningMtx
Definition: World.h:336
double yaw() const
std::string resolvePath(const std::string &in_path) const
Definition: World.cpp:162
b2Body * m_b2_ground_body
Definition: World.h:322
GLfloat GLfloat p
double pitch() const
std::function< void(WorldElementBase &)> world_element_visitor_t
Definition: World.h:223
std::atomic_bool m_gui_thread_must_close
Definition: World.h:145
std::thread m_gui_thread
Definition: World.h:142
BlockList m_blocks
Definition: World.h:326
int m_b2d_vel_iters
Definition: World.h:265
void runVisitorOnVehicles(const vehicle_visitor_t &v)
Definition: World.cpp:192
#define ASSERT_(f)
double m_simul_timestep
Definition: World.h:262
std::string BASE_IMPEXP trim(const std::string &str)
World()
Default ctor: inits an empty world.
Definition: World.cpp:27
void connectToServer()
Definition: World.cpp:205
void run_simulation(double dt)
Definition: World.cpp:71
std::string m_base_path
Definition: World.h:279


mvsim
Author(s):
autogenerated on Fri May 7 2021 03:05:51