23 #if defined(MVSIM_HAS_ZMQ) && defined(MVSIM_HAS_PROTOBUF) 24 #include <mvsim/mvsim-msgs/TimeStampedPose.pb.h> 28 using namespace mvsim;
34 if (anim_keyframes_path_ && !anim_keyframes_path_->empty())
36 auto& poseSeq = anim_keyframes_path_.value();
38 mrpt::math::TPose3D q;
40 const double tMax = mrpt::Clock::toDouble(poseSeq.rbegin()->first);
43 mrpt::Clock::fromDouble(std::fmod(context.simul_time, tMax)), q,
46 if (interOk) this->
setPose(initial_q_ + q);
49 if (!b2dBody_)
return;
52 b2dBody_->SetTransform(
b2Vec2(q_.x, q_.y), q_.yaw);
55 b2dBody_->SetLinearVelocity(
b2Vec2(dq_.vx, dq_.vy));
56 b2dBody_->SetAngularVelocity(dq_.omega);
67 const b2Vec2& pos = b2dBody_->GetPosition();
68 const float angle = b2dBody_->GetAngle();
77 vo->guiUpdate(std::nullopt, std::nullopt);
80 const b2Vec2& vel = b2dBody_->GetLinearVelocity();
81 const float w = b2dBody_->GetAngularVelocity();
88 (q_.translation() - former_q_.translation()) * (1.0 / context.
dt);
92 isInCollision_ =
false;
94 cl !=
nullptr && cl->
contact !=
nullptr &&
98 isInCollision_ =
true;
101 hadCollisionFlag_ = hadCollisionFlag_ || isInCollision_;
107 internalHandlePublish(context);
111 [[maybe_unused]]
const mrpt::math::TVector2D& force,
112 [[maybe_unused]]
const mrpt::math::TPoint2D& applyPoint)
118 std::shared_lock lck(q_mtx_);
120 mrpt::math::TTwist2D local_vel = dq_;
121 local_vel.rotate(-q_.yaw);
127 std::shared_lock lck(q_mtx_);
129 return {q_.x, q_.y, q_.yaw};
134 std::shared_lock lck(q_mtx_);
135 return mrpt::poses::CPose3D(q_);
138 bool Simulable::parseSimulable(
144 using namespace std::string_literals;
151 mrpt::math::TPose3D p;
157 "%lf %lf %lf", &p.x, &p.y, &p.yaw))
159 "Error parsing <init_pose>%s</init_pose>", nPose->value());
160 p.yaw *=
M_PI / 180.0;
168 mrpt::math::TPose3D p;
174 "%lf %lf %lf %lf %lf %lf ", &p.x, &p.y, &p.z, &p.yaw,
177 "Error parsing <init_pose3d>%s</init_pose3d>", nPose3->value());
178 p.yaw *=
M_PI / 180.0;
179 p.pitch *=
M_PI / 180.0;
180 p.roll *=
M_PI / 180.0;
188 "Missing required XML node <init_pose>x y phi</init_pose>");
196 mrpt::math::TTwist2D dq;
202 "%lf %lf %lf", &dq.vx, &dq.vy, &dq.omega))
204 "Error parsing <init_vel>%s</init_vel>", nInitVel->value());
205 dq.omega *=
M_PI / 180.0;
208 dq.rotate(this->
getPose().yaw);
215 if (
auto node = rootNode.
first_node(
"publish"); node)
218 params[
"publish_pose_topic"] =
TParamEntry(
"%s", &publishPoseTopic_);
219 params[
"publish_pose_period"] =
TParamEntry(
"%lf", &publishPosePeriod_);
221 params[
"publish_relative_pose_topic"] =
223 std::string listObjects;
224 params[
"publish_relative_pose_objects"] =
227 auto varValues = simulable_parent_->user_defined_variables();
228 varValues[
"NAME"] =
name_;
234 bool publishEnabled =
true;
236 auxPar[
"enabled"] =
TParamEntry(
"%bool", &publishEnabled);
240 if (!publishEnabled) publishPoseTopic_.clear();
243 if (!listObjects.empty())
245 mrpt::system::tokenize(
246 mrpt::system::trim(listObjects),
" ,",
247 publishRelativePoseOfOtherObjects_);
250 std::cout <<
"[DEBUG] " 251 "Publishing relative poses of " 252 << publishRelativePoseOfOtherObjects_.size() <<
" objects (" 253 << listObjects <<
") to topic " << publishRelativePoseTopic_
258 (publishRelativePoseOfOtherObjects_.empty() &&
259 publishRelativePoseTopic_.empty()) ||
260 (!publishRelativePoseOfOtherObjects_.empty() &&
261 !publishRelativePoseTopic_.empty()));
267 if (
auto nAnim = rootNode.
first_node(
"animation"); nAnim)
269 auto aType = nAnim->first_attribute(
"type");
270 ASSERTMSG_(aType,
"<animation> tag requires a type=\"...\" attribute");
271 const std::string sType = aType->value();
273 if (sType ==
"keyframes")
275 auto& poseSeq = anim_keyframes_path_.emplace();
276 poseSeq.setInterpolationMethod(mrpt::poses::imLinearSlerp);
278 for (
auto n = nAnim->first_node(); n; n = n->next_sibling())
280 if (strcmp(n->name(),
"time_pose") == 0)
282 mrpt::math::TPose3D p;
289 "%lf %lf %lf %lf", &t, &p.x, &p.y, &p.yaw))
291 "Error parsing <time_pose>:\n%s", n->value());
292 p.yaw *=
M_PI / 180.0;
294 poseSeq.insert(mrpt::Clock::fromDouble(t), p);
296 else if (strcmp(n->name(),
"time_pose3d") == 0)
298 mrpt::math::TPose3D p;
305 "%lf %lf %lf %lf %lf %lf %lf", &t, &p.x, &p.y,
306 &p.z, &p.yaw, &p.pitch, &p.roll))
308 "Error parsing <time_pose3d>:\n%s", n->value());
309 p.yaw *=
M_PI / 180.0;
310 p.pitch *=
M_PI / 180.0;
311 p.roll *=
M_PI / 180.0;
313 poseSeq.insert(mrpt::Clock::fromDouble(t), p);
321 THROW_EXCEPTION_FMT(
"Invalid animation type='%s'", sType.c_str());
329 void Simulable::internalHandlePublish(
const TSimulContext& context)
331 std::shared_lock lck(q_mtx_);
335 if (publishPoseTopic_.empty() && publishRelativePoseTopic_.empty())
return;
339 const double tNow = mrpt::Clock::toDouble(mrpt::Clock::now());
340 if (tNow < publishPoseLastTime_ + publishPosePeriod_)
return;
342 publishPoseLastTime_ = tNow;
344 if (!publishPoseTopic_.empty())
346 mvsim_msgs::TimeStampedPose msg;
347 msg.set_unixtimestamp(tNow);
348 msg.set_objectid(
name_);
350 auto pose = msg.mutable_pose();
354 pose->set_yaw(q_.yaw);
355 pose->set_pitch(q_.pitch);
356 pose->set_roll(q_.roll);
358 client.publishTopic(publishPoseTopic_, msg);
361 if (!publishRelativePoseTopic_.empty())
363 mvsim_msgs::TimeStampedPose msg;
364 msg.set_unixtimestamp(tNow);
365 msg.set_relativetoobjectid(
name_);
368 const auto& allObjects =
372 for (
const auto& otherId : publishRelativePoseOfOtherObjects_)
374 if (
auto itObj = allObjects.find(otherId);
375 itObj != allObjects.end())
377 msg.set_objectid(otherId);
379 const auto relPose = itObj->second->q_ - q_;
381 auto pose = msg.mutable_pose();
382 pose->set_x(relPose.x);
383 pose->set_y(relPose.y);
384 pose->set_z(relPose.z);
385 pose->set_yaw(relPose.yaw);
386 pose->set_pitch(relPose.pitch);
387 pose->set_roll(relPose.roll);
389 client.publishTopic(publishRelativePoseTopic_, msg);
394 <<
"[WARNING] Trying to publish relative pose of '" 395 << otherId <<
"' wrt '" <<
name_ 396 <<
"' but could not find any object in the world with " 410 #if defined(MVSIM_HAS_ZMQ) && defined(MVSIM_HAS_PROTOBUF) 412 if (!publishPoseTopic_.empty())
415 if (!publishRelativePoseTopic_.empty())
417 publishRelativePoseTopic_);
433 vo->guiUpdate(std::nullopt, std::nullopt);
440 q_mtx_.lock_shared();
441 mrpt::math::TPose3D ret = q_;
442 q_mtx_.unlock_shared();
450 q_mtx_.lock_shared();
451 mrpt::math::TTwist2D ret = dq_;
452 q_mtx_.unlock_shared();
458 q_mtx_.lock_shared();
460 q_mtx_.unlock_shared();
467 const_cast<mrpt::math::TTwist2D&
>(dq_) = dq;
471 mrpt::math::TTwist2D local_dq = dq.rotated(q_.yaw);
473 b2dBody_->SetLinearVelocity(
b2Vec2(local_dq.vx, local_dq.vy));
474 b2dBody_->SetAngularVelocity(dq.omega);
std::map< std::string, TParamEntry > TParameterDefinitions
void parse_xmlnode_children_as_param(const rapidxml::xml_node< char > &xml_node, const TParameterDefinitions ¶ms, const std::map< std::string, std::string > &variableNamesValues={}, const char *functionNameContext="", mrpt::system::COutputLogger *logger=nullptr)
TF2SIMD_FORCE_INLINE tf2Scalar angle(const Quaternion &q1, const Quaternion &q2)
mrpt::math::TPose3D getPose() const
mrpt::math::TPose3D getPoseNoLock() const
No thread-safe version. Used internally only.
virtual void apply_force(const mrpt::math::TVector2D &force, const mrpt::math::TPoint2D &applyPoint=mrpt::math::TPoint2D(0, 0))
mrpt::math::TTwist2D getTwist() const
const rapidxml::xml_node< Ch > * first_node(const char *name) const
void parse_xmlnode_attribs(const rapidxml::xml_node< char > &xml_node, const TParameterDefinitions ¶ms, const std::map< std::string, std::string > &variableNamesValues={}, const char *functionNameContext="")
geometry_msgs::TransformStamped t
mrpt::poses::CPose3D getCPose3D() const
Alternative to getPose()
mrpt::poses::CPose2D getCPose2D() const
Alternative to getPose()
std::string parse(const std::string &input, const std::map< std::string, std::string > &variableNamesValues={})
const std::map< std::string, std::string > & user_defined_variables() const
virtual void registerOnServer(mvsim::Client &c)
virtual void simul_post_timestep(const TSimulContext &context)
void setPose(const mrpt::math::TPose3D &p) const
virtual void simul_pre_timestep(const TSimulContext &context)
void advertiseTopic(const std::string &topicName)
mrpt::math::TTwist2D getVelocityLocal() const
void setTwist(const mrpt::math::TTwist2D &dq) const
mvsim::Client & commsClient()
mrpt::math::TVector3D getLinearAcceleration() const
World * getSimulableWorldObject()
SimulableList & getListOfSimulableObjects()
Always lock/unlock getListOfSimulableObjectsMtx() before using this:
virtual VisualObject * meAsVisualObject()