50 static const std::string
LOGNAME =
"occupancy_map_monitor";
52 : OccupancyMapUpdater(
"PointCloudUpdater")
56 , max_range_(
std::numeric_limits<double>::infinity())
59 , point_cloud_subscriber_(nullptr)
60 , point_cloud_filter_(nullptr)
64 PointCloudOctomapUpdater::~PointCloudOctomapUpdater()
73 if (!params.
hasMember(
"point_cloud_topic"))
75 point_cloud_topic_ =
static_cast<const std::string&
>(params[
"point_cloud_topic"]);
77 readXmlParam(params,
"max_range", &max_range_);
78 readXmlParam(params,
"padding_offset", &padding_);
79 readXmlParam(params,
"padding_scale", &scale_);
80 readXmlParam(params,
"point_subsample", &point_subsample_);
82 readXmlParam(params,
"max_update_rate", &max_update_rate_);
84 filtered_cloud_topic_ =
static_cast<const std::string&
>(params[
"filtered_cloud_topic"]);
86 ns_ =
static_cast<const std::string&
>(params[
"ns"]);
97 bool PointCloudOctomapUpdater::initialize()
99 tf_buffer_ = std::make_shared<tf2_ros::Buffer>();
100 tf_listener_ = std::make_shared<tf2_ros::TransformListener>(*tf_buffer_, root_nh_);
101 shape_mask_ = std::make_unique<point_containment_filter::ShapeMask>();
102 shape_mask_->setTransformCallback(
103 [
this](
ShapeHandle shape, Eigen::Isometry3d& tf) {
return getShapeTransform(shape, tf); });
105 std::string prefix =
"";
108 if (!filtered_cloud_topic_.empty())
109 filtered_cloud_publisher_ =
110 private_nh_.advertise<sensor_msgs::PointCloud2>(prefix + filtered_cloud_topic_, 10,
false);
114 void PointCloudOctomapUpdater::start()
116 if (point_cloud_subscriber_)
120 if (tf_listener_ && tf_buffer_ && !monitor_->getMapFrame().empty())
123 monitor_->getMapFrame(), 5, root_nh_);
124 point_cloud_filter_->registerCallback(
125 [
this](
const sensor_msgs::PointCloud2::ConstPtr& cloud) { cloudMsgCallback(cloud); });
126 ROS_INFO_NAMED(
LOGNAME,
"Listening to '%s' using message filter with target frame '%s'", point_cloud_topic_.c_str(),
127 point_cloud_filter_->getTargetFramesString().c_str());
131 point_cloud_subscriber_->registerCallback(
132 [
this](
const sensor_msgs::PointCloud2::ConstPtr& cloud) { cloudMsgCallback(cloud); });
137 void PointCloudOctomapUpdater::stopHelper()
139 delete point_cloud_filter_;
140 delete point_cloud_subscriber_;
143 void PointCloudOctomapUpdater::stop()
146 point_cloud_filter_ =
nullptr;
147 point_cloud_subscriber_ =
nullptr;
154 h = shape_mask_->addShape(shape, scale_, padding_);
160 void PointCloudOctomapUpdater::forgetShape(
ShapeHandle handle)
163 shape_mask_->removeShape(handle);
166 bool PointCloudOctomapUpdater::getShapeTransform(
ShapeHandle h, Eigen::Isometry3d& transform)
const
168 ShapeTransformCache::const_iterator it = transform_cache_.find(h);
169 if (it != transform_cache_.end())
173 return it != transform_cache_.end();
176 void PointCloudOctomapUpdater::updateMask(
const sensor_msgs::PointCloud2& ,
177 const Eigen::Vector3d& , std::vector<int>& )
181 void PointCloudOctomapUpdater::cloudMsgCallback(
const sensor_msgs::PointCloud2::ConstPtr& cloud_msg)
186 if (max_update_rate_ > 0)
194 if (monitor_->getMapFrame().empty())
195 monitor_->setMapFrame(cloud_msg->header.frame_id);
199 if (monitor_->getMapFrame() == cloud_msg->header.frame_id)
200 map_h_sensor.setIdentity();
207 tf2::fromMsg(tf_buffer_->lookupTransform(monitor_->getMapFrame(), cloud_msg->header.frame_id,
208 cloud_msg->header.stamp),
222 const tf2::Vector3& sensor_origin_tf = map_h_sensor.getOrigin();
223 octomap::point3d sensor_origin(sensor_origin_tf.getX(), sensor_origin_tf.getY(), sensor_origin_tf.getZ());
224 Eigen::Vector3d sensor_origin_eigen(sensor_origin_tf.getX(), sensor_origin_tf.getY(), sensor_origin_tf.getZ());
226 if (!updateTransformCache(cloud_msg->header.frame_id, cloud_msg->header.stamp))
230 shape_mask_->maskContainment(*cloud_msg, sensor_origin_eigen, 0.0, max_range_, mask_);
231 updateMask(*cloud_msg, sensor_origin_eigen, mask_);
234 std::unique_ptr<sensor_msgs::PointCloud2> filtered_cloud;
239 std::unique_ptr<sensor_msgs::PointCloud2Iterator<float>> iter_filtered_x;
240 std::unique_ptr<sensor_msgs::PointCloud2Iterator<float>> iter_filtered_y;
241 std::unique_ptr<sensor_msgs::PointCloud2Iterator<float>> iter_filtered_z;
243 if (!filtered_cloud_topic_.empty())
245 filtered_cloud = std::make_unique<sensor_msgs::PointCloud2>();
246 filtered_cloud->header = cloud_msg->header;
248 pcd_modifier.setPointCloud2FieldsByString(1,
"xyz");
249 pcd_modifier.resize(cloud_msg->width * cloud_msg->height);
252 iter_filtered_x = std::make_unique<sensor_msgs::PointCloud2Iterator<float>>(*filtered_cloud,
"x");
253 iter_filtered_y = std::make_unique<sensor_msgs::PointCloud2Iterator<float>>(*filtered_cloud,
"y");
254 iter_filtered_z = std::make_unique<sensor_msgs::PointCloud2Iterator<float>>(*filtered_cloud,
"z");
256 size_t filtered_cloud_size = 0;
264 for (
unsigned int row = 0; row < cloud_msg->height; row += point_subsample_)
266 unsigned int row_c = row * cloud_msg->width;
271 for (
unsigned int col = 0; col < cloud_msg->width; col += point_subsample_, pt_iter += point_subsample_)
277 if (!std::isnan(pt_iter[0]) && !std::isnan(pt_iter[1]) && !std::isnan(pt_iter[2]))
284 tf2::Vector3 point_tf = map_h_sensor * tf2::Vector3(pt_iter[0], pt_iter[1], pt_iter[2]);
285 model_cells.insert(tree_->coordToKey(point_tf.getX(), point_tf.getY(), point_tf.getZ()));
289 tf2::Vector3 clipped_point_tf =
290 map_h_sensor * (tf2::Vector3(pt_iter[0], pt_iter[1], pt_iter[2]).normalize() * max_range_);
292 tree_->coordToKey(clipped_point_tf.getX(), clipped_point_tf.getY(), clipped_point_tf.getZ()));
296 tf2::Vector3 point_tf = map_h_sensor * tf2::Vector3(pt_iter[0], pt_iter[1], pt_iter[2]);
297 occupied_cells.insert(tree_->coordToKey(point_tf.getX(), point_tf.getY(), point_tf.getZ()));
301 **iter_filtered_x = pt_iter[0];
302 **iter_filtered_y = pt_iter[1];
303 **iter_filtered_z = pt_iter[2];
304 ++filtered_cloud_size;
316 if (tree_->computeRayKeys(sensor_origin, tree_->keyToCoord(occupied_cell), key_ray_))
317 free_cells.insert(key_ray_.begin(), key_ray_.end());
321 if (tree_->computeRayKeys(sensor_origin, tree_->keyToCoord(model_cell), key_ray_))
322 free_cells.insert(key_ray_.begin(), key_ray_.end());
326 if (tree_->computeRayKeys(sensor_origin, tree_->keyToCoord(clip_cell), key_ray_))
327 free_cells.insert(key_ray_.begin(), key_ray_.end());
339 occupied_cells.erase(model_cell);
343 free_cells.erase(occupied_cell);
351 tree_->updateNode(free_cell,
false);
355 tree_->updateNode(occupied_cell,
true);
358 const float lg = tree_->getClampingThresMinLog() - tree_->getClampingThresMaxLog();
360 tree_->updateNode(model_cell, lg);
366 tree_->unlockWrite();
368 tree_->triggerUpdateCallback();
373 pcd_modifier.resize(filtered_cloud_size);
374 filtered_cloud_publisher_.publish(*filtered_cloud);