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

Feature/filtered elevation layer #84

Open
wants to merge 38 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
5af50a9
added elevation layer package as a plugin of costmap_2d
chisarie Oct 19, 2018
b3d8ac0
deleted .idea files
chisarie Oct 19, 2018
55ea64e
implemented elevation layer for costmap_2d. It takes elevaton mapping…
chisarie Oct 22, 2018
fd906f5
fixed namespace bug
chisarie Oct 22, 2018
2655dfd
working on including filter to find edges of elevation layer
chisarie Oct 22, 2018
addee5c
adding grid_map_filters to the elevation layer to detect edges of the…
chisarie Oct 23, 2018
105f9a5
elevation layer using filter done. Still one small bug with combinati…
chisarie Oct 25, 2018
4ed82cf
tried height treshold and filter treshold together, not good
chisarie Oct 26, 2018
d505d15
halfing the trshold if map filtered
chisarie Oct 26, 2018
afbfd7d
putting the elevation data outside the for loop
chisarie Oct 26, 2018
0a5a674
made filter thread safe
chisarie Oct 29, 2018
c8abffb
combination method and footprint clearing working
chisarie Oct 30, 2018
12d5302
label free space explicitly
chisarie Oct 30, 2018
c05ebbe
add config file for elevation filters
hogabrie Oct 31, 2018
68c83bb
Updated README file
chisarie Nov 5, 2018
88dec09
making changes from pull request feedback
chisarie Nov 6, 2018
b2cfdea
added elevation_filters.yaml in here
chisarie Nov 6, 2018
a0387bc
added param_io, throttled some warnings and now dividing by 2.0 inste…
chisarie Nov 6, 2018
f721df4
moved layer names in yaml file
chisarie Nov 6, 2018
cdc2d1a
added smart pointer
chisarie Nov 6, 2018
3c8ee6a
converted combination_method to enum
chisarie Nov 7, 2018
a15f192
set current_ to false if last received elevation map to old
chisarie Nov 7, 2018
570622c
converted param_io back to standard Ros
chisarie Nov 7, 2018
d927d28
added doxygen comments to header file
chisarie Nov 7, 2018
eb2d3fd
added max_allowed_blind_time, taken from parameter server
chisarie Nov 8, 2018
0e0a86a
last cleaning ups, and also made combination_method case insensitive
chisarie Nov 12, 2018
437f3f6
deleted useless nodehandles and made one as member of the class
chisarie Nov 12, 2018
9c7860b
Merge branch 'feature/filtered_elevation_layer' into test/new_nav
harmishhk Nov 13, 2018
927731a
refactored variable names, include order and doxygen format
chisarie Dec 4, 2018
34c43c8
New software added to the main readme and removed comments in elevati…
chisarie Dec 5, 2018
cb4e2d6
minor readme.md chenges
chisarie Dec 5, 2018
3b3dc76
elevation_layer renamed as elevation_maping_costmap_2d_plugin. Someho…
chisarie Dec 5, 2018
a5b78aa
Merge remote-tracking branch 'origin/test/new_nav' into feature/filte…
chisarie Dec 6, 2018
1833bfc
fixed typo in folder
chisarie Dec 7, 2018
463fa92
formatted code and made warnings throttles at 0.5 hz
chisarie Dec 7, 2018
ae5817c
Update README.md
Mar 11, 2019
0c350f1
Update costmap_plugins.xml
pfankhauser Mar 11, 2019
c8d01e9
All comments start with a capital letter and end with a period.
chisarie Mar 11, 2019
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
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,7 @@

# Sublime
*.sublime*

