• 基于ROS和turtlebot2的多机器人导航定位配置记录


    基于ROS和turtlebot2的多机器人导航定位配置记录

    整个流程是:
    1 先用单个机器人完成环境建图
    2 配置两个机器人的主从机
    3 配置两个机器人的turtlebot_bringup、amcl、key_teleop、move_base

    需要的前置知识:ROS的命名空间,TFtree

    先列一下参考文章:
    古月居博客的多机器人导航
    ROS配置多机器人导航
    多机器人导航与编队(一)
    多机器人导航与编队(二)

    需要修改的文件:
    turtlebot_bringup minimal.launch robot.launch.xml
    turtlebot_teleop keboard_teleop.launch
    turtlebot_navigation amcl.launch, movebase.launch,hokuyo_laser.launch
    kobuki_node base.yaml

    turtlebot_bringup minimal.launch:需要加入 命名空间 group ns=“robot1”

    <launch>  
    <group ns="robot1">
    	
      <arg name="base"              default="$(env TURTLEBOT_BASE)"         doc="mobile base type [create, roomba]"/>
      <arg name="battery"           default="$(env TURTLEBOT_BATTERY)"      doc="kernel provided locatio for battery info, use /proc/acpi/battery/BAT0 in 2.6 or earlier kernels." />
      <arg name="stacks"            default="$(env TURTLEBOT_STACKS)"       doc="stack type displayed in visualisation/simulation [circles, hexagons]"/>
      <arg name="3d_sensor"         default="$(env TURTLEBOT_3D_SENSOR)"    doc="3d sensor types [kinect, asux_xtion_pro]"/>
      <arg name="simulation"        default="$(env TURTLEBOT_SIMULATION)"   doc="set flags to indicate this turtle is run in simulation mode."/>
      <arg name="serialport"        default="$(env TURTLEBOT_SERIAL_PORT)"  doc="used by create to configure the port it is connected on [/dev/ttyUSB0, /dev/ttyS0]"/>
    
      <param name="/use_sim_time" value="$(arg simulation)"/>
    
      <include file="$(find turtlebot_bringup)/launch/includes/robot.launch.xml">
        <arg name="base" value="$(arg base)" />
        <arg name="stacks" value="$(arg stacks)" />
        <arg name="3d_sensor" value="$(arg 3d_sensor)" />
      include>
      <include file="$(find turtlebot_bringup)/launch/includes/mobile_base.launch.xml">
        <arg name="base" value="$(arg base)" />
        <arg name="serialport" value="$(arg serialport)" />
      include>
      <include unless="$(eval arg('battery') == 'None')" file="$(find turtlebot_bringup)/launch/includes/netbook.launch.xml">
        <arg name="battery" value="$(arg battery)" />
      include>
    group>
    launch>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    keboard_teleop.launch 加入group命名空间

    <launch>
    <group ns="robot1">
      
        <node pkg="turtlebot_teleop" type="turtlebot_teleop_key" name="turtlebot_teleop_keyboard"  output="screen">
        <param name="scale_linear" value="0.5" type="double"/>
        <param name="scale_angular" value="1.5" type="double"/>
        <remap from="turtlebot_teleop_keyboard/cmd_vel" to="cmd_vel_mux/input/teleop"/>
      node>
    group>
    launch>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    robot.launch.xml:添加robot_state_publisher
    作用是给tf添加前缀

    
    <launch>
      <arg name="base"/>
      <arg name="stacks"/>
      <arg name="3d_sensor"/>
      
      <include file="$(find turtlebot_bringup)/launch/includes/description.launch.xml">
        <arg name="base" value="$(arg base)" />
        <arg name="stacks" value="$(arg stacks)" />
        <arg name="3d_sensor" value="$(arg 3d_sensor)" />
      include>
    
        
      <param name="robot/name" value="$(optenv ROBOT turtlebot)"/>
      <param name="robot/type" value="turtlebot"/>
      
      <node pkg="robot_state_publisher" type="robot_state_publisher" name="robot_state_publisher">
        <param name="publish_frequency" type="double" value="5.0" />
        <param name="tf_prefix" value="robot1" />
      node>
    
      <node pkg="diagnostic_aggregator" type="aggregator_node" name="diagnostic_aggregator" >
        <rosparam command="load" file="$(find turtlebot_bringup)/param/$(arg base)/diagnostics.yaml" />
      node>
    launch>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    amcl.launch 修改map路径,并发布连接上maprobot1/odom的tf,加入group ns

    <launch>
    <group ns="robot1">
      
      <arg name="map_file" default="/home/gglin/map/map.yaml"/>
      <node name="map_server" pkg="map_server" type="map_server" args="$(arg map_file)" >
         <param name="frame_id" value="map" />
    node>
    
      <node pkg="tf" type="static_transform_publisher" name="map_to_odom" args="0.0 0.0 0.0 0 0 0.0 map robot1/odom 1000"/>
      
    
      
      <arg name="custom_amcl_launch_file" default="$(find multi_robots_navgation)/launch/includes/robot1_amcl.launch.xml"/>
      <arg name="initial_pose_x" default="0.0"/> 
      <arg name="initial_pose_y" default="0.0"/> 
      <arg name="initial_pose_a" default="0.0"/>
      <include file="$(arg custom_amcl_launch_file)">
        <arg name="initial_pose_x" value="$(arg initial_pose_x)"/>
        <arg name="initial_pose_y" value="$(arg initial_pose_y)"/>
        <arg name="initial_pose_a" value="$(arg initial_pose_a)"/>
      include>
    
      
      <include file="$(find multi_robots_navgation)/launch/includes/robot1_move_base.launch.xml">
      include>
    
    group>
    launch>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    其包含的 robot1_amcl.launch.xml 如下 修改odom_frame_idodom_frame_id

    <launch>
      <arg name="use_map_topic"   default="false"/>
      <arg name="scan_topic"      default="scan"/> 
      <arg name="initial_pose_x"  default="0.0"/>
      <arg name="initial_pose_y"  default="0.0"/>
      <arg name="initial_pose_a"  default="0.0"/>
      <arg name="odom_frame_id"   default="robot1/odom"/>
      <arg name="base_frame_id"   default="robot1/base_footprint"/>
      <arg name="global_frame_id" default="map"/>
    
      <node pkg="amcl" type="amcl" name="amcl">
        <param name="use_map_topic"             value="$(arg use_map_topic)"/>
        
        <param name="odom_model_type"           value="diff"/>
        <param name="odom_alpha5"               value="0.1"/>
        <param name="gui_publish_rate"          value="10.0"/>
        <param name="laser_max_beams"             value="60"/>
        <param name="laser_max_range"           value="26.0"/>
        <param name="min_particles"             value="500"/>
        <param name="max_particles"             value="2000"/>
        <param name="kld_err"                   value="0.05"/>
        <param name="kld_z"                     value="0.99"/>
        <param name="odom_alpha1"               value="0.2"/>
        <param name="odom_alpha2"               value="0.2"/>
        
        <param name="odom_alpha3"               value="0.2"/>
        <param name="odom_alpha4"               value="0.2"/>
        <param name="laser_z_hit"               value="0.5"/>
        <param name="laser_z_short"             value="0.05"/>
        <param name="laser_z_max"               value="0.05"/>
        <param name="laser_z_rand"              value="0.5"/>
        <param name="laser_sigma_hit"           value="0.2"/>
        <param name="laser_lambda_short"        value="0.1"/>
        <param name="laser_model_type"          value="likelihood_field"/>
        
        <param name="laser_likelihood_max_dist" value="2.0"/>
        <param name="update_min_d"              value="0.2"/>
        <param name="update_min_a"              value="0.2"/>
        <param name="odom_frame_id"             value="$(arg odom_frame_id)"/> 
        <param name="base_frame_id"             value="$(arg base_frame_id)"/> 
        <param name="global_frame_id"           value="$(arg global_frame_id)"/>
        <param name="resample_interval"         value="1"/>
        
        <param name="transform_tolerance"       value="1.0"/>
        <param name="recovery_alpha_slow"       value="0.0"/>
        <param name="recovery_alpha_fast"       value="0.0"/>
        <param name="initial_pose_x"            value="$(arg initial_pose_x)"/>
        <param name="initial_pose_y"            value="$(arg initial_pose_y)"/>
        <param name="initial_pose_a"            value="$(arg initial_pose_a)"/>
        <remap from="scan"                      to="$(arg scan_topic)"/>
      node>
    launch>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52

    amcl包含的robot1_move_base.launch.xml 如下,修改的地方 odom_frame_id base_frame_id

    
    <launch>
      <include file="$(find multi_robots_navgation)/launch/includes/velocity_smoother.launch.xml"/>
      <include file="$(find multi_robots_navgation)/launch/includes/safety_controller.launch.xml"/>
      
      <arg name="odom_frame_id"   default="robot1/odom"/>
      <arg name="base_frame_id"   default="robot1/base_footprint"/>
      <arg name="global_frame_id" default="map"/>
      <arg name="odom_topic" default="odom" />
      <arg name="laser_topic" default="scan" />
      <arg name="custom_param_file" default="$(find multi_robots_navgation)/param/dummy.yaml"/>
    
      <node pkg="move_base" type="move_base" respawn="false" name="move_base" output="screen">
        <rosparam file="$(find multi_robots_navgation)/param/costmap_common_params.yaml" command="load" ns="global_costmap" />
        <rosparam file="$(find multi_robots_navgation)/param/costmap_common_params.yaml" command="load" ns="local_costmap" />   
        <rosparam file="$(find multi_robots_navgation)/param/local_costmap_params.yaml" command="load" />   
        <rosparam file="$(find multi_robots_navgation)/param/global_costmap_params.yaml" command="load" />
        <rosparam file="$(find multi_robots_navgation)/param/dwa_local_planner_params.yaml" command="load" />
        <rosparam file="$(find multi_robots_navgation)/param/move_base_params.yaml" command="load" />
        <rosparam file="$(find multi_robots_navgation)/param/global_planner_params.yaml" command="load" />
        <rosparam file="$(find multi_robots_navgation)/param/navfn_global_planner_params.yaml" command="load" />
        
        <rosparam file="$(arg custom_param_file)" command="load" />
        
        
        <param name="global_costmap/global_frame" value="$(arg global_frame_id)"/>
        <param name="global_costmap/robot_base_frame" value="$(arg base_frame_id)"/>
        <param name="local_costmap/global_frame" value="$(arg odom_frame_id)"/>
        <param name="local_costmap/robot_base_frame" value="$(arg base_frame_id)"/>
        <param name="DWAPlannerROS/global_frame_id" value="$(arg odom_frame_id)"/>
    
        <remap from="cmd_vel" to="navigation_velocity_smoother/raw_cmd_vel"/>
        <remap from="odom" to="$(arg odom_topic)"/>
        <remap from="scan" to="$(arg laser_topic)"/>
      node>
    launch>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    hokuyo_laser.launch 添加group ns 和 发布静态tf

    <launch>
    <group ns="robot1">
      <node name="hokuyo" pkg="hokuyo_node" type="hokuyo_node" respawn="false" output="screen">
    
       
      <param name="calibrate_time" type="bool" value="false"/> 
    
      
      <param name="port" type="string" value="/dev/hokuyo"/> 
      <param name="frame_id"  type="string" value="robot1/laser"/>
      <param name="intensity" type="bool" value="false"/>
      node>
    
      <node pkg="tf" type="static_transform_publisher" name="base_to_laser" args="0.0 0.0 0.18 0 0.0 0.0 robot1/base_link robot1/laser 100"/>
    group>
    launch>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    base.yaml: 修改odom_framebase_frame

    ##############################################################################
    # Firmware Source
    ##############################################################################
    
    device_port: /dev/kobuki
    
    # published joint states
    wheel_left_joint_name: wheel_left_joint
    wheel_right_joint_name: wheel_right_joint
    
    # battery voltage at full charge (100%) (float, default: 16.5)
    battery_capacity: 16.5
    
    # battery voltage at first warning (15%) (float, default: 13.5)
    battery_low: 14.0
    
    # battery voltage at critical level (5%) (float, default: 13.2)
    battery_dangerous: 13.2
    
    # If a new command isn't received within this many seconds, the base is stopped (double, default: 0.6)
    cmd_vel_timeout: 0.6
    
    # Causes node to publish TF for odom_frame to base_frame. Disable only if you plan to use robot_pose_ekf
    # (see use_imu_heading description) (bool, default: true)
    publish_tf: true
    
    # Use imu readings for heading instead of encoders. That's the normal operation mode for Kobuki, as its
    # gyro is very reliable. Disable only if you want to fuse encoders and imu readings in a more sophisticated
    # way, for example filtering and fussing with robot_pose_ekf (bool, default: true)
    use_imu_heading: true
    
    # Name of the odometry TF frame (string, default: odom)
    odom_frame: robot1/odom
    
    # Name of the base TF frame  (string, default: base_footprint)
    base_frame: robot1/base_footprint
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    正常的tf应该类似这样
    在这里插入图片描述

  • 相关阅读:
    mybatisplus和java8一些常用方法总结
    【Leetcode】1259. Handshakes That Don‘t Cross
    flutter实现上拉加载下拉刷新
    jxTMS+职教:SaaS模式的低门槛开发实训
    基于MindStudio的Pytorch离线推理
    Elastic学习之旅 (2) 快速安装ELK
    vue+vite+ts添加eslint校验和代码提交校验
    3.【openCV_imread()函数详解】
    微信小程序进阶(1)--自定义组件
    Redis原理到常用语法基础图文讲解
  • 原文地址:https://blog.csdn.net/weixin_44388819/article/details/125875872