parent
7e272f2e2b
commit
698fc1043f
|
@ -21,6 +21,7 @@ Cartographer ROS Integration
|
|||
:hidden:
|
||||
|
||||
configuration
|
||||
tuning
|
||||
ros_api
|
||||
data
|
||||
faq
|
||||
|
|
|
@ -0,0 +1,140 @@
|
|||
.. Copyright 2016 The Cartographer Authors
|
||||
|
||||
.. 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.
|
||||
|
||||
.. cartographer SHA: ea7c39b6f078c693b92fed06d86ca501021147d9
|
||||
.. cartographer_ros SHA: 44459e18102305745c56f92549b87d8e91f434fe
|
||||
.. TODO(hrapp): mention insert_free_space somewhere
|
||||
|
||||
Tuning
|
||||
======
|
||||
|
||||
Tuning Cartographer is unfortunately really difficult.
|
||||
The system has many parameters many of which affect each other.
|
||||
This tuning guide tries to explain a principled approach on concrete examples.
|
||||
|
||||
Two systems
|
||||
-----------
|
||||
|
||||
Cartographer can be seen as two separate, but related systems.
|
||||
The first one is local SLAM (sometimes also called frontend).
|
||||
Its job is build a locally consistent set of submaps and tie them together, but it will drift over time.
|
||||
Most of its options can be found in `trajectory_builder_2d.lua`_ for 2D and `trajectory_builder_3d.lua`_ for 3D.
|
||||
|
||||
.. _trajectory_builder_2d.lua: https://github.com/googlecartographer/cartographer/blob/ea7c39b6f078c693b92fed06d86ca501021147d9/configuration_files/trajectory_builder_2d.lua
|
||||
.. _trajectory_builder_3d.lua: https://github.com/googlecartographer/cartographer/blob/ea7c39b6f078c693b92fed06d86ca501021147d9/configuration_files/trajectory_builder_3d.lua
|
||||
|
||||
The other system is global SLAM (sometimes called the backend).
|
||||
It runs in background threads and its main job is to find loop closure constraints.
|
||||
It does that by scan-matching scans against submaps.
|
||||
It also incorporates other sensor data to get a higher level view and identify the most consistent global solution.
|
||||
In 3D, it also tries to find the direction of gravity.
|
||||
Most of its options can be found in `sparse_pose_graph.lua`_
|
||||
|
||||
.. _sparse_pose_graph.lua: https://github.com/googlecartographer/cartographer/blob/ea7c39b6f078c693b92fed06d86ca501021147d9/configuration_files/sparse_pose_graph.lua
|
||||
|
||||
On a higher abstraction, the job of local SLAM is to generate good submaps and the job of global SLAM is to tie them most consistently together.
|
||||
|
||||
Tuning local SLAM
|
||||
-----------------
|
||||
|
||||
For this example we'll start at ``cartographer`` commit `ea7c39b`_ and ``cartographer_ros`` commit `44459e1`_ and look at the bag ``b2-2016-04-27-12-31-41.bag`` from our test data set.
|
||||
|
||||
At our starting configuration, we see some slipping pretty early in the bag.
|
||||
The backpack passed over a ramp in the Deutsches Museum which violates the 2D assumption of a flat floor.
|
||||
It is visible in the laser scan data that contradicting information is passed to the SLAM.
|
||||
But the slipping also indicates that we trust the point cloud matching too much and disregard the other sensors quite strongly.
|
||||
Our aim is to improve the situation through tuning.
|
||||
|
||||
.. _ea7c39b: https://github.com/googlecartographer/cartographer/commit/ea7c39b6f078c693b92fed06d86ca501021147d9
|
||||
.. _44459e1: https://github.com/googlecartographer/cartographer_ros/commit/44459e18102305745c56f92549b87d8e91f434fe
|
||||
|
||||
If we only look at this particular submap, that the error is fully contained in one submap.
|
||||
We also see that over time, global SLAM figures out that something weird happened and partially corrects for it.
|
||||
The broken submap is broken forever though.
|
||||
|
||||
.. TODO(hrapp): VIDEO
|
||||
|
||||
Since the problem here is slippage inside a submap, it is a local SLAM issue.
|
||||
So let's turn off global SLAM to not mess with our tuning.
|
||||
|
||||
.. code-block:: lua
|
||||
|
||||
SPARSE_POSE_GRAPH.optimize_every_n_scans = 0
|
||||
|
||||
Correct size of submaps
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Local SLAM drifts over time, only loop closure can fix this drift.
|
||||
Submaps must be small enough so that the drift inside them is below the resolution, so that they are locally correct.
|
||||
On the other hand, they should be large enough to be being distinct for loop closure to work properly.
|
||||
The size of submaps is configured through ``TRAJECTORY_BUILDER_2D.submaps.num_range_data``.
|
||||
Looking at the individual submaps for this example they already fit the two constraints rather well, so we assume this parameter is well tuned.
|
||||
|
||||
The choice of scan matchers
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The idea behind local SLAM is to use sensor data of other sensors besides the range finder to predict where the next scan should be inserted into the submap.
|
||||
Then, the ``CeresScanMatcher`` takes this as prior and finds the best spot where the scan match fits the submap.
|
||||
It does this by interpolating the submap and sub-pixel aligning the scan.
|
||||
This is fast, but cannot fix errors that are significantly larger than the resolution of the submaps.
|
||||
If your sensor setup and timing is reasonable, using only the ``CeresScanMatcher`` is usually the best choice to make.
|
||||
|
||||
If you do not have other sensors or you do not trust them, Cartographer also provides a ``RealTimeCorrelativeScanMatcher``.
|
||||
It uses an approach similar to how scans are matched against submaps in loop closure, but instead it matches against the current submap.
|
||||
The best match is then used as prior for the ``CeresScanMatcher``.
|
||||
This scan matcher is very expensive and will essentially override any signal from other sensors but the range finder, but it is robust in feature rich environments.
|
||||
|
||||
Tuning the correlative scan matcher
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
TODO
|
||||
|
||||
Tuning the ``CeresScanMatcher``
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
In our case, the scan matcher can freely move the match forward and backwards without impacting the score.
|
||||
We'd like to penalize this situation by making the scan matcher pay more for deviating from the prior that it got.
|
||||
The two parameters controlling this are ``TRAJECTORY_BUILDER_2D.ceres_scan_matcher.translation_weight`` and ``rotation_weight``.
|
||||
The higher, the more expensive it is to move the result away from the prior, or in other words: scan matching has to generate a higher score in another position to be accepted.
|
||||
|
||||
For instructional purposes, let's make deviating from the prior really expensive:
|
||||
|
||||
.. code-block:: lua
|
||||
|
||||
TRAJECTORY_BUILDER_2D.ceres_scan_matcher.translation_weight = 1e3
|
||||
|
||||
.. TODO(hrapp): video
|
||||
|
||||
This allows the optimizer to pretty liberally overwrite the scan matcher results.
|
||||
This results in poses close to the prior, but inconsistent with the depth sensor and clearly broken.
|
||||
Experimenting with this value yields a better result at ``2e2``.
|
||||
|
||||
.. TODO(hrapp): VIDEO with translation_weight = 2e2
|
||||
|
||||
Here, the scan matcher used rotation to still slightly mess up the result though.
|
||||
Setting the ``rotation_weight`` to ``4e2`` leaves us with a reasonable result.
|
||||
|
||||
|
||||
Verification
|
||||
------------
|
||||
|
||||
To make sure that we did not overtune for this particular issue, we need to run the configuration against other collected data.
|
||||
In this case, the new parameters did reveal slipping, for example at the beginning of ``b2-2016-04-05-14-44-52.bag``, so we had to lower the ``translation_weight`` to ``1e2``.
|
||||
This setting is worse for the case we wanted to fix, but no longer slips.
|
||||
Before checking them in, we normalize all weights, since they only have relative meaning.
|
||||
The result of this tuning was `PR 428`_.
|
||||
In general, always try to tune for a platform, not a particular bag.
|
||||
|
||||
.. _PR 428: https://github.com/googlecartographer/cartographer/pull/428
|
||||
|
Loading…
Reference in New Issue