Nav2 Navigation Stack - lyrical  lyrical
ROS 2 Navigation Stack
voxel_layer.cpp
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  *********************************************************************/
38 
39 #include "nav2_costmap_2d/voxel_layer.hpp"
40 
41 #include <algorithm>
42 #include <cassert>
43 #include <vector>
44 #include <memory>
45 #include <utility>
46 
47 #include "pluginlib/class_list_macros.hpp"
48 #include "sensor_msgs/point_cloud2_iterator.hpp"
49 
50 #define VOXEL_BITS 16
52 
53 using nav2_costmap_2d::NO_INFORMATION;
54 using nav2_costmap_2d::LETHAL_OBSTACLE;
55 using nav2_costmap_2d::FREE_SPACE;
56 using rcl_interfaces::msg::ParameterType;
57 
58 namespace nav2_costmap_2d
59 {
60 
62 {
64 
65  auto node = node_.lock();
66  if (!node) {
67  throw std::runtime_error{"Failed to lock node"};
68  }
69 
70  enabled_ = node->declare_or_get_parameter(name_ + "." + "enabled", true);
71  footprint_clearing_enabled_ = node->declare_or_get_parameter(
72  name_ + "." + "footprint_clearing_enabled", true);
73  min_obstacle_height_ = node->declare_or_get_parameter(
74  name_ + "." + "min_obstacle_height", 0.0);
75  max_obstacle_height_ = node->declare_or_get_parameter(
76  name_ + "." + "max_obstacle_height", 2.0);
77  size_z_ = node->declare_or_get_parameter(name_ + "." + "z_voxels", 10);
78  origin_z_ = node->declare_or_get_parameter(name_ + "." + "origin_z", 0.0);
79  z_resolution_ = node->declare_or_get_parameter(name_ + "." + "z_resolution", 0.2);
80  unknown_threshold_ = node->declare_or_get_parameter(
81  name_ + "." + "unknown_threshold", 15);
82  mark_threshold_ = node->declare_or_get_parameter(name_ + "." + "mark_threshold", 0);
83  int combination_method_param = node->declare_or_get_parameter(
84  name_ + "." + "combination_method", 1);
85  publish_voxel_ = node->declare_or_get_parameter(
86  name_ + "." + "publish_voxel_map", false);
87  combination_method_ = combination_method_from_int(combination_method_param);
88 
89  if (publish_voxel_) {
90  voxel_pub_ = node->create_publisher<nav2_msgs::msg::VoxelGrid>(
91  "voxel_grid", nav2::qos::LatchedPublisherQoS(1));
92  voxel_pub_->on_activate();
93  }
94 
95  clearing_endpoints_pub_ = node->create_publisher<sensor_msgs::msg::PointCloud2>(
96  "clearing_endpoints", nav2::qos::LatchedPublisherQoS());
97  clearing_endpoints_pub_->on_activate();
98 
99  unknown_threshold_ += (VOXEL_BITS - size_z_);
100  matchSize();
101 }
102 
104 {
106  auto node = node_.lock();
107  // Add callback for dynamic parameters
108  post_set_params_handler_ = node->add_post_set_parameters_callback(
109  std::bind(
111  this, std::placeholders::_1));
112  on_set_params_handler_ = node->add_on_set_parameters_callback(
113  std::bind(
115  this, std::placeholders::_1));
116 }
117 
119 {
121  auto node = node_.lock();
122  if (post_set_params_handler_ && node) {
123  node->remove_post_set_parameters_callback(post_set_params_handler_.get());
124  }
125  post_set_params_handler_.reset();
126  if (on_set_params_handler_ && node) {
127  node->remove_on_set_parameters_callback(on_set_params_handler_.get());
128  }
129  on_set_params_handler_.reset();
130 }
131 
133 {
134 }
135 
137 {
138  std::lock_guard<Costmap2D::mutex_t> guard(*getMutex());
140  voxel_grid_.resize(size_x_, size_y_, size_z_);
141  assert(voxel_grid_.sizeX() == size_x_ && voxel_grid_.sizeY() == size_y_);
142 }
143 
145 {
146  // Call the base class method before adding our own functionality
148  resetMaps();
149 }
150 
152 {
153  // Call the base class method before adding our own functionality
154  // Note: at the time this was written, ObstacleLayer doesn't implement
155  // resetMaps so this goes to the next layer down Costmap2DLayer which also
156  // doesn't implement this, so it actually goes all the way to Costmap2D
158  voxel_grid_.reset();
159 }
160 
162  double robot_x, double robot_y, double robot_yaw, double * min_x,
163  double * min_y, double * max_x, double * max_y)
164 {
165  std::lock_guard<Costmap2D::mutex_t> guard(*getMutex());
166 
167  if (rolling_window_) {
168  updateOrigin(robot_x - getSizeInMetersX() / 2, robot_y - getSizeInMetersY() / 2);
169  }
170  if (!enabled_) {
171  return;
172  }
173  useExtraBounds(min_x, min_y, max_x, max_y);
174 
175  bool current = true;
176  std::vector<Observation::ConstSharedPtr> observations, clearing_observations;
177 
178  // get the marking observations
179  current = getMarkingObservations(observations) && current;
180 
181  // get the clearing observations
182  current = getClearingObservations(clearing_observations) && current;
183 
184  // update the global current status
185  setCurrent(current);
186 
187  // raytrace freespace
188  for (const auto & clearing_observation : clearing_observations) {
189  raytraceFreespace(*clearing_observation, min_x, min_y, max_x, max_y);
190  }
191 
192  // place the new obstacles into a priority queue... each with a priority of zero to begin with
193  for (const auto & observation : observations) {
194  const Observation & obs = *observation;
195 
196  const sensor_msgs::msg::PointCloud2 & cloud = obs.cloud_;
197 
198  // the height filter of the observation buffer can leave a cloud without points
199  if (cloud.height == 0 || cloud.width == 0) {
200  continue;
201  }
202 
203  double sq_obstacle_max_range = obs.obstacle_max_range_ * obs.obstacle_max_range_;
204  double sq_obstacle_min_range = obs.obstacle_min_range_ * obs.obstacle_min_range_;
205 
206  sensor_msgs::PointCloud2ConstIterator<float> iter_x(cloud, "x");
207  sensor_msgs::PointCloud2ConstIterator<float> iter_y(cloud, "y");
208  sensor_msgs::PointCloud2ConstIterator<float> iter_z(cloud, "z");
209 
210  for (; iter_x != iter_x.end(); ++iter_x, ++iter_y, ++iter_z) {
211  // if the obstacle is too low, we won't add it
212  if (*iter_z < min_obstacle_height_) {
213  continue;
214  }
215 
216  // if the obstacle is too high or too far away from the robot we won't add it
217  if (*iter_z > max_obstacle_height_) {
218  continue;
219  }
220 
221  // compute the squared distance from the hitpoint to the pointcloud's origin
222  double sq_dist = (*iter_x - obs.origin_.x) * (*iter_x - obs.origin_.x) +
223  (*iter_y - obs.origin_.y) * (*iter_y - obs.origin_.y) +
224  (*iter_z - obs.origin_.z) * (*iter_z - obs.origin_.z);
225 
226  // if the point is far enough away... we won't consider it
227  if (sq_dist >= sq_obstacle_max_range) {
228  continue;
229  }
230 
231  // If the point is too close, do not consider it
232  if (sq_dist < sq_obstacle_min_range) {
233  continue;
234  }
235 
236  // now we need to compute the map coordinates for the observation
237  unsigned int mx, my, mz;
238  if (*iter_z < origin_z_) {
239  if (!worldToMap3D(*iter_x, *iter_y, origin_z_, mx, my, mz)) {
240  continue;
241  }
242  } else if (!worldToMap3D(*iter_x, *iter_y, *iter_z, mx, my, mz)) {
243  continue;
244  }
245 
246  // mark the cell in the voxel grid and check if we should also mark it in the costmap
247  if (voxel_grid_.markVoxelInMap(mx, my, mz, mark_threshold_)) {
248  unsigned int index = getIndex(mx, my);
249 
250  costmap_[index] = LETHAL_OBSTACLE;
251  touch(
252  static_cast<double>(*iter_x), static_cast<double>(*iter_y),
253  min_x, min_y, max_x, max_y);
254  }
255  }
256  }
257 
258  if (publish_voxel_) {
259  auto grid_msg = std::make_unique<nav2_msgs::msg::VoxelGrid>();
260  unsigned int size = voxel_grid_.sizeX() * voxel_grid_.sizeY();
261  grid_msg->size_x = voxel_grid_.sizeX();
262  grid_msg->size_y = voxel_grid_.sizeY();
263  grid_msg->size_z = voxel_grid_.sizeZ();
264  grid_msg->data.resize(size);
265  memcpy(&grid_msg->data[0], voxel_grid_.getData(), size * sizeof(unsigned int));
266 
267  grid_msg->origin.x = origin_x_;
268  grid_msg->origin.y = origin_y_;
269  grid_msg->origin.z = origin_z_;
270 
271  grid_msg->resolutions.x = resolution_;
272  grid_msg->resolutions.y = resolution_;
273  grid_msg->resolutions.z = z_resolution_;
274  grid_msg->header.frame_id = global_frame_;
275  grid_msg->header.stamp = clock_->now();
276 
277  voxel_pub_->publish(std::move(grid_msg));
278  }
279 
280  updateFootprint(robot_x, robot_y, robot_yaw, min_x, min_y, max_x, max_y);
281 }
282 
284  const Observation & clearing_observation, double * min_x,
285  double * min_y,
286  double * max_x,
287  double * max_y)
288 {
289  auto clearing_endpoints_ = std::make_unique<sensor_msgs::msg::PointCloud2>();
290 
291  if (clearing_observation.cloud_.height == 0 || clearing_observation.cloud_.width == 0) {
292  return;
293  }
294 
295  double sensor_x, sensor_y, sensor_z;
296  double ox = clearing_observation.origin_.x;
297  double oy = clearing_observation.origin_.y;
298  double oz = clearing_observation.origin_.z;
299 
300  if (!worldToMap3DFloat(ox, oy, oz, sensor_x, sensor_y, sensor_z)) {
301  RCLCPP_WARN(
302  logger_,
303  "Sensor origin at (%.2f, %.2f %.2f) is out of map bounds "
304  "(%.2f, %.2f, %.2f) to (%.2f, %.2f, %.2f). "
305  "The costmap cannot raytrace for it.",
306  ox, oy, oz,
307  origin_x_, origin_y_, origin_z_,
308  origin_x_ + getSizeInMetersX(), origin_y_ + getSizeInMetersY(),
309  origin_z_ + getSizeInMetersZ());
310 
311  return;
312  }
313 
314  bool publish_clearing_points;
315 
316  {
317  auto node = node_.lock();
318  if (!node) {
319  throw std::runtime_error{"Failed to lock node"};
320  }
321  publish_clearing_points = (node->count_subscribers("clearing_endpoints") > 0);
322  }
323 
324  clearing_endpoints_->data.clear();
325  clearing_endpoints_->width = clearing_observation.cloud_.width;
326  clearing_endpoints_->height = clearing_observation.cloud_.height;
327  clearing_endpoints_->is_dense = true;
328  clearing_endpoints_->is_bigendian = false;
329 
330  sensor_msgs::PointCloud2Modifier modifier(*clearing_endpoints_);
331  modifier.setPointCloud2Fields(
332  3, "x", 1, sensor_msgs::msg::PointField::FLOAT32,
333  "y", 1, sensor_msgs::msg::PointField::FLOAT32,
334  "z", 1, sensor_msgs::msg::PointField::FLOAT32);
335 
336  sensor_msgs::PointCloud2Iterator<float> clearing_endpoints_iter_x(*clearing_endpoints_, "x");
337  sensor_msgs::PointCloud2Iterator<float> clearing_endpoints_iter_y(*clearing_endpoints_, "y");
338  sensor_msgs::PointCloud2Iterator<float> clearing_endpoints_iter_z(*clearing_endpoints_, "z");
339 
340  // we can pre-compute the endpoints of the map outside of the inner loop... we'll need these later
341  double map_end_x = origin_x_ + getSizeInMetersX();
342  double map_end_y = origin_y_ + getSizeInMetersY();
343  double map_end_z = origin_z_ + getSizeInMetersZ();
344 
345  sensor_msgs::PointCloud2ConstIterator<float> iter_x(clearing_observation.cloud_, "x");
346  sensor_msgs::PointCloud2ConstIterator<float> iter_y(clearing_observation.cloud_, "y");
347  sensor_msgs::PointCloud2ConstIterator<float> iter_z(clearing_observation.cloud_, "z");
348 
349  for (; iter_x != iter_x.end(); ++iter_x, ++iter_y, ++iter_z) {
350  double wpx = *iter_x;
351  double wpy = *iter_y;
352  double wpz = *iter_z;
353 
354  double distance = dist(ox, oy, oz, wpx, wpy, wpz);
355  double scaling_fact = 1.0;
356  scaling_fact = std::max(std::min(scaling_fact, (distance - 2 * resolution_) / distance), 0.0);
357  wpx = scaling_fact * (wpx - ox) + ox;
358  wpy = scaling_fact * (wpy - oy) + oy;
359  wpz = scaling_fact * (wpz - oz) + oz;
360 
361  double a = wpx - ox;
362  double b = wpy - oy;
363  double c = wpz - oz;
364  double t = 1.0;
365  bool wp_outside = false;
366 
367  // we can only raytrace to a maximum z height
368  if (wpz > map_end_z) {
369  // we know we want the vector's z value to be max_z
370  t = std::max(0.0, std::min(t, (map_end_z - 0.01 - oz) / c));
371  wp_outside = true;
372  } else if (wpz < origin_z_) {
373  // and we can only raytrace down to the floor
374  // we know we want the vector's z value to be 0.0
375  t = std::min(t, (origin_z_ - oz) / c);
376  wp_outside = true;
377  }
378 
379  // the minimum value to raytrace from is the origin
380  if (wpx < origin_x_) {
381  t = std::min(t, (origin_x_ - ox) / a);
382  wp_outside = true;
383  }
384  if (wpy < origin_y_) {
385  t = std::min(t, (origin_y_ - oy) / b);
386  wp_outside = true;
387  }
388 
389  // the maximum value to raytrace to is the end of the map
390  if (wpx > map_end_x) {
391  t = std::min(t, (map_end_x - ox) / a);
392  wp_outside = true;
393  }
394  if (wpy > map_end_y) {
395  t = std::min(t, (map_end_y - oy) / b);
396  wp_outside = true;
397  }
398 
399  constexpr double wp_epsilon = 1e-5;
400  if (wp_outside) {
401  if (t > 0.0) {
402  t -= wp_epsilon;
403  } else if (t < 0.0) {
404  t += wp_epsilon;
405  }
406  }
407 
408  wpx = ox + a * t;
409  wpy = oy + b * t;
410  wpz = oz + c * t;
411 
412  double point_x, point_y, point_z;
413  if (worldToMap3DFloat(wpx, wpy, wpz, point_x, point_y, point_z)) {
414  unsigned int cell_raytrace_max_range = cellDistance(clearing_observation.raytrace_max_range_);
415  unsigned int cell_raytrace_min_range = cellDistance(clearing_observation.raytrace_min_range_);
416 
417 
418  // voxel_grid_.markVoxelLine(sensor_x, sensor_y, sensor_z, point_x, point_y, point_z);
419  voxel_grid_.clearVoxelLineInMap(
420  sensor_x, sensor_y, sensor_z, point_x, point_y, point_z,
421  costmap_,
422  unknown_threshold_, mark_threshold_, FREE_SPACE, NO_INFORMATION,
423  cell_raytrace_max_range, cell_raytrace_min_range);
424 
426  ox, oy, wpx, wpy, clearing_observation.raytrace_max_range_,
427  clearing_observation.raytrace_min_range_, min_x, min_y,
428  max_x,
429  max_y);
430 
431  if (publish_clearing_points) {
432  *clearing_endpoints_iter_x = wpx;
433  *clearing_endpoints_iter_y = wpy;
434  *clearing_endpoints_iter_z = wpz;
435 
436  ++clearing_endpoints_iter_x;
437  ++clearing_endpoints_iter_y;
438  ++clearing_endpoints_iter_z;
439  }
440  }
441  }
442 
443  if (publish_clearing_points) {
444  clearing_endpoints_->header.frame_id = global_frame_;
445  clearing_endpoints_->header.stamp = clearing_observation.cloud_.header.stamp;
446 
447  clearing_endpoints_pub_->publish(std::move(clearing_endpoints_));
448  }
449 }
450 
451 void VoxelLayer::updateOrigin(double new_origin_x, double new_origin_y)
452 {
453  // project the new origin into the grid
454  int cell_ox, cell_oy;
455  cell_ox = static_cast<int>((new_origin_x - origin_x_) / resolution_);
456  cell_oy = static_cast<int>((new_origin_y - origin_y_) / resolution_);
457 
458  // compute the associated world coordinates for the origin cell
459  // because we want to keep things grid-aligned
460  double new_grid_ox, new_grid_oy;
461  new_grid_ox = origin_x_ + cell_ox * resolution_;
462  new_grid_oy = origin_y_ + cell_oy * resolution_;
463 
464  // To save casting from unsigned int to int a bunch of times
465  int size_x = size_x_;
466  int size_y = size_y_;
467 
468  // we need to compute the overlap of the new and existing windows
469  int lower_left_x, lower_left_y, upper_right_x, upper_right_y;
470  lower_left_x = std::min(std::max(cell_ox, 0), size_x);
471  lower_left_y = std::min(std::max(cell_oy, 0), size_y);
472  upper_right_x = std::min(std::max(cell_ox + size_x, 0), size_x);
473  upper_right_y = std::min(std::max(cell_oy + size_y, 0), size_y);
474 
475  unsigned int cell_size_x = upper_right_x - lower_left_x;
476  unsigned int cell_size_y = upper_right_y - lower_left_y;
477 
478  // we need a map to store the obstacles in the window temporarily
479  unsigned char * local_map = new unsigned char[cell_size_x * cell_size_y];
480  unsigned int * local_voxel_map = new unsigned int[cell_size_x * cell_size_y];
481  unsigned int * voxel_map = voxel_grid_.getData();
482 
483  // copy the local window in the costmap to the local map
485  costmap_, lower_left_x, lower_left_y, size_x_, local_map, 0, 0, cell_size_x,
486  cell_size_x,
487  cell_size_y);
489  voxel_map, lower_left_x, lower_left_y, size_x_, local_voxel_map, 0, 0, cell_size_x,
490  cell_size_x,
491  cell_size_y);
492 
493  // we'll reset our maps to unknown space if appropriate
494  resetMaps();
495 
496  // update the origin with the appropriate world coordinates
497  origin_x_ = new_grid_ox;
498  origin_y_ = new_grid_oy;
499 
500  // compute the starting cell location for copying data back in
501  int start_x = lower_left_x - cell_ox;
502  int start_y = lower_left_y - cell_oy;
503 
504  // now we want to copy the overlapping information back into the map, but in its new location
506  local_map, 0, 0, cell_size_x, costmap_, start_x, start_y, size_x_, cell_size_x,
507  cell_size_y);
509  local_voxel_map, 0, 0, cell_size_x, voxel_map, start_x, start_y, size_x_,
510  cell_size_x,
511  cell_size_y);
512 
513  // make sure to clean up
514  delete[] local_map;
515  delete[] local_voxel_map;
516 }
517 
518 rcl_interfaces::msg::SetParametersResult VoxelLayer::validateParameterUpdatesCallback(
519  const std::vector<rclcpp::Parameter> & parameters)
520 {
521  rcl_interfaces::msg::SetParametersResult result;
522  result.successful = true;
523  for (const auto & parameter : parameters) {
524  const auto & param_type = parameter.get_type();
525  const auto & param_name = parameter.get_name();
526  if (param_name.find(name_ + ".") != 0) {
527  continue;
528  }
529  if (param_name == name_ + "." + "publish_voxel_map") {
530  RCLCPP_WARN(
531  logger_, "publish voxel map is not a dynamic parameter "
532  "cannot be changed while running. Rejecting parameter update.");
533  result.successful = false;
534  } else if (param_type == ParameterType::PARAMETER_DOUBLE) {
535  if (parameter.as_double() < 0.0 && param_name == name_ + "." + "z_resolution") {
536  RCLCPP_WARN(
537  logger_, "The value of parameter '%s' is incorrectly set to %f, "
538  "it should be >=0. Ignoring parameter update.",
539  param_name.c_str(), parameter.as_double());
540  result.successful = false;
541  }
542  }
543  }
544  return result;
545 }
546 
547 void
549  const std::vector<rclcpp::Parameter> & parameters)
550 {
551  std::lock_guard<Costmap2D::mutex_t> guard(*getMutex());
552  bool resize_map_needed = false;
553 
554  for (const auto & parameter : parameters) {
555  const auto & param_type = parameter.get_type();
556  const auto & param_name = parameter.get_name();
557  if (param_name.find(name_ + ".") != 0) {
558  continue;
559  }
560 
561  if (param_type == ParameterType::PARAMETER_DOUBLE) {
562  if (param_name == name_ + "." + "min_obstacle_height" &&
563  min_obstacle_height_ != parameter.as_double())
564  {
565  min_obstacle_height_ = parameter.as_double();
566  setCurrent(false);
567  } else if (param_name == name_ + "." + "max_obstacle_height" && // NOLINT(readability/braces)
568  max_obstacle_height_ != parameter.as_double())
569  {
570  max_obstacle_height_ = parameter.as_double();
571  setCurrent(false);
572  } else if (param_name == name_ + "." + "origin_z" && // NOLINT(readability/braces)
573  origin_z_ != parameter.as_double())
574  {
575  origin_z_ = parameter.as_double();
576  resize_map_needed = true;
577  setCurrent(false);
578  } else if (param_name == name_ + "." + "z_resolution" && // NOLINT(readability/braces)
579  z_resolution_ != parameter.as_double())
580  {
581  z_resolution_ = parameter.as_double();
582  resize_map_needed = true;
583  setCurrent(false);
584  }
585 
586  } else if (param_type == ParameterType::PARAMETER_BOOL) {
587  if (param_name == name_ + "." + "enabled" &&
588  enabled_ != parameter.as_bool())
589  {
590  enabled_ = parameter.as_bool();
591  setCurrent(false);
592  } else if (param_name == name_ + "." + "footprint_clearing_enabled") {
593  footprint_clearing_enabled_ = parameter.as_bool();
594  }
595 
596  } else if (param_type == ParameterType::PARAMETER_INTEGER) {
597  if (param_name == name_ + "." + "z_voxels" &&
598  size_z_ != parameter.as_int())
599  {
600  size_z_ = parameter.as_int();
601  resize_map_needed = true;
602  setCurrent(false);
603  } else if (param_name == name_ + "." + "unknown_threshold") {
604  unknown_threshold_ = parameter.as_int() + (VOXEL_BITS - size_z_);
605  setCurrent(false);
606  } else if (param_name == name_ + "." + "mark_threshold") {
607  mark_threshold_ = parameter.as_int();
608  setCurrent(false);
609  } else if (param_name == name_ + "." + "combination_method") {
610  combination_method_ = combination_method_from_int(parameter.as_int());
611  }
612  }
613  }
614 
615  if (resize_map_needed) {
616  matchSize();
617  }
618 }
619 
620 } // namespace nav2_costmap_2d
A QoS profile for latched, reliable topics with a history of 1 messages.
unsigned int getIndex(unsigned int mx, unsigned int my) const
Given two map coordinates... compute the associated index.
Definition: costmap_2d.hpp:231
void copyMapRegion(data_type *source_map, unsigned int sm_lower_left_x, unsigned int sm_lower_left_y, unsigned int sm_size_x, data_type *dest_map, unsigned int dm_lower_left_x, unsigned int dm_lower_left_y, unsigned int dm_size_x, unsigned int region_size_x, unsigned int region_size_y)
Copy a region of a source map into a destination map.
Definition: costmap_2d.hpp:428
double getSizeInMetersY() const
Accessor for the y size of the costmap in meters.
Definition: costmap_2d.cpp:563
double getSizeInMetersX() const
Accessor for the x size of the costmap in meters.
Definition: costmap_2d.cpp:558
virtual void resetMaps()
Resets the costmap and static_map to be unknown space.
Definition: costmap_2d.cpp:125
unsigned int cellDistance(double world_dist)
Given distance in the world... convert it to cells.
Definition: costmap_2d.cpp:254
void touch(double x, double y, double *min_x, double *min_y, double *max_x, double *max_y)
virtual void matchSize()
Match the size of the master costmap.
CombinationMethod combination_method_from_int(const int value)
Converts an integer to a CombinationMethod enum and logs on failure.
Abstract class for layered costmap plugin implementations.
Definition: layer.hpp:62
void setCurrent(bool current)
Set whether the data in the layer is up to date.
Definition: layer.hpp:149
Stores an observation in terms of a point cloud and the origin of the source.
Definition: observation.hpp:47
virtual void activate()
Activate the layer.
std::string global_frame_
The global frame for the costmap.
void updateRaytraceBounds(double ox, double oy, double wx, double wy, double max_range, double min_range, double *min_x, double *min_y, double *max_x, double *max_y)
Process update costmap with raytracing the window bounds.
bool getMarkingObservations(std::vector< nav2_costmap_2d::Observation::ConstSharedPtr > &marking_observations) const
Get the observations used to mark space.
bool getClearingObservations(std::vector< nav2_costmap_2d::Observation::ConstSharedPtr > &clearing_observations) const
Get the observations used to clear space.
void updateFootprint(double robot_x, double robot_y, double robot_yaw, double *min_x, double *min_y, double *max_x, double *max_y)
Clear costmap layer info below the robot's footprint.
virtual void deactivate()
Deactivate the layer.
virtual void onInitialize()
Initialization process of layer on startup.
double min_obstacle_height_
Max Obstacle Height.
double max_obstacle_height_
Max Obstacle Height.
virtual void reset()
Reset this costmap.
Takes laser and pointcloud data to populate a 3D voxel representation of the environment.
Definition: voxel_layer.hpp:65
virtual void onInitialize()
Initialization process of layer on startup.
Definition: voxel_layer.cpp:61
virtual void activate()
Activate the layer.
virtual ~VoxelLayer()
Voxel Layer destructor.
double getSizeInMetersZ() const
Get the height of the voxel sizes in meters.
virtual void updateBounds(double robot_x, double robot_y, double robot_yaw, double *min_x, double *min_y, double *max_x, double *max_y)
Update the bounds of the master costmap by this layer's update dimensions.
void updateOrigin(double new_origin_x, double new_origin_y)
Update the layer's origin to a new pose, often when in a rolling costmap.
virtual void deactivate()
Deactivate the layer.
bool worldToMap3DFloat(double wx, double wy, double wz, double &mx, double &my, double &mz)
Convert world coordinates into map coordinates.
bool worldToMap3D(double wx, double wy, double wz, unsigned int &mx, unsigned int &my, unsigned int &mz)
Convert world coordinates into map coordinates.
virtual void resetMaps()
Reset internal maps.
virtual void matchSize()
Match the size of the master costmap.
rcl_interfaces::msg::SetParametersResult validateParameterUpdatesCallback(const std::vector< rclcpp::Parameter > &parameters)
Validate incoming parameter updates before applying them. This callback is triggered when one or more...
void updateParametersCallback(const std::vector< rclcpp::Parameter > &parameters)
Apply parameter updates after validation This callback is executed when parameters have been successf...
virtual void reset()
Reset this costmap.
double dist(double x0, double y0, double z0, double x1, double y1, double z1)
Find L2 norm distance in 3D.
virtual void raytraceFreespace(const nav2_costmap_2d::Observation &clearing_observation, double *min_x, double *min_y, double *max_x, double *max_y)
Use raycasting between 2 points to clear freespace.
void resize(unsigned int size_x, unsigned int size_y, unsigned int size_z)
Resizes a voxel grid to the desired size.
Definition: voxel_grid.cpp:67