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
00033
00034
00035
00036
00037
00038 #include <moveit/robot_interaction/interaction_handler.h>
00039 #include <moveit/robot_interaction/robot_interaction.h>
00040 #include <moveit/robot_interaction/interactive_marker_helpers.h>
00041 #include <moveit/robot_interaction/kinematic_options_map.h>
00042 #include <moveit/transforms/transforms.h>
00043 #include <interactive_markers/interactive_marker_server.h>
00044 #include <interactive_markers/menu_handler.h>
00045 #include <eigen_conversions/eigen_msg.h>
00046 #include <tf_conversions/tf_eigen.h>
00047 #include <boost/lexical_cast.hpp>
00048 #include <boost/math/constants/constants.hpp>
00049 #include <algorithm>
00050 #include <limits>
00051
00052 #include <Eigen/Core>
00053 #include <Eigen/Geometry>
00054
00055 namespace robot_interaction
00056 {
00057
00058 InteractionHandler::InteractionHandler(
00059 const RobotInteractionPtr& robot_interaction,
00060 const std::string &name,
00061 const robot_state::RobotState &initial_robot_state,
00062 const boost::shared_ptr<tf::Transformer> &tf)
00063 :LockedRobotState(initial_robot_state)
00064 ,name_(fixName(name))
00065 ,planning_frame_(initial_robot_state.getRobotModel()->getModelFrame())
00066 ,tf_(tf)
00067 ,robot_interaction_(NULL)
00068 ,kinematic_options_map_(robot_interaction->getKinematicOptionsMap())
00069 ,display_meshes_(true)
00070 ,display_controls_(true)
00071 {
00072 setRobotInteraction(robot_interaction.get());
00073 }
00074
00075 InteractionHandler::InteractionHandler(
00076 const RobotInteractionPtr& robot_interaction,
00077 const std::string &name,
00078 const boost::shared_ptr<tf::Transformer> &tf)
00079 :LockedRobotState(robot_interaction->getRobotModel())
00080 ,name_(fixName(name))
00081 ,planning_frame_(robot_interaction->getRobotModel()->getModelFrame())
00082 ,tf_(tf)
00083 ,robot_interaction_(NULL)
00084 ,kinematic_options_map_(robot_interaction->getKinematicOptionsMap())
00085 ,display_meshes_(true)
00086 ,display_controls_(true)
00087 {
00088 setRobotInteraction(robot_interaction.get());
00089 }
00090
00091
00092 InteractionHandler::InteractionHandler(
00093 const std::string &name,
00094 const robot_state::RobotState &initial_robot_state,
00095 const boost::shared_ptr<tf::Transformer> &tf)
00096 :LockedRobotState(initial_robot_state)
00097 ,name_(fixName(name))
00098 ,planning_frame_(initial_robot_state.getRobotModel()->getModelFrame())
00099 ,tf_(tf)
00100 ,robot_interaction_(NULL)
00101 ,kinematic_options_map_(new KinematicOptionsMap)
00102 ,display_meshes_(true)
00103 ,display_controls_(true)
00104 {
00105 }
00106
00107
00108 InteractionHandler::InteractionHandler(
00109 const std::string &name,
00110 const robot_model::RobotModelConstPtr &robot_model,
00111 const boost::shared_ptr<tf::Transformer> &tf)
00112 :LockedRobotState(robot_model)
00113 ,name_(fixName(name))
00114 ,planning_frame_(robot_model->getModelFrame())
00115 ,tf_(tf)
00116 ,robot_interaction_(NULL)
00117 ,kinematic_options_map_(new KinematicOptionsMap)
00118 ,display_meshes_(true)
00119 ,display_controls_(true)
00120 {
00121 }
00122
00123 std::string InteractionHandler::fixName(std::string name)
00124 {
00125 std::replace(name.begin(), name.end(), '_', '-');
00126 return name;
00127 }
00128
00129 void InteractionHandler::setPoseOffset(const EndEffectorInteraction& eef, const geometry_msgs::Pose& m)
00130 {
00131 boost::mutex::scoped_lock slock(offset_map_lock_);
00132 offset_map_[eef.eef_group] = m;
00133 }
00134
00135 void InteractionHandler::setPoseOffset(const JointInteraction& vj, const geometry_msgs::Pose& m)
00136 {
00137 boost::mutex::scoped_lock slock(offset_map_lock_);
00138 offset_map_[vj.joint_name] = m;
00139 }
00140
00141 void InteractionHandler::clearPoseOffset(const EndEffectorInteraction& eef)
00142 {
00143 boost::mutex::scoped_lock slock(offset_map_lock_);
00144 offset_map_.erase(eef.eef_group);
00145 }
00146
00147 void InteractionHandler::clearPoseOffset(const JointInteraction& vj)
00148 {
00149 boost::mutex::scoped_lock slock(offset_map_lock_);
00150 offset_map_.erase(vj.joint_name);
00151 }
00152
00153 void InteractionHandler::clearPoseOffsets()
00154 {
00155 boost::mutex::scoped_lock slock(offset_map_lock_);
00156 offset_map_.clear();
00157 }
00158
00159 bool InteractionHandler::getPoseOffset(const EndEffectorInteraction& eef, geometry_msgs::Pose& m)
00160 {
00161 boost::mutex::scoped_lock slock(offset_map_lock_);
00162 std::map<std::string, geometry_msgs::Pose>::iterator it = offset_map_.find(eef.eef_group);
00163 if (it != offset_map_.end())
00164 {
00165 m = it->second;
00166 return true;
00167 }
00168 return false;
00169 }
00170
00171 bool InteractionHandler::getPoseOffset(const JointInteraction& vj, geometry_msgs::Pose& m)
00172 {
00173 boost::mutex::scoped_lock slock(offset_map_lock_);
00174 std::map<std::string, geometry_msgs::Pose>::iterator it = offset_map_.find(vj.joint_name);
00175 if (it != offset_map_.end())
00176 {
00177 m = it->second;
00178 return true;
00179 }
00180 return false;
00181 }
00182
00183 bool InteractionHandler::getLastEndEffectorMarkerPose(const EndEffectorInteraction& eef, geometry_msgs::PoseStamped& ps)
00184 {
00185 boost::mutex::scoped_lock slock(pose_map_lock_);
00186 std::map<std::string, geometry_msgs::PoseStamped>::iterator it = pose_map_.find(eef.eef_group);
00187 if (it != pose_map_.end())
00188 {
00189 ps = it->second;
00190 return true;
00191 }
00192 return false;
00193 }
00194
00195 bool InteractionHandler::getLastJointMarkerPose(const JointInteraction& vj, geometry_msgs::PoseStamped& ps)
00196 {
00197 boost::mutex::scoped_lock slock(pose_map_lock_);
00198 std::map<std::string, geometry_msgs::PoseStamped>::iterator it = pose_map_.find(vj.joint_name);
00199 if (it != pose_map_.end())
00200 {
00201 ps = it->second;
00202 return true;
00203 }
00204 return false;
00205 }
00206
00207 void InteractionHandler::clearLastEndEffectorMarkerPose(const EndEffectorInteraction& eef)
00208 {
00209 boost::mutex::scoped_lock slock(pose_map_lock_);
00210 pose_map_.erase(eef.eef_group);
00211 }
00212
00213 void InteractionHandler::clearLastJointMarkerPose(const JointInteraction& vj)
00214 {
00215 boost::mutex::scoped_lock slock(pose_map_lock_);
00216 pose_map_.erase(vj.joint_name);
00217 }
00218
00219 void InteractionHandler::clearLastMarkerPoses()
00220 {
00221 boost::mutex::scoped_lock slock(pose_map_lock_);
00222 pose_map_.clear();
00223 }
00224
00225 void InteractionHandler::setMenuHandler(const boost::shared_ptr<interactive_markers::MenuHandler>& mh)
00226 {
00227 boost::mutex::scoped_lock lock(state_lock_);
00228 menu_handler_ = mh;
00229 }
00230
00231 const boost::shared_ptr<interactive_markers::MenuHandler>& InteractionHandler::getMenuHandler()
00232 {
00233 boost::mutex::scoped_lock lock(state_lock_);
00234 return menu_handler_;
00235 }
00236
00237 void InteractionHandler::clearMenuHandler()
00238 {
00239 boost::mutex::scoped_lock lock(state_lock_);
00240 menu_handler_.reset();
00241 }
00242
00243
00244 void InteractionHandler::handleGeneric(
00245 const GenericInteraction &g,
00246 const visualization_msgs::InteractiveMarkerFeedbackConstPtr &feedback)
00247 {
00248 if (g.process_feedback)
00249 {
00250 StateChangeCallbackFn callback;
00251
00252 LockedRobotState::modifyState(boost::bind(&InteractionHandler::updateStateGeneric,
00253 this,
00254 _1,
00255 &g,
00256 &feedback,
00257 &callback));
00258
00259
00260 if (callback)
00261 callback(this);
00262 }
00263 }
00264
00265 void InteractionHandler::handleEndEffector(
00266 const EndEffectorInteraction &eef,
00267 const visualization_msgs::InteractiveMarkerFeedbackConstPtr &feedback)
00268 {
00269 if (feedback->event_type != visualization_msgs::InteractiveMarkerFeedback::POSE_UPDATE)
00270 return;
00271
00272 geometry_msgs::PoseStamped tpose;
00273 geometry_msgs::Pose offset;
00274 if (!getPoseOffset(eef, offset))
00275 offset.orientation.w = 1;
00276 if (transformFeedbackPose(feedback, offset, tpose))
00277 {
00278 pose_map_lock_.lock();
00279 pose_map_[eef.eef_group] = tpose;
00280 pose_map_lock_.unlock();
00281 }
00282 else
00283 return;
00284
00285 StateChangeCallbackFn callback;
00286
00287
00288
00289 LockedRobotState::modifyState(boost::bind(&InteractionHandler::updateStateEndEffector,
00290 this,
00291 _1,
00292 &eef,
00293 &tpose.pose,
00294 &callback));
00295
00296
00297 if (callback)
00298 callback(this);
00299 }
00300
00301 void InteractionHandler::handleJoint(
00302 const JointInteraction &vj,
00303 const visualization_msgs::InteractiveMarkerFeedbackConstPtr &feedback)
00304 {
00305 if (feedback->event_type != visualization_msgs::InteractiveMarkerFeedback::POSE_UPDATE)
00306 return;
00307
00308 geometry_msgs::PoseStamped tpose;
00309 geometry_msgs::Pose offset;
00310 if (!getPoseOffset(vj, offset))
00311 offset.orientation.w = 1;
00312 if (transformFeedbackPose(feedback, offset, tpose))
00313 {
00314 pose_map_lock_.lock();
00315 pose_map_[vj.joint_name] = tpose;
00316 pose_map_lock_.unlock();
00317 }
00318 else
00319 return;
00320
00321 StateChangeCallbackFn callback;
00322
00323
00324
00325 LockedRobotState::modifyState(boost::bind(&InteractionHandler::updateStateJoint,
00326 this,
00327 _1,
00328 &vj,
00329 &tpose.pose,
00330 &callback));
00331
00332
00333 if (callback)
00334 callback(this);
00335 }
00336
00337
00338 void InteractionHandler::updateStateGeneric(
00339 robot_state::RobotState* state,
00340 const GenericInteraction *g,
00341 const visualization_msgs::InteractiveMarkerFeedbackConstPtr *feedback,
00342 StateChangeCallbackFn *callback)
00343 {
00344 bool ok = g->process_feedback(*state, *feedback);
00345 bool error_state_changed = setErrorState(g->marker_name_suffix, !ok);
00346 if (update_callback_)
00347 *callback = boost::bind(update_callback_,
00348 _1,
00349 error_state_changed);
00350 }
00351
00352
00353 void InteractionHandler::updateStateEndEffector(
00354 robot_state::RobotState* state,
00355 const EndEffectorInteraction* eef,
00356 const geometry_msgs::Pose* pose,
00357 StateChangeCallbackFn *callback)
00358 {
00359
00360
00361 KinematicOptions kinematic_options = kinematic_options_map_->getOptions(eef->parent_group);
00362
00363 bool ok = kinematic_options.setStateFromIK(*state,
00364 eef->parent_group,
00365 eef->parent_link,
00366 *pose);
00367 bool error_state_changed = setErrorState(eef->parent_group, !ok);
00368 if (update_callback_)
00369 *callback = boost::bind(update_callback_,
00370 _1,
00371 error_state_changed);
00372 }
00373
00374
00375 void InteractionHandler::updateStateJoint(
00376 robot_state::RobotState* state,
00377 const JointInteraction* vj,
00378 const geometry_msgs::Pose* feedback_pose,
00379 StateChangeCallbackFn *callback)
00380 {
00381 geometry_msgs::Pose rel_pose = *feedback_pose;
00382 if (!vj->parent_frame.empty() && !robot_state::Transforms::sameFrame(vj->parent_frame, planning_frame_))
00383 {
00384 Eigen::Affine3d p;
00385 tf::poseMsgToEigen(rel_pose, p);
00386 tf::poseEigenToMsg(state->getGlobalLinkTransform(vj->parent_frame).inverse() * p, rel_pose);
00387 }
00388
00389 Eigen::Quaterniond q;
00390 tf::quaternionMsgToEigen(rel_pose.orientation, q);
00391 std::map<std::string, double> vals;
00392 if (vj->dof == 3)
00393 {
00394 vals[vj->joint_name + "/x"] = rel_pose.position.x;
00395 vals[vj->joint_name + "/y"] = rel_pose.position.y;
00396 Eigen::Vector3d xyz = q.matrix().eulerAngles(0, 1, 2);
00397 vals[vj->joint_name + "/theta"] = xyz[2];
00398 }
00399 else
00400 if (vj->dof == 6)
00401 {
00402 vals[vj->joint_name + "/trans_x"] = rel_pose.position.x;
00403 vals[vj->joint_name + "/trans_y"] = rel_pose.position.y;
00404 vals[vj->joint_name + "/trans_z"] = rel_pose.position.z;
00405 vals[vj->joint_name + "/rot_x"] = q.x();
00406 vals[vj->joint_name + "/rot_y"] = q.y();
00407 vals[vj->joint_name + "/rot_z"] = q.z();
00408 vals[vj->joint_name + "/rot_w"] = q.w();
00409 }
00410 state->setVariablePositions(vals);
00411 state->update();
00412
00413 if (update_callback_)
00414 *callback = boost::bind(update_callback_,
00415 _1,
00416 false);
00417 }
00418
00419 bool InteractionHandler::inError(const EndEffectorInteraction& eef) const
00420 {
00421 return getErrorState(eef.parent_group);
00422 }
00423
00424 bool InteractionHandler::inError(const GenericInteraction& g) const
00425 {
00426 return getErrorState(g.marker_name_suffix);
00427 }
00428
00429 bool InteractionHandler::inError(const JointInteraction& vj) const
00430 {
00431 return false;
00432 }
00433
00434 void InteractionHandler::clearError(void)
00435 {
00436 boost::mutex::scoped_lock lock(state_lock_);
00437 error_state_.clear();
00438 }
00439
00440
00441
00442 bool InteractionHandler::setErrorState(const std::string& name, bool new_error_state)
00443 {
00444 bool old_error_state = error_state_.find(name) != error_state_.end();
00445
00446 if (new_error_state == old_error_state)
00447 return false;
00448
00449 if (new_error_state)
00450 error_state_.insert(name);
00451 else
00452 error_state_.erase(name);
00453
00454 return true;
00455 }
00456
00457 bool InteractionHandler::getErrorState(const std::string& name) const
00458 {
00459 boost::mutex::scoped_lock lock(state_lock_);
00460 return error_state_.find(name) != error_state_.end();
00461
00462 }
00463
00464 bool InteractionHandler::transformFeedbackPose(const visualization_msgs::InteractiveMarkerFeedbackConstPtr &feedback,
00465 const geometry_msgs::Pose &offset,
00466 geometry_msgs::PoseStamped &tpose)
00467 {
00468 tpose.header = feedback->header;
00469 tpose.pose = feedback->pose;
00470 if (feedback->header.frame_id != planning_frame_)
00471 {
00472 if (tf_)
00473 try
00474 {
00475 tf::Stamped<tf::Pose> spose;
00476 tf::poseStampedMsgToTF(tpose, spose);
00477
00478 tf_->transformPose(planning_frame_, spose, spose);
00479
00480 tf::Transform tf_offset;
00481 tf::poseMsgToTF(offset, tf_offset);
00482 spose.setData(spose * tf_offset.inverse());
00483 tf::poseStampedTFToMsg(spose, tpose);
00484 }
00485 catch (tf::TransformException& e)
00486 {
00487 ROS_ERROR("Error transforming from frame '%s' to frame '%s'",
00488 tpose.header.frame_id.c_str(),
00489 planning_frame_.c_str());
00490 return false;
00491 }
00492 else
00493 {
00494 ROS_ERROR("Cannot transform from frame '%s' to frame '%s' (no TF instance provided)",
00495 tpose.header.frame_id.c_str(),
00496 planning_frame_.c_str());
00497 return false;
00498 }
00499 }
00500 return true;
00501 }
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513 void InteractionHandler::setRobotInteraction(RobotInteraction* robot_interaction)
00514 {
00515 boost::mutex::scoped_lock lock(state_lock_);
00516
00517
00518
00519
00520 if (robot_interaction_)
00521 {
00522 if (robot_interaction_ != robot_interaction)
00523 {
00524 ROS_ERROR("setKinematicOptions() called from 2 different RobotInteraction instances.");
00525 }
00526 return;
00527 }
00528
00529 robot_interaction_ = robot_interaction;
00530
00531 KinematicOptionsMapPtr shared_kinematic_options_map = robot_interaction->getKinematicOptionsMap();
00532
00533
00534
00535
00536
00537
00538
00539 shared_kinematic_options_map->merge(*kinematic_options_map_);
00540
00541
00542
00543
00544
00545
00546 kinematic_options_map_ = shared_kinematic_options_map;
00547 }
00548
00549
00550
00551
00552 void InteractionHandler::setIKTimeout(double timeout)
00553 {
00554 KinematicOptions delta;
00555 delta.timeout_seconds_ = timeout;
00556
00557 boost::mutex::scoped_lock lock(state_lock_);
00558 kinematic_options_map_->setOptions(KinematicOptionsMap::ALL,
00559 delta,
00560 KinematicOptions::TIMEOUT);
00561 }
00562
00563 void InteractionHandler::setIKAttempts(unsigned int attempts)
00564 {
00565 KinematicOptions delta;
00566 delta.max_attempts_ = attempts;
00567
00568 boost::mutex::scoped_lock lock(state_lock_);
00569 kinematic_options_map_->setOptions(KinematicOptionsMap::ALL,
00570 delta,
00571 KinematicOptions::MAX_ATTEMPTS);
00572 }
00573
00574 void InteractionHandler::setKinematicsQueryOptions(
00575 const kinematics::KinematicsQueryOptions &opt)
00576 {
00577 KinematicOptions delta;
00578 delta.options_ = opt;
00579
00580 boost::mutex::scoped_lock lock(state_lock_);
00581 kinematic_options_map_->setOptions(KinematicOptionsMap::ALL,
00582 delta,
00583 KinematicOptions::ALL_QUERY_OPTIONS);
00584 }
00585
00586 void InteractionHandler::setKinematicsQueryOptionsForGroup(
00587 const std::string& group_name,
00588 const kinematics::KinematicsQueryOptions &opt)
00589 {
00590 KinematicOptions delta;
00591 delta.options_ = opt;
00592
00593 boost::mutex::scoped_lock lock(state_lock_);
00594 kinematic_options_map_->setOptions(group_name,
00595 delta,
00596 KinematicOptions::ALL_QUERY_OPTIONS);
00597 }
00598
00599 void InteractionHandler::setGroupStateValidityCallback(
00600 const robot_state::GroupStateValidityCallbackFn &callback)
00601 {
00602 KinematicOptions delta;
00603 delta.state_validity_callback_ = callback;
00604
00605 boost::mutex::scoped_lock lock(state_lock_);
00606 kinematic_options_map_->setOptions(KinematicOptionsMap::ALL,
00607 delta,
00608 KinematicOptions::STATE_VALIDITY_CALLBACK);
00609 }
00610
00611 const kinematics::KinematicsQueryOptions& InteractionHandler::getKinematicsQueryOptions() const
00612 {
00613 boost::mutex::scoped_lock lock(state_lock_);
00614 return kinematic_options_map_->getOptions(KinematicOptionsMap::DEFAULT).options_;
00615 }
00616
00617
00618 void InteractionHandler::setUpdateCallback(const InteractionHandlerCallbackFn &callback)
00619 {
00620 boost::mutex::scoped_lock lock(state_lock_);
00621 update_callback_ = callback;
00622 }
00623
00624 const InteractionHandlerCallbackFn& InteractionHandler::getUpdateCallback() const
00625 {
00626 boost::mutex::scoped_lock lock(state_lock_);
00627 return update_callback_;
00628 }
00629
00630 void InteractionHandler::setMeshesVisible(bool visible)
00631 {
00632 boost::mutex::scoped_lock lock(state_lock_);
00633 display_meshes_ = visible;
00634 }
00635
00636 bool InteractionHandler::getMeshesVisible() const
00637 {
00638 boost::mutex::scoped_lock lock(state_lock_);
00639 return display_meshes_;
00640 }
00641
00642 void InteractionHandler::setControlsVisible(bool visible)
00643 {
00644 boost::mutex::scoped_lock lock(state_lock_);
00645 display_controls_ = visible;
00646 }
00647
00648 bool InteractionHandler::getControlsVisible() const
00649 {
00650 boost::mutex::scoped_lock lock(state_lock_);
00651 return display_controls_;
00652 }
00653
00654
00655 }