当前位置:   article > 正文

ROS2极简总结-SLAM_ros2 slam

ros2 slam

参考文献:Navigation using ROS 2 Mapping


SLAM - Simultaneous Localization And Mapping

同步定位和建图

机器人仿真或实际运动环境的最简描述。

建图 - SLAM

  • SLAM:同时估计机器人的位置姿态和环境的地图
    • 定位:给定地图推断位置
    • 建图:推断给定位置的地图
    • SLAM:同时学习地图和定位机器人
  • SLAM 的目标是创建或增强环境地图。
  • 地图表示 2D 或 3D 环境。
  • 实际上是一个很难解决的问题!

至少目前没有很好的统一的解决方案,相关算法都在研发和改进中。

地图类型

栅格地图图形地图特征地图

ROS2 SLAM工具箱

目前,ROS2 的 SLAM 还没有可靠唯一标准。 一些有力竞争者是:

  • LaMa (2D) - IRIS Labs - 新的,可以说是更好的,强有力的竞争者
  • Cartographer (2D/3D) - Google - 从 ROS1 移植,经常使用,但没有维护
  • SLAM 工具箱 (2D) - Steve Macenski - 当前随 Navigation2 一起提供,需要支持。 如果可以,请参与帮助!

二维SLAM

占用栅格图

  • 为每个网格单元计算概率(贝叶斯过滤器)

三维SLAM

用于三维占用地图的八叉树

  • 基于树的数据结构

效果引用(github.com/rsasaki0109/li_slam_ros2) 


此处简单用turtlebot3+cartographer+ros2foxy+webots2021b在win10下,跑一个效果:

  • set TURTLEBOT3_MODEL=burger 
  • ros2 launch webots_ros2_turtlebot robot_launch.py
  • ros2 launch turtlebot3_cartographer cartographer.launch.py use_sim_time:=true
  • ros2 run turtlebot3_teleop teleop_keyboard

ros2 launch webots_ros2_turtlebot robot_launch.py

启动webots仿真

  1. """Launch Webots TurtleBot3 Burger driver."""
  2. import os
  3. import pathlib
  4. from launch.substitutions import LaunchConfiguration
  5. from launch.actions import DeclareLaunchArgument
  6. from launch.substitutions.path_join_substitution import PathJoinSubstitution
  7. from launch import LaunchDescription
  8. from launch_ros.actions import Node
  9. import launch
  10. from ament_index_python.packages import get_package_share_directory
  11. from webots_ros2_core.webots_launcher import WebotsLauncher
  12. def generate_launch_description():
  13. package_dir = get_package_share_directory('webots_ros2_turtlebot')
  14. world = LaunchConfiguration('world')
  15. robot_description = pathlib.Path(os.path.join(package_dir, 'resource', 'turtlebot_webots.urdf')).read_text()
  16. ros2_control_params = os.path.join(package_dir, 'resource', 'ros2control.yml')
  17. webots = WebotsLauncher(
  18. world=PathJoinSubstitution([package_dir, 'worlds', world])
  19. )
  20. # TODO: Revert once the https://github.com/ros-controls/ros2_control/pull/444 PR gets into the release
  21. controller_manager_timeout = ['--controller-manager-timeout', '50'] if os.name == 'nt' else []
  22. controller_manager_prefix = 'python.exe' if os.name == 'nt' else "bash -c 'sleep 10; $0 $@' "
  23. diffdrive_controller_spawner = Node(
  24. package='controller_manager',
  25. executable='spawner.py',
  26. output='screen',
  27. prefix=controller_manager_prefix,
  28. arguments=['diffdrive_controller'] + controller_manager_timeout,
  29. )
  30. joint_state_broadcaster_spawner = Node(
  31. package='controller_manager',
  32. executable='spawner.py',
  33. output='screen',
  34. prefix=controller_manager_prefix,
  35. arguments=['joint_state_broadcaster'] + controller_manager_timeout,
  36. )
  37. turtlebot_driver = Node(
  38. package='webots_ros2_driver',
  39. executable='driver',
  40. output='screen',
  41. parameters=[
  42. {'robot_description': robot_description},
  43. ros2_control_params
  44. ],
  45. remappings=[
  46. ('/diffdrive_controller/cmd_vel_unstamped', '/cmd_vel')
  47. ]
  48. )
  49. robot_state_publisher = Node(
  50. package='robot_state_publisher',
  51. executable='robot_state_publisher',
  52. output='screen',
  53. parameters=[{
  54. 'robot_description': '<robot name=""><link name=""/></robot>'
  55. }],
  56. )
  57. footprint_publisher = Node(
  58. package='tf2_ros',
  59. executable='static_transform_publisher',
  60. output='screen',
  61. arguments=['0', '0', '0', '0', '0', '0', 'base_link', 'base_footprint'],
  62. )
  63. return LaunchDescription([
  64. DeclareLaunchArgument(
  65. 'world',
  66. default_value='turtlebot3_burger_example.wbt',
  67. description='Choose one of the world files from `/webots_ros2_turtlebot/world` directory'
  68. ),
  69. joint_state_broadcaster_spawner,
  70. diffdrive_controller_spawner,
  71. webots,
  72. robot_state_publisher,
  73. turtlebot_driver,
  74. footprint_publisher,
  75. launch.actions.RegisterEventHandler(
  76. event_handler=launch.event_handlers.OnProcessExit(
  77. target_action=webots,
  78. on_exit=[launch.actions.EmitEvent(event=launch.events.Shutdown())],
  79. )
  80. )
  81. ])

