00001 #include <moveit_planning_helper/MoveItPlanner.h>
00002 #include <convenience_ros_functions/RobotInfo.h>
00003 #include <geometric_shapes/solid_primitive_dims.h>
00004
00005 #define ALLOWED_PLANNING_TIME 3
00006 #define ALLOWED_PLANNING_TIME_PATH_CONSTRAINTS 60
00007 #define ALLOWED_PLANNING_ATTEMPTS 10
00008
00009 using moveit_planning_helper::MoveItPlanner;
00010 using convenience_ros_functions::RobotInfo;
00011 using convenience_ros_functions::ROSFunctions;
00012
00013
00014 MoveItPlanner::MoveItPlanner(ros::NodeHandle& n,
00015 const std::string& _moveit_motion_plan_service,
00016 const std::string& _moveit_check_state_validity_service):
00017 node(n),
00018 moveit_motion_plan_service(_moveit_motion_plan_service),
00019 moveit_check_state_validity_service(_moveit_check_state_validity_service)
00020 {
00021 init();
00022 }
00023
00024 MoveItPlanner::~MoveItPlanner()
00025 {
00026 shutdown();
00027 }
00028
00029 bool MoveItPlanner::init(){
00030 ROS_INFO("Initialising MoveItPlanner");
00031 ROSFunctions::initSingleton();
00032 state_validity_client=node.serviceClient<moveit_msgs::GetStateValidity>(moveit_check_state_validity_service);
00033 motion_plan_client = node.serviceClient<moveit_msgs::GetMotionPlan>(moveit_motion_plan_service);
00034 return true;
00035 }
00036
00037 void MoveItPlanner::shutdown(){
00038 motion_plan_client.shutdown();
00039 state_validity_client.shutdown();
00040 ROS_INFO("Shutting down MoveItPlanner.");
00041 }
00042
00043
00044 moveit_msgs::MoveItErrorCodes MoveItPlanner::requestTrajectory(
00045 const geometry_msgs::PoseStamped& arm_base_pose,
00046 float arm_reach_span,
00047 const std::string& planning_group,
00048 const moveit_msgs::Constraints& goal_constraints,
00049 const moveit_msgs::Constraints * path_constraints,
00050 const sensor_msgs::JointState& start_state,
00051 moveit_msgs::RobotTrajectory& result_traj) {
00052
00053 moveit_msgs::WorkspaceParameters wspace;
00054 if (!makeWorkspace(arm_base_pose,arm_reach_span,wspace)) {
00055 ROS_ERROR("Could not create MoveIt workspace");
00056 ROS_ERROR_STREAM("Origin pose: "<<arm_base_pose);
00057 ROS_ERROR_STREAM("Arm reach span: "<<arm_reach_span);
00058 moveit_msgs::MoveItErrorCodes ret;
00059 ret.val=moveit_msgs::MoveItErrorCodes::FAILURE;
00060 return ret;
00061 }
00062
00063
00064
00065 std::vector<moveit_msgs::Constraints> constr;
00066 constr.push_back(goal_constraints);
00067 moveit_msgs::MoveItErrorCodes error_code=requestTrajectory(planning_group, constr, start_state, wspace, NULL, path_constraints,result_traj);
00068
00069 return error_code;
00070 }
00071
00072
00073 moveit_msgs::MoveItErrorCodes MoveItPlanner::requestTrajectoryForMobileRobot(
00074 const geometry_msgs::PoseStamped& start_pose,
00075 const geometry_msgs::PoseStamped& target_pose,
00076 float arm_reach_span, const std::string& planning_group,
00077 const moveit_msgs::Constraints& goal_constraints,
00078 const moveit_msgs::Constraints * path_constraints,
00079 const sensor_msgs::JointState& start_state,
00080 const std::string& virtual_joint_name,
00081 const std::string& target_frame_virtual_joint,
00082 moveit_msgs::RobotTrajectory& result_traj) {
00083
00084 moveit_msgs::WorkspaceParameters wspace;
00085 if (!makeWorkspace(start_pose,target_pose,arm_reach_span,wspace)) {
00086 ROS_ERROR("Could not create MoveIt workspace");
00087 ROS_ERROR_STREAM("Start pose: "<<start_pose);
00088 ROS_ERROR_STREAM("Target: "<<target_pose);
00089 moveit_msgs::MoveItErrorCodes ret;
00090 ret.val=moveit_msgs::MoveItErrorCodes::FAILURE;
00091 return ret;
00092 }
00093
00094 sensor_msgs::MultiDOFJointState * virtualJointState=NULL;
00095 if (!virtual_joint_name.empty()) {
00096 virtualJointState = new sensor_msgs::MultiDOFJointState();
00097 ROS_INFO_STREAM("Transforming virtual joint pose to '"<<target_frame_virtual_joint<<"'");
00098 *virtualJointState=RobotInfo::getVirtualJointState(start_pose, virtual_joint_name, target_frame_virtual_joint);
00099 }
00100
00101
00102
00103
00104 std::vector<moveit_msgs::Constraints> constr;
00105 constr.push_back(goal_constraints);
00106 moveit_msgs::MoveItErrorCodes error_code=requestTrajectory(planning_group, constr, start_state, wspace, virtualJointState, path_constraints,result_traj);
00107
00108 if (virtualJointState) delete virtualJointState;
00109
00110 return error_code;
00111 }
00112
00113
00114 moveit_msgs::MoveItErrorCodes MoveItPlanner::requestTrajectory(const std::string& group_name,
00115 const std::vector<moveit_msgs::Constraints>& goal_constraints,
00116 const sensor_msgs::JointState& from_state,
00117 const moveit_msgs::WorkspaceParameters& wspace,
00118 const sensor_msgs::MultiDOFJointState *mdjs,
00119 const moveit_msgs::Constraints* path_constraints,
00120 moveit_msgs::RobotTrajectory& result){
00121
00122 moveit_msgs::MotionPlanResponse response;
00123
00124
00125 moveit_msgs::RobotState robotState;
00126 robotState.is_diff=false;
00127 robotState.joint_state=from_state;
00128
00129 if (mdjs) robotState.multi_dof_joint_state=*mdjs;
00130
00131
00132 if (!isValidState(robotState,group_name)) {
00133 ROS_ERROR("MoveItPlanner: Invalid robot state, can't do planning");
00134 moveit_msgs::MoveItErrorCodes ret;
00135 ret.val=moveit_msgs::MoveItErrorCodes::INVALID_ROBOT_STATE;
00136 return ret;
00137 }
00138
00139
00140
00141 moveit_msgs::MotionPlanRequest request;
00142 request.goal_constraints=goal_constraints;
00143 request.group_name=group_name;
00144 request.start_state=robotState;
00145 request.workspace_parameters=wspace;
00146
00147 request.planner_id="RRTConnectkConfigDefault";
00148
00149
00150 request.num_planning_attempts=ALLOWED_PLANNING_ATTEMPTS;
00151 request.allowed_planning_time=ALLOWED_PLANNING_TIME;
00152
00153 if (path_constraints) {
00154
00155 request.path_constraints=*path_constraints;
00156 request.allowed_planning_time=ALLOWED_PLANNING_TIME_PATH_CONSTRAINTS;
00157 }
00158
00159
00160
00161
00162 response=sendServiceRequest(request);
00163
00164 if (response.error_code.val == moveit_msgs::MoveItErrorCodes::SUCCESS) {
00165 result=response.trajectory;
00166 }
00167
00168
00169
00170
00171 return response.error_code;
00172 }
00173
00174
00175 moveit_msgs::MotionPlanResponse MoveItPlanner::sendServiceRequest(moveit_msgs::MotionPlanRequest& request) {
00176 moveit_msgs::GetMotionPlan mp_srv;
00177 mp_srv.request.motion_plan_request = request;
00178 ROS_DEBUG("Sending planning request");
00179 if (!motion_plan_client.exists()) {
00180 ROS_ERROR("Service %s does not exist, can't get motion plan",motion_plan_client.getService().c_str());
00181 mp_srv.response.motion_plan_response.error_code.val=moveit_msgs::MoveItErrorCodes::FAILURE;
00182 }else{
00183 bool success=motion_plan_client.call(mp_srv);
00184
00185 }
00186 return mp_srv.response.motion_plan_response;
00187 }
00188
00189 double pickMin(const double pos, const double rel, const double extend){
00190 double m=std::min(pos,rel+pos);
00191 return m-extend;
00192 }
00193
00194 double pickMax(const double pos, const double rel, const double extend){
00195 double m=std::max(pos,rel+pos);
00196 return m+extend;
00197 }
00198
00199
00200 bool MoveItPlanner::makeWorkspace(const geometry_msgs::PoseStamped& from,
00201 const geometry_msgs::PoseStamped& to,
00202 float arm_reach_span, moveit_msgs::WorkspaceParameters& wspace) const{
00203
00204 static const float maxWait=2.0;
00205 static const bool latestTime=false;
00206 static const bool printErrors=true;
00207 geometry_msgs::Pose rel;
00208 int err=ROSFunctions::Singleton()->relativePose(from,to,rel,latestTime,maxWait,printErrors);
00209 if (err < 0) {
00210 ROS_ERROR("Can't make MoveIt! workspace because transform between frames not possible. Error code %i",err);
00211
00212
00213 return false;
00214 }
00215
00216 wspace.header=from.header;
00217 wspace.min_corner.x= pickMin(from.pose.position.x, rel.position.x,arm_reach_span);
00218 wspace.min_corner.y= pickMin(from.pose.position.y, rel.position.y,arm_reach_span);
00219 wspace.min_corner.z= pickMin(from.pose.position.z, rel.position.z,arm_reach_span);
00220 wspace.max_corner.x= pickMax(from.pose.position.x, rel.position.x,arm_reach_span);
00221 wspace.max_corner.y= pickMax(from.pose.position.y, rel.position.y,arm_reach_span);
00222 wspace.max_corner.z= pickMax(from.pose.position.z, rel.position.z,arm_reach_span);
00223 return true;
00224 }
00225
00226 bool MoveItPlanner::makeWorkspace(const geometry_msgs::PoseStamped& from,
00227 float arm_reach_span,
00228 moveit_msgs::WorkspaceParameters& wspace) const {
00229
00230 wspace.header=from.header;
00231 wspace.min_corner.x= from.pose.position.x-fabs(arm_reach_span);
00232 wspace.min_corner.y= from.pose.position.y-fabs(arm_reach_span);
00233 wspace.min_corner.z= from.pose.position.z-fabs(arm_reach_span);
00234 wspace.max_corner.x= from.pose.position.x+fabs(arm_reach_span);
00235 wspace.max_corner.y= from.pose.position.y+fabs(arm_reach_span);
00236 wspace.max_corner.z= from.pose.position.z+fabs(arm_reach_span);
00237 return true;
00238 }
00239
00240
00241 bool MoveItPlanner::isValidState(const moveit_msgs::RobotState& robotState, const std::string& group)
00242 {
00243
00244 moveit_msgs::GetStateValidity::Request get_state_validity_request;
00245 moveit_msgs::GetStateValidity::Response get_state_validity_response;
00246 get_state_validity_request.robot_state = robotState;
00247 get_state_validity_request.group_name = group;
00248
00249
00250 ROS_DEBUG("checking state validity..");
00251 if (!state_validity_client.exists()) {
00252 ROS_ERROR("MoveIt! state valididty client not connected");
00253 return false;
00254 }
00255 if (!state_validity_client.call(get_state_validity_request, get_state_validity_response))
00256 {
00257 ROS_ERROR("Failed to call MoveIt! state validity service");
00258 return false;
00259 }
00260 if(get_state_validity_response.valid) {
00261
00262
00263
00264
00265 return true;
00266
00267 } else {
00268 ROS_ERROR("State is invalid");
00269 std::cout<<get_state_validity_response<<std::endl;
00270
00271
00272 return false;
00273 }
00274 return false;
00275 }
00276
00277
00278
00279
00280 shape_msgs::SolidPrimitive getCone(const double& height, const double& radius){
00281 shape_msgs::SolidPrimitive bv;
00282 bv.type = shape_msgs::SolidPrimitive::CONE;
00283 bv.dimensions.resize(geometric_shapes::SolidPrimitiveDimCount<shape_msgs::SolidPrimitive::CONE>::value);
00284 bv.dimensions[shape_msgs::SolidPrimitive::CONE_HEIGHT] = height;
00285 bv.dimensions[shape_msgs::SolidPrimitive::CONE_RADIUS] = radius;
00286 return bv;
00287
00288 }
00289
00290
00291
00292
00293 shape_msgs::SolidPrimitive getCylinder(const double& height, const double& radius){
00294 shape_msgs::SolidPrimitive bv;
00295 bv.type = shape_msgs::SolidPrimitive::CYLINDER;
00296 bv.dimensions.resize(geometric_shapes::SolidPrimitiveDimCount<shape_msgs::SolidPrimitive::CYLINDER>::value);
00297 bv.dimensions[shape_msgs::SolidPrimitive::CYLINDER_HEIGHT] = height;
00298 bv.dimensions[shape_msgs::SolidPrimitive::CYLINDER_RADIUS] = radius;
00299 return bv;
00300
00301 }
00302
00303
00304 shape_msgs::SolidPrimitive getBox(const double& x,const double& y,const double& z){
00305 shape_msgs::SolidPrimitive bv;
00306 bv.type = shape_msgs::SolidPrimitive::BOX;
00307 bv.dimensions.resize(geometric_shapes::SolidPrimitiveDimCount<shape_msgs::SolidPrimitive::BOX>::value);
00308 bv.dimensions[shape_msgs::SolidPrimitive::BOX_X] = x;
00309 bv.dimensions[shape_msgs::SolidPrimitive::BOX_Y] = y;
00310 bv.dimensions[shape_msgs::SolidPrimitive::BOX_Z] = z;
00311 return bv;
00312
00313 }
00314 shape_msgs::SolidPrimitive getSphere(const double& radius){
00315 shape_msgs::SolidPrimitive bv;
00316 bv.type = shape_msgs::SolidPrimitive::SPHERE;
00317 bv.dimensions.resize(geometric_shapes::SolidPrimitiveDimCount<shape_msgs::SolidPrimitive::SPHERE>::value);
00318 bv.dimensions[shape_msgs::SolidPrimitive::SPHERE_RADIUS] = radius;
00319 return bv;
00320 }
00321
00322
00323 moveit_msgs::PositionConstraint MoveItPlanner::getBoxConstraint(const std::string &link_name,
00324 const geometry_msgs::PoseStamped& boxOrigin, const double& x, const double& y, const double& z) {
00325
00326 moveit_msgs::PositionConstraint pc;
00327 pc.link_name = link_name;
00328 pc.target_point_offset.x = 0;
00329 pc.target_point_offset.y = 0;
00330 pc.target_point_offset.z = 0;
00331
00332 pc.header=boxOrigin.header;
00333
00334 pc.constraint_region.primitives.resize(1);
00335 shape_msgs::SolidPrimitive &bv = pc.constraint_region.primitives[0];
00336 bv=getBox(x,y,z);
00337
00338 pc.constraint_region.primitive_poses.resize(1);
00339 geometry_msgs::Pose& pose=pc.constraint_region.primitive_poses[0];
00340 pose=boxOrigin.pose;
00341
00342 pc.weight=1.0;
00343
00344 return pc;
00345 }
00346
00347
00348 moveit_msgs::Constraints MoveItPlanner::getJointConstraint(const sensor_msgs::JointState& js, const float& joint_tolerance){
00349 moveit_msgs::Constraints c;
00350 for (int i=0; i<js.name.size(); ++i){
00351 moveit_msgs::JointConstraint jc;
00352 jc.joint_name=js.name[i];
00353 jc.position=js.position[i];
00354 jc.tolerance_above=joint_tolerance;
00355 jc.tolerance_below=joint_tolerance;
00356 jc.weight=1.0;
00357 c.joint_constraints.push_back(jc);
00358 }
00359 return c;
00360
00361 }
00362
00363
00364 moveit_msgs::OrientationConstraint MoveItPlanner::getOrientationConstraint(const std::string& link_name,
00365 const geometry_msgs::QuaternionStamped& quat,
00366 const float& x_tolerance,
00367 const float& y_tolerance,
00368 const float& z_tolerance) {
00369 moveit_msgs::OrientationConstraint ocm;
00370 ocm.link_name = link_name;
00371 ocm.header = quat.header;
00372 ocm.orientation = quat.quaternion;
00373 ocm.absolute_x_axis_tolerance = x_tolerance;
00374 ocm.absolute_y_axis_tolerance = y_tolerance;
00375 ocm.absolute_z_axis_tolerance = z_tolerance;
00376 ocm.weight = 1.0;
00377 return ocm;
00378 }
00379
00380 moveit_msgs::PositionConstraint MoveItPlanner::getSpherePoseConstraint(
00381 const std::string &link_name,
00382 const geometry_msgs::PoseStamped &target_pose,
00383 float maxArmReachDistance) {
00384
00385
00386
00387
00388 moveit_msgs::PositionConstraint pc;
00389 pc.link_name = link_name;
00390 pc.weight=1.0;
00391 pc.target_point_offset.x = 0;
00392 pc.target_point_offset.y = 0;
00393 pc.target_point_offset.z = 0;
00394 pc.header=target_pose.header;
00395
00396 pc.constraint_region.primitives.resize(1);
00397 pc.constraint_region.primitive_poses.resize(1);
00398
00399 shape_msgs::SolidPrimitive &bv = pc.constraint_region.primitives[0];
00400 geometry_msgs::Pose& pose=pc.constraint_region.primitive_poses[0];
00401
00402 geometry_msgs::Pose sphereOrigin=target_pose.pose;
00403 pose=sphereOrigin;
00404 bv=getSphere(maxArmReachDistance);
00405 return pc;
00406 }
00407
00408
00409
00410 moveit_msgs::Constraints MoveItPlanner::getPoseConstraint(const std::string &link_name,
00411 const geometry_msgs::PoseStamped &pose, double tolerance_pos, double tolerance_angle, int type) {
00412
00413 moveit_msgs::Constraints goal;
00414
00415 if (type<=1) {
00416 goal.position_constraints.resize(1);
00417 moveit_msgs::PositionConstraint &pcm = goal.position_constraints[0];
00418 pcm.link_name = link_name;
00419 pcm.target_point_offset.x = 0;
00420 pcm.target_point_offset.y = 0;
00421 pcm.target_point_offset.z = 0;
00422 pcm.constraint_region.primitives.resize(1);
00423 shape_msgs::SolidPrimitive &bv = pcm.constraint_region.primitives[0];
00424 bv=getSphere(tolerance_pos);
00425
00426 pcm.header = pose.header;
00427 pcm.constraint_region.primitive_poses.resize(1);
00428 pcm.constraint_region.primitive_poses[0].position = pose.pose.position;
00429
00430
00431 pcm.constraint_region.primitive_poses[0].orientation.x = 0.0;
00432 pcm.constraint_region.primitive_poses[0].orientation.y = 0.0;
00433 pcm.constraint_region.primitive_poses[0].orientation.z = 0.0;
00434 pcm.constraint_region.primitive_poses[0].orientation.w = 1.0;
00435 pcm.weight = 1.0;
00436 }
00437
00438 if ((type==1) || (type==2)){
00439 goal.orientation_constraints.resize(1);
00440 moveit_msgs::OrientationConstraint &ocm = goal.orientation_constraints[0];
00441 ocm.link_name = link_name;
00442 ocm.header = pose.header;
00443 ocm.orientation = pose.pose.orientation;
00444 ocm.absolute_x_axis_tolerance = tolerance_angle;
00445 ocm.absolute_y_axis_tolerance = tolerance_angle;
00446 ocm.absolute_z_axis_tolerance = tolerance_angle;
00447 ocm.weight = 1.0;
00448 }
00449
00450
00451 return goal;
00452 }
00453