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 #include <pcl/point_cloud.h>
00030 #include <pcl/octree/octree.h>
00031 #include <pcl_ros/point_cloud.h>
00032 #include <pcl/point_types.h>
00033 #include <pcl/filters/extract_indices.h>
00034
00035 #include <geometry_msgs/PoseStamped.h>
00036 #include <geometry_msgs/PointStamped.h>
00037
00038 #include <tf/transform_listener.h>
00039 #include <tf/transform_broadcaster.h>
00040 #include <pcl_ros/transforms.h>
00041 #include <pcl/io/pcd_io.h>
00042
00043 #include <ros/ros.h>
00044 #include "sensor_msgs/PointCloud2.h"
00045
00046 #include <iostream>
00047 #include <vector>
00048
00049 #include <message_filters/subscriber.h>
00050 #include <message_filters/synchronizer.h>
00051 #include <message_filters/sync_policies/approximate_time.h>
00052
00053 #include <float.h>
00054 #include <math.h>
00055
00056
00057 template <typename T>
00058 class NeverEmptyQueue : public std::queue<T>
00059 {
00060 public:
00061 virtual void pop() {
00062 if(this->size() > 1) std::queue<T>::pop();
00063 }
00064 };
00065
00066
00067 typedef pcl::PointCloud<pcl::PointXYZ> PointCloud;
00068 typedef std::vector<pcl::PointXYZ, Eigen::aligned_allocator<pcl::PointXYZ> > AlignedPointTVector;
00069
00070 ros::Publisher cloud_pub;
00071 ros::Publisher point_pub;
00072 tf::TransformListener* listener;
00073 tf::TransformBroadcaster* broadcaster;
00074 tf::StampedTransform g_transform;
00075 bool g_transform_ready = false;
00076
00077 sensor_msgs::PointCloud2ConstPtr g_cloud;
00078 geometry_msgs::PoseStampedConstPtr g_pose;
00079
00080 bool g_cloud_ready = false;
00081 bool g_pose_ready = false;
00082
00083 NeverEmptyQueue<sensor_msgs::PointCloud2ConstPtr> g_cloud_queue;
00084 NeverEmptyQueue<geometry_msgs::PoseStampedConstPtr> g_pose_queue;
00085
00086
00087 double g_resolution, g_min_dist;
00088 std::string g_vector_frame;
00089
00090 void cloudCallback(const sensor_msgs::PointCloud2ConstPtr& cloud_msg) {
00091 g_cloud_queue.push(cloud_msg);
00092 }
00093
00094 void poseCallback(const geometry_msgs::PoseStampedConstPtr& pose) {
00095 g_pose_queue.push(pose);
00096 }
00097
00098
00099 void intersectPose(const sensor_msgs::PointCloud2ConstPtr& cloud_msg, const geometry_msgs::PoseStampedConstPtr& pose) {
00100 sensor_msgs::PointCloud2 cloud_transformed;
00101 std::string vector_frame = pose->header.frame_id;
00102 ros::Time stamp = ros::Time(0);
00103 if(!((pose->pose.position.x == 0) && (pose->pose.position.y) == 0 && (pose->pose.position.z == 0))) {
00104
00105 tf::Transform trans;
00106 trans.setOrigin(tf::Vector3(
00107 pose->pose.position.x,
00108 pose->pose.position.y,
00109 pose->pose.position.z
00110 ));
00111 trans.setRotation(tf::Quaternion(
00112 pose->pose.orientation.x,
00113 pose->pose.orientation.y,
00114 pose->pose.orientation.z,
00115 pose->pose.orientation.w
00116 ));
00117 vector_frame = g_vector_frame;
00118 g_transform = tf::StampedTransform(trans, stamp, pose->header.frame_id, vector_frame);
00119 g_transform_ready = true;
00120
00121 }
00122 sensor_msgs::PointCloud2 cloud_msg_copy = *cloud_msg;
00123 cloud_msg_copy.header.stamp=ros::Time(0);
00124 listener->waitForTransform(cloud_msg->header.frame_id, vector_frame, stamp, ros::Duration(2.0));
00125 pcl_ros::transformPointCloud(vector_frame, cloud_msg_copy, cloud_transformed, *listener);
00126 int tPoints = cloud_transformed.width*cloud_transformed.height;
00127 if(tPoints == 0) return;
00128 PointCloud cloud;
00129 pcl::fromROSMsg(cloud_transformed, cloud);
00130
00131 pcl::octree::OctreePointCloudSearch<pcl::PointXYZ> octree (g_resolution);
00132 octree.setInputCloud(cloud.makeShared());
00133 octree.addPointsFromInputCloud();
00134
00135 Eigen::Vector3f origin(0, 0, 0);
00136 Eigen::Vector3f direction(RAND_MAX, 0.0f, 0.0f);
00137 std::vector<int> k_indices;
00138
00139 int nPoints = octree.getIntersectedVoxelIndices(origin, direction, k_indices);
00140 PointCloud::Ptr out (new PointCloud);
00141 out->header.frame_id = vector_frame;
00142 for(int i=0; i<nPoints; i++) {
00143 if(g_min_dist < DBL_MAX) {
00144 pcl::PointXYZ pt = cloud.points[k_indices[i]];
00145 if(sqrt(pt.x*pt.x + pt.y*pt.y + pt.z*pt.z) > g_min_dist)
00146 out->points.push_back(cloud.points[k_indices[i]]);
00147 }
00148 }
00149 out->header.stamp = ros::Time::now();
00150 sensor_msgs::PointCloud2 out_msg;
00151 pcl::toROSMsg(*out, out_msg);
00152 sensor_msgs::PointCloud2 out_transformed;
00153 out_msg.header.stamp=ros::Time(0);
00154 listener->waitForTransform(out->header.frame_id, "base_link", ros::Time(0), ros::Duration(2.0));
00155 pcl_ros::transformPointCloud("base_link", out_msg, out_transformed, *listener);
00156 cloud_pub.publish(out_transformed);
00157 }
00158
00159 void sendTransform(const ros::TimerEvent& te) {
00160 if(g_transform_ready) {
00161 g_transform.stamp_ = ros::Time::now();
00162 broadcaster->sendTransform(g_transform);
00163 }
00164 }
00165
00166 int main(int argc, char* argv[]) {
00167 ros::init(argc, argv, "world_intersect");
00168 ros::NodeHandle nh;
00169
00170 ros::NodeHandle pnh("~");
00171 pnh.param("vector_frame", g_vector_frame, std::string("intersected_vector"));
00172 pnh.param("octree_resolution", g_resolution, 0.02);
00173 pnh.param("min_dist", g_min_dist, DBL_MAX);
00174
00175 listener = new tf::TransformListener(ros::Duration(45));
00176 broadcaster = new tf::TransformBroadcaster();
00177
00178 cloud_pub = nh.advertise<sensor_msgs::PointCloud2>("intersected_points", 1);
00179 point_pub = nh.advertise<geometry_msgs::PointStamped>("intersected_point", 1);
00180
00181 ros::Subscriber cloud_sub = nh.subscribe<sensor_msgs::PointCloud2>("cloud", 1, cloudCallback);
00182 ros::Subscriber pose_sub = nh.subscribe<geometry_msgs::PoseStamped>("pose", 1, poseCallback);
00183
00184 ros::Rate rate(10);
00185 while(((g_cloud_queue.size() == 0) || (g_pose_queue.size() == 0)) && ros::ok()) {
00186 ros::spinOnce();
00187 rate.sleep();
00188 }
00189
00190 ros::Timer timer = nh.createTimer(ros::Duration(0.05), sendTransform, false);
00191
00192 while(ros::ok()) {
00193
00194 intersectPose(g_cloud_queue.front(), g_pose_queue.front());
00195 g_cloud_queue.pop();
00196 g_pose_queue.pop();
00197 ros::spinOnce();
00198 rate.sleep();
00199 }
00200
00201
00202
00203
00204
00205
00206
00207
00208 }