carl_moveit.cpp
Go to the documentation of this file.
00001 #include <carl_moveit/carl_moveit.h>
00002 #include <carl_moveit/eigen_pinv.hpp>
00003 
00004 using namespace std;
00005 
00006 CarlMoveIt::CarlMoveIt() :
00007     tfListener(tfBuffer),
00008     armTrajectoryClient("jaco_arm/joint_velocity_controller/trajectory"),
00009     moveToPoseServer(n, "carl_moveit_wrapper/move_to_pose", boost::bind(&CarlMoveIt::moveToPose, this, _1), false),
00010     moveToJointPoseServer(n, "carl_moveit_wrapper/move_to_joint_pose", boost::bind(&CarlMoveIt::moveToJointPose, this, _1), false)
00011 {
00012   armJointStateSubscriber = n.subscribe("joint_states", 1, &CarlMoveIt::armJointStatesCallback, this);
00013   cartesianControlSubscriber = n.subscribe("carl_moveit_wrapper/cartesian_control", 1, &CarlMoveIt::cartesianControlCallback, this);
00014   armHomedSubscriber = n.subscribe("jaco_arm/arm_homed", 1, &CarlMoveIt::armHomedCallback, this);
00015   recognizedObjectsSubscriber = n.subscribe("object_recognition_listener/recognized_objects", 1, &CarlMoveIt::recognizedObjectsCallback, this);
00016 
00017   angularCmdPublisher = n.advertise<wpi_jaco_msgs::AngularCommand>("jaco_arm/angular_cmd", 1);
00018   trajectoryVisPublisher = n.advertise<moveit_msgs::DisplayTrajectory>("carl_moveit/computed_trajectory", 1);
00019 
00020   ikClient = n.serviceClient<moveit_msgs::GetPositionIK>("compute_ik");
00021   clearOctomapClient = n.serviceClient<std_srvs::Empty>("clear_octomap");
00022 
00023   armGroup = new move_group_interface::MoveGroup("arm");
00024   armGroup->startStateMonitor();
00025 
00026   planningSceneInterface = new move_group_interface::PlanningSceneInterface();
00027 
00028   //advertise service
00029   cartesianPathServer = n.advertiseService("carl_moveit_wrapper/cartesian_path", &CarlMoveIt::cartesianPathCallback, this);
00030   ikServer = n.advertiseService("carl_moveit_wrapper/call_ik", &CarlMoveIt::ikCallback, this);
00031   attachObjectServer = n.advertiseService("carl_moveit_wrapper/attach_closest_object", &CarlMoveIt::attachClosestSceneObject, this);
00032   detachObjectServer = n.advertiseService("carl_moveit_wrapper/detach_objects", &CarlMoveIt::detachSceneObjects, this);
00033 
00034   //start action server
00035   moveToPoseServer.start();
00036   moveToJointPoseServer.start();
00037 }
00038 
00039 CarlMoveIt::~CarlMoveIt()
00040 {
00041   delete armGroup;
00042   delete planningSceneInterface;
00043 }
00044 
00045 void CarlMoveIt::armHomedCallback(const std_msgs::Bool &msg)
00046 {
00047   if (msg.data)
00048   {
00049     std_srvs::Empty srv;
00050     if (!clearOctomapClient.call(srv))
00051       ROS_INFO("Failed to call clear octomap service.");
00052   }
00053 }
00054 
00055 void CarlMoveIt::armJointStatesCallback(const sensor_msgs::JointState &msg)
00056 {
00057   jointState = msg;
00058 }
00059 
00064 static inline double simplify_angle(double angle)
00065 {
00066   double previous_rev = floor(angle / (2.0 * M_PI)) * 2.0 * M_PI;
00067   double next_rev = ceil(angle / (2.0 * M_PI)) * 2.0 * M_PI;
00068   double current_rev;
00069   if (fabs(angle - previous_rev) < fabs(angle - next_rev))
00070     return angle - previous_rev;
00071   return angle - next_rev;
00072 }
00073 
00079 static inline double nearest_equivalent(double desired, double current)
00080 {
00081   //calculate current number of revolutions
00082   double previous_rev = floor(current / (2 * M_PI));
00083   double next_rev = ceil(current / (2 * M_PI));
00084   double current_rev;
00085   if (fabs(current - previous_rev * 2 * M_PI) < fabs(current - next_rev * 2 * M_PI))
00086     current_rev = previous_rev;
00087   else
00088     current_rev = next_rev;
00089 
00090   //determine closest angle
00091   double lowVal = (current_rev - 1) * 2 * M_PI + desired;
00092   double medVal = current_rev * 2 * M_PI + desired;
00093   double highVal = (current_rev + 1) * 2 * M_PI + desired;
00094   if (fabs(current - lowVal) <= fabs(current - medVal) && fabs(current - lowVal) <= fabs(current - highVal))
00095     return lowVal;
00096   if (fabs(current - medVal) <= fabs(current - lowVal) && fabs(current - medVal) <= fabs(current - highVal))
00097     return medVal;
00098   return highVal;
00099 }
00100 
00101 void CarlMoveIt::moveToPose(const rail_manipulation_msgs::MoveToPoseGoalConstPtr &goal)
00102 {
00103   moveit_msgs::GetPositionIK::Response ikRes = callIK(goal->pose);
00104 
00105   rail_manipulation_msgs::MoveToPoseResult result;
00106   if (ikRes.error_code.val == ikRes.error_code.SUCCESS)
00107   {
00108     ROS_INFO("IK service call succeeded");
00109 
00110     //extract joint states
00111     int jacoStartIndex = 0;
00112     for (unsigned int i = 0; i < jointState.name.size(); i++)
00113     {
00114       if (jointState.name[i].compare("jaco_joint_1") == 0)
00115       {
00116         jacoStartIndex = i;
00117         break;
00118       }
00119     }
00120 
00121     std::vector<double> jointGoal;
00122     jointGoal.resize(6);
00123     //set joints to be closest to current joint positions
00124     for (unsigned int i = jacoStartIndex; i < jacoStartIndex + NUM_JACO_JOINTS; i++)
00125     {
00126       jointGoal[i - jacoStartIndex] = nearest_equivalent(simplify_angle(ikRes.solution.joint_state.position[i]), jointState.position[i]);
00127     }
00128 
00129     //plan and execute
00130     armGroup->setPlannerId("arm[KPIECEkConfigDefault]");
00131     if (goal->planningTime == 0.0)
00132       armGroup->setPlanningTime(5.0);
00133     else
00134       armGroup->setPlanningTime(goal->planningTime);
00135     armGroup->setStartStateToCurrentState();
00136     armGroup->setJointValueTarget(jointGoal);
00137     ROS_INFO("Planning and moving...");
00138     //armGroup->asyncMove();
00139     move_group_interface::MoveItErrorCode errorCode = armGroup->move();
00140     ROS_INFO("Finished plan and move");
00141     if (errorCode == moveit_msgs::MoveItErrorCodes::SUCCESS)
00142     {
00143       ROS_INFO("Succeeded");
00144       result.success = true;
00145     }
00146     else
00147     {
00148       ROS_INFO("Failed with MoveIt error code: %d", errorCode.val);
00149       result.success = false;
00150     }
00151   }
00152   else
00153   {
00154     ROS_INFO("IK service call failed with error code: %d", ikRes.error_code.val);
00155     result.success = false;
00156   }
00157 
00158   moveToPoseServer.setSucceeded(result);
00159 }
00160 
00161 void CarlMoveIt::moveToJointPose(const rail_manipulation_msgs::MoveToJointPoseGoalConstPtr &goal)
00162 {
00163   //extract joint states
00164   int jacoStartIndex = 0;
00165   for (unsigned int i = 0; i < jointState.name.size(); i++)
00166   {
00167     if (jointState.name[i].compare("jaco_joint_1") == 0)
00168     {
00169       jacoStartIndex = i;
00170       break;
00171     }
00172   }
00173 
00174   vector<double> jointGoal;
00175   jointGoal.resize(NUM_JACO_JOINTS);
00176   //set joints to be closest to current joint positions
00177   for (unsigned int i = jacoStartIndex; i < jacoStartIndex + NUM_JACO_JOINTS; i++)
00178   {
00179     jointGoal[i - jacoStartIndex] = nearest_equivalent(simplify_angle(goal->joints[i - jacoStartIndex]), jointState.position[i]);
00180   }
00181 
00182   //plan and execute
00183   rail_manipulation_msgs::MoveToJointPoseResult result;
00184   armGroup->setPlannerId("arm[KPIECEkConfigDefault]");
00185   if (goal->planningTime == 0.0)
00186     armGroup->setPlanningTime(5.0);
00187   else
00188     armGroup->setPlanningTime(goal->planningTime);
00189   armGroup->setStartStateToCurrentState();
00190   armGroup->setJointValueTarget(jointGoal);
00191   ROS_INFO("Planning and moving...");
00192   //armGroup->asyncMove();
00193   move_group_interface::MoveItErrorCode errorCode = armGroup->move();
00194   ROS_INFO("Finished plan and move");
00195   if (errorCode == moveit_msgs::MoveItErrorCodes::SUCCESS)
00196   {
00197     ROS_INFO("Succeeded");
00198     result.success = true;
00199   }
00200   else
00201   {
00202     ROS_INFO("Failed with MoveIt error code: %d", errorCode.val);
00203     result.success = false;
00204   }
00205 
00206   moveToJointPoseServer.setSucceeded(result);
00207 }
00208 
00209 bool CarlMoveIt::cartesianPathCallback(rail_manipulation_msgs::CartesianPath::Request &req, rail_manipulation_msgs::CartesianPath::Response &res)
00210 {
00211   double eefStep = .05;
00212   double  jumpThreshold = 1.5;
00213   moveit_msgs::RobotTrajectory finalTraj;
00214 
00215   //convert waypoints to correct frame
00216   vector<geometry_msgs::Pose> convertedWaypoints;
00217   for (unsigned int i = 0; i < req.waypoints.size(); i ++)
00218   {
00219     geometry_msgs::PoseStamped tempPose;
00220     tempPose.header.frame_id = armGroup->getPoseReferenceFrame();
00221     tf.transformPose(armGroup->getPoseReferenceFrame(), req.waypoints[i], tempPose);
00222     convertedWaypoints.push_back(tempPose.pose);
00223   }
00224 
00225   //calculate trajectory
00226   moveit_msgs::RobotTrajectory tempTraj;
00227   double completion = armGroup->computeCartesianPath(convertedWaypoints, eefStep, jumpThreshold, tempTraj, req.avoidCollisions);
00228   if (completion == -1)
00229   {
00230     ROS_INFO("Could not calculate a path.");
00231     res.success = false;
00232     return true;
00233   }
00234 
00235   if (completion == 1.0)
00236   {
00237     finalTraj = tempTraj;
00238   }
00239   else
00240   {
00241     ROS_INFO("Could not find a complete path, varying parameters and recalculating...");
00242     //vary jumpThreshold and eefStep
00243     for (unsigned int i = 0; i < 2; i ++)
00244     {
00245       double newCompletion;
00246       if (i != 0)
00247         jumpThreshold += 1.5;
00248       for (unsigned int j = 0; j < 3; j ++)
00249       {
00250         if (j == 0)
00251           eefStep /= 2.0;
00252         else
00253           eefStep *= 2.0;
00254         newCompletion = armGroup->computeCartesianPath(convertedWaypoints, eefStep, jumpThreshold, tempTraj, req.avoidCollisions);
00255         if (newCompletion > completion)
00256         {
00257           ROS_INFO("Found a better path.");
00258           finalTraj = tempTraj;
00259           completion = newCompletion;
00260           if (newCompletion == 1.0)
00261           {
00262             ROS_INFO("Found a complete path!");
00263             break;
00264           }
00265         }
00266       }
00267       if (newCompletion == 1.0)
00268         break;
00269     }
00270   }
00271 
00272   if (completion == 0.0)
00273   {
00274     ROS_INFO("Could not calculate a path.");
00275     res.success = false;
00276     return true;
00277   }
00278   else
00279   {
00280     res.success = true;
00281     res.completion = completion;
00282   }
00283 
00284   //display trajectory
00285   /*
00286   moveit_msgs::DisplayTrajectory trajVis;
00287   trajVis.model_id = "carl";
00288   trajVis.trajectory.clear();
00289   trajVis.trajectory.push_back(finalTraj);
00290   moveit::core::robotStateToRobotStateMsg(*(armGroup->getCurrentState()), trajVis.trajectory_start);
00291   trajectoryVisPublisher.publish(trajVis);
00292   */
00293 
00294   //execute the trajectory
00295   move_group_interface::MoveGroup::Plan plan;
00296   plan.trajectory_ = finalTraj;
00297   moveit::core::robotStateToRobotStateMsg(*(armGroup->getCurrentState()), plan.start_state_);
00298   //plan.planning_time_ = 0.0; //does this matter?
00299   armGroup->execute(plan);
00300 
00301   res.success = true;
00302   return true;
00303 }
00304 
00305 bool CarlMoveIt::ikCallback(rail_manipulation_msgs::CallIK::Request &req, rail_manipulation_msgs::CallIK::Response &res)
00306 {
00307   moveit_msgs::GetPositionIK::Response ikRes = callIK(req.pose);
00308 
00309   if (ikRes.error_code.val == ikRes.error_code.SUCCESS)
00310   {
00311     ROS_INFO("IK service call succeeded");
00312 
00313     //extract joint states
00314     int jacoStartIndex = 0;
00315     for (unsigned int i = 0; i < jointState.name.size(); i++)
00316     {
00317       if (jointState.name[i].compare("jaco_joint_1") == 0)
00318       {
00319         jacoStartIndex = i;
00320         break;
00321       }
00322     }
00323 
00324     std::vector<double> joints;
00325     joints.resize(6);
00326     //set joints to be closest to current joint positions
00327     for (unsigned int i = jacoStartIndex; i <= jacoStartIndex + NUM_JACO_JOINTS; i++)
00328     {
00329       joints[i - jacoStartIndex] = nearest_equivalent(simplify_angle(ikRes.solution.joint_state.position[i]), jointState.position[i]);
00330     }
00331 
00332     res.jointPositions = joints;
00333     res.success = true;
00334   }
00335   else
00336   {
00337     ROS_INFO("IK service call failed with error code: %d", ikRes.error_code.val);
00338     res.success = false;
00339   }
00340 
00341   return true;
00342 }
00343 
00344 moveit_msgs::GetPositionIK::Response CarlMoveIt::callIK(geometry_msgs::PoseStamped pose)
00345 {
00346   moveit_msgs::GetPositionIK::Request ikReq;
00347   moveit_msgs::GetPositionIK::Response ikRes;
00348 
00349   //robot_state::RobotStatePtr kinematicState(new robot_state::RobotState(kinematicModel));
00350   robot_state::RobotStatePtr kinematicState = armGroup->getCurrentState();
00351   const robot_state::JointModelGroup *jointModelGroup = kinematicState->getRobotModel()->getJointModelGroup("arm");
00352   //kinematicState->setVariableValues(jointState);
00353 
00354   ikReq.ik_request.group_name = "arm";
00355   ikReq.ik_request.pose_stamped = pose;
00356   ikReq.ik_request.ik_link_name = "jaco_link_eef";
00357   //seed state
00358   ikReq.ik_request.robot_state.joint_state.name = jointModelGroup->getJointModelNames();
00359   kinematicState->copyJointGroupPositions(jointModelGroup, ikReq.ik_request.robot_state.joint_state.position);
00360   //other parameters
00361   //ikReq.ik_request.avoid_collisions = true;
00362   ikReq.ik_request.timeout = ros::Duration(.1);
00363   ikReq.ik_request.attempts = 10;
00364 
00365   ikClient.call(ikReq, ikRes);
00366 
00367   return ikRes;
00368 }
00369 
00370 void CarlMoveIt::cartesianControlCallback(const geometry_msgs::Twist &msg)
00371 {
00372   //get the jacobian
00373   robot_state::RobotStatePtr kinematicState = armGroup->getCurrentState();
00374   const moveit::core::JointModelGroup* jointModelGroup = kinematicState->getRobotModel()->getJointModelGroup("arm");
00375   Eigen::Vector3d referencePointPosition(0.0, 0.0, 0.0);  //what does this do?
00376   Eigen::MatrixXd jacobian;
00377   kinematicState->getJacobian(jointModelGroup, kinematicState->getLinkModel(jointModelGroup->getLinkModelNames().back()), referencePointPosition, jacobian);
00378 
00379   //calculate the jacobian pseudoinverse
00380 
00381   //Method 1: SVD
00382   Eigen::MatrixXd pInv = EIGEN_PINV::pinv(jacobian, 0.001);
00383 
00384 
00385   //Method 2: Permuting the jacobian's main diagonal
00386   /*
00387   Eigen::MatrixXd pInv;
00388   float val = .001;
00389   Eigen::MatrixXd permutedJacobian = jacobian + val*Eigen::MatrixXd::Identity(6, 6);
00390   pInv = permutedJacobian.inverse();
00391   */
00392 
00393   //calculate joint velocities
00394   Eigen::VectorXd twist(6);
00395   twist << msg.linear.x, msg.linear.y, msg.linear.z, msg.angular.x, msg.angular.y, msg.angular.z;
00396   Eigen::VectorXd jointVel(6);
00397   jointVel = pInv * twist;
00398 
00399   //publish joint velocity command to the arm
00400   wpi_jaco_msgs::AngularCommand cmd;
00401   cmd.position = false;
00402   cmd.armCommand = true;
00403   cmd.fingerCommand = false;
00404   cmd.repeat = true;
00405   cmd.joints.resize(6);
00406   for(unsigned int i = 0; i < jointVel.size(); i ++)
00407   {
00408     cmd.joints[i] = jointVel[i];
00409   }
00410   angularCmdPublisher.publish(cmd);
00411 }
00412 
00413 void CarlMoveIt::recognizedObjectsCallback(const rail_manipulation_msgs::SegmentedObjectList &msg)
00414 {
00415   //remove previously detected collision objects
00416   unattachedObjects.clear();  //clear list of unattached scene object names
00417   vector<string> previousObjects = planningSceneInterface->getKnownObjectNames();
00418   if (!attachedObjects.empty())
00419   {
00420     //don't remove the attached object
00421     for (unsigned int i = 0; i < previousObjects.size(); i ++)
00422     {
00423       for (unsigned int j = 0; j < attachedObjects.size(); j ++)
00424       if (previousObjects[i] == attachedObjects[j])
00425       {
00426         previousObjects.erase(previousObjects.begin() + i);
00427         i --;
00428         break;
00429       }
00430     }
00431   }
00432   planningSceneInterface->removeCollisionObjects(previousObjects);
00433 
00434   {
00435     boost::recursive_mutex::scoped_lock lock(api_mutex); //lock for the stored objects array
00436 
00437     //store objects
00438     objectList = msg;
00439 
00440     if (!msg.objects.empty())
00441     {
00442       //add all objects to the planning scene
00443       vector<moveit_msgs::CollisionObject> collisionObjects;
00444       collisionObjects.resize(msg.objects.size());
00445       for (unsigned int i = 0; i < collisionObjects.size(); i++)
00446       {
00447         //create collision object
00448         collisionObjects[i].header.frame_id = msg.objects[i].point_cloud.header.frame_id;
00449         stringstream ss;
00450         if (msg.objects[i].recognized)
00451           ss << msg.objects[i].name << i;
00452         else
00453           ss << "object" << i;
00454         //check for name collisions
00455         for (unsigned int j = 0; j < attachedObjects.size(); j ++)
00456         {
00457           if (ss.str() == attachedObjects[j])
00458             ss << "(2)";
00459         }
00460         collisionObjects[i].id = ss.str();
00461         unattachedObjects.push_back(ss.str());
00462 
00463         //convert point cloud to pcl point cloud
00464         pcl::PointCloud<pcl::PointXYZRGB>::Ptr objectCloud(new pcl::PointCloud<pcl::PointXYZRGB>);
00465         pcl::PCLPointCloud2 converter;
00466         pcl_conversions::toPCL(msg.objects[i].point_cloud, converter);
00467         pcl::fromPCLPointCloud2(converter, *objectCloud);
00468 
00469         // compute principal direction
00470         Eigen::Matrix3f covariance;
00471         Eigen::Vector4f centroid;
00472         centroid[0] = msg.objects[i].centroid.x;
00473         centroid[1] = msg.objects[i].centroid.y;
00474         centroid[2] = msg.objects[i].centroid.z;
00475         pcl::computeCovarianceMatrixNormalized(*objectCloud, centroid, covariance);
00476         Eigen::SelfAdjointEigenSolver<Eigen::Matrix3f> eigen_solver(covariance, Eigen::ComputeEigenvectors);
00477         Eigen::Matrix3f eig_dx = eigen_solver.eigenvectors();
00478         eig_dx.col(2) = eig_dx.col(0).cross(eig_dx.col(1));
00479 
00480         //move the points to that reference frame
00481         Eigen::Matrix4f p2w(Eigen::Matrix4f::Identity());
00482         p2w.block(0, 0, 3, 3) = eig_dx.transpose();
00483         p2w.block(0, 3, 3, 1) = -1.f * (p2w.block(0, 0, 3, 3) * centroid.head(3));
00484         pcl::PointCloud<pcl::PointXYZRGB> c_points;
00485         pcl::transformPointCloud(*objectCloud, c_points, p2w);
00486 
00487         pcl::PointXYZRGB min_pt, max_pt;
00488         pcl::getMinMax3D(c_points, min_pt, max_pt);
00489         const Eigen::Vector3f mean_diag = 0.5f * (max_pt.getVector3fMap() + min_pt.getVector3fMap());
00490 
00491         //final transform
00492         const Eigen::Quaternionf qfinal(eig_dx);
00493         const Eigen::Vector3f tfinal = eig_dx * mean_diag + centroid.head(3);
00494 
00495         //set object shape
00496         shape_msgs::SolidPrimitive boundingVolume;
00497         boundingVolume.type = shape_msgs::SolidPrimitive::BOX;
00498         boundingVolume.dimensions.resize(3);
00499         boundingVolume.dimensions[shape_msgs::SolidPrimitive::BOX_X] = max_pt.x - min_pt.x;
00500         boundingVolume.dimensions[shape_msgs::SolidPrimitive::BOX_Y] = max_pt.y - min_pt.y;
00501         boundingVolume.dimensions[shape_msgs::SolidPrimitive::BOX_Z] = max_pt.z - min_pt.z;
00502         collisionObjects[i].primitives.push_back(boundingVolume);
00503         geometry_msgs::Pose pose;
00504         pose.position.x = tfinal[0];
00505         pose.position.y = tfinal[1];
00506         pose.position.z = tfinal[2];
00507         pose.orientation.w = qfinal.w();
00508         pose.orientation.x = qfinal.x();
00509         pose.orientation.y = qfinal.y();
00510         pose.orientation.z = qfinal.z();
00511         collisionObjects[i].primitive_poses.push_back(pose);
00512         collisionObjects[i].operation = moveit_msgs::CollisionObject::ADD;
00513       }
00514 
00515       planningSceneInterface->addCollisionObjects(collisionObjects);
00516     }
00517   }
00518 }
00519 
00520 bool CarlMoveIt::attachClosestSceneObject(std_srvs::Empty::Request &req, std_srvs::Empty::Response &res)
00521 {
00522   boost::recursive_mutex::scoped_lock lock(api_mutex);  //lock for the stored objects array
00523 
00524   //find the closest point to the gripper pose
00525   int closest = 0;
00526   if (objectList.objects.size() == 0)
00527   {
00528     ROS_INFO("No scene objects to attach.");
00529     return true;
00530   } else if (objectList.objects.size() > 1)
00531   {
00532     // find the closest point
00533     float min = numeric_limits<float>::infinity();
00534     //geometry_msgs::Vector3 &v = grasp.transform.translation;
00535     // check each segmented object
00536     for (size_t i = 0; i < objectList.objects.size(); i++)
00537     {
00538       geometry_msgs::TransformStamped eef_transform = tfBuffer.lookupTransform(
00539               objectList.objects[i].point_cloud.header.frame_id, armGroup->getEndEffectorLink(), ros::Time(0)
00540       );
00541       geometry_msgs::Vector3 &v = eef_transform.transform.translation;
00542       //convert PointCloud2 to PointCloud to access the data easily
00543       sensor_msgs::PointCloud cloud;
00544       sensor_msgs::convertPointCloud2ToPointCloud(objectList.objects[i].point_cloud, cloud);
00545       // check each point in the cloud
00546       for (size_t j = 0; j < cloud.points.size(); j++)
00547       {
00548         // euclidean distance to the point
00549         float dist = sqrt(
00550                 pow(cloud.points[j].x - v.x, 2) + pow(cloud.points[j].y - v.y, 2) + pow(cloud.points[j].z - v.z, 2)
00551         );
00552         if (dist < min)
00553         {
00554           min = dist;
00555           closest = i;
00556         }
00557       }
00558     }
00559 
00560     if (min > SCENE_OBJECT_DST_THRESHOLD)
00561     {
00562       ROS_INFO("No scene objects are close enough to the end effector to be attached.");
00563       return true;
00564     }
00565   }
00566 
00567   vector<string> touchLinks;
00568   touchLinks.push_back("jaco_link_eef");
00569   touchLinks.push_back("jaco_link_finger_1");
00570   touchLinks.push_back("jaco_link_finger_2");
00571   touchLinks.push_back("jaco_link_finger_3");
00572   touchLinks.push_back("jaco_link_finger_tip_1");
00573   touchLinks.push_back("jaco_link_finger_tip_2");
00574   touchLinks.push_back("jaco_link_finger_tip_3");
00575   touchLinks.push_back("jaco_link_hand");
00576   armGroup->attachObject(unattachedObjects[closest], armGroup->getEndEffectorLink(), touchLinks);
00577   attachedObjects.push_back(unattachedObjects[closest]);
00578   unattachedObjects.erase(unattachedObjects.begin() + closest);
00579 
00580   return true;
00581 }
00582 
00583 bool CarlMoveIt::detachSceneObjects(std_srvs::Empty::Request &req, std_srvs::Empty::Response &res)
00584 {
00585   for (int i = 0; i < attachedObjects.size(); i ++)
00586   {
00587     armGroup->detachObject(attachedObjects[i]);
00588   }
00589   planningSceneInterface->removeCollisionObjects(attachedObjects);
00590   attachedObjects.clear();
00591 
00592   return true;
00593 }
00594 
00595 int main(int argc, char **argv)
00596 {
00597   ros::init(argc, argv, "carl_moveit_wrapper");
00598 
00599   CarlMoveIt c;
00600 
00601   ros::spin();
00602 }


carl_moveit
Author(s): David Kent
autogenerated on Thu Jun 6 2019 20:28:44