tuning.rst 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. .. Copyright 2018 The Cartographer Authors
  2. .. Licensed under the Apache License, Version 2.0 (the "License");
  3. you may not use this file except in compliance with the License.
  4. You may obtain a copy of the License at
  5. .. http://www.apache.org/licenses/LICENSE-2.0
  6. .. Unless required by applicable law or agreed to in writing, software
  7. distributed under the License is distributed on an "AS IS" BASIS,
  8. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  9. See the License for the specific language governing permissions and
  10. limitations under the License.
  11. .. cartographer SHA: aba4575d937df4c9697f61529200c084f2562584
  12. .. cartographer_ros SHA: 99c23b6ac7874f7974e9ed808ace841da6f2c8b0
  13. .. TODO(hrapp): mention insert_free_space somewhere
  14. Tuning methodology
  15. ==================
  16. Tuning Cartographer is unfortunately really difficult.
  17. The system has many parameters many of which affect each other.
  18. This tuning guide tries to explain a principled approach on concrete examples.
  19. Built-in tools
  20. --------------
  21. Cartographer provides built-in tools for SLAM evaluation that can be particularly useful for measuring the local SLAM quality.
  22. They are stand-alone executables that ship with the core ``cartographer`` library and are hence independent, but compatible with ``cartographer_ros``.
  23. Therefore, please head to the `Cartographer Read the Docs Evaluation site`_ for a conceptual overview and a guide on how to use the tools in practice.
  24. These tools assume that you have serialized the SLAM state to a ``.pbstream`` file.
  25. With ``cartographer_ros``, you can invoke the ``assets_writer`` to serialize the state - see the :ref:`assets_writer` section for more information.
  26. .. _Cartographer Read the Docs Evaluation site: https://google-cartographer.readthedocs.io/en/latest/evaluation.html
  27. Example: tuning local SLAM
  28. --------------------------
  29. For this example we'll start at ``cartographer`` commit `aba4575`_ and ``cartographer_ros`` commit `99c23b6`_ and look at the bag ``b2-2016-04-27-12-31-41.bag`` from our test data set.
  30. At our starting configuration, we see some slipping pretty early in the bag.
  31. The backpack passed over a ramp in the Deutsches Museum which violates the 2D assumption of a flat floor.
  32. It is visible in the laser scan data that contradicting information is passed to the SLAM.
  33. But the slipping also indicates that we trust the point cloud matching too much and disregard the other sensors quite strongly.
  34. Our aim is to improve the situation through tuning.
  35. .. _aba4575: https://github.com/googlecartographer/cartographer/commit/aba4575d937df4c9697f61529200c084f2562584
  36. .. _99c23b6: https://github.com/googlecartographer/cartographer_ros/commit/99c23b6ac7874f7974e9ed808ace841da6f2c8b0
  37. If we only look at this particular submap, that the error is fully contained in one submap.
  38. We also see that over time, global SLAM figures out that something weird happened and partially corrects for it.
  39. The broken submap is broken forever though.
  40. .. TODO(hrapp): VIDEO
  41. Since the problem here is slippage inside a submap, it is a local SLAM issue.
  42. So let's turn off global SLAM to not mess with our tuning.
  43. .. code-block:: lua
  44. POSE_GRAPH.optimize_every_n_nodes = 0
  45. Correct size of submaps
  46. ^^^^^^^^^^^^^^^^^^^^^^^
  47. The size of submaps is configured through ``TRAJECTORY_BUILDER_2D.submaps.num_range_data``.
  48. Looking at the individual submaps for this example they already fit the two constraints rather well, so we assume this parameter is well tuned.
  49. Tuning the ``CeresScanMatcher``
  50. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  51. In our case, the scan matcher can freely move the match forward and backwards without impacting the score.
  52. We'd like to penalize this situation by making the scan matcher pay more for deviating from the prior that it got.
  53. The two parameters controlling this are ``TRAJECTORY_BUILDER_2D.ceres_scan_matcher.translation_weight`` and ``rotation_weight``.
  54. 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.
  55. For instructional purposes, let's make deviating from the prior really expensive:
  56. .. code-block:: lua
  57. TRAJECTORY_BUILDER_2D.ceres_scan_matcher.translation_weight = 1e3
  58. .. TODO(hrapp): video
  59. This allows the optimizer to pretty liberally overwrite the scan matcher results.
  60. This results in poses close to the prior, but inconsistent with the depth sensor and clearly broken.
  61. Experimenting with this value yields a better result at ``2e2``.
  62. .. TODO(hrapp): VIDEO with translation_weight = 2e2
  63. Here, the scan matcher used rotation to still slightly mess up the result though.
  64. Setting the ``rotation_weight`` to ``4e2`` leaves us with a reasonable result.
  65. Verification
  66. ^^^^^^^^^^^^
  67. To make sure that we did not overtune for this particular issue, we need to run the configuration against other collected data.
  68. 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``.
  69. This setting is worse for the case we wanted to fix, but no longer slips.
  70. Before checking them in, we normalize all weights, since they only have relative meaning.
  71. The result of this tuning was `PR 428`_.
  72. In general, always try to tune for a platform, not a particular bag.
  73. .. _PR 428: https://github.com/googlecartographer/cartographer/pull/428
  74. Special Cases
  75. -------------
  76. The default configuration and the above tuning steps are focused on quality.
  77. Only after we have achieved good quality, we can further consider special cases.
  78. Low Latency
  79. ^^^^^^^^^^^
  80. By low latency, we mean that an optimized local pose becomes available shortly after sensor input was received,
  81. usually within a second, and that global optimization has no backlog.
  82. Low latency is required for online algorithms, such as robot localization.
  83. Local SLAM, which operates in the foreground, directly affects latency.
  84. Global SLAM builds up a queue of background tasks.
  85. When global SLAM cannot keep up the queue, drift can accumulate indefinitely,
  86. so global SLAM should be tuned to work in real time.
  87. There are many options to tune the different components for speed, and we list them ordered from
  88. the recommended, straightforward ones to the those that are more intrusive.
  89. It is recommended to only explore one option at a time, starting with the first.
  90. Configuration parameters are documented in the `Cartographer documentation`_.
  91. .. _Cartographer documentation: https://google-cartographer.readthedocs.io/en/latest/configuration.html
  92. To tune global SLAM for lower latency, we reduce its computational load
  93. until is consistently keeps up with real-time input.
  94. Below this threshold, we do not reduce it further, but try to achieve the best possible quality.
  95. To reduce global SLAM latency, we can
  96. - decrease ``optimize_every_n_nodes``
  97. - increase ``MAP_BUILDER.num_background_threads`` up to the number of cores
  98. - decrease ``global_sampling_ratio``
  99. - decrease ``constraint_builder.sampling_ratio``
  100. - increase ``constraint_builder.min_score``
  101. - for the adaptive voxel filter(s), decrease ``.min_num_points``, ``.max_range``, increase ``.max_length``
  102. - increase ``voxel_filter_size``, ``submaps.resolution``, decrease ``submaps.num_range_data``
  103. - decrease search windows sizes, ``.linear_xy_search_window``, ``.linear_z_search_window``, ``.angular_search_window``
  104. - increase ``global_constraint_search_after_n_seconds``
  105. - decrease ``max_num_iterations``
  106. To tune local SLAM for lower latency, we can
  107. - increase ``voxel_filter_size``
  108. - increase ``submaps.resolution``
  109. - for the adaptive voxel filter(s), decrease ``.min_num_points``, ``.max_range``, increase ``.max_length``
  110. - decrease ``max_range`` (especially if data is noisy)
  111. - decrease ``submaps.num_range_data``
  112. Note that larger voxels will slightly increase scan matching scores as a side effect,
  113. so score thresholds should be increased accordingly.
  114. Pure Localization in a Given Map
  115. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  116. Pure localization is different from mapping.
  117. First, we expect a lower latency of both local and global SLAM.
  118. Second, global SLAM will usually find a very large number of inter constraints between the frozen trajectory
  119. that serves as a map and the current trajectory.
  120. To tune for pure localization, we should first enable ``TRAJECTORY_BUILDER.pure_localization = true`` and
  121. strongly decrease ``POSE_GRAPH.optimize_every_n_nodes`` to receive frequent results.
  122. With these settings, global SLAM will usually be too slow and cannot keep up.
  123. As a next step, we strongly decrease ``global_sampling_ratio`` and ``constraint_builder.sampling_ratio``
  124. to compensate for the large number of constraints.
  125. We then tune for lower latency as explained above until the system reliably works in real time.
  126. If you run in ``pure_localization``, ``submaps.resolution`` **should be matching** with the resolution of the submaps in the ``.pbstream`` you are running on.
  127. Using different resolutions is currently untested and may not work as expected.
  128. Odometry in Global Optimization
  129. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  130. If a separate odometry source is used as an input for local SLAM (``use_odometry = true``), we can also tune the global SLAM to benefit from this additional information.
  131. There are in total four parameters that allow us to tune the individual weights of local SLAM and odometry in the optimization:
  132. .. code-block:: lua
  133. POSE_GRAPH.optimization_problem.local_slam_pose_translation_weight
  134. POSE_GRAPH.optimization_problem.local_slam_pose_rotation_weight
  135. POSE_GRAPH.optimization_problem.odometry_translation_weight
  136. POSE_GRAPH.optimization_problem.odometry_rotation_weight
  137. We can set these weights depending on how much we trust either local SLAM or the odometry.
  138. By default, odometry is weighted into global optimization similar to local slam (scan matching) poses.
  139. However, odometry from wheel encoders often has a high uncertainty in rotation.
  140. In this case, the rotation weight can be reduced, even down to zero.
  141. Still have a problem ?
  142. ----------------------
  143. If you can't get Cartographer to work reliably on your data, you can open a `GitHub issue`_ asking for help.
  144. Developers are keen to help, but they can only be helpful if you follow `an issue template`_ containing the result of ``rosbag_validate``, a link to a fork of ``cartographer_ros`` with your config and a link to a ``.bag`` file reproducing your problem.
  145. .. note::
  146. There are already lots of GitHub issues with all sorts of problems solved by the developers. Going through `the closed issues of cartographer_ros`_ and `of cartographer`_ is a great way to learn more about Cartographer and maybe find a solution to your problem !
  147. .. _GitHub issue: https://github.com/googlecartographer/cartographer_ros/issues
  148. .. _an issue template: https://github.com/googlecartographer/cartographer_ros/issues/new?labels=question
  149. .. _the closed issues of cartographer_ros: https://github.com/googlecartographer/cartographer_ros/issues?q=is%3Aissue+is%3Aclosed
  150. .. _of cartographer: https://github.com/googlecartographer/cartographer_ros/issues?q=is%3Aissue+is%3Aclosed