38 #include "nav2_costmap_2d/layered_costmap.hpp"
47 #include <rclcpp/clock.hpp>
49 #include "nav2_costmap_2d/footprint.hpp"
58 : primary_costmap_(), combined_costmap_(),
59 global_frame_(global_frame),
60 rolling_window_(rolling_window),
71 circumscribed_radius_(1.0),
72 inscribed_radius_(0.1),
73 footprint_(std::make_shared<std::vector<geometry_msgs::msg::Point>>())
86 while (plugins_.size() > 0) {
89 while (filters_.size() > 0) {
96 std::unique_lock<Costmap2D::mutex_t> lock(*(combined_costmap_.getMutex()));
97 plugins_.push_back(plugin);
102 std::unique_lock<Costmap2D::mutex_t> lock(*(combined_costmap_.getMutex()));
103 filters_.push_back(filter);
107 unsigned int size_x,
unsigned int size_y,
double resolution,
112 std::unique_lock<Costmap2D::mutex_t> lock(*(combined_costmap_.getMutex()));
113 size_locked_ = size_locked;
114 primary_costmap_.
resizeMap(size_x, size_y, resolution, origin_x, origin_y);
115 combined_costmap_.
resizeMap(size_x, size_y, resolution, origin_x, origin_y);
116 for (vector<std::shared_ptr<Layer>>::iterator plugin = plugins_.begin();
117 plugin != plugins_.end(); ++plugin)
120 (*plugin)->matchSize();
123 for (vector<std::shared_ptr<Layer>>::iterator filter = filters_.begin();
124 filter != filters_.end(); ++filter)
126 (*filter)->matchSize();
133 return !combined_costmap_.
worldToMap(robot_x, robot_y, mx, my);
140 std::unique_lock<Costmap2D::mutex_t> lock(*(combined_costmap_.getMutex()));
144 if (rolling_window_) {
147 primary_costmap_.
updateOrigin(new_origin_x, new_origin_y);
148 combined_costmap_.
updateOrigin(new_origin_x, new_origin_y);
152 rclcpp::Clock clock{RCL_ROS_TIME};
153 RCLCPP_WARN_THROTTLE(
154 rclcpp::get_logger(
"nav2_costmap_2d"),
156 "Robot is out of bounds of the costmap");
159 if (plugins_.size() == 0 && filters_.size() == 0) {
163 minx_ = miny_ = std::numeric_limits<double>::max();
164 maxx_ = maxy_ = std::numeric_limits<double>::lowest();
166 for (vector<std::shared_ptr<Layer>>::iterator plugin = plugins_.begin();
167 plugin != plugins_.end(); ++plugin)
169 double prev_minx = minx_;
170 double prev_miny = miny_;
171 double prev_maxx = maxx_;
172 double prev_maxy = maxy_;
173 (*plugin)->updateBounds(robot_x, robot_y, robot_yaw, &minx_, &miny_, &maxx_, &maxy_);
174 if (minx_ > prev_minx || miny_ > prev_miny || maxx_ < prev_maxx || maxy_ < prev_maxy) {
177 "nav2_costmap_2d"),
"Illegal bounds change, was [tl: (%f, %f), br: (%f, %f)], but "
178 "is now [tl: (%f, %f), br: (%f, %f)]. The offending layer is %s",
179 prev_minx, prev_miny, prev_maxx, prev_maxy,
180 minx_, miny_, maxx_, maxy_,
181 (*plugin)->getName().c_str());
184 for (vector<std::shared_ptr<Layer>>::iterator filter = filters_.begin();
185 filter != filters_.end(); ++filter)
187 double prev_minx = minx_;
188 double prev_miny = miny_;
189 double prev_maxx = maxx_;
190 double prev_maxy = maxy_;
191 (*filter)->updateBounds(robot_x, robot_y, robot_yaw, &minx_, &miny_, &maxx_, &maxy_);
192 if (minx_ > prev_minx || miny_ > prev_miny || maxx_ < prev_maxx || maxy_ < prev_maxy) {
195 "nav2_costmap_2d"),
"Illegal bounds change, was [tl: (%f, %f), br: (%f, %f)], but "
196 "is now [tl: (%f, %f), br: (%f, %f)]. The offending filter is %s",
197 prev_minx, prev_miny, prev_maxx, prev_maxy,
198 minx_, miny_, maxx_, maxy_,
199 (*filter)->getName().c_str());
207 x0 = std::max(0, x0);
208 xn = std::min(
static_cast<int>(combined_costmap_.
getSizeInCellsX()), xn + 1);
209 y0 = std::max(0, y0);
210 yn = std::min(
static_cast<int>(combined_costmap_.
getSizeInCellsY()), yn + 1);
214 "nav2_costmap_2d"),
"Updating area x: [%d, %d] y: [%d, %d]", x0, xn, y0, yn);
216 if (xn >= x0 && yn >= y0) {
217 if (filters_.size() == 0) {
219 combined_costmap_.
resetMap(x0, y0, xn, yn);
220 for (vector<std::shared_ptr<Layer>>::iterator plugin = plugins_.begin();
221 plugin != plugins_.end(); ++plugin)
223 (*plugin)->updateCosts(combined_costmap_, x0, y0, xn, yn);
228 primary_costmap_.
resetMap(x0, y0, xn, yn);
229 for (vector<std::shared_ptr<Layer>>::iterator plugin = plugins_.begin();
230 plugin != plugins_.end(); ++plugin)
232 (*plugin)->updateCosts(primary_costmap_, x0, y0, xn, yn);
237 if (!combined_costmap_.
copyWindow(primary_costmap_, x0, y0, xn, yn, x0, y0)) {
239 rclcpp::get_logger(
"nav2_costmap_2d"),
240 "Can not copy costmap (%i,%i)..(%i,%i) window",
242 throw std::runtime_error{
"Can not copy costmap"};
247 for (vector<std::shared_ptr<Layer>>::iterator filter = filters_.begin();
248 filter != filters_.end(); ++filter)
250 (*filter)->updateCosts(combined_costmap_, x0, y0, xn, yn);
263 for (vector<std::shared_ptr<Layer>>::iterator plugin = plugins_.begin();
264 plugin != plugins_.end(); ++plugin)
266 if (*plugin && !(*plugin)->isEnabled()) {
267 (*plugin)->setCurrent(
true);
270 for (vector<std::shared_ptr<Layer>>::iterator filter = filters_.begin();
271 filter != filters_.end(); ++filter)
273 if (!(*filter)->isEnabled()) {
274 (*filter)->setCurrent(
true);
281 for (vector<std::shared_ptr<Layer>>::iterator plugin = plugins_.begin();
282 plugin != plugins_.end(); ++plugin)
284 if (!(*plugin)->isCurrent()) {
288 for (vector<std::shared_ptr<Layer>>::iterator filter = filters_.begin();
289 filter != filters_.end(); ++filter)
291 if (!(*filter)->isCurrent()) {
305 std::make_shared<std::vector<geometry_msgs::msg::Point>>(footprint_spec));
306 inscribed_radius_.store(std::get<0>(inside_outside));
307 circumscribed_radius_.store(std::get<1>(inside_outside));
309 for (vector<std::shared_ptr<Layer>>::iterator plugin = plugins_.begin();
310 plugin != plugins_.end();
313 (*plugin)->onFootprintChanged();
315 for (vector<std::shared_ptr<Layer>>::iterator filter = filters_.begin();
316 filter != filters_.end();
319 (*filter)->onFootprintChanged();
void resetMap(unsigned int x0, unsigned int y0, unsigned int xn, unsigned int yn)
Reset the costmap in bounds.
void resizeMap(unsigned int size_x, unsigned int size_y, double resolution, double origin_x, double origin_y)
Resize the costmap.
bool copyWindow(const Costmap2D &source, unsigned int sx0, unsigned int sy0, unsigned int sxn, unsigned int syn, unsigned int dx0, unsigned int dy0)
Copies the (x0,y0)..(xn,yn) window from source costmap into a current costmap.
void worldToMapEnforceBounds(double wx, double wy, int &mx, int &my) const
Convert from world coordinates to map coordinates, constraining results to legal bounds.
bool worldToMap(double wx, double wy, unsigned int &mx, unsigned int &my) const
Convert from world coordinates to map coordinates.
void setDefaultValue(unsigned char c)
Set the default background value of the costmap.
virtual void updateOrigin(double new_origin_x, double new_origin_y)
Move the origin of the costmap to a new location.... keeping data when it can.
double getSizeInMetersY() const
Accessor for the y size of the costmap in meters.
double getSizeInMetersX() const
Accessor for the x size of the costmap in meters.
unsigned int getSizeInCellsX() const
Accessor for the x size of the costmap in cells.
unsigned int getSizeInCellsY() const
Accessor for the y size of the costmap in cells.
void addPlugin(std::shared_ptr< Layer > plugin)
Add a new plugin to the plugins vector to process.
~LayeredCostmap()
Destructor.
void addFilter(std::shared_ptr< Layer > filter)
Add a new costmap filter plugin to the filters vector to process.
void resizeMap(unsigned int size_x, unsigned int size_y, double resolution, double origin_x, double origin_y, bool size_locked=false)
Resize the map to a new size, resolution, or origin.
bool isOutofBounds(double robot_x, double robot_y)
Checks if the robot is outside the bounds of its costmap in the case of poorly configured setups.
void updateMap(double robot_x, double robot_y, double robot_yaw)
Update the underlying costmap with new data. If you want to update the map outside of the update loop...
LayeredCostmap(std::string global_frame, bool rolling_window, bool track_unknown)
Constructor for a costmap.
void setFootprint(const std::vector< geometry_msgs::msg::Point > &footprint_spec)
Updates the stored footprint, updates the circumscribed and inscribed radii, and calls onFootprintCha...
bool isCurrent()
If the costmap is current, e.g. are all the layers processing recent data and not stale information f...
std::pair< double, double > calculateMinAndMaxDistances(const std::vector< geometry_msgs::msg::Point > &footprint)
Calculate the extreme distances for the footprint.