$search
00001 /********************************************************************* 00002 * 00003 * Software License Agreement (BSD License) 00004 * 00005 * Copyright (c) 2008, Willow Garage, Inc. 00006 * All rights reserved. 00007 * 00008 * Redistribution and use in source and binary forms, with or without 00009 * modification, are permitted provided that the following conditions 00010 * are met: 00011 * 00012 * * Redistributions of source code must retain the above copyright 00013 * notice, this list of conditions and the following disclaimer. 00014 * * Redistributions in binary form must reproduce the above 00015 * copyright notice, this list of conditions and the following 00016 * disclaimer in the documentation and/or other materials provided 00017 * with the distribution. 00018 * * Neither the name of the Willow Garage nor the names of its 00019 * contributors may be used to endorse or promote products derived 00020 * from this software without specific prior written permission. 00021 * 00022 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00023 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00024 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00025 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 00026 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00027 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00028 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00029 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00030 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00031 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 00032 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00033 * POSSIBILITY OF SUCH DAMAGE. 00034 * 00035 * \author E. Gil Jones 00036 *********************************************************************/ 00037 00038 #include <stdio.h> 00039 #include <stdlib.h> 00040 #include <time.h> 00041 #include <boost/thread.hpp> 00042 00043 #include <ros/ros.h> 00044 #include <actionlib/client/simple_action_client.h> 00045 #include <actionlib/server/simple_action_server.h> 00046 00047 #include <move_arm_msgs/MoveArmAction.h> 00048 #include <cotesys_ros_grasping/MoveArmToPositionAction.h> 00049 00050 namespace cotesys_ros_grasping 00051 { 00052 00053 struct GraspDef { 00054 std::string name; 00055 double ik_to_gripper_x_diff_; 00056 double ik_to_gripper_y_diff_; 00057 double ik_to_gripper_z_diff_; 00058 00059 double end_effector_rot_x_; 00060 double end_effector_rot_y_; 00061 double end_effector_rot_z_; 00062 double end_effector_rot_w_; 00063 }; 00064 00065 class MoveArmToPositionServer 00066 { 00067 public: 00068 MoveArmToPositionServer(); 00069 00070 bool execute(const cotesys_ros_grasping::MoveArmToPositionGoalConstPtr& goal); 00071 00072 private: 00073 00074 std::string left_arm_name_, right_arm_name_; 00075 std::string right_ik_link_, left_ik_link_; 00076 00077 std::map<std::string, GraspDef> grasp_def_map_; 00078 00079 ros::NodeHandle priv_nh_, root_nh_; 00080 boost::shared_ptr<actionlib::SimpleActionClient<move_arm_msgs::MoveArmAction> > left_move_arm_client_, right_move_arm_client_; 00081 boost::shared_ptr<actionlib::SimpleActionServer<cotesys_ros_grasping::MoveArmToPositionAction> > action_server_; 00082 00083 }; 00084 00085 MoveArmToPositionServer::MoveArmToPositionServer() 00086 : priv_nh_("~") 00087 { 00088 priv_nh_.param<std::string>("left_arm_name", left_arm_name_, "left_arm"); 00089 priv_nh_.param<std::string>("right_arm_name", right_arm_name_, "right_arm"); 00090 priv_nh_.param<std::string>("right_ik_link", right_ik_link_, "r_wrist_roll_link"); 00091 priv_nh_.param<std::string>("left_ik_link", left_ik_link_, "l_wrist_roll_link"); 00092 00093 if(!priv_nh_.hasParam("grasps")) { 00094 ROS_WARN_STREAM("No grasps loaded"); 00095 } else { 00096 XmlRpc::XmlRpcValue grasps_xml; 00097 priv_nh_.getParam("grasps", grasps_xml); 00098 if(grasps_xml.getType() != XmlRpc::XmlRpcValue::TypeArray) { 00099 ROS_WARN("grasps is not an array"); 00100 } else if(grasps_xml.size() == 0) { 00101 ROS_WARN("No grasps specified in grasps yaml"); 00102 } else { 00103 bool hasDefault = false; 00104 for(int i = 0; i < grasps_xml.size(); i++) { 00105 if(!grasps_xml[i].hasMember("name")) { 00106 ROS_WARN("Each grasp must have a name"); 00107 continue; 00108 } 00109 GraspDef grasp; 00110 grasp.name = std::string(grasps_xml[i]["name"]); 00111 if(grasp.name == "default") { 00112 hasDefault = true; 00113 } 00114 ROS_INFO_STREAM("Adding grasp named " << grasp.name); 00115 if(grasps_xml[i].hasMember("ik_to_gripper_x_diff")) { 00116 grasp.ik_to_gripper_x_diff_ = grasps_xml[i]["ik_to_gripper_x_diff"]; 00117 } 00118 if(grasps_xml[i].hasMember("ik_to_gripper_y_diff")) { 00119 grasp.ik_to_gripper_y_diff_ = grasps_xml[i]["ik_to_gripper_y_diff"]; 00120 } 00121 if(grasps_xml[i].hasMember("ik_to_gripper_z_diff")) { 00122 grasp.ik_to_gripper_z_diff_ = grasps_xml[i]["ik_to_gripper_z_diff"]; 00123 } 00124 if(grasps_xml[i].hasMember("end_effector_x_rot")) { 00125 grasp.end_effector_rot_x_ = grasps_xml[i]["end_effector_x_rot"]; 00126 } else { 00127 ROS_WARN("no x rot"); 00128 } 00129 if(grasps_xml[i].hasMember("end_effector_y_rot")) { 00130 grasp.end_effector_rot_y_ = grasps_xml[i]["end_effector_y_rot"]; 00131 } else { 00132 ROS_WARN("no y rot"); 00133 } 00134 if(grasps_xml[i].hasMember("end_effector_z_rot")) { 00135 grasp.end_effector_rot_z_ = grasps_xml[i]["end_effector_z_rot"]; 00136 } else { 00137 ROS_WARN("no z rot"); 00138 } 00139 if(grasps_xml[i].hasMember("end_effector_w_rot")) { 00140 grasp.end_effector_rot_w_ = grasps_xml[i]["end_effector_w_rot"]; 00141 } else { 00142 ROS_WARN("no w rot"); 00143 } 00144 ROS_INFO_STREAM("Quaternion is " << grasp.end_effector_rot_x_ << " " 00145 << grasp.end_effector_rot_y_ << " " 00146 << grasp.end_effector_rot_z_ << " " 00147 << grasp.end_effector_rot_w_); 00148 00149 grasp_def_map_[grasp.name] = grasp; 00150 } 00151 if(!hasDefault) { 00152 ROS_WARN("No default grasp pose"); 00153 } 00154 } 00155 } 00156 00157 //TODO - test if the end effector parameters specify a valid quaternion 00158 00159 left_move_arm_client_.reset(new actionlib::SimpleActionClient<move_arm_msgs::MoveArmAction>("left_move_arm_action", true)); 00160 right_move_arm_client_.reset(new actionlib::SimpleActionClient<move_arm_msgs::MoveArmAction>("right_move_arm_action", true)); 00161 00162 //TODO - wait for the servers 00163 00164 action_server_.reset(new actionlib::SimpleActionServer<cotesys_ros_grasping::MoveArmToPositionAction>(root_nh_, "move_arm_to_position", 00165 boost::bind(&MoveArmToPositionServer::execute, this, _1))); 00166 } 00167 00168 bool MoveArmToPositionServer::execute(const cotesys_ros_grasping::MoveArmToPositionGoalConstPtr& req) 00169 { 00170 if(req->arm_name != left_arm_name_ && req->arm_name != right_arm_name_) { 00171 ROS_ERROR_STREAM("Can't do anything for arm named " << req->arm_name); 00172 return false; 00173 } 00174 00175 std::string grasp_name = req->grasp_name; 00176 if(grasp_def_map_.find(req->grasp_name) == grasp_def_map_.end()) { 00177 if(grasp_def_map_.find("default") != grasp_def_map_.end()) { 00178 ROS_DEBUG("Using default"); 00179 grasp_name = "default"; 00180 } else { 00181 ROS_INFO_STREAM("Don't have grasp named " << req->grasp_name << " and no default defined"); 00182 return false; 00183 } 00184 } 00185 00186 ROS_INFO_STREAM("Going to execute grasp named " << grasp_name); 00187 GraspDef& grasp = grasp_def_map_[grasp_name]; 00188 00189 std::string ik_link_name; 00190 boost::shared_ptr<actionlib::SimpleActionClient<move_arm_msgs::MoveArmAction> > move_arm_client; 00191 if(req->arm_name == left_arm_name_) { 00192 ik_link_name = left_ik_link_; 00193 move_arm_client = left_move_arm_client_; 00194 } else { 00195 ik_link_name = right_ik_link_; 00196 move_arm_client = right_move_arm_client_; 00197 } 00198 00199 move_arm_msgs::MoveArmGoal goal; 00200 00201 goal.motion_plan_request.group_name=req->arm_name; 00202 goal.motion_plan_request.num_planning_attempts = 1; 00203 goal.motion_plan_request.planner_id = ""; 00204 goal.planner_service_name = "ompl_planning/plan_kinematic_path"; 00205 goal.motion_plan_request.allowed_planning_time = ros::Duration(2.0); 00206 00207 goal.motion_plan_request.goal_constraints.position_constraints.resize(1); 00208 goal.motion_plan_request.goal_constraints.position_constraints[0].header.stamp = ros::Time(); 00209 goal.motion_plan_request.goal_constraints.position_constraints[0].header.frame_id = "base_link"; 00210 00211 goal.motion_plan_request.goal_constraints.position_constraints[0].link_name = ik_link_name; 00212 goal.motion_plan_request.goal_constraints.position_constraints[0].position.x = req->point.x-grasp.ik_to_gripper_x_diff_; 00213 goal.motion_plan_request.goal_constraints.position_constraints[0].position.y = req->point.y-grasp.ik_to_gripper_y_diff_; 00214 goal.motion_plan_request.goal_constraints.position_constraints[0].position.z = req->point.z-grasp.ik_to_gripper_z_diff_; 00215 00216 goal.motion_plan_request.goal_constraints.position_constraints[0].constraint_region_shape.type = geometric_shapes_msgs::Shape::BOX; 00217 goal.motion_plan_request.goal_constraints.position_constraints[0].constraint_region_shape.dimensions.push_back(0.20); 00218 goal.motion_plan_request.goal_constraints.position_constraints[0].constraint_region_shape.dimensions.push_back(0.20); 00219 goal.motion_plan_request.goal_constraints.position_constraints[0].constraint_region_shape.dimensions.push_back(0.20); 00220 00221 goal.motion_plan_request.goal_constraints.position_constraints[0].constraint_region_orientation.w = 1.0; 00222 goal.motion_plan_request.goal_constraints.position_constraints[0].weight = 1.0; 00223 00224 goal.motion_plan_request.goal_constraints.orientation_constraints.resize(1); 00225 goal.motion_plan_request.goal_constraints.orientation_constraints[0].header.stamp = ros::Time(); 00226 goal.motion_plan_request.goal_constraints.orientation_constraints[0].header.frame_id = "base_link"; 00227 goal.motion_plan_request.goal_constraints.orientation_constraints[0].link_name = ik_link_name; 00228 goal.motion_plan_request.goal_constraints.orientation_constraints[0].orientation.x = grasp.end_effector_rot_x_; 00229 goal.motion_plan_request.goal_constraints.orientation_constraints[0].orientation.y = grasp.end_effector_rot_y_; 00230 goal.motion_plan_request.goal_constraints.orientation_constraints[0].orientation.z = grasp.end_effector_rot_z_; 00231 goal.motion_plan_request.goal_constraints.orientation_constraints[0].orientation.w = grasp.end_effector_rot_w_; 00232 00233 goal.motion_plan_request.goal_constraints.orientation_constraints[0].absolute_roll_tolerance = 0.15; 00234 goal.motion_plan_request.goal_constraints.orientation_constraints[0].absolute_pitch_tolerance = 0.15; 00235 goal.motion_plan_request.goal_constraints.orientation_constraints[0].absolute_yaw_tolerance = 0.15; 00236 00237 goal.motion_plan_request.goal_constraints.orientation_constraints[0].weight = 1.0; 00238 00239 //turning off collisions with the stupid camera frame 00240 motion_planning_msgs::CollisionOperation coll; 00241 coll.object1 = "r_forearm_cam"; 00242 coll.object2 = coll.COLLISION_SET_ALL; 00243 coll.operation = coll.DISABLE; 00244 goal.motion_plan_request.ordered_collision_operations.collision_operations.push_back(coll); 00245 coll.object1 = "l_forearm_cam"; 00246 goal.motion_plan_request.ordered_collision_operations.collision_operations.push_back(coll); 00247 if(req->arm_name == left_arm_name_) { 00248 coll.object1 = "l_forearm_link"; 00249 coll.object2 = coll.COLLISION_SET_ATTACHED_OBJECTS; 00250 coll.operation = coll.DISABLE; 00251 goal.motion_plan_request.ordered_collision_operations.collision_operations.push_back(coll); 00252 } else { 00253 coll.object1 = "r_forearm_link"; 00254 coll.object2 = coll.COLLISION_SET_ATTACHED_OBJECTS; 00255 coll.operation = coll.DISABLE; 00256 goal.motion_plan_request.ordered_collision_operations.collision_operations.push_back(coll); 00257 } 00258 00259 cotesys_ros_grasping::MoveArmToPositionResult res; 00260 00261 move_arm_client->sendGoal(goal); 00262 bool call_ok = move_arm_client->waitForResult(ros::Duration(30.0)); 00263 if(!call_ok) { 00264 res.error_code = move_arm_client->getResult()->error_code; 00265 action_server_->setAborted(res); 00266 } else { 00267 actionlib::SimpleClientGoalState state = move_arm_client->getState(); 00268 if(state != actionlib::SimpleClientGoalState::SUCCEEDED) { 00269 res.error_code = move_arm_client->getResult()->error_code; 00270 action_server_->setAborted(res); 00271 } else { 00272 res.error_code = move_arm_client->getResult()->error_code; 00273 action_server_->setSucceeded(res); 00274 } 00275 } 00276 return true; 00277 } 00278 00279 } 00280 00281 int main(int argc, char** argv) 00282 { 00283 ros::init(argc, argv, "move_arm_to_position"); 00284 00285 ros::AsyncSpinner spinner(1); // Use 1 thread 00286 spinner.start(); 00287 00288 cotesys_ros_grasping::MoveArmToPositionServer move_arm_pos; 00289 00290 ROS_INFO("Move_arm_to_position action started"); 00291 ros::waitForShutdown(); 00292 00293 return 0; 00294 }