nonpersistent_voxel_layer.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  *
3  * Software License Agreement (BSD License)
4  *
5  * Copyright (c) 2008, 2013, Willow Garage, Inc.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * * Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  * * Redistributions in binary form must reproduce the above
15  * copyright notice, this list of conditions and the following
16  * disclaimer in the documentation and/or other materials provided
17  * with the distribution.
18  * * Neither the name of Willow Garage, Inc. nor the names of its
19  * contributors may be used to endorse or promote products derived
20  * from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  * POSSIBILITY OF SUCH DAMAGE.
34  *
35  * Author: Eitan Marder-Eppstein
36  * David V. Lu!!
37  * Steve Macenski
38  *********************************************************************/
42 
43 #define VOXEL_BITS 16
45 
46 using costmap_2d::NO_INFORMATION;
47 using costmap_2d::LETHAL_OBSTACLE;
48 using costmap_2d::FREE_SPACE;
49 
51 using costmap_2d::Observation;
52 
53 namespace costmap_2d
54 {
55 
56 void NonPersistentVoxelLayer::onInitialize()
57 {
58  ObstacleLayer::onInitialize();
59  ros::NodeHandle private_nh("~/" + name_);
60 
61  private_nh.param("publish_voxel_map", publish_voxel_, false);
62  private_nh.param("footprint_clearing_enabled", footprint_clearing_enabled_, true);
63  if (publish_voxel_)
64  voxel_pub_ = private_nh.advertise < costmap_2d::VoxelGrid > ("voxel_grid", 1);
65 }
66 
67 void NonPersistentVoxelLayer::setupDynamicReconfigure(ros::NodeHandle& nh)
68 {
69  voxel_dsrv_ = new dynamic_reconfigure::Server<costmap_2d::NonPersistentVoxelPluginConfig>(nh);
70  dynamic_reconfigure::Server<costmap_2d::NonPersistentVoxelPluginConfig>::CallbackType cb = boost::bind(
71  &NonPersistentVoxelLayer::reconfigureCB, this, _1, _2);
72  voxel_dsrv_->setCallback(cb);
73 }
74 
75 NonPersistentVoxelLayer::~NonPersistentVoxelLayer()
76 {
77  if (voxel_dsrv_)
78  delete voxel_dsrv_;
79 }
80 
81 void NonPersistentVoxelLayer::reconfigureCB(costmap_2d::NonPersistentVoxelPluginConfig &config, uint32_t level)
82 {
83  enabled_ = config.enabled;
84  max_obstacle_height_ = config.max_obstacle_height;
85  size_z_ = config.z_voxels;
86  origin_z_ = config.origin_z;
87  z_resolution_ = config.z_resolution;
88  unknown_threshold_ = config.unknown_threshold + (VOXEL_BITS - size_z_);
89  mark_threshold_ = config.mark_threshold;
90  combination_method_ = config.combination_method;
91  matchSize();
92 }
93 
94 void NonPersistentVoxelLayer::updateFootprint(double robot_x, double robot_y, double robot_yaw, double* min_x, double* min_y,
95  double* max_x, double* max_y)
96 {
97  if (!footprint_clearing_enabled_)
98  return;
99  transformFootprint(robot_x, robot_y, robot_yaw, getFootprint(), transformed_footprint_);
100 
101  for (unsigned int i = 0; i < transformed_footprint_.size(); i++)
102  {
103  touch(transformed_footprint_[i].x, transformed_footprint_[i].y, min_x, min_y, max_x, max_y);
104  }
105 
106  setConvexPolygonCost(transformed_footprint_, costmap_2d::FREE_SPACE);
107 }
108 
109 
110 void NonPersistentVoxelLayer::matchSize()
111 {
112  ObstacleLayer::matchSize();
113  voxel_grid_.resize(size_x_, size_y_, size_z_);
114  ROS_ASSERT(voxel_grid_.sizeX() == size_x_ && voxel_grid_.sizeY() == size_y_);
115 }
116 
117 void NonPersistentVoxelLayer::reset()
118 {
119  deactivate();
120  resetMaps();
121  voxel_grid_.reset();
122  activate();
123 }
124 
125 void NonPersistentVoxelLayer::resetMaps()
126 {
127  Costmap2D::resetMaps();
128  voxel_grid_.reset();
129 }
130 
131 void NonPersistentVoxelLayer::updateBounds(double robot_x, double robot_y, double robot_yaw, double* min_x,
132  double* min_y, double* max_x, double* max_y)
133 {
134  // update origin information for rolling costmap publication
135  if (rolling_window_)
136  {
137  updateOrigin(robot_x - getSizeInMetersX() / 2, robot_y - getSizeInMetersY() / 2);
138  }
139 
140  // reset maps each iteration
141  resetMaps();
142 
143  // if not enabled, stop here
144  if (!enabled_)
145  return;
146 
147  // get the maximum sized window required to operate
148  useExtraBounds(min_x, min_y, max_x, max_y);
149 
150  // get the marking observations
151  bool current = true;
152  std::vector<Observation> observations;
153  current = getMarkingObservations(observations) && current;
154 
155  // update the global current status
156  current_ = current;
157 
158  // place the new obstacles into a priority queue... each with a priority of zero to begin with
159  for (std::vector<Observation>::const_iterator it = observations.begin(); it != observations.end(); ++it)
160  {
161  const Observation& obs = *it;
162 
163  #if ROS_VERSION_MINIMUM(1,14,0)
164  // >= Melodic
165  pcl::PointCloud<pcl::PointXYZ> cloud;
166  pcl::fromROSMsg(*obs.cloud_, cloud);
167  #else
168  // < Melodic
169  const pcl::PointCloud<pcl::PointXYZ>& cloud = *(obs.cloud_);
170  #endif
171 
172  double sq_obstacle_range = obs.obstacle_range_ * obs.obstacle_range_;
173 
174  for (unsigned int i = 0; i < cloud.points.size(); ++i)
175  {
176  // if the obstacle is too high or too far away from the robot we won't add it
177  if (cloud.points[i].z > max_obstacle_height_)
178  continue;
179 
180  // compute the squared distance from the hitpoint to the pointcloud's origin
181  double sq_dist = (cloud.points[i].x - obs.origin_.x) * (cloud.points[i].x - obs.origin_.x)
182  + (cloud.points[i].y - obs.origin_.y) * (cloud.points[i].y - obs.origin_.y)
183  + (cloud.points[i].z - obs.origin_.z) * (cloud.points[i].z - obs.origin_.z);
184 
185  // if the point is far enough away... we won't consider it
186  if (sq_dist >= sq_obstacle_range)
187  continue;
188 
189  // now we need to compute the map coordinates for the observation
190  unsigned int mx, my, mz;
191  if (cloud.points[i].z < origin_z_)
192  {
193  if (!worldToMap3D(cloud.points[i].x, cloud.points[i].y, origin_z_, mx, my, mz))
194  continue;
195  }
196  else if (!worldToMap3D(cloud.points[i].x, cloud.points[i].y, cloud.points[i].z, mx, my, mz))
197  {
198  continue;
199  }
200 
201  // mark the cell in the voxel grid and check if we should also mark it in the costmap
202  if (voxel_grid_.markVoxelInMap(mx, my, mz, mark_threshold_))
203  {
204  unsigned int index = getIndex(mx, my);
205 
206  costmap_[index] = LETHAL_OBSTACLE;
207  touch((double)cloud.points[i].x, (double)cloud.points[i].y, min_x, min_y, max_x, max_y);
208  }
209  }
210  }
211 
212  if (publish_voxel_)
213  {
214  costmap_2d::VoxelGrid grid_msg;
215  unsigned int size = voxel_grid_.sizeX() * voxel_grid_.sizeY();
216  grid_msg.size_x = voxel_grid_.sizeX();
217  grid_msg.size_y = voxel_grid_.sizeY();
218  grid_msg.size_z = voxel_grid_.sizeZ();
219  grid_msg.data.resize(size);
220  memcpy(&grid_msg.data[0], voxel_grid_.getData(), size * sizeof(unsigned int));
221 
222  grid_msg.origin.x = origin_x_;
223  grid_msg.origin.y = origin_y_;
224  grid_msg.origin.z = origin_z_;
225 
226  grid_msg.resolutions.x = resolution_;
227  grid_msg.resolutions.y = resolution_;
228  grid_msg.resolutions.z = z_resolution_;
229  grid_msg.header.frame_id = global_frame_;
230  grid_msg.header.stamp = ros::Time::now();
231  voxel_pub_.publish(grid_msg);
232  }
233 
234  updateFootprint(robot_x, robot_y, robot_yaw, min_x, min_y, max_x, max_y);
235 }
236 
237 void NonPersistentVoxelLayer::updateOrigin(double new_origin_x, double new_origin_y)
238 {
239  // project the new origin into the grid
240  int cell_ox, cell_oy;
241  cell_ox = int((new_origin_x - origin_x_) / resolution_);
242  cell_oy = int((new_origin_y - origin_y_) / resolution_);
243 
244  // update the origin with the appropriate world coordinates
245  origin_x_ = origin_x_ + cell_ox * resolution_;
246  origin_y_ = origin_y_ + cell_oy * resolution_;
247 }
248 
249 } // namespace costmap_2d
geometry_msgs::Point origin_
pcl::PointCloud< pcl::PointXYZ > * cloud_
PLUGINLIB_EXPORT_CLASS(BAGReader, nodelet::Nodelet)
void fromROSMsg(const sensor_msgs::PointCloud2 &cloud, pcl::PointCloud< T > &pcl_cloud)
TFSIMD_FORCE_INLINE const tfScalar & y() const
static const unsigned char FREE_SPACE
#define VOXEL_BITS
bool param(const std::string &param_name, T &param_val, const T &default_val) const
TFSIMD_FORCE_INLINE const tfScalar & x() const
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
static Time now()
#define ROS_ASSERT(cond)
void transformFootprint(double x, double y, double theta, const std::vector< geometry_msgs::Point > &footprint_spec, std::vector< geometry_msgs::Point > &oriented_footprint)


nonpersistent_voxel_layer
Author(s): Steven Macenski, stevenmacenski@gmail.com
autogenerated on Wed Jun 12 2019 19:47:02