00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include <moveit/robot_interaction/robot_interaction.h>
00033 #include <moveit/robot_interaction/interactive_marker_helpers.h>
00034 #include <moveit/transforms/transforms.h>
00035 #include <interactive_markers/interactive_marker_server.h>
00036 #include <interactive_markers/menu_handler.h>
00037 #include <eigen_conversions/eigen_msg.h>
00038 #include <tf_conversions/tf_eigen.h>
00039 #include <boost/lexical_cast.hpp>
00040 #include <boost/math/constants/constants.hpp>
00041 #include <algorithm>
00042 #include <limits>
00043
00044 #include <Eigen/Core>
00045 #include <Eigen/Geometry>
00046
00047 namespace robot_interaction
00048 {
00049
00050 static const float END_EFFECTOR_UNREACHABLE_COLOR[4] = { 1.0, 0.3, 0.3, 1.0 };
00051 static const float END_EFFECTOR_REACHABLE_COLOR[4] = { 0.2, 1.0, 0.2, 1.0 };
00052 static const float END_EFFECTOR_WHITE_COLOR[4] = { 1.0, 1.0, 1.0, 1.0 };
00053 static const float END_EFFECTOR_COLLISION_COLOR[4] = { 0.8, 0.8, 0.0, 1.0 };
00054
00055 const std::string RobotInteraction::INTERACTIVE_MARKER_TOPIC = "robot_interaction_interactive_marker_topic";
00056
00057 RobotInteraction::InteractionHandler::InteractionHandler(const std::string &name,
00058 const robot_state::RobotState &kstate,
00059 const boost::shared_ptr<tf::Transformer> &tf) :
00060 name_(name),
00061 kstate_(new robot_state::RobotState(kstate)),
00062 tf_(tf),
00063 display_meshes_(true),
00064 display_controls_(true)
00065 {
00066 setup();
00067 }
00068
00069 RobotInteraction::InteractionHandler::InteractionHandler(const std::string &name,
00070 const robot_model::RobotModelConstPtr &robot_model,
00071 const boost::shared_ptr<tf::Transformer> &tf) :
00072 name_(name),
00073 kstate_(new robot_state::RobotState(robot_model)),
00074 tf_(tf),
00075 display_meshes_(true),
00076 display_controls_(true)
00077 {
00078 setup();
00079 }
00080
00081 void RobotInteraction::InteractionHandler::setup()
00082 {
00083 std::replace(name_.begin(), name_.end(), '_', '-');
00084 ik_timeout_ = 0.0;
00085 ik_attempts_ = 0;
00086 planning_frame_ = kstate_->getRobotModel()->getModelFrame();
00087 }
00088
00089 void RobotInteraction::InteractionHandler::setPoseOffset(const RobotInteraction::EndEffector& eef, const geometry_msgs::Pose& m)
00090 {
00091 boost::mutex::scoped_lock slock(offset_map_lock_);
00092 offset_map_[eef.eef_group] = m;
00093 }
00094
00095 void RobotInteraction::InteractionHandler::setPoseOffset(const RobotInteraction::Joint& vj, const geometry_msgs::Pose& m)
00096 {
00097 boost::mutex::scoped_lock slock(offset_map_lock_);
00098 offset_map_[vj.joint_name] = m;
00099 }
00100
00101 void RobotInteraction::InteractionHandler::clearPoseOffset(const RobotInteraction::EndEffector& eef)
00102 {
00103 boost::mutex::scoped_lock slock(offset_map_lock_);
00104 offset_map_.erase(eef.eef_group);
00105 }
00106
00107 void RobotInteraction::InteractionHandler::clearPoseOffset(const RobotInteraction::Joint& vj)
00108 {
00109 boost::mutex::scoped_lock slock(offset_map_lock_);
00110 offset_map_.erase(vj.joint_name);
00111 }
00112
00113 void RobotInteraction::InteractionHandler::clearPoseOffsets()
00114 {
00115 boost::mutex::scoped_lock slock(offset_map_lock_);
00116 offset_map_.clear();
00117 }
00118
00119 bool RobotInteraction::InteractionHandler::getPoseOffset(const RobotInteraction::EndEffector& eef, geometry_msgs::Pose& m)
00120 {
00121 boost::mutex::scoped_lock slock(offset_map_lock_);
00122 std::map<std::string, geometry_msgs::Pose>::iterator it = offset_map_.find(eef.eef_group);
00123 if (it != offset_map_.end())
00124 {
00125 m = it->second;
00126 return true;
00127 }
00128 return false;
00129 }
00130
00131 bool RobotInteraction::InteractionHandler::getPoseOffset(const RobotInteraction::Joint& vj, geometry_msgs::Pose& m)
00132 {
00133 boost::mutex::scoped_lock slock(offset_map_lock_);
00134 std::map<std::string, geometry_msgs::Pose>::iterator it = offset_map_.find(vj.joint_name);
00135 if (it != offset_map_.end())
00136 {
00137 m = it->second;
00138 return true;
00139 }
00140 return false;
00141 }
00142
00143 bool RobotInteraction::InteractionHandler::getLastEndEffectorMarkerPose(const RobotInteraction::EndEffector& eef, geometry_msgs::PoseStamped& ps)
00144 {
00145 boost::mutex::scoped_lock slock(pose_map_lock_);
00146 std::map<std::string, geometry_msgs::PoseStamped>::iterator it = pose_map_.find(eef.eef_group);
00147 if (it != pose_map_.end())
00148 {
00149 ps = it->second;
00150 return true;
00151 }
00152 return false;
00153 }
00154
00155 bool RobotInteraction::InteractionHandler::getLastJointMarkerPose(const RobotInteraction::Joint& vj, geometry_msgs::PoseStamped& ps)
00156 {
00157 boost::mutex::scoped_lock slock(pose_map_lock_);
00158 std::map<std::string, geometry_msgs::PoseStamped>::iterator it = pose_map_.find(vj.joint_name);
00159 if (it != pose_map_.end())
00160 {
00161 ps = it->second;
00162 return true;
00163 }
00164 return false;
00165 }
00166
00167 void RobotInteraction::InteractionHandler::clearLastEndEffectorMarkerPose(const RobotInteraction::EndEffector& eef)
00168 {
00169 boost::mutex::scoped_lock slock(pose_map_lock_);
00170 pose_map_.erase(eef.eef_group);
00171 }
00172
00173 void RobotInteraction::InteractionHandler::clearLastJointMarkerPose(const RobotInteraction::Joint& vj)
00174 {
00175 boost::mutex::scoped_lock slock(pose_map_lock_);
00176 pose_map_.erase(vj.joint_name);
00177 }
00178
00179 void RobotInteraction::InteractionHandler::clearLastMarkerPoses()
00180 {
00181 boost::mutex::scoped_lock slock(pose_map_lock_);
00182 pose_map_.clear();
00183 }
00184
00185 void RobotInteraction::InteractionHandler::setMenuHandler(const boost::shared_ptr<interactive_markers::MenuHandler>& mh)
00186 {
00187 menu_handler_ = mh;
00188 }
00189
00190 const boost::shared_ptr<interactive_markers::MenuHandler>& RobotInteraction::InteractionHandler::getMenuHandler()
00191 {
00192 return menu_handler_;
00193 }
00194
00195 void RobotInteraction::InteractionHandler::clearMenuHandler()
00196 {
00197 menu_handler_.reset();
00198 }
00199
00200 robot_state::RobotStateConstPtr RobotInteraction::InteractionHandler::getState() const
00201 {
00202 boost::unique_lock<boost::mutex> ulock(state_lock_);
00203 if (kstate_)
00204 return kstate_;
00205 else
00206 {
00207 do
00208 {
00209 state_available_condition_.wait(ulock);
00210 } while (!kstate_);
00211 return kstate_;
00212 }
00213 }
00214
00215 void RobotInteraction::InteractionHandler::setState(const robot_state::RobotState& kstate)
00216 {
00217 boost::unique_lock<boost::mutex> ulock(state_lock_);
00218 if (!kstate_)
00219 {
00220 do
00221 {
00222 state_available_condition_.wait(ulock);
00223 } while (!kstate_);
00224 }
00225 if (kstate_.unique())
00226 *kstate_ = kstate;
00227 else
00228 kstate_.reset(new robot_state::RobotState(kstate));
00229 }
00230
00231 robot_state::RobotStatePtr RobotInteraction::InteractionHandler::getUniqueStateAccess()
00232 {
00233 robot_state::RobotStatePtr result;
00234 {
00235 boost::unique_lock<boost::mutex> ulock(state_lock_);
00236 if (!kstate_)
00237 {
00238 do
00239 {
00240 state_available_condition_.wait(ulock);
00241 } while (!kstate_);
00242 }
00243 result.swap(kstate_);
00244 }
00245 if (!result.unique())
00246 result.reset(new robot_state::RobotState(*result));
00247 return result;
00248 }
00249
00250 void RobotInteraction::InteractionHandler::setStateToAccess(robot_state::RobotStatePtr &state)
00251 {
00252 boost::unique_lock<boost::mutex> ulock(state_lock_);
00253 if (state != kstate_)
00254 kstate_.swap(state);
00255 state_available_condition_.notify_all();
00256 }
00257
00258 void RobotInteraction::InteractionHandler::handleGeneric(const RobotInteraction::Generic &g, const visualization_msgs::InteractiveMarkerFeedbackConstPtr &feedback)
00259 {
00260 if (g.process_feedback)
00261 {
00262 robot_state::RobotStatePtr state = getUniqueStateAccess();
00263 bool ok = g.process_feedback(*state, feedback);
00264 setStateToAccess(state);
00265
00266 bool error_state_changed = false;
00267 if (!ok)
00268 {
00269 error_state_changed = inError(g) ? false : true;
00270 error_state_.insert(g.marker_name_suffix);
00271 }
00272 else
00273 {
00274 error_state_changed = inError(g) ? true : false;
00275 error_state_.erase(g.marker_name_suffix);
00276 }
00277
00278 if (update_callback_)
00279 update_callback_(this, error_state_changed);
00280 }
00281 }
00282
00283 void RobotInteraction::InteractionHandler::handleEndEffector(const robot_interaction::RobotInteraction::EndEffector &eef,
00284 const visualization_msgs::InteractiveMarkerFeedbackConstPtr &feedback)
00285 {
00286 if (feedback->event_type != visualization_msgs::InteractiveMarkerFeedback::POSE_UPDATE)
00287 return;
00288
00289 geometry_msgs::PoseStamped tpose;
00290 geometry_msgs::Pose offset;
00291 if (!getPoseOffset(eef, offset))
00292 offset.orientation.w = 1;
00293 if (transformFeedbackPose(feedback, offset, tpose))
00294 {
00295 pose_map_lock_.lock();
00296 pose_map_[eef.eef_group] = tpose;
00297 pose_map_lock_.unlock();
00298 }
00299 else
00300 return;
00301
00302 robot_state::RobotStatePtr state = getUniqueStateAccess();
00303 bool update_state_result = robot_interaction::RobotInteraction::updateState(*state, eef, tpose.pose, ik_attempts_, ik_timeout_, state_validity_callback_fn_, kinematics_query_options_);
00304 setStateToAccess(state);
00305
00306 bool error_state_changed = false;
00307 if (!update_state_result)
00308 {
00309 error_state_changed = inError(eef) ? false : true;
00310 error_state_.insert(eef.parent_group);
00311 }
00312 else
00313 {
00314 error_state_changed = inError(eef) ? true : false;
00315 error_state_.erase(eef.parent_group);
00316 }
00317
00318 if (update_callback_)
00319 update_callback_(this, error_state_changed);
00320 }
00321
00322 void RobotInteraction::InteractionHandler::handleJoint(const robot_interaction::RobotInteraction::Joint &vj,
00323 const visualization_msgs::InteractiveMarkerFeedbackConstPtr &feedback)
00324 {
00325 if (feedback->event_type != visualization_msgs::InteractiveMarkerFeedback::POSE_UPDATE)
00326 return;
00327
00328 geometry_msgs::PoseStamped tpose;
00329 geometry_msgs::Pose offset;
00330 if (!getPoseOffset(vj, offset))
00331 offset.orientation.w = 1;
00332 if (transformFeedbackPose(feedback, offset, tpose))
00333 {
00334 pose_map_lock_.lock();
00335 pose_map_[vj.joint_name] = tpose;
00336 pose_map_lock_.unlock();
00337 }
00338 else
00339 return;
00340
00341 if (!vj.parent_frame.empty() && !robot_state::Transforms::sameFrame(vj.parent_frame, planning_frame_))
00342 {
00343 robot_state::RobotStatePtr state = getUniqueStateAccess();
00344 const robot_state::LinkState *ls = state->getLinkState(vj.parent_frame);
00345 if (ls)
00346 {
00347 Eigen::Affine3d p;
00348 tf::poseMsgToEigen(tpose.pose, p);
00349 tf::poseEigenToMsg(ls->getGlobalLinkTransform().inverse() * p, tpose.pose);
00350 }
00351 robot_interaction::RobotInteraction::updateState(*state, vj, tpose.pose);
00352 setStateToAccess(state);
00353 }
00354 else
00355 {
00356 robot_state::RobotStatePtr state = getUniqueStateAccess();
00357 robot_interaction::RobotInteraction::updateState(*state, vj, tpose.pose);
00358 setStateToAccess(state);
00359 }
00360
00361 if (update_callback_)
00362 update_callback_(this, false);
00363 }
00364
00365 bool RobotInteraction::InteractionHandler::inError(const robot_interaction::RobotInteraction::EndEffector& eef) const
00366 {
00367 return error_state_.find(eef.parent_group) != error_state_.end();
00368 }
00369
00370 bool RobotInteraction::InteractionHandler::inError(const robot_interaction::RobotInteraction::Generic& g) const
00371 {
00372 return error_state_.find(g.marker_name_suffix) != error_state_.end();
00373 }
00374
00375 bool RobotInteraction::InteractionHandler::inError(const robot_interaction::RobotInteraction::Joint& vj) const
00376 {
00377 return false;
00378 }
00379
00380 void RobotInteraction::InteractionHandler::clearError(void)
00381 {
00382 error_state_.clear();
00383 }
00384
00385 bool RobotInteraction::InteractionHandler::transformFeedbackPose(const visualization_msgs::InteractiveMarkerFeedbackConstPtr &feedback,
00386 const geometry_msgs::Pose &offset,
00387 geometry_msgs::PoseStamped &tpose)
00388 {
00389 tpose.header = feedback->header;
00390 tpose.pose = feedback->pose;
00391 if (feedback->header.frame_id != planning_frame_)
00392 {
00393 if (tf_)
00394 try
00395 {
00396 tf::Stamped<tf::Pose> spose;
00397 tf::poseStampedMsgToTF(tpose, spose);
00398
00399 tf_->transformPose(planning_frame_, spose, spose);
00400
00401 tf::Transform tf_offset;
00402 tf::poseMsgToTF(offset, tf_offset);
00403 spose.setData(spose * tf_offset.inverse());
00404 tf::poseStampedTFToMsg(spose, tpose);
00405 }
00406 catch (tf::TransformException& e)
00407 {
00408 ROS_ERROR("Error transforming from frame '%s' to frame '%s'", tpose.header.frame_id.c_str(), planning_frame_.c_str());
00409 return false;
00410 }
00411 else
00412 {
00413 ROS_ERROR("Cannot transform from frame '%s' to frame '%s' (no TF instance provided)", tpose.header.frame_id.c_str(), planning_frame_.c_str());
00414 return false;
00415 }
00416 }
00417 return true;
00418 }
00419
00420 RobotInteraction::RobotInteraction(const robot_model::RobotModelConstPtr &robot_model, const std::string &ns) :
00421 robot_model_(robot_model)
00422 {
00423 topic_ = ns.empty() ? INTERACTIVE_MARKER_TOPIC : ns + "/" + INTERACTIVE_MARKER_TOPIC;
00424 int_marker_server_ = new interactive_markers::InteractiveMarkerServer(topic_);
00425
00426
00427 run_processing_thread_ = true;
00428 processing_thread_.reset(new boost::thread(boost::bind(&RobotInteraction::processingThread, this)));
00429 }
00430
00431 RobotInteraction::~RobotInteraction()
00432 {
00433 run_processing_thread_ = false;
00434 new_feedback_condition_.notify_all();
00435 processing_thread_->join();
00436
00437 clear();
00438 delete int_marker_server_;
00439 }
00440
00441 void RobotInteraction::decideActiveComponents(const std::string &group, EndEffectorInteractionStyle style)
00442 {
00443 decideActiveEndEffectors(group, style);
00444 decideActiveJoints(group);
00445 if (active_eef_.empty() && active_vj_.empty() && active_generic_.empty())
00446 ROS_INFO_NAMED("robot_interaction", "No active joints or end effectors found for group '%s'. Make sure you have defined an end effector in your SRDF file and that kinematics.yaml is loaded in this node's namespace.", group.c_str());
00447 }
00448
00449 void RobotInteraction::addActiveComponent(const InteractiveMarkerConstructorFn &construct,
00450 const ProcessFeedbackFn &process,
00451 const InteractiveMarkerUpdateFn &update,
00452 const std::string &name)
00453 {
00454 boost::unique_lock<boost::mutex> ulock(marker_access_lock_);
00455 Generic g;
00456 g.construct_marker = construct;
00457 g.update_pose = update;
00458 g.process_feedback = process;
00459
00460 g.marker_name_suffix = "_" + name + "_" + boost::lexical_cast<std::string>(active_generic_.size());
00461 active_generic_.push_back(g);
00462 }
00463
00464 double RobotInteraction::computeGroupMarkerSize(const std::string &group)
00465 {
00466 static const double DEFAULT_SCALE = 0.2;
00467 if (group.empty())
00468 return DEFAULT_SCALE;
00469 const robot_model::JointModelGroup *jmg = robot_model_->getJointModelGroup(group);
00470 if (!jmg)
00471 return 0.0;
00472
00473 const std::vector<std::string> &links = jmg->getLinkModelNames();
00474 if (links.empty())
00475 return DEFAULT_SCALE;
00476
00477
00478 const double inf = std::numeric_limits<double>::infinity();
00479 Eigen::Vector3d lo( inf, inf, inf);
00480 Eigen::Vector3d hi(-inf, -inf, -inf);
00481 robot_state::RobotState default_state(robot_model_);
00482 default_state.setToDefaultValues();
00483
00484 for (std::size_t i = 0 ; i < links.size() ; ++i)
00485 {
00486 robot_state::LinkState *ls = default_state.getLinkState(links[i]);
00487 if (!ls)
00488 continue;
00489 const Eigen::Vector3d &ext = ls->getLinkModel()->getShapeExtentsAtOrigin();
00490
00491 Eigen::Vector3d corner1 = ext/2.0;
00492 corner1 = ls->getGlobalLinkTransform() * corner1;
00493 Eigen::Vector3d corner2 = ext/-2.0;
00494 corner2 = ls->getGlobalLinkTransform() * corner2;
00495 lo = lo.cwiseMin(corner1);
00496 hi = hi.cwiseMax(corner2);
00497 }
00498
00499
00500 double s = std::max(std::max(hi.x() - lo.x(), hi.y() - lo.y()), hi.z() - lo.z());
00501 s *= 1.73205081;
00502
00503
00504 if (s < 1e-3)
00505 s = DEFAULT_SCALE;
00506 return s;
00507 }
00508
00509 void RobotInteraction::decideActiveJoints(const std::string &group)
00510 {
00511 boost::unique_lock<boost::mutex> ulock(marker_access_lock_);
00512 active_vj_.clear();
00513
00514 ROS_DEBUG_NAMED("robot_interaction", "Deciding active joints for group '%s'", group.c_str());
00515
00516 if (group.empty())
00517 return;
00518
00519 const boost::shared_ptr<const srdf::Model> &srdf = robot_model_->getSRDF();
00520 const robot_model::JointModelGroup *jmg = robot_model_->getJointModelGroup(group);
00521
00522 if (!jmg || !srdf)
00523 return;
00524
00525 std::set<std::string> used;
00526 if (jmg->hasJointModel(robot_model_->getRootJointName()))
00527 {
00528 robot_state::RobotState default_state(robot_model_);
00529 default_state.setToDefaultValues();
00530 std::vector<double> aabb;
00531 default_state.computeAABB(aabb);
00532
00533 const std::vector<srdf::Model::VirtualJoint> &vj = srdf->getVirtualJoints();
00534 for (std::size_t i = 0 ; i < vj.size() ; ++i)
00535 if (vj[i].name_ == robot_model_->getRootJointName())
00536 {
00537 if (vj[i].type_ == "planar" || vj[i].type_ == "floating")
00538 {
00539 Joint v;
00540 v.connecting_link = vj[i].child_link_;
00541 v.parent_frame = vj[i].parent_frame_;
00542 v.joint_name = vj[i].name_;
00543 if (vj[i].type_ == "planar")
00544 v.dof = 3;
00545 else
00546 v.dof = 6;
00547
00548 v.size = std::max(std::max(aabb[1] - aabb[0], aabb[3] - aabb[2]), aabb[5] - aabb[4]);
00549 active_vj_.push_back(v);
00550 used.insert(v.joint_name);
00551 }
00552 }
00553 }
00554
00555 const std::vector<const robot_model::JointModel*> &joints = jmg->getJointModels();
00556 for (std::size_t i = 0 ; i < joints.size() ; ++i)
00557 {
00558 if ((joints[i]->getType() == robot_model::JointModel::PLANAR || joints[i]->getType() == robot_model::JointModel::FLOATING) &&
00559 used.find(joints[i]->getName()) == used.end())
00560 {
00561 Joint v;
00562 v.connecting_link = joints[i]->getChildLinkModel()->getName();
00563 if (joints[i]->getParentLinkModel())
00564 v.parent_frame = joints[i]->getParentLinkModel()->getName();
00565 v.joint_name = joints[i]->getName();
00566 if (joints[i]->getType() == robot_model::JointModel::PLANAR)
00567 v.dof = 3;
00568 else
00569 v.dof = 6;
00570
00571 v.size = computeGroupMarkerSize(group);
00572 active_vj_.push_back(v);
00573 }
00574 }
00575 }
00576
00577 void RobotInteraction::decideActiveEndEffectors(const std::string &group, EndEffectorInteractionStyle style)
00578 {
00579 boost::unique_lock<boost::mutex> ulock(marker_access_lock_);
00580
00581 active_eef_.clear();
00582
00583 ROS_DEBUG_NAMED("robot_interaction", "Deciding active end-effectors for group '%s'", group.c_str());
00584
00585 if (group.empty())
00586 return;
00587
00588 const boost::shared_ptr<const srdf::Model> &srdf = robot_model_->getSRDF();
00589 const robot_model::JointModelGroup *jmg = robot_model_->getJointModelGroup(group);
00590
00591 if (!jmg || !srdf)
00592 {
00593 ROS_WARN_NAMED("robot_interaction", "Unable to decide active end effector: no joint model group or no srdf model");
00594 return;
00595 }
00596
00597 const std::vector<srdf::Model::EndEffector> &eef = srdf->getEndEffectors();
00598 const std::pair<robot_model::SolverAllocatorFn, robot_model::SolverAllocatorMapFn> &smap = jmg->getSolverAllocators();
00599
00600
00601 if (smap.first)
00602 {
00603 if (eef.empty() && !jmg->getLinkModelNames().empty())
00604 {
00605
00606 EndEffector ee;
00607 ee.parent_group = group;
00608 ee.parent_link = jmg->getLinkModelNames().back();
00609 ee.eef_group = group;
00610 ee.interaction = style;
00611 active_eef_.push_back(ee);
00612 }
00613 else
00614 for (std::size_t i = 0 ; i < eef.size() ; ++i)
00615 if ((jmg->hasLinkModel(eef[i].parent_link_) || jmg->getName() == eef[i].parent_group_) && jmg->canSetStateFromIK(eef[i].parent_link_))
00616 {
00617
00618 EndEffector ee;
00619 ee.parent_group = group;
00620 ee.parent_link = eef[i].parent_link_;
00621 ee.eef_group = eef[i].component_group_;
00622 ee.interaction = style;
00623 active_eef_.push_back(ee);
00624 break;
00625 }
00626 }
00627 else
00628 {
00629 if (!smap.second.empty())
00630 {
00631 for (std::map<const robot_model::JointModelGroup*, robot_model::SolverAllocatorFn>::const_iterator it = smap.second.begin() ;
00632 it != smap.second.end() ; ++it)
00633 {
00634 for (std::size_t i = 0 ; i < eef.size() ; ++i)
00635 if ((it->first->hasLinkModel(eef[i].parent_link_) || jmg->getName() == eef[i].parent_group_) && it->first->canSetStateFromIK(eef[i].parent_link_))
00636 {
00637
00638 EndEffector ee;
00639 ee.parent_group = it->first->getName();
00640 ee.parent_link = eef[i].parent_link_;
00641 ee.eef_group = eef[i].component_group_;
00642 ee.interaction = style;
00643 active_eef_.push_back(ee);
00644 break;
00645 }
00646 }
00647 }
00648 }
00649
00650 for (std::size_t i = 0 ; i < active_eef_.size() ; ++i)
00651 {
00652
00653 active_eef_[i].size = active_eef_[i].eef_group == active_eef_[i].parent_group ? computeGroupMarkerSize("") : computeGroupMarkerSize(active_eef_[i].eef_group);
00654 ROS_DEBUG_NAMED("robot_interaction", "Found active end-effector '%s', of scale %lf", active_eef_[i].eef_group.c_str(), active_eef_[i].size);
00655 }
00656 }
00657
00658 void RobotInteraction::clear()
00659 {
00660 boost::unique_lock<boost::mutex> ulock(marker_access_lock_);
00661 active_eef_.clear();
00662 active_vj_.clear();
00663 active_generic_.clear();
00664 clearInteractiveMarkersUnsafe();
00665 publishInteractiveMarkers();
00666 }
00667
00668 void RobotInteraction::clearInteractiveMarkers()
00669 {
00670 boost::unique_lock<boost::mutex> ulock(marker_access_lock_);
00671 clearInteractiveMarkersUnsafe();
00672 }
00673
00674 void RobotInteraction::clearInteractiveMarkersUnsafe()
00675 {
00676 handlers_.clear();
00677 shown_markers_.clear();
00678 int_marker_server_->clear();
00679 }
00680
00681 void RobotInteraction::addEndEffectorMarkers(const InteractionHandlerPtr &handler, const RobotInteraction::EndEffector& eef,
00682 visualization_msgs::InteractiveMarker& im,
00683 bool position,
00684 bool orientation)
00685 {
00686 geometry_msgs::Pose pose;
00687 pose.orientation.w = 1;
00688 addEndEffectorMarkers(handler, eef, pose, im, position, orientation);
00689 }
00690
00691 void RobotInteraction::addEndEffectorMarkers(const InteractionHandlerPtr &handler, const RobotInteraction::EndEffector& eef,
00692 const geometry_msgs::Pose& im_to_eef, visualization_msgs::InteractiveMarker& im,
00693 bool position,
00694 bool orientation)
00695 {
00696 if (eef.parent_group == eef.eef_group || !robot_model_->hasLinkModel(eef.parent_link))
00697 return;
00698
00699 visualization_msgs::InteractiveMarkerControl m_control;
00700 m_control.always_visible = false;
00701 if (position && orientation)
00702 m_control.interaction_mode = m_control.MOVE_ROTATE_3D;
00703 else if (orientation)
00704 m_control.interaction_mode = m_control.ROTATE_3D;
00705 else
00706 m_control.interaction_mode = m_control.MOVE_3D;
00707
00708 std_msgs::ColorRGBA marker_color;
00709 const float *color = handler->inError(eef) ? END_EFFECTOR_UNREACHABLE_COLOR : END_EFFECTOR_REACHABLE_COLOR;
00710 marker_color.r = color[0];
00711 marker_color.g = color[1];
00712 marker_color.b = color[2];
00713 marker_color.a = color[3];
00714
00715 robot_state::RobotStateConstPtr kinematic_state = handler->getState();
00716 const std::vector<std::string> &link_names = kinematic_state->getJointStateGroup(eef.eef_group)->getJointModelGroup()->getLinkModelNames();
00717 visualization_msgs::MarkerArray marker_array;
00718 kinematic_state->getRobotMarkers(marker_array, link_names, marker_color, eef.eef_group, ros::Duration());
00719 tf::Pose tf_root_to_link;
00720 tf::poseEigenToTF(kinematic_state->getLinkState(eef.parent_link)->getGlobalLinkTransform(), tf_root_to_link);
00721
00722 kinematic_state.reset();
00723
00724 for (std::size_t i = 0 ; i < marker_array.markers.size() ; ++i)
00725 {
00726 marker_array.markers[i].header = im.header;
00727 marker_array.markers[i].mesh_use_embedded_materials = true;
00728
00729 tf::Pose tf_root_to_im, tf_root_to_mesh, tf_im_to_eef;
00730 tf::poseMsgToTF(im.pose, tf_root_to_im);
00731 tf::poseMsgToTF(marker_array.markers[i].pose, tf_root_to_mesh);
00732 tf::poseMsgToTF(im_to_eef, tf_im_to_eef);
00733 tf::Pose tf_eef_to_mesh = tf_root_to_link.inverse() * tf_root_to_mesh;
00734 tf::Pose tf_im_to_mesh = tf_im_to_eef * tf_eef_to_mesh;
00735 tf::Pose tf_root_to_mesh_new = tf_root_to_im * tf_im_to_mesh;
00736 tf::poseTFToMsg(tf_root_to_mesh_new, marker_array.markers[i].pose);
00737
00738 m_control.markers.push_back(marker_array.markers[i]);
00739 }
00740
00741 im.controls.push_back(m_control);
00742 }
00743
00744 static inline std::string getMarkerName(const RobotInteraction::InteractionHandlerPtr &handler, const RobotInteraction::EndEffector &eef)
00745 {
00746 return "EE:" + handler->getName() + "_" + eef.parent_link;
00747 }
00748
00749 static inline std::string getMarkerName(const RobotInteraction::InteractionHandlerPtr &handler, const RobotInteraction::Joint &vj)
00750 {
00751 return "JJ:" + handler->getName() + "_" + vj.connecting_link;
00752 }
00753
00754 static inline std::string getMarkerName(const RobotInteraction::InteractionHandlerPtr &handler, const RobotInteraction::Generic &g)
00755 {
00756 return "GG:" + handler->getName() + "_" + g.marker_name_suffix;
00757 }
00758
00759 void RobotInteraction::addInteractiveMarkers(const InteractionHandlerPtr &handler, const double marker_scale)
00760 {
00761
00762 std::vector<visualization_msgs::InteractiveMarker> ims;
00763 {
00764 boost::unique_lock<boost::mutex> ulock(marker_access_lock_);
00765 robot_state::RobotStateConstPtr s = handler->getState();
00766
00767 for (std::size_t i = 0 ; i < active_generic_.size() ; ++i)
00768 {
00769 visualization_msgs::InteractiveMarker im;
00770 if (active_generic_[i].construct_marker(*s, im))
00771 {
00772 im.name = getMarkerName(handler, active_generic_[i]);
00773 shown_markers_[im.name] = i;
00774 ims.push_back(im);
00775 ROS_DEBUG_NAMED("robot_interaction", "Publishing interactive marker %s (size = %lf)", im.name.c_str(), im.scale);
00776 }
00777 }
00778
00779 for (std::size_t i = 0 ; i < active_eef_.size() ; ++i)
00780 {
00781 geometry_msgs::PoseStamped pose;
00782 geometry_msgs::Pose control_to_eef_tf;
00783 pose.header.frame_id = robot_model_->getModelFrame();
00784 pose.header.stamp = ros::Time::now();
00785 computeMarkerPose(handler, active_eef_[i], *s, pose.pose, control_to_eef_tf);
00786
00787 std::string marker_name = getMarkerName(handler, active_eef_[i]);
00788 shown_markers_[marker_name] = i;
00789
00790
00791 double mscale = marker_scale < std::numeric_limits<double>::epsilon() ? active_eef_[i].size : marker_scale;
00792
00793 visualization_msgs::InteractiveMarker im = makeEmptyInteractiveMarker(marker_name, pose, mscale);
00794 if (handler && handler->getControlsVisible())
00795 {
00796 if (active_eef_[i].interaction & EEF_POSITION_ARROWS)
00797 addPositionControl(im, active_eef_[i].interaction & EEF_FIXED);
00798 if (active_eef_[i].interaction & EEF_ORIENTATION_CIRCLES)
00799 addOrientationControl(im, active_eef_[i].interaction & EEF_FIXED);
00800 if (active_eef_[i].interaction & (EEF_POSITION_SPHERE|EEF_ORIENTATION_SPHERE))
00801 {
00802 std_msgs::ColorRGBA color;
00803 color.r = 0;
00804 color.g = 1;
00805 color.b = 1;
00806 color.a = 0.5;
00807 addViewPlaneControl(im,
00808 mscale * 0.25,
00809 color,
00810 active_eef_[i].interaction&EEF_POSITION_SPHERE,
00811 active_eef_[i].interaction&EEF_ORIENTATION_SPHERE);
00812 }
00813 }
00814 if (handler && handler->getMeshesVisible() && (active_eef_[i].interaction & (EEF_POSITION_EEF|EEF_ORIENTATION_EEF)))
00815 addEndEffectorMarkers(handler,
00816 active_eef_[i],
00817 control_to_eef_tf,
00818 im,
00819 active_eef_[i].interaction & EEF_POSITION_EEF,
00820 active_eef_[i].interaction & EEF_ORIENTATION_EEF);
00821 ims.push_back(im);
00822 ROS_DEBUG_NAMED("robot_interaction", "Publishing interactive marker %s (size = %lf)", marker_name.c_str(), mscale);
00823 }
00824 for (std::size_t i = 0 ; i < active_vj_.size() ; ++i)
00825 {
00826 geometry_msgs::PoseStamped pose;
00827 pose.header.frame_id = robot_model_->getModelFrame();
00828 pose.header.stamp = ros::Time::now();
00829 const robot_state::LinkState *ls = s->getLinkState(active_vj_[i].connecting_link);
00830 tf::poseEigenToMsg(ls->getGlobalLinkTransform(), pose.pose);
00831 std::string marker_name = getMarkerName(handler, active_vj_[i]);
00832 shown_markers_[marker_name] = i;
00833
00834
00835 double mscale = marker_scale < std::numeric_limits<double>::epsilon() ? active_vj_[i].size : marker_scale;
00836
00837 visualization_msgs::InteractiveMarker im = makeEmptyInteractiveMarker(marker_name, pose, mscale);
00838 if (handler && handler->getControlsVisible())
00839 {
00840 if (active_vj_[i].dof == 3)
00841 addPlanarXYControl(im, false);
00842 else
00843 add6DOFControl(im, false);
00844 }
00845 ims.push_back(im);
00846 ROS_DEBUG_NAMED("robot_interaction", "Publishing interactive marker %s (size = %lf)", marker_name.c_str(), mscale);
00847 }
00848 handlers_[handler->getName()] = handler;
00849 }
00850
00851
00852
00853
00854 for (std::size_t i = 0 ; i < ims.size() ; ++i)
00855 {
00856 int_marker_server_->insert(ims[i]);
00857 int_marker_server_->setCallback(ims[i].name, boost::bind(&RobotInteraction::processInteractiveMarkerFeedback, this, _1));
00858
00859
00860 if (boost::shared_ptr<interactive_markers::MenuHandler> mh = handler->getMenuHandler())
00861 mh->apply(*int_marker_server_, ims[i].name);
00862 }
00863 }
00864
00865 void RobotInteraction::computeMarkerPose(const InteractionHandlerPtr &handler, const EndEffector &eef, const robot_state::RobotState &robot_state,
00866 geometry_msgs::Pose &pose, geometry_msgs::Pose &control_to_eef_tf) const
00867 {
00868 const robot_state::LinkState *ls = robot_state.getLinkState(eef.parent_link);
00869
00870
00871 tf::Transform tf_root_to_link, tf_root_to_control;
00872 tf::poseEigenToTF(ls->getGlobalLinkTransform(), tf_root_to_link);
00873
00874 geometry_msgs::Pose msg_link_to_control;
00875 if (handler->getPoseOffset(eef, msg_link_to_control))
00876 {
00877 tf::Transform tf_link_to_control;
00878 tf::poseMsgToTF(msg_link_to_control, tf_link_to_control);
00879
00880 tf_root_to_control = tf_root_to_link * tf_link_to_control;
00881 tf::poseTFToMsg(tf_link_to_control.inverse(), control_to_eef_tf);
00882 }
00883 else
00884 {
00885 tf_root_to_control = tf_root_to_link;
00886 control_to_eef_tf.orientation.x = 0.0;
00887 control_to_eef_tf.orientation.y = 0.0;
00888 control_to_eef_tf.orientation.z = 0.0;
00889 control_to_eef_tf.orientation.w = 1.0;
00890 }
00891
00892 tf::poseTFToMsg(tf_root_to_control, pose);
00893 }
00894
00895 void RobotInteraction::updateInteractiveMarkers(const InteractionHandlerPtr &handler)
00896 {
00897 std::map<std::string, geometry_msgs::Pose> pose_updates;
00898 {
00899 boost::unique_lock<boost::mutex> ulock(marker_access_lock_);
00900
00901 robot_state::RobotStateConstPtr s = handler->getState();
00902 for (std::size_t i = 0 ; i < active_eef_.size() ; ++i)
00903 {
00904 std::string marker_name = getMarkerName(handler, active_eef_[i]);
00905 geometry_msgs::Pose control_to_eef_tf;
00906 computeMarkerPose(handler, active_eef_[i], *s, pose_updates[marker_name], control_to_eef_tf);
00907 }
00908
00909 for (std::size_t i = 0 ; i < active_vj_.size() ; ++i)
00910 {
00911 std::string marker_name = getMarkerName(handler, active_vj_[i]);
00912 const robot_state::LinkState *ls = s->getLinkState(active_vj_[i].connecting_link);
00913 tf::poseEigenToMsg(ls->getGlobalLinkTransform(), pose_updates[marker_name]);
00914 }
00915
00916 for (std::size_t i = 0 ; i < active_generic_.size() ; ++i)
00917 {
00918 std::string marker_name = getMarkerName(handler, active_generic_[i]);
00919 geometry_msgs::Pose pose;
00920 if (active_generic_[i].update_pose && active_generic_[i].update_pose(*s, pose))
00921 pose_updates[marker_name] = pose;
00922 }
00923 }
00924 for (std::map<std::string, geometry_msgs::Pose>::const_iterator it = pose_updates.begin() ; it != pose_updates.end() ; ++it)
00925 int_marker_server_->setPose(it->first, it->second);
00926 int_marker_server_->applyChanges();
00927 }
00928
00929 void RobotInteraction::publishInteractiveMarkers()
00930 {
00931
00932 int_marker_server_->applyChanges();
00933 }
00934
00935 bool RobotInteraction::showingMarkers(const InteractionHandlerPtr &handler)
00936 {
00937 boost::unique_lock<boost::mutex> ulock(marker_access_lock_);
00938
00939 for (std::size_t i = 0 ; i < active_eef_.size() ; ++i)
00940 if (shown_markers_.find(getMarkerName(handler, active_eef_[i])) == shown_markers_.end())
00941 return false;
00942 for (std::size_t i = 0 ; i < active_vj_.size() ; ++i)
00943 if (shown_markers_.find(getMarkerName(handler, active_vj_[i])) == shown_markers_.end())
00944 return false;
00945 for (std::size_t i = 0 ; i < active_generic_.size() ; ++i)
00946 if (shown_markers_.find(getMarkerName(handler, active_generic_[i])) == shown_markers_.end())
00947 return false;
00948 return true;
00949 }
00950
00951 bool RobotInteraction::updateState(robot_state::RobotState &state, const Joint &vj, const geometry_msgs::Pose &pose)
00952 {
00953 Eigen::Quaterniond q;
00954 tf::quaternionMsgToEigen(pose.orientation, q);
00955 std::map<std::string, double> vals;
00956 if (vj.dof == 3)
00957 {
00958 vals[vj.joint_name + "/x"] = pose.position.x;
00959 vals[vj.joint_name + "/y"] = pose.position.y;
00960 Eigen::Vector3d xyz = q.matrix().eulerAngles(0, 1, 2);
00961 vals[vj.joint_name + "/theta"] = xyz[2];
00962 }
00963 else
00964 if (vj.dof == 6)
00965 {
00966 vals[vj.joint_name + "/trans_x"] = pose.position.x;
00967 vals[vj.joint_name + "/trans_y"] = pose.position.y;
00968 vals[vj.joint_name + "/trans_z"] = pose.position.z;
00969 vals[vj.joint_name + "/rot_x"] = q.x();
00970 vals[vj.joint_name + "/rot_y"] = q.y();
00971 vals[vj.joint_name + "/rot_z"] = q.z();
00972 vals[vj.joint_name + "/rot_w"] = q.w();
00973 }
00974 state.getJointState(vj.joint_name)->setVariableValues(vals);
00975 state.updateLinkTransforms();
00976 return true;
00977 }
00978
00979 bool RobotInteraction::updateState(robot_state::RobotState &state, const EndEffector &eef, const geometry_msgs::Pose &pose,
00980 unsigned int attempts, double ik_timeout,
00981 const robot_state::StateValidityCallbackFn &validity_callback,
00982 const kinematics::KinematicsQueryOptions &kinematics_query_options)
00983 {
00984 return state.getJointStateGroup(eef.parent_group)->setFromIK(pose, eef.parent_link, kinematics_query_options.lock_redundant_joints ? 1 : attempts,
00985 ik_timeout, validity_callback, kinematics_query_options);
00986 }
00987
00988 void RobotInteraction::processInteractiveMarkerFeedback(const visualization_msgs::InteractiveMarkerFeedbackConstPtr& feedback)
00989 {
00990
00991 boost::unique_lock<boost::mutex> ulock(marker_access_lock_);
00992 std::map<std::string, std::size_t>::const_iterator it = shown_markers_.find(feedback->marker_name);
00993 if (it == shown_markers_.end())
00994 {
00995 ROS_ERROR("Unknown marker name: '%s' (not published by RobotInteraction class)", feedback->marker_name.c_str());
00996 return;
00997 }
00998
00999 std::size_t u = feedback->marker_name.find_first_of("_");
01000 if (u == std::string::npos || u < 4)
01001 {
01002 ROS_ERROR("Invalid marker name: '%s'", feedback->marker_name.c_str());
01003 return;
01004 }
01005
01006 feedback_map_[feedback->marker_name] = feedback;
01007 new_feedback_condition_.notify_all();
01008 }
01009
01010 void RobotInteraction::processingThread()
01011 {
01012 boost::unique_lock<boost::mutex> ulock(marker_access_lock_);
01013
01014 while (run_processing_thread_ && ros::ok())
01015 {
01016 while (feedback_map_.empty() && run_processing_thread_ && ros::ok())
01017 new_feedback_condition_.wait(ulock);
01018
01019 while (!feedback_map_.empty() && ros::ok())
01020 {
01021 visualization_msgs::InteractiveMarkerFeedbackConstPtr feedback = feedback_map_.begin()->second;
01022 feedback_map_.erase(feedback_map_.begin());
01023 ROS_DEBUG_NAMED("robot_interaction", "Processing feedback from map for marker [%s]", feedback->marker_name.c_str());
01024
01025 std::map<std::string, std::size_t>::const_iterator it = shown_markers_.find(feedback->marker_name);
01026 if (it == shown_markers_.end())
01027 {
01028 ROS_ERROR("Unknown marker name: '%s' (not published by RobotInteraction class) (should never have ended up in the feedback_map!)", feedback->marker_name.c_str());
01029 continue;
01030 }
01031 std::size_t u = feedback->marker_name.find_first_of("_");
01032 if (u == std::string::npos || u < 4)
01033 {
01034 ROS_ERROR("Invalid marker name: '%s' (should never have ended up in the feedback_map!)", feedback->marker_name.c_str());
01035 continue;
01036 }
01037 std::string marker_class = feedback->marker_name.substr(0, 2);
01038 std::string handler_name = feedback->marker_name.substr(3, u - 3);
01039 std::map<std::string, InteractionHandlerPtr>::const_iterator jt = handlers_.find(handler_name);
01040 if (jt == handlers_.end())
01041 {
01042 ROS_ERROR("Interactive Marker Handler '%s' is not known.", handler_name.c_str());
01043 continue;
01044 }
01045
01046
01047 try
01048 {
01049 if (marker_class == "EE")
01050 {
01051
01052 EndEffector eef = active_eef_[it->second];
01053 InteractionHandlerPtr ih = jt->second;
01054 marker_access_lock_.unlock();
01055 try
01056 {
01057 ih->handleEndEffector(eef, feedback);
01058 }
01059 catch(std::runtime_error &ex)
01060 {
01061 ROS_ERROR("Exception caught while handling end-effector update: %s", ex.what());
01062 }
01063 catch(...)
01064 {
01065 ROS_ERROR("Exception caught while handling end-effector update");
01066 }
01067 marker_access_lock_.lock();
01068 }
01069 else
01070 if (marker_class == "JJ")
01071 {
01072
01073 Joint vj = active_vj_[it->second];
01074 InteractionHandlerPtr ih = jt->second;
01075 marker_access_lock_.unlock();
01076 try
01077 {
01078 ih->handleJoint(vj, feedback);
01079 }
01080 catch(std::runtime_error &ex)
01081 {
01082 ROS_ERROR("Exception caught while handling joint update: %s", ex.what());
01083 }
01084 catch(...)
01085 {
01086 ROS_ERROR("Exception caught while handling joint update");
01087 }
01088 marker_access_lock_.lock();
01089 }
01090 else
01091 if (marker_class == "GG")
01092 {
01093 InteractionHandlerPtr ih = jt->second;
01094 Generic g = active_generic_[it->second];
01095 marker_access_lock_.unlock();
01096 try
01097 {
01098 ih->handleGeneric(g, feedback);
01099 }
01100 catch(std::runtime_error &ex)
01101 {
01102 ROS_ERROR("Exception caught while handling joint update: %s", ex.what());
01103 }
01104 catch(...)
01105 {
01106 ROS_ERROR("Exception caught while handling joint update");
01107 }
01108 marker_access_lock_.lock();
01109 }
01110 else
01111 ROS_ERROR("Unknown marker class ('%s') for marker '%s'", marker_class.c_str(), feedback->marker_name.c_str());
01112 }
01113 catch (std::runtime_error &ex)
01114 {
01115 ROS_ERROR("Exception caught while processing event: %s", ex.what());
01116 }
01117 catch (...)
01118 {
01119 ROS_ERROR("Exception caught while processing event");
01120 }
01121 }
01122 }
01123 }
01124
01125 }