├── .gitignore
├── LICENSE
├── README.md
├── elevation_mapping
├── .gitignore
├── CMakeLists.txt
├── config
│ └── sensor_processors
│ │ ├── aslam.yaml
│ │ ├── fotonic_g45.yaml
│ │ ├── hokuyo_utm-30lx.yaml
│ │ ├── kinect_nguyen_et_al.yaml
│ │ ├── perfect.yaml
│ │ ├── primesense_carmine_109_short_range_datasheet.yaml
│ │ ├── primesense_carmine_109_short_range_uncalibrated.yaml
│ │ ├── realsense_ZR300.yaml
│ │ ├── realsense_d435.yaml
│ │ └── velodyne_HDL-32E.yaml
├── include
│ └── elevation_mapping
│ │ ├── ElevationMap.hpp
│ │ ├── ElevationMapFunctors.hpp
│ │ ├── ElevationMapping.hpp
│ │ ├── PointXYZRGBConfidenceRatio.hpp
│ │ ├── RobotMotionMapUpdater.hpp
│ │ ├── WeightedEmpiricalCumulativeDistributionFunction.hpp
│ │ ├── input_sources
│ │ ├── Input.hpp
│ │ └── InputSourceManager.hpp
│ │ ├── postprocessing
│ │ ├── PostprocessingPipelineFunctor.hpp
│ │ ├── PostprocessingWorker.hpp
│ │ └── PostprocessorPool.hpp
│ │ └── sensor_processors
│ │ ├── LaserSensorProcessor.hpp
│ │ ├── PerfectSensorProcessor.hpp
│ │ ├── SensorProcessorBase.hpp
│ │ ├── StereoSensorProcessor.hpp
│ │ └── StructuredLightSensorProcessor.hpp
├── package.xml
├── src
│ ├── ElevationMap.cpp
│ ├── ElevationMapping.cpp
│ ├── PointXYZRGBConfidenceRatio.cpp
│ ├── RobotMotionMapUpdater.cpp
│ ├── elevation_mapping_node.cpp
│ ├── input_sources
│ │ ├── Input.cpp
│ │ └── InputSourceManager.cpp
│ ├── postprocessing
│ │ ├── PostprocessingPipelineFunctor.cpp
│ │ ├── PostprocessingWorker.cpp
│ │ └── PostprocessorPool.cpp
│ └── sensor_processors
│ │ ├── LaserSensorProcessor.cpp
│ │ ├── PerfectSensorProcessor.cpp
│ │ ├── SensorProcessorBase.cpp
│ │ ├── StereoSensorProcessor.cpp
│ │ └── StructuredLightSensorProcessor.cpp
└── test
│ ├── ElevationMapTest.cpp
│ ├── WeightedEmpiricalCumulativeDistributionFunctionTest.cpp
│ ├── elevation_mapping.test
│ ├── input_sources
│ ├── InputSourcesTest.cpp
│ ├── config
│ │ ├── TestConfigurations.yaml
│ │ └── rosconsole.config
│ ├── input_sources.test
│ └── test_input_sources.cpp
│ ├── postprocessing
│ ├── PostprocessorTest.cpp
│ ├── main.cpp
│ ├── postprocessor.test
│ └── postprocessor_pipeline.yaml
│ └── test_elevation_mapping.cpp
├── elevation_mapping_demos
├── .pydevproject
├── CMakeLists.txt
├── config
│ ├── elevation_maps
│ │ ├── long_range.yaml
│ │ ├── remove_object.yaml
│ │ ├── simple_demo_map.yaml
│ │ └── starleth_map.yaml
│ ├── postprocessing
│ │ └── postprocessor_pipeline.yaml
│ ├── robots
│ │ ├── ground_truth_demo.yaml
│ │ ├── remove_object.yaml
│ │ ├── simple_demo_robot.yaml
│ │ ├── starleth.yaml
│ │ └── waffle_robot.yaml
│ ├── rosconsole.conf
│ └── visualization
│ │ ├── fused.yaml
│ │ └── raw.yaml
├── doc
│ ├── anymal_forrest.jpg
│ ├── anymal_locomotion_planner.jpg
│ ├── anymal_outdoor_stairs.jpg
│ ├── elevation_map.jpg
│ └── starleth_kinect.jpg
├── launch
│ ├── ground_truth_demo.launch
│ ├── realsense_demo.launch
│ ├── simple_demo.launch
│ ├── starleth_kinect_demo.launch
│ ├── turtlesim3_waffle_demo.launch
│ └── visualization.launch
├── package.xml
├── rviz
│ ├── elevation_map_visualization.rviz
│ └── turtlebot3_waffle_demo.rviz
├── scripts
│ └── tf_to_pose_publisher.py
└── test
│ └── empty_test.cpp
└── jenkins-pipeline
/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled Object files
2 | *.slo
3 | *.lo
4 | *.o
5 | *.obj
6 |
7 | # Compiled Dynamic libraries
8 | *.so
9 | *.dylib
10 | *.dll
11 |
12 | # Compiled Static libraries
13 | *.lai
14 | *.la
15 | *.a
16 | *.lib
17 |
18 | # Executables
19 | *.exe
20 | *.out
21 | *.app
22 |
23 | # Eclipse
24 | .cproject
25 | .project
26 | .settings
27 |
28 | # Sublime
29 | *.sublime*
30 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright 2019, ANYbotics AG.
2 |
3 | Redistribution and use in source and binary forms, with or without
4 | modification, are permitted provided that the following conditions
5 | are met:
6 |
7 | 1. Redistributions of source code must retain the above copyright
8 | notice, this list of conditions and the following disclaimer.
9 |
10 | 2. Redistributions in binary form must reproduce the above copyright
11 | notice, this list of conditions and the following disclaimer in
12 | the documentation and/or other materials provided with the
13 | distribution.
14 |
15 | 3. Neither the name of the copyright holder nor the names of its
16 | contributors may be used to endorse or promote products derived
17 | from this software without specific prior written permission.
18 |
19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Robot-Centric Elevation Mapping
2 |
3 | ## Overview
4 |
5 | This is a [ROS] package developed for elevation mapping with a mobile robot. The software is designed for (local) navigation tasks with robots which are equipped with a pose estimation (e.g. IMU & odometry) and a distance sensor (e.g. structured light (Kinect, RealSense), laser range sensor, stereo camera). The provided elevation map is limited around the robot and reflects the pose uncertainty that is aggregated through the motion of the robot (robot-centric mapping). This method is developed to explicitly handle drift of the robot pose estimation.
6 |
7 | This is research code, expect that it changes often and any fitness for a particular purpose is disclaimed.
8 |
9 | The source code is released under a [BSD 3-Clause license](LICENSE).
10 |
11 | **Author: Péter Fankhauser
12 | Co-Author: Maximilian Wulf
13 | Affiliation: [ANYbotics](https://www.anybotics.com/)
14 | Maintainer: Maximilian Wulf, mwulf@anybotics.com
**
15 |
16 | This projected was initially developed at ETH Zurich (Autonomous Systems Lab & Robotic Systems Lab).
17 |
18 | [This work is conducted as part of ANYmal Research, a community to advance legged robotics.](https://www.anymal-research.org/)
19 |
20 |
21 |
22 |
23 | Videos of the elevation mapping software in use:
24 |
25 |
26 |
27 |
28 |
29 |
30 | ## Citing
31 |
32 | The robot-centric elevation mapping methods used in this software are described in the following paper (available [here](https://doi.org/10.3929/ethz-b-000272110)). If you use this work in an academic context, please cite the following publication(s):
33 |
34 | * > P. Fankhauser, M. Bloesch, and M. Hutter,
35 | > **"Probabilistic Terrain Mapping for Mobile Robots with Uncertain Localization"**,
36 | > in IEEE Robotics and Automation Letters (RA-L), vol. 3, no. 4, pp. 3019–3026, 2018. ([PDF](http://dx.doi.org/10.1109/LRA.2018.2849506))
37 |
38 | @article{Fankhauser2018ProbabilisticTerrainMapping,
39 | author = {Fankhauser, P{\'{e}}ter and Bloesch, Michael and Hutter, Marco},
40 | doi = {10.1109/LRA.2018.2849506},
41 | title = {Probabilistic Terrain Mapping for Mobile Robots with Uncertain Localization},
42 | journal = {IEEE Robotics and Automation Letters (RA-L)},
43 | volume = {3},
44 | number = {4},
45 | pages = {3019--3026},
46 | year = {2018}
47 | }
48 |
49 | * > P. Fankhauser, M. Bloesch, C. Gehring, M. Hutter, and R. Siegwart,
50 | > **"Robot-Centric Elevation Mapping with Uncertainty Estimates"**,
51 | > in International Conference on Climbing and Walking Robots (CLAWAR), 2014. ([PDF](http://dx.doi.org/10.3929/ethz-a-010173654))
52 |
53 | @inproceedings{Fankhauser2014RobotCentricElevationMapping,
54 | author = {Fankhauser, P\'{e}ter and Bloesch, Michael and Gehring, Christian and Hutter, Marco and Siegwart, Roland},
55 | title = {Robot-Centric Elevation Mapping with Uncertainty Estimates},
56 | booktitle = {International Conference on Climbing and Walking Robots (CLAWAR)},
57 | year = {2014}
58 | }
59 |
60 | ## Installation
61 |
62 | ### Dependencies
63 |
64 | This software is built on the Robotic Operating System ([ROS]), which needs to be [installed](http://wiki.ros.org) first. Additionally, the Robot-Centric Elevation Mapping depends on following software:
65 |
66 | - [Grid Map](https://github.com/anybotics/grid_map) (grid map library for mobile robots)
67 | - [kindr](http://github.com/anybotics/kindr) (kinematics and dynamics library for robotics),
68 | - [kindr_ros](https://github.com/anybotics/kindr_ros) (ROS wrapper for kindr),
69 | - [Point Cloud Library (PCL)](http://pointclouds.org/) (point cloud processing),
70 | - [Eigen](http://eigen.tuxfamily.org) (linear algebra library).
71 |
72 |
73 | ### Building
74 |
75 | In order to install the Robot-Centric Elevation Mapping, clone the latest version from this repository into your catkin workspace and compile the package using ROS.
76 |
77 | cd catkin_workspace/src
78 | git clone https://github.com/anybotics/elevation_mapping.git
79 | cd ../
80 | catkin config --cmake-args -DCMAKE_BUILD_TYPE=Release
81 | catkin build
82 |
83 |
84 | ### Unit Tests
85 |
86 | Build tests with
87 |
88 | roscd elevation_mapping
89 | catkin build --catkin-make-args run_tests -- --this
90 |
91 | Run the tests with
92 |
93 | rostest elevation_mapping elevation_mapping.test -t
94 |
95 |
96 | ## Basic Usage
97 |
98 | 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.
99 |
100 | ### TurtleBot3 Waffle Simulation
101 |
102 | A running example is provided, making use of the Turtlebot3 simulation environment. This example can be used to test elevation mapping, as a starting point for further integration.
103 |
104 | To start with, the Turtlebot3 simulation dependencies need to be installed:
105 |
106 | sudo apt install ros-melodic-turtlebot3*
107 |
108 | The elevation mapping demo together with the turtlebot3 simulation can be started with
109 |
110 | roslaunch elevation_mapping_demos turtlesim3_waffle_demo.launch
111 |
112 | To control the robot with a keyboard, a new terminal window needs to be opened (remember to source your ROS environment). Then run
113 |
114 | export TURTLEBOT3_MODEL=waffle
115 | roslaunch turtlebot3_teleop turtlebot3_teleop_key.launch
116 |
117 | Velocity inputs can be sent to the robot by pressing the keys `a`, `w`,`d`, `x`. To stop the robot completely, press `s`.
118 |
119 | ## Nodes
120 |
121 | ### Node: elevation_mapping
122 |
123 | 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.
124 |
125 |
126 | #### Subscribed Topics
127 |
128 | * **`/points`** ([sensor_msgs/PointCloud2])
129 |
130 | The distance measurements.
131 |
132 | * **`/pose`** ([geometry_msgs/PoseWithCovarianceStamped])
133 |
134 | The robot pose and covariance.
135 |
136 | * **`/tf`** ([tf/tfMessage])
137 |
138 | The transformation tree.
139 |
140 |
141 | #### Published Topics
142 |
143 | * **`elevation_map`** ([grid_map_msgs/GridMap])
144 |
145 | The entire (fused) elevation map. It is published periodically (see `fused_map_publishing_rate` parameter) or after the `trigger_fusion` service is called.
146 |
147 | * **`elevation_map_raw`** ([grid_map_msgs/GridMap])
148 |
149 | The entire (raw) elevation map before the fusion step.
150 |
151 |
152 | #### Services
153 |
154 | * **`trigger_fusion`** ([std_srvs/Empty])
155 |
156 | Trigger the fusing process for the entire elevation map and publish it. For example, you can trigger the map fusion step from the console with
157 |
158 | rosservice call /elevation_mapping/trigger_fusion
159 |
160 | * **`get_submap`** ([grid_map_msgs/GetGridMap])
161 |
162 | Get a fused elevation submap for a requested position and size. For example, you can get the fused elevation submap at position (-0.5, 0.0) and size (0.5, 1.2) described in the odom frame and save it to a text file form the console with
163 |
164 | rosservice call -- /elevation_mapping/get_submap odom -0.5 0.0 0.5 1.2 []
165 |
166 | * **`get_raw_submap`** ([grid_map_msgs/GetGridMap])
167 |
168 | Get a raw elevation submap for a requested position and size. For example, you can get the raw elevation submap at position (-0.5, 0.0) and size (0.5, 1.2) described in the odom frame and save it to a text file form the console with
169 |
170 | rosservice call -- /elevation_mapping/get_raw_submap odom -0.5 0.0 0.5 1.2 []
171 |
172 | * **`clear_map`** ([std_srvs/Empty])
173 |
174 | Initiates clearing of the entire map for resetting purposes. Trigger the map clearing with
175 |
176 | rosservice call /elevation_mapping/clear_map
177 |
178 | * **`masked_replace`** ([grid_map_msgs/SetGridMap])
179 |
180 | Allows for setting the individual layers of the elevation map through a service call. The layer mask can be used to only set certain cells and not the entire map. Cells containing NAN in the mask are not set, all the others are set. If the layer mask is not supplied, the entire map will be set in the intersection of both maps. The provided map can be of different size and position than the map that will be altered. An example service call to set some cells marked with a mask in the elevation layer to 0.5 is
181 |
182 | rosservice call /elevation_mapping/masked_replace "map:
183 | info:
184 | header:
185 | seq: 3
186 | stamp: {secs: 3, nsecs: 80000000}
187 | frame_id: 'odom'
188 | resolution: 0.1
189 | length_x: 0.3
190 | length_y: 0.3
191 | pose:
192 | position: {x: 5.0, y: 0.0, z: 0.0}
193 | orientation: {x: 0.0, y: 0.0, z: 0.0, w: 0.0}
194 | layers: [elevation,mask]
195 | basic_layers: [elevation]
196 | data:
197 | - layout:
198 | dim:
199 | - {label: 'column_index', size: 3, stride: 9}
200 | - {label: 'row_index', size: 3, stride: 3}
201 | data_offset: 0
202 | data: [0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5]
203 | - layout:
204 | dim:
205 | - {label: 'column_index', size: 3, stride: 9}
206 | - {label: 'row_index', size: 3, stride: 3}
207 | data_offset: 0
208 | data: [0, 0, 0, .NAN, .NAN, .NAN, 0, 0, 0]
209 | outer_start_index: 0
210 | inner_start_index: 0"
211 |
212 | * **`save_map`** ([grid_map_msgs/ProcessFile])
213 |
214 | Saves the current fused grid map and raw grid map to rosbag files. Field `topic_name` must be a base name, i.e. no leading slash character (/). If field `topic_name` is empty, then `elevation_map` is used per default. Example with default topic name
215 |
216 | rosservice call /elevation_mapping/save_map "file_path: '/home/integration/elevation_map.bag' topic_name: ''"
217 |
218 | * **`load_map`** ([grid_map_msgs/ProcessFile])
219 |
220 | Loads the fused grid map and raw grid map from rosbag files. Field `topic_name` must be a base name, i.e. no leading slash character (/). If field `topic_name` is empty, then `elevation_map` is used per default. Example with default topic name
221 |
222 | rosservice call /elevation_mapping/load_map "file_path: '/home/integration/elevation_map.bag' topic_name: ''"
223 |
224 | * **`disable_updates`** ([std_srvs/Empty])
225 |
226 | Stops updating the elevation map with sensor input. Trigger the update stopping with
227 |
228 | rosservice call /elevation_mapping/disable_updates {}
229 |
230 | * **`enable_updates`** ([std_srvs/Empty])
231 |
232 | Start updating the elevation map with sensor input. Trigger the update starting with
233 |
234 | rosservice call /elevation_mapping/enable_updates {}
235 |
236 | #### Parameters
237 |
238 | * **`DEPRECATED point_cloud_topic`** (string, default: "/points")
239 |
240 | The name of the distance measurements topic. Use input_sources instead.
241 |
242 | * **`input_sources`** (list of input sources, default: none)
243 |
244 | Here you specify your inputs to elevation mapping, currently "pointcloud" inputs are supported.
245 |
246 | Example configuration:
247 | ```yaml
248 | input_sources:
249 | front: # A name to identify the input source
250 | type: pointcloud # Supported types: pointcloud
251 | topic: /lidar_front/depth/points
252 | queue_size: 1
253 | publish_on_update: true # Wheter to publish the elevation map after a callback from this source.
254 | rear:
255 | type: pointcloud
256 | topic: /lidar_rear/depth/points
257 | queue_size: 5
258 | publish_on_update: false
259 | ```
260 | No input sources can be configured with an empty array:
261 | ```yaml
262 | input_sources: []
263 | ```
264 | * **`robot_pose_topic`** (string, default: "/robot_state/pose")
265 |
266 | The name of the robot pose and covariance topic.
267 |
268 | * **`base_frame_id`** (string, default: "/robot")
269 |
270 | The id of the robot base tf frame.
271 |
272 | * **`map_frame_id`** (string, default: "/map")
273 |
274 | The id of the tf frame of the elevation map.
275 |
276 | * **`track_point_frame_id`** (string, default: "/robot")
277 |
278 | The elevation map is moved along with the robot following a *track point*. This is the id of the tf frame in which the track point is defined.
279 |
280 | * **`track_point_x`**, **`track_point_y`**, **`track_point_z`** (double, default: 0.0, 0.0, 0.0)
281 |
282 | The elevation map is moved along with the robot following a *track point*. This is the position of the track point in the `track_point_frame_id`.
283 |
284 | * **`robot_pose_cache_size`** (int, default: 200, min: 0)
285 |
286 | The size of the robot pose cache.
287 |
288 | * **`min_update_rate`** (double, default: 2.0)
289 |
290 | The mininum update rate (in Hz) at which the elevation map is updated either from new measurements or the robot pose estimates.
291 |
292 | * **`fused_map_publishing_rate`** (double, default: 1.0)
293 |
294 | The rate for publishing the entire (fused) elevation map.
295 |
296 | * **`relocate_rate`** (double, default: 3.0)
297 |
298 | The rate (in Hz) at which the elevation map is checked for relocation following the tracking point.
299 |
300 | * **`length_in_x`**, **`length_in_y`** (double, default: 1.5, min: 0.0)
301 |
302 | The size (in m) of the elevation map.
303 |
304 | * **`position_x`**, **`position_y`** (double, default: 0.0)
305 |
306 | The position of the elevation map center, in the elevation map frame. This parameter sets the planar position offsets between the generated elevation map and the frame in which it is published (`map_frame_id`). It is only useful if no `track_point_frame_id` parameter is used.
307 |
308 | * **`resolution`** (double, default: 0.01, min: 0.0)
309 |
310 | The resolution (cell size in m/cell) of the elevation map.
311 |
312 | * **`min_variance`**, **`max_variance`** (double, default: 9.0e-6, 0.01)
313 |
314 | The minimum and maximum values for the elevation map variance data.
315 |
316 | * **`mahalanobis_distance_threshold`** (double, default: 2.5)
317 |
318 | Each cell in the elevation map has an uncertainty for its height value. Depending on the Mahalonobis distance of the existing height distribution and the new measurements, the incoming data is fused with the existing estimate, overwritten, or ignored. This parameter determines the threshold on the Mahalanobis distance which determines how the incoming measurements are processed.
319 |
320 | * **`sensor_processor/ignore_points_above`** (double, default: inf)
321 | A hard threshold on the height of points introduced by the depth sensor. Points with a height over this threshold will not be considered valid during the data collection step.
322 |
323 | * **`sensor_processor/ignore_points_below`** (double, default: -inf)
324 | A hard threshold on the height of points introduced by the depth sensor. Points with a height below this threshold will not be considered valid during the data collection step.
325 |
326 | * **`multi_height_noise`** (double, default: 9.0e-7)
327 |
328 | Noise added to measurements that are higher than the current elevation map at that particular position. This noise-adding process is only performed if a point falls over the Mahalanobis distance threshold. A higher value is useful to adapt faster to dynamic environments (e.g., moving objects), but might cause more noise in the height estimation.
329 |
330 | * **`min_horizontal_variance`**, **`max_horizontal_variance`** (double, default: pow(resolution / 2.0, 2), 0.5)
331 |
332 | The minimum and maximum values for the elevation map horizontal variance data.
333 |
334 | * **`enable_visibility_cleanup`** (bool, default: true)
335 |
336 | Enable/disable a separate thread that removes elements from the map which are not visible anymore, by means of ray-tracing, originating from the sensor frame.
337 |
338 | * **`visibility_cleanup_rate`** (double, default: 1.0)
339 |
340 | The rate (in Hz) at which the visibility clean-up is performed.
341 |
342 | * **`enable_continuous_cleanup`** (bool, default: false)
343 |
344 | Enable/disable a continuous clean-up of the elevation map. If enabled, on arrival of each new sensor data the elevation map will be cleared and filled up only with the latest data from the sensor. When continuous clean-up is enabled, visibility clean-up will automatically be disabled since it is not needed in this case.
345 |
346 | * **`num_callback_threads`** (int, default: 1, min: 1)
347 | The number of threads to use for processing callbacks. More threads results in higher throughput, at cost of more resource usage.
348 |
349 | * **`postprocessor_pipeline_name`** (string, default: postprocessor_pipeline)
350 |
351 | The name of the pipeline to execute for postprocessing. It expects a pipeline configuration to be loaded in the private namespace of the node under this name.
352 | E.g.:
353 | ```
354 |
355 | ...
356 |
357 |
358 | ```
359 | A pipeline is a grid_map_filter chain, see grid_map_demos/filters_demo.yaml and [ros / filters](http://wiki.ros.org/filters) for more information.
360 |
361 | * **`postprocessor_num_threads`** (int, default: 1, min: 1)
362 |
363 | The number of threads to use for asynchronous postprocessing. More threads results in higher throughput, at cost of more resource usage.
364 |
365 | * **`scanning_duration`** (double, default: 1.0)
366 |
367 | The sensor's scanning duration (in s) which is used for the visibility cleanup. Set this roughly to the duration it takes between two consecutive full scans (e.g. 0.033 for a ToF camera with 30 Hz, or 3 s for a rotating laser scanner). Depending on how dense or sparse your scans are, increase or reduce the scanning duration. Smaller values lead to faster dynamic object removal and bigger values help to reduce faulty map cleanups.
368 |
369 | * **`sensor_cutoff_min_depth`**, **`sensor_cutoff_max_depth`** (double, default: 0.2, 2.0)
370 |
371 | The minimum and maximum values for the length of the distance sensor measurements. Measurements outside this interval are ignored.
372 |
373 | * **`sensor_model_normal_factor_a`**, **`sensor_model_normal_factor_b`**, **`sensor_model_normal_factor_c`**, **`sensor_model_lateral_factor`** (double)
374 |
375 | The data for the sensor noise model.
376 |
377 | ## Changelog
378 |
379 | See [Changelog]
380 |
381 | ## Bugs & Feature Requests
382 |
383 | Please report bugs and request features using the [Issue Tracker](https://github.com/anybotics/elevation_mapping/issues).
384 |
385 | [Changelog]: CHANGELOG.rst
386 | [ROS]: http://www.ros.org
387 | [rviz]: http://wiki.ros.org/rviz
388 | [grid_map_msgs/GridMap]: https://github.com/anybotics/grid_map/blob/master/grid_map_msgs/msg/GridMap.msg
389 | [sensor_msgs/PointCloud2]: http://docs.ros.org/api/sensor_msgs/html/msg/PointCloud2.html
390 | [geometry_msgs/PoseWithCovarianceStamped]: http://docs.ros.org/api/geometry_msgs/html/msg/PoseWithCovarianceStamped.html
391 | [tf/tfMessage]: http://docs.ros.org/kinetic/api/tf/html/msg/tfMessage.html
392 | [std_srvs/Empty]: http://docs.ros.org/api/std_srvs/html/srv/Empty.html
393 | [grid_map_msgs/GetGridMap]: https://github.com/anybotics/grid_map/blob/master/grid_map_msgs/srv/GetGridMap.srv
394 | [grid_map_msgs/ProcessFile]: https://github.com/ANYbotics/grid_map/blob/master/grid_map_msgs/srv/ProcessFile.srv
395 |
--------------------------------------------------------------------------------
/elevation_mapping/.gitignore:
--------------------------------------------------------------------------------
1 | *.pydevproject
2 |
--------------------------------------------------------------------------------
/elevation_mapping/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.5.1)
2 | project(elevation_mapping)
3 |
4 | set(CMAKE_CXX_STANDARD 14)
5 | add_compile_options(-Wall -Wextra -Wpedantic)
6 |
7 | set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
8 |
9 | set(
10 | CATKIN_PACKAGE_DEPENDENCIES
11 | eigen_conversions
12 | grid_map_core
13 | grid_map_ros
14 | grid_map_msgs
15 | kindr
16 | kindr_ros
17 | message_filters
18 | pcl_ros
19 | roscpp
20 | sensor_msgs
21 | std_msgs
22 | tf
23 | tf_conversions
24 | )
25 |
26 | find_package(catkin REQUIRED
27 | COMPONENTS
28 | ${CATKIN_PACKAGE_DEPENDENCIES}
29 | )
30 |
31 | find_package(Boost REQUIRED COMPONENTS system)
32 | find_package(Eigen3 REQUIRED)
33 |
34 | catkin_package(
35 | INCLUDE_DIRS
36 | include
37 | ${Eigen_INCLUDE_DIRS}
38 | LIBRARIES
39 | ${PROJECT_NAME}_library
40 | CATKIN_DEPENDS
41 | ${CATKIN_PACKAGE_DEPENDENCIES}
42 | DEPENDS
43 | Boost
44 | )
45 |
46 | include_directories(
47 | include
48 | SYSTEM
49 | ${Boost_INCLUDE_DIRS}
50 | ${catkin_INCLUDE_DIRS}
51 | ${Eigen_INCLUDE_DIRS}
52 | )
53 |
54 | ###########
55 | # Library #
56 | ###########
57 |
58 | # Our custom pcl type with precompiled template instantiations.
59 | add_library(${PROJECT_NAME}_pcl_types
60 | src/PointXYZRGBConfidenceRatio.cpp
61 | )
62 | target_link_libraries(${PROJECT_NAME}_pcl_types
63 | ${catkin_LIBRARIES}
64 | )
65 |
66 | add_library(${PROJECT_NAME}_library
67 | src/ElevationMapping.cpp
68 | src/ElevationMap.cpp
69 | src/input_sources/Input.cpp
70 | src/input_sources/InputSourceManager.cpp
71 | src/postprocessing/PostprocessorPool.cpp
72 | src/postprocessing/PostprocessingWorker.cpp
73 | src/postprocessing/PostprocessingPipelineFunctor.cpp
74 | src/RobotMotionMapUpdater.cpp
75 | src/sensor_processors/SensorProcessorBase.cpp
76 | src/sensor_processors/StructuredLightSensorProcessor.cpp
77 | src/sensor_processors/StereoSensorProcessor.cpp
78 | src/sensor_processors/LaserSensorProcessor.cpp
79 | src/sensor_processors/PerfectSensorProcessor.cpp
80 | )
81 |
82 | target_link_libraries(${PROJECT_NAME}_library
83 | ${catkin_LIBRARIES}
84 | ${PROJECT_NAME}_pcl_types
85 | pthread
86 | )
87 |
88 | ##############
89 | # Executable #
90 | ##############
91 |
92 | add_executable(${PROJECT_NAME}
93 | src/elevation_mapping_node.cpp
94 | )
95 |
96 | target_link_libraries(${PROJECT_NAME}
97 | ${PROJECT_NAME}_library
98 | )
99 |
100 | #############
101 | ## Install ##
102 | #############
103 |
104 | install(
105 | TARGETS
106 | ${PROJECT_NAME}
107 | ${PROJECT_NAME}_pcl_types
108 | ${PROJECT_NAME}_library
109 | ARCHIVE DESTINATION
110 | ${CATKIN_PACKAGE_LIB_DESTINATION}
111 | LIBRARY DESTINATION
112 | ${CATKIN_PACKAGE_LIB_DESTINATION}
113 | RUNTIME DESTINATION
114 | ${CATKIN_PACKAGE_BIN_DESTINATION}
115 | )
116 |
117 | install(
118 | DIRECTORY
119 | include/${PROJECT_NAME}/
120 | DESTINATION
121 | ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
122 | )
123 |
124 | install(
125 | DIRECTORY
126 | config
127 | DESTINATION
128 | ${CATKIN_PACKAGE_SHARE_DESTINATION}
129 | )
130 |
131 | ##########
132 | ## Test ##
133 | ##########
134 |
135 | if(CATKIN_ENABLE_TESTING)
136 | find_package(catkin REQUIRED
137 | COMPONENTS
138 | ${CATKIN_PACKAGE_DEPENDENCIES}
139 | grid_map_filters
140 | roslaunch
141 | rostest
142 | )
143 |
144 | # Cummulative distribution
145 | catkin_add_gtest(test_${PROJECT_NAME}_cumulative_distribution
146 | test/ElevationMapTest.cpp
147 | test/test_elevation_mapping.cpp
148 | test/WeightedEmpiricalCumulativeDistributionFunctionTest.cpp
149 | )
150 |
151 | target_link_libraries(test_${PROJECT_NAME}_cumulative_distribution
152 | ${PROJECT_NAME}_library
153 | )
154 |
155 | target_include_directories(test_${PROJECT_NAME}_cumulative_distribution
156 | PRIVATE
157 | include
158 | )
159 |
160 | target_include_directories(test_${PROJECT_NAME}_cumulative_distribution
161 | SYSTEM PUBLIC
162 | ${catkin_INCLUDE_DIRS}
163 | )
164 |
165 | # Input sources
166 | add_rostest_gtest(test_${PROJECT_NAME}_input_sources
167 | test/input_sources/input_sources.test
168 | test/input_sources/test_input_sources.cpp
169 | test/input_sources/InputSourcesTest.cpp
170 | )
171 |
172 | target_link_libraries(test_${PROJECT_NAME}_input_sources
173 | ${PROJECT_NAME}_library
174 | )
175 |
176 | target_include_directories(test_${PROJECT_NAME}_input_sources
177 | PRIVATE
178 | include
179 | )
180 |
181 | target_include_directories(test_${PROJECT_NAME}_input_sources SYSTEM PUBLIC
182 | ${Boost_INCLUDE_DIRS}
183 | ${catkin_INCLUDE_DIRS}
184 | ${Eigen_INCLUDE_DIRS}
185 | )
186 |
187 | # Postprocessor
188 | add_rostest_gtest(test_${PROJECT_NAME}_postprocessor
189 | test/postprocessing/postprocessor.test
190 | test/postprocessing/main.cpp
191 | test/postprocessing/PostprocessorTest.cpp
192 | )
193 |
194 | target_include_directories(test_${PROJECT_NAME}_postprocessor PRIVATE
195 | include
196 | )
197 |
198 | target_include_directories(test_${PROJECT_NAME}_postprocessor SYSTEM PUBLIC
199 | ${catkin_INCLUDE_DIRS}
200 | )
201 |
202 | target_link_libraries(test_${PROJECT_NAME}_postprocessor
203 | ${GTEST_LIBRARIES}
204 | ${PROJECT_NAME}_library
205 | ${catkin_LIBRARIES}
206 | )
207 |
208 | find_package(cmake_code_coverage QUIET)
209 | if(cmake_code_coverage_FOUND)
210 | add_gtest_coverage(TEST_BUILD_TARGETS
211 | test_${PROJECT_NAME}_cumulative_distribution
212 | )
213 | add_rostest_coverage(TEST_BUILD_TARGETS
214 | test_${PROJECT_NAME}_input_sources
215 | )
216 | add_rostest_coverage(TEST_BUILD_TARGETS
217 | test_${PROJECT_NAME}_postprocessor
218 | )
219 | endif()
220 | endif()
221 |
222 | ###########
223 | ## Clang ##
224 | ###########
225 |
226 | find_package(cmake_clang_tools QUIET)
227 | if(cmake_clang_tools_FOUND)
228 | add_default_clang_tooling()
229 | endif(cmake_clang_tools_FOUND)
230 |
--------------------------------------------------------------------------------
/elevation_mapping/config/sensor_processors/aslam.yaml:
--------------------------------------------------------------------------------
1 | # ASLAM Stereo camera:
2 | # "Localization and Path Planning of a Climbing Robot for Corrosion Monitoring",
3 | # Hannes Keller, Semester Project, ETH Zurich, 2014.
4 |
5 | sensor_processor/type: stereo
6 | sensor_processor/p_1: 0.03287
7 | sensor_processor/p_2: -0.0001276
8 | sensor_processor/p_3: 0.4850
9 | sensor_processor/p_4: 399.1046
10 | sensor_processor/p_5: 0.000006735
11 | sensor_processor/lateral_factor: 0.001376915
12 | sensor_processor/depth_to_disparity_factor: 47.3
13 |
--------------------------------------------------------------------------------
/elevation_mapping/config/sensor_processors/fotonic_g45.yaml:
--------------------------------------------------------------------------------
1 | # Written by Lefteris kotsonis.
2 | # Modeling Fotonic G45 Sensor Noise for Improved 3D Reconstruction and Tracking.
3 | sensor_processor/type: structured_light
4 | sensor_processor/cutoff_min_depth: 0.5
5 | sensor_processor/cutoff_max_depth: 3.25
6 | sensor_processor/normal_factor_a: 0.0263
7 | sensor_processor/normal_factor_b: 0
8 | sensor_processor/normal_factor_c: 0
9 | sensor_processor/normal_factor_d: 0
10 | sensor_processor/normal_factor_e: 1
11 | sensor_processor/lateral_factor: 0.003163
12 |
--------------------------------------------------------------------------------
/elevation_mapping/config/sensor_processors/hokuyo_utm-30lx.yaml:
--------------------------------------------------------------------------------
1 | # Hokuyo UTM-30LX laser scanner
2 | # Pomerleau, F.; Breitenmoser, A; Ming Liu; Colas, F.; Siegwart, R.,
3 | # "Noise characterization of depth sensors for surface inspections,"
4 | # International Conference on Applied Robotics for the Power Industry (CARPI), 2012.
5 |
6 | sensor_processor/type: laser
7 | sensor_processor/min_radius: 0.018
8 | sensor_processor/beam_angle: 0.0006
9 | sensor_processor/beam_constant: 0.0015
10 |
--------------------------------------------------------------------------------
/elevation_mapping/config/sensor_processors/kinect_nguyen_et_al.yaml:
--------------------------------------------------------------------------------
1 | # Kinect (short-range mode) model taken from:
2 | # Nguyen, C. V., Izadi, S., & Lovell, D. (2012).
3 | # Modeling Kinect Sensor Noise for Improved 3D Reconstruction and Tracking.
4 | sensor_processor/type: structured_light
5 | sensor_processor/cutoff_min_depth: 0.35
6 | sensor_processor/cutoff_max_depth: 3.0
7 | sensor_processor/normal_factor_a: 0.0012
8 | sensor_processor/normal_factor_b: 0.0019
9 | sensor_processor/normal_factor_c: 0.4
10 | sensor_processor/normal_factor_d: 0
11 | sensor_processor/normal_factor_e: 1
12 | sensor_processor/lateral_factor: 0.001376915 # for theta = 45°: 0.835 * 0.00780 [mm/px] / 4.73 [mm]
13 |
--------------------------------------------------------------------------------
/elevation_mapping/config/sensor_processors/perfect.yaml:
--------------------------------------------------------------------------------
1 | # Noiseless ground truth measurements
2 | sensor_processor/type: perfect
3 |
--------------------------------------------------------------------------------
/elevation_mapping/config/sensor_processors/primesense_carmine_109_short_range_datasheet.yaml:
--------------------------------------------------------------------------------
1 | # Approximation of datasheet for Carmine 1.09 from:
2 | # http://www.openni.org/rd1-09-specifications/
3 | # Coefficients for normal model computed with least squares regression.
4 | # Coefficients for lateral model taken from kinect_nguyen_et_al.yaml
5 | sensor_processor/type: structured_light
6 | sensor_processor/cutoff_min_depth: 0.2
7 | sensor_processor/cutoff_max_depth: 2.0
8 | sensor_processor/factor_a: 0.000181
9 | sensor_processor/factor_b: 0.00166
10 | sensor_processor/factor_c: 0.1
11 | sensor_processor/lateral_factor: 0.001376915
12 |
--------------------------------------------------------------------------------
/elevation_mapping/config/sensor_processors/primesense_carmine_109_short_range_uncalibrated.yaml:
--------------------------------------------------------------------------------
1 | # Manual tuned for uncalibrated PrimeSense Carmine 1.09.
2 | # Also includes uncertainties with non perpedicular surfaces and
3 | # biases/warp at further distances.
4 | # Coefficients for lateral model taken from kinect_nguyen_et_al.yaml
5 | sensor_processor/type: structured_light
6 | sensor_processor/cutoff_min_depth: 0.2
7 | sensor_processor/cutoff_max_depth: 2.0
8 | sensor_processor/normal_factor_a: 0.003
9 | sensor_processor/normal_factor_b: 0.015
10 | sensor_processor/normal_factor_c: 0.25
11 | sensor_processor/lateral_factor: 0.04
12 |
--------------------------------------------------------------------------------
/elevation_mapping/config/sensor_processors/realsense_ZR300.yaml:
--------------------------------------------------------------------------------
1 | # Written by Takahiro Miki.
2 | # Modeling Realsense ZR300 Sensor Noise for Improved 3D Reconstruction and Tracking.
3 | sensor_processor/type: structured_light
4 | sensor_processor/cutoff_min_depth: 0.35
5 | sensor_processor/cutoff_max_depth: 3.0
6 | sensor_processor/normal_factor_a: 0.00241809
7 | sensor_processor/normal_factor_b: 0.00662547
8 | sensor_processor/normal_factor_c: 0.77199589
9 | sensor_processor/normal_factor_d: 0
10 | sensor_processor/normal_factor_e: 1
11 | sensor_processor/lateral_factor: 0.00220941
12 |
--------------------------------------------------------------------------------
/elevation_mapping/config/sensor_processors/realsense_d435.yaml:
--------------------------------------------------------------------------------
1 | # Written by Lefteris kotsonis.
2 | # Modeling Realsense D435 Sensor Noise for Improved 3D Reconstruction and Tracking.
3 | sensor_processor/type: structured_light
4 | sensor_processor/cutoff_min_depth: 0.2
5 | sensor_processor/cutoff_max_depth: 3.25
6 | sensor_processor/normal_factor_a: 0.000611
7 | sensor_processor/normal_factor_b: 0.003587
8 | sensor_processor/normal_factor_c: 0.3515
9 | sensor_processor/normal_factor_d: 0
10 | sensor_processor/normal_factor_e: 1
11 | sensor_processor/lateral_factor: 0.01576
12 |
--------------------------------------------------------------------------------
/elevation_mapping/config/sensor_processors/velodyne_HDL-32E.yaml:
--------------------------------------------------------------------------------
1 | # Velodyne_HDL-32E
2 | # TODO
3 |
4 | sensor_processor/type: laser
5 | sensor_processor/min_radius: 0.018
6 | sensor_processor/beam_angle: 0.0006
7 | sensor_processor/beam_constant: 0.0015
8 |
--------------------------------------------------------------------------------
/elevation_mapping/include/elevation_mapping/ElevationMap.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | * ElevationMap.hpp
3 | *
4 | * Created on: Feb 5, 2014
5 | * Author: Péter Fankhauser
6 | * Institute: ETH Zurich, ANYbotics
7 | */
8 |
9 | #pragma once
10 |
11 | // Grid Map
12 | #include
13 |
14 | // Eigen
15 | #include
16 | #include
17 |
18 | // Kindr
19 | #include
20 |
21 | // Boost
22 | #include
23 |
24 | // ROS
25 | #include
26 |
27 | // Elevation Mapping
28 | #include "elevation_mapping/PointXYZRGBConfidenceRatio.hpp"
29 | #include "elevation_mapping/postprocessing/PostprocessorPool.hpp"
30 |
31 | namespace elevation_mapping {
32 |
33 | /*!
34 | * Elevation map stored as grid map handling elevation height, variance, color etc.
35 | */
36 | class ElevationMap {
37 | public:
38 | /*!
39 | * Constructor.
40 | */
41 | explicit ElevationMap(ros::NodeHandle nodeHandle);
42 |
43 | /*!
44 | * Destructor.
45 | */
46 | virtual ~ElevationMap();
47 |
48 | /*!
49 | * Set the geometry of the elevation map. Clears all the data.
50 | * @param length the side lengths in x, and y-direction of the elevation map [m].
51 | * @param resolution the cell size in [m/cell].
52 | * @param position the 2d position of the elevation map in the elevation map frame [m].
53 | * @return true if successful.
54 | */
55 | void setGeometry(const grid_map::Length& length, const double& resolution, const grid_map::Position& position);
56 |
57 | /*!
58 | * Add new measurements to the elevation map.
59 | * @param pointCloud the point cloud data.
60 | * @param pointCloudVariances the corresponding variances of the point cloud data.
61 | * @param timeStamp the time of the input point cloud.
62 | * @param transformationSensorToMap
63 | * @return true if successful.
64 | */
65 | bool add(const PointCloudType::Ptr pointCloud, Eigen::VectorXf& pointCloudVariances, const ros::Time& timeStamp,
66 | const Eigen::Affine3d& transformationSensorToMap);
67 |
68 | /*!
69 | * Update the elevation map with variance update data.
70 | * @param varianceUpdate the variance update in vertical direction.
71 | * @param horizontalVarianceUpdateX the variance update in horizontal x-direction.
72 | * @param horizontalVarianceUpdateY the variance update in horizontal y-direction.
73 | * @param horizontalVarianceUpdateXY the correlated variance update in horizontal xy-direction.
74 | * @param time the time of the update.
75 | * @return true if successful.
76 | */
77 | bool update(const grid_map::Matrix& varianceUpdate, const grid_map::Matrix& horizontalVarianceUpdateX,
78 | const grid_map::Matrix& horizontalVarianceUpdateY, const grid_map::Matrix& horizontalVarianceUpdateXY, const ros::Time& time);
79 |
80 | /*!
81 | * Triggers the fusion of the entire elevation map.
82 | * @return true if successful.
83 | */
84 | bool fuseAll();
85 |
86 | /*!
87 | * Fuses the elevation map for a certain rectangular area.
88 | * @param position the center position of the area to fuse.
89 | * @param length the sides lengths of the area to fuse.
90 | * @return true if successful.
91 | */
92 | bool fuseArea(const Eigen::Vector2d& position, const Eigen::Array2d& length);
93 |
94 | /*!
95 | * Clears all data of the elevation map (data and time).
96 | * @return true if successful.
97 | */
98 | bool clear();
99 |
100 | /*!
101 | * Removes parts of the map based on visibility criterion with ray tracing.
102 | * @param transformationSensorToMap
103 | * @param updatedTime
104 | */
105 | void visibilityCleanup(const ros::Time& updatedTime);
106 |
107 | /*!
108 | * Move the grid map w.r.t. to the grid map frame.
109 | * @param position the new location of the elevation map in the map frame.
110 | */
111 | void move(const Eigen::Vector2d& position);
112 |
113 | /*!
114 | * Publishes the (latest) raw elevation map. Optionally, if a postprocessing pipeline was configured,
115 | * the map is postprocessed before publishing.
116 | * @return true if successful.
117 | */
118 | // TODO (magnus) rename? E.g. adapt for postprocessing structure.
119 | bool publishRawElevationMap();
120 |
121 | /*!
122 | * Publishes the fused elevation map. Takes the latest available fused elevation
123 | * map, does not trigger the fusion process.
124 | * @return true if successful.
125 | */
126 | bool publishFusedElevationMap();
127 |
128 | /*!
129 | * Publishes the (latest) visibility cleanup map.
130 | * @return true if successful.
131 | */
132 | bool publishVisibilityCleanupMap();
133 |
134 | /*!
135 | * Gets a reference to the raw grid map.
136 | * @return the raw grid map.
137 | */
138 | grid_map::GridMap& getRawGridMap();
139 |
140 | /*!
141 | * Sets a raw grid map.
142 | * @param map The input raw grid map to set.
143 | */
144 | void setRawGridMap(const grid_map::GridMap& map);
145 |
146 | /*!
147 | * Gets a reference to the fused grid map.
148 | * @return the fused grid map.
149 | */
150 | grid_map::GridMap& getFusedGridMap();
151 |
152 | /*!
153 | * Sets a fused grid map.
154 | * @param map The input fused grid map to set.
155 | */
156 | void setFusedGridMap(const grid_map::GridMap& map);
157 |
158 | /*!
159 | * Gets the time of last map update.
160 | * @return time of the last map update.
161 | */
162 | ros::Time getTimeOfLastUpdate();
163 |
164 | /*!
165 | * Gets the time of last map fusion.
166 | * @return time of the last map fusion.
167 | */
168 | ros::Time getTimeOfLastFusion();
169 |
170 | /*!
171 | * Get the pose of the elevation map frame w.r.t. the inertial parent frame of the robot (e.g. world, map etc.).
172 | * @return pose of the elevation map frame w.r.t. the parent frame of the robot.
173 | */
174 | const kindr::HomTransformQuatD& getPose();
175 |
176 | /*!
177 | * Gets the position of a raw data point (x, y of cell position & height of cell value) in
178 | * the parent frame of the robot.
179 | * @param index the index of the requested cell.
180 | * @param position the position of the data point in the parent frame of the robot.
181 | * @return true if successful, false if no valid data available.
182 | */
183 | bool getPosition3dInRobotParentFrame(const Eigen::Array2i& index, kindr::Position3D& position);
184 |
185 | /*!
186 | * Gets the fused data mutex.
187 | * @return reference to the fused data mutex.
188 | */
189 | boost::recursive_mutex& getFusedDataMutex();
190 |
191 | /*!
192 | * Gets the raw data mutex.
193 | * @return reference to the raw data mutex.
194 | */
195 | boost::recursive_mutex& getRawDataMutex();
196 |
197 | /*!
198 | * Set the frame id.
199 | * @param frameId the frame id.
200 | */
201 | void setFrameId(const std::string& frameId);
202 |
203 | /*!
204 | * Get the frame id.
205 | * @return the frameId.
206 | */
207 | const std::string& getFrameId();
208 |
209 | /*!
210 | * Set the timestamp of the raw and fused elevation map.
211 | * @param timestmap to set.
212 | */
213 | void setTimestamp(ros::Time timestamp);
214 |
215 | /*!
216 | * If the raw elevation map has subscribers.
217 | * @return true if number of subscribers bigger then 0.
218 | */
219 | bool hasRawMapSubscribers() const;
220 |
221 | /*!
222 | * If the fused elevation map has subscribers.
223 | * @return true if number of subscribers bigger then 0.
224 | */
225 | bool hasFusedMapSubscribers() const;
226 |
227 | /*!
228 | * Callback method for the updates of the underlying map.
229 | * Updates the internal underlying map.
230 | * @param underlyingMap the underlying map.
231 | */
232 | void underlyingMapCallback(const grid_map_msgs::GridMap& underlyingMap);
233 |
234 | /*!
235 | * Method to set the height value around the center of the robot, can be used for initialization.
236 | * @param initPosition Position to calculate inner rectangle.
237 | * @param mapHeight The height that gets set uniformly.
238 | * @param lengthInXSubmap Length of the submap in X direction.
239 | * @param lengthInYSubmap Length of the submap in Y direction.
240 | * @param margin Extra margin that gets added to the submap boundaries.
241 | */
242 | void setRawSubmapHeight(const grid_map::Position& initPosition, float mapHeight, double lengthInXSubmap, double lengthInYSubmap,
243 | double margin);
244 |
245 | friend class ElevationMapping;
246 |
247 | private:
248 | /*!
249 | * Fuses a region of the map.
250 | * @param topLeftIndex the top left index of the region.
251 | * @param size the size (in number of cells) of the region.
252 | * @return true if successful.
253 | */
254 | bool fuse(const grid_map::Index& topLeftIndex, const grid_map::Index& size);
255 |
256 | /*!
257 | * Cleans the elevation map data to stay within the specified bounds.
258 | * @return true if successful.
259 | */
260 | bool clean();
261 |
262 | /*!
263 | * Resets the fused map data.
264 | * @return true if successful.
265 | */
266 | void resetFusedData();
267 |
268 | /*!
269 | * Cumulative distribution function.
270 | * @param x the argument value.
271 | * @param mean the mean of the distribution.
272 | * @param standardDeviation the standardDeviation of the distribution.
273 | * @return the function value.
274 | */
275 | float cumulativeDistributionFunction(float x, float mean, float standardDeviation);
276 |
277 | //! ROS nodehandle.
278 | ros::NodeHandle nodeHandle_;
279 |
280 | //! Raw elevation map as grid map.
281 | grid_map::GridMap rawMap_;
282 |
283 | //! Fused elevation map as grid map.
284 | grid_map::GridMap fusedMap_;
285 |
286 | //! Visibility cleanup debug map.
287 | grid_map::GridMap visibilityCleanupMap_;
288 |
289 | //! Underlying map, used for ground truth maps, multi-robot mapping etc.
290 | grid_map::GridMap underlyingMap_;
291 |
292 | //! Thread Pool to handle raw map postprocessing filter pipelines.
293 | PostprocessorPool postprocessorPool_;
294 |
295 | //! True if underlying map has been set, false otherwise.
296 | bool hasUnderlyingMap_;
297 |
298 | //! Pose of the elevation map frame w.r.t. the inertial parent frame of the robot (e.g. world, map etc.).
299 | kindr::HomTransformQuatD pose_;
300 |
301 | //! ROS publishers. Publishing of the raw elevation map is handled by the postprocessing pool.
302 | ros::Publisher elevationMapFusedPublisher_;
303 | ros::Publisher visibilityCleanupMapPublisher_;
304 |
305 | //! Mutex lock for fused map.
306 | boost::recursive_mutex fusedMapMutex_;
307 |
308 | //! Mutex lock for raw map.
309 | boost::recursive_mutex rawMapMutex_;
310 |
311 | //! Mutex lock for visibility cleanup map.
312 | boost::recursive_mutex visibilityCleanupMapMutex_;
313 |
314 | //! Underlying map subscriber.
315 | ros::Subscriber underlyingMapSubscriber_;
316 |
317 | //! Initial ros time
318 | ros::Time initialTime_;
319 |
320 | //! Parameters. Are set through the ElevationMapping class.
321 | double minVariance_;
322 | double maxVariance_;
323 | double mahalanobisDistanceThreshold_;
324 | double multiHeightNoise_;
325 | double minHorizontalVariance_;
326 | double maxHorizontalVariance_;
327 | std::string underlyingMapTopic_;
328 | bool enableVisibilityCleanup_;
329 | bool enableContinuousCleanup_;
330 | double visibilityCleanupDuration_;
331 | double scanningDuration_;
332 | };
333 |
334 | } // namespace elevation_mapping
335 |
--------------------------------------------------------------------------------
/elevation_mapping/include/elevation_mapping/ElevationMapFunctors.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | * ElevationMapFunctors.hpp
3 | *
4 | * Created on: Jan 4, 2014
5 | * Author: Péter Fankhauser
6 | * Institute: ETH Zurich, ANYbotics
7 | */
8 |
9 | #pragma once
10 |
11 | namespace elevation_mapping {
12 |
13 | template
14 | struct VarianceClampOperator {
15 | VarianceClampOperator(const Scalar& minVariance, const Scalar& maxVariance) : minVariance_(minVariance), maxVariance_(maxVariance) {}
16 | const Scalar operator()(const Scalar& x) const {
17 | return x < minVariance_ ? minVariance_ : (x > maxVariance_ ? std::numeric_limits::infinity() : x);
18 | }
19 | Scalar minVariance_, maxVariance_;
20 | };
21 |
22 | } // namespace elevation_mapping
23 |
--------------------------------------------------------------------------------
/elevation_mapping/include/elevation_mapping/ElevationMapping.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | * ElevationMap.hpp
3 | *
4 | * Created on: Nov 12, 2013
5 | * Author: Péter Fankhauser
6 | * Institute: ETH Zurich, ANYbotics
7 | */
8 |
9 | #pragma once
10 |
11 | // Grid Map
12 | #include
13 | #include
14 | #include
15 |
16 | // ROS
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 |
25 | // Eigen
26 | #include
27 | #include
28 |
29 | // Boost
30 | #include
31 |
32 | // Elevation Mapping
33 | #include "elevation_mapping/ElevationMap.hpp"
34 | #include "elevation_mapping/PointXYZRGBConfidenceRatio.hpp"
35 | #include "elevation_mapping/RobotMotionMapUpdater.hpp"
36 | #include "elevation_mapping/WeightedEmpiricalCumulativeDistributionFunction.hpp"
37 | #include "elevation_mapping/input_sources/InputSourceManager.hpp"
38 | #include "elevation_mapping/sensor_processors/SensorProcessorBase.hpp"
39 |
40 | namespace elevation_mapping {
41 |
42 | enum class InitializationMethods { PlanarFloorInitializer };
43 |
44 | /*!
45 | * The elevation mapping main class. Coordinates the ROS interfaces, the timing,
46 | * and the data handling between the other classes.
47 | */
48 | class ElevationMapping {
49 | public:
50 | /*!
51 | * Constructor.
52 | *
53 | * @param nodeHandle the ROS node handle.
54 | */
55 | explicit ElevationMapping(ros::NodeHandle& nodeHandle);
56 |
57 | /*!
58 | * Destructor.
59 | */
60 | virtual ~ElevationMapping();
61 |
62 | /*!
63 | * Callback function for new data to be added to the elevation map.
64 | *
65 | * @param pointCloudMsg The point cloud to be fused with the existing data.
66 | * @param publishPointCloud If true, publishes the pointcloud after updating the map.
67 | * @param sensorProcessor_ The sensorProcessor to use in this callback.
68 | */
69 | void pointCloudCallback(const sensor_msgs::PointCloud2ConstPtr& pointCloudMsg, bool publishPointCloud,
70 | const SensorProcessorBase::Ptr& sensorProcessor_);
71 |
72 | /*!
73 | * Callback function for the update timer. Forces an update of the map from
74 | * the robot's motion if no new measurements are received for a certain time
75 | * period.
76 | *
77 | * @param timerEvent The timer event.
78 | */
79 | void mapUpdateTimerCallback(const ros::TimerEvent& timerEvent);
80 |
81 | /*!
82 | * Callback function for the fused map publish timer. Publishes the fused map
83 | * based on configurable duration.
84 | *
85 | * @param timerEvent The timer event.
86 | */
87 | void publishFusedMapCallback(const ros::TimerEvent& timerEvent);
88 |
89 | /*!
90 | * Callback function for cleaning map based on visibility ray tracing.
91 | *
92 | * @param timerEvent The timer event.
93 | */
94 | void visibilityCleanupCallback(const ros::TimerEvent& timerEvent);
95 |
96 | /*!
97 | * ROS service callback function to trigger the fusion of the entire
98 | * elevation map.
99 | *
100 | * @param request The ROS service request.
101 | * @param response The ROS service response.
102 | * @return true if successful.
103 | */
104 | bool fuseEntireMapServiceCallback(std_srvs::Empty::Request& request, std_srvs::Empty::Response& response);
105 |
106 | /*!
107 | * ROS service callback function to return a submap of the fused elevation map.
108 | *
109 | * @param request The ROS service request defining the location and size of the fused submap.
110 | * @param response The ROS service response containing the requested fused submap.
111 | * @return true if successful.
112 | */
113 | bool getFusedSubmapServiceCallback(grid_map_msgs::GetGridMap::Request& request, grid_map_msgs::GetGridMap::Response& response);
114 |
115 | /*!
116 | * ROS service callback function to return a submap of the raw elevation map.
117 | *
118 | * @param request The ROS service request defining the location and size of the raw submap.
119 | * @param response The ROS service response containing the requested raw submap.
120 | * @return true if successful.
121 | */
122 | bool getRawSubmapServiceCallback(grid_map_msgs::GetGridMap::Request& request, grid_map_msgs::GetGridMap::Response& response);
123 |
124 | /*!
125 | * ROS service callback function to enable updates of the elevation map.
126 | *
127 | * @param request The ROS service request.
128 | * @param response The ROS service response.
129 | * @return true if successful.
130 | */
131 | bool enableUpdatesServiceCallback(std_srvs::Empty::Request& request, std_srvs::Empty::Response& response);
132 |
133 | /*!
134 | * ROS service callback function to disable updates of the elevation map.
135 | *
136 | * @param request The ROS service request.
137 | * @param response The ROS service response.
138 | * @return true if successful.
139 | */
140 | bool disableUpdatesServiceCallback(std_srvs::Empty::Request& request, std_srvs::Empty::Response& response);
141 |
142 | /*!
143 | * ROS service callback function to clear all data of the elevation map.
144 | *
145 | * @param request The ROS service request.
146 | * @param response The ROS service response.
147 | * @return true if successful.
148 | */
149 | bool clearMapServiceCallback(std_srvs::Empty::Request& request, std_srvs::Empty::Response& response);
150 |
151 | /*!
152 | * ROS service callback function to allow for setting the individual layers of the elevation map through a service call.
153 | * The layer mask can be used to only set certain cells and not the entire map. Cells
154 | * containing NAN in the mask are not set, all the others are set. If the layer mask is
155 | * not supplied, the entire map will be set in the intersection of both maps. The
156 | * provided map can be of different size and position than the map that will be altered.
157 | *
158 | * @param request The ROS service request.
159 | * @param response The ROS service response.
160 | * @return true if successful.
161 | */
162 | bool maskedReplaceServiceCallback(grid_map_msgs::SetGridMap::Request& request, grid_map_msgs::SetGridMap::Response& response);
163 |
164 | /*!
165 | * ROS service callback function to save the grid map with all layers to a ROS bag file.
166 | *
167 | * @param request The ROS service request.
168 | * @param response The ROS service response.
169 | * @return true if successful.
170 | */
171 | bool saveMapServiceCallback(grid_map_msgs::ProcessFile::Request& request, grid_map_msgs::ProcessFile::Response& response);
172 |
173 | /*!
174 | * ROS service callback function to load the grid map with all layers from a ROS bag file.
175 | *
176 | * @param request The ROS service request.
177 | * @param response The ROS service response.
178 | * @return true if successful.
179 | */
180 | bool loadMapServiceCallback(grid_map_msgs::ProcessFile::Request& request, grid_map_msgs::ProcessFile::Response& response);
181 |
182 | private:
183 | /*!
184 | * Reads and verifies the ROS parameters.
185 | *
186 | * @return true if successful.
187 | */
188 | bool readParameters();
189 |
190 | /*!
191 | * Performs the initialization procedure.
192 | *
193 | * @return true if successful.
194 | */
195 | bool initialize();
196 |
197 | /**
198 | * Sets up the subscribers for both robot poses and input data.
199 | */
200 | void setupSubscribers();
201 |
202 | /*!
203 | * Separate thread for all fusion service calls.
204 | */
205 | void runFusionServiceThread();
206 |
207 | /*!
208 | * Separate thread for visibility cleanup.
209 | */
210 | void visibilityCleanupThread();
211 |
212 | /*!
213 | * Update the elevation map from the robot motion up to a certain time.
214 | *
215 | * @param time Time to which the map is updated to.
216 | * @return true if successful.
217 | */
218 | bool updatePrediction(const ros::Time& time);
219 |
220 | /*!
221 | * Updates the location of the map to follow the tracking point. Takes care
222 | * of the data handling the goes along with the relocalization.
223 | *
224 | * @return true if successful.
225 | */
226 | bool updateMapLocation();
227 |
228 | /*!
229 | * Reset and start the map update timer.
230 | */
231 | void resetMapUpdateTimer();
232 |
233 | /*!
234 | * Stop the map update timer.
235 | */
236 | void stopMapUpdateTimer();
237 |
238 | /*!
239 | * Initializes a submap around the robot of the elevation map with a constant height
240 | */
241 | bool initializeElevationMap();
242 |
243 | //! ROS nodehandle.
244 | ros::NodeHandle nodeHandle_;
245 |
246 | protected:
247 | //! Input sources.
248 | InputSourceManager inputSources_;
249 | //! ROS subscribers.
250 | ros::Subscriber pointCloudSubscriber_; //!< Deprecated, use input_source instead.
251 | message_filters::Subscriber robotPoseSubscriber_;
252 |
253 | //! ROS service servers.
254 | ros::ServiceServer fusionTriggerService_;
255 | ros::ServiceServer fusedSubmapService_;
256 | ros::ServiceServer rawSubmapService_;
257 | ros::ServiceServer enableUpdatesService_;
258 | ros::ServiceServer disableUpdatesService_;
259 | ros::ServiceServer clearMapService_;
260 | ros::ServiceServer maskedReplaceService_;
261 | ros::ServiceServer saveMapService_;
262 | ros::ServiceServer loadMapService_;
263 |
264 | //! Callback thread for the fusion services.
265 | boost::thread fusionServiceThread_;
266 |
267 | //! Callback queue for fusion service thread.
268 | ros::CallbackQueue fusionServiceQueue_;
269 |
270 | //! Cache for the robot pose messages.
271 | message_filters::Cache robotPoseCache_;
272 |
273 | //! Size of the cache for the robot pose messages.
274 | int robotPoseCacheSize_;
275 |
276 | //! Frame ID of the elevation map
277 | std::string mapFrameId_;
278 |
279 | //! TF listener and broadcaster.
280 | tf::TransformListener transformListener_;
281 |
282 | //! Point which the elevation map follows.
283 | kindr::Position3D trackPoint_;
284 | std::string trackPointFrameId_;
285 |
286 | //! ROS topics for subscriptions.
287 | std::string pointCloudTopic_; //!< Deprecated, use input_source instead.
288 | std::string robotPoseTopic_;
289 |
290 | //! Elevation map.
291 | ElevationMap map_;
292 |
293 | //! Sensor processors. Deprecated use the one from input sources instead.
294 | SensorProcessorBase::Ptr sensorProcessor_;
295 |
296 | //! Robot motion elevation map updater.
297 | RobotMotionMapUpdater robotMotionMapUpdater_;
298 |
299 | //! If true, robot motion updates are ignored.
300 | bool ignoreRobotMotionUpdates_;
301 |
302 | //! If false, elevation mapping stops updating
303 | bool updatesEnabled_;
304 |
305 | //! Time of the last point cloud update.
306 | ros::Time lastPointCloudUpdateTime_;
307 |
308 | //! Timer for the robot motion update.
309 | ros::Timer mapUpdateTimer_;
310 |
311 | //! Maximum time that the map will not be updated.
312 | ros::Duration maxNoUpdateDuration_;
313 |
314 | //! Time tolerance for updating the map with data before the last update.
315 | //! This is useful when having multiple sensors adding data to the map.
316 | ros::Duration timeTolerance_;
317 |
318 | //! Timer for publishing the fused map.
319 | ros::Timer fusedMapPublishTimer_;
320 |
321 | //! Duration for the publishing the fusing map.
322 | ros::Duration fusedMapPublishTimerDuration_;
323 |
324 | //! If map is fused after every change for debugging/analysis purposes.
325 | bool isContinuouslyFusing_;
326 |
327 | //! Timer for the raytracing cleanup.
328 | ros::Timer visibilityCleanupTimer_;
329 |
330 | //! Duration for the raytracing cleanup timer.
331 | ros::Duration visibilityCleanupTimerDuration_;
332 |
333 | //! Callback queue for raytracing cleanup thread.
334 | ros::CallbackQueue visibilityCleanupQueue_;
335 |
336 | //! Callback thread for raytracing cleanup.
337 | boost::thread visibilityCleanupThread_;
338 |
339 | //! Becomes true when corresponding poses and point clouds can be found
340 | bool receivedFirstMatchingPointcloudAndPose_;
341 |
342 | //! Name of the mask layer used in the masked replace service
343 | std::string maskedReplaceServiceMaskLayerName_;
344 |
345 | //! Enables initialization of the elevation map
346 | bool initializeElevationMap_;
347 |
348 | //! Enum to choose the initialization method
349 | int initializationMethod_;
350 |
351 | //! Width of submap of the elevation map with a constant height
352 | double lengthInXInitSubmap_;
353 |
354 | //! Height of submap of the elevation map with a constant height
355 | double lengthInYInitSubmap_;
356 |
357 | //! Margin of submap of the elevation map with a constant height
358 | double marginInitSubmap_;
359 |
360 | //! Target frame to get the init height of the elevation map
361 | std::string targetFrameInitSubmap_;
362 |
363 | //! Additional offset of the height value
364 | double initSubmapHeightOffset_;
365 | };
366 |
367 | } // namespace elevation_mapping
368 |
--------------------------------------------------------------------------------
/elevation_mapping/include/elevation_mapping/PointXYZRGBConfidenceRatio.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | * PointXYZRGBConfidenceRatio.hpp
3 | *
4 | * Created on: Nov 26, 2020
5 | * Author: Magnus Gärtner
6 | * Institute: ETH Zurich, ANYbotics
7 | *
8 | * This file defines our custom pcl type, ie including a confidence_ratio.
9 | * Adapted from https://github.com/PointCloudLibrary/pcl/blob/master/common/include/pcl/impl/point_types.hpp
10 | */
11 |
12 | #pragma once
13 |
14 | #include
15 | #include
16 | #include
17 |
18 | namespace pcl {
19 |
20 | #pragma GCC diagnostic push
21 | #pragma GCC diagnostic ignored "-Wpedantic"
22 | struct _PointXYZRGBConfidenceRatio {
23 | PCL_ADD_POINT4D; // This adds the members x,y,z which can also be accessed using the point (which is float[4])
24 | PCL_ADD_RGB;
25 | union {
26 | struct {
27 | float confidence_ratio;
28 | };
29 | float data_c[4];
30 | };
31 | PCL_MAKE_ALIGNED_OPERATOR_NEW
32 | } EIGEN_ALIGN16; // enforce SSE padding for correct memory alignment
33 | #pragma GCC diagnostic pop
34 |
35 | struct PointXYZRGBConfidenceRatio : public _PointXYZRGBConfidenceRatio {
36 | inline PointXYZRGBConfidenceRatio(const _PointXYZRGBConfidenceRatio& p) {
37 | // XZY
38 | x = p.x;
39 | y = p.y;
40 | z = p.z;
41 | data[3] = 1.0f;
42 |
43 | // RGB
44 | rgba = p.rgba;
45 |
46 | // Confidence
47 | confidence_ratio = p.confidence_ratio;
48 | }
49 |
50 | inline PointXYZRGBConfidenceRatio(float _confidence_ratio = 1.f)
51 | : PointXYZRGBConfidenceRatio(0.f, 0.f, 0.f, 0, 0, 0, _confidence_ratio) {}
52 |
53 | inline PointXYZRGBConfidenceRatio(std::uint8_t _r, std::uint8_t _g, std::uint8_t _b)
54 | : PointXYZRGBConfidenceRatio(0.f, 0.f, 0.f, _r, _g, _b) {}
55 |
56 | inline PointXYZRGBConfidenceRatio(float _x, float _y, float _z) : PointXYZRGBConfidenceRatio(_x, _y, _z, 0, 0, 0) {}
57 |
58 | inline PointXYZRGBConfidenceRatio(float _x, float _y, float _z, std::uint8_t _r, std::uint8_t _g, std::uint8_t _b,
59 | float _confidence_ratio = 1.f) {
60 | x = _x;
61 | y = _y;
62 | z = _z;
63 | data[3] = 1.0f;
64 |
65 | r = _r;
66 | g = _g;
67 | b = _b;
68 | a = 255;
69 |
70 | confidence_ratio = _confidence_ratio;
71 | }
72 |
73 | friend std::ostream& operator<<(std::ostream& os, const PointXYZRGBConfidenceRatio& p);
74 | };
75 |
76 | PCL_EXPORTS std::ostream& operator<<(std::ostream& os, const PointXYZRGBConfidenceRatio& p);
77 |
78 | } // namespace pcl
79 |
80 | namespace elevation_mapping {
81 | using PointCloudType = pcl::PointCloud;
82 | } // namespace elevation_mapping
83 |
84 | POINT_CLOUD_REGISTER_POINT_STRUCT(pcl::_PointXYZRGBConfidenceRatio, // here we assume a XYZ + "confidence_ratio" (as fields)
85 | (float, x, x) // NOLINT
86 | (float, y, y) // NOLINT
87 | (float, z, z) // NOLINT
88 | (std::uint32_t, rgba, rgba) // NOLINT
89 | (float, confidence_ratio, confidence_ratio)) // NOLINT
90 |
91 | POINT_CLOUD_REGISTER_POINT_WRAPPER(pcl::PointXYZRGBConfidenceRatio, pcl::_PointXYZRGBConfidenceRatio)
92 |
--------------------------------------------------------------------------------
/elevation_mapping/include/elevation_mapping/RobotMotionMapUpdater.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | * RobotMotionMapUpdater.hpp
3 | *
4 | * Created on: Feb 5, 2014
5 | * Author: Péter Fankhauser
6 | * Institute: ETH Zurich, ANYbotics
7 | */
8 |
9 | #pragma once
10 |
11 | // Elevation Mapping
12 | #include "elevation_mapping/ElevationMap.hpp"
13 |
14 | // Eigen
15 | #include
16 |
17 | // Kindr
18 | #include
19 |
20 | // ROS
21 | #include
22 |
23 | namespace elevation_mapping {
24 |
25 | /*!
26 | * Computes the map variance update from the pose covariance of the robot.
27 | */
28 | class RobotMotionMapUpdater {
29 | public:
30 | using Pose = kindr::HomogeneousTransformationPosition3RotationQuaternionD;
31 | using Covariance = Eigen::Matrix;
32 | using PoseCovariance = Eigen::Matrix;
33 | using ReducedCovariance = Eigen::Matrix;
34 | using Jacobian = Eigen::Matrix;
35 |
36 | /*!
37 | * Constructor.
38 | */
39 | explicit RobotMotionMapUpdater(ros::NodeHandle nodeHandle);
40 |
41 | /*!
42 | * Destructor.
43 | */
44 | virtual ~RobotMotionMapUpdater();
45 |
46 | /*!
47 | * Reads and verifies the ROS parameters.
48 | * @return true if successful.
49 | */
50 | bool readParameters();
51 |
52 | /*!
53 | * Computes the model update for the elevation map based on the pose covariance and
54 | * adds the update to the map.
55 | * @param[in] map the elevation map to be updated.
56 | * @param[in] robotPose the current pose.
57 | * @param[in] robotPoseCovariance the current pose covariance matrix.
58 | * @param[in] time the time of the current update.
59 | * @return true if successful.
60 | */
61 | bool update(ElevationMap& map, const Pose& robotPose, const PoseCovariance& robotPoseCovariance, const ros::Time& time);
62 |
63 | private:
64 | /*!
65 | * Computes the reduced covariance (4x4: x, y, z, yaw) from the full pose covariance (6x6: x, y, z, roll, pitch, yaw).
66 | * @param[in] robotPose the robot pose.
67 | * @param[in] robotPoseCovariance the full pose covariance matrix (6x6).
68 | * @param[out] reducedCovariance the reduced covariance matrix (4x4);
69 | * @return true if successful.
70 | */
71 | bool computeReducedCovariance(const Pose& robotPose, const PoseCovariance& robotPoseCovariance, ReducedCovariance& reducedCovariance);
72 |
73 | /*!
74 | * Computes the covariance between the new and the previous pose.
75 | * @param[in] robotPose the current robot pose.
76 | * @param[in] reducedCovariance the current robot pose covariance matrix (reduced).
77 | * @param[out] relativeRobotPoseCovariance the relative covariance between the current and the previous robot pose (reduced form).
78 | * @return true if successful.
79 | */
80 | bool computeRelativeCovariance(const Pose& robotPose, const ReducedCovariance& reducedCovariance, ReducedCovariance& relativeCovariance);
81 |
82 | //! ROS nodehandle.
83 | ros::NodeHandle nodeHandle_;
84 |
85 | //! Time of the previous update.
86 | ros::Time previousUpdateTime_;
87 |
88 | //! Previous robot pose.
89 | Pose previousRobotPose_;
90 |
91 | //! Robot pose covariance (reduced) from the previous update.
92 | ReducedCovariance previousReducedCovariance_;
93 |
94 | //! Scaling factor for the covariance matrix (default 1).
95 | double covarianceScale_;
96 | };
97 |
98 | } // namespace elevation_mapping
99 |
--------------------------------------------------------------------------------
/elevation_mapping/include/elevation_mapping/WeightedEmpiricalCumulativeDistributionFunction.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | * WeightedEmpiricalCumulativeDistributionFunction.hpp
3 | *
4 | * Created on: Dec 7, 2015
5 | * Author: Péter Fankhauser
6 | * Institute: ETH Zurich, ANYbotics
7 | */
8 |
9 | #pragma once
10 |
11 | #include
12 | #include