pointcloud_acquisition_with_head_movement.cpp
Go to the documentation of this file.
00001 #include <ros/ros.h>
00002 #include <sensor_msgs/PointCloud2.h>
00003 //boost
00004 #include <boost/thread/mutex.hpp>
00005 
00006 //for moving of the head
00007 #include <actionlib/client/simple_action_client.h>
00008 #include <pr2_controllers_msgs/PointHeadAction.h>
00009 
00010 //for writting to bag
00011 #include <rosbag/bag.h>
00012 
00013 //msg synchronisation
00014 #include <message_filters/subscriber.h>
00015 #include <message_filters/synchronizer.h>
00016 #include <message_filters/sync_policies/approximate_time.h>
00017 
00018 
00019 #include "pcl_ros/transforms.h"
00020 #include <tf/transform_listener.h>
00021 
00022 #include "sensor_msgs/CameraInfo.h"
00023 #include "sensor_msgs/Image.h"
00024 // Our Action interface type, provided as a typedef for convenience
00025 typedef actionlib::SimpleActionClient<pr2_controllers_msgs::PointHeadAction> PointHeadClient;
00026   typedef message_filters::sync_policies::ApproximateTime< sensor_msgs::PointCloud2,
00027                                                            sensor_msgs::Image > MySyncPolicy;
00028 
00029 class PointCloudCapturer
00030 {
00031   //subscribers/publishers
00032   ros::NodeHandle nh_;
00033   //ros::Subscriber cloud_sub_;
00034 
00035   std::string input_cloud_topic_, input_image_topic_, input_camera_info_topic_;
00036   bool cloud_and_image_received_, move_head_;
00037 
00038   //point head client
00039   PointHeadClient* point_head_client_;
00040   //move offset
00041   double move_offset_y_min_, move_offset_y_max_, step_y_; 
00042   double move_offset_z_min_, move_offset_z_max_, step_z_;
00043   double move_offset_x_;
00044   double current_position_x_, current_position_y_, current_position_z_;
00045   double rate_;
00046   boost::thread spin_thread_;
00047   double EPS;
00048   rosbag::Bag bag_;
00049   std::string bag_name_;
00050   tf::TransformListener tf_;
00051   std::string to_frame_;
00052   //ros::Subscriber camera_sub_;
00053 
00054   message_filters::Subscriber<sensor_msgs::Image> camera_sub_;
00055   message_filters::Subscriber<sensor_msgs::PointCloud2> cloud_sub_;
00056   message_filters::Synchronizer<MySyncPolicy> synchronizer_;
00057   message_filters::Connection sync_connection_;
00058   sensor_msgs::CameraInfoConstPtr cam_info_;
00059 public:
00060   PointCloudCapturer(ros::NodeHandle &n)
00061     :  nh_(n), synchronizer_( MySyncPolicy(1), cloud_sub_, camera_sub_)
00062   {
00063     nh_.param("input_cloud_topic", input_cloud_topic_, std::string("/kinect_head/camera/rgb/points"));
00064     nh_.param("input_image_topic", input_image_topic_, std::string("/kinect_head/camera/rgb/image_color"));
00065     nh_.param("input_camera_info_topic", input_camera_info_topic_, std::string("/kinect_head/camera/rgb/camera_info"));
00066 //    cloud_sub_= nh_.subscribe (input_cloud_topic_, 10, &PointCloudCapturer::cloud_cb, this);
00067   
00068     camera_sub_.subscribe( nh_, input_image_topic_, 1000 );
00069     cloud_sub_.subscribe( nh_, input_cloud_topic_, 1000 );
00070 
00071     sync_connection_ = synchronizer_.registerCallback( &PointCloudCapturer::callback, this );
00072 
00073     ROS_INFO("[PointCloudColorizer:] Subscribing to cloud topic %s", input_cloud_topic_.c_str());
00074 
00075     point_head_client_ = new PointHeadClient("/head_traj_controller/point_head_action", true);
00076     //wait for head controller action server to come up 
00077     while(!point_head_client_->waitForServer(ros::Duration(5.0)) && ros::ok())
00078     {
00079       ROS_INFO("Waiting for the point_head_action server to come up");
00080     }
00081     cloud_and_image_received_ = false;
00082     nh_.param("move_offset_y_min", move_offset_y_min_, -1.5);
00083     nh_.param("move_offset_y_max", move_offset_y_max_, 1.5);
00084     nh_.param("step_y", step_y_, 0.3);
00085     nh_.param("move_offset_z_min", move_offset_z_min_, 0.3);
00086     nh_.param("move_offset_z_max", move_offset_z_max_, 1.5);
00087     nh_.param("step_z", step_z_, 0.3);
00088     nh_.param("move_offset_x", move_offset_x_, 1.0);
00089     nh_.param("bag_name", bag_name_, std::string("bosch_kitchen_tr.bag"));
00090     nh_.param("to_frame", to_frame_, std::string("base_link"));
00091     nh_.param("rate", rate_, 1.0);
00092     current_position_x_ = move_offset_x_;
00093     current_position_y_ = move_offset_y_min_;
00094     current_position_z_ = move_offset_z_min_;
00095     move_head("base_link", current_position_x_, current_position_y_, current_position_z_);
00096     EPS = 1e-5;
00097     //thread ROS spinner
00098     spin_thread_ = boost::thread (boost::bind (&ros::spin));
00099     bag_.open(bag_name_, rosbag::bagmode::Write);
00100   }
00101 
00102   ~PointCloudCapturer()
00103   {
00104     bag_.close();
00105     delete point_head_client_;
00106   }
00107 
00108 //  void cloud_cb (const sensor_msgs::PointCloud2ConstPtr& pc)
00109   void callback (const sensor_msgs::PointCloud2ConstPtr& pc, const sensor_msgs::ImageConstPtr& im)
00110   {
00111     if (!cloud_and_image_received_)
00112     {
00113       //Write cloud
00114       //transform to target frame
00115       bool found_transform = tf_.waitForTransform(pc->header.frame_id, to_frame_,
00116                                                   pc->header.stamp, ros::Duration(10.0));
00117       tf::StampedTransform transform;
00118       if (found_transform)
00119       {
00120         //ROS_ASSERT_MSG(found_transform, "Could not transform to camera frame");
00121         tf_.lookupTransform(to_frame_,pc->header.frame_id, pc->header.stamp, transform);
00122         ROS_DEBUG("[TransformPointcloudNode:] Point cloud published in frame %s", pc->header.frame_id.c_str());
00123       }
00124       else
00125       {
00126         ROS_ERROR("No transform for pointcloud found!!!");
00127         return;
00128       }
00129       bag_.write(input_cloud_topic_, pc->header.stamp, *pc);
00130       geometry_msgs::TransformStamped transform_msg;
00131       tf::transformStampedTFToMsg(transform, transform_msg);
00132       bag_.write(input_cloud_topic_ + "/transform", transform_msg.header.stamp, transform_msg);
00133       ROS_INFO("Wrote cloud to %s", bag_name_.c_str());
00134 
00135       //Write image
00136       found_transform = tf_.waitForTransform(im->header.frame_id, to_frame_,
00137                                                   im->header.stamp, ros::Duration(10.0));
00138       if (found_transform)
00139       {
00140         //ROS_ASSERT_MSG(found_transform, "Could not transform to camera frame");
00141         tf_.lookupTransform(to_frame_,im->header.frame_id, im->header.stamp, transform);
00142         ROS_DEBUG("[TransformPointcloudNode:] Point cloud published in frame %s", im->header.frame_id.c_str());
00143       }
00144       else
00145       {
00146         ROS_ERROR("No transform for image found!!!");
00147         return;
00148       }
00149       bag_.write(input_image_topic_, im->header.stamp, im);
00150       tf::transformStampedTFToMsg(transform, transform_msg);
00151       bag_.write(input_image_topic_ + "/transform", transform_msg.header.stamp, transform_msg);
00152       ROS_INFO("Wrote image to %s", bag_name_.c_str());
00153 
00154       cam_info_ = ros::topic::waitForMessage<sensor_msgs::CameraInfo>(input_camera_info_topic_);
00155       bag_.write(input_camera_info_topic_, cam_info_->header.stamp, cam_info_);
00156       ROS_INFO("Wrote Camera Info to %s", bag_name_.c_str());
00157       cloud_and_image_received_ = true;
00158     }
00159   }
00160 
00161   void move_head (std::string frame_id, double x, double y, double z)
00162   {
00163     //the goal message we will be sending
00164     pr2_controllers_msgs::PointHeadGoal goal;
00165     
00166     //the target point, expressed in the requested frame
00167     geometry_msgs::PointStamped point;
00168     point.header.frame_id = frame_id;
00169     point.point.x = x; point.point.y = y; point.point.z = z;
00170     goal.target = point;
00171     
00172     //we are pointing the wide_stereo camera frame 
00173     //(pointing_axis defaults to X-axis)
00174     goal.pointing_frame = "narrow_stereo_optical_frame";
00175     
00176     //take at least 2 seconds to get there
00177     goal.min_duration = ros::Duration(1);
00178     
00179     //and go no faster than 0.1 rad/s
00180     goal.max_velocity = 0.5;
00181     
00182     //send the goal
00183     point_head_client_->sendGoal(goal);
00184     
00185     //wait for it to get there
00186     bool finished_within_time = point_head_client_->waitForResult(ros::Duration(20.0));
00187     if (!finished_within_time)
00188     {
00189       ROS_ERROR("Head did not move to pose: %f %f %f", point.point.x, point.point.y, point.point.z);
00190     }
00191     else
00192     {
00193       actionlib::SimpleClientGoalState state = point_head_client_->getState();
00194       bool success = (state == actionlib::SimpleClientGoalState::SUCCEEDED);
00195       if(success)
00196         ROS_INFO("Action move head finished: %s position: %f %f %f", state.toString().c_str(), point.point.x, point.point.y, point.point.z);
00197       else
00198         ROS_ERROR("Action move head failed: %s", state.toString().c_str());
00199     }
00200   }
00201 
00202   void spin ()
00203     {
00204       ros::Rate loop_rate(rate_);
00205       while (ros::ok())
00206       {
00207         if (cloud_and_image_received_)
00208         {
00209           // swing left to right and right to left by increasing y step
00210           if ( (((move_offset_y_min_ < current_position_y_) && (current_position_y_ < move_offset_y_max_))
00211                 || (fabs(current_position_y_ - move_offset_y_min_) < EPS) || (fabs(current_position_y_ - move_offset_y_max_) < EPS))
00212                && 
00213                ((current_position_z_ < move_offset_z_max_) 
00214                 || (fabs(current_position_z_ - move_offset_z_min_) < EPS) || (fabs(current_position_z_ - move_offset_z_max_) < EPS)) )
00215           {
00216             current_position_y_ += step_y_;
00217             ROS_INFO("in left to right");
00218           }
00219      
00220           // increase z step
00221           else if ( ((current_position_y_ < move_offset_y_min_) || (current_position_y_ > move_offset_y_max_)) 
00222                     && 
00223                     (current_position_z_ < move_offset_z_max_) )
00224           {
00225             current_position_z_ += step_z_;
00226             step_y_ = -step_y_;
00227             current_position_y_ += step_y_;
00228             ROS_INFO("in increase z");
00229           }
00230 
00231           // check if we are done
00232           else if ( ((current_position_y_ < move_offset_y_min_) || (current_position_y_ > move_offset_y_max_)) 
00233                     && 
00234                     ((current_position_z_ > move_offset_z_max_) || (fabs(current_position_z_ - move_offset_z_max_) < EPS)) )
00235           {
00236             ROS_INFO("DONE - exiting");
00237             ros::shutdown();
00238           }
00239           else
00240           {
00241             ROS_INFO("Not an option");
00242           }
00243           move_head("base_link", current_position_x_, current_position_y_, current_position_z_);
00244           cloud_and_image_received_ = false; 
00245         }
00246         ros::spinOnce();
00247         loop_rate.sleep();
00248        }
00249     }
00250 };
00251 
00252 int main(int argc, char** argv)
00253 {
00254   ros::init(argc, argv, "pointcloud_capturer_node");
00255   ros::NodeHandle n("~");
00256   PointCloudCapturer pp(n);
00257   pp.spin();
00258 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Properties Friends


pr2_data_acquisition_tools
Author(s): Dejan Pangercic
autogenerated on Sun Oct 6 2013 11:56:39