World_simul.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/obs/CSinCosLookUpTableFor2DScans.h>
13 #include <mrpt/poses/CPose3D.h>
14 #include <mrpt/poses/CPose3DQuat.h>
15 #include <mrpt/system/filesystem.h>
16 #include <mrpt/tfest.h> // least-squares methods
17 #include <mrpt/tfest/TMatchingPair.h>
18 #include <mrpt/version.h>
19 #include <mvsim/World.h>
20 
21 using namespace mvsim;
22 using namespace std;
23 
25 void World::run_simulation(double dt)
26 {
27  ASSERT_(initialized_);
28 
29  const double t0 = mrpt::Clock::nowDouble();
30 
31  // Define start of simulation time:
32  if (!simul_start_wallclock_time_.has_value()) simul_start_wallclock_time_ = t0 - dt;
33 
34  timlogger_.registerUserMeasure("run_simulation.dt", dt);
35 
36  const double simulTimestep = get_simul_timestep();
37 
38  // sanity checks:
39  ASSERT_(dt > 0);
40  ASSERT_(simulTimestep > 0);
41 
42  // Run in time steps:
43  const double end_time = get_simul_time() + dt;
44  // tolerance for rounding errors summing time steps
45  const double timetol = 1e-4;
46  while (get_simul_time() < (end_time - timetol))
47  {
48  // Timestep: always "simul_step" for the sake of repeatibility,
49  // except if requested to run a shorter step:
50  const double remainingTime = end_time - get_simul_time();
51  if (remainingTime <= 0) break;
52 
53  internal_one_timestep(remainingTime >= simulTimestep ? simulTimestep : remainingTime);
54 
55  // IMPORTANT: This must be inside the loop to allow breaking if we are
56  // closing the app and simulatedTime is not ticking anymore.
57  if (simulator_must_close()) break;
58  }
59 
60  const double t1 = mrpt::Clock::toDouble(mrpt::Clock::now());
61 
62  timlogger_.registerUserMeasure("run_simulation.cpu_dt", t1 - t0);
63 }
64 
67 {
68  if (simulator_must_close()) return;
69 
70  std::lock_guard<std::mutex> lck(simulationStepRunningMtx_);
71 
72  timer_iteration_.Tic();
73 
74  TSimulContext context;
75  context.world = this;
76  context.b2_world = box2d_world_.get();
77  context.simul_time = get_simul_time();
78  context.dt = dt;
79 
80  auto lckListObjs = mrpt::lockHelper(getListOfSimulableObjectsMtx());
81 
82  // 1) Pre-step
83  {
84  mrpt::system::CTimeLoggerEntry tle(timlogger_, "timestep.1.prestep");
85  for (auto& e : simulableObjects_)
86  if (e.second) e.second->simul_pre_timestep(context);
87  }
88  // 2) vehicles terrain elevation
89  {
90  mrpt::system::CTimeLoggerEntry tle(timlogger_, "timestep.2.terrain_elevation");
91  internal_simul_pre_step_terrain_elevation();
92  }
93 
94  // 3) Run dynamics
95  {
96  mrpt::system::CTimeLoggerEntry tle(timlogger_, "timestep.3.dynamics_integrator");
97 
98  box2d_world_->Step(dt, b2dVelIters_, b2dPosIters_);
99 
100  // Move time forward:
101  auto lckSimTim = mrpt::lockHelper(simul_time_mtx_);
102  simulTime_ += dt;
103  }
104 
105  // 4) Save dynamical state and post-step processing:
106  // This also makes a copy of all objects dynamical state, so service calls
107  // can be answered straight away without waiting for the main simulation
108  // mutex:
109  {
110  mrpt::system::CTimeLoggerEntry tle(timlogger_, "timestep.4.save_dynstate");
111 
112  const auto lckPhys = mrpt::lockHelper(physical_objects_mtx());
113  const auto lckCopy = mrpt::lockHelper(copy_of_objects_dynstate_mtx_);
114 
115  for (auto& e : simulableObjects_)
116  {
117  if (!e.second) continue;
118  // process:
119  e.second->simul_post_timestep(context);
120 
121  // save our own copy of the kinematic state:
122  copy_of_objects_dynstate_pose_[e.first] = e.second->getPose();
123  copy_of_objects_dynstate_twist_[e.first] = e.second->getTwist();
124 
125  if (e.second->hadCollision()) copy_of_objects_had_collision_.insert(e.first);
126  }
127  }
128  {
129  const auto lckCollis = mrpt::lockHelper(reset_collision_flags_mtx_);
130  for (const auto& sId : reset_collision_flags_)
131  {
132  if (auto itV = simulableObjects_.find(sId); itV != simulableObjects_.end())
133  itV->second->resetCollisionFlag();
134  }
135  reset_collision_flags_.clear();
136  }
137  lckListObjs.unlock(); // for simulableObjects_
138 
139  // 5) Wait for 3D sensors (OpenGL raytrace) to get executed on its thread:
140  mrpt::system::CTimeLoggerEntry tle4(timlogger_, "timestep.5.wait_3D_sensors");
141  if (pending_running_sensors_on_3D_scene())
142  {
143  // Use a huge timeout here to avoid timing out in build farms / cloud
144  // containers:
145  for (int i = 0; i < 20000 && pending_running_sensors_on_3D_scene(); i++)
146  std::this_thread::sleep_for(std::chrono::milliseconds(1));
147 
148  if (pending_running_sensors_on_3D_scene())
149  {
150  MRPT_LOG_WARN(
151  "Timeout waiting for async sensors to be simulated in opengl "
152  "thread.");
153  timlogger_.registerUserMeasure("timestep.timeout_3D_sensors", 1.0);
154  }
155  }
156  tle4.stop();
157 
158  // 6) If we have .rawlog generation enabled, process odometry, etc.
159  mrpt::system::CTimeLoggerEntry tle5(timlogger_, "timestep.6.post_rawlog");
160 
161  internalPostSimulStepForRawlog();
162  internalPostSimulStepForTrajectory();
163 
164  tle5.stop();
165 
166  const double ts = timer_iteration_.Tac();
167  timlogger_.registerUserMeasure("timestep", ts);
168  if (ts > dt) timlogger_.registerUserMeasure("timestep.too_slow_alert", ts);
169 }
170 
172 {
173  ASSERT_GE_(simulTimestep_, .0);
174  static bool firstTimeCheck = true;
175 
176  auto lambdaMinimumSensorPeriod = [this]() -> std::optional<double>
177  {
178  std::optional<double> ret;
179  for (const auto& veh : vehicles_)
180  {
181  if (!veh.second) continue;
182  for (const auto& s : veh.second->getSensors())
183  {
184  const double T = s->sensor_period();
185  if (ret)
186  mrpt::keep_min(*ret, T);
187  else
188  ret = T;
189  }
190  }
191  return ret;
192  };
193 
194  if (simulTimestep_ == 0)
195  {
196  // `0` means auto-determine as the minimum of 5 ms and the shortest
197  // sensor sample period.
198  simulTimestep_ = 5e-3;
199 
200  auto sensorMinPeriod = lambdaMinimumSensorPeriod();
201  if (sensorMinPeriod) mrpt::keep_min(simulTimestep_, *sensorMinPeriod);
202 
203  MRPT_LOG_INFO_FMT(
204  "Physics simulation timestep automatically determined as: %.02f ms",
205  1e3 * simulTimestep_);
206 
207  firstTimeCheck = false; // no need to check.
208  }
209  else if (firstTimeCheck)
210  {
211  firstTimeCheck = false;
212  auto sensorMinPeriod = lambdaMinimumSensorPeriod();
213  if (sensorMinPeriod && simulTimestep_ > *sensorMinPeriod)
214  {
215  MRPT_LOG_WARN_FMT(
216  "Physics simulation timestep (%.02f ms) should be >= than the "
217  "minimum sensor period (%.02f ms) to avoid missing sensor "
218  "readings!!",
219  1e3 * simulTimestep_, 1e3 * *sensorMinPeriod);
220  }
221  }
222 
223  return simulTimestep_;
224 }
225 
227 {
228  if (save_to_rawlog_.empty()) return;
229 
230  ASSERT_GT_(rawlog_odometry_rate_, 0.0);
231 
232  const double now = get_simul_time();
233  const double T_odom = 1.0 / rawlog_odometry_rate_;
234 
235  if (rawlog_last_odom_time_.has_value() && (now - *rawlog_last_odom_time_) < T_odom)
236  {
237  return; // not yet
238  }
239 
240  rawlog_last_odom_time_ = now;
241 
242  // Create one observation per robot:
243  for (const auto& veh : vehicles_)
244  {
245  auto obs = mrpt::obs::CObservationOdometry::Create();
246  obs->timestamp = get_simul_timestamp();
247  obs->sensorLabel = "odom";
248  obs->odometry = veh.second->getCPose2D();
249 
250  obs->hasVelocities = true;
251  obs->velocityLocal = veh.second->getVelocityLocal();
252 
253  // TODO: Simul noisy odometry and odom velocity
254 
255  internalOnObservation(*veh.second, obs);
256  }
257 }
258 
260 {
261  using namespace std::string_literals;
262 
263  if (save_ground_truth_trajectory_.empty()) return;
264 
265  ASSERT_GT_(ground_truth_rate_, 0.0);
266 
267  const double now = get_simul_time();
268  const double T_odom = 1.0 / ground_truth_rate_;
269 
270  if (gt_last_time_.has_value() && (now - *gt_last_time_) < T_odom)
271  {
272  return; // not yet
273  }
274 
275  gt_last_time_ = now;
276 
277  // Create one entry per robot.
278  // First, create the output files if this is the first time:
279  auto lck = mrpt::lockHelper(gt_io_mtx_);
280  if (gt_io_per_veh_.empty())
281  {
282  for (const auto& [vehName, veh] : vehicles_)
283  {
284  const std::string fileName = mrpt::system::fileNameChangeExtension(
285  save_ground_truth_trajectory_, vehName + ".txt"s);
286 
287  MRPT_LOG_INFO_STREAM("Creating ground truth file: " << fileName);
288 
289  gt_io_per_veh_[vehName] = std::fstream(fileName, std::ios::out);
290  }
291  }
292 
293  const double t = mrpt::Clock::toDouble(get_simul_timestamp());
294 
295  for (const auto& [vehName, veh] : vehicles_)
296  {
297  const auto p = mrpt::poses::CPose3DQuat(veh->getCPose3D());
298 
299  // each row contains these elements separated by spaces:
300  // timestamp x y z q_x q_y q_z q_w
301 
302  gt_io_per_veh_.at(vehName) << mrpt::format(
303  "%f %f %f %f %f %f %f %f\n", t, p.x(), p.y(), p.z(), p.quat().x(), p.quat().y(),
304  p.quat().z(), p.quat().w());
305  }
306 }
307 
309 {
310  // For each vehicle:
311  // (1/2) Compute its 3D pose according to the mesh tilt angle.
312  // and apply gravity force.
313  const double gravity = get_gravity();
314 
315  mrpt::tfest::TMatchingPairList corrs;
316  mrpt::poses::CPose3D optimalTf;
317 
318  std::map<const VehicleBase*, std::vector<float>> wheel_heights_per_vehicle;
319 
320  const World::VehicleList& lstVehs = getListOfVehicles();
321  for (auto& [name, veh] : lstVehs)
322  {
323  const size_t nWheels = veh->getNumWheels();
324 
325  // 1) Compute its 3D pose according to the mesh tilt angle.
326  // Idea: run a least-squares method to find the best
327  // SE(3) transformation that map the wheels contact point,
328  // as seen in local & global coordinates.
329  // (For large tilt angles, may have to run it iteratively...)
330  // -------------------------------------------------------------
331  // the final downwards direction (unit vector (0,0,-1)) as seen in
332  // vehicle local frame.
333  mrpt::math::TPoint3D dir_down;
334  for (int iter = 0; iter < 2; iter++)
335  {
336  const mrpt::math::TPose3D& cur_pose = veh->getPose();
337 
338  // This object is faster for repeated point projections
339  const mrpt::poses::CPose3D cur_cpose(cur_pose);
340 
341  mrpt::math::TPose3D new_pose = cur_pose;
342  corrs.clear();
343 
344  bool all_equal = true;
345  std::optional<float> equal_zs;
346 
347  // Store wheels height for the posterior stage of collision detection:
348  auto& wheelHeights = wheel_heights_per_vehicle[veh.get()];
349  wheelHeights.resize(nWheels);
350 
351  for (size_t iW = 0; iW < nWheels; iW++)
352  {
353  const Wheel& wheel = veh->getWheelInfo(iW);
354 
355  // Local frame
356  mrpt::tfest::TMatchingPair corr;
357 
358  corr.localIdx = iW;
359  corr.local = mrpt::math::TPoint3D(wheel.x, wheel.y, 0);
360 
361  // Global frame
362  const mrpt::math::TPoint3D gPt = cur_cpose.composePoint({wheel.x, wheel.y, 0.0});
363 
364  const mrpt::math::TPoint3D gPtWheelsAxis =
365  gPt + mrpt::math::TPoint3D(.0, .0, 0.5 * wheel.diameter);
366 
367  // Get "the ground" under my wheel axis:
368  const float z = this->getHighestElevationUnder(gPtWheelsAxis);
369 
370  wheelHeights[iW] = z;
371 
372  if (!equal_zs) equal_zs = z;
373  if (std::abs(*equal_zs - z) > 1e-4) all_equal = false;
374 
375  corr.globalIdx = iW;
376  corr.global = mrpt::math::TPoint3D(gPt.x, gPt.y, z);
377 
378  corrs.push_back(corr);
379  } // end for each Wheel
380 
381  if (all_equal && equal_zs.has_value())
382  {
383  // Optimization: just use the constant elevation without optimizing:
384  new_pose.z = *equal_zs;
385  new_pose.pitch = 0;
386  new_pose.roll = 0;
387  }
388  else if (corrs.size() >= 3)
389  {
390  // Register:
391  double transf_scale;
392  mrpt::poses::CPose3DQuat tmpl;
393 
394  mrpt::tfest::se3_l2(corrs, tmpl, transf_scale, true /*force scale unity*/);
395 
396  optimalTf = mrpt::poses::CPose3D(tmpl);
397 
398  new_pose.z = optimalTf.z();
399  new_pose.yaw = optimalTf.yaw();
400  new_pose.pitch = optimalTf.pitch();
401  new_pose.roll = optimalTf.roll();
402  }
403 
404  veh->setPose(new_pose);
405 
406  } // end iters
407 
408  // compute "down" direction:
409  {
410  mrpt::poses::CPose3D rot_only;
411  rot_only.setRotationMatrix(optimalTf.getRotationMatrix());
412  rot_only.inverseComposePoint(.0, .0, -1.0, dir_down.x, dir_down.y, dir_down.z);
413  }
414 
415  // 2) Apply gravity force
416  // -------------------------------------------------------------
417  {
418  // To chassis:
419  const double chassis_weight = veh->getChassisMass() * gravity;
420  const mrpt::math::TPoint2D chassis_com = veh->getChassisCenterOfMass();
421  veh->apply_force(
422  {dir_down.x * chassis_weight, dir_down.y * chassis_weight}, chassis_com);
423 
424  // To wheels:
425  for (size_t iW = 0; iW < nWheels; iW++)
426  {
427  const Wheel& wheel = veh->getWheelInfo(iW);
428  const double wheel_weight = wheel.mass * gravity;
429  veh->apply_force(
430  {dir_down.x * wheel_weight, dir_down.y * wheel_weight}, {wheel.x, wheel.y});
431  }
432  }
433  } // end for each vehicle
434 
435  // (2/2) Collisions due to steep slopes
436 
437  // Make a list of objects subject to collide with the occupancy grid:
438  // - Vehicles
439  // - Blocks
440  const World::BlockList& lstBlocks = getListOfBlocks();
441  const size_t nObjs = lstVehs.size() + lstBlocks.size();
442  obstacles_for_each_obj_.resize(nObjs);
443  size_t objIdx = 0;
444  for (auto& [name, veh] : lstVehs)
445  {
446  auto& e = obstacles_for_each_obj_.at(objIdx);
447  if (!e.has_value()) e.emplace();
448 
449  TInfoPerCollidableobj& ipv = e.value();
450  ipv.pose = veh->getCPose3D();
451  ipv.representativeHeight = 1.05 * veh->chassisZMax();
452  ipv.contour = veh->getChassisShape();
453  ipv.maxWorkableStepHeight = 0.55 * veh->getWheelInfo(0).diameter;
454 
455  const auto& tw = veh->getTwist();
456  ipv.speed = mrpt::math::TVector2D(tw.vx, tw.vy).norm();
457 
458  if (auto it = wheel_heights_per_vehicle.find(veh.get());
459  it != wheel_heights_per_vehicle.end())
460  {
461  ipv.wheel_heights = &it->second;
462  }
463 
464  objIdx++;
465  }
466 
467 #if 0 // Do not process blocks for now...
468  for (const auto& [name, block] : lstBlocks)
469  {
470  auto& e = obstacles_for_each_obj_.at(objIdx);
471  objIdx++;
472 
473  // only for moving blocks:
474  if (block->isStatic()) continue;
475  const auto tw = block->getTwist();
476  if (std::abs(tw.vx) < 1e-4 && std::abs(tw.vy) < 1e-4 && std::abs(tw.omega) < 1e-4) continue;
477 
478  if (!e.has_value()) e.emplace();
479 
480  TInfoPerCollidableobj& ipv = e.value();
481  ipv.pose = block->getCPose3D();
482  ipv.representativeHeight = 1.05 * block->block_z_max();
483  ipv.contour = block->blockShape();
484  }
485 #endif
486 
487  // For each object, create a ground body with fixtures at each potential collision point
488  // around the vehicle, so it can collide with the environment:
489  for (auto& e : obstacles_for_each_obj_)
490  {
491  if (!e.has_value()) continue;
492 
493  TInfoPerCollidableobj& ipv = e.value();
494 
495  ASSERT_(ipv.wheel_heights);
496  // Get mean wheels elevation:
497  float avrg_wheels_z = .0f;
498  for (const auto z : *ipv.wheel_heights) avrg_wheels_z += z;
499  avrg_wheels_z /= 1.0f * ipv.wheel_heights->size();
500 
501  ipv.contour_heights.assign(ipv.contour.size(), 0);
502  // 1) get obstacles around the vehicle:
503  for (size_t k = 0; k < ipv.contour.size(); k++)
504  {
505  const auto ptLocal = mrpt::math::TPoint3D(
506  ipv.contour.at(k).x, ipv.contour.at(k).y, ipv.representativeHeight);
507  const auto ptGlobal = ipv.pose.composePoint(ptLocal);
508  const float z = getHighestElevationUnder(ptGlobal);
509  ipv.contour_heights.at(k) = z;
510  }
511  // 2) Create a Box2D "ground body" with square "fixtures" so the
512  // vehicle can collide with the occ. grid:
513 
514  // Create Box2D objects upon first usage:
515  if (!ipv.collide_body)
516  {
517  b2BodyDef bdef;
518  ipv.collide_body = getBox2DWorld()->CreateBody(&bdef);
519  ASSERT_(ipv.collide_body);
520  }
521  // Force move the body to the vehicle origins (to use obstacles in
522  // local coords):
523  ipv.collide_body->SetTransform(b2Vec2(ipv.pose.x(), ipv.pose.y()), .0f);
524 
525  // Create fixtures at their place (or disable it if no obstacle has
526  // been sensed):
527  ipv.collide_fixtures.resize(ipv.contour.size());
528  for (size_t k = 0; k < ipv.contour.size(); k++)
529  {
530  const double obsW = 0.01 + ipv.speed * 0.07;
531 
532  if (!ipv.collide_fixtures[k].fixture)
533  {
534  // Physical properties of each "obstacle":
535  // make the size proportional to speed to avoid "going thru" walls:
536  b2PolygonShape sqrPoly;
537  sqrPoly.SetAsBox(obsW, obsW);
538  sqrPoly.m_radius = 1e-3; // The "skin" depth of the body
539  b2FixtureDef fixtureDef;
540  fixtureDef.shape = &sqrPoly;
541  fixtureDef.restitution = 0.1f; // restitution_;
542  fixtureDef.density = 0; // Fixed (inf. mass)
543  fixtureDef.friction = 0.5f; // lateral_friction_; // 0.5f;
544 
545  ipv.collide_fixtures[k].fixture = ipv.collide_body->CreateFixture(&fixtureDef);
546  }
547 
548  const bool is_collision =
549  (ipv.contour_heights[k] - avrg_wheels_z) > ipv.maxWorkableStepHeight;
550 
551  if (!is_collision)
552  {
553  // Box2D's way of saying: don't collide with this!
554  ipv.collide_fixtures[k].fixture->SetSensor(true);
555  ipv.collide_fixtures[k].fixture->GetUserData().pointer =
557  }
558  else
559  {
560  ipv.collide_fixtures[k].fixture->SetSensor(false);
561  ipv.collide_fixtures[k].fixture->GetUserData().pointer = 0;
562 
563  b2PolygonShape* poly =
564  dynamic_cast<b2PolygonShape*>(ipv.collide_fixtures[k].fixture->GetShape());
565  ASSERT_(poly != nullptr);
566 
567  const auto ptLocal = mrpt::math::TPoint3D(
568  ipv.contour.at(k).x, ipv.contour.at(k).y, ipv.representativeHeight);
569  auto ptGlobal = ipv.pose.composePoint(ptLocal);
570  ptGlobal.x = mrpt::round(ptGlobal.x / obsW) * obsW;
571  ptGlobal.y = mrpt::round(ptGlobal.y / obsW) * obsW;
572 
573  const float lx = ptGlobal.x - ipv.pose.x();
574  const float ly = ptGlobal.y - ipv.pose.y();
575 
576  poly->SetAsBox(obsW, obsW, b2Vec2(lx, ly), .0f /*angle*/);
577  }
578  }
579  } // end for object
580 }
581 
583 {
584  if (!lut2d_objects_is_up_to_date_) internal_update_lut_cache();
585 
586  return lut2d_objects_;
587 }
588 
590 {
591  constexpr float LUT_GRID_SIZE = 4.0;
593  c.x = static_cast<int32_t>(p.x / LUT_GRID_SIZE);
594  c.y = static_cast<int32_t>(p.y / LUT_GRID_SIZE);
595  return c;
596 }
597 
599 {
600  lut2d_objects_is_up_to_date_ = true;
601 
602  lut2d_objects_.clear();
603  for (const auto& [name, obj] : blocks_)
604  {
605  std::set<lut_2d_coordinates_t, LutIndexHash> affected_coords;
606  const auto p = obj->getCPose3D();
607  for (const auto& vertex : obj->blockShape())
608  {
609  const auto pt = p.composePoint({vertex.x, vertex.y, .0});
610  const auto c = xy_to_lut_coords(mrpt::math::TPoint2Df(pt.x, pt.y));
611  affected_coords.insert(c);
612  }
613  for (const auto& c : affected_coords) lut2d_objects_[c].push_back(obj);
614  }
615 }
mvsim
Definition: Client.h:21
fileName
static const char * fileName
Definition: settings.cpp:28
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::World::VehicleList
std::multimap< std::string, VehicleBase::Ptr > VehicleList
Definition: World.h:291
mvsim::World::internal_simul_pre_step_terrain_elevation
void internal_simul_pre_step_terrain_elevation()
Definition: World_simul.cpp:308
mvsim::World::internalPostSimulStepForTrajectory
void internalPostSimulStepForTrajectory()
Definition: World_simul.cpp:259
b2Body::SetTransform
void SetTransform(const b2Vec2 &position, float angle)
Definition: b2_body.cpp:415
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
World.h
mvsim::World::internal_update_lut_cache
void internal_update_lut_cache() const
Definition: World_simul.cpp:598
b2FixtureDef
Definition: b2_fixture.h:61
mvsim::TSimulContext::simul_time
double simul_time
Current time in the simulated world.
Definition: basic_types.h:62
mvsim::World::lut_2d_coordinates_t::y
int32_t y
Definition: World.h:687
mvsim::Wheel::x
double x
Definition: Wheel.h:40
b2Vec2
A 2D column vector.
Definition: b2_math.h:41
mvsim::World::TInfoPerCollidableobj
Definition: World.h:888
f
f
mvsim::World::TInfoPerCollidableobj::wheel_heights
const std::vector< float > * wheel_heights
Definition: World.h:898
mvsim::World::TInfoPerCollidableobj::maxWorkableStepHeight
double maxWorkableStepHeight
Definition: World.h:895
mvsim::TSimulContext::dt
double dt
timestep
Definition: basic_types.h:63
mvsim::Wheel::diameter
double diameter
Definition: Wheel.h:46
b2FixtureDef::restitution
float restitution
The restitution (elasticity) usually in the range [0,1].
Definition: b2_fixture.h:85
b2FixtureDef::friction
float friction
The friction coefficient, usually in the range [0,1].
Definition: b2_fixture.h:82
mvsim::World::TInfoPerCollidableobj::contour
mrpt::math::TPolygon2D contour
Definition: World.h:897
mvsim::Wheel
Definition: Wheel.h:33
mvsim::TSimulContext
Definition: basic_types.h:58
b2Shape::m_radius
float m_radius
Definition: b2_shape.h:102
mvsim::World::BlockList
std::multimap< std::string, Block::Ptr > BlockList
Definition: World.h:297
mvsim::World::run_simulation
void run_simulation(double dt)
Definition: World_simul.cpp:25
mvsim::World::TInfoPerCollidableobj::pose
mrpt::poses::CPose3D pose
Definition: World.h:892
b2PolygonShape::SetAsBox
void SetAsBox(float hx, float hy)
Definition: b2_polygon_shape.cpp:36
b2FixtureDef::density
float density
The density, usually in kg/m^2.
Definition: b2_fixture.h:92
mvsim::TSimulContext::world
World * world
Definition: basic_types.h:61
b2BodyDef
Definition: b2_body.h:52
mvsim::World::TInfoPerCollidableobj::speed
double speed
Definition: World.h:896
b2FixtureDef::shape
const b2Shape * shape
Definition: b2_fixture.h:76
mvsim::World::TInfoPerCollidableobj::contour_heights
std::vector< float > contour_heights
Definition: World.h:899
mvsim::World::LUTCache
std::unordered_map< lut_2d_coordinates_t, std::vector< Simulable::Ptr >, LutIndexHash > LUTCache
Definition: World.h:719
mvsim::World::internalPostSimulStepForRawlog
void internalPostSimulStepForRawlog()
Definition: World_simul.cpp:226
mvsim::World::lut_2d_coordinates_t
Definition: World.h:685
mvsim::INVISIBLE_FIXTURE_USER_DATA
constexpr uintptr_t INVISIBLE_FIXTURE_USER_DATA
Used to signal a Box2D fixture as "invisible" to sensors.
Definition: basic_types.h:67
b2PolygonShape
Definition: b2_polygon_shape.h:32
mvsim::TSimulContext::b2_world
b2World * b2_world
Definition: basic_types.h:60
mvsim::World::TInfoPerCollidableobj::representativeHeight
double representativeHeight
Definition: World.h:894
mvsim::Wheel::mass
double mass
[kg]
Definition: Wheel.h:47
std
mvsim::World::get_simul_timestep
double get_simul_timestep() const
Simulation fixed-time interval for numerical integration.
Definition: World_simul.cpp:171
mvsim::Wheel::y
double y
Definition: Wheel.h:40
mvsim::World::TInfoPerCollidableobj::collide_fixtures
std::vector< TFixturePtr > collide_fixtures
Definition: World.h:900
mvsim::World::lut_2d_coordinates_t::x
int32_t x
Definition: World.h:687
mvsim::World::TInfoPerCollidableobj::collide_body
b2Body * collide_body
Definition: World.h:893
t
geometry_msgs::TransformStamped t
mvsim::World::internal_one_timestep
void internal_one_timestep(double dt)
Definition: World_simul.cpp:66
b2Body::CreateFixture
b2Fixture * CreateFixture(const b2FixtureDef *def)
Definition: b2_body.cpp:165


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