Nav2 Navigation Stack - kilted  kilted
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 
21 namespace nav2_costmap_2d
22 {
23 
24 constexpr int costmapUpdateQueueDepth = 10;
25 
27  const nav2_util::LifecycleNode::WeakPtr & parent,
28  const std::string & topic_name)
29 : topic_name_(topic_name)
30 {
31  auto node = parent.lock();
32  logger_ = node->get_logger();
33  costmap_sub_ = node->create_subscription<nav2_msgs::msg::Costmap>(
34  topic_name_,
35  rclcpp::QoS(rclcpp::KeepLast(1)).transient_local().reliable(),
36  std::bind(&CostmapSubscriber::costmapCallback, this, std::placeholders::_1));
37  costmap_update_sub_ = node->create_subscription<nav2_msgs::msg::CostmapUpdate>(
38  topic_name_ + "_updates",
39  rclcpp::QoS(rclcpp::KeepLast(costmapUpdateQueueDepth)).transient_local().reliable(),
40  std::bind(&CostmapSubscriber::costmapUpdateCallback, this, std::placeholders::_1));
41 }
42 
44  const rclcpp::Node::WeakPtr & parent,
45  const std::string & topic_name)
46 : topic_name_(topic_name)
47 {
48  auto node = parent.lock();
49  logger_ = node->get_logger();
50  costmap_sub_ = node->create_subscription<nav2_msgs::msg::Costmap>(
51  topic_name_,
52  rclcpp::QoS(rclcpp::KeepLast(1)).transient_local().reliable(),
53  std::bind(&CostmapSubscriber::costmapCallback, this, std::placeholders::_1));
54  costmap_update_sub_ = node->create_subscription<nav2_msgs::msg::CostmapUpdate>(
55  topic_name_ + "_updates",
56  rclcpp::QoS(rclcpp::KeepLast(costmapUpdateQueueDepth)).transient_local().reliable(),
57  std::bind(&CostmapSubscriber::costmapUpdateCallback, this, std::placeholders::_1));
58 }
59 
60 std::shared_ptr<Costmap2D> CostmapSubscriber::getCostmap()
61 {
62  if (!isCostmapReceived()) {
63  throw std::runtime_error("Costmap is not available");
64  }
65  if (costmap_msg_) {
66  processCurrentCostmapMsg();
67  }
68  return costmap_;
69 }
70 
71 void CostmapSubscriber::costmapCallback(const nav2_msgs::msg::Costmap::SharedPtr msg)
72 {
73  {
74  std::lock_guard<std::mutex> lock(costmap_msg_mutex_);
75  costmap_msg_ = msg;
76  frame_id_ = costmap_msg_->header.frame_id;
77  }
78  if (!isCostmapReceived()) {
79  costmap_ = std::make_shared<Costmap2D>(
80  msg->metadata.size_x, msg->metadata.size_y,
81  msg->metadata.resolution, msg->metadata.origin.position.x,
82  msg->metadata.origin.position.y);
83 
84  processCurrentCostmapMsg();
85  }
86 }
87 
89  const nav2_msgs::msg::CostmapUpdate::SharedPtr update_msg)
90 {
91  if (isCostmapReceived()) {
92  if (costmap_msg_) {
93  processCurrentCostmapMsg();
94  }
95 
96  std::lock_guard<Costmap2D::mutex_t> lock(*(costmap_->getMutex()));
97 
98  auto map_cell_size_x = costmap_->getSizeInCellsX();
99  auto map_call_size_y = costmap_->getSizeInCellsY();
100 
101  if (map_cell_size_x < update_msg->x + update_msg->size_x ||
102  map_call_size_y < update_msg->y + update_msg->size_y)
103  {
104  RCLCPP_WARN(
105  logger_, "Update area outside of original map area. Costmap bounds: %d X %d, "
106  "Update origin: %d, %d bounds: %d X %d", map_cell_size_x, map_call_size_y,
107  update_msg->x, update_msg->y, update_msg->size_x, update_msg->size_y);
108  return;
109  }
110  unsigned char * master_array = costmap_->getCharMap();
111  // copy update msg row-wise
112  for (size_t y = 0; y < update_msg->size_y; ++y) {
113  auto starting_index_of_row_update_in_costmap = (y + update_msg->y) * map_cell_size_x +
114  update_msg->x;
115 
116  std::copy_n(
117  update_msg->data.begin() + (y * update_msg->size_x),
118  update_msg->size_x, &master_array[starting_index_of_row_update_in_costmap]);
119  }
120  } else {
121  RCLCPP_WARN(logger_, "No costmap received.");
122  }
123 }
124 
125 void CostmapSubscriber::processCurrentCostmapMsg()
126 {
127  std::scoped_lock lock(*(costmap_->getMutex()), costmap_msg_mutex_);
128  if (haveCostmapParametersChanged()) {
129  costmap_->resizeMap(
130  costmap_msg_->metadata.size_x, costmap_msg_->metadata.size_y,
131  costmap_msg_->metadata.resolution,
132  costmap_msg_->metadata.origin.position.x,
133  costmap_msg_->metadata.origin.position.y);
134  }
135 
136  unsigned char * master_array = costmap_->getCharMap();
137  std::copy(costmap_msg_->data.begin(), costmap_msg_->data.end(), master_array);
138  costmap_msg_.reset();
139 }
140 
141 bool CostmapSubscriber::haveCostmapParametersChanged()
142 {
143  return hasCostmapSizeChanged() ||
144  hasCostmapResolutionChanged() ||
145  hasCostmapOriginPositionChanged();
146 }
147 
148 bool CostmapSubscriber::hasCostmapSizeChanged()
149 {
150  return costmap_->getSizeInCellsX() != costmap_msg_->metadata.size_x ||
151  costmap_->getSizeInCellsY() != costmap_msg_->metadata.size_y;
152 }
153 
154 bool CostmapSubscriber::hasCostmapResolutionChanged()
155 {
156  return costmap_->getResolution() != costmap_msg_->metadata.resolution;
157 }
158 
159 bool CostmapSubscriber::hasCostmapOriginPositionChanged()
160 {
161  return costmap_->getOriginX() != costmap_msg_->metadata.origin.position.x ||
162  costmap_->getOriginY() != costmap_msg_->metadata.origin.position.y;
163 }
164 
165 } // namespace nav2_costmap_2d
CostmapSubscriber(const nav2_util::LifecycleNode::WeakPtr &parent, const std::string &topic_name)
A constructor.
void costmapUpdateCallback(const nav2_msgs::msg::CostmapUpdate::SharedPtr update_msg)
Callback for the costmap's update topic.
void costmapCallback(const nav2_msgs::msg::Costmap::SharedPtr msg)
Callback for the costmap topic.
std::shared_ptr< Costmap2D > getCostmap()
Get current costmap.