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 #include <ros/ros.h>
00033 #include <actionlib/server/simple_action_server.h>
00034 #include <sensor_msgs/PointCloud2.h>
00035 #include <sensor_msgs/point_cloud_conversion.h>
00036 #include <tf/transform_listener.h>
00037 #include <pcl/io/io.h>
00038 #include "tabletop_object_detector/SegmentObjectInHand.h"
00039 #include "pr2_create_object_model/ModelObjectInHandAction.h"
00040 #include "pr2_create_object_model/ObjectInHand.h"
00041 #include "object_manipulator/tools/mechanism_interface.h"
00042 #include "motion_planning_msgs/LinkPadding.h"
00043 #include "motion_planning_msgs/OrderedCollisionOperations.h"
00044 #include <eigen_conversions/eigen_msg.h>
00045 #include <Eigen/Core>
00046 #include <Eigen/Geometry>
00047 #include <object_manipulation_msgs/ClusterBoundingBox.h>
00048
00049 #include <tabletop_collision_map_processing/collision_map_interface.h>
00050
00051 using pr2_create_object_model::ObjectInHand;
00052
00053 class InHandObjectModeler
00054 {
00055
00056 private:
00057
00059 ros::NodeHandle root_nh_;
00060
00062 ros::NodeHandle priv_nh_;
00063
00065 actionlib::SimpleActionServer<pr2_create_object_model::ModelObjectInHandAction> model_object_action_server_;
00066
00068 pr2_create_object_model::ModelObjectInHandResult model_object_result_;
00069
00071 ros::Publisher pub_cloud;
00072
00074 std::string segment_object_service_name_;
00075
00077 object_manipulator::MechanismInterface mech_interface_;
00078
00080 tabletop_collision_map_processing::CollisionMapInterface collision_map_interface_;
00081
00083 bool stereo_;
00084
00085 public:
00086
00087 InHandObjectModeler() :
00088 root_nh_(""),
00089 priv_nh_("~"),
00090 model_object_action_server_(priv_nh_, "/model_object_in_hand_action",
00091 boost::bind(&InHandObjectModeler::executeCB, this, _1), false)
00092 {
00093 segment_object_service_name_ = "/segment_object_in_hand_srv";
00094
00095 while ( !ros::service::waitForService(segment_object_service_name_, ros::Duration().fromSec(3.0)) && priv_nh_.ok() )
00096 {
00097 ROS_INFO("Waiting for service %s...", segment_object_service_name_.c_str());
00098 }
00099 if (!priv_nh_.ok()) exit(0);
00100
00101 pub_cloud = priv_nh_.advertise<ObjectInHand>("modeled_object_in_hand", 1);
00102
00103 priv_nh_.param<bool>("stereo", stereo_, true);
00104
00105 model_object_action_server_.start();
00106 ROS_INFO("started action server");
00107 }
00108
00110 void executeCB(const pr2_create_object_model::ModelObjectInHandGoalConstPtr &goal)
00111 {
00112 sensor_msgs::PointCloud2 object_in_hand;
00113 sensor_msgs::PointCloud2 cluster;
00114
00115
00116 if(stereo_)
00117 {
00118 int res = system("rosrun dynamic_reconfigure dynparam set_from_parameters /narrow_stereo_textured/narrow_stereo_textured_proc _min_disparity:=30");
00119 }
00120 bool result;
00121
00122
00123 if(!goal->move_arm){
00124 result = callSegmentObjectInHand(goal->arm_name, cluster);
00125 if(result != 0)
00126 {
00127 object_in_hand = cluster;
00128 }
00129 }
00130 else
00131 {
00132
00133 moveArmIntoView(goal->arm_name);
00134
00135
00136 turnArmInwards(goal->arm_name, object_in_hand, goal->keep_level);
00137 }
00138
00139 model_object_result_.cluster = object_in_hand;
00140
00141 std::string collision_name;
00142 if (goal->add_to_collision_map && !object_in_hand.data.empty())
00143 {
00144 try
00145 {
00146 bool success = true;
00147 ros::Time start_time = ros::Time::now();
00148 while (!collision_map_interface_.connectionsEstablished(ros::Duration(1.0)))
00149 {
00150 if (!priv_nh_.ok() || ros::Time::now() - start_time >= ros::Duration(5.0))
00151 {
00152 success = false;
00153 break;
00154 }
00155 }
00156 if (success)
00157 {
00158
00159
00160 if(goal->arm_name == "right_arm")
00161 {
00162 }
00163 else if(goal->arm_name == "left_arm")
00164 {
00165 }
00166
00167
00168 sensor_msgs::PointCloud cluster1;
00169 sensor_msgs::convertPointCloud2ToPointCloud(object_in_hand, cluster1);
00170
00171
00172
00173
00174
00175
00176
00177 object_manipulation_msgs::ClusterBoundingBox bbox;
00178 collision_map_interface_.getClusterBoundingBox(cluster1, bbox.pose_stamped, bbox.dimensions);
00179 collision_map_interface_.processCollisionGeometryForBoundingBox(bbox, collision_name);
00180
00181 ros::Duration(0.5).sleep();
00182
00183 mech_interface_.attachObjectToGripper(goal->arm_name, collision_name);
00184 }
00185 if (!success)
00186 {
00187 ROS_ERROR("Create object model: failed to add object to collision map");
00188 collision_name.clear();
00189 }
00190 }
00191 catch(...)
00192 {
00193 ROS_ERROR("Error while trying to add object to collision map");
00194 collision_name.clear();
00195 }
00196 }
00197
00198
00199 ObjectInHand oih;
00200 oih.cluster = object_in_hand;
00201 oih.arm_name = goal->arm_name;
00202 oih.collision_name = collision_name;
00203 model_object_result_.collision_name = collision_name;
00204 ROS_INFO("frame_id: %s, final num points: %d, collision name: %s",
00205 object_in_hand.header.frame_id.c_str(), (int)object_in_hand.width, collision_name.c_str());
00206 pub_cloud.publish(oih);
00207
00208
00209 if(stereo_)
00210 {
00211 int res = system("rosrun dynamic_reconfigure dynparam set_from_parameters /narrow_stereo_textured/narrow_stereo_textured_proc _min_disparity:=0");
00212 }
00213 model_object_action_server_.setSucceeded(model_object_result_);
00214 }
00215
00217 bool callSegmentObjectInHand(std::string arm_name, sensor_msgs::PointCloud2 &object_in_hand)
00218 {
00219 tabletop_object_detector::SegmentObjectInHand segmentation_srv;
00220 if (arm_name.compare("right_arm") == 0)
00221 segmentation_srv.request.wrist_frame = std::string("r_wrist_roll_link");
00222 else
00223 segmentation_srv.request.wrist_frame = std::string("l_wrist_roll_link");
00224 if (!ros::service::call(segment_object_service_name_, segmentation_srv))
00225 {
00226 ROS_ERROR("Call to segmentation service failed");
00227 return 0;
00228 }
00229 object_in_hand = segmentation_srv.response.cluster;
00230 return 1;
00231 }
00232
00233 void pointHead(std::string arm_name)
00234 {
00235 geometry_msgs::PointStamped desired_head_point;
00236 if(stereo_)
00237 {
00238 if (arm_name.compare("right_arm") == 0)
00239 desired_head_point.header.frame_id = "r_wrist_roll_link";
00240 else
00241 desired_head_point.header.frame_id = "l_wrist_roll_link";
00242 desired_head_point.point.x = .2;
00243 mech_interface_.pointHeadAction(desired_head_point, "/narrow_stereo_optical_frame");
00244 }
00245 else
00246 {
00247 geometry_msgs::PoseStamped gripper_pose = mech_interface_.getGripperPose(arm_name, std::string("torso_lift_link"));
00248 desired_head_point.header.frame_id = "torso_lift_link";
00249 desired_head_point.point.x = gripper_pose.pose.position.x;
00250 desired_head_point.point.y = gripper_pose.pose.position.y;
00251 desired_head_point.point.z = gripper_pose.pose.position.z - .4;
00252 mech_interface_.pointHeadAction(desired_head_point, "/openni_rgb_optical_frame");
00253 }
00254 ROS_INFO("pointing head");
00255 }
00256
00258 bool moveArmIntoView(std::string arm_name)
00259 {
00260 geometry_msgs::PoseStamped desired_pose = mech_interface_.getGripperPose(arm_name, std::string("torso_lift_link"));
00261 desired_pose.pose.position.x = .7;
00262 desired_pose.pose.position.y = 0;
00263 desired_pose.pose.position.z = 0.20;
00264 mech_interface_.moveArmToPoseCartesian(arm_name, desired_pose, ros::Duration(6.0), .015, .09, .03, .2, .1);
00265 ROS_INFO("moving arm in front of head");
00266
00267 pointHead(arm_name);
00268 ros::Duration(0.5).sleep();
00269
00270 return 1;
00271 }
00272
00274 bool turnArmInwards(std::string arm_name, sensor_msgs::PointCloud2 &object_in_hand, int keep_level)
00275 {
00276 geometry_msgs::PoseStamped current_pose = mech_interface_.getGripperPose(arm_name, std::string("torso_lift_link"));
00277 Eigen::eigen2_Transform3d current_trans;
00278 tf::poseMsgToEigen(current_pose.pose, current_trans);
00279 Eigen::eigen2_Transform3d desired_trans;
00280
00281 int num_steps = 0;
00282 double rot_angle;
00283 std::vector<geometry_msgs::PoseStamped> desired_poses;
00284 Eigen::Vector3d z(0,0,1);
00285
00286
00287
00288
00289
00290
00291
00292 if(1)
00293 {
00294
00295
00296
00297 Eigen::Vector3d x_axis = current_trans.rotation().col(0);
00298 rot_angle = atan2(x_axis[1], -x_axis[0]);
00299 std::cout << "rot_angle before:" << rot_angle << std::endl;
00300 if(arm_name.compare("right_arm") == 0 && rot_angle < -M_PI/4) rot_angle += 2*M_PI;
00301 if(arm_name.compare("left_arm") == 0 && rot_angle > M_PI/4) rot_angle -= 2*M_PI;
00302
00303 std::cout << "rot_angle after:" << rot_angle << std::endl;
00304
00305
00306 double max_angle_step = M_PI/8;
00307 num_steps = ceil(fabs(rot_angle) / max_angle_step) + 1;
00308 std::cout << "num_steps:" << num_steps << std::endl;
00309
00310
00311 Eigen::eigen2_Transform3d step_trans;
00312 geometry_msgs::PoseStamped desired_pose;
00313 for(int view_ind=0; view_ind<num_steps; view_ind++)
00314 {
00315 double frac;
00316 if(num_steps == 1) frac = 1;
00317 else frac = view_ind / float(num_steps-1);
00318
00319 Eigen::eigen2_AngleAxis<double> step_rotation(rot_angle*frac, z);
00320 step_trans = step_rotation * current_trans;
00321 for(int i=0; i<3; i++) step_trans(i,3) = current_trans(i,3);
00322 tf::poseEigenToMsg(step_trans, desired_pose.pose);
00323 desired_pose.header.frame_id = "torso_lift_link";
00324 desired_pose.header.stamp = ros::Time::now();
00325 desired_poses.push_back(desired_pose);
00326
00327 }
00328 Eigen::eigen2_Transform3d towards_trans = step_trans;
00329
00330 if(fabs(rot_angle) < M_PI)
00331 {
00332 double additional_angle = -M_PI;
00333 if(arm_name.compare("left_arm") == 0) additional_angle = M_PI;
00334 int num_add_steps = ceil(fabs(additional_angle) / max_angle_step) + 1;
00335 for(double step=0; step<num_add_steps; step++)
00336 {
00337 double frac = step / float(num_add_steps-1);
00338 Eigen::eigen2_AngleAxis<double> step_rotation(additional_angle*frac, z);
00339 step_trans = step_rotation * towards_trans;
00340 for(int i=0; i<3; i++) step_trans(i,3) = towards_trans(i,3);
00341 tf::poseEigenToMsg(step_trans, desired_pose.pose);
00342 desired_pose.header.frame_id = "torso_lift_link";
00343 desired_pose.header.stamp = ros::Time::now();
00344 desired_poses.push_back(desired_pose);
00345 }
00346 }
00347 }
00348
00349
00350 bool result;
00351 sensor_msgs::PointCloud2 cluster;
00352 for(size_t view_ind=0; view_ind<desired_poses.size(); view_ind++){
00353
00354
00355
00356 mech_interface_.moveArmToPoseCartesian(arm_name, desired_poses[view_ind],
00357 ros::Duration(1.0), .015, .09, .02, .16, .1);
00358
00359
00360 pointHead(arm_name);
00361
00362
00363
00364 result = callSegmentObjectInHand(arm_name, cluster);
00365 if(result != 0)
00366 {
00367
00368 if(object_in_hand.width == 0) object_in_hand = cluster;
00369 else
00370 {
00371 result = pcl::concatenatePointCloud(object_in_hand, cluster, object_in_hand);
00372 ROS_INFO("concatenate result: %d", result);
00373 object_in_hand.header.stamp = ros::Time::now();
00374 }
00375
00376
00377 ROS_INFO("frame_id: %s, num points: %d", object_in_hand.header.frame_id.c_str(), (int)object_in_hand.width);
00378 pub_cloud.publish(object_in_hand);
00379 }
00380 }
00381
00382 return 1;
00383 }
00384
00385
00387 bool moveArmAway(std::string arm_name)
00388 {
00389 geometry_msgs::PoseStamped current_pose = mech_interface_.getGripperPose(arm_name, std::string("base_link"));
00390 geometry_msgs::Vector3Stamped translation;
00391 translation.header.frame_id = "base_link";
00392 translation.header.stamp = ros::Time::now();
00393 translation.vector.z = .01;
00394 mech_interface_.translateGripperCartesian(arm_name, translation, ros::Duration(3.0), .015, .09, .02, .16, .1);
00395 return 1;
00396 }
00397
00398 };
00399
00400 int main(int argc, char** argv)
00401 {
00402 ros::init(argc, argv, "create_object_model_server");
00403 InHandObjectModeler node;
00404 ROS_INFO("create object model action server ready");
00405 ros::spin();
00406 return 0;
00407 }