robot_interaction.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2012, Willow Garage, Inc.
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are met:
00007  *
00008  *     * Redistributions of source code must retain the above copyright
00009  *       notice, this list of conditions and the following disclaimer.
00010  *     * Redistributions in binary form must reproduce the above copyright
00011  *       notice, this list of conditions and the following disclaimer in the
00012  *       documentation and/or other materials provided with the distribution.
00013  *     * Neither the name of the Willow Garage, Inc. nor the names of its
00014  *       contributors may be used to endorse or promote products derived from
00015  *       this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00018  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00021  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00022  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00023  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00024  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00025  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00026  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00027  * POSSIBILITY OF SUCH DAMAGE.
00028  */
00029 
00030 /* Author: Ioan Sucan, Adam Leeper */
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(), '_', '-'); // we use _ as a special char in marker name
00084   ik_timeout_ = 0.0; // so that the default IK timeout is used in setFromIK()
00085   ik_attempts_ = 0; // so that the default IK attempts is used in setFromIK()
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         // Express feedback (marker) pose in planning frame
00399         tf_->transformPose(planning_frame_, spose, spose);
00400         // Apply inverse of offset to bring feedback pose back into the end-effector support link frame
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   // spin a thread that will process feedback events
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   // compute the suffix that will be added to the generated markers
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   // compute the aabb of the links that make up the group
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   // slightly bigger than the size of the largest end effector dimension
00500   double s = std::max(std::max(hi.x() - lo.x(), hi.y() - lo.y()), hi.z() - lo.z());
00501   s *= 1.73205081; // sqrt(3)
00502 
00503   // if the scale is less than 1mm, set it to default
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           // take the max of the X, Y, Z extent
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       // take the max of the X, Y, Z extent
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   // if we have an IK solver for the selected group, we check if there are any end effectors attached to this group
00601   if (smap.first)
00602   {
00603     if (eef.empty() && !jmg->getLinkModelNames().empty())
00604     {
00605       // No end effectors.  Use last link in group as the "end effector".
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           // We found an end-effector whose parent is the group.
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             // We found an end-effector whose parent is a subgroup of the group.  (May be more than one)
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     // if we have a separate group for the eef, we compte the scale based on it; otherwise, we use a default scale
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   // Release the ptr count on the kinematic state
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     // - - - - - - Do some math for the offset - - - - - -
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   // If scale is left at default size of 0, scale will be based on end effector link size. a good value is between 0-1
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       // Determine interactive maker size
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       // Determine interactive maker size
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) // planar joint
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   // we do this while marker_access_lock_ is unlocked because the interactive marker server locks
00852   // for most function calls, and maintains that lock while the feedback callback is running
00853   // that can cause a deadlock if we were to run the loop below while marker_access_lock_ is locked
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     // Add menu handler to all markers that this interaction handler creates.
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   // Need to allow for control pose offsets
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   // the server locks internally, so we need not worry about locking
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   // perform some validity checks
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); // skip the ":"
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       // we put this in a try-catch because user specified callbacks may be triggered
01047       try
01048       {
01049         if (marker_class == "EE")
01050         {
01051           // make a copy of the data, so we do not lose it while we are unlocked
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             // make a copy of the data, so we do not lose it while we are unlocked
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 }


robot_interaction
Author(s): Ioan Sucan
autogenerated on Mon Oct 6 2014 02:33:46