43 #include <interactive_markers/interactive_marker_server.hpp>
44 #include <interactive_markers/menu_handler.hpp>
45 #include <tf2_eigen/tf2_eigen.hpp>
46 #include <tf2_geometry_msgs/tf2_geometry_msgs.hpp>
48 #if __has_include(<tf2/LinearMath/Transform.hpp>)
49 #include <tf2/LinearMath/Transform.hpp>
51 #include <tf2/LinearMath/Transform.h>
59 #include <Eigen/Geometry>
63 static const rclcpp::Logger
LOGGER = rclcpp::get_logger(
"moveit_ros_robot_interaction.robot_interaction");
64 static const float END_EFFECTOR_UNREACHABLE_COLOR[4] = { 1.0, 0.3, 0.3, 1.0 };
65 static const float END_EFFECTOR_REACHABLE_COLOR[4] = { 0.2, 1.0, 0.2, 1.0 };
70 const rclcpp::Node::SharedPtr& node,
const std::string& ns)
71 : robot_model_(robot_model), kinematic_options_map_(std::make_shared<
KinematicOptionsMap>())
75 int_marker_server_ =
new interactive_markers::InteractiveMarkerServer(topic_, node_);
78 run_processing_thread_ =
true;
79 processing_thread_ = std::make_unique<std::thread>([
this] { processingThread(); });
84 run_processing_thread_ =
false;
85 new_feedback_condition_.notify_all();
86 processing_thread_->join();
89 delete int_marker_server_;
99 decideActiveEndEffectors(
group, style);
100 decideActiveJoints(
group);
101 if (!
group.empty() && active_eef_.empty() && active_vj_.empty() && active_generic_.empty())
103 "No active joints or end effectors found for group '%s'. "
104 "Make sure that kinematics.yaml is loaded in this node's namespace.",
110 const std::string&
name)
112 std::unique_lock<std::mutex> ulock(marker_access_lock_);
119 active_generic_.push_back(g);
122 static const double DEFAULT_SCALE = 0.25;
123 double RobotInteraction::computeLinkMarkerSize(
const std::string& link)
132 Eigen::MatrixXd::Index max_index;
133 ext.maxCoeff(&max_index);
135 size = 1.01 * ext.norm();
147 return DEFAULT_SCALE;
153 double RobotInteraction::computeGroupMarkerSize(
const std::string&
group)
156 return DEFAULT_SCALE;
163 return DEFAULT_SCALE;
167 for (
const std::string& link : links)
175 Eigen::MatrixXd::Index max_index;
176 ext.maxCoeff(&max_index);
178 size = std::max(size, 1.01 * ext.norm());
184 return computeLinkMarkerSize(links[0]);
190 void RobotInteraction::decideActiveJoints(
const std::string&
group)
192 std::unique_lock<std::mutex> ulock(marker_access_lock_);
198 RCLCPP_DEBUG(LOGGER,
"Deciding active joints for group '%s'",
group.c_str());
200 const srdf::ModelConstSharedPtr& srdf = robot_model_->getSRDF();
206 std::set<std::string> used;
210 default_state.setToDefaultValues();
211 std::vector<double> aabb;
212 default_state.computeAABB(aabb);
214 const std::vector<srdf::Model::VirtualJoint>& vj = srdf->getVirtualJoints();
215 for (
const srdf::Model::VirtualJoint& joint : vj)
216 if (joint.name_ == robot_model_->getRootJointName())
218 if (joint.type_ ==
"planar" || joint.type_ ==
"floating")
221 v.connecting_link = joint.child_link_;
222 v.parent_frame = joint.parent_frame_;
223 if (!v.parent_frame.empty() && v.parent_frame[0] ==
'/')
224 v.parent_frame = v.parent_frame.substr(1);
225 v.joint_name = joint.name_;
226 if (joint.type_ ==
"planar")
231 v.size = std::max(std::max(aabb[1] - aabb[0], aabb[3] - aabb[2]), aabb[5] - aabb[4]);
232 active_vj_.push_back(v);
233 used.insert(v.joint_name);
238 const std::vector<const moveit::core::JointModel*>& joints = jmg->
getJointModels();
243 used.find(joint->getName()) == used.end())
246 v.connecting_link = joint->getChildLinkModel()->getName();
247 if (joint->getParentLinkModel())
248 v.parent_frame = joint->getParentLinkModel()->getName();
249 v.joint_name = joint->getName();
255 v.size = computeGroupMarkerSize(
group);
256 active_vj_.push_back(v);
261 void RobotInteraction::decideActiveEndEffectors(
const std::string&
group)
268 std::unique_lock<std::mutex> ulock(marker_access_lock_);
274 RCLCPP_DEBUG(LOGGER,
"Deciding active end-effectors for group '%s'",
group.c_str());
276 const srdf::ModelConstSharedPtr& srdf = robot_model_->getSRDF();
281 RCLCPP_WARN(LOGGER,
"Unable to decide active end effector: no joint model group or no srdf model");
285 const std::vector<srdf::Model::EndEffector>& eefs = srdf->getEndEffectors();
286 const std::pair<moveit::core::JointModelGroup::KinematicsSolver, moveit::core::JointModelGroup::KinematicsSolverMap>&
290 bool found_eef{
false };
291 for (
const srdf::Model::EndEffector& eef : eefs)
293 if (single_group->hasLinkModel(eef.parent_link_) &&
294 (eef.parent_group_.empty() || single_group->getName() == eef.parent_group_) &&
295 single_group->canSetStateFromIK(eef.parent_link_))
298 EndEffectorInteraction ee;
299 ee.parent_group = single_group->getName();
300 ee.parent_link = eef.parent_link_;
301 ee.eef_group = eef.component_group_;
302 ee.interaction = style;
303 active_eef_.push_back(ee);
309 if (!found_eef && !single_group->getLinkModelNames().empty())
311 std::string last_link{ single_group->getLinkModelNames().back() };
313 if (single_group->canSetStateFromIK(last_link))
315 EndEffectorInteraction ee;
316 ee.parent_group = single_group->getName();
317 ee.parent_link = last_link;
318 ee.eef_group = single_group->getName();
319 ee.interaction = style;
320 active_eef_.push_back(ee);
328 add_active_end_effectors_for_single_group(jmg);
331 else if (!smap.second.empty())
333 for (
const std::pair<const moveit::core::JointModelGroup* const, moveit::core::JointModelGroup::KinematicsSolver>&
335 add_active_end_effectors_for_single_group(it.first);
339 for (EndEffectorInteraction& eef : active_eef_)
343 eef.size = (eef.eef_group == eef.parent_group) ? computeLinkMarkerSize(eef.parent_link) :
344 computeGroupMarkerSize(eef.eef_group);
345 RCLCPP_DEBUG(LOGGER,
"Found active end-effector '%s', of scale %lf", eef.eef_group.c_str(), eef.size);
348 if (active_eef_.size() == 1)
349 active_eef_[0].size *= 1.5;
354 std::unique_lock<std::mutex> ulock(marker_access_lock_);
357 active_generic_.clear();
358 clearInteractiveMarkersUnsafe();
364 std::unique_lock<std::mutex> ulock(marker_access_lock_);
365 clearInteractiveMarkersUnsafe();
368 void RobotInteraction::clearInteractiveMarkersUnsafe()
371 shown_markers_.clear();
372 int_marker_move_subscribers_.clear();
373 int_marker_move_topics_.clear();
374 int_marker_names_.clear();
375 int_marker_server_->clear();
378 void RobotInteraction::addEndEffectorMarkers(
const InteractionHandlerPtr& handler,
const EndEffectorInteraction& eef,
379 visualization_msgs::msg::InteractiveMarker& im,
bool position,
382 geometry_msgs::msg::Pose pose;
383 pose.orientation.w = 1;
384 addEndEffectorMarkers(handler, eef, pose, im, position, orientation);
387 void RobotInteraction::addEndEffectorMarkers(
const InteractionHandlerPtr& handler,
const EndEffectorInteraction& eef,
388 const geometry_msgs::msg::Pose& im_to_eef,
389 visualization_msgs::msg::InteractiveMarker& im,
bool position,
392 if (eef.parent_group == eef.eef_group || !robot_model_->hasLinkModel(eef.parent_link))
395 visualization_msgs::msg::InteractiveMarkerControl m_control;
396 m_control.always_visible =
false;
397 if (position && orientation)
398 m_control.interaction_mode = m_control.MOVE_ROTATE_3D;
399 else if (orientation)
400 m_control.interaction_mode = m_control.ROTATE_3D;
402 m_control.interaction_mode = m_control.MOVE_3D;
404 std_msgs::msg::ColorRGBA marker_color;
405 const float* color = handler->inError(eef) ? END_EFFECTOR_UNREACHABLE_COLOR : END_EFFECTOR_REACHABLE_COLOR;
406 marker_color.r = color[0];
407 marker_color.g = color[1];
408 marker_color.b = color[2];
409 marker_color.a = color[3];
411 moveit::core::RobotStateConstPtr rstate = handler->getState();
412 const std::vector<std::string>& link_names = rstate->getJointModelGroup(eef.eef_group)->getLinkModelNames();
413 visualization_msgs::msg::MarkerArray marker_array;
414 rstate->getRobotMarkers(marker_array, link_names, marker_color, eef.eef_group, rclcpp::Duration::from_seconds(0));
415 tf2::Transform tf_root_to_link;
416 tf2::fromMsg(tf2::toMsg(rstate->getGlobalLinkTransform(eef.parent_link)), tf_root_to_link);
420 for (visualization_msgs::msg::Marker& marker : marker_array.markers)
422 marker.header = im.header;
423 marker.mesh_use_embedded_materials = !marker.mesh_resource.empty();
425 tf2::Transform tf_root_to_im, tf_root_to_mesh, tf_im_to_eef;
426 tf2::fromMsg(im.pose, tf_root_to_im);
427 tf2::fromMsg(marker.pose, tf_root_to_mesh);
428 tf2::fromMsg(im_to_eef, tf_im_to_eef);
429 tf2::Transform tf_eef_to_mesh = tf_root_to_link.inverse() * tf_root_to_mesh;
430 tf2::Transform tf_im_to_mesh = tf_im_to_eef * tf_eef_to_mesh;
431 tf2::Transform tf_root_to_mesh_new = tf_root_to_im * tf_im_to_mesh;
432 tf2::toMsg(tf_root_to_mesh_new, marker.pose);
434 m_control.markers.push_back(marker);
437 im.controls.push_back(m_control);
440 static inline std::string getMarkerName(
const InteractionHandlerPtr& handler,
const EndEffectorInteraction& eef)
442 return "EE:" + handler->getName() +
"_" + eef.parent_link;
445 static inline std::string getMarkerName(
const InteractionHandlerPtr& handler,
const JointInteraction& vj)
447 return "JJ:" + handler->getName() +
"_" + vj.connecting_link;
450 static inline std::string getMarkerName(
const InteractionHandlerPtr& handler,
const GenericInteraction& g)
452 return "GG:" + handler->getName() +
"_" + g.marker_name_suffix;
458 std::vector<visualization_msgs::msg::InteractiveMarker> ims;
460 std::unique_lock<std::mutex> ulock(marker_access_lock_);
461 moveit::core::RobotStateConstPtr s = handler->getState();
463 for (std::size_t i = 0; i < active_generic_.size(); ++i)
465 visualization_msgs::msg::InteractiveMarker im;
466 if (active_generic_[i].construct_marker(*s, im))
468 im.name = getMarkerName(handler, active_generic_[i]);
469 shown_markers_[im.name] = i;
471 RCLCPP_DEBUG(LOGGER,
"Publishing interactive marker %s (size = %lf)", im.name.c_str(), im.scale);
475 for (std::size_t i = 0; i < active_eef_.size(); ++i)
477 geometry_msgs::msg::PoseStamped pose;
478 geometry_msgs::msg::Pose control_to_eef_tf;
479 pose.header.frame_id = robot_model_->getModelFrame();
480 pose.header.stamp = node_->now();
481 computeMarkerPose(handler, active_eef_[i], *s, pose.pose, control_to_eef_tf);
483 std::string marker_name = getMarkerName(handler, active_eef_[i]);
484 shown_markers_[marker_name] = i;
487 double mscale = marker_scale < std::numeric_limits<double>::epsilon() ? active_eef_[i].size : marker_scale;
490 if (handler && handler->getControlsVisible())
498 std_msgs::msg::ColorRGBA color;
507 if (handler && handler->getMeshesVisible() &&
509 addEndEffectorMarkers(handler, active_eef_[i], control_to_eef_tf, im,
513 registerMoveInteractiveMarkerTopic(marker_name, handler->getName() +
"_" + active_eef_[i].parent_link);
514 RCLCPP_DEBUG(LOGGER,
"Publishing interactive marker %s (size = %lf)", marker_name.c_str(), mscale);
516 for (std::size_t i = 0; i < active_vj_.size(); ++i)
518 geometry_msgs::msg::PoseStamped pose;
519 pose.header.frame_id = robot_model_->getModelFrame();
520 pose.header.stamp = node_->now();
521 pose.pose = tf2::toMsg(s->getGlobalLinkTransform(active_vj_[i].connecting_link));
522 std::string marker_name = getMarkerName(handler, active_vj_[i]);
523 shown_markers_[marker_name] = i;
526 double mscale = marker_scale < std::numeric_limits<double>::epsilon() ? active_vj_[i].size : marker_scale;
529 if (handler && handler->getControlsVisible())
531 if (active_vj_[i].dof == 3)
537 registerMoveInteractiveMarkerTopic(marker_name, handler->getName() +
"_" + active_vj_[i].connecting_link);
538 RCLCPP_DEBUG(LOGGER,
"Publishing interactive marker %s (size = %lf)", marker_name.c_str(), mscale);
540 handlers_[handler->getName()] = handler;
546 for (
const visualization_msgs::msg::InteractiveMarker& im : ims)
548 int_marker_server_->insert(im);
549 int_marker_server_->setCallback(im.name,
550 [
this](
const auto& feedback) { processInteractiveMarkerFeedback(feedback); });
553 if (std::shared_ptr<interactive_markers::MenuHandler> mh = handler->getMenuHandler())
554 mh->apply(*int_marker_server_, im.name);
558 void RobotInteraction::registerMoveInteractiveMarkerTopic(
const std::string& marker_name,
const std::string&
name)
560 std::stringstream ss;
561 ss <<
"/rviz/moveit/move_marker/";
563 int_marker_move_topics_.push_back(ss.str());
564 int_marker_names_.push_back(marker_name);
571 std::unique_lock<std::mutex> ulock(marker_access_lock_);
572 if (int_marker_move_subscribers_.empty())
574 for (
size_t i = 0; i < int_marker_move_topics_.size(); ++i)
576 std::string topic_name = int_marker_move_topics_[i];
577 std::string marker_name = int_marker_names_[i];
578 std::function<void(
const geometry_msgs::msg::PoseStamped::SharedPtr)> subscription_callback =
579 [
this, marker_name](
const geometry_msgs::msg::PoseStamped::SharedPtr& msg) {
580 moveInteractiveMarker(marker_name, *msg);
582 auto subscription = node_->create_subscription<geometry_msgs::msg::PoseStamped>(
583 topic_name, rclcpp::SystemDefaultsQoS(), subscription_callback);
584 int_marker_move_subscribers_.push_back(subscription);
590 std::unique_lock<std::mutex> ulock(marker_access_lock_);
591 int_marker_move_subscribers_.clear();
595 void RobotInteraction::computeMarkerPose(
const InteractionHandlerPtr& handler,
const EndEffectorInteraction& eef,
597 geometry_msgs::msg::Pose& control_to_eef_tf)
const
600 tf2::Transform tf_root_to_link, tf_root_to_control;
603 geometry_msgs::msg::Pose msg_link_to_control;
604 if (handler->getPoseOffset(eef, msg_link_to_control))
606 tf2::Transform tf_link_to_control;
607 tf2::fromMsg(msg_link_to_control, tf_link_to_control);
609 tf_root_to_control = tf_root_to_link * tf_link_to_control;
610 tf2::toMsg(tf_link_to_control.inverse(), control_to_eef_tf);
614 tf_root_to_control = tf_root_to_link;
615 control_to_eef_tf.orientation.x = 0.0;
616 control_to_eef_tf.orientation.y = 0.0;
617 control_to_eef_tf.orientation.z = 0.0;
618 control_to_eef_tf.orientation.w = 1.0;
621 tf2::toMsg(tf_root_to_control, pose);
626 std::string root_link;
627 std::map<std::string, geometry_msgs::msg::Pose> pose_updates;
629 std::unique_lock<std::mutex> ulock(marker_access_lock_);
631 moveit::core::RobotStateConstPtr s = handler->getState();
632 root_link = s->getRobotModel()->getModelFrame();
636 std::string marker_name = getMarkerName(handler, eef);
637 geometry_msgs::msg::Pose control_to_eef_tf;
638 computeMarkerPose(handler, eef, *s, pose_updates[marker_name], control_to_eef_tf);
643 std::string marker_name = getMarkerName(handler, vj);
644 pose_updates[marker_name] = tf2::toMsg(s->getGlobalLinkTransform(vj.connecting_link));
649 std::string marker_name = getMarkerName(handler, gi);
650 geometry_msgs::msg::Pose pose;
651 if (gi.update_pose && gi.update_pose(*s, pose))
652 pose_updates[marker_name] = pose;
656 std_msgs::msg::Header header;
657 header.frame_id = root_link;
658 for (std::map<std::string, geometry_msgs::msg::Pose>::const_iterator it = pose_updates.begin();
659 it != pose_updates.end(); ++it)
660 int_marker_server_->setPose(it->first, it->second, header);
661 int_marker_server_->applyChanges();
667 int_marker_server_->applyChanges();
672 std::unique_lock<std::mutex> ulock(marker_access_lock_);
675 if (shown_markers_.find(getMarkerName(handler, eef)) == shown_markers_.end())
678 if (shown_markers_.find(getMarkerName(handler, vj)) == shown_markers_.end())
681 if (shown_markers_.find(getMarkerName(handler, gi)) == shown_markers_.end())
686 void RobotInteraction::moveInteractiveMarker(
const std::string&
name,
const geometry_msgs::msg::PoseStamped& msg)
688 std::map<std::string, std::size_t>::const_iterator it = shown_markers_.find(
name);
689 if (it != shown_markers_.end())
691 auto feedback = std::make_shared<visualization_msgs::msg::InteractiveMarkerFeedback>();
692 feedback->header = msg.header;
693 feedback->marker_name =
name;
694 feedback->pose = msg.pose;
695 feedback->event_type = visualization_msgs::msg::InteractiveMarkerFeedback::POSE_UPDATE;
696 processInteractiveMarkerFeedback(feedback);
698 std::unique_lock<std::mutex> ulock(marker_access_lock_);
699 int_marker_server_->setPose(
name, msg.pose, msg.header);
700 int_marker_server_->applyChanges();
705 void RobotInteraction::processInteractiveMarkerFeedback(
706 const visualization_msgs::msg::InteractiveMarkerFeedback::ConstSharedPtr& feedback)
709 std::unique_lock<std::mutex> ulock(marker_access_lock_);
710 std::map<std::string, std::size_t>::const_iterator it = shown_markers_.find(feedback->marker_name);
711 if (it == shown_markers_.end())
713 RCLCPP_ERROR(LOGGER,
"Unknown marker name: '%s' (not published by RobotInteraction class)",
714 feedback->marker_name.c_str());
718 std::size_t u = feedback->marker_name.find_first_of(
'_');
719 if (u == std::string::npos || u < 4)
721 RCLCPP_ERROR(LOGGER,
"Invalid marker name: '%s'", feedback->marker_name.c_str());
725 feedback_map_[feedback->marker_name] = feedback;
726 new_feedback_condition_.notify_all();
729 void RobotInteraction::processingThread()
731 std::unique_lock<std::mutex> ulock(marker_access_lock_);
733 while (run_processing_thread_ && rclcpp::ok())
735 while (feedback_map_.empty() && run_processing_thread_ && rclcpp::ok())
736 new_feedback_condition_.wait(ulock);
738 while (!feedback_map_.empty() && rclcpp::ok())
740 auto feedback = feedback_map_.begin()->second;
741 feedback_map_.erase(feedback_map_.begin());
742 RCLCPP_DEBUG(LOGGER,
"Processing feedback from map for marker [%s]", feedback->marker_name.c_str());
744 std::map<std::string, std::size_t>::const_iterator it = shown_markers_.find(feedback->marker_name);
745 if (it == shown_markers_.end())
748 "Unknown marker name: '%s' (not published by RobotInteraction class) "
749 "(should never have ended up in the feedback_map!)",
750 feedback->marker_name.c_str());
753 std::size_t u = feedback->marker_name.find_first_of(
'_');
754 if (u == std::string::npos || u < 4)
756 RCLCPP_ERROR(LOGGER,
"Invalid marker name: '%s' (should never have ended up in the feedback_map!)",
757 feedback->marker_name.c_str());
760 std::string marker_class = feedback->marker_name.substr(0, 2);
761 std::string handler_name = feedback->marker_name.substr(3, u - 3);
762 std::map<std::string, InteractionHandlerPtr>::const_iterator jt = handlers_.find(handler_name);
763 if (jt == handlers_.end())
765 RCLCPP_ERROR(LOGGER,
"Interactive Marker Handler '%s' is not known.", handler_name.c_str());
772 if (marker_class ==
"EE")
775 EndEffectorInteraction eef = active_eef_[it->second];
776 InteractionHandlerPtr ih = jt->second;
777 marker_access_lock_.unlock();
780 ih->handleEndEffector(eef, feedback);
782 catch (std::exception& ex)
784 RCLCPP_ERROR(LOGGER,
"Exception caught while handling end-effector update: %s", ex.what());
786 marker_access_lock_.lock();
788 else if (marker_class ==
"JJ")
791 JointInteraction vj = active_vj_[it->second];
792 InteractionHandlerPtr ih = jt->second;
793 marker_access_lock_.unlock();
796 ih->handleJoint(vj, feedback);
798 catch (std::exception& ex)
800 RCLCPP_ERROR(LOGGER,
"Exception caught while handling joint update: %s", ex.what());
802 marker_access_lock_.lock();
804 else if (marker_class ==
"GG")
806 InteractionHandlerPtr ih = jt->second;
807 GenericInteraction g = active_generic_[it->second];
808 marker_access_lock_.unlock();
811 ih->handleGeneric(g, feedback);
813 catch (std::exception& ex)
815 RCLCPP_ERROR(LOGGER,
"Exception caught while handling joint update: %s", ex.what());
817 marker_access_lock_.lock();
820 RCLCPP_ERROR(LOGGER,
"Unknown marker class ('%s') for marker '%s'", marker_class.c_str(),
821 feedback->marker_name.c_str());
823 catch (std::exception& ex)
825 RCLCPP_ERROR(LOGGER,
"Exception caught while processing event: %s", ex.what());
const std::vector< std::string > & getLinkModelNames() const
Get the names of the links that are part of this joint group.
const std::vector< const JointModel * > & getJointModels() const
Get all the joints in this group (including fixed and mimic joints).
bool hasJointModel(const std::string &joint) const
Check if a joint is part of this group.
const std::pair< KinematicsSolver, KinematicsSolverMap > & getGroupKinematics() const
A joint from the robot. Models the transform that this joint applies in the kinematic chain....
JointType getType() const
Get the type of joint.
A link from the robot. Contains the constant transform applied to the link and its geometry.
const Eigen::Vector3d & getShapeExtentsAtOrigin() const
Get the extents of the link's geometry (dimensions of axis-aligned bounding box around all shapes tha...
const JointModel * getParentJointModel() const
Get the joint model whose child this link is. There will always be a parent joint.
const LinkModel * getParentLinkModel() const
Get the link model whose child this link is (through some joint). There may not always be a parent li...
Representation of a robot's state. This includes position, velocity, acceleration and effort.
const Eigen::Isometry3d & getGlobalLinkTransform(const std::string &link_name)
Get the link transform w.r.t. the root link (model frame) of the RobotModel. This is typically the ro...
void publishInteractiveMarkers()
void clearInteractiveMarkers()
void updateInteractiveMarkers(const InteractionHandlerPtr &handler)
void decideActiveComponents(const std::string &group)
void toggleMoveInteractiveMarkerTopic(bool enable)
virtual ~RobotInteraction()
RobotInteraction(const moveit::core::RobotModelConstPtr &robot_model, const rclcpp::Node::SharedPtr &node, const std::string &ns="")
bool showingMarkers(const InteractionHandlerPtr &handler)
void addActiveComponent(const InteractiveMarkerConstructorFn &construct, const ProcessFeedbackFn &process, const InteractiveMarkerUpdateFn &update=InteractiveMarkerUpdateFn(), const std::string &name="")
void addInteractiveMarkers(const InteractionHandlerPtr &handler, const double marker_scale=0.0)
static const std::string INTERACTIVE_MARKER_TOPIC
The topic name on which the internal Interactive Marker Server operates.
Vec3fX< details::Vec3Data< double > > Vector3d
void addViewPlaneControl(visualization_msgs::msg::InteractiveMarker &int_marker, double radius, const std_msgs::msg::ColorRGBA &color, bool position=true, bool orientation=true)
void add6DOFControl(visualization_msgs::msg::InteractiveMarker &int_marker, bool orientation_fixed=false)
std::function< bool(moveit::core::RobotState &state, const visualization_msgs::msg::InteractiveMarkerFeedback::ConstSharedPtr &feedback)> ProcessFeedbackFn
std::function< bool(const moveit::core::RobotState &, geometry_msgs::msg::Pose &)> InteractiveMarkerUpdateFn
std::function< bool(const moveit::core::RobotState &state, visualization_msgs::msg::InteractiveMarker &marker)> InteractiveMarkerConstructorFn
void addOrientationControl(visualization_msgs::msg::InteractiveMarker &int_marker, bool orientation_fixed=false)
visualization_msgs::msg::InteractiveMarker makeEmptyInteractiveMarker(const std::string &name, const geometry_msgs::msg::PoseStamped &stamped, double scale)
void addPlanarXYControl(visualization_msgs::msg::InteractiveMarker &int_marker, bool orientation_fixed=false)
void addPositionControl(visualization_msgs::msg::InteractiveMarker &int_marker, bool orientation_fixed=false)
const rclcpp::Logger LOGGER
std::string parent_link
The name of the link in the parent group that connects to the end-effector.
std::string marker_name_suffix
ProcessFeedbackFn process_feedback
InteractiveMarkerConstructorFn construct_marker
InteractiveMarkerUpdateFn update_pose