Nav2 Navigation Stack - rolling  main
ROS 2 Navigation Stack
static_layer.cpp
1 /*********************************************************************
2  *
3  * Software License Agreement (BSD License)
4  *
5  * Copyright (c) 2008, 2013, Willow Garage, Inc.
6  * Copyright (c) 2015, Fetch Robotics, Inc.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * * Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  * * Redistributions in binary form must reproduce the above
16  * copyright notice, this list of conditions and the following
17  * disclaimer in the documentation and/or other materials provided
18  * with the distribution.
19  * * Neither the name of Willow Garage, Inc. nor the names of its
20  * contributors may be used to endorse or promote products derived
21  * from this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34  * POSSIBILITY OF SUCH DAMAGE.
35  *
36  * Author: Eitan Marder-Eppstein
37  * David V. Lu!!
38  *********************************************************************/
39 
40 #include "nav2_costmap_2d/static_layer.hpp"
41 
42 #include <algorithm>
43 #include <string>
44 
45 #include "pluginlib/class_list_macros.hpp"
46 #include "tf2/convert.hpp"
47 #include "tf2_geometry_msgs/tf2_geometry_msgs.hpp"
48 #include "nav2_ros_common/validate_messages.hpp"
49 
50 #define EPSILON 1e-5
51 
53 
54 using nav2_costmap_2d::NO_INFORMATION;
55 using nav2_costmap_2d::LETHAL_OBSTACLE;
56 using nav2_costmap_2d::INSCRIBED_INFLATED_OBSTACLE;
57 using nav2_costmap_2d::FREE_SPACE;
58 using rcl_interfaces::msg::ParameterType;
59 
60 namespace nav2_costmap_2d
61 {
62 
64 : map_buffer_(nullptr)
65 {
66 }
67 
69 {
70 }
71 
72 void
74 {
75  global_frame_ = layered_costmap_->getGlobalFrameID();
76 
77  getParameters();
78 
79  rclcpp::QoS map_qos = nav2::qos::StandardTopicQoS(); // initialize to default
80  if (map_subscribe_transient_local_) {
82  }
83 
84  RCLCPP_INFO(
85  logger_,
86  "Subscribing to the map topic (%s) with %s durability",
87  map_topic_.c_str(),
88  map_subscribe_transient_local_ ? "transient local" : "volatile");
89 
90  auto node = node_.lock();
91  if (!node) {
92  throw std::runtime_error{"Failed to lock node"};
93  }
94 
95  map_sub_ = node->create_subscription<nav_msgs::msg::OccupancyGrid>(
96  map_topic_,
97  std::bind(&StaticLayer::incomingMap, this, std::placeholders::_1),
98  map_qos);
99 
100  if (subscribe_to_updates_) {
101  RCLCPP_INFO(logger_, "Subscribing to updates");
102  map_update_sub_ = node->create_subscription<map_msgs::msg::OccupancyGridUpdate>(
103  map_topic_ + "_updates",
104  std::bind(&StaticLayer::incomingUpdate, this, std::placeholders::_1));
105  }
106 }
107 
108 void
110 {
111  auto node = node_.lock();
112  // Add callback for dynamic parameters
113  post_set_params_handler_ = node->add_post_set_parameters_callback(
114  std::bind(
116  this, std::placeholders::_1));
117  on_set_params_handler_ = node->add_on_set_parameters_callback(
118  std::bind(
120  this, std::placeholders::_1));
121 }
122 
123 void
125 {
126  auto node = node_.lock();
127  if (post_set_params_handler_ && node) {
128  node->remove_post_set_parameters_callback(post_set_params_handler_.get());
129  }
130  post_set_params_handler_.reset();
131  if (on_set_params_handler_ && node) {
132  node->remove_on_set_parameters_callback(on_set_params_handler_.get());
133  }
134  on_set_params_handler_.reset();
135 }
136 
137 void
139 {
140  has_updated_data_ = true;
141  setCurrent(false);
142 }
143 
144 void
146 {
147  int temp_lethal_threshold = 0;
148  double temp_tf_tol = 0.0;
149 
150  auto node = node_.lock();
151  if (!node) {
152  throw std::runtime_error{"Failed to lock node"};
153  }
154 
155  enabled_ = node->declare_or_get_parameter(name_ + "." + "enabled", true);
156  resize_master_ = node->declare_or_get_parameter(name_ + "." + "resize_master", true);
157  subscribe_to_updates_ = node->declare_or_get_parameter(
158  name_ + "." + "subscribe_to_updates", false);
159  footprint_clearing_enabled_ = node->declare_or_get_parameter(
160  name_ + "." + "footprint_clearing_enabled", false);
161  restore_cleared_footprint_ = node->declare_or_get_parameter(
162  name_ + "." + "restore_cleared_footprint", true);
163  map_topic_ = node->declare_or_get_parameter(
164  name_ + "." + "map_topic", std::string("map"));
165  map_topic_ = joinWithParentNamespace(map_topic_);
166  map_subscribe_transient_local_ = node->declare_or_get_parameter(
167  name_ + "." + "map_subscribe_transient_local", true);
168  node->get_parameter("track_unknown_space", track_unknown_space_);
169  node->get_parameter("use_maximum", use_maximum_);
170  node->get_parameter("lethal_cost_threshold", temp_lethal_threshold);
171  node->get_parameter("inscribed_obstacle_cost_value", inscribed_obstacle_cost_value_);
172  node->get_parameter("unknown_cost_value", unknown_cost_value_);
173  node->get_parameter("trinary_costmap", trinary_costmap_);
174  node->get_parameter("transform_tolerance", temp_tf_tol);
175 
176  // Enforce bounds
177  lethal_threshold_ = std::max(std::min(temp_lethal_threshold, 100), 0);
178  map_received_ = false;
179  map_received_in_update_bounds_ = false;
180 
181  transform_tolerance_ = tf2::durationFromSec(temp_tf_tol);
182 }
183 
184 void
185 StaticLayer::processMap(const nav_msgs::msg::OccupancyGrid & new_map)
186 {
187  RCLCPP_DEBUG(logger_, "StaticLayer: Process map");
188 
189  unsigned int size_x = new_map.info.width;
190  unsigned int size_y = new_map.info.height;
191 
192  RCLCPP_DEBUG(
193  logger_,
194  "StaticLayer: Received a %d X %d map at %f m/pix", size_x, size_y,
195  new_map.info.resolution);
196 
197  // resize costmap if size, resolution or origin do not match
198  Costmap2D * master = layered_costmap_->getCostmap();
199  if (usesMasterCostmapSize() && (master->getSizeInCellsX() != size_x ||
200  master->getSizeInCellsY() != size_y ||
201  !isEqual(master->getResolution(), new_map.info.resolution, EPSILON) ||
202  !isEqual(master->getOriginX(), new_map.info.origin.position.x, EPSILON) ||
203  !isEqual(master->getOriginY(), new_map.info.origin.position.y, EPSILON) ||
204  !layered_costmap_->isSizeLocked()))
205  {
206  // Update the size of the layered costmap (and all layers, including this one)
207  RCLCPP_INFO(
208  logger_,
209  "StaticLayer: Resizing costmap to %d X %d at %f m/pix", size_x, size_y,
210  new_map.info.resolution);
211 
212  double fmod_x = std::fmod(new_map.info.origin.position.x, new_map.info.resolution);
213  double fmod_y = std::fmod(new_map.info.origin.position.y, new_map.info.resolution);
214 
215  if (std::abs(fmod_x) > EPSILON || std::abs(fmod_y) > EPSILON) {
216  RCLCPP_WARN(
217  logger_,
218  "StaticLayer: Costmap origin coordinates are not perfectly aligned with the resolution. "
219  "This may cause misalignment aliasing between rolling and non-rolling costmaps.\n"
220  "Map origin: (%.f, %.f) | Resolution: %.f",
221  new_map.info.origin.position.x, new_map.info.origin.position.y,
222  new_map.info.resolution);
223  }
224 
225  layered_costmap_->resizeMap(
226  size_x, size_y, new_map.info.resolution,
227  new_map.info.origin.position.x,
228  new_map.info.origin.position.y,
229  true);
230  } else if (size_x_ != size_x || size_y_ != size_y || // NOLINT
231  !isEqual(resolution_, new_map.info.resolution, EPSILON) ||
232  !isEqual(origin_x_, new_map.info.origin.position.x, EPSILON) ||
233  !isEqual(origin_y_, new_map.info.origin.position.y, EPSILON))
234  {
235  // only update the size of the costmap stored locally in this layer
236  RCLCPP_INFO(
237  logger_,
238  "StaticLayer: Resizing static layer to %d X %d at %f m/pix", size_x, size_y,
239  new_map.info.resolution);
240  if (!layered_costmap_->isRolling() && !resize_master_ && size_x_ > 0 && size_y_ > 0) {
241  // Re-render the previous map's extent so a moved or shrunk map clears what it covered
243  origin_x_, origin_y_,
244  origin_x_ + size_x_ * resolution_, origin_y_ + size_y_ * resolution_);
245  }
246  resizeMap(
247  size_x, size_y, new_map.info.resolution,
248  new_map.info.origin.position.x, new_map.info.origin.position.y);
249  }
250 
251  unsigned int index = 0;
252 
253  // we have a new map, update full size of map
254  std::lock_guard<Costmap2D::mutex_t> guard(*getMutex());
255 
256  // initialize the costmap with static data
257  for (unsigned int i = 0; i < size_y; ++i) {
258  for (unsigned int j = 0; j < size_x; ++j) {
259  unsigned char value = new_map.data[index];
260  costmap_[index] = interpretValue(value);
261  ++index;
262  }
263  }
264 
265  map_frame_ = new_map.header.frame_id;
266 
267  x_ = y_ = 0;
268  width_ = size_x_;
269  height_ = size_y_;
270  has_updated_data_ = true;
271 
272  setCurrent(true);
273 }
274 
275 void
277 {
278  // If we are using rolling costmap or not resizing the master, the static map size is
279  // unrelated to the size of the layered costmap
280  if (usesMasterCostmapSize()) {
281  Costmap2D * master = layered_costmap_->getCostmap();
282  resizeMap(
283  master->getSizeInCellsX(), master->getSizeInCellsY(), master->getResolution(),
284  master->getOriginX(), master->getOriginY());
285  } else {
286  // The master was resized (and cleared) by someone else: repaint our extent into it
287  has_updated_data_ = true;
288  }
289 }
290 
291 bool
293 {
294  return !layered_costmap_->isRolling() && resize_master_;
295 }
296 
297 unsigned char
298 StaticLayer::interpretValue(unsigned char value)
299 {
300  // check if the static value is above the unknown or lethal thresholds
301  if (track_unknown_space_ && value == unknown_cost_value_) {
302  return NO_INFORMATION;
303  } else if (!track_unknown_space_ && value == unknown_cost_value_) {
304  return FREE_SPACE;
305  } else if (value == inscribed_obstacle_cost_value_) {
306  return INSCRIBED_INFLATED_OBSTACLE;
307  } else if (value >= lethal_threshold_) {
308  return LETHAL_OBSTACLE;
309  } else if (trinary_costmap_) {
310  return FREE_SPACE;
311  }
312 
313  double scale = static_cast<double>(value) / lethal_threshold_;
314  return scale * LETHAL_OBSTACLE;
315 }
316 
317 void
318 StaticLayer::incomingMap(const nav_msgs::msg::OccupancyGrid::ConstSharedPtr & new_map)
319 {
320  if (!nav2::validateMsg(*new_map)) {
321  RCLCPP_ERROR(logger_, "Received map message is malformed. Rejecting.");
322  return;
323  }
324  if (!layered_costmap_->isRolling() && !resize_master_ &&
325  new_map->header.frame_id != global_frame_)
326  {
327  // Non-rolling bounds are reported in the map frame, so it must be the costmap frame
328  RCLCPP_ERROR_THROTTLE(
329  logger_, *clock_, 10000,
330  "StaticLayer: Map in frame %s ignored: with resize_master false on a non-rolling costmap "
331  "the map must be in the costmap global frame (%s)",
332  new_map->header.frame_id.c_str(), global_frame_.c_str());
333  return;
334  }
335  if (!map_received_) {
336  processMap(*new_map);
337  map_received_ = true;
338  return;
339  }
340  std::lock_guard<Costmap2D::mutex_t> guard(*getMutex());
341  map_buffer_ = new_map;
342  setCurrent(false);
343 }
344 
345 void
346 StaticLayer::incomingUpdate(map_msgs::msg::OccupancyGridUpdate::ConstSharedPtr update)
347 {
348  if (!nav2::validateMsg(*update)) {
349  RCLCPP_ERROR(logger_, "Received map update is malformed. Rejecting.");
350  return;
351  }
352 
353  std::lock_guard<Costmap2D::mutex_t> guard(*getMutex());
354  if (update->y < static_cast<int32_t>(y_) ||
355  y_ + height_ < update->y + update->height ||
356  update->x < static_cast<int32_t>(x_) ||
357  x_ + width_ < update->x + update->width)
358  {
359  RCLCPP_WARN(
360  logger_,
361  "StaticLayer: Map update ignored. Exceeds bounds of static layer.\n"
362  "Static layer origin: %d, %d bounds: %d X %d\n"
363  "Update origin: %d, %d bounds: %d X %d",
364  x_, y_, width_, height_, update->x, update->y, update->width,
365  update->height);
366  return;
367  }
368 
369  if (update->header.frame_id != map_frame_) {
370  RCLCPP_WARN(
371  logger_,
372  "StaticLayer: Map update ignored. Current map is in frame %s "
373  "but update was in frame %s",
374  map_frame_.c_str(), update->header.frame_id.c_str());
375  return;
376  }
377 
378  unsigned int di = 0;
379  for (unsigned int y = 0; y < update->height; y++) {
380  unsigned int index_base = (update->y + y) * size_x_;
381  for (unsigned int x = 0; x < update->width; x++) {
382  unsigned int index = index_base + x + update->x;
383  costmap_[index] = interpretValue(update->data[di++]);
384  }
385  }
386 
387  has_updated_data_ = true;
388 }
389 
390 
391 void
393  double robot_x, double robot_y, double robot_yaw, double * min_x,
394  double * min_y,
395  double * max_x,
396  double * max_y)
397 {
398  if (!map_received_) {
399  map_received_in_update_bounds_ = false;
400  return;
401  }
402  map_received_in_update_bounds_ = true;
403 
404  std::lock_guard<Costmap2D::mutex_t> guard(*getMutex());
405 
406  // If there is a new available map, load it.
407  if (map_buffer_) {
408  processMap(*map_buffer_);
409  map_buffer_ = nullptr;
410  }
411 
412  if (!layered_costmap_->isRolling() ) {
413  if (!(has_updated_data_ || has_extra_bounds_)) {
414  return;
415  }
416  }
417 
418  useExtraBounds(min_x, min_y, max_x, max_y);
419 
420  if (layered_costmap_->isRolling()) {
421  // For rolling costmaps the global_frame (e.g. odom) differs from the
422  // map frame. mapToWorld() returns coordinates in the map frame, but
423  // the layered costmap interprets bounds in its global_frame. Report
424  // bounds that cover the full rolling window using the robot pose,
425  // which is already in the correct frame. updateCosts() handles the
426  // per-cell map↔odom transform itself.
427  Costmap2D * master = layered_costmap_->getCostmap();
428  double half_w = master->getSizeInMetersX() / 2.0;
429  double half_h = master->getSizeInMetersY() / 2.0;
430  *min_x = std::min(robot_x - half_w, *min_x);
431  *min_y = std::min(robot_y - half_h, *min_y);
432  *max_x = std::max(robot_x + half_w, *max_x);
433  *max_y = std::max(robot_y + half_h, *max_y);
434  } else {
435  double wx, wy;
436 
437  mapToWorld(x_, y_, wx, wy);
438  *min_x = std::min(wx, *min_x);
439  *min_y = std::min(wy, *min_y);
440 
441  mapToWorld(x_ + width_, y_ + height_, wx, wy);
442  *max_x = std::max(wx, *max_x);
443  *max_y = std::max(wy, *max_y);
444  }
445 
446  has_updated_data_ = false;
447 
448  updateFootprint(robot_x, robot_y, robot_yaw, min_x, min_y, max_x, max_y);
449 }
450 
451 void
453  double robot_x, double robot_y, double robot_yaw,
454  double * min_x, double * min_y,
455  double * max_x,
456  double * max_y)
457 {
458  if (!footprint_clearing_enabled_) {return;}
459 
460  transformFootprint(robot_x, robot_y, robot_yaw, getFootprint(), transformed_footprint_);
461 
462  for (unsigned int i = 0; i < transformed_footprint_.size(); i++) {
463  touch(transformed_footprint_[i].x, transformed_footprint_[i].y, min_x, min_y, max_x, max_y);
464  }
465 }
466 
467 void
469  nav2_costmap_2d::Costmap2D & master_grid,
470  int min_i, int min_j, int max_i, int max_j)
471 {
472  std::lock_guard<Costmap2D::mutex_t> guard(*getMutex());
473  if (!enabled_) {
474  return;
475  }
476  if (!map_received_in_update_bounds_) {
477  static int count = 0;
478  // throttle warning down to only 1/10 message rate
479  if (++count == 10) {
480  RCLCPP_WARN(logger_, "Can't update static costmap layer, no map received");
481  count = 0;
482  }
483  return;
484  }
485 
486  // global_frame_ -> map_frame_; only needed for rolling costmaps, where the frames differ
487  tf2::Transform tf2_transform = tf2::Transform::getIdentity();
488  if (layered_costmap_->isRolling()) {
489  geometry_msgs::msg::TransformStamped transform;
490  try {
491  transform = tf_->lookupTransform(
492  map_frame_, global_frame_, tf2::TimePointZero,
493  transform_tolerance_);
494  } catch (tf2::TransformException & ex) {
495  RCLCPP_ERROR(logger_, "StaticLayer: %s", ex.what());
496  has_updated_data_ = true;
497  return;
498  }
499  tf2::fromMsg(transform.transform, tf2_transform);
500  }
501 
502  std::vector<MapLocation> map_region_to_restore;
503  if (footprint_clearing_enabled_) {
504  // The footprint is in global_frame_ but is rasterized into this layer's map_frame_ grid
505  std::vector<geometry_msgs::msg::Point> footprint_in_map_frame = transformed_footprint_;
506  if (layered_costmap_->isRolling()) {
507  for (auto & point : footprint_in_map_frame) {
508  const tf2::Vector3 p = tf2_transform * tf2::Vector3(point.x, point.y, 0);
509  point.x = p.x();
510  point.y = p.y();
511  }
512  }
513  map_region_to_restore.reserve(100);
514  getMapRegionOccupiedByPolygon(footprint_in_map_frame, map_region_to_restore);
515  setMapRegionOccupiedByPolygon(map_region_to_restore, nav2_costmap_2d::FREE_SPACE);
516  }
517 
518  if (usesMasterCostmapSize()) {
519  // if not rolling, the layered costmap (master_grid) has same coordinates as this layer
520  if (!use_maximum_) {
521  updateWithTrueOverwrite(master_grid, min_i, min_j, max_i, max_j);
522  } else {
523  updateWithMax(master_grid, min_i, min_j, max_i, max_j);
524  }
525  } else {
526  // If rolling window or not resizing the master, the master_grid is unlikely to have
527  // same coordinates as this layer
528  unsigned int mx, my;
529  double wx, wy;
530 
531  for (int i = min_i; i < max_i; ++i) {
532  for (int j = min_j; j < max_j; ++j) {
533  // Convert master_grid coordinates (i,j) into global_frame_(wx,wy) coordinates
534  layered_costmap_->getCostmap()->mapToWorld(i, j, wx, wy);
535  // Transform from global_frame_ to map_frame_
536  tf2::Vector3 p(wx, wy, 0);
537  p = tf2_transform * p;
538  // Set master_grid with cell from map
539  if (worldToMap(p.x(), p.y(), mx, my)) {
540  const unsigned char cost = getCost(mx, my);
541  if (!use_maximum_) {
542  master_grid.setCost(i, j, cost);
543  } else if (cost != NO_INFORMATION) {
544  // Same rule as updateWithMax: unknown is transparent, known beats unknown
545  const unsigned char old_cost = master_grid.getCost(i, j);
546  if (old_cost == NO_INFORMATION || cost > old_cost) {
547  master_grid.setCost(i, j, cost);
548  }
549  }
550  }
551  }
552  }
553  }
554 
555  if (footprint_clearing_enabled_ && restore_cleared_footprint_) {
556  // restore the map region occupied by the polygon using cached data
557  restoreMapRegionOccupiedByPolygon(map_region_to_restore);
558  }
559  setCurrent(true);
560 }
561 
569 bool StaticLayer::isEqual(double a, double b, double epsilon)
570 {
571  return std::abs(a - b) < epsilon;
572 }
573 
574 rcl_interfaces::msg::SetParametersResult StaticLayer::validateParameterUpdatesCallback(
575  const std::vector<rclcpp::Parameter> & parameters)
576 {
577  rcl_interfaces::msg::SetParametersResult result;
578  result.successful = true;
579  for (const auto & parameter : parameters) {
580  const auto & param_type = parameter.get_type();
581  const auto & param_name = parameter.get_name();
582  if (param_name.find(name_ + ".") != 0) {
583  continue;
584  }
585 
586  if (param_name == name_ + "." + "map_subscribe_transient_local" ||
587  param_name == name_ + "." + "map_topic" ||
588  param_name == name_ + "." + "subscribe_to_updates" ||
589  param_name == name_ + "." + "resize_master")
590  {
591  RCLCPP_WARN(
592  logger_, "%s is not a dynamic parameter "
593  "cannot be changed while running. Rejecting parameter update.", param_name.c_str());
594  } else if (param_type == ParameterType::PARAMETER_BOOL && // NOLINT
595  param_name == name_ + "." + "restore_cleared_footprint")
596  {
597  if (!footprint_clearing_enabled_) {
598  RCLCPP_WARN(
599  logger_, "restore_cleared_footprint cannot be used "
600  "when footprint_clearing_enabled is False. Rejecting parameter update.");
601  result.successful = false;
602  }
603  }
604  }
605  return result;
606 }
607 
608 void
610  const std::vector<rclcpp::Parameter> & parameters)
611 {
612  std::lock_guard<Costmap2D::mutex_t> guard(*getMutex());
613 
614  for (const auto & parameter : parameters) {
615  const auto & param_type = parameter.get_type();
616  const auto & param_name = parameter.get_name();
617  if (param_name.find(name_ + ".") != 0) {
618  continue;
619  }
620 
621  if (param_type == ParameterType::PARAMETER_BOOL) {
622  if (param_name == name_ + "." + "enabled" && enabled_ != parameter.as_bool()) {
623  enabled_ = parameter.as_bool();
624 
625  x_ = y_ = 0;
626  width_ = size_x_;
627  height_ = size_y_;
628  has_updated_data_ = true;
629  setCurrent(false);
630  } else if (param_name == name_ + "." + "footprint_clearing_enabled") {
631  footprint_clearing_enabled_ = parameter.as_bool();
632  } else if (param_name == name_ + "." + "restore_cleared_footprint") {
633  restore_cleared_footprint_ = parameter.as_bool();
634  }
635  }
636  }
637 }
638 
639 } // namespace nav2_costmap_2d
A QoS profile for latched, reliable topics with a history of 10 messages.
A QoS profile for standard reliable topics with a history of 10 messages.
A 2D costmap provides a mapping between points in the world and their associated "costs".
Definition: costmap_2d.hpp:69
void mapToWorld(unsigned int mx, unsigned int my, double &wx, double &wy) const
Convert from map coordinates to world coordinates.
Definition: costmap_2d.cpp:280
void resizeMap(unsigned int size_x, unsigned int size_y, double resolution, double origin_x, double origin_y)
Resize the costmap.
Definition: costmap_2d.cpp:111
unsigned char getCost(unsigned int mx, unsigned int my) const
Get the cost of a cell in the costmap.
Definition: costmap_2d.cpp:265
bool worldToMap(double wx, double wy, unsigned int &mx, unsigned int &my) const
Convert from world coordinates to map coordinates.
Definition: costmap_2d.cpp:292
double getResolution() const
Accessor for the resolution of the costmap.
Definition: costmap_2d.cpp:578
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
void setMapRegionOccupiedByPolygon(const std::vector< MapLocation > &polygon_map_region, unsigned char new_cost_value)
Sets the given map region to desired value.
Definition: costmap_2d.cpp:421
void restoreMapRegionOccupiedByPolygon(const std::vector< MapLocation > &polygon_map_region)
Restores the corresponding map region using given map region.
Definition: costmap_2d.cpp:430
bool getMapRegionOccupiedByPolygon(const std::vector< geometry_msgs::msg::Point > &polygon, std::vector< MapLocation > &polygon_map_region)
Gets the map region occupied by polygon.
Definition: costmap_2d.cpp:438
unsigned int getSizeInCellsX() const
Accessor for the x size of the costmap in cells.
Definition: costmap_2d.cpp:548
double getOriginY() const
Accessor for the y origin of the costmap.
Definition: costmap_2d.cpp:573
unsigned int getSizeInCellsY() const
Accessor for the y size of the costmap in cells.
Definition: costmap_2d.cpp:553
double getOriginX() const
Accessor for the x origin of the costmap.
Definition: costmap_2d.cpp:568
void setCost(unsigned int mx, unsigned int my, unsigned char cost)
Set the cost of a cell in the costmap.
Definition: costmap_2d.cpp:275
void addExtraBounds(double mx0, double my0, double mx1, double my1)
void touch(double x, double y, double *min_x, double *min_y, double *max_x, double *max_y)
Abstract class for layered costmap plugin implementations.
Definition: layer.hpp:60
std::string joinWithParentNamespace(const std::string &topic)
Definition: layer.cpp:83
void setCurrent(bool current)
Set whether the data in the layer is up to date.
Definition: layer.hpp:147
const std::vector< geometry_msgs::msg::Point > & getFootprint() const
Convenience function for layered_costmap_->getFootprint().
Definition: layer.cpp:70
bool isRolling()
If this costmap is rolling or not.
Costmap2D * getCostmap()
Get the costmap pointer to the master costmap.
void resizeMap(unsigned int size_x, unsigned int size_y, double resolution, double origin_x, double origin_y, bool size_locked=false)
Resize the map to a new size, resolution, or origin.
bool isSizeLocked()
Get if the size of the costmap is locked.
Takes in a map generated from SLAM to add costs to costmap.
void getParameters()
Get parameters of layer.
bool usesMasterCostmapSize() const
Whether this layer's grid is the master's grid (non-rolling, resize_master true). Otherwise the map k...
virtual ~StaticLayer()
Static Layer destructor.
virtual void deactivate()
Deactivate this layer.
bool has_updated_data_
frame that map is located in
void updateParametersCallback(const std::vector< rclcpp::Parameter > &parameters)
Apply parameter updates after validation This callback is executed when parameters have been successf...
unsigned char interpretValue(unsigned char value)
Interpret the value in the static map given on the topic to convert into costs for the costmap to uti...
StaticLayer()
Static Layer constructor.
virtual void matchSize()
Match the size of the master costmap.
virtual void onInitialize()
Initialization process of layer on startup.
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 activate()
Activate this layer.
void incomingUpdate(map_msgs::msg::OccupancyGridUpdate::ConstSharedPtr update)
Callback to update the costmap's map from the map_server (or SLAM) with an update in a particular are...
bool isEqual(double a, double b, double epsilon)
Check if two double values are equal within a given epsilon.
std::string global_frame_
The global frame for the costmap.
void processMap(const nav_msgs::msg::OccupancyGrid &new_map)
Process a new map coming from a topic.
virtual void updateCosts(nav2_costmap_2d::Costmap2D &master_grid, int min_i, int min_j, int max_i, int max_j)
Update the costs in the master costmap in the window.
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 incomingMap(const nav_msgs::msg::OccupancyGrid::ConstSharedPtr &new_map)
Callback to update the costmap's map from the map_server.
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.
virtual void reset()
Reset this costmap.
void transformFootprint(double x, double y, double theta, const std::vector< geometry_msgs::msg::Point > &footprint_spec, std::vector< geometry_msgs::msg::Point > &oriented_footprint)
Given a pose and base footprint, build the oriented footprint of the robot (list of Points)
Definition: footprint.cpp:112