Nav2 Navigation Stack - lyrical  lyrical
ROS 2 Navigation Stack
vector_object_server.cpp
1 // Copyright (c) 2023 Samsung R&D Institute Russia
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "nav2_map_server/vector_object_server.hpp"
16 
17 #include <chrono>
18 #include <exception>
19 #include <functional>
20 #include <limits>
21 #include <stdexcept>
22 #include <utility>
23 
24 #include "rclcpp/create_timer.hpp"
25 
26 #include "nav2_util/occ_grid_utils.hpp"
27 #include "nav2_util/occ_grid_values.hpp"
28 
29 using namespace std::placeholders;
30 
31 namespace nav2_map_server
32 {
33 
34 VectorObjectServer::VectorObjectServer(const rclcpp::NodeOptions & options)
35 : nav2::LifecycleNode("vector_object_server", "", options), process_map_(false)
36 {}
37 
38 nav2::CallbackReturn
39 VectorObjectServer::on_configure(const rclcpp_lifecycle::State & /*state*/)
40 {
41  RCLCPP_INFO(get_logger(), "Configuring");
42  // Obtaining ROS parameters
43  if (!obtainParams()) {
44  return nav2::CallbackReturn::FAILURE;
45  }
46 
48  // Transform buffer and listener initialization
49  tf_buffer_ = nav2::create_transform_buffer(this);
50  tf_listener_ = nav2::create_transform_listener(*tf_buffer_, this);
51  } else {
52  RCLCPP_INFO(
53  get_logger(),
54  "Parameter enforce_global_frame_id is true. TF listener is disabled. "
55  "All incoming shapes must have frame_id empty or equal to global_frame_id '%s'.",
56  global_frame_id_.c_str());
57  }
58 
59  map_pub_ = create_publisher<nav_msgs::msg::OccupancyGrid>(
60  map_topic_,
62 
63  add_shapes_service_ = create_service<nav2_msgs::srv::AddShapes>(
64  "~/add_shapes",
65  std::bind(&VectorObjectServer::addShapesCallback, this, _1, _2, _3));
66 
67  get_shapes_service_ = create_service<nav2_msgs::srv::GetShapes>(
68  "~/get_shapes",
69  std::bind(&VectorObjectServer::getShapesCallback, this, _1, _2, _3));
70 
71  remove_shapes_service_ = create_service<nav2_msgs::srv::RemoveShapes>(
72  "~/remove_shapes",
73  std::bind(&VectorObjectServer::removeShapesCallback, this, _1, _2, _3));
74 
75  return nav2::CallbackReturn::SUCCESS;
76 }
77 
78 nav2::CallbackReturn
79 VectorObjectServer::on_activate(const rclcpp_lifecycle::State & /*state*/)
80 {
81  RCLCPP_INFO(get_logger(), "Activating");
82 
83  map_pub_->on_activate();
84 
85  // Trigger map to be published
86  process_map_ = true;
88 
89  // Creating bond connection
90  createBond();
91 
92  return nav2::CallbackReturn::SUCCESS;
93 }
94 
95 nav2::CallbackReturn
96 VectorObjectServer::on_deactivate(const rclcpp_lifecycle::State & /*state*/)
97 {
98  RCLCPP_INFO(get_logger(), "Deactivating");
99 
100  if (map_timer_) {
101  map_timer_->cancel();
102  map_timer_.reset();
103  }
104  process_map_ = false;
105 
106  map_pub_->on_deactivate();
107 
108  // Destroying bond connection
109  destroyBond();
110 
111  return nav2::CallbackReturn::SUCCESS;
112 }
113 
114 nav2::CallbackReturn
115 VectorObjectServer::on_cleanup(const rclcpp_lifecycle::State & /*state*/)
116 {
117  RCLCPP_INFO(get_logger(), "Cleaning up");
118 
119  add_shapes_service_.reset();
120  get_shapes_service_.reset();
121  remove_shapes_service_.reset();
122 
123  map_pub_.reset();
124  map_.reset();
125 
126  shapes_.clear();
127 
128  tf_listener_.reset();
129  tf_buffer_.reset();
130 
131  return nav2::CallbackReturn::SUCCESS;
132 }
133 
134 nav2::CallbackReturn
135 VectorObjectServer::on_shutdown(const rclcpp_lifecycle::State & /*state*/)
136 {
137  RCLCPP_INFO(get_logger(), "Shutting down");
138  return nav2::CallbackReturn::SUCCESS;
139 }
140 
142 {
143  auto node = shared_from_this();
144 
145  // Main ROS-parameters
146  map_topic_ = nav2::declare_or_get_parameter(node, "map_topic", std::string{"vo_map"});
147  global_frame_id_ = nav2::declare_or_get_parameter(node, "global_frame_id", std::string{"map"});
148  enforce_global_frame_id_ = nav2::declare_or_get_parameter(node, "enforce_global_frame_id", false);
149  resolution_ = nav2::declare_or_get_parameter(node, "resolution", 0.05);
150  default_value_ = nav2::declare_or_get_parameter(
151  node, "default_value",
152  static_cast<int>(nav2_util::OCC_GRID_UNKNOWN));
153  overlay_type_ = static_cast<OverlayType>(nav2::declare_or_get_parameter(
154  node, "overlay_type",
155  static_cast<int>(OverlayType::OVERLAY_SEQ)));
156  update_frequency_ = nav2::declare_or_get_parameter(node, "update_frequency", 1.0);
157  transform_tolerance_ = nav2::declare_or_get_parameter(node, "transform_tolerance", 0.1);
158 
159  // Shapes
160  auto shape_names = nav2::declare_or_get_parameter(node, "shapes", std::vector<std::string>());
161  for (std::string shape_name : shape_names) {
162  std::string shape_type;
163  try {
164  shape_type = nav2::declare_or_get_parameter<std::string>(node, shape_name + ".type");
165  } catch (const std::exception & ex) {
166  RCLCPP_ERROR(
167  get_logger(), "Error while getting shape %s type: %s", shape_name.c_str(), ex.what());
168  return false;
169  }
170 
171  if (shape_type == "polygon") {
172  auto polygon = std::make_shared<Polygon>(node);
173  if (!polygon->obtainParams(shape_name)) {
174  return false;
175  }
176  shapes_.push_back(polygon);
177  } else if (shape_type == "circle") {
178  auto circle = std::make_shared<Circle>(node);
179  if (!circle->obtainParams(shape_name)) {
180  return false;
181  }
182  shapes_.push_back(circle);
183  } else {
184  RCLCPP_ERROR(
185  get_logger(),
186  "Please specify the correct type for shape %s. Supported types are 'polygon' and 'circle'",
187  shape_name.c_str());
188  return false;
189  }
190  }
191 
192  // if any shapes has non-global frame id, no shapes will be added and return false.
194  for (const auto & shape : shapes_) {
195  const std::string & frame_id = shape->getFrameID();
196  if (!frame_id.empty() && frame_id != global_frame_id_) {
197  RCLCPP_ERROR(
198  get_logger(),
199  "Shape '%s' has frame_id '%s' which differs from global_frame_id '%s'. "
200  "All shapes must have frame_id empty or equal to global_frame_id "
201  "when enforce_global_frame_id is true.",
202  shape->getUUID().c_str(), frame_id.c_str(), global_frame_id_.c_str());
203  shapes_.clear();
204  return false;
205  }
206  }
207  }
208 
209  return true;
210 }
211 
212 std::vector<std::shared_ptr<Shape>>::iterator
213 VectorObjectServer::findShape(const unsigned char * uuid)
214 {
215  for (auto it = shapes_.begin(); it != shapes_.end(); it++) {
216  if ((*it)->isUUID(uuid)) {
217  return it;
218  }
219  }
220  return shapes_.end();
221 }
222 
224 {
225  for (auto shape : shapes_) {
226  if (shape->getFrameID() != global_frame_id_ && !shape->getFrameID().empty()) {
227  // Shape to be updated dynamically
228  if (!shape->toFrame(global_frame_id_, tf_buffer_, transform_tolerance_)) {
229  RCLCPP_ERROR(
230  get_logger(), "Can not transform vector object from %s to %s frame",
231  shape->getFrameID().c_str(), global_frame_id_.c_str());
232  return false;
233  }
234  }
235  }
236 
237  return true;
238 }
239 
241  double & min_x, double & min_y, double & max_x, double & max_y) const
242 {
243  min_x = std::numeric_limits<double>::max();
244  min_y = std::numeric_limits<double>::max();
245  max_x = std::numeric_limits<double>::lowest();
246  max_y = std::numeric_limits<double>::lowest();
247 
248  double min_p_x, min_p_y, max_p_x, max_p_y;
249  for (auto shape : shapes_) {
250  shape->getBoundaries(min_p_x, min_p_y, max_p_x, max_p_y);
251  min_x = std::min(min_x, min_p_x);
252  min_y = std::min(min_y, min_p_y);
253  max_x = std::max(max_x, max_p_x);
254  max_y = std::max(max_y, max_p_y);
255  }
256 
257  if (
258  min_x == std::numeric_limits<double>::max() ||
259  min_y == std::numeric_limits<double>::max() ||
260  max_x == std::numeric_limits<double>::lowest() ||
261  max_y == std::numeric_limits<double>::lowest())
262  {
263  throw std::runtime_error("Can not obtain map boundaries");
264  }
265 }
266 
268  const double & min_x, const double & min_y, const double & max_x, const double & max_y)
269 {
270  // Calculate size of update map
271  int size_x = static_cast<int>((max_x - min_x) / resolution_) + 1;
272  int size_y = static_cast<int>((max_y - min_y) / resolution_) + 1;
273 
274  if (size_x < 0) {
275  throw std::runtime_error("Incorrect map x-size");
276  }
277 
278  if (size_y < 0) {
279  throw std::runtime_error("Incorrect map y-size");
280  }
281 
282  if (!map_) {
283  map_ = std::make_shared<nav_msgs::msg::OccupancyGrid>();
284  }
285 
286  if (
287  map_->info.width != static_cast<unsigned int>(size_x) ||
288  map_->info.height != static_cast<unsigned int>(size_y))
289  {
290  // Map size was changed
291  map_->data = std::vector<int8_t>(size_x * size_y, default_value_);
292  map_->info.width = size_x;
293  map_->info.height = size_y;
294  } else if (size_x > 0 && size_y > 0) {
295  // Map size was not changed
296  memset(map_->data.data(), default_value_, size_x * size_y * sizeof(int8_t));
297  }
298 
299  map_->header.frame_id = global_frame_id_;
300  map_->info.resolution = resolution_;
301  map_->info.origin.position.x = min_x;
302  map_->info.origin.position.y = min_y;
303 }
304 
306 {
307  // Filling the shapes
308  for (auto shape : shapes_) {
309  if (shape->isFill()) {
310  // Put filled shape on map
311  double wx1 = std::numeric_limits<double>::max();
312  double wy1 = std::numeric_limits<double>::max();
313  double wx2 = std::numeric_limits<double>::lowest();
314  double wy2 = std::numeric_limits<double>::lowest();
315  unsigned int mx1 = 0;
316  unsigned int my1 = 0;
317  unsigned int mx2 = 0;
318  unsigned int my2 = 0;
319 
320  shape->getBoundaries(wx1, wy1, wx2, wy2);
321  if (
322  !nav2_util::worldToMap(map_, wx1, wy1, mx1, my1) ||
323  !nav2_util::worldToMap(map_, wx2, wy2, mx2, my2))
324  {
325  RCLCPP_ERROR(
326  get_logger(),
327  "Error to get shape boundaries on map (UUID: %s)", shape->getUUID().c_str());
328  return;
329  }
330 
331  unsigned int it;
332  for (unsigned int my = my1; my <= my2; my++) {
333  for (unsigned int mx = mx1; mx <= mx2; mx++) {
334  it = my * map_->info.width + mx;
335  double wx, wy;
336  nav2_util::mapToWorld(map_, mx, my, wx, wy);
337  if (shape->isPointInside(wx, wy)) {
338  processVal(map_->data[it], shape->getValue(), overlay_type_);
339  }
340  }
341  }
342  } else {
343  // Put shape borders on map
344  shape->putBorders(map_, overlay_type_);
345  }
346  }
347 }
348 
350 {
351  if (map_) {
352  auto map = std::make_unique<nav_msgs::msg::OccupancyGrid>(*map_);
353  map_pub_->publish(std::move(map));
354  }
355 }
356 
358 {
359  if (!process_map_) {
360  return;
361  }
362 
363  try {
364  if (shapes_.size() > 0) {
365  if (!transformVectorObjects()) {
366  return;
367  }
368  double min_x, min_y, max_x, max_y;
369 
370  getMapBoundaries(min_x, min_y, max_x, max_y);
371  updateMap(min_x, min_y, max_x, max_y);
373  } else {
374  updateMap(0.0, 0.0, 0.0, 0.0);
375  }
376  } catch (const std::exception & ex) {
377  RCLCPP_ERROR(get_logger(), "Can not update map: %s", ex.what());
378  return;
379  }
380 
381  publishMap();
382 }
383 
385 {
386  for (auto shape : shapes_) {
387  if (shape->getFrameID() != global_frame_id_ && !shape->getFrameID().empty()) {
388  if (!map_timer_) {
389  map_timer_ = this->create_timer(
390  std::chrono::duration<double>(1.0 / update_frequency_),
391  std::bind(&VectorObjectServer::processMap, this));
392  }
393  RCLCPP_INFO(get_logger(), "Publishing map dynamically at %f Hz rate", update_frequency_);
394  return;
395  }
396  }
397 
398  if (map_timer_) {
399  map_timer_->cancel();
400  map_timer_.reset();
401  }
402  RCLCPP_INFO(get_logger(), "Publishing map once");
403  processMap();
404 }
405 
407  const std::shared_ptr<rmw_request_id_t>/*request_header*/,
408  const std::shared_ptr<nav2_msgs::srv::AddShapes::Request> request,
409  std::shared_ptr<nav2_msgs::srv::AddShapes::Response> response)
410 {
411  // Initialize result with true. If one of the required vector object was not added properly,
412  // set it to false.
413  response->success = true;
414 
416  // Lambda for checking frame_id consistency
417  auto check_frame_id = [this](
418  const auto & shapes, const std::string & shape_type_name)
419  {
420  for (const auto & shape : shapes) {
421  if (!shape.header.frame_id.empty() && shape.header.frame_id != global_frame_id_) {
422  RCLCPP_ERROR(
423  get_logger(),
424  "%s frame_id '%s' must be empty or equal to global_frame_id '%s' "
425  "when enforce_global_frame_id is true. Rejecting request.",
426  shape_type_name.c_str(), shape.header.frame_id.c_str(), global_frame_id_.c_str());
427  return false;
428  }
429  }
430  return true;
431  };
432 
433  if (!check_frame_id(request->polygons, "Polygon") ||
434  !check_frame_id(request->circles, "Circle"))
435  {
436  response->success = false;
437  return;
438  }
439  }
440 
441  auto node = shared_from_this();
442 
443  // Process polygons
444  for (auto req_poly : request->polygons) {
445  nav2_msgs::msg::PolygonObject::SharedPtr new_params =
446  std::make_shared<nav2_msgs::msg::PolygonObject>(req_poly);
447 
448  auto it = findShape(new_params->uuid.uuid.data());
449  if (it != shapes_.end()) {
450  // Vector Object with given UUID was found: updating it
451  // Check that found shape has correct type
452  if ((*it)->getType() != POLYGON) {
453  RCLCPP_ERROR(
454  get_logger(),
455  "Shape (UUID: %s) is not a polygon type for a polygon update. Not adding shape.",
456  (*it)->getUUID().c_str());
457  response->success = false;
458  // Do not add this shape
459  continue;
460  }
461 
462  std::shared_ptr<Polygon> polygon = std::static_pointer_cast<Polygon>(*it);
463 
464  // Preserving old parameters for the case, if new ones to be incorrect
465  nav2_msgs::msg::PolygonObject::SharedPtr old_params = polygon->getParams();
466  if (!polygon->setParams(new_params)) {
467  RCLCPP_ERROR(
468  get_logger(),
469  "Failed to update existing polygon object (UUID: %s) with new params. "
470  "Reverting to old polygon params.",
471  (*it)->getUUID().c_str());
472  // Restore old parameters
473  polygon->setParams(old_params);
474  // ... and set the failure to return
475  response->success = false;
476  }
477  } else {
478  // Vector Object with given UUID was not found: creating a new one
479  std::shared_ptr<Polygon> polygon = std::make_shared<Polygon>(node);
480  if (polygon->setParams(new_params)) {
481  shapes_.push_back(polygon);
482  } else {
483  RCLCPP_ERROR(
484  get_logger(), "Failed to create a new polygon object using the provided params.");
485  response->success = false;
486  }
487  }
488  }
489 
490  // Process circles
491  for (auto req_crcl : request->circles) {
492  nav2_msgs::msg::CircleObject::SharedPtr new_params =
493  std::make_shared<nav2_msgs::msg::CircleObject>(req_crcl);
494 
495  auto it = findShape(new_params->uuid.uuid.data());
496  if (it != shapes_.end()) {
497  // Vector object with given UUID was found: updating it
498  // Check that found shape has correct type
499  if ((*it)->getType() != CIRCLE) {
500  RCLCPP_ERROR(
501  get_logger(),
502  "Shape (UUID: %s) is not a circle type for a circle update. Not adding shape.",
503  (*it)->getUUID().c_str());
504  response->success = false;
505  // Do not add this shape
506  continue;
507  }
508 
509  std::shared_ptr<Circle> circle = std::static_pointer_cast<Circle>(*it);
510 
511  // Preserving old parameters for the case, if new ones to be incorrect
512  nav2_msgs::msg::CircleObject::SharedPtr old_params = circle->getParams();
513  if (!circle->setParams(new_params)) {
514  RCLCPP_ERROR(
515  get_logger(),
516  "Failed to update existing circle object (UUID: %s) with new params. "
517  "Reverting to old circle params.",
518  (*it)->getUUID().c_str());
519  // Restore old parameters
520  circle->setParams(old_params);
521  // ... and set the failure to return
522  response->success = false;
523  }
524  } else {
525  // Vector Object with given UUID was not found: creating a new one
526  std::shared_ptr<Circle> circle = std::make_shared<Circle>(node);
527  if (circle->setParams(new_params)) {
528  shapes_.push_back(circle);
529  } else {
530  RCLCPP_ERROR(
531  get_logger(), "Failed to create a new circle object using the provided params.");
532  response->success = false;
533  }
534  }
535  }
536 
537  switchMapUpdate();
538 }
539 
541  const std::shared_ptr<rmw_request_id_t>/*request_header*/,
542  const std::shared_ptr<nav2_msgs::srv::GetShapes::Request>/*request*/,
543  std::shared_ptr<nav2_msgs::srv::GetShapes::Response> response)
544 {
545  std::shared_ptr<Polygon> polygon;
546  std::shared_ptr<Circle> circle;
547 
548  for (auto shape : shapes_) {
549  switch (shape->getType()) {
550  case POLYGON:
551  polygon = std::static_pointer_cast<Polygon>(shape);
552  response->polygons.push_back(*(polygon->getParams()));
553  break;
554  case CIRCLE:
555  circle = std::static_pointer_cast<Circle>(shape);
556  response->circles.push_back(*(circle->getParams()));
557  break;
558  default:
559  RCLCPP_WARN(get_logger(), "Unknown shape type (UUID: %s)", shape->getUUID().c_str());
560  }
561  }
562 }
563 
565  const std::shared_ptr<rmw_request_id_t>/*request_header*/,
566  const std::shared_ptr<nav2_msgs::srv::RemoveShapes::Request> request,
567  std::shared_ptr<nav2_msgs::srv::RemoveShapes::Response> response)
568 {
569  // Initialize result with true. If one of the required vector object was not found,
570  // set it to false.
571  response->success = true;
572 
573  if (request->all_objects) {
574  // Clear all objects
575  shapes_.clear();
576  } else {
577  // Find objects to remove
578  for (auto req_uuid : request->uuids) {
579  auto it = findShape(req_uuid.uuid.data());
580  if (it != shapes_.end()) {
581  // Shape with given UUID was found: remove it
582  (*it).reset();
583  shapes_.erase(it);
584  } else {
585  // Required vector object was not found
586  RCLCPP_ERROR(
587  get_logger(),
588  "Can not find shape to remove with UUID: %s",
589  unparseUUID(req_uuid.uuid.data()).c_str());
590  response->success = false;
591  }
592  }
593  }
594 
595  switchMapUpdate();
596 }
597 
598 } // namespace nav2_map_server
599 
600 #include "rclcpp_components/register_node_macro.hpp"
601 
602 // Register the component with class_loader.
603 // This acts as a sort of entry point, allowing the component to be discoverable when its library
604 // is being loaded into a running process.
605 RCLCPP_COMPONENTS_REGISTER_NODE(nav2_map_server::VectorObjectServer)
void destroyBond()
Destroy bond connection to lifecycle manager.
nav2::LifecycleNode::SharedPtr shared_from_this()
Get a shared pointer of this.
rclcpp::GenericTimer< CallbackT >::SharedPtr create_timer(std::chrono::duration< DurationRepT, DurationT > period, CallbackT callback, rclcpp::CallbackGroup::SharedPtr group=nullptr)
Create a sim-time-aware timer for Nav2 lifecycle nodes.
void createBond()
Create bond connection to lifecycle manager.
A QoS profile for latched, reliable topics with a history of 1 messages.
void addShapesCallback(const std::shared_ptr< rmw_request_id_t > request_header, const std::shared_ptr< nav2_msgs::srv::AddShapes::Request > request, std::shared_ptr< nav2_msgs::srv::AddShapes::Response > response)
Callback for AddShapes service call. Reads all input vector objects from service request,...
void switchMapUpdate()
If map to be update dynamically, creates map processing timer, otherwise process map once.
void publishMap()
Publishes output map.
nav2::CallbackReturn on_cleanup(const rclcpp_lifecycle::State &state) override
: Resets all services, publishers, map and TF-s
double process_map_
Whether to process and publish map.
nav2::ServiceServer< nav2_msgs::srv::GetShapes >::SharedPtr get_shapes_service_
GetShapes service.
bool transformVectorObjects()
Transform all vector shapes from their local frame to output map frame.
void processMap()
Calculates new map sizes, updates map, processes all vector objects on it and publishes output map on...
std::vector< std::shared_ptr< Shape > > shapes_
All shapes vector.
double update_frequency_
Frequency to dynamically update/publish the map (if necessary)
int8_t default_value_
Default value the output map to be filled with.
void removeShapesCallback(const std::shared_ptr< rmw_request_id_t > request_header, const std::shared_ptr< nav2_msgs::srv::RemoveShapes::Request > request, std::shared_ptr< nav2_msgs::srv::RemoveShapes::Response > response)
Callback for RemoveShapes service call. Try to remove requested vector objects and switches map proce...
std::vector< std::shared_ptr< Shape > >::iterator findShape(const unsigned char *uuid)
Finds the shape with given UUID.
double resolution_
Output map resolution.
nav2::CallbackReturn on_activate(const rclcpp_lifecycle::State &state) override
: Activates output map publisher and creates bond connection
bool enforce_global_frame_id_
If true, disables TF listener and requires all incoming shapes to have frame_id empty or equal to glo...
nav2::Publisher< nav_msgs::msg::OccupancyGrid >::SharedPtr map_pub_
Output map publisher.
nav_msgs::msg::OccupancyGrid::SharedPtr map_
Output map with vector objects on it.
void putVectorObjectsOnMap()
Processes all vector objects on raster output map.
double transform_tolerance_
Transform tolerance.
std::string global_frame_id_
Frame of output map.
std::string map_topic_
@beirf Topic name where the output map to be published to
nav2::CallbackReturn on_shutdown(const rclcpp_lifecycle::State &state) override
Called in shutdown state.
rclcpp::TimerBase::SharedPtr map_timer_
Map update timer.
void getMapBoundaries(double &min_x, double &min_y, double &max_x, double &max_y) const
Obtains map boundaries to place all vector objects inside.
void getShapesCallback(const std::shared_ptr< rmw_request_id_t > request_header, const std::shared_ptr< nav2_msgs::srv::GetShapes::Request > request, std::shared_ptr< nav2_msgs::srv::GetShapes::Response > response)
Callback for GetShapes service call. Gets all shapes and returns them to the service response.
nav2::CallbackReturn on_deactivate(const rclcpp_lifecycle::State &state) override
: Deactivates map publisher and timer (if any), destroys bond connection
nav2::ServiceServer< nav2_msgs::srv::AddShapes >::SharedPtr add_shapes_service_
AddShapes service.
nav2::TransformListener::SharedPtr tf_listener_
TF listener.
nav2::TransformBuffer::SharedPtr tf_buffer_
TF buffer.
void updateMap(const double &min_x, const double &min_y, const double &max_x, const double &max_y)
Creates or updates existing map with required sizes and fills it with default value.
nav2::CallbackReturn on_configure(const rclcpp_lifecycle::State &state) override
: Initializes TF buffer/listener, obtains ROS-parameters, creates incoming services,...
OverlayType overlay_type_
@Overlay Type of overlay of vector objects on the map
bool obtainParams()
Supporting routine obtaining all ROS-parameters.
nav2::ServiceServer< nav2_msgs::srv::RemoveShapes >::SharedPtr remove_shapes_service_
RemoveShapes service.