当前位置:   article > 正文

ROS2:如何将Cartographer和Navigation2一起使用(2):使用纯定位和Nav2进行导航_amcl和cartographer

amcl和cartographer

ROS2中的navigation2使用AMCL和map_server来估计自己的位置并自主移动。

map_server发布/map主题,AMCL根据/map和雷达的/scan、里程计/odom信息估计自己的位置,并将/tf发布到/odom。

通过将AMCL和map_server分别替换成cartographer_node、cartographer_occupancy_grid_node而不是AMCL,Cartographer可以单独进行纯定位并在导航中运行它,同时估计自己的位置。

实现在ROS2中的Cartographer纯定位可以在上篇文章中发现,本文将讲解Cartographer替换AMCL配合Nav2实现导航仿真。

ROS2:如何将Cartographer和Navigation2一起使用(1):从SLAM到纯定位_什么都不会的码小白的博客-CSDN博客

Nav2操作

首先检查Navigation2默认状态下的操作。

  1. export TURTLEBOT3_MODEL=burger
  2. ros2 launch turtlebot3_gazebo turtlebot3_world.launch.py

当在Gazebo环境中运行Nav2时,务必将use_sim_time设置为true。

运行turtlebot3包中的navigation2.launch可以使用下面的命令。

  1. export TURTLEBOT3_MODEL=burger
  2. ros2 launch turtlebot3_navigation2 navigation2.launch.py use_sim_time:=true

单击Rviz命令面板上的2D Pose Estimate设置初始位置,然后用Nav2 Goal拖动地图上的目标位置,使用Turtlebot3向目标位置移动。

创建启动文件启动Cartographer和Nav2

 Nav2中的bringup_launch.py​​是在navigation2.launch.py​​中调用的,而执行amcl和map_server的localization_launch.py​​是在bringup_launch.py中执行的。
通过重写bringup_launch.py​​来创建新的启动文件,以运行上一篇文章中创建的cartographer_localization.launch.py​​而不是localization_launch。

在launch文件夹下创建一个新的启动文件bringup_launch_cartographer.launch.py,以下是启动文件内容的示例。

  1. import os
  2. from ament_index_python.packages import get_package_share_directory
  3. from launch import LaunchDescription
  4. from launch.actions import (DeclareLaunchArgument, GroupAction,
  5. IncludeLaunchDescription, SetEnvironmentVariable)
  6. from launch.conditions import IfCondition
  7. from launch.launch_description_sources import PythonLaunchDescriptionSource
  8. from launch.substitutions import LaunchConfiguration, PythonExpression
  9. from launch_ros.actions import Node
  10. from launch_ros.actions import PushRosNamespace
  11. from nav2_common.launch import RewrittenYaml
  12. def generate_launch_description():
  13. # Get the launch directory
  14. bringup_dir = get_package_share_directory('nav2_bringup')
  15. launch_dir = os.path.join(bringup_dir, 'launch')
  16. cartographer_launch_dir = os.path.join(get_package_share_directory('turtlebot3_cartographer'), 'launch')
  17. # Create the launch configuration variables
  18. namespace = LaunchConfiguration('namespace')
  19. use_namespace = LaunchConfiguration('use_namespace')
  20. slam = LaunchConfiguration('slam')
  21. map_yaml_file = LaunchConfiguration('map')
  22. use_sim_time = LaunchConfiguration('use_sim_time')
  23. params_file = LaunchConfiguration('params_file')
  24. autostart = LaunchConfiguration('autostart')
  25. use_composition = LaunchConfiguration('use_composition')
  26. use_respawn = LaunchConfiguration('use_respawn')
  27. log_level = LaunchConfiguration('log_level')
  28. remappings = [('/tf', 'tf'),
  29. ('/tf_static', 'tf_static')]
  30. configured_params = RewrittenYaml(
  31. source_file=params_file,
  32. root_key=namespace,
  33. param_rewrites={},
  34. convert_types=True)
  35. stdout_linebuf_envvar = SetEnvironmentVariable(
  36. 'RCUTILS_LOGGING_BUFFERED_STREAM', '1')
  37. declare_namespace_cmd = DeclareLaunchArgument(
  38. 'namespace',
  39. default_value='',
  40. description='Top-level namespace')
  41. declare_use_namespace_cmd = DeclareLaunchArgument(
  42. 'use_namespace',
  43. default_value='false',
  44. description='Whether to apply a namespace to the navigation stack')
  45. declare_map_yaml_cmd = DeclareLaunchArgument(
  46. 'map',
  47. default_value='',
  48. description='Full path to map yaml file to load')
  49. declare_use_sim_time_cmd = DeclareLaunchArgument(
  50. 'use_sim_time',
  51. default_value='false',
  52. description='Use simulation (Gazebo) clock if true')
  53. declare_params_file_cmd = DeclareLaunchArgument(
  54. 'params_file',
  55. default_value=os.path.join(bringup_dir, 'params', 'nav2_params.yaml'),
  56. description='Full path to the ROS2 parameters file to use for all launched nodes')
  57. declare_autostart_cmd = DeclareLaunchArgument(
  58. 'autostart', default_value='true',
  59. description='Automatically startup the nav2 stack')
  60. declare_use_composition_cmd = DeclareLaunchArgument(
  61. 'use_composition', default_value='True',
  62. description='Whether to use composed bringup')
  63. declare_use_respawn_cmd = DeclareLaunchArgument(
  64. 'use_respawn', default_value='False',
  65. description='Whether to respawn if a node crashes. Applied when composition is disabled.')
  66. declare_log_level_cmd = DeclareLaunchArgument(
  67. 'log_level', default_value='info',
  68. description='log level')
  69. # Specify the actions
  70. bringup_cmd_group = GroupAction([
  71. PushRosNamespace(
  72. condition=IfCondition(use_namespace),
  73. namespace=namespace),
  74. Node(
  75. condition=IfCondition(use_composition),
  76. name='nav2_container',
  77. package='rclcpp_components',
  78. executable='component_container_isolated',
  79. parameters=[configured_params, {'autostart': autostart}],
  80. arguments=['--ros-args', '--log-level', log_level],
  81. remappings=remappings,
  82. output='screen'),
  83. IncludeLaunchDescription(
  84. PythonLaunchDescriptionSource(os.path.join(cartographer_launch_dir,
  85. 'cartographer_localization.launch.py'))),
  86. IncludeLaunchDescription(
  87. PythonLaunchDescriptionSource(os.path.join(launch_dir, 'navigation_launch.py')),
  88. launch_arguments={'namespace': namespace,
  89. 'use_sim_time': use_sim_time,
  90. 'autostart': autostart,
  91. 'params_file': params_file,
  92. 'use_composition': use_composition,
  93. 'use_respawn': use_respawn,
  94. 'container_name': 'nav2_container'}.items()),
  95. ])
  96. # Create the launch description and populate
  97. ld = LaunchDescription()
  98. # Set environment variables
  99. ld.add_action(stdout_linebuf_envvar)
  100. # Declare the launch options
  101. ld.add_action(declare_namespace_cmd)
  102. ld.add_action(declare_use_namespace_cmd)
  103. ld.add_action(declare_map_yaml_cmd)
  104. ld.add_action(declare_use_sim_time_cmd)
  105. ld.add_action(declare_params_file_cmd)
  106. ld.add_action(declare_autostart_cmd)
  107. ld.add_action(declare_use_composition_cmd)
  108. ld.add_action(declare_use_respawn_cmd)
  109. ld.add_action(declare_log_level_cmd)
  110. # Add the actions to launch all of the navigation nodes
  111. ld.add_action(bringup_cmd_group)
  112. return ld

