world_intersect.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2013, Oregon State University
00003  * All rights reserved.
00004  * 
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are met:
00007  *     * Redistributions of source code must retain the above copyright
00008  *       notice, this list of conditions and the following disclaimer.
00009  *     * Redistributions in binary form must reproduce the above copyright
00010  *       notice, this list of conditions and the following disclaimer in the
00011  *       documentation and/or other materials provided with the distribution.
00012  *     * Neither the name of the Oregon State University nor the
00013  *       names of its contributors may be used to endorse or promote products
00014  *       derived from this software without specific prior written permission.
00015  * 
00016  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00017  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00018  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00019  * DISCLAIMED. IN NO EVENT SHALL OREGON STATE UNIVERSITY BE LIABLE FOR ANY
00020  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00021  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00022  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00023  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00024  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00025  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00026  * 
00027  * Author Dan Lazewatsky/lazewatd@engr.orst.edu
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 // params
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 // void callback(const sensor_msgs::PointCloud2ConstPtr& cloud_msg, const geometry_msgs::PoseStampedConstPtr& pose) {
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);//(cloud_msg->header.stamp > pose->header.stamp) ? cloud_msg->header.stamp : pose->header.stamp;
00103         if(!((pose->pose.position.x == 0) && (pose->pose.position.y) == 0 && (pose->pose.position.z == 0))) {
00104                 //ROS_WARN("Expecting point to be the origin of its coordinate frame, but it isn't");
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                 // broadcaster->sendTransform(tf::StampedTransform(trans, stamp, pose->header.frame_id, vector_frame));
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     //cloud_pub = nh.advertise<PointCloud>("intersected_points", 1);
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                 //sensor_msgs::PointCloud2ConstPtr& c = g_cloud_queue.front();
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         // message_filters::Subscriber<sensor_msgs::PointCloud2>   cloud_sub(nh, "cloud", 1);
00202         // message_filters::Subscriber<geometry_msgs::PoseStamped>   pose_sub(nh, "pose", 1);
00203         // typedef message_filters::sync_policies::ApproximateTime<sensor_msgs::PointCloud2, geometry_msgs::PoseStamped> ApproximatePolicy;
00204         // message_filters::Synchronizer<ApproximatePolicy> sync(ApproximatePolicy(10), cloud_sub, pose_sub);
00205         // sync.registerCallback(boost::bind(&intersectPose, _1, _2));
00206                 
00207         //ros::spin();
00208 }


world_intersect
Author(s): Daniel Lazewatsky
autogenerated on Mon Oct 6 2014 10:19:35