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),
72 circumscribed_radius_(1.0),
73 inscribed_radius_(0.1),
74 footprint_(std::make_shared<std::vector<geometry_msgs::msg::Point>>())
87 while (plugins_.size() > 0) {
90 while (filters_.size() > 0) {
97 std::unique_lock<Costmap2D::mutex_t> lock(*(combined_costmap_.getMutex()));
98 plugins_.push_back(plugin);
103 std::unique_lock<Costmap2D::mutex_t> lock(*(combined_costmap_.getMutex()));
104 filters_.push_back(filter);
108 unsigned int size_x,
unsigned int size_y,
double resolution,
113 std::unique_lock<Costmap2D::mutex_t> lock(*(combined_costmap_.getMutex()));
114 size_locked_ = size_locked;
115 primary_costmap_.
resizeMap(size_x, size_y, resolution, origin_x, origin_y);
116 combined_costmap_.
resizeMap(size_x, size_y, resolution, origin_x, origin_y);
117 for (vector<std::shared_ptr<Layer>>::iterator plugin = plugins_.begin();
118 plugin != plugins_.end(); ++plugin)
121 (*plugin)->matchSize();
124 for (vector<std::shared_ptr<Layer>>::iterator filter = filters_.begin();
125 filter != filters_.end(); ++filter)
127 (*filter)->matchSize();
134 return !combined_costmap_.
worldToMap(robot_x, robot_y, mx, my);
141 std::unique_lock<Costmap2D::mutex_t> lock(*(combined_costmap_.getMutex()));
145 if (rolling_window_) {
148 primary_costmap_.
updateOrigin(new_origin_x, new_origin_y);
149 combined_costmap_.
updateOrigin(new_origin_x, new_origin_y);
153 rclcpp::Clock clock{RCL_ROS_TIME};
154 RCLCPP_WARN_THROTTLE(
155 rclcpp::get_logger(
"nav2_costmap_2d"),
157 "Robot is out of bounds of the costmap");
160 if (plugins_.size() == 0 && filters_.size() == 0) {
164 minx_ = miny_ = std::numeric_limits<double>::max();
165 maxx_ = maxy_ = std::numeric_limits<double>::lowest();
167 for (vector<std::shared_ptr<Layer>>::iterator plugin = plugins_.begin();
168 plugin != plugins_.end(); ++plugin)
170 double prev_minx = minx_;
171 double prev_miny = miny_;
172 double prev_maxx = maxx_;
173 double prev_maxy = maxy_;
174 (*plugin)->updateBounds(robot_x, robot_y, robot_yaw, &minx_, &miny_, &maxx_, &maxy_);
175 if (minx_ > prev_minx || miny_ > prev_miny || maxx_ < prev_maxx || maxy_ < prev_maxy) {
178 "nav2_costmap_2d"),
"Illegal bounds change, was [tl: (%f, %f), br: (%f, %f)], but "
179 "is now [tl: (%f, %f), br: (%f, %f)]. The offending layer is %s",
180 prev_minx, prev_miny, prev_maxx, prev_maxy,
181 minx_, miny_, maxx_, maxy_,
182 (*plugin)->getName().c_str());
185 for (vector<std::shared_ptr<Layer>>::iterator filter = filters_.begin();
186 filter != filters_.end(); ++filter)
188 double prev_minx = minx_;
189 double prev_miny = miny_;
190 double prev_maxx = maxx_;
191 double prev_maxy = maxy_;
192 (*filter)->updateBounds(robot_x, robot_y, robot_yaw, &minx_, &miny_, &maxx_, &maxy_);
193 if (minx_ > prev_minx || miny_ > prev_miny || maxx_ < prev_maxx || maxy_ < prev_maxy) {
196 "nav2_costmap_2d"),
"Illegal bounds change, was [tl: (%f, %f), br: (%f, %f)], but "
197 "is now [tl: (%f, %f), br: (%f, %f)]. The offending filter is %s",
198 prev_minx, prev_miny, prev_maxx, prev_maxy,
199 minx_, miny_, maxx_, maxy_,
200 (*filter)->getName().c_str());
208 x0 = std::max(0, x0);
209 xn = std::min(
static_cast<int>(combined_costmap_.
getSizeInCellsX()), xn + 1);
210 y0 = std::max(0, y0);
211 yn = std::min(
static_cast<int>(combined_costmap_.
getSizeInCellsY()), yn + 1);
215 "nav2_costmap_2d"),
"Updating area x: [%d, %d] y: [%d, %d]", x0, xn, y0, yn);
217 if (xn < x0 || yn < y0) {
221 if (filters_.size() == 0) {
223 combined_costmap_.
resetMap(x0, y0, xn, yn);
224 for (vector<std::shared_ptr<Layer>>::iterator plugin = plugins_.begin();
225 plugin != plugins_.end(); ++plugin)
227 (*plugin)->updateCosts(combined_costmap_, x0, y0, xn, yn);
232 primary_costmap_.
resetMap(x0, y0, xn, yn);
233 for (vector<std::shared_ptr<Layer>>::iterator plugin = plugins_.begin();
234 plugin != plugins_.end(); ++plugin)
236 (*plugin)->updateCosts(primary_costmap_, x0, y0, xn, yn);
241 if (!combined_costmap_.
copyWindow(primary_costmap_, x0, y0, xn, yn, x0, y0)) {
243 rclcpp::get_logger(
"nav2_costmap_2d"),
244 "Can not copy costmap (%i,%i)..(%i,%i) window",
246 throw std::runtime_error{
"Can not copy costmap"};
251 for (vector<std::shared_ptr<Layer>>::iterator filter = filters_.begin();
252 filter != filters_.end(); ++filter)
254 (*filter)->updateCosts(combined_costmap_, x0, y0, xn, yn);
269 for (vector<std::shared_ptr<Layer>>::iterator plugin = plugins_.begin();
270 plugin != plugins_.end(); ++plugin)
272 current_ = current_ && ((*plugin)->isCurrent() || !(*plugin)->isEnabled());
274 for (vector<std::shared_ptr<Layer>>::iterator filter = filters_.begin();
275 filter != filters_.end(); ++filter)
277 current_ = current_ && ((*filter)->isCurrent() || !(*filter)->isEnabled());
290 std::make_shared<std::vector<geometry_msgs::msg::Point>>(footprint_spec));
291 inscribed_radius_.store(std::get<0>(inside_outside));
292 circumscribed_radius_.store(std::get<1>(inside_outside));
294 for (vector<std::shared_ptr<Layer>>::iterator plugin = plugins_.begin();
295 plugin != plugins_.end();
298 (*plugin)->onFootprintChanged();
300 for (vector<std::shared_ptr<Layer>>::iterator filter = filters_.begin();
301 filter != filters_.end();
304 (*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.