Nav2 Navigation Stack - jazzy  jazzy
ROS 2 Navigation Stack
clear_costmap_service.cpp
1 // Copyright (c) 2018 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 <vector>
16 #include <string>
17 #include <algorithm>
18 #include <memory>
19 
20 #include "nav2_costmap_2d/clear_costmap_service.hpp"
21 #include "nav2_costmap_2d/costmap_2d_ros.hpp"
22 
23 namespace nav2_costmap_2d
24 {
25 
26 using std::vector;
27 using std::string;
28 using std::shared_ptr;
29 using std::any_of;
30 using ClearExceptRegion = nav2_msgs::srv::ClearCostmapExceptRegion;
31 using ClearAroundRobot = nav2_msgs::srv::ClearCostmapAroundRobot;
32 using ClearAroundPose = nav2_msgs::srv::ClearCostmapAroundPose;
33 using ClearEntirely = nav2_msgs::srv::ClearEntireCostmap;
34 
36  const nav2_util::LifecycleNode::WeakPtr & parent,
37  Costmap2DROS & costmap)
38 : costmap_(costmap)
39 {
40  auto node = parent.lock();
41  logger_ = node->get_logger();
42  reset_value_ = costmap_.getCostmap()->getDefaultValue();
43 
44  clear_except_service_ = node->create_service<ClearExceptRegion>(
45  "clear_except_" + costmap_.getName(),
46  std::bind(
47  &ClearCostmapService::clearExceptRegionCallback, this,
48  std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
49 
50  clear_around_service_ = node->create_service<ClearAroundRobot>(
51  "clear_around_" + costmap.getName(),
52  std::bind(
53  &ClearCostmapService::clearAroundRobotCallback, this,
54  std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
55 
56  clear_around_pose_service_ = node->create_service<ClearAroundPose>(
57  std::string("clear_around_pose_") + costmap_.getName(),
58  std::bind(
59  &ClearCostmapService::clearAroundPoseCallback, this,
60  std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
61 
62  clear_entire_service_ = node->create_service<ClearEntirely>(
63  "clear_entirely_" + costmap_.getName(),
64  std::bind(
65  &ClearCostmapService::clearEntireCallback, this,
66  std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
67 }
68 
70 {
71  // make sure services shutdown.
72  clear_except_service_.reset();
73  clear_around_service_.reset();
74  clear_around_pose_service_.reset();
75  clear_entire_service_.reset();
76 }
77 
78 void ClearCostmapService::clearExceptRegionCallback(
79  const shared_ptr<rmw_request_id_t>/*request_header*/,
80  const shared_ptr<ClearExceptRegion::Request> request,
81  const shared_ptr<ClearExceptRegion::Response>/*response*/)
82 {
83  RCLCPP_INFO(
84  logger_, "%s",
85  ("Received request to clear except a region the " + costmap_.getName()).c_str());
86 
87  clearRegion(request->reset_distance, true);
88 }
89 
90 void ClearCostmapService::clearAroundRobotCallback(
91  const shared_ptr<rmw_request_id_t>/*request_header*/,
92  const shared_ptr<ClearAroundRobot::Request> request,
93  const shared_ptr<ClearAroundRobot::Response>/*response*/)
94 {
95  clearRegion(request->reset_distance, false);
96 }
97 
98 void ClearCostmapService::clearAroundPoseCallback(
99  const shared_ptr<rmw_request_id_t>/*request_header*/,
100  const shared_ptr<ClearAroundPose::Request> request,
101  const shared_ptr<ClearAroundPose::Response>/*response*/)
102 {
103  RCLCPP_INFO(
104  logger_, "%s",
105  ("Received request to clear around pose for " + costmap_.getName()).c_str());
106 
107  clearAroundPose(request->pose, request->reset_distance);
108 }
109 
110 void ClearCostmapService::clearEntireCallback(
111  const std::shared_ptr<rmw_request_id_t>/*request_header*/,
112  const std::shared_ptr<ClearEntirely::Request>/*request*/,
113  const std::shared_ptr<ClearEntirely::Response>/*response*/)
114 {
115  RCLCPP_INFO(
116  logger_, "%s",
117  ("Received request to clear entirely the " + costmap_.getName()).c_str());
118 
119  clearEntirely();
120 }
121 
123  const geometry_msgs::msg::PoseStamped & pose,
124  const double reset_distance)
125 {
126  double x, y;
127 
128  // Transform pose to costmap frame if necessary
129  geometry_msgs::msg::PoseStamped global_pose;
130  try {
131  if (pose.header.frame_id == costmap_.getGlobalFrameID()) {
132  global_pose = pose;
133  } else {
134  costmap_.getTfBuffer()->transform(pose, global_pose, costmap_.getGlobalFrameID());
135  }
136  } catch (tf2::TransformException & ex) {
137  RCLCPP_ERROR(
138  logger_,
139  "Cannot clear map around pose because pose cannot be transformed to costmap frame: %s",
140  ex.what());
141  return;
142  }
143 
144  x = global_pose.pose.position.x;
145  y = global_pose.pose.position.y;
146 
147  auto layers = costmap_.getLayeredCostmap()->getPlugins();
148 
149  for (auto & layer : *layers) {
150  if (layer->isClearable()) {
151  auto costmap_layer = std::static_pointer_cast<CostmapLayer>(layer);
152  clearLayerRegion(costmap_layer, x, y, reset_distance, false);
153  }
154  }
155 }
156 
157 void ClearCostmapService::clearRegion(const double reset_distance, bool invert)
158 {
159  double x, y;
160 
161  if (!getPosition(x, y)) {
162  RCLCPP_ERROR(
163  logger_, "%s",
164  "Cannot clear map because robot pose cannot be retrieved.");
165  return;
166  }
167 
168  auto layers = costmap_.getLayeredCostmap()->getPlugins();
169 
170  for (auto & layer : *layers) {
171  if (layer->isClearable()) {
172  auto costmap_layer = std::static_pointer_cast<CostmapLayer>(layer);
173  clearLayerRegion(costmap_layer, x, y, reset_distance, invert);
174  }
175  }
176 
177  // AlexeyMerzlyakov: No need to clear layer region for costmap filters
178  // as they are always supposed to be not clearable.
179 }
180 
181 void ClearCostmapService::clearLayerRegion(
182  shared_ptr<CostmapLayer> & costmap, double pose_x, double pose_y, double reset_distance,
183  bool invert)
184 {
185  std::unique_lock<Costmap2D::mutex_t> lock(*(costmap->getMutex()));
186 
187  double start_point_x = pose_x - reset_distance / 2;
188  double start_point_y = pose_y - reset_distance / 2;
189  double end_point_x = start_point_x + reset_distance;
190  double end_point_y = start_point_y + reset_distance;
191 
192  int start_x, start_y, end_x, end_y;
193  costmap->worldToMapEnforceBounds(start_point_x, start_point_y, start_x, start_y);
194  costmap->worldToMapEnforceBounds(end_point_x, end_point_y, end_x, end_y);
195 
196  costmap->clearArea(start_x, start_y, end_x, end_y, invert);
197 
198  double ox = costmap->getOriginX(), oy = costmap->getOriginY();
199  double width = costmap->getSizeInMetersX(), height = costmap->getSizeInMetersY();
200  costmap->addExtraBounds(ox, oy, ox + width, oy + height);
201 }
202 
204 {
205  std::unique_lock<Costmap2D::mutex_t> lock(*(costmap_.getCostmap()->getMutex()));
206  costmap_.resetLayers();
207 }
208 
209 bool ClearCostmapService::getPosition(double & x, double & y) const
210 {
211  geometry_msgs::msg::PoseStamped pose;
212  if (!costmap_.getRobotPose(pose)) {
213  return false;
214  }
215 
216  x = pose.pose.position.x;
217  y = pose.pose.position.y;
218 
219  return true;
220 }
221 
222 } // namespace nav2_costmap_2d
void clearAroundPose(const geometry_msgs::msg::PoseStamped &pose, double reset_distance)
Clears the region around a specific pose.
ClearCostmapService()=delete
A constructor.
void clearRegion(double reset_distance, bool invert)
Clears the region outside of a user-specified area reverting to the static map.
A ROS wrapper for a 2D Costmap. Handles subscribing to topics that provide observations about obstacl...
bool getRobotPose(geometry_msgs::msg::PoseStamped &global_pose)
Get the pose of the robot in the global frame of the costmap.
std::string getName() const
Returns costmap name.
LayeredCostmap * getLayeredCostmap()
Get the layered costmap object used in the node.
void resetLayers()
Reset each individual layer.
std::string getGlobalFrameID()
Returns the global frame of the costmap.
Costmap2D * getCostmap()
Return a pointer to the "master" costmap which receives updates from all the layers.
unsigned char getDefaultValue()
Get the default background value of the costmap.
Definition: costmap_2d.hpp:299
std::vector< std::shared_ptr< Layer > > * getPlugins()
Get the vector of pointers to the costmap plugins.