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
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047 #include "pcdfilter_pa/pcdfilter_pa_ros.h"
00048
00049
00050 #include <sensor_msgs/point_cloud_conversion.h>
00051 #include <laser_geometry/laser_geometry.h>
00052
00053
00054 cPcdFilterPaRos::cPcdFilterPaRos() {
00055 }
00056
00057
00058 cPcdFilterPaRos::~cPcdFilterPaRos() {
00059 }
00060
00061
00062 sensor_msgs::PointCloud2Ptr cPcdFilterPaRos::convertCloud (
00063 const sensor_msgs::PointCloudConstPtr &msg) const {
00064
00065 sensor_msgs::PointCloud2Ptr result(new sensor_msgs::PointCloud2);
00066 sensor_msgs::convertPointCloudToPointCloud2(*msg, *result);
00067
00068 return result;
00069 }
00070
00071
00072 sensor_msgs::PointCloud2Ptr cPcdFilterPaRos::convertCloud(
00073 const sensor_msgs::LaserScanConstPtr &msg) const {
00074
00075 laser_geometry::LaserProjection projector;
00076
00077 sensor_msgs::PointCloud2Ptr result (new sensor_msgs::PointCloud2);
00078
00079 if (rosparams_.laser_nan_replacement_value_ < 0) {
00080 projector.projectLaser(*msg, *result, -1,
00081 laser_geometry::channel_option::Default);
00082 } else {
00083 sensor_msgs::LaserScan msg_changed(*msg);
00084
00085 for (int i = 0; i < msg_changed.ranges.size(); i++) {
00086 if (std::isnan(msg_changed.ranges[i])) {
00087 msg_changed.ranges[i] =
00088 rosparams_.laser_nan_replacement_value_;
00089 }
00090 }
00091
00092 projector.projectLaser(msg_changed, *result, -1,
00093 laser_geometry::channel_option::Default);
00094 }
00095
00096 return result;
00097 }
00098
00099
00100 bool cPcdFilterPaRos::updateTf( const tf::TransformListener &tf_listener,
00101 const std::string base_frame, const ros::Time time) {
00102
00103 bool result = filters_.update(tf_listener, base_frame, time,
00104 params_.filters_);
00105
00106 if (rosparams_.debugging_) {
00107 for (int i = 0; i < params_.filters_.size(); i++) {
00108 ROS_INFO("%s: updated filter[%d] (%s)",
00109 ros::this_node::getName().data(), i,
00110 params_.filters_[i].toString().data());
00111 }
00112 }
00113
00114 return result;
00115 }
00116
00117
00118 bool cPcdFilterPaRos::updateTf(
00119 const tf::TransformListener &tf_listener) {
00120
00121 if (pcd_buffered_msg_.use_count() < 1) {
00122 params_.filters_.clear();
00123 return false;
00124 }
00125 return updateTf(tf_listener, pcd_buffered_msg_->header.frame_id,
00126 pcd_buffered_msg_->header.stamp);
00127 }
00128
00129
00130 bool cPcdFilterPaRos::filterCloud(const sensor_msgs::PointCloud2ConstPtr &msg,
00131 sensor_msgs::PointCloud2Ptr &result) {
00132
00133 pcd_buffered_msg_ = msg;
00134
00135
00136 pcd_buffered_points_= convertCloudToOpencv(msg);
00137
00138 if (pcd_buffered_points_.rows == 0) {
00139 ROS_WARN("%s: size of pointcloud after conversion to opencv is 0",
00140 ros::this_node::getName().data());
00141
00142 pcd_buffered_points_.release();
00143 pcd_buffered_msg_.reset();
00144 return false;
00145 }
00146
00147
00148 bool result_bool = filterCloud(result);
00149
00150 if (!rosparams_.buffer_pointcloud_) {
00151 pcd_buffered_points_.release();
00152 pcd_buffered_msg_.reset();
00153 }
00154 return result_bool;
00155 }
00156
00157
00158 bool cPcdFilterPaRos::filterCloud(sensor_msgs::PointCloud2Ptr &result) {
00159
00160 if ((pcd_buffered_msg_.use_count() < 1) ||
00161 (pcd_buffered_points_.empty())) {
00162 return false;
00163 }
00164
00165 std::vector<bool> mask;
00166 std::vector<int> count;
00167
00168
00169
00170 count = pointcloudFilter(pcd_buffered_points_, mask);
00171
00172
00173 result = applyMasktoCloud(pcd_buffered_msg_, mask);
00174
00175 if (rosparams_.debugging_) {
00176 std::stringstream ss;
00177 ss << "remaining points " << result->height << " (" <<
00178 pcd_buffered_points_.rows;
00179 for (int i = 0; i < count.size(); i++) {
00180 ss << " - " << count[i];
00181 }
00182 ss << ")";
00183 ROS_INFO("%s: %s", ros::this_node::getName().data(), ss.str().data());
00184 }
00185
00186 return true;
00187 }
00188
00189
00190 const cv::Mat cPcdFilterPaRos::convertCloudToOpencv(
00191 const sensor_msgs::PointCloud2ConstPtr &msg,
00192 const bool force_copy) const {
00193
00194
00195 int count = msg->height * msg->width;
00196 int point_step = msg->point_step;
00197
00198
00199 int types[4] = {-1, -1, -1, -1};
00200 int offsets[4] = {0, 0, 0, 0};
00201 for (int i = 0; i < msg->fields.size(); i++) {
00202 int position = 3;
00203 if ((msg->fields[i].name == "x") || (msg->fields[i].name == "X")) {
00204 position = 0;
00205 }
00206 if ((msg->fields[i].name == "y") || (msg->fields[i].name == "Y")) {
00207 position = 1;
00208 }
00209 if ((msg->fields[i].name == "z") || (msg->fields[i].name == "Z")) {
00210 position = 2;
00211 }
00212
00213 types[position] = msg->fields[i].datatype;
00214 offsets[position] = msg->fields[i].offset ;
00215 }
00216
00217 for (int i = 0; i < 3; i++) {
00218 if (types[i] < 0) {
00219 return cv::Mat();
00220 }
00221 }
00222
00223
00224 bool simple_assign = true;
00225 for (int i = 0; i < 3; i++) {
00226 if ((types[0] != types[i]) || (offsets[i] != i * offsets[1])) {
00227 simple_assign = false;
00228 break;
00229 }
00230 }
00231 if (simple_assign) {
00232 if ((types[0] == sensor_msgs::PointField::FLOAT32) &&
00233 (offsets[1] == 4)) {
00234 cv::Mat result(count, 3, CV_32FC1,
00235 const_cast<uint8_t*> (&(msg->data.front())), point_step);
00236 if (force_copy) {
00237 if (rosparams_.debugging_) {
00238 ROS_INFO("%s: opencv - simple copy of pointcloud)",
00239 ros::this_node::getName().data());
00240 }
00241 cv::Mat result_copy;
00242 result.copyTo(result_copy);
00243 return result_copy;
00244 } else {
00245 if (rosparams_.debugging_) {
00246 ROS_INFO("%s: opencv - reassignment of pointcloud)",
00247 ros::this_node::getName().data());
00248 }
00249 return result;
00250 }
00251 }
00252 if ((types[0] == sensor_msgs::PointField::FLOAT64) &&
00253 (offsets[1] == 8)) {
00254 if (rosparams_.debugging_) {
00255 ROS_INFO("%s: opencv - reassignment of pointcloud"
00256 " + conversion", ros::this_node::getName().data());
00257 }
00258 cv::Mat result;
00259 cv::Mat (count, 3, CV_64FC1,
00260 const_cast<uint8_t*> (&(msg->data.front())),
00261 point_step).convertTo(result, CV_32FC1);
00262 return result;
00263 }
00264 }
00265
00266
00267 if (rosparams_.debugging_) {
00268 ROS_INFO("%s: opencv - complex copy of pointcloud",
00269 ros::this_node::getName().data());
00270 }
00271 cv::Mat result(count, 3, CV_32FC1);
00272 int current_pos = 0;
00273 for (int i = 0; i < count; i++) {
00274
00275 for (int j = 0; j < 3; j++) {
00276 const void *ptr = &(msg->data[current_pos + offsets[j]]);
00277 double value = -1;
00278 switch (types[j]) {
00279 case sensor_msgs::PointField::FLOAT64:
00280 value = float(*((const double* ) ptr));
00281 break;
00282 case sensor_msgs::PointField::FLOAT32:
00283 value = *((const float* ) ptr) ;
00284 break;
00285 case sensor_msgs::PointField::INT32:
00286 value = float(*((const int32_t* ) ptr));
00287 break;
00288 case sensor_msgs::PointField::UINT32:
00289 value = float(*((const uint32_t*) ptr));
00290 break;
00291 case sensor_msgs::PointField::INT16:
00292 value = float(*((const int16_t* ) ptr));
00293 break;
00294 case sensor_msgs::PointField::UINT16:
00295 value = float(*((const uint16_t*) ptr));
00296 break;
00297 case sensor_msgs::PointField::INT8:
00298 value = float(*((const int8_t* ) ptr));
00299 break;
00300 case sensor_msgs::PointField::UINT8:
00301 value = float(*((const uint8_t* ) ptr));
00302 break;
00303 }
00304 result.at<double>(i,j) = value;
00305 }
00306 current_pos+= point_step;
00307 }
00308
00309 return result;
00310 }
00311
00312
00313 sensor_msgs::PointCloud2Ptr cPcdFilterPaRos::applyMasktoCloud(
00314 const sensor_msgs::PointCloud2ConstPtr cloud,
00315 const std::vector<bool> mask) const {
00316
00317 int point_step = cloud->point_step;
00318
00319 int size_old = cloud->height * cloud->width;
00320 if ((size_old == 0) && (point_step > 0)) {
00321 size_old = cloud->data.size() / point_step;
00322 }
00323
00324 int size_new = mask.size() <= size_old ? mask.size() : size_old;
00325 int count = 0;
00326 for (int i = 0; i < size_new; i++) {
00327 if (mask[i]) {count++;}
00328 }
00329 size_new = count;
00330
00331
00332 sensor_msgs::PointCloud2Ptr result (new sensor_msgs::PointCloud2);
00333 result->header.frame_id = cloud->header.frame_id;
00334 result->header.stamp = cloud->header.stamp;
00335 result->is_bigendian = cloud->is_bigendian;
00336 result->is_dense = cloud->is_dense;
00337 result->height = size_new;
00338 result->width = 1;
00339 result->point_step = cloud->point_step;
00340 result->row_step = cloud->point_step;
00341
00342 result->fields = cloud->fields;
00343 result->data.resize(size_new * point_step);
00344
00345 uint8_t *pos_new = &result->data[0];
00346 const uint8_t *pos_old_base = &cloud->data[0];
00347 for (int i = 0; i < size_old; i++) {
00348 if (mask[i]) {
00349 memcpy(pos_new, pos_old_base + i*point_step, point_step);
00350 pos_new+= point_step;
00351 }
00352 }
00353
00354 return result;
00355 }