# VSCode
.vscode
*/build/*
11 changes: 9 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,9 @@ Run the unit tests with
In order to get the Robot-Centric Elevation Mapping to run with your robot, you will need to adapt a few parameters. It is the easiest if duplicate and adapt all the parameter files that you need to change from the `elevation_mapping_demos` package (e.g. the `simple_demo` example). These are specifically the parameter files in `config` and the launch file from the `launch` folder.


## Nodes
## Packages

### Node: elevation_mapping
### elevation_mapping

This is the main Robot-Centric Elevation Mapping node. It uses the distance sensor measurements and the pose and covariance of the robot to generate an elevation map with variance estimates.

Expand Down Expand Up @@ -235,6 +235,11 @@ This is the main Robot-Centric Elevation Mapping node. It uses the distance sens

The data for the sensor noise model.

### elevation_mapping_costmap_2d_plugin

This is a plugin for [costmap_2d] and provides an implementation of a 2d costmap. With the `elevation_mapping_costmap_2d_plugin` package, the generated elevation map can be used to build a costmap_2d to work with the [ROS] [navigation] stack. It takes the elevation map as input and generates a layer of obstacles in the local costmap_2d.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whats the message type of costmap_2d, OccupancyGrid? It would be good to state this.


The layer applies a height and a sharpness filter to the incoming data. The behaviour can be adjusted tuning the parameters `heightThreshold_` and `edgesSharpnessThreshold_`. The former labels as obstacles all data above a certain height, while the latter labels as obstacles data above a certain edge sharpness, where a sharp edge is defined as a sudden change in height; this is used to avoid labeling slopes as obstacle.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

heightThreshold_ is this an absolute height or relative to the neighbor cells?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Absolute

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So is this really sensible when the robot's position drifts over time?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We did't experience that. I mean, even if the robot drifts in map frame, the sensor still outputs proper depth values and elevation mapping is built on those, irrespective of the drift (right? I am not that sure anymore, i should doublecheck)


## Bugs & Feature Requests

Expand All @@ -249,3 +254,5 @@ Please report bugs and request features using the [Issue Tracker](https://github
[tf/tfMessage]: http://docs.ros.org/kinetic/api/tf/html/msg/tfMessage.html
[std_srvs/Empty]: http://docs.ros.org/api/std_srvs/html/srv/Empty.html
[grid_map_msg/GetGridMap]: https://github.com/anybotics/grid_map/blob/master/grid_map_msg/srv/GetGridMap.srv
[costmap_2d]: http://wiki.ros.org/costmap_2d
[navigation]: http://wiki.ros.org/navigation
97 changes: 97 additions & 0 deletions elevation_mapping_costmap_2d_plugin/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
cmake_minimum_required(VERSION 2.8.3)
project(elevation_mapping_costmap_2d_plugin)

## Use C++11
add_definitions(-std=c++11)
## By adding -Wall and -Werror, the compiler does not ignore warnings anymore,
## enforcing cleaner code.
#add_definitions(-std=c++11 -Wall -Werror)

## Find catkin macros and libraries
find_package(catkin REQUIRED COMPONENTS
roscpp
tf
costmap_2d
dynamic_reconfigure
grid_map_ros
filters
)

# Find system libraries
find_package(Boost REQUIRED)

# add dynamic reconfigure configs
generate_dynamic_reconfigure_options(
cfg/ElevationPlugin.cfg
)

###################################
## catkin specific configuration ##
###################################
## The catkin_package macro generates cmake config files for your package
## Declare things to be passed to dependent projects
## INCLUDE_DIRS: uncomment this if your package contains header files
## LIBRARIES: libraries you create in this project that dependent projects also need
## CATKIN_DEPENDS: catkin_packages dependent projects also need
## DEPENDS: system dependencies of this project that dependent projects also need
catkin_package(
INCLUDE_DIRS
include
LIBRARIES
${PROJECT_NAME}
CATKIN_DEPENDS
roscpp
tf
costmap_2d
dynamic_reconfigure
grid_map_ros
filters
DEPENDS
Boost
)

## build ##

###########
## Build ##
###########

## Specify additional locations of header files
## Your package locations should be listed before other locations
include_directories(
include
${catkin_INCLUDE_DIRS}
${Boost_INCLUDE_DIRS}
)

## declare a cpp library
add_library(${PROJECT_NAME}
src/elevation_layer.cpp
)


## cmake target dependencies of the executable/library

# build config headers
add_dependencies(${PROJECT_NAME} elevation_mapping_costmap_2d_plugin_gencfg)

## libraries to link a library or executable target against
target_link_libraries(${PROJECT_NAME}
${catkin_LIBRARIES}
)


## install ##

## executables and/or libraries for installation
install(TARGETS ${PROJECT_NAME}
ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)

## cpp-header files for installation
install(DIRECTORY include/${PROJECT_NAME}/
DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
FILES_MATCHING PATTERN "*.h"
)
9 changes: 9 additions & 0 deletions elevation_mapping_costmap_2d_plugin/cfg/ElevationPlugin.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/usr/bin/env python
PACKAGE = "elevation_mapping_costmap_2d_plugin"

from dynamic_reconfigure.parameter_generator_catkin import ParameterGenerator, bool_t, double_t, int_t

gen = ParameterGenerator()
gen.add("enabled", bool_t, 0, "Whether to apply this plugin or not", True)

exit(gen.generate("elevation_mapping_costmap_2d_plugin", "elevation_mapping_costmap_2d_plugin", "ElevationPlugin"))
10 changes: 10 additions & 0 deletions elevation_mapping_costmap_2d_plugin/config/elevation_filters.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
elevation_filters:
- name: edge_detection # Edge detection on elevation layer with convolution filter.
type: gridMapFilters/SlidingWindowMathExpressionFilter
params:
input_layer: elevation
output_layer: edges
expression: 'sumOfFinites([0,1,0;1,-4,1;0,1,0].*elevation)' # Edge detection.
compute_empty_cells: false
edge_handling: mean
window_size: 3 # Make sure to make this compatible with the kernel matrix.
7 changes: 7 additions & 0 deletions elevation_mapping_costmap_2d_plugin/costmap_plugins.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<class_libraries>
<library path="lib/libelevation_mapping_costmap_2d_plugin">
<class type="elevation_mapping_costmap_2d_plugin::ElevationLayer" base_class_type="costmap_2d::Layer">
<description>Adds elevation map info to costmap_2d.</description>
</class>
</library>
</class_libraries>
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
/*
* elevation_layer.h
*
* Created on: Nov 5, 2018
* Author: Eugenio Chisari
* Institute: ANYbotics
*/

