Nav2 Navigation Stack - lyrical  lyrical
ROS 2 Navigation Stack
asymmetric_inflation_layer.hpp
1 // Copyright (c) 2026, Marc Blöchlinger
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 #ifndef NAV2_COSTMAP_2D__ASYMMETRIC_INFLATION_LAYER_HPP_
16 #define NAV2_COSTMAP_2D__ASYMMETRIC_INFLATION_LAYER_HPP_
17 
18 #include <algorithm>
19 #include <vector>
20 #include <mutex>
21 #include <memory>
22 #include <string>
23 #include <utility>
24 #include <unordered_map>
25 #include <cstdint>
26 
27 #include "rclcpp/rclcpp.hpp"
28 #include "nav2_costmap_2d/inflation_layer.hpp"
29 #include "nav_msgs/msg/path.hpp"
30 
31 namespace nav2_costmap_2d
32 {
33 
35 {
36  std::pair<double, double> start;
37  std::pair<double, double> end;
38 };
39 
40 enum class Side : int8_t
41 {
42  Right = -1,
43  Neutral = 0,
44  Left = 1,
45 };
46 
60 {
61 public:
63  ~AsymmetricInflationLayer() override = default;
64 
68  void onInitialize() override;
69 
73  void activate() override;
74 
78  void deactivate() override;
79 
93  void updateBounds(
94  double robot_x, double robot_y, double robot_yaw, double * min_x,
95  double * min_y, double * max_x, double * max_y) override;
96 
110  void updateCosts(
111  nav2_costmap_2d::Costmap2D & master_grid,
112  int min_i, int min_j, int max_i, int max_j) override;
113 
117  void matchSize() override;
118 
119 protected:
123  void onFootprintChanged() override;
124 
128  void globalPathCallback(const nav_msgs::msg::Path::ConstSharedPtr msg);
129 
139  std::vector<AsymmetricPathSegment> extractLocalPathSegments(
140  nav2_costmap_2d::Costmap2D & master_grid);
141 
157  Side computeObstacleSide(
158  double cx, double cy,
159  const std::vector<size_t> & candidates,
160  const std::vector<AsymmetricPathSegment> & local_path_segments);
161 
171  std::unordered_map<uint64_t, std::vector<size_t>>
173  const std::vector<AsymmetricPathSegment> & local_path_segments);
174 
191  nav2_costmap_2d::Costmap2D & master_grid,
192  int roi_min_i, int roi_min_j, int roi_width, int roi_height,
193  const std::unordered_map<uint64_t, std::vector<size_t>> & spatial_hash,
194  const std::vector<AsymmetricPathSegment> & local_path_segments);
195 
212  void applyInflation(
213  unsigned char * master_array,
214  const MatrixXfRM & distance_map,
215  int min_i, int min_j, int max_i, int max_j,
216  int roi_min_i, int roi_min_j,
217  unsigned int size_x);
218 
223 
228  rcl_interfaces::msg::SetParametersResult validateParameterUpdatesCallback(
229  const std::vector<rclcpp::Parameter> & parameters);
230 
236  const std::vector<rclcpp::Parameter> & parameters);
237 
238  // --- Parameters ---
245  std::string plan_topic_;
247  tf2::Duration transform_tolerance_;
248 
249  // --- State ---
250  double current_robot_x_{0.0};
251  double current_robot_y_{0.0};
252  bool asymmetry_active_{false};
253 
254  // --- Asymmetric Lookup Table ---
256  std::vector<unsigned char> cost_lut_disfavored_;
257 
258  // --- Path subscription ---
259  nav2::Subscription<nav_msgs::msg::Path>::SharedPtr path_sub_;
260  nav_msgs::msg::Path::ConstSharedPtr latest_global_path_;
261  std::mutex path_mutex_;
262 };
263 
264 } // namespace nav2_costmap_2d
265 
266 #endif // NAV2_COSTMAP_2D__ASYMMETRIC_INFLATION_LAYER_HPP_
Costmap layer that inflates obstacles asymmetrically relative to the global path, biasing the navigab...
void matchSize() override
Match the size of the master costmap.
void updateCosts(nav2_costmap_2d::Costmap2D &master_grid, int min_i, int min_j, int max_i, int max_j) override
Update the costs in the master costmap.
Side computeObstacleSide(double cx, double cy, const std::vector< size_t > &candidates, const std::vector< AsymmetricPathSegment > &local_path_segments)
Classify an obstacle cell as left (+1), right (-1), or neutral (0) relative to the closest path segme...
void updateBounds(double robot_x, double robot_y, double robot_yaw, double *min_x, double *min_y, double *max_x, double *max_y) override
Update the bounds of the master costmap by this layer's update dimensions.
rcl_interfaces::msg::SetParametersResult validateParameterUpdatesCallback(const std::vector< rclcpp::Parameter > &parameters)
Validate parameter updates (pre-set callback). Returns success/failure without mutating any state.
void applyInflation(unsigned char *master_array, const MatrixXfRM &distance_map, int min_i, int min_j, int max_i, int max_j, int roi_min_i, int roi_min_j, unsigned int size_x)
Apply disfavored-side costs from a distance map with max(old, new) semantics.
void activate() override
Activate the layer; registers the parameter validation/update callbacks.
void updateParametersCallback(const std::vector< rclcpp::Parameter > &parameters)
Apply parameter updates (post-set callback) after they have been validated. Recomputes caches when ge...
tf2::Duration transform_tolerance_
Timeout for path-frame TF lookups.
std::vector< AsymmetricPathSegment > extractLocalPathSegments(nav2_costmap_2d::Costmap2D &master_grid)
Extract global path segments that overlap the local costmap window.
void deactivate() override
Deactivate the layer; removes the parameter validation/update callbacks.
std::unordered_map< uint64_t, std::vector< size_t > > buildPathSpatialHash(const std::vector< AsymmetricPathSegment > &local_path_segments)
Build a spatial hash mapping 2D bucket keys to path segment indices.
void onInitialize() override
Initialization process of layer on startup.
double cost_scaling_factor_right_
Exponential decay rate for cells on the RIGHT side of the path.
double goal_distance_threshold_
Distance to goal where asymmetry disables to prevent docking oscillations.
MatrixXfRM seedDistanceMap(nav2_costmap_2d::Costmap2D &master_grid, int roi_min_i, int roi_min_j, int roi_width, int roi_height, const std::unordered_map< uint64_t, std::vector< size_t >> &spatial_hash, const std::vector< AsymmetricPathSegment > &local_path_segments)
Build a distance map seeded from disfavored-side obstacle boundary cells.
double cost_scaling_factor_left_
Exponential decay rate for cells on the LEFT side of the path.
void globalPathCallback(const nav_msgs::msg::Path::ConstSharedPtr msg)
Callback for incoming global path messages.
void computeAsymmetricCaches()
Pre-compute cost_lut_disfavored_ using c_side (the smaller per-side scaling factor)
void onFootprintChanged() override
Process updates on footprint changes to the inflation layer.
std::vector< unsigned char > cost_lut_disfavored_
Cost LUT for the disfavored side, built with c_side (the smaller per-side scaling factor)
A 2D costmap provides a mapping between points in the world and their associated "costs".
Definition: costmap_2d.hpp:69
Layer to convolve costmap by robot's radius or footprint using Eigen-based Felzenszwalb-Huttenlocher ...
Eigen::Matrix< float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor > MatrixXfRM
Row-major float matrix type for efficient row-wise access.