00001 #include <ros/ros.h>
00002 #include <sensor_msgs/PointCloud2.h>
00003
00004 #include <boost/thread/mutex.hpp>
00005
00006
00007 #include <actionlib/client/simple_action_client.h>
00008 #include <pr2_controllers_msgs/PointHeadAction.h>
00009
00010
00011 #include <rosbag/bag.h>
00012
00013
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
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
00032 ros::NodeHandle nh_;
00033
00034
00035 std::string input_cloud_topic_, input_image_topic_, input_camera_info_topic_;
00036 bool cloud_and_image_received_, move_head_;
00037
00038
00039 PointHeadClient* point_head_client_;
00040
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
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
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
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
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
00109 void callback (const sensor_msgs::PointCloud2ConstPtr& pc, const sensor_msgs::ImageConstPtr& im)
00110 {
00111 if (!cloud_and_image_received_)
00112 {
00113
00114
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
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
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
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
00164 pr2_controllers_msgs::PointHeadGoal goal;
00165
00166
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
00173
00174 goal.pointing_frame = "narrow_stereo_optical_frame";
00175
00176
00177 goal.min_duration = ros::Duration(1);
00178
00179
00180 goal.max_velocity = 0.5;
00181
00182
00183 point_head_client_->sendGoal(goal);
00184
00185
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
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
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
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 }