#pragma once

// C++ Libraries.
#include <atomic>
#include <boost/algorithm/string/predicate.hpp>
#include <mutex>

// Ros headers.
#include <dynamic_reconfigure/server.h>
#include <nav_msgs/OccupancyGrid.h>
#include <ros/ros.h>

// Costmap2d headers.
#include <costmap_2d/costmap_layer.h>
#include <costmap_2d/footprint.h>
#include <costmap_2d/layered_costmap.h>
#include <costmap_2d/observation_buffer.h>

// Package related headers.
#include <filters/filter_chain.h>
#include <message_filters/subscriber.h>
#include <grid_map_ros/GridMapRosConverter.hpp>
#include "elevation_mapping_costmap_2d_plugin/ElevationPluginConfig.h"

namespace elevation_mapping_costmap_2d_plugin {

/*!
* Method to update the cost of a portion of map.
*/
enum CombinationMethod { Overwrite, Maximum, Unknown };

/*!
* Converts the string from the yaml file to the proper CombinationMethod enum.
* @param str Input string from yaml file.
* @return CombinationMethod Enum equivalent.
*/
CombinationMethod convertCombinationMethod(const std::string& str);

/*!
* Plug-in layer of a costmap_2d derived from elevation_map information.
*/
class ElevationLayer : public costmap_2d::CostmapLayer {
public:
/*!
* Constructor.
*/
ElevationLayer();

/*!
* Destructor.
*/
~ElevationLayer() override = default;

/*!
* Function called from parent class at initialization.
*/
void onInitialize() override;

/*!
* @brief This is called by the LayeredCostmap to poll this plugin as to how
* much of the costmap it needs to update. Each layer can increase
* the size of this bounds.
*
* For more details, see "Layered Costmaps for Context-Sensitive Navigation",
* by Lu et. Al, IROS 2014.
*/
void updateBounds(double robot_x, double robot_y, double robot_yaw, double* min_x, double* min_y, double* max_x, double* max_y) override;

/*!
* @brief Actually update the underlying costmap, only within the bounds
* calculated during UpdateBounds().
*/
void updateCosts(costmap_2d::Costmap2D& master_grid, int min_i, int min_j, int max_i, int max_j) override;

/*!
* @brief Restart publishers if they've been stopped.
*/
void activate() override;

/*!
* @brief Stop publishers.
*/
void deactivate() override;

/*!
* @brief Deactivate, reset the map and then reactivate
*/
void reset() override;

/*!
* Callback to receive the grid_map msg from elevation_map.
* @param occupancy_grid GridMap msg from elevation_map.
*/
void elevationMapCallback(const grid_map_msgs::GridMapConstPtr& occupancy_grid);

protected:
/*!
* Set up the dynamic reconfigure.
* @param nh
*/
virtual void setupDynamicReconfigure(ros::NodeHandle& nh);

/*!
* Clear obstacles inside the footprint of the robort if the flag footprintClearingEnabled_ is true.
* @param robot_x
* @param robot_y
* @param robot_yaw
* @param min_x
* @param min_y
* @param max_x
* @param max_y
*/
void updateFootprint(double robot_x, double robot_y, double robot_yaw, double* min_x, double* min_y, double* max_x, double* max_y);

//! The global frame for the costmap.
std::string globalFrame_;

//! Dynamic reconfigure server.
std::unique_ptr<dynamic_reconfigure::Server<elevation_mapping_costmap_2d_plugin::ElevationPluginConfig> > dsrv_;

//! Combination method to use to update the cost of a portion of map.
CombinationMethod combinationMethod_;

//! Polygon describing the form of the footprint of the robot.
std::vector<geometry_msgs::Point> transformedFootprint_;

//! Whether the local costmap should move together with the robot.
bool rollingWindow_;

//! Whether to clean the obstacles inside the robot footprint.
bool footprintClearingEnabled_;

//! Whether the elevation_map msg was received.
std::atomic_bool elevationMapReceived_;

//! After this time [seconds] without receiving any elevation_map, the robot will have to stop.
double maxAllowedBlindTime_;

private:
/*!
* Dynamic reconfiguration of the parameters.
* @param config
* @param level
*/
void reconfigureCB(elevation_mapping_costmap_2d_plugin::ElevationPluginConfig& config, uint32_t level);

ros::NodeHandle nodeHandle_;

//! The elevation_map from which to take the information abut the environment (filtered or not).
grid_map::GridMap elevationMap_;

//! lock_guard mutex to make elevation_map setting thread safe.
std::mutex elevationMapMutex_;

//! Ros subscriber to grid_map msgs.
ros::Subscriber elevationSubscriber_;

//! Last time an elevation_map was received.
ros::Time lastElevationMapUpdate_;

//! Height threshold below which nothing is considered obstacle.
double heightThreshold_;

//! Sharpness threshold above which an object is considered an obstacle.
double edgesSharpnessThreshold_;

//! Topic_name of the elevation_map incoming msg.
std::string elevationTopic_;

//! Filter chain used to filter the incoming elevation_map.
filters::FilterChain<grid_map::GridMap> filterChain_;

//! Filter chain parameters name to use.
std::string filterChainParametersName_;

//! Whether filters configuration parameters was found.
bool filtersConfigurationLoaded_;

//! Name of the layer of the incoming map to use.
std::string elevationLayerName_;

//! Name to give to the filtered layer.
std::string edgesLayerName_;
};

} // namespace elevation_mapping_costmap_2d_plugin
23 changes: 23 additions & 0 deletions elevation_mapping_costmap_2d_plugin/package.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?xml version="1.0"?>
<package format="2">
<name>elevation_mapping_costmap_2d_plugin</name>
<version>0.0.2</version>
<description>adds elevation mapping informations to costmap_2d</description>
<author email="echisari@anybotics.com">Eugenio Chisari</author>
<maintainer email="echisari@anybotics.com">Eugenio Chisari</maintainer>
<license>BSD</license>

<buildtool_depend>catkin</buildtool_depend>

<depend>roscpp</depend>
<depend>boost</depend>
<depend>tf</depend>
<depend>costmap_2d</depend>
<depend>dynamic_reconfigure</depend>
<depend>grid_map_ros</depend>
<depend>filters</depend>

<export>
<costmap_2d plugin="${prefix}/costmap_plugins.xml" />
</export>
</package>
Loading