Nav2 Navigation Stack - rolling  main
ROS 2 Navigation Stack
costmap_subscriber.cpp
1 // Copyright (c) 2019 Intel Corporation
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 <string>
16 #include <memory>
17 #include <mutex>
18 
19 #include "nav2_costmap_2d/costmap_subscriber.hpp"
20 #include "nav2_ros_common/validate_messages.hpp"
21 
22 namespace nav2_costmap_2d
23 {
24 
25 std::shared_ptr<Costmap2D> CostmapSubscriber::getCostmap()
26 {
27  if (!isCostmapReceived()) {
28  throw std::runtime_error("Costmap is not available");
29  }
30  processCurrentCostmapMsg();
31  return costmap_;
32 }
33 
34 void CostmapSubscriber::costmapCallback(const nav2_msgs::msg::Costmap::ConstSharedPtr & msg)
35 {
36  if (!nav2::validateMsg(*msg)) {
37  RCLCPP_ERROR(logger_, "Received costmap message is malformed. Rejecting.");
38  return;
39  }
40 
41  std::lock_guard<std::recursive_mutex> lock(costmap_msg_mutex_);
42  costmap_msg_ = msg;
43  frame_id_ = costmap_msg_->header.frame_id;
44 
45  if (!isCostmapReceived()) {
46  costmap_ = std::make_shared<Costmap2D>(
47  msg->metadata.size_x, msg->metadata.size_y,
48  msg->metadata.resolution, msg->metadata.origin.position.x,
49  msg->metadata.origin.position.y);
50 
51  processCurrentCostmapMsg();
52  }
53 }
54 
56  const nav2_msgs::msg::CostmapUpdate::ConstSharedPtr & update_msg)
57 {
58  if (isCostmapReceived()) {
59  processCurrentCostmapMsg();
60 
61  std::lock_guard<Costmap2D::mutex_t> lock(*(costmap_->getMutex()));
62 
63  auto map_cell_size_x = costmap_->getSizeInCellsX();
64  auto map_call_size_y = costmap_->getSizeInCellsY();
65 
66  if (map_cell_size_x < update_msg->x + update_msg->size_x ||
67  map_call_size_y < update_msg->y + update_msg->size_y)
68  {
69  RCLCPP_WARN(
70  logger_, "Update area outside of original map area. Costmap bounds: %d X %d, "
71  "Update origin: %d, %d bounds: %d X %d", map_cell_size_x, map_call_size_y,
72  update_msg->x, update_msg->y, update_msg->size_x, update_msg->size_y);
73  return;
74  }
75  unsigned char * master_array = costmap_->getCharMap();
76  // copy update msg row-wise
77  for (size_t y = 0; y < update_msg->size_y; ++y) {
78  auto starting_index_of_row_update_in_costmap = (y + update_msg->y) * map_cell_size_x +
79  update_msg->x;
80 
81  std::copy_n(
82  update_msg->data.begin() + (y * update_msg->size_x),
83  update_msg->size_x, &master_array[starting_index_of_row_update_in_costmap]);
84  }
85  } else {
86  RCLCPP_WARN(logger_, "No costmap received.");
87  }
88 }
89 
90 void CostmapSubscriber::processCurrentCostmapMsg()
91 {
92  std::scoped_lock lock(*(costmap_->getMutex()), costmap_msg_mutex_);
93  if (!costmap_msg_) {
94  return;
95  }
96  if (haveCostmapParametersChanged()) {
97  costmap_->resizeMap(
98  costmap_msg_->metadata.size_x, costmap_msg_->metadata.size_y,
99  costmap_msg_->metadata.resolution,
100  costmap_msg_->metadata.origin.position.x,
101  costmap_msg_->metadata.origin.position.y);
102  }
103 
104  unsigned char * master_array = costmap_->getCharMap();
105  std::copy(costmap_msg_->data.begin(), costmap_msg_->data.end(), master_array);
106  costmap_msg_.reset();
107 }
108 
109 bool CostmapSubscriber::haveCostmapParametersChanged()
110 {
111  return hasCostmapSizeChanged() ||
112  hasCostmapResolutionChanged() ||
113  hasCostmapOriginPositionChanged();
114 }
115 
116 bool CostmapSubscriber::hasCostmapSizeChanged()
117 {
118  return costmap_->getSizeInCellsX() != costmap_msg_->metadata.size_x ||
119  costmap_->getSizeInCellsY() != costmap_msg_->metadata.size_y;
120 }
121 
122 bool CostmapSubscriber::hasCostmapResolutionChanged()
123 {
124  return costmap_->getResolution() != costmap_msg_->metadata.resolution;
125 }
126 
127 bool CostmapSubscriber::hasCostmapOriginPositionChanged()
128 {
129  return costmap_->getOriginX() != costmap_msg_->metadata.origin.position.x ||
130  costmap_->getOriginY() != costmap_msg_->metadata.origin.position.y;
131 }
132 
133 } // namespace nav2_costmap_2d
std::shared_ptr< Costmap2D > getCostmap()
Get current costmap.
void costmapCallback(const nav2_msgs::msg::Costmap::ConstSharedPtr &msg)
Callback for the costmap topic.
void costmapUpdateCallback(const nav2_msgs::msg::CostmapUpdate::ConstSharedPtr &update_msg)
Callback for the costmap's update topic.