Simulable.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 <box2d/b2_contact.h>
11 #include <box2d/b2_distance.h>
12 #include <mvsim/Block.h>
13 #include <mvsim/Simulable.h>
15 #include <mvsim/VisualObject.h>
16 #include <mvsim/World.h>
17 
18 #if defined(MVSIM_HAS_ZMQ) && defined(MVSIM_HAS_PROTOBUF)
19 #include <mvsim/Comms/Client.h>
20 #endif
21 
22 #include <cmath> // fmod()
23 
24 #include "JointXMLnode.h"
25 #include "parse_utils.h"
26 #include "xml_utils.h"
27 
28 #if defined(MVSIM_HAS_ZMQ) && defined(MVSIM_HAS_PROTOBUF)
29 #include <mvsim/mvsim-msgs/TimeStampedPose.pb.h>
30 
31 #endif
32 
33 using namespace mvsim;
34 
36  [[maybe_unused]] const TSimulContext& context)
37 {
38  // Follow animation, if enabled:
39  if (anim_keyframes_path_ && !anim_keyframes_path_->empty())
40  {
41  auto& poseSeq = anim_keyframes_path_.value();
42 
43  mrpt::math::TPose3D q;
44  bool interOk = false;
45  const double tMax = mrpt::Clock::toDouble(poseSeq.rbegin()->first);
46 
47  poseSeq.interpolate(
48  mrpt::Clock::fromDouble(std::fmod(context.simul_time, tMax)), q, interOk);
49 
50  if (interOk) this->setPose(initial_q_ + q);
51  }
52 
53  if (!b2dBody_) return;
54 
55  // Pos:
56  const auto qq = simulable_parent_->applyWorldRenderOffset(q_);
57  b2dBody_->SetTransform(b2Vec2(qq.x, qq.y), q_.yaw);
58 
59  // Vel:
60  b2dBody_->SetLinearVelocity(b2Vec2(dq_.vx, dq_.vy));
61  b2dBody_->SetAngularVelocity(dq_.omega);
62 }
63 
65 {
66  if (b2dBody_)
67  {
68  std::unique_lock lck(q_mtx_);
69 
70  // simulable_parent_->physical_objects_mtx(): already locked by caller
71 
72  // Pos:
73  const b2Vec2& pos = b2dBody_->GetPosition();
74  const float angle = b2dBody_->GetAngle();
75  const auto off = simulable_parent_->worldRenderOffset();
76  q_.x = pos(0) - off.x;
77  q_.y = pos(1) - off.y;
78  q_.yaw = angle;
79  // The rest (z,pitch,roll) will be always 0, unless other
80  // world-element modifies them! (e.g. elevation map)
81 
82  // Update the GUI element **poses** only:
83  if (auto* vo = meAsVisualObject(); vo) vo->guiUpdate(std::nullopt, std::nullopt);
84 
85  // Vel:
86  const b2Vec2& vel = b2dBody_->GetLinearVelocity();
87  const float w = b2dBody_->GetAngularVelocity();
88  dq_.vx = vel(0);
89  dq_.vy = vel(1);
90  dq_.omega = w;
91 
92  // Estimate acceleration from finite differences:
93  ddq_lin_ = (q_.translation() - former_q_.translation()) * (1.0 / context.dt);
94  former_q_ = q_;
95 
96  // Instantaneous collision flag:
97  isInCollision_ = false;
98  if (b2ContactEdge* cl = b2dBody_->GetContactList(); cl != nullptr)
99  {
100  for (auto contact = cl->contact; contact != nullptr; contact = contact->GetNext())
101  {
102  // We may store with which other bodies it's in collision?
103  const auto shA = cl->contact->GetFixtureA()->GetShape();
104  const auto shB = cl->contact->GetFixtureB()->GetShape();
105 
106  if (cl->contact->GetFixtureA()->IsSensor()) continue;
107  if (cl->contact->GetFixtureB()->IsSensor()) continue;
108 
109  b2DistanceInput di;
110  di.proxyA.Set(shA, 0 /*index for chains*/);
111  di.proxyB.Set(shB, 0 /*index for chains*/);
112  di.transformA = cl->contact->GetFixtureA()->GetBody()->GetTransform();
113  di.transformB = cl->contact->GetFixtureB()->GetBody()->GetTransform();
114  di.useRadii = true;
115 
116  b2SimplexCache dc;
117  dc.count = 0;
118  b2DistanceOutput dO;
119  b2Distance(&dO, &dc, &di);
120 
121  if (dO.distance < simulable_parent_->collisionThreshold() ||
122  cl->contact->IsTouching())
123  isInCollision_ = true;
124  }
125  }
126 
127  // Reseteable collision flag:
128  hadCollisionFlag_ = hadCollisionFlag_ || isInCollision_;
129  }
130 
131  // Optional publish to topics:
132  internalHandlePublish(context);
133 }
134 
136  [[maybe_unused]] const mrpt::math::TVector2D& force,
137  [[maybe_unused]] const mrpt::math::TPoint2D& applyPoint)
138 { /* default: do nothing*/
139 }
140 
141 mrpt::math::TTwist2D Simulable::getVelocityLocal() const
142 {
143  std::shared_lock lck(q_mtx_);
144 
145  mrpt::math::TTwist2D local_vel = dq_;
146  local_vel.rotate(-q_.yaw); // "-" means inverse pose
147  return local_vel;
148 }
149 
150 mrpt::poses::CPose2D Simulable::getCPose2D() const
151 {
152  std::shared_lock lck(q_mtx_);
153 
154  return {q_.x, q_.y, q_.yaw};
155 }
156 
157 mrpt::poses::CPose3D Simulable::getCPose3D() const
158 {
159  std::shared_lock lck(q_mtx_);
160  return mrpt::poses::CPose3D(q_);
161 }
162 
164 {
165  std::shared_lock lck(q_mtx_);
166  return isInCollision_;
167 }
168 
170 {
171  std::shared_lock lck(q_mtx_);
172  return hadCollisionFlag_;
173 }
174 
176 {
177  std::unique_lock lck(q_mtx_);
178  hadCollisionFlag_ = false;
179 }
180 
181 bool Simulable::parseSimulable(const JointXMLnode<>& rootNode, const ParseSimulableParams& psp)
182 {
183  MRPT_START
184 
185  using namespace rapidxml;
186  using namespace std::string_literals;
187 
188  // -------------------------------------
189  // (Mandatory) initial pose:
190  // -------------------------------------
191  std::optional<mrpt::math::TPose3D> initPose;
192  if (const xml_node<>* nPose = rootNode.first_node("init_pose"); nPose)
193  {
194  mrpt::math::TPose3D p;
195  if (3 !=
196  ::sscanf(
197  mvsim::parse(nPose->value(), getSimulableWorldObject()->user_defined_variables())
198  .c_str(),
199  "%lf %lf %lf", &p.x, &p.y, &p.yaw))
200  THROW_EXCEPTION_FMT("Error parsing <init_pose>%s</init_pose>", nPose->value());
201  p.yaw *= M_PI / 180.0; // deg->rad
202 
203  initPose = p;
204  }
205  else if (const xml_node<>* nPose3 = rootNode.first_node("init_pose3d"); nPose3)
206  {
207  mrpt::math::TPose3D p;
208  if (6 !=
209  ::sscanf(
210  mvsim::parse(nPose3->value(), getSimulableWorldObject()->user_defined_variables())
211  .c_str(),
212  "%lf %lf %lf %lf %lf %lf ", &p.x, &p.y, &p.z, &p.yaw, &p.pitch, &p.roll))
213  THROW_EXCEPTION_FMT("Error parsing <init_pose3d>%s</init_pose3d>", nPose3->value());
214  p.yaw *= M_PI / 180.0; // deg->rad
215  p.pitch *= M_PI / 180.0; // deg->rad
216  p.roll *= M_PI / 180.0; // deg->rad
217 
218  initPose = p;
219  }
220  else if (psp.init_pose_mandatory)
221  {
222  THROW_EXCEPTION("Missing required XML node <init_pose>x y phi</init_pose>");
223  }
224 
225  if (const rapidxml::xml_node<char>* xml_skip_elevation_adjust =
226  rootNode.first_node("skip_elevation_adjust");
227  initPose && xml_skip_elevation_adjust == nullptr)
228  {
229  // "skip" tag is NOT present => Do adjustment:
230 
231  // Query: the highest object point:
232  auto queryPt = initPose->translation();
233 
234  // Automatic determine the height of the query point:
235  if (auto meBlock = dynamic_cast<mvsim::Block*>(this); meBlock)
236  {
237  queryPt.z += 0.5 * meBlock->block_z_max();
238  }
239  else if (auto meVeh = dynamic_cast<mvsim::VehicleBase*>(this); meVeh)
240  {
241  queryPt.z += 0.5 * meVeh->chassisZMax();
242  }
243  else
244  {
245  queryPt.z += 1.5; // default [m]
246  }
247  ASSERT_EQUAL_(queryPt.z, queryPt.z); // != NaN
248 
249  if (std::optional<float> elev = simulable_parent_->getHighestElevationUnder(queryPt); elev)
250  {
251  initPose->z = elev.value();
252  }
253  }
254 
255  if (initPose)
256  {
257  this->setPose(*initPose);
258  initial_q_ = *initPose; // save it for later usage in some animations, etc.
259  }
260 
261  // -------------------------------------
262  // (Optional) initial vel:
263  // -------------------------------------
264  if (const xml_node<>* nInitVel = rootNode.first_node("init_vel"); nInitVel)
265  {
266  mrpt::math::TTwist2D dq;
267  if (3 !=
268  ::sscanf(
269  mvsim::parse(nInitVel->value(), getSimulableWorldObject()->user_defined_variables())
270  .c_str(),
271  "%lf %lf %lf", &dq.vx, &dq.vy, &dq.omega))
272  THROW_EXCEPTION_FMT("Error parsing <init_vel>%s</init_vel>", nInitVel->value());
273  dq.omega *= M_PI / 180.0; // deg->rad
274 
275  // Convert twist (velocity) from local -> global coords:
276  dq.rotate(this->getPose().yaw);
277  this->setTwist(dq);
278  }
279 
280  // -------------------------------------
281  // Parse <publish> XML tag
282  // -------------------------------------
283  if (auto node = rootNode.first_node("publish"); node)
284  {
285  TParameterDefinitions params;
286  params["publish_pose_topic"] = TParamEntry("%s", &publishPoseTopic_);
287  params["publish_pose_period"] = TParamEntry("%lf", &publishPosePeriod_);
288 
289  params["publish_relative_pose_topic"] = TParamEntry("%s", &publishRelativePoseTopic_);
290  std::string listObjects;
291  params["publish_relative_pose_objects"] = TParamEntry("%s", &listObjects);
292 
293  auto varValues = simulable_parent_->user_defined_variables();
294  varValues["NAME"] = name_;
295 
296  parse_xmlnode_children_as_param(*node, params, varValues);
297 
298  // Parse the "enabled" attribute:
299  {
300  bool publishEnabled = true;
301  TParameterDefinitions auxPar;
302  auxPar["enabled"] = TParamEntry("%bool", &publishEnabled);
303  parse_xmlnode_attribs(*node, auxPar, varValues);
304 
305  // Reset publish topic if enabled==false
306  if (!publishEnabled) publishPoseTopic_.clear();
307  }
308 
309  if (!listObjects.empty())
310  {
311  mrpt::system::tokenize(
312  mrpt::system::trim(listObjects), " ,", publishRelativePoseOfOtherObjects_);
313  }
314  ASSERT_(
315  (publishRelativePoseOfOtherObjects_.empty() && publishRelativePoseTopic_.empty()) ||
316  (!publishRelativePoseOfOtherObjects_.empty() && !publishRelativePoseTopic_.empty()));
317 
318  } // end <publish>
319 
320  // Parse animation effects:
321  // ----------------------------
322  if (auto nAnim = rootNode.first_node("animation"); nAnim)
323  {
324  auto aType = nAnim->first_attribute("type");
325  ASSERTMSG_(aType, "<animation> tag requires a type=\"...\" attribute");
326  const std::string sType = aType->value();
327 
328  if (sType == "keyframes")
329  {
330  auto& poseSeq = anim_keyframes_path_.emplace();
331  poseSeq.setInterpolationMethod(mrpt::poses::imLinearSlerp);
332 
333  for (auto n = nAnim->first_node(); n; n = n->next_sibling())
334  {
335  if (strcmp(n->name(), "time_pose") == 0)
336  {
337  mrpt::math::TPose3D p;
338  double t = 0;
339  if (4 !=
340  ::sscanf(
341  mvsim::parse(
342  n->value(), getSimulableWorldObject()->user_defined_variables())
343  .c_str(),
344  "%lf %lf %lf %lf", &t, &p.x, &p.y, &p.yaw))
345  THROW_EXCEPTION_FMT("Error parsing <time_pose>:\n%s", n->value());
346  p.yaw *= M_PI / 180.0; // deg->rad
347 
348  poseSeq.insert(mrpt::Clock::fromDouble(t), p);
349  }
350  else if (strcmp(n->name(), "time_pose3d") == 0)
351  {
352  mrpt::math::TPose3D p;
353  double t = 0;
354  if (7 !=
355  ::sscanf(
356  mvsim::parse(
357  n->value(), getSimulableWorldObject()->user_defined_variables())
358  .c_str(),
359  "%lf %lf %lf %lf %lf %lf %lf", &t, &p.x, &p.y, &p.z, &p.yaw, &p.pitch,
360  &p.roll))
361  THROW_EXCEPTION_FMT("Error parsing <time_pose3d>:\n%s", n->value());
362  p.yaw *= M_PI / 180.0; // deg->rad
363  p.pitch *= M_PI / 180.0; // deg->rad
364  p.roll *= M_PI / 180.0; // deg->rad
365 
366  poseSeq.insert(mrpt::Clock::fromDouble(t), p);
367  }
368  }
369 
370  // anim_keyframes_path_->saveToTextFile(name_ + "_path.txt"s);
371  }
372  else
373  {
374  THROW_EXCEPTION_FMT("Invalid animation type='%s'", sType.c_str());
375  }
376  }
377 
378  return true;
379  MRPT_END
380 }
381 
382 void Simulable::internalHandlePublish(const TSimulContext& context)
383 {
384 #if defined(MVSIM_HAS_ZMQ) && defined(MVSIM_HAS_PROTOBUF)
385  std::shared_lock lck(q_mtx_);
386 
387  MRPT_START
388 
389  if (publishPoseTopic_.empty() && publishRelativePoseTopic_.empty()) return;
390 
391  auto& client = context.world->commsClient();
392 
393  const double tNow = mrpt::Clock::toDouble(mrpt::Clock::now());
394  if (tNow < publishPoseLastTime_ + publishPosePeriod_) return;
395 
396  publishPoseLastTime_ = tNow;
397 
398  if (!publishPoseTopic_.empty())
399  {
400  mvsim_msgs::TimeStampedPose msg;
401  msg.set_unixtimestamp(tNow);
402  msg.set_objectid(name_);
403 
404  auto pose = msg.mutable_pose();
405  pose->set_x(q_.x);
406  pose->set_y(q_.y);
407  pose->set_z(.0);
408  pose->set_yaw(q_.yaw);
409  pose->set_pitch(q_.pitch);
410  pose->set_roll(q_.roll);
411 
412  client.publishTopic(publishPoseTopic_, msg);
413  }
414 
415  if (!publishRelativePoseTopic_.empty())
416  {
417  mvsim_msgs::TimeStampedPose msg;
418  msg.set_unixtimestamp(tNow);
419  msg.set_relativetoobjectid(name_);
420 
421  // Note: getSimulableWorldObjectMtx() is already hold by my caller.
422  const auto& allObjects = getSimulableWorldObject()->getListOfSimulableObjects();
423 
424  // detect other objects and publish their relative poses wrt me:
425  for (const auto& otherId : publishRelativePoseOfOtherObjects_)
426  {
427  if (auto itObj = allObjects.find(otherId); itObj != allObjects.end())
428  {
429  msg.set_objectid(otherId);
430 
431  const auto relPose = itObj->second->q_ - q_;
432 
433  auto pose = msg.mutable_pose();
434  pose->set_x(relPose.x);
435  pose->set_y(relPose.y);
436  pose->set_z(relPose.z);
437  pose->set_yaw(relPose.yaw);
438  pose->set_pitch(relPose.pitch);
439  pose->set_roll(relPose.roll);
440 
441  client.publishTopic(publishRelativePoseTopic_, msg);
442  }
443  else
444  {
445  std::cerr << "[WARNING] Trying to publish relative pose of '" << otherId
446  << "' wrt '" << name_
447  << "' but could not find any object in the world with "
448  "the former name."
449  << std::endl;
450  }
451  }
452  }
453 
454  MRPT_END
455 #endif
456 }
457 
459 {
460  MRPT_START
461 
462 #if defined(MVSIM_HAS_ZMQ) && defined(MVSIM_HAS_PROTOBUF)
463  // Topic:
464  if (!publishPoseTopic_.empty())
465  c.advertiseTopic<mvsim_msgs::TimeStampedPose>(publishPoseTopic_);
466 
467  if (!publishRelativePoseTopic_.empty())
468  c.advertiseTopic<mvsim_msgs::TimeStampedPose>(publishRelativePoseTopic_);
469 #endif
470 
471  MRPT_END
472 }
473 
474 void Simulable::setPose(const mrpt::math::TPose3D& p, bool notifyChange) const
475 {
476  {
477  std::unique_lock lck(q_mtx_);
478 
479  Simulable& me = const_cast<Simulable&>(*this);
480 
481  me.q_ = p;
482 
483  // Update the GUI element poses only:
484  if (auto* vo = me.meAsVisualObject(); vo) vo->guiUpdate(std::nullopt, std::nullopt);
485  }
486 
487  if (notifyChange) const_cast<Simulable*>(this)->notifySimulableSetPose(p);
488 }
489 
490 mrpt::math::TPose3D Simulable::getPose() const
491 {
492  std::shared_lock lck(q_mtx_);
493  return q_;
494 }
495 
496 mrpt::math::TPose3D Simulable::getPoseNoLock() const { return q_; }
497 
498 mrpt::math::TTwist2D Simulable::getTwist() const
499 {
500  std::shared_lock lck(q_mtx_);
501  return dq_;
502 }
503 
504 mrpt::math::TVector3D Simulable::getLinearAcceleration() const
505 {
506  std::shared_lock lck(q_mtx_);
507  return ddq_lin_;
508 }
509 
510 void Simulable::setTwist(const mrpt::math::TTwist2D& dq) const
511 {
512  std::unique_lock lck(q_mtx_);
513 
514  const_cast<mrpt::math::TTwist2D&>(dq_) = dq;
515 
516  if (b2dBody_)
517  {
518  mrpt::math::TTwist2D local_dq = dq.rotated(q_.yaw);
519 
520  b2dBody_->SetLinearVelocity(b2Vec2(local_dq.vx, local_dq.vy));
521  b2dBody_->SetAngularVelocity(dq.omega);
522  }
523 }
Client.h
Block.h
b2DistanceInput::transformB
b2Transform transformB
Definition: b2_distance.h:81
mvsim
Definition: Client.h:21
b2ContactEdge
Definition: b2_contact.h:77
b2Vec2::y
float y
Definition: b2_math.h:128
parse_utils.h
b2DistanceInput::transformA
b2Transform transformA
Definition: b2_distance.h:80
angle
TFSIMD_FORCE_INLINE tfScalar angle(const Quaternion &q1, const Quaternion &q2)
mvsim::JointXMLnode
Definition: basic_types.h:53
mvsim::Simulable::getSimulableWorldObject
World * getSimulableWorldObject()
Definition: Simulable.h:128
mvsim::ParseSimulableParams::init_pose_mandatory
bool init_pose_mandatory
Definition: Simulable.h:32
mvsim::TParamEntry
Definition: TParameterDefinitions.h:38
JointXMLnode.h
call-shutdown.client
client
Definition: call-shutdown.py:26
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::World::getListOfSimulableObjects
SimulableList & getListOfSimulableObjects()
Always lock/unlock getListOfSimulableObjectsMtx() before using this:
Definition: World.h:317
b2_distance.h
World.h
mvsim::Simulable::getCPose3D
mrpt::poses::CPose3D getCPose3D() const
Alternative to getPose()
Definition: Simulable.cpp:157
mvsim::Client
Definition: Client.h:48
b2Distance
B2_API void b2Distance(b2DistanceOutput *output, b2SimplexCache *cache, const b2DistanceInput *input)
Definition: b2_distance.cpp:454
mvsim::Simulable::getVelocityLocal
mrpt::math::TTwist2D getVelocityLocal() const
Definition: Simulable.cpp:141
TParameterDefinitions.h
b2Vec2
A 2D column vector.
Definition: b2_math.h:41
b2_contact.h
mvsim::Simulable::hadCollision
bool hadCollision() const
Definition: Simulable.cpp:169
xml_utils.h
b2DistanceInput::proxyB
b2DistanceProxy proxyB
Definition: b2_distance.h:79
mvsim::TSimulContext::dt
double dt
timestep
Definition: basic_types.h:63
b2DistanceOutput::distance
float distance
Definition: b2_distance.h:90
Simulable.h
rapidxml
Definition: rapidxml.hpp:57
mvsim::TSimulContext
Definition: basic_types.h:58
mvsim::Simulable::meAsVisualObject
virtual VisualObject * meAsVisualObject()
Definition: Simulable.h:64
mvsim::JointXMLnode::first_node
const rapidxml::xml_node< Ch > * first_node(const char *name) const
Definition: JointXMLnode.h:30
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::parse
std::string parse(const std::string &input, const std::map< std::string, std::string > &variableNamesValues={})
Definition: parse_utils.cpp:217
mvsim::Simulable::setTwist
void setTwist(const mrpt::math::TTwist2D &dq) const
Definition: Simulable.cpp:510
b2SimplexCache::count
uint16 count
Definition: b2_distance.h:68
mvsim::trim
std::string trim(const std::string &s)
Definition: parse_utils.cpp:251
mvsim::Simulable::name_
std::string name_
Definition: Simulable.h:145
mvsim::Block
Definition: Block.h:50
b2Vec2::x
float x
Definition: b2_math.h:128
mvsim::TSimulContext::world
World * world
Definition: basic_types.h:61
b2SimplexCache
Definition: b2_distance.h:65
mvsim::Simulable::registerOnServer
virtual void registerOnServer(mvsim::Client &c)
Definition: Simulable.cpp:458
b2DistanceOutput
Output for b2Distance.
Definition: b2_distance.h:86
mvsim::Simulable::getLinearAcceleration
mrpt::math::TVector3D getLinearAcceleration() const
Definition: Simulable.cpp:504
mvsim::Simulable::setPose
void setPose(const mrpt::math::TPose3D &p, bool notifyChange=true) const
Definition: Simulable.cpp:474
mvsim::VehicleBase
Definition: VehicleBase.h:44
rapidxml::xml_node
Definition: rapidxml.hpp:137
mvsim::ParseSimulableParams
Definition: Simulable.h:28
mvsim::Simulable
Definition: Simulable.h:39
b2DistanceInput::proxyA
b2DistanceProxy proxyA
Definition: b2_distance.h:78
b2DistanceInput
Definition: b2_distance.h:76
mvsim::Simulable::apply_force
virtual void apply_force(const mrpt::math::TVector2D &force, const mrpt::math::TPoint2D &applyPoint=mrpt::math::TPoint2D(0, 0))
Definition: Simulable.cpp:135
mvsim::Simulable::simul_pre_timestep
virtual void simul_pre_timestep(const TSimulContext &context)
Definition: Simulable.cpp:35
b2DistanceProxy::Set
void Set(const b2Shape *shape, int32 index)
Definition: b2_distance.cpp:32
mvsim::Client::advertiseTopic
void advertiseTopic(const std::string &topicName)
Definition: Client.h:177
mvsim::Simulable::isInCollision
bool isInCollision() const
Definition: Simulable.cpp:163
mvsim::Simulable::resetCollisionFlag
void resetCollisionFlag()
Definition: Simulable.cpp:175
mvsim::Simulable::getPose
mrpt::math::TPose3D getPose() const
Definition: Simulable.cpp:490
mvsim::Simulable::getTwist
mrpt::math::TTwist2D getTwist() const
Definition: Simulable.cpp:498
mvsim::Simulable::getCPose2D
mrpt::poses::CPose2D getCPose2D() const
Alternative to getPose()
Definition: Simulable.cpp:150
VisualObject.h
mvsim::parse_xmlnode_attribs
void parse_xmlnode_attribs(const rapidxml::xml_node< char > &xml_node, const TParameterDefinitions &params, const std::map< std::string, std::string > &variableNamesValues={}, const char *functionNameContext="")
Definition: xml_utils.cpp:182
b2DistanceInput::useRadii
bool useRadii
Definition: b2_distance.h:82
t
geometry_msgs::TransformStamped t
mvsim::Simulable::getPoseNoLock
mrpt::math::TPose3D getPoseNoLock() const
No thread-safe version. Used internally only.
Definition: Simulable.cpp:496


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