对比bringup_launch.py​​,添加以下部分。

  1. cartographer_launch_dir = os.path.join(get_package_share_directory('turtlebot3_cartographer'), 'launch')
  2. IncludeLaunchDescription(
  3. PythonLaunchDescriptionSource(os.path.join(cartographer_launch_dir,
  4. 'cartographer_localization.launch.py'))),

创建一个新的bringup_launch,启动bringup_launch_cartographer.launch.py。
​​​​*map.yaml 由于不需要pgm,所以与map_dir相关的部分已被删除。

相应的navigation2_cartographer.launch.py代码如下。

  1. import os
  2. from ament_index_python.packages import get_package_share_directory
  3. from launch import LaunchDescription
  4. from launch.actions import DeclareLaunchArgument
  5. from launch.actions import IncludeLaunchDescription
  6. from launch.launch_description_sources import PythonLaunchDescriptionSource
  7. from launch.substitutions import LaunchConfiguration
  8. from launch_ros.actions import Node
  9. TURTLEBOT3_MODEL = os.environ['TURTLEBOT3_MODEL']
  10. def generate_launch_description():
  11. use_sim_time = LaunchConfiguration('use_sim_time', default='false')
  12. param_file_name = TURTLEBOT3_MODEL + '.yaml'
  13. param_dir = LaunchConfiguration(
  14. 'params_file',
  15. default=os.path.join(
  16. get_package_share_directory('turtlebot3_navigation2'),
  17. 'param',
  18. param_file_name))
  19. nav2_launch_file_dir = os.path.join(get_package_share_directory('turtlebot3_navigation2'), 'launch')
  20. rviz_config_dir = os.path.join(
  21. get_package_share_directory('nav2_bringup'),
  22. 'rviz',
  23. 'nav2_default_view.rviz')
  24. return LaunchDescription([
  25. DeclareLaunchArgument(
  26. 'params_file',
  27. default_value=param_dir,
  28. description='Full path to param file to load'),
  29. DeclareLaunchArgument(
  30. 'use_sim_time',
  31. default_value='false',
  32. description='Use simulation (Gazebo) clock if true'),
  33. IncludeLaunchDescription(
  34. PythonLaunchDescriptionSource([nav2_launch_file_dir, '/bringup_launch_cartographer.launch.py']),
  35. launch_arguments={
  36. 'use_sim_time': use_sim_time,
  37. 'params_file': param_dir}.items(),
  38. ),
  39. Node(
  40. package='rviz2',
  41. executable='rviz2',
  42. name='rviz2',
  43. arguments=['-d', rviz_config_dir],
  44. parameters=[{'use_sim_time': use_sim_time}],
  45. output='screen'),
  46. ])

运行

 

  1. export TURTLEBOT3_MODEL=burger
  2. ros2 launch turtlebot3_gazebo turtlebot3_world.launch.py
  1. export TURTLEBOT3_MODEL=burger
  2. ros2 launch turtlebot3_navigation2 navigation2_cartographer.launch.py use_sim_time:=true

rviz2显示全局成本图。同样,如果使用 Nav2 Goal 拖动地图上的目标位置,Turtlebot3 也会向目标移动。(无需设置初始位置)

运行时的rqt_graph

 

tf树

 /map --> 发出 /odom 的 TF 的节点变为 cartographer_ros 而不是 amcl。

总结

本文通过结合 Nav2 和使用 cartographer 估计其自身位置,实现机器人的导航。
amcl 需要 /odom,但如果更改cartographer 设置,即使对于无法进行里程计的机器人,也可以使用 Nav2 进行导航。 

本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号