ros2 launch turtlebot3_cartographer cartographer.launch.py use_sim_time:=true

启动SLAM建图

  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_ros.actions import Node
  6. from launch.substitutions import LaunchConfiguration
  7. from launch.actions import IncludeLaunchDescription
  8. from launch.launch_description_sources import PythonLaunchDescriptionSource
  9. from launch.substitutions import ThisLaunchFileDir
  10. def generate_launch_description():
  11. use_sim_time = LaunchConfiguration('use_sim_time', default='false')
  12. turtlebot3_cartographer_prefix = get_package_share_directory('turtlebot3_cartographer')
  13. cartographer_config_dir = LaunchConfiguration('cartographer_config_dir', default=os.path.join(
  14. turtlebot3_cartographer_prefix, 'config'))
  15. configuration_basename = LaunchConfiguration('configuration_basename',
  16. default='turtlebot3_lds_2d.lua')
  17. resolution = LaunchConfiguration('resolution', default='0.05')
  18. publish_period_sec = LaunchConfiguration('publish_period_sec', default='1.0')
  19. rviz_config_dir = os.path.join(get_package_share_directory('turtlebot3_cartographer'),
  20. 'rviz', 'tb3_cartographer.rviz')
  21. return LaunchDescription([
  22. DeclareLaunchArgument(
  23. 'cartographer_config_dir',
  24. default_value=cartographer_config_dir,
  25. description='Full path to config file to load'),
  26. DeclareLaunchArgument(
  27. 'configuration_basename',
  28. default_value=configuration_basename,
  29. description='Name of lua file for cartographer'),
  30. DeclareLaunchArgument(
  31. 'use_sim_time',
  32. default_value='false',
  33. description='Use simulation (Gazebo) clock if true'),
  34. Node(
  35. package='cartographer_ros',
  36. executable='cartographer_node',
  37. name='cartographer_node',
  38. output='screen',
  39. parameters=[{'use_sim_time': use_sim_time}],
  40. arguments=['-configuration_directory', cartographer_config_dir,
  41. '-configuration_basename', configuration_basename]),
  42. DeclareLaunchArgument(
  43. 'resolution',
  44. default_value=resolution,
  45. description='Resolution of a grid cell in the published occupancy grid'),
  46. DeclareLaunchArgument(
  47. 'publish_period_sec',
  48. default_value=publish_period_sec,
  49. description='OccupancyGrid publishing period'),
  50. IncludeLaunchDescription(
  51. PythonLaunchDescriptionSource([ThisLaunchFileDir(), '/occupancy_grid.launch.py']),
  52. launch_arguments={'use_sim_time': use_sim_time, 'resolution': resolution,
  53. 'publish_period_sec': publish_period_sec}.items(),
  54. ),
  55. Node(
  56. package='rviz2',
  57. executable='rviz2',
  58. name='rviz2',
  59. arguments=['-d', rviz_config_dir],
  60. parameters=[{'use_sim_time': use_sim_time}],
  61. output='screen'),
  62. ])

ros2 run turtlebot3_teleop teleop_keyboard

