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  double sq_obstacle_max_range = obs.obstacle_max_range_ * obs.obstacle_max_range_;
199  double sq_obstacle_min_range = obs.obstacle_min_range_ * obs.obstacle_min_range_;
200 
201  sensor_msgs::PointCloud2ConstIterator<float> iter_x(cloud, "x");
202  sensor_msgs::PointCloud2ConstIterator<float> iter_y(cloud, "y");
203  sensor_msgs::PointCloud2ConstIterator<float> iter_z(cloud, "z");
204 
205  for (; iter_x != iter_x.end(); ++iter_x, ++iter_y, ++iter_z) {
206  // if the obstacle is too low, we won't add it
207  if (*iter_z < min_obstacle_height_) {
208  continue;
209  }
210 
211  // if the obstacle is too high or too far away from the robot we won't add it
212  if (*iter_z > max_obstacle_height_) {
213  continue;
214  }
215 
216  // compute the squared distance from the hitpoint to the pointcloud's origin
217  double sq_dist = (*iter_x - obs.origin_.x) * (*iter_x - obs.origin_.x) +
218  (*iter_y - obs.origin_.y) * (*iter_y - obs.origin_.y) +
219  (*iter_z - obs.origin_.z) * (*iter_z - obs.origin_.z);
220 
221  // if the point is far enough away... we won't consider it
222  if (sq_dist >= sq_obstacle_max_range) {
223  continue;
224  }
225 
226  // If the point is too close, do not consider it
227  if (sq_dist < sq_obstacle_min_range) {
228  continue;
229  }
230 
231  // now we need to compute the map coordinates for the observation
232  unsigned int mx, my, mz;
233  if (*iter_z < origin_z_) {
234  if (!worldToMap3D(*iter_x, *iter_y, origin_z_, mx, my, mz)) {
235  continue;
236  }
237  } else if (!worldToMap3D(*iter_x, *iter_y, *iter_z, mx, my, mz)) {
238  continue;
239  }
240 
241  // mark the cell in the voxel grid and check if we should also mark it in the costmap
242  if (voxel_grid_.markVoxelInMap(mx, my, mz, mark_threshold_)) {
243  unsigned int index = getIndex(mx, my);
244 
245  costmap_[index] = LETHAL_OBSTACLE;
246  touch(
247  static_cast<double>(*iter_x), static_cast<double>(*iter_y),
248  min_x, min_y, max_x, max_y);
249  }
250  }
251  }
252 
253  if (publish_voxel_) {
254  auto grid_msg = std::make_unique<nav2_msgs::msg::VoxelGrid>();
255  unsigned int size = voxel_grid_.sizeX() * voxel_grid_.sizeY();
256  grid_msg->size_x = voxel_grid_.sizeX();
257  grid_msg->size_y = voxel_grid_.sizeY();
258  grid_msg->size_z = voxel_grid_.sizeZ();
259  grid_msg->data.resize(size);
260  memcpy(&grid_msg->data[0], voxel_grid_.getData(), size * sizeof(unsigned int));
261 
262  grid_msg->origin.x = origin_x_;
263  grid_msg->origin.y = origin_y_;
264  grid_msg->origin.z = origin_z_;
265 
266  grid_msg->resolutions.x = resolution_;
267  grid_msg->resolutions.y = resolution_;
268  grid_msg->resolutions.z = z_resolution_;
269  grid_msg->header.frame_id = global_frame_;
270  grid_msg->header.stamp = clock_->now();
271 
272  voxel_pub_->publish(std::move(grid_msg));
273  }
274 
275  updateFootprint(robot_x, robot_y, robot_yaw, min_x, min_y, max_x, max_y);
276 }
277 
279  const Observation & clearing_observation, double * min_x,
280  double * min_y,
281  double * max_x,
282  double * max_y)
283 {
284  auto clearing_endpoints_ = std::make_unique<sensor_msgs::msg::PointCloud2>();
285 
286  if (clearing_observation.cloud_.height == 0 || clearing_observation.cloud_.width == 0) {
287  return;
288  }
289 
290  double sensor_x, sensor_y, sensor_z;
291  double ox = clearing_observation.origin_.x;
292  double oy = clearing_observation.origin_.y;
293  double oz = clearing_observation.origin_.z;
294 
295  if (!worldToMap3DFloat(ox, oy, oz, sensor_x, sensor_y, sensor_z)) {
296  RCLCPP_WARN(
297  logger_,
298  "Sensor origin at (%.2f, %.2f %.2f) is out of map bounds "
299  "(%.2f, %.2f, %.2f) to (%.2f, %.2f, %.2f). "
300  "The costmap cannot raytrace for it.",
301  ox, oy, oz,
302  origin_x_, origin_y_, origin_z_,
303  origin_x_ + getSizeInMetersX(), origin_y_ + getSizeInMetersY(),
304  origin_z_ + getSizeInMetersZ());
305 
306  return;
307  }
308 
309  bool publish_clearing_points;
310 
311  {
312  auto node = node_.lock();
313  if (!node) {
314  throw std::runtime_error{"Failed to lock node"};
315  }
316  publish_clearing_points = (node->count_subscribers("clearing_endpoints") > 0);
317  }
318 
319  clearing_endpoints_->data.clear();
320  clearing_endpoints_->width = clearing_observation.cloud_.width;
321  clearing_endpoints_->height = clearing_observation.cloud_.height;
322  clearing_endpoints_->is_dense = true;
323  clearing_endpoints_->is_bigendian = false;
324 
325  sensor_msgs::PointCloud2Modifier modifier(*clearing_endpoints_);
326  modifier.setPointCloud2Fields(
327  3, "x", 1, sensor_msgs::msg::PointField::FLOAT32,
328  "y", 1, sensor_msgs::msg::PointField::FLOAT32,
329  "z", 1, sensor_msgs::msg::PointField::FLOAT32);
330 
331  sensor_msgs::PointCloud2Iterator<float> clearing_endpoints_iter_x(*clearing_endpoints_, "x");
332  sensor_msgs::PointCloud2Iterator<float> clearing_endpoints_iter_y(*clearing_endpoints_, "y");
333  sensor_msgs::PointCloud2Iterator<float> clearing_endpoints_iter_z(*clearing_endpoints_, "z");
334 
335  // we can pre-compute the endpoints of the map outside of the inner loop... we'll need these later
336  double map_end_x = origin_x_ + getSizeInMetersX();
337  double map_end_y = origin_y_ + getSizeInMetersY();
338  double map_end_z = origin_z_ + getSizeInMetersZ();
339 
340  sensor_msgs::PointCloud2ConstIterator<float> iter_x(clearing_observation.cloud_, "x");
341  sensor_msgs::PointCloud2ConstIterator<float> iter_y(clearing_observation.cloud_, "y");
342  sensor_msgs::PointCloud2ConstIterator<float> iter_z(clearing_observation.cloud_, "z");
343 
344  for (; iter_x != iter_x.end(); ++iter_x, ++iter_y, ++iter_z) {
345  double wpx = *iter_x;
346  double wpy = *iter_y;
347  double wpz = *iter_z;
348 
349  double distance = dist(ox, oy, oz, wpx, wpy, wpz);
350  double scaling_fact = 1.0;
351  scaling_fact = std::max(std::min(scaling_fact, (distance - 2 * resolution_) / distance), 0.0);
352  wpx = scaling_fact * (wpx - ox) + ox;
353  wpy = scaling_fact * (wpy - oy) + oy;
354  wpz = scaling_fact * (wpz - oz) + oz;
355 
356  double a = wpx - ox;
357  double b = wpy - oy;
358  double c = wpz - oz;
359  double t = 1.0;
360  bool wp_outside = false;
361 
362  // we can only raytrace to a maximum z height
363  if (wpz > map_end_z) {
364  // we know we want the vector's z value to be max_z
365  t = std::max(0.0, std::min(t, (map_end_z - 0.01 - oz) / c));
366  wp_outside = true;
367  } else if (wpz < origin_z_) {
368  // and we can only raytrace down to the floor
369  // we know we want the vector's z value to be 0.0
370  t = std::min(t, (origin_z_ - oz) / c);
371  wp_outside = true;
372  }
373 
374  // the minimum value to raytrace from is the origin
375  if (wpx < origin_x_) {
376  t = std::min(t, (origin_x_ - ox) / a);
377  wp_outside = true;
378  }
379  if (wpy < origin_y_) {
380  t = std::min(t, (origin_y_ - oy) / b);
381  wp_outside = true;
382  }
383 
384  // the maximum value to raytrace to is the end of the map
385  if (wpx > map_end_x) {
386  t = std::min(t, (map_end_x - ox) / a);
387  wp_outside = true;
388  }
389  if (wpy > map_end_y) {
390  t = std::min(t, (map_end_y - oy) / b);
391  wp_outside = true;
392  }
393 
394  constexpr double wp_epsilon = 1e-5;
395  if (wp_outside) {
396  if (t > 0.0) {
397  t -= wp_epsilon;
398  } else if (t < 0.0) {
399  t += wp_epsilon;
400  }
401  }
402 
403  wpx = ox + a * t;
404  wpy = oy + b * t;
405  wpz = oz + c * t;
406 
407  double point_x, point_y, point_z;
408  if (worldToMap3DFloat(wpx, wpy, wpz, point_x, point_y, point_z)) {
409  unsigned int cell_raytrace_max_range = cellDistance(clearing_observation.raytrace_max_range_);
410  unsigned int cell_raytrace_min_range = cellDistance(clearing_observation.raytrace_min_range_);
411 
412 
413  // voxel_grid_.markVoxelLine(sensor_x, sensor_y, sensor_z, point_x, point_y, point_z);
414  voxel_grid_.clearVoxelLineInMap(
415  sensor_x, sensor_y, sensor_z, point_x, point_y, point_z,
416  costmap_,
417  unknown_threshold_, mark_threshold_, FREE_SPACE, NO_INFORMATION,
418  cell_raytrace_max_range, cell_raytrace_min_range);
419 
421  ox, oy, wpx, wpy, clearing_observation.raytrace_max_range_,
422  clearing_observation.raytrace_min_range_, min_x, min_y,
423  max_x,
424  max_y);
425 
426  if (publish_clearing_points) {
427  *clearing_endpoints_iter_x = wpx;
428  *clearing_endpoints_iter_y = wpy;
429  *clearing_endpoints_iter_z = wpz;
430 
431  ++clearing_endpoints_iter_x;
432  ++clearing_endpoints_iter_y;
433  ++clearing_endpoints_iter_z;
434  }
435  }
436  }
437 
438  if (publish_clearing_points) {
439  clearing_endpoints_->header.frame_id = global_frame_;
440  clearing_endpoints_->header.stamp = clearing_observation.cloud_.header.stamp;
441 
442  clearing_endpoints_pub_->publish(std::move(clearing_endpoints_));
443  }
444 }
445 
446 void VoxelLayer::updateOrigin(double new_origin_x, double new_origin_y)
447 {
448  // project the new origin into the grid
449  int cell_ox, cell_oy;
450  cell_ox = static_cast<int>((new_origin_x - origin_x_) / resolution_);
451  cell_oy = static_cast<int>((new_origin_y - origin_y_) / resolution_);
452 
453  // compute the associated world coordinates for the origin cell
454  // because we want to keep things grid-aligned
455  double new_grid_ox, new_grid_oy;
456  new_grid_ox = origin_x_ + cell_ox * resolution_;
457  new_grid_oy = origin_y_ + cell_oy * resolution_;
458 
459  // To save casting from unsigned int to int a bunch of times
460  int size_x = size_x_;
461  int size_y = size_y_;
462 
463  // we need to compute the overlap of the new and existing windows
464  int lower_left_x, lower_left_y, upper_right_x, upper_right_y;
465  lower_left_x = std::min(std::max(cell_ox, 0), size_x);
466  lower_left_y = std::min(std::max(cell_oy, 0), size_y);
467  upper_right_x = std::min(std::max(cell_ox + size_x, 0), size_x);
468  upper_right_y = std::min(std::max(cell_oy + size_y, 0), size_y);
469 
470  unsigned int cell_size_x = upper_right_x - lower_left_x;
471  unsigned int cell_size_y = upper_right_y - lower_left_y;
472 
473  // we need a map to store the obstacles in the window temporarily
474  unsigned char * local_map = new unsigned char[cell_size_x * cell_size_y];
475  unsigned int * local_voxel_map = new unsigned int[cell_size_x * cell_size_y];
476  unsigned int * voxel_map = voxel_grid_.getData();
477 
478  // copy the local window in the costmap to the local map
480  costmap_, lower_left_x, lower_left_y, size_x_, local_map, 0, 0, cell_size_x,
481  cell_size_x,
482  cell_size_y);
484  voxel_map, lower_left_x, lower_left_y, size_x_, local_voxel_map, 0, 0, cell_size_x,
485  cell_size_x,
486  cell_size_y);
487 
488  // we'll reset our maps to unknown space if appropriate
489  resetMaps();
490 
491  // update the origin with the appropriate world coordinates
492  origin_x_ = new_grid_ox;
493  origin_y_ = new_grid_oy;
494 
495  // compute the starting cell location for copying data back in
496  int start_x = lower_left_x - cell_ox;
497  int start_y = lower_left_y - cell_oy;
498 
499  // now we want to copy the overlapping information back into the map, but in its new location
501  local_map, 0, 0, cell_size_x, costmap_, start_x, start_y, size_x_, cell_size_x,
502  cell_size_y);
504  local_voxel_map, 0, 0, cell_size_x, voxel_map, start_x, start_y, size_x_,
505  cell_size_x,
506  cell_size_y);
507 
508  // make sure to clean up
509  delete[] local_map;
510  delete[] local_voxel_map;
511 }
512 
513 rcl_interfaces::msg::SetParametersResult VoxelLayer::validateParameterUpdatesCallback(
514  const std::vector<rclcpp::Parameter> & parameters)
515 {
516  rcl_interfaces::msg::SetParametersResult result;
517  result.successful = true;
518  for (const auto & parameter : parameters) {
519  const auto & param_type = parameter.get_type();
520  const auto & param_name = parameter.get_name();
521  if (param_name.find(name_ + ".") != 0) {
522  continue;
523  }
524  if (param_name == name_ + "." + "publish_voxel_map") {
525  RCLCPP_WARN(
526  logger_, "publish voxel map is not a dynamic parameter "
527  "cannot be changed while running. Rejecting parameter update.");
528  result.successful = false;
529  } else if (param_type == ParameterType::PARAMETER_DOUBLE) {
530  if (parameter.as_double() < 0.0 && param_name == name_ + "." + "z_resolution") {
531  RCLCPP_WARN(
532  logger_, "The value of parameter '%s' is incorrectly set to %f, "
533  "it should be >=0. Ignoring parameter update.",
534  param_name.c_str(), parameter.as_double());
535  result.successful = false;
536  }
537  }
538  }
539  return result;
540 }
541 
542 void
544  const std::vector<rclcpp::Parameter> & parameters)
545 {
546  std::lock_guard<Costmap2D::mutex_t> guard(*getMutex());
547  bool resize_map_needed = false;
548 
549  for (const auto & parameter : parameters) {
550  const auto & param_type = parameter.get_type();
551  const auto & param_name = parameter.get_name();
552  if (param_name.find(name_ + ".") != 0) {
553  continue;
554  }
555 
556  if (param_type == ParameterType::PARAMETER_DOUBLE) {
557  if (param_name == name_ + "." + "min_obstacle_height" &&
558  min_obstacle_height_ != parameter.as_double())
559  {
560  min_obstacle_height_ = parameter.as_double();
561  setCurrent(false);
562  } else if (param_name == name_ + "." + "max_obstacle_height" && // NOLINT(readability/braces)
563  max_obstacle_height_ != parameter.as_double())
564  {
565  max_obstacle_height_ = parameter.as_double();
566  setCurrent(false);
567  } else if (param_name == name_ + "." + "origin_z" && // NOLINT(readability/braces)
568  origin_z_ != parameter.as_double())
569  {
570  origin_z_ = parameter.as_double();
571  resize_map_needed = true;
572  setCurrent(false);
573  } else if (param_name == name_ + "." + "z_resolution" && // NOLINT(readability/braces)
574  z_resolution_ != parameter.as_double())
575  {
576  z_resolution_ = parameter.as_double();
577  resize_map_needed = true;
578  setCurrent(false);
579  }
580 
581  } else if (param_type == ParameterType::PARAMETER_BOOL) {
582  if (param_name == name_ + "." + "enabled" &&
583  enabled_ != parameter.as_bool())
584  {
585  enabled_ = parameter.as_bool();
586  setCurrent(false);
587  } else if (param_name == name_ + "." + "footprint_clearing_enabled") {
588  footprint_clearing_enabled_ = parameter.as_bool();
589  }
590 
591  } else if (param_type == ParameterType::PARAMETER_INTEGER) {
592  if (param_name == name_ + "." + "z_voxels" &&
593  size_z_ != parameter.as_int())
594  {
595  size_z_ = parameter.as_int();
596  resize_map_needed = true;
597  setCurrent(false);
598  } else if (param_name == name_ + "." + "unknown_threshold") {
599  unknown_threshold_ = parameter.as_int() + (VOXEL_BITS - size_z_);
600  setCurrent(false);
601  } else if (param_name == name_ + "." + "mark_threshold") {
602  mark_threshold_ = parameter.as_int();
603  setCurrent(false);
604  } else if (param_name == name_ + "." + "combination_method") {
605  combination_method_ = combination_method_from_int(parameter.as_int());
606  }
607  }
608  }
609 
610  if (resize_map_needed) {
611  matchSize();
612  }
613 }
614 
615 } // 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:60
void setCurrent(bool current)
Set whether the data in the layer is up to date.
Definition: layer.hpp:147
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:64
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