15 #include "nav2_costmap_2d/denoise_layer.hpp"
22 #include "rclcpp/rclcpp.hpp"
30 const auto node = node_.lock();
33 throw std::runtime_error(
"DenoiseLayer::onInitialize: Failed to lock node");
35 enabled_ = node->declare_or_get_parameter(name_ +
"." +
"enabled",
true);
37 const int minimal_group_size_param = node->declare_or_get_parameter(
38 name_ +
"." +
"minimal_group_size", 2);
40 const int group_connectivity_type_param = node->declare_or_get_parameter(
41 name_ +
"." +
"group_connectivity_type", 8);
43 if (minimal_group_size_param <= 1) {
46 "DenoiseLayer::onInitialize(): param minimal_group_size: %i."
47 " A value of 1 or less means that all map cells will be left as they are.",
48 minimal_group_size_param);
49 minimal_group_size_ = 1;
51 minimal_group_size_ =
static_cast<size_t>(minimal_group_size_param);
54 if (group_connectivity_type_param == 4) {
59 if (group_connectivity_type_param != 8) {
61 logger_,
"DenoiseLayer::onInitialize(): param group_connectivity_type: %i."
62 " Possible values are 4 (neighbors pixels are connected horizontally and vertically) "
63 "or 8 (neighbors pixels are connected horizontally, vertically and diagonally)."
64 "The default value 8 will be used",
65 group_connectivity_type_param);
86 double ,
double ,
double ,
88 double * ,
double * ) {}
98 if (min_x >= max_x || min_y >= max_y) {
101 no_information_is_obstacle_ = master_grid.
getDefaultValue() != NO_INFORMATION;
104 unsigned char * master_array = master_grid.
getCharMap();
107 const size_t width = max_x - min_x;
108 const size_t height = max_y - min_y;
109 Image<uint8_t> roi_image(height, width, master_array + min_y * step + min_x, step);
113 }
catch (std::exception & ex) {
114 RCLCPP_ERROR(logger_,
"%s", (std::string(
"Inner error: ") + ex.what()).c_str());
127 if (minimal_group_size_ <= 1) {
131 if (minimal_group_size_ == 2) {
133 removeSinglePixels(image);
141 DenoiseLayer::removeGroups(Image<uint8_t> & image)
const
144 image, buffer_, group_connectivity_type_, minimal_group_size_,
145 [
this](uint8_t pixel) {
return isBackground(pixel);});
149 DenoiseLayer::removeSinglePixels(Image<uint8_t> & image)
const
153 uint8_t * buf = buffer_.
get<uint8_t>(image.rows() * image.columns());
154 Image<uint8_t> max_neighbors_image(image.rows(), image.columns(), buf, image.columns());
158 if (!no_information_is_obstacle_) {
159 auto replace_to_free = [](uint8_t v) {
160 return v == NO_INFORMATION ? FREE_SPACE : v;
162 auto max = [&](
const std::initializer_list<uint8_t> lst) {
163 std::array<uint8_t, 3> rbuf = {
164 replace_to_free(*lst.begin()),
165 replace_to_free(*(lst.begin() + 1)),
166 replace_to_free(*(lst.begin() + 2))
168 return *std::max_element(rbuf.begin(), rbuf.end());
170 dilate(image, max_neighbors_image, group_connectivity_type_, max);
172 auto max = [](
const std::initializer_list<uint8_t> lst) {
173 return std::max(lst);
175 dilate(image, max_neighbors_image, group_connectivity_type_, max);
178 max_neighbors_image.convert(
179 image, [
this](uint8_t maxNeighbor, uint8_t & img) {
180 if (!isBackground(img) && isBackground(maxNeighbor)) {
186 bool DenoiseLayer::isBackground(uint8_t pixel)
const
189 pixel == LETHAL_OBSTACLE ||
190 pixel == INSCRIBED_INFLATED_OBSTACLE ||
191 (pixel == NO_INFORMATION && no_information_is_obstacle_);
199 #include "pluginlib/class_list_macros.hpp"
A 2D costmap provides a mapping between points in the world and their associated "costs".
unsigned char * getCharMap() const
Will return a pointer to the underlying unsigned char array used as the costmap.
unsigned int getSizeInCellsX() const
Accessor for the x size of the costmap in cells.
unsigned char getDefaultValue()
Get the default background value of the costmap.
Layer filters noise-induced standalone obstacles (white costmap pixels) or small obstacles groups.
void updateCosts(nav2_costmap_2d::Costmap2D &master_grid, int min_x, int min_y, int max_x, int max_y) override
Filters noise-induced obstacles in the selected region of the costmap The method is called when costm...
void onInitialize() override
Initializes the layer on startup This method is called at the end of plugin initialization....
void updateBounds(double robot_x, double robot_y, double robot_yaw, double *min_x, double *min_y, double *max_x, double *max_y) override
Reports that no expansion is required The method is called to ask the plugin: which area of costmap i...
bool isClearable() override
Reports that no clearing operation is required.
void reset() override
Reset this layer.
Image with pixels of type T Сan own data, be a wrapper over some memory buffer, or refer to a fragmen...
Abstract class for layered costmap plugin implementations.
void setCurrent(bool current)
Set whether the data in the layer is up to date.
T * get(std::size_t count)
Return a pointer to an uninitialized array of count elements Delete the old block of memory and alloc...
void removeGroups(Image< uint8_t > &image, MemoryBuffer &buffer, ConnectivityType group_connectivity_type, size_t minimal_group_size, const IsBg &is_background) const
Calls removeGroupsPickLabelType with the Way4/Way8 template parameter based on the runtime value of g...
@ Way4
neighbors pixels are connected horizontally and vertically
@ Way8
neighbors pixels are connected horizontally, vertically and diagonally
void dilate(const Image< uint8_t > &input, Image< uint8_t > &output, ConnectivityType connectivity, Max &&max_function)
Perform morphological dilation.