启动键盘遥控机器人

  1. import os
  2. import select
  3. import sys
  4. import rclpy
  5. from geometry_msgs.msg import Twist
  6. from rclpy.qos import QoSProfile
  7. if os.name == 'nt':
  8. import msvcrt
  9. else:
  10. import termios
  11. import tty
  12. BURGER_MAX_LIN_VEL = 0.22
  13. BURGER_MAX_ANG_VEL = 2.84
  14. WAFFLE_MAX_LIN_VEL = 0.26
  15. WAFFLE_MAX_ANG_VEL = 1.82
  16. LIN_VEL_STEP_SIZE = 0.01
  17. ANG_VEL_STEP_SIZE = 0.1
  18. TURTLEBOT3_MODEL = os.environ['TURTLEBOT3_MODEL']
  19. msg = """
  20. Control Your TurtleBot3!
  21. ---------------------------
  22. Moving around:
  23. w
  24. a s d
  25. x
  26. w/x : increase/decrease linear velocity (Burger : ~ 0.22, Waffle and Waffle Pi : ~ 0.26)
  27. a/d : increase/decrease angular velocity (Burger : ~ 2.84, Waffle and Waffle Pi : ~ 1.82)
  28. space key, s : force stop
  29. CTRL-C to quit
  30. """
  31. e = """
  32. Communications Failed
  33. """
  34. def get_key(settings):
  35. if os.name == 'nt':
  36. return msvcrt.getch().decode('utf-8')
  37. tty.setraw(sys.stdin.fileno())
  38. rlist, _, _ = select.select([sys.stdin], [], [], 0.1)
  39. if rlist:
  40. key = sys.stdin.read(1)
  41. else:
  42. key = ''
  43. termios.tcsetattr(sys.stdin, termios.TCSADRAIN, settings)
  44. return key
  45. def print_vels(target_linear_velocity, target_angular_velocity):
  46. print('currently:\tlinear velocity {0}\t angular velocity {1} '.format(
  47. target_linear_velocity,
  48. target_angular_velocity))
  49. def make_simple_profile(output, input, slop):
  50. if input > output:
  51. output = min(input, output + slop)
  52. elif input < output:
  53. output = max(input, output - slop)
  54. else:
  55. output = input
  56. return output
  57. def constrain(input_vel, low_bound, high_bound):
  58. if input_vel < low_bound:
  59. input_vel = low_bound
  60. elif input_vel > high_bound:
  61. input_vel = high_bound
  62. else:
  63. input_vel = input_vel
  64. return input_vel
  65. def check_linear_limit_velocity(velocity):
  66. if TURTLEBOT3_MODEL == 'burger':
  67. return constrain(velocity, -BURGER_MAX_LIN_VEL, BURGER_MAX_LIN_VEL)
  68. else:
  69. return constrain(velocity, -WAFFLE_MAX_LIN_VEL, WAFFLE_MAX_LIN_VEL)
  70. def check_angular_limit_velocity(velocity):
  71. if TURTLEBOT3_MODEL == 'burger':
  72. return constrain(velocity, -BURGER_MAX_ANG_VEL, BURGER_MAX_ANG_VEL)
  73. else:
  74. return constrain(velocity, -WAFFLE_MAX_ANG_VEL, WAFFLE_MAX_ANG_VEL)
  75. def main():
  76. settings = None
  77. if os.name != 'nt':
  78. settings = termios.tcgetattr(sys.stdin)
  79. rclpy.init()
  80. qos = QoSProfile(depth=10)
  81. node = rclpy.create_node('teleop_keyboard')
  82. pub = node.create_publisher(Twist, 'cmd_vel', qos)
  83. status = 0
  84. target_linear_velocity = 0.0
  85. target_angular_velocity = 0.0
  86. control_linear_velocity = 0.0
  87. control_angular_velocity = 0.0
  88. try:
  89. print(msg)
  90. while(1):
  91. key = get_key(settings)
  92. if key == 'w':
  93. target_linear_velocity =\
  94. check_linear_limit_velocity(target_linear_velocity + LIN_VEL_STEP_SIZE)
  95. status = status + 1
  96. print_vels(target_linear_velocity, target_angular_velocity)
  97. elif key == 'x':
  98. target_linear_velocity =\
  99. check_linear_limit_velocity(target_linear_velocity - LIN_VEL_STEP_SIZE)
  100. status = status + 1
  101. print_vels(target_linear_velocity, target_angular_velocity)
  102. elif key == 'a':
  103. target_angular_velocity =\
  104. check_angular_limit_velocity(target_angular_velocity + ANG_VEL_STEP_SIZE)
  105. status = status + 1
  106. print_vels(target_linear_velocity, target_angular_velocity)
  107. elif key == 'd':
  108. target_angular_velocity =\
  109. check_angular_limit_velocity(target_angular_velocity - ANG_VEL_STEP_SIZE)
  110. status = status + 1
  111. print_vels(target_linear_velocity, target_angular_velocity)
  112. elif key == ' ' or key == 's':
  113. target_linear_velocity = 0.0
  114. control_linear_velocity = 0.0
  115. target_angular_velocity = 0.0
  116. control_angular_velocity = 0.0
  117. print_vels(target_linear_velocity, target_angular_velocity)
  118. else:
  119. if (key == '\x03'):
  120. break
  121. if status == 20:
  122. print(msg)
  123. status = 0
  124. twist = Twist()
  125. control_linear_velocity = make_simple_profile(
  126. control_linear_velocity,
  127. target_linear_velocity,
  128. (LIN_VEL_STEP_SIZE / 2.0))
  129. twist.linear.x = control_linear_velocity
  130. twist.linear.y = 0.0
  131. twist.linear.z = 0.0
  132. control_angular_velocity = make_simple_profile(
  133. control_angular_velocity,
  134. target_angular_velocity,
  135. (ANG_VEL_STEP_SIZE / 2.0))
  136. twist.angular.x = 0.0
  137. twist.angular.y = 0.0
  138. twist.angular.z = control_angular_velocity
  139. pub.publish(twist)
  140. except Exception as e:
  141. print(e)
  142. finally:
  143. twist = Twist()
  144. twist.linear.x = 0.0
  145. twist.linear.y = 0.0
  146. twist.linear.z = 0.0
  147. twist.angular.x = 0.0
  148. twist.angular.y = 0.0
  149. twist.angular.z = 0.0
  150. pub.publish(twist)
  151. if os.name != 'nt':
  152. termios.tcsetattr(sys.stdin, termios.TCSADRAIN, settings)
  153. if __name__ == '__main__':
  154. main()

-End-


声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/天景科技苑/article/detail/870454
推荐阅读
相关标签
  

闽ICP备14008679号