PointCloudFilter.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Copyright (c) 2014-2017, Dataspeed Inc.
00005  *  All rights reserved.
00006  *
00007  *  Redistribution and use in source and binary forms, with or without
00008  *  modification, are permitted provided that the following conditions
00009  *  are met:
00010  *
00011  *   * Redistributions of source code must retain the above copyright
00012  *     notice, this list of conditions and the following disclaimer.
00013  *   * Redistributions in binary form must reproduce the above
00014  *     copyright notice, this list of conditions and the following
00015  *     disclaimer in the documentation and/or other materials provided
00016  *     with the distribution.
00017  *   * Neither the name of Dataspeed Inc. nor the names of its
00018  *     contributors may be used to endorse or promote products derived
00019  *     from this software without specific prior written permission.
00020  *
00021  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00027  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00029  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00031  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032  *  POSSIBILITY OF SUCH DAMAGE.
00033  *********************************************************************/
00034 
00035 #include "PointCloudFilter.h"
00036 #include <sensor_msgs/point_cloud2_iterator.h>
00037 
00038 namespace mobility_base_pointcloud_filter
00039 {
00040 
00041 PointCloudFilter::PointCloudFilter(ros::NodeHandle nh, ros::NodeHandle priv_nh) : nh_(nh)
00042 {
00043   if (!nh.getParam("width", width_)) {
00044     width_ = 0.14 * M_PI;
00045   }
00046   ros::SubscriberStatusCallback connect_cb = boost::bind(&PointCloudFilter::connectCb, this);
00047   pub_ = nh.advertise<sensor_msgs::PointCloud2>("points_filtered", 10, connect_cb, connect_cb);
00048 }
00049 
00050 PointCloudFilter::~PointCloudFilter()
00051 {
00052 }
00053 
00054 void PointCloudFilter::connectCb()
00055 {
00056   boost::lock_guard<boost::mutex> lock(connect_mutex_);
00057   if (!pub_.getNumSubscribers()) {
00058     sub_.shutdown();
00059   } else if (!sub_) {
00060     sub_ = nh_.subscribe("points", 10, &PointCloudFilter::recvCallback, this);
00061   }
00062 }
00063 
00064 static inline float normalizeAnglePositive(float angle)
00065 {
00066   return fmodf(fmodf(angle, 2.0*M_PI) + 2.0*M_PI, 2.0*M_PI);
00067 }
00068 
00069 void PointCloudFilter::recvCallback(const sensor_msgs::PointCloud2Ptr& msg)
00070 {
00071 #if 0
00072   ros::WallTime tic = ros::WallTime::now();
00073 #endif
00074 
00075   if (width_ == 0.0) {
00076     pub_.publish(msg);
00077     return;
00078   }
00079 
00080   const float ANGLE_WIDTH = std::min(fabs(width_), M_PI_4);
00081   const float ANGLE_START = M_PI_4;
00082   const float ANGLE_INC = M_PI_2;
00083 
00084   // Remove points in the four blind spots. Assumes x, y, and z are consecutive
00085 #if 0 // atan2() is slow
00086   for (sensor_msgs::PointCloud2Iterator<float> it(*msg, "x"); it != it.end(); it.operator ++()) {
00087     const float angle = normalizeAnglePositive(atan2f(it[1], it[0]));
00088     for (unsigned int j = 0; j < 4; j++) {
00089       const float a1 = ANGLE_START + (j * ANGLE_INC) - (ANGLE_WIDTH / 2);
00090       const float a2 = ANGLE_START + (j * ANGLE_INC) + (ANGLE_WIDTH / 2);
00091       if ((a2 > angle) && (angle > a1)) {
00092         it[2] = NAN; // z
00093         break;
00094       }
00095     }
00096   }
00097 #elif 1 // unit vector is ~3x faster
00098   const float UNIT_X_LOW = cosf(ANGLE_START + (ANGLE_WIDTH / 2));
00099   const float UNIT_X_HI  = cosf(ANGLE_START - (ANGLE_WIDTH / 2));
00100   for (sensor_msgs::PointCloud2Iterator<float> it(*msg, "x"); it != it.end(); it.operator ++()) {
00101     const float x = it[0];
00102     const float y = it[1];
00103     const float unit_x = fabsf(x / sqrtf(x * x + y * y));
00104     if ((UNIT_X_HI > unit_x) && (unit_x > UNIT_X_LOW)) {
00105       it[2] = NAN; // z
00106     }
00107   }
00108 #endif
00109 
00110   pub_.publish(msg);
00111 
00112 #if 0
00113   ros::WallTime toc = ros::WallTime::now();
00114   ROS_INFO("PointCloudFilter completed in %04uus", (unsigned int)((toc - tic).toNSec() / 1000));
00115 #endif
00116 }
00117 
00118 } // namespace mobility_base_pointcloud_filter


mobility_base_pointcloud_filter
Author(s): Dataspeed Inc.
autogenerated on Thu Jun 6 2019 21:45:34