manipulation_transforms_ros.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Copyright (c) 2008, Willow Garage, Inc.
00005  *  All rights reserved.
00006  *
00007  *  Redistribution and use in source and binary forms, with or without
00008  *  modification, are permitted provided that the following conditions
00009  *  are met:
00010  *
00011  *   * Redistributions of source code must retain the above copyright
00012  *     notice, this list of conditions and the following disclaimer.
00013  *   * Redistributions in binary form must reproduce the above
00014  *     copyright notice, this list of conditions and the following
00015  *     disclaimer in the documentation and/or other materials provided
00016  *     with the distribution.
00017  *   * Neither the name of the Willow Garage nor the names of its
00018  *     contributors may be used to endorse or promote products derived
00019  *     from this software without specific prior written permission.
00020  *
00021  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00027  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00029  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00031  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032  *  POSSIBILITY OF SUCH DAMAGE.
00033  *********************************************************************/
00034 
00042 #include <ros/ros.h>
00043 #include <boost/format.hpp>
00044 #include <tf/transform_listener.h>
00045 #include <geometry_msgs/PoseStamped.h>
00046 #include <tf_conversions/tf_kdl.h>
00047 
00048 #include "manipulation_transforms/manipulation_transforms_ros.h"
00049 #include "manipulation_transforms/util.h"
00050 
00051 using namespace std;
00052 
00053 ManipulationTransformsROS::ManipulationTransformsROS(const std::string &reference_frame) :
00054                                 BASE_FRAME_(reference_frame)
00055         {
00056         init_services();
00057 }
00058 
00059 ManipulationTransformsROS::ManipulationTransformsROS(const std::string &reference_frame, const std::string &ns) :
00060                 BASE_FRAME_(reference_frame)
00061         {
00062         if (ros::isStarted()) {
00063                 init_services(ns);
00064 
00065                 // Load rigid grasp transforms
00066                 ROS_DEBUG_STREAM("Waiting for transforms under namespace " << param_nh_.getNamespace());
00067                 ros::Rate r = ros::Rate(15);
00068                 while ( checkForParamServerTransforms(param_nh_, false) < 1 && !ros::isShuttingDown())
00069                         r.sleep();
00070 
00071                 //FIXME: there is a potential race condition here if user is attempting to load in many transforms
00072                 //while this call is blocking, but it's almost surely never gonna matter
00073 
00074                 if (loadParamServerTransforms(param_nh_))
00075                         ROS_INFO("READY!");
00076         }
00077 }
00078 
00079 ManipulationTransformsROS::ManipulationTransformsROS(const std::string &reference_frame,
00080                 geometry_msgs::PoseStamped &obj_init_pose,
00081                 std::vector<geometry_msgs::PoseStamped> effector_init_poses) :
00082                 BASE_FRAME_(reference_frame)
00083 {
00084         ROS_WARN_STREAM_COND(obj_init_pose.header.frame_id != BASE_FRAME_, "frame_id for object_pose should be \""
00085                         << BASE_FRAME_ << "\", but it's \"" << obj_init_pose.header.frame_id << "\"");
00086 
00087         // Set number of effectors from the number of transforms provided
00088         n_effectors_ = effector_init_poses.size();
00089         ROS_INFO("Initializing with %u effector transforms", n_effectors_);
00090 
00091         if (n_effectors_ < 1 ) {
00092                 ROS_ERROR("Expected transforms for at least one effector, but got %u", n_effectors_);
00093                 ROS_WARN_COND(n_effectors_ != 1 && n_effectors_ != 2, "Querying object pose only supported for 1 or 2 effectors");
00094         }
00095 
00096         btTransform bt_object_pose;
00097         tf::poseMsgToTF(obj_init_pose.pose, bt_object_pose);
00098 
00099         vector<btTransform> bt_effector_poses;
00100         bt_effector_poses.resize(n_effectors_);
00101 
00102         for (unsigned int i = 0; i < n_effectors_; ++i) {
00103                 ROS_WARN_STREAM_COND(effector_init_poses[i].header.frame_id != BASE_FRAME_, "frame_id for effector_pose should be \""
00104                                         << BASE_FRAME_ << "\", but it's \"" << effector_init_poses[i].header.frame_id << "\"");
00105                 tf::poseMsgToTF(effector_init_poses[i].pose, bt_effector_poses[i]);
00106         }
00107 
00108         // Pass service call transforms into solver
00109         solver_.setInitialTransforms(bt_object_pose, bt_effector_poses);
00110 }
00111 
00112 ManipulationTransformsROS::~ManipulationTransformsROS(){}
00113 
00114 void ManipulationTransformsROS::init_services(const std::string &ns)
00115 {
00116         // Initialize private namespace
00117         private_nh_ = ros::NodeHandle("~");
00118 
00119         // Initialize param namespace
00120         param_nh_ = ros::NodeHandle(ns);
00121 
00122         // Advertise services
00123         load_initial_transforms_service_ = private_nh_.advertiseService("LoadInitialTransforms", &ManipulationTransformsROS::loadInitialTransforms, this);
00124         set_initial_transforms_service_ = private_nh_.advertiseService("SetInitialTransforms", &ManipulationTransformsROS::setInitialTransforms, this);
00125         effector_poses_to_object_service_ = private_nh_.advertiseService("MapEffectorPosesToObject", &ManipulationTransformsROS::mapEffectorPosesToObject, this);
00126         object_pose_to_effectors_service_ = private_nh_.advertiseService("MapObjectPoseToEffectors", &ManipulationTransformsROS::mapObjectPoseToEffectors, this);
00127         effector_twists_to_object_service_ = private_nh_.advertiseService("MapEffectorTwistsToObject", &ManipulationTransformsROS::mapEffectorTwistsToObject, this);
00128         object_twist_to_effectors_service_ = private_nh_.advertiseService("MapObjectTwistToEffectors", &ManipulationTransformsROS::mapObjectTwistToEffectors, this);
00129         effector_trajectories_to_object_service_ = private_nh_.advertiseService("MapEffectorTrajectoriesToObject", &ManipulationTransformsROS::mapEffectorTrajectoriesToObject, this);
00130         object_trajectory_to_effectors_service_ = private_nh_.advertiseService("MapObjectTrajectoryToEffectors", &ManipulationTransformsROS::mapObjectTrajectoryToEffectors, this);
00131 }
00132 
00133 bool ManipulationTransformsROS::setInitialTransforms(manipulation_transforms::SetInitialTransforms::Request &req,
00134                 manipulation_transforms::SetInitialTransforms::Response &resp)
00135 {
00136         ROS_WARN_STREAM_COND(req.object_pose.header.frame_id != BASE_FRAME_, "frame_id for object_pose should be \""
00137                         << BASE_FRAME_ << "\", but it's \"" << req.object_pose.header.frame_id << "\"");
00138 
00139         // Set number of effectors from the number of transforms provided
00140         n_effectors_ = req.effector_poses.size();
00141         ROS_INFO("Initializing with %u effector transforms", n_effectors_);
00142 
00143         if (n_effectors_ < 1 ) {
00144                 ROS_ERROR("Expected transforms for at least one effector, but got %u", n_effectors_);
00145                 ROS_WARN_COND(n_effectors_ != 1 && n_effectors_ != 2, "Querying object pose only supported for 1 or 2 effectors");
00146                 resp.success = false;
00147         }
00148 
00149         tf::poseMsgToTF(req.object_pose.pose, obj_initial_pose_);
00150 
00151         effector_init_poses.resize(n_effectors_);
00152 
00153         for (unsigned int i = 0; i < n_effectors_; ++i) {
00154                 ROS_WARN_STREAM_COND(req.effector_poses[i].header.frame_id != BASE_FRAME_, "frame_id for effector_pose should be \""
00155                                         << BASE_FRAME_ << "\", but it's \"" << req.effector_poses[i].header.frame_id << "\"");
00156                 tf::poseMsgToTF(req.effector_poses[i].pose, effector_init_poses[i]);
00157         }
00158 
00159         // Pass service call transforms into solver
00160         solver_.setInitialTransforms(obj_initial_pose_, effector_init_poses);
00161 
00162         // Report to user
00163         ROS_DEBUG_STREAM("OBJECT INITIAL POSE: " << manipulation_transforms_util::btTransform_to_string(obj_initial_pose_));
00164         for (unsigned int i = 0; i < n_effectors_; ++i)
00165                 ROS_DEBUG_STREAM("EFFECTOR " << i << " INITIAL POSE: " << manipulation_transforms_util::btTransform_to_string(effector_init_poses[i]));
00166 
00167         resp.success = true;
00168 
00169         return resp.success;
00170 }
00171 
00172 bool ManipulationTransformsROS::loadInitialTransforms(manipulation_transforms::LoadInitialTransforms::Request &req,
00173                 manipulation_transforms::LoadInitialTransforms::Response &resp)
00174 {
00175         // Allow user to load from private node handle TODO: document
00176         if (req.name == "useprivate") {
00177                 resp.success = loadParamServerTransforms(param_nh_);
00178         }
00179         else {
00180                 ros::NodeHandle nh(req.name);
00181                 resp.success = loadParamServerTransforms(nh);
00182         }
00183 
00184         return resp.success;
00185 }
00186 
00190 bool ManipulationTransformsROS::mapEffectorPosesToObject(manipulation_transforms::MapEffectorPosesToObject::Request &req,
00191                 manipulation_transforms::MapEffectorPosesToObject::Response &resp)
00192 {
00193         if (n_effectors_ != req.effector_poses.size()) {
00194                 ROS_ERROR("Expected transforms for %u effectors, but got %lu", n_effectors_, req.effector_poses.size());
00195         }
00196 
00197         // Transform request to btTransforms
00198         btTransform bt_object_pose;
00199         vector<btTransform> bt_effector_poses;
00200         bt_effector_poses.resize(n_effectors_);
00201 
00202         for (unsigned int i = 0; i < n_effectors_; ++i) {
00203                 ROS_WARN_STREAM_COND(req.effector_poses[i].header.frame_id != BASE_FRAME_,
00204                                 "frame_id for effector pose " << i << " should be \"" << BASE_FRAME_ << "\", but it's \""
00205                                 << req.effector_poses[i].header.frame_id << "\"");
00206                 ROS_DEBUG_STREAM("effector " << i << " query pose: " << req.effector_poses[i].pose);
00207                 tf::poseMsgToTF(req.effector_poses[i].pose, bt_effector_poses[i]);
00208         }
00209 
00210         // Find solution pose
00211         resp.error = solver_.mapEffectorPosesToObject(bt_effector_poses, bt_object_pose);
00212 
00213         // Transform back to message
00214         tf::poseTFToMsg(bt_object_pose, resp.object_pose.pose);
00215         resp.object_pose.header.frame_id = BASE_FRAME_;
00216         resp.object_pose.header.stamp = ros::Time::now();
00217 
00218         ROS_DEBUG_STREAM("result obj pose: " << resp.object_pose);
00219 
00220         return true;
00221 }
00222 
00226 bool ManipulationTransformsROS::mapObjectPoseToEffectors(manipulation_transforms::MapObjectPoseToEffectors::Request &req,
00227                 manipulation_transforms::MapObjectPoseToEffectors::Response &resp)
00228 {
00229         ROS_WARN_STREAM_COND(req.object_pose.header.frame_id != BASE_FRAME_,
00230                         "frame_id for object_pose should be \"" << BASE_FRAME_ << "\", but it's \""
00231                         << req.object_pose.header.frame_id << "\"");
00232 
00233         ROS_DEBUG_STREAM("obj query pose: " << req.object_pose);
00234 
00235         // Transform request to btTransforms
00236         btTransform bt_object_pose;
00237         tf::poseMsgToTF(req.object_pose.pose, bt_object_pose);
00238 
00239         // Allocate space for solution
00240         vector<btTransform> bt_effector_poses;
00241         bt_effector_poses.resize(n_effectors_); // will throw warnings without this
00242 
00243         // Find solution poses
00244         solver_.mapObjectPoseToEffectors(bt_object_pose, bt_effector_poses);
00245 
00246         // Transform back to messages
00247         resp.effector_poses.resize(n_effectors_);
00248         for (unsigned int i = 0; i < n_effectors_; ++i) {
00249                 tf::poseTFToMsg(bt_effector_poses[i], resp.effector_poses[i].pose);
00250                 resp.effector_poses[i].header.frame_id = BASE_FRAME_;
00251                 resp.effector_poses[i].header.stamp = ros::Time::now();
00252 
00253                 ROS_DEBUG_STREAM("effector " << i << " result pose: " << resp.effector_poses[i]);
00254         }
00255 
00256         return true;
00257 }
00258 
00262 bool ManipulationTransformsROS::mapEffectorTwistsToObject(manipulation_transforms::MapEffectorTwistsToObject::Request &req,
00263                 manipulation_transforms::MapEffectorTwistsToObject::Response &resp)
00264 {
00265         if (n_effectors_ != req.effector_twists.size()) {
00266                         ROS_ERROR("Expected transforms for %u effectors, but got %lu", n_effectors_, req.effector_twists.size());
00267                 }
00268 
00269                 // Transform request to KDL twists
00270                 KDL::Twist object_twist;
00271                 vector<KDL::Twist> effector_twists;
00272                 effector_twists.resize(n_effectors_);
00273 
00274                 for (unsigned int i = 0; i < n_effectors_; ++i) {
00275                         ROS_WARN_STREAM_COND(req.effector_twists[i].header.frame_id != BASE_FRAME_,
00276                                         "frame_id for effector pose " << i << " should be \"" << BASE_FRAME_ << "\", but it's \""
00277                                         << req.effector_twists[i].header.frame_id << "\"");
00278                         ROS_DEBUG_STREAM("effector " << i << " query twist: " << req.effector_twists[i].twist);
00279                         tf::TwistMsgToKDL(req.effector_twists[i].twist, effector_twists[i]);
00280                 }
00281 
00282                 // Find solution pose
00283                 resp.error = solver_.mapEffectorTwistsToObject(effector_twists, object_twist);
00284 
00285                 // Transform back to message
00286                 tf::TwistKDLToMsg(object_twist, resp.object_twist.twist);
00287                 resp.object_twist.header.frame_id = BASE_FRAME_;
00288                 resp.object_twist.header.stamp = ros::Time::now();
00289 
00290                 ROS_DEBUG_STREAM("result obj pose: " << resp.object_twist);
00291 
00292                 return true;
00293 }
00294 
00298 bool ManipulationTransformsROS::mapObjectTwistToEffectors(manipulation_transforms::MapObjectTwistToEffectors::Request &req,
00299                 manipulation_transforms::MapObjectTwistToEffectors::Response &resp)
00300 {
00301 
00302         ROS_WARN_STREAM_COND(req.object_twist.header.frame_id != BASE_FRAME_,
00303                         "frame_id for object_pose should be \"" << BASE_FRAME_ << "\", but it's \""
00304                         << req.object_twist.header.frame_id << "\"");
00305 
00306         ROS_DEBUG_STREAM("obj query pose: " << req.object_twist);
00307 
00308         // Transform request to KDL
00309         KDL::Twist object_twist;
00310         tf::TwistMsgToKDL(req.object_twist.twist, object_twist);
00311 
00312         // Allocate space for solution
00313         vector<KDL::Twist> effector_twists;
00314         effector_twists.resize(n_effectors_); // will throw warnings without this
00315 
00316         // Find solution poses
00317         solver_.mapObjectTwistToEffectors(object_twist, effector_twists);
00318 
00319         // Transform back to messages
00320         resp.effector_twists.resize(n_effectors_);
00321         for (unsigned int i = 0; i < n_effectors_; ++i) {
00322                 tf::TwistKDLToMsg(effector_twists[i], resp.effector_twists[i].twist);
00323                 resp.effector_twists[i].header.frame_id = BASE_FRAME_;
00324                 resp.effector_twists[i].header.stamp = ros::Time::now();
00325 
00326                 ROS_DEBUG_STREAM("effector " << i << " result twist: " << resp.effector_twists[i]);
00327         }
00328 
00329         return true;
00330 }
00331 
00335 bool ManipulationTransformsROS::mapObjectTrajectoryToEffectors(manipulation_transforms::MapObjectTrajectoryToEffectors::Request &req,
00336                 manipulation_transforms::MapObjectTrajectoryToEffectors::Response &resp)
00337 {
00338         //TODO implement this
00339         return true;
00340 }
00341 
00345 bool ManipulationTransformsROS::mapEffectorTrajectoriesToObject(manipulation_transforms::MapEffectorTrajectoriesToObject::Request &req,
00346                         manipulation_transforms::MapEffectorTrajectoriesToObject::Response &resp)
00347 {
00348         //TODO implement this
00349         return true;
00350 }
00351 
00352 int ManipulationTransformsROS::checkForParamServerTransforms(const ros::NodeHandle &nh, bool warn)
00353 {
00354         //check object transform parameters first
00355         bool user_obj_params = false;
00356         user_obj_params |= nh.hasParam("obj_init_pose/position");
00357         user_obj_params |= nh.hasParam("obj_init_pose/orientation");
00358 
00359         // Bail now if no object transforms found
00360         if (!user_obj_params) {
00361                 ROS_WARN_STREAM_COND(warn,
00362                                 "Could not detect required transform parameters \"obj_init_pose\" under namespace \""
00363                                 <<  nh.getNamespace() << "\"");
00364                 return -1;
00365         }
00366 
00367         // Otherwise, start looking for effector transforms matching "effector#_init_pose/position" and "effector#_init_pose/orientation"
00368         int n = 0;
00369         while (nh.hasParam((boost::format("effector%u_init_pose/position") % n).str()) &&
00370                 nh.hasParam((boost::format("effector%u_init_pose/orientation") % n).str())) {
00371                 n++;
00372         }
00373 
00374         return n;
00375 }
00376 
00377 bool ManipulationTransformsROS::loadParamServerTransforms(const ros::NodeHandle &nh)
00378 {
00379         // Set n_effectors_ to the number of transforms found on the parameter server
00380         if ((n_effectors_ = checkForParamServerTransforms(nh, false)) < 1)
00381                 return false;
00382 
00383         ROS_WARN_COND(n_effectors_ != 1 && n_effectors_ != 2, "Querying object pose only supported for 1 or 2 effectors");
00384         ROS_INFO("Initializing with %u effector transforms found on the parameter server", n_effectors_);
00385 
00386         obj_initial_pose_ = manipulation_transforms_util::readTransformParameter(nh, "obj_init_pose");
00387         effector_init_poses.resize(n_effectors_);
00388 
00389         for (unsigned int i = 0; i < n_effectors_; ++i)
00390                 effector_init_poses[i] = manipulation_transforms_util::readTransformParameter(nh, (boost::format("effector%u_init_pose") % i).str());
00391 
00392         // Pass loaded transforms into solver
00393         solver_.setInitialTransforms(obj_initial_pose_, effector_init_poses);
00394 
00395         ROS_INFO_STREAM("Loaded new obj grasp transforms from namespace \"" << nh.getNamespace() << "\"");
00396         ROS_DEBUG_STREAM("OBJECT INITIAL POSE: " << manipulation_transforms_util::btTransform_to_string(obj_initial_pose_));
00397         for (unsigned int i = 0; i < n_effectors_; ++i)
00398                 ROS_DEBUG_STREAM("EFFECTOR " << i << " INITIAL POSE: " << manipulation_transforms_util::btTransform_to_string(effector_init_poses[i]));
00399 
00400         return true;
00401 }
00402 
00403 


manipulation_transforms
Author(s): Jonathan Scholz
autogenerated on Tue Jan 7 2014 11:10:08