Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Impl noise filtering layer in the costmap_2d #2567

Merged
Merged
Show file tree
Hide file tree
Changes from 44 commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
69dafcf
Impl noise filtering layer in the costmap_2d
ryzhikovas Sep 17, 2021
7b11fd9
Remove redundant forward declaration of test
ryzhikovas Oct 6, 2021
60c3dc4
Remove costmap2d grid lock
ryzhikovas Oct 6, 2021
763b1ef
Check for existence of Lifecycle Node when requesting parameters
ryzhikovas Oct 6, 2021
113278b
Clarify empty/free cell constants
ryzhikovas Oct 6, 2021
fb31355
Fix license headers
ryzhikovas Oct 6, 2021
5e0a512
Minor refactoring
ryzhikovas Oct 7, 2021
25f9592
Migration from OpenCV
ryzhikovas Oct 27, 2021
9ea3bc5
Fix obstacle codes
ryzhikovas Nov 24, 2021
7e70fb7
Automatic switching between label types
ryzhikovas Dec 30, 2021
dfdd57a
Remove unused code
ryzhikovas Jan 11, 2022
eb5177f
Fix code style
ryzhikovas Jan 14, 2022
42b715f
Interpret INFLATED_OBSTACLE as obstacle too
ryzhikovas Jan 14, 2022
544a09e
Clarify the name of the replaceOutOfBounds method
ryzhikovas Jan 14, 2022
67ed09f
Fix failed tests
ryzhikovas Jan 14, 2022
3c005b9
Fix excessive memory reservation
ryzhikovas Feb 22, 2022
12bcecf
Refactoring: fix order of functions
ryzhikovas Feb 22, 2022
03a2cae
Refactoring: rename boundary case objects
ryzhikovas Feb 23, 2022
70b6cd8
Refactoring: rewrite makeLabel() description
ryzhikovas Feb 23, 2022
267d583
Refactoring: clarify createShape()
ryzhikovas Mar 9, 2022
18c3bac
Refactoring: remove obsolete connectedComponents doc
ryzhikovas Mar 11, 2022
83b0fc3
Refactoring: named constants in image proc. test
ryzhikovas Mar 14, 2022
ad04d6e
Fix NO_INFORMATION code interpretation
ryzhikovas Mar 17, 2022
cb1e6e5
Refactoring: replace magic numbers with constants
ryzhikovas Mar 17, 2022
9b49c8f
Linting fix
ryzhikovas Mar 22, 2022
e18a4fb
Test automatic switching of type label_trees
ryzhikovas Mar 24, 2022
0a5416e
Сomments improvements
ryzhikovas Apr 5, 2022
b4d5502
Fix infinite loop in connectedComponents
ryzhikovas Jun 7, 2022
82dbef0
More consistent naming
ryzhikovas Jun 7, 2022
e60fa9d
Fix removeSinglePixels when NO_INFORMATION is not obstacle
ryzhikovas Jun 7, 2022
c9a50ec
Fix internal map construction
ryzhikovas Oct 9, 2022
a2deb8f
Add debug dump
ryzhikovas Oct 10, 2022
abc31a6
Add images to the tests in which step != columns
ryzhikovas Oct 19, 2022
f094ae6
Adapt probeRows for non-continuous images
ryzhikovas Oct 19, 2022
55df387
Add standard header files
ryzhikovas Oct 19, 2022
3b4bd64
Rollback debug dump
ryzhikovas Nov 6, 2022
6c8d1fe
Add tests for the case when NO_INFORMATION is obstacle
ryzhikovas Nov 6, 2022
e3e669c
Update the year in copyright
ryzhikovas Dec 7, 2022
101c99c
Fix the enumeration description (autodoc)
ryzhikovas Dec 7, 2022
7a63824
Remove redundant out-of-bounds check
ryzhikovas Dec 7, 2022
dac9c11
Change the outdated test name
ryzhikovas Dec 7, 2022
f5683c5
Simplify max function and slightly speed up it
ryzhikovas Dec 8, 2022
c6be9c2
Fix uncrustify errors
ryzhikovas Dec 25, 2022
8105b53
Move impl details to denoise subdirectory
ryzhikovas Apr 28, 2023
9830245
Fix header guards names
ryzhikovas May 11, 2023
1901f81
Update year in copyright
ryzhikovas May 11, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions nav2_costmap_2d/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ add_library(layers SHARED
src/observation_buffer.cpp
plugins/voxel_layer.cpp
plugins/range_sensor_layer.cpp
plugins/denoise_layer.cpp
)
ament_target_dependencies(layers
${dependencies}
Expand Down
3 changes: 3 additions & 0 deletions nav2_costmap_2d/costmap_plugins.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
<class type="nav2_costmap_2d::RangeSensorLayer" base_class_type="nav2_costmap_2d::Layer">
<description>A range-sensor (sonar, IR) based obstacle layer for costmap_2d</description>
</class>
<class type="nav2_costmap_2d::DenoiseLayer" base_class_type="nav2_costmap_2d::Layer">
<description>Filters noise-induced freestanding obstacles or small obstacles groups</description>
</class>
</library>

<library path="filters">
Expand Down
207 changes: 207 additions & 0 deletions nav2_costmap_2d/include/nav2_costmap_2d/denoise/image.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
// Copyright (c) 2022 Andrey Ryzhikov
AlexeyMerzlyakov marked this conversation as resolved.
Show resolved Hide resolved
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef NAV2_COSTMAP_2D__IMAGE_HPP_
#define NAV2_COSTMAP_2D__IMAGE_HPP_
AlexeyMerzlyakov marked this conversation as resolved.
Show resolved Hide resolved

#include <cstddef>
#include <stdexcept>

namespace nav2_costmap_2d
{

/**
* @brief Image with pixels of type T
* Сan own data, be a wrapper over some memory buffer, or refer to a fragment of another image
* Pixels of one row are stored continuity. But rows continuity is not guaranteed.
* The distance (number of elements of type T) from row(i) to row(i + 1) is equal to step()
* @tparam T type of pixel
*/
template<class T>
class Image
{
public:
/// @brief Create empty image
Image() = default;

/**
* @brief Create image referencing to a third-party buffer
* @param rows number of image rows
* @param columns number of image columns
* @param data existing memory buffer with size at least rows * columns
* @param step offset from row(i) to row(i + 1) in memory buffer (number of elements of type T).
* offset = columns if rows are stored continuity
*/
Image(size_t rows, size_t columns, T * data, size_t step);

/**
* @brief Create image referencing to the other
* Share image data between new and old object.
* Changing data in a new object will affect the given one and vice versa
*/
Image(Image & other);

/**
* @brief Create image from the other (move constructor)
*/
Image(Image && other) noexcept;

/// @return number of image rows
size_t rows() const {return rows_;}

/// @return number of image columns
size_t columns() const {return columns_;}

/// @return true if image empty
bool empty() const {return rows_ == 0 || columns_ == 0;}

/// @return offset (number of elements of type T) from row(i) to row(i + 1)
size_t step() const {return step_;}

/**
* @return pointer to first pixel of row
* @warning If row >= rows(), the behavior is undefined
*/
T * row(size_t row);

/// @overload
const T * row(size_t row) const;

/**
* @brief Read (and modify, if need) each pixel sequentially
* @tparam Functor function object.
* Signature should be equivalent to the following:
* void fn(T& pixel) or void fn(const T& pixel)
* @param fn a function that will be applied to each pixel in the image. Can modify image data
*/
template<class Functor>
void forEach(Functor && fn);

/**
* @brief Read each pixel sequentially
* @tparam Functor function object.
* Signature should be equivalent to the following:
* void fn(const T& pixel)
* @param fn a function that will be applied to each pixel in the image
*/
template<class Functor>
void forEach(Functor && fn) const;
/**
* @brief Convert each pixel to corresponding pixel of target using a custom function
*
* The source and target must be the same size.
* For calculation of new target value the operation can use source value and
* an optionally current target value.
* This function call operation(this[i, j], target[i, j]) for each pixel
* where target[i, j] is mutable
* @tparam TargetElement type of target pixel
* @tparam Converter function object.
* Signature should be equivalent to the following:
* void fn(const T& src, TargetElement& trg)
* @param target output image with TargetElement-type pixels
* @param operation the binary operation op is applied to pairs of pixels:
* first (const) from source and second (mutable) from target
* @throw std::logic_error if the source and target of different sizes
*/
template<class TargetElement, class Converter>
void convert(Image<TargetElement> & target, Converter && converter) const;

private:
T * data_start_{};
size_t rows_{};
size_t columns_{};
size_t step_{};
};

template<class T>
Image<T>::Image(size_t rows, size_t columns, T * data, size_t step)
: rows_{rows}, columns_{columns}, step_{step}
{
data_start_ = data;
}

template<class T>
Image<T>::Image(Image & other)
: data_start_{other.data_start_},
rows_{other.rows_}, columns_{other.columns_}, step_{other.step_} {}

template<class T>
Image<T>::Image(Image && other) noexcept
: data_start_{other.data_start_},
rows_{other.rows_}, columns_{other.columns_}, step_{other.step_} {}

template<class T>
T * Image<T>::row(size_t row)
{
return const_cast<T *>( static_cast<const Image<T> &>(*this).row(row) );
}

template<class T>
const T * Image<T>::row(size_t row) const
{
return data_start_ + row * step_;
}

template<class T>
template<class Functor>
void Image<T>::forEach(Functor && fn)
{
static_cast<const Image<T> &>(*this).forEach(
[&](const T & pixel) {
fn(const_cast<T &>(pixel));
});
}

template<class T>
template<class Functor>
void Image<T>::forEach(Functor && fn) const
{
const T * rowPtr = row(0);

for (size_t row = 0; row < rows(); ++row) {
const T * rowEnd = rowPtr + columns();

for (const T * pixel = rowPtr; pixel != rowEnd; ++pixel) {
fn(*pixel);
}
rowPtr += step();
}
}

template<class T>
template<class TargetElement, class Converter>
void Image<T>::convert(Image<TargetElement> & target, Converter && converter) const
{
if (rows() != target.rows() || columns() != target.columns()) {
throw std::logic_error("Image::convert. The source and target images size are different");
}
const T * source_row = row(0);
TargetElement * target_row = target.row(0);

for (size_t row = 0; row < rows(); ++row) {
const T * rowInEnd = source_row + columns();
const T * src = source_row;
TargetElement * trg = target_row;

for (; src != rowInEnd; ++src, ++trg) {
converter(*src, *trg);
}
source_row += step();
target_row += target.step();
}
}

} // namespace nav2_costmap_2d

#endif // NAV2_COSTMAP_2D__IMAGE_HPP_
Loading