机器人操作系统ROS—使用激光雷达RpLidar A1进行SLAM定位建图

移动机器人在环境中获取障碍物的具体位置、房间的内部轮廓等信息都是非常必要的,这些信息是机器人创建地图、进行导航的基础数据。考虑成本,买了一个SLAMTEC公司的低成本二维激光雷达RpLidar A1进行初步的学习,它可以最快10hz的频率检测360度范围内的障碍物信息,最远检测距离12米,适合室内移动机器人使用。本文讲解如何使用它感知周围环境。

一、准备工作

1、安装ros对应驱动功能包rplidar

sudo apt install ros-melodic-rplidar-ros

2、硬件连接

接好连接线并插到usb口上,激光雷达会开始旋转。

检查激光雷达是否被正常识别:

lsusb|grep Cygnal

二、测试激光雷达

1、启动激光node节点

roscore
rosrun rplidar_ros rplidarNode
  [ INFO] [1593424905.411970119]: RPLIDAR running on ROS package rplidar_ros. SDK Version:1.7.0
  RPLIDAR S/N: CCE39A87C5E392D5A5E492F85C36316B
  [ INFO] [1593424907.918969787]: Firmware Ver: 1.25
  [ INFO] [1593424907.919051349]: Hardware Rev: 5
  [ INFO] [1593424907.920679886]: RPLidar health status : 0

2、查看激光雷达topic输出的数据

# 查看topic
rostopic list -v|grep scan
  * /scan [sensor_msgs/LaserScan] 1 publisher

# 查看输出数据格式定义
rosmsg show sensor_msgs/LaserScan
    std_msgs/Header header
      uint32 seq
      time stamp
      string frame_id
    float32 angle_min
    float32 angle_max
    float32 angle_increment
    float32 time_increment
    float32 scan_time
    float32 range_min
    float32 range_max
    float32[] ranges
    float32[] intensities

# 输出topic内容
rostopic echo /scan

三、激光数据可视化

# 使用rplidar功能包在rviz中查看激光雷达数据(frame=laser、RPLidarLaserScan Topic=/scan)
roslaunch rplidar_ros view_rplidar.launch

四、使用激光雷达进行SLAM定位建图

SLAM(Simultaneous Localization and Mapping 实时定位与建图)可以简单的理解为机器人在未知环境中从一个未知位置开始移动,移动过程中根据位置估计和地图进行自身定位,同时生成增量式地图,以实现机器人在未知环境中的自主定位和导航。

要完成机器人的slam和自主导航,机器人首先要有感知周围环境的能力,尤其要有感知深度(即距离)信息的能力,激光雷达(价格贵)、双目摄像头(标定较为复杂、运算量大)、RGB-D摄像头(视野窄、盲区大、噪声大)都具备探测深度的能力。

目前slam有较多的开源实现,例如gmapping、hector_slam、cartographer、rgbdslam、orb_slam、move_base、amcl等。本文不详细讨论slam的算法实现,先教会大家怎么使用这些开源库,在后续文章中再深入学习。

# 安装依赖包
sudo apt install ros-melodic-fake-localization ros-melodic-map-server ros-melodic-hector-slam ros-melodic-gmapping ros-melodic-slam-gmapping ros-melodic-open-karto ros-melodic-slam-karto

# 新建ros程序包
cd ~/catkin_ws/src
# catkin_create_pkg <package_name> [depend1] [depend2] [depend3]
catkin_create_pkg ros_slam_rplidar std_msgs rospy roscpp
# 编辑slam launch
cd ~/catkin_ws/src/ros_slam_rplidar/launch/slam/
vim hector.launch    #不需要里程计数据,只根据激光信息即可构建地图
    <!--
    notice : you should install hector-slam at first,  sudo apt-get install ros-melodic-hector-slam
               this launch just for test, you should improve the param for the best result.
     -->
    <launch>
      <node pkg="tf" type="static_transform_publisher" name="link1_broadcaster" args="1 0 0 0 0 0 base_link laser 100" /> <!--change -->
        <node pkg="hector_mapping" type="hector_mapping" name="hector_height_mapping" output="screen">
        <param name="scan_topic" value="scan" />
        <param name="base_frame" value="base_link" />
        <param name="odom_frame" value="base_link" />
        <param name="output_timing" value="false"/>
        <param name="advertise_map_service" value="true"/>
        <param name="use_tf_scan_transformation" value="true"/>
        <param name="use_tf_pose_start_estimate" value="false"/>
        <param name="pub_map_odom_transform" value="true"/>
        <param name="map_with_known_poses" value="false"/>
        <param name="map_pub_period" value="0.5"/>
        <param name="update_factor_free" value="0.45"/>
        <param name="map_update_distance_thresh" value="0.02"/>
        <param name="map_update_angle_thresh" value="0.1"/>
        <param name="map_resolution" value="0.05"/>
        <param name="map_size" value="1024"/>
        <param name="map_start_x" value="0.5"/>
        <param name="map_start_y" value="0.5"/>
      </node>
    </launch>
vim gmapping.launch   #需要IMU+里程计+激光信息构建地图
    <!--
      notice : you should install gmapping-slam at first, command 'sudo apt-get install ros-indigo-gmapping'and 'sudo apt-get install ros-indigo-slam-gmapping'.
               this launch just for test, you should improve the param for the best result.
      you nedd change the frame of the "static_transform_publisher" when using the real robot platform.
      it is better  subscribe the topic /odom with true to slam in gmapping
     -->
    <launch>
      <node pkg="tf" type="static_transform_publisher" name="link1_broadcaster" args="0 0 0 0 0 0 base_link laser 100" /> <!--change -->
      <node pkg="tf" type="static_transform_publisher" name="link2_broadcaster" args="0 0 0 0 0 0 odom base_link 100" /> <!--change -->
      <node pkg="gmapping" type="slam_gmapping" name="simple_gmapping" output="screen">
          <!--remap from="scan" to="base_scan"/-->
          <param name="map_update_interval" value="5.0"/>
          <param name="maxUrange" value="8.0"/>
          <param name="sigma" value="0.05"/>
          <param name="kernelSize" value="1"/>
          <param name="lstep" value="0.05"/>
          <param name="astep" value="0.05"/>
          <param name="iterations" value="5"/>
          <param name="lsigma" value="0.075"/>
          <param name="ogain" value="3.0"/>
          <param name="lskip" value="0"/>
          <param name="minimumScore" value="50"/>
          <param name="srr" value="0.1"/>
          <param name="srt" value="0.2"/>
          <param name="str" value="0.1"/>
          <param name="stt" value="0.2"/>
          <param name="linearUpdate" value="0.3"/>
          <param name="angularUpdate" value="0.4"/>
          <param name="temporalUpdate" value="3.0"/>
          <param name="resampleThreshold" value="0.5"/>
          <param name="particles" value="30"/>
          <param name="xmin" value="-5.0"/>
          <param name="ymin" value="-5.0"/>
          <param name="xmax" value="5.0"/>
          <param name="ymax" value="5.0"/>
          <param name="delta" value="0.05"/>
          <param name="llsamplerange" value="0.01"/>
          <param name="llsamplestep" value="0.01"/>
          <param name="lasamplerange" value="0.005"/>
          <param name="lasamplestep" value="0.005"/>
      </node>
    </launch>

vim karto.launch
    <!--
      notice : you should install karto-slam at first, command 'sudo apt-get install ros-indigo-open-karto'and 'sudo apt-get install ros-indigo-slam-karto'.
              this launch just for test, you should improve the param for the best result.
      you nedd change the frame of the "static_transform_publisher" when using the real robot platform.
      it is better  subscribe the topic /odom with true to slam in gmapping
    -->
    <launch>
      <node pkg="tf" type="static_transform_publisher" name="link1_broadcaster" args="0 0 0 0 0 0 base_link laser 100" /> <!--change -->
      <node pkg="tf" type="static_transform_publisher" name="link2_broadcaster" args="0 0 0 0 0 0 odom base_link 100" /> <!--change -->
      <node pkg="slam_karto" type="slam_karto" name="slam_karto" output="screen">
        <remap from="scan" to="scan"/>
        <param name="odom_frame" value="odom"/>
        <param name="map_update_interval" value="25"/>
        <param name="resolution" value="0.025"/>
        <rosparam command="load" file="$(find ros_slam_rplidar)/launch/slam/karto_mapper_params.yaml" />
      </node>
    </launch>
vim karto_mapper_params.yaml
    # General Parameters
    use_scan_matching: true
    use_scan_barycenter: true
    minimum_travel_distance: 0.3 
    minimum_travel_heading: 0.4  # 0.2         #in radians
    scan_buffer_size: 67                       
    scan_buffer_maximum_scan_distance: 20.0
    link_match_minimum_response_fine: 0.6
    link_scan_maximum_distance: 4         #  6
    do_loop_closing: true
    loop_match_minimum_chain_size: 5
    loop_match_maximum_variance_coarse: 0.4    # gets squared later
    loop_match_minimum_response_coarse: 0.4        # 0.6
    loop_match_minimum_response_fine: 0.6
    # Correlation Parameters -              Correlation Parameters
    correlation_search_space_dimension: 2
    correlation_search_space_resolution: 0.05
    correlation_search_space_smear_deviation: 0.05
    # Correlation Parameters - Loop Closure Parameters
    loop_search_space_dimension: 10  # 2.8
    loop_search_space_resolution: 0.1
    loop_search_space_smear_deviation: 0.05
    loop_search_maximum_distance: 4.0
    # Scan Matcher Parameters
    distance_variance_penalty: 0.3             # gets squared later
    angle_variance_penalty: 0.35                # in degrees (gets converted to radians then squared)
    fine_search_angle_offset: 0.00349               # in degrees (gets converted to radians)
    coarse_search_angle_offset: 0.349            # in degrees (gets converted to radians)
    coarse_angle_resolution: 0.0349                # in degrees (gets converted to radians)
    minimum_angle_penalty: 0.9
    minimum_distance_penalty: 0.5
    use_response_expansion: false

# 编辑slam rviz
cd ~/catkin_ws/src/ros_slam_rplidar/rviz/
vim slam.rviz
    Panels:
      - Class: rviz/Displays
        Help Height: 78
        Name: Displays
        Property Tree Widget:
          Expanded:
            - /Global Options1
            - /Status1
            - /RPLidarLaserScan1
          Splitter Ratio: 0.5
        Tree Height: 413
      - Class: rviz/Selection
        Name: Selection
      - Class: rviz/Tool Properties
        Expanded:
          - /2D Pose Estimate1
          - /2D Nav Goal1
        Name: Tool Properties
        Splitter Ratio: 0.588679
      - Class: rviz/Views
        Expanded:
          - /Current View1
        Name: Views
        Splitter Ratio: 0.5
      - Class: rviz/Time
        Experimental: false
        Name: Time
        SyncMode: 0
        SyncSource: RPLidarLaserScan
    Visualization Manager:
      Class: ""
      Displays:
        - Alpha: 0.5
          Cell Size: 1
          Class: rviz/Grid
          Color: 160; 160; 164
          Enabled: true
          Line Style:
            Line Width: 0.03
            Value: Lines
          Name: Grid
          Normal Cell Count: 0
          Offset:
            X: 0
            Y: 0
            Z: 0
          Plane: XY
          Plane Cell Count: 10
          Reference Frame: <Fixed Frame>
          Value: true
        - Alpha: 1
          Autocompute Intensity Bounds: true
          Autocompute Value Bounds:
            Max Value: 0
            Min Value: 0
            Value: true
          Axis: Z
          Channel Name: intensity
          Class: rviz/LaserScan
          Color: 255; 255; 255
          Color Transformer: AxisColor
          Decay Time: 0
          Enabled: true
          Invert Rainbow: false
          Max Color: 255; 255; 255
          Max Intensity: 4096
          Min Color: 0; 0; 0
          Min Intensity: 0
          Name: RPLidarLaserScan
          Position Transformer: XYZ
          Queue Size: 1000
          Selectable: true
          Size (Pixels): 5
          Size (m): 0.03
          Style: Squares
          Topic: /scan
          Use Fixed Frame: true
          Use rainbow: true
          Value: true
        - Alpha: 0.7
          Class: rviz/Map
          Color Scheme: map
          Draw Behind: false
          Enabled: true
          Name: Map
          Topic: /map
          Value: true
      Enabled: true
      Global Options:
        Background Color: 48; 48; 48
        Fixed Frame: map
        Frame Rate: 30
      Name: root
      Tools:
        - Class: rviz/MoveCamera
        - Class: rviz/Interact
          Hide Inactive Objects: true
        - Class: rviz/Select
        - Class: rviz/SetInitialPose
          Topic: /initialpose
        - Class: rviz/SetGoal
          Topic: /move_base_simple/goal
      Value: true
      Views:
        Current:
          Class: rviz/Orbit
          Distance: 11.1184
          Enable Stereo Rendering:
            Stereo Eye Separation: 0.06
            Stereo Focal Distance: 1
            Swap Stereo Eyes: false
            Value: false
          Focal Point:
            X: -0.0344972
            Y: 0.065886
            Z: 0.148092
          Name: Current View
          Near Clip Distance: 0.01
          Pitch: 1.5698
          Target Frame: <Fixed Frame>
          Value: Orbit (rviz)
          Yaw: 5.66358
        Saved: ~
    Window Geometry:
      Displays:
        collapsed: false
      Height: 626
      Hide Left Dock: false
      Hide Right Dock: false
      QMainWindow State: 000000ff00000000fd0000000400000000000001950000022cfc0200000006fb0000001200530065006c0065006300740069006f006e00000001e10000009b0000006400fffffffb0000001e0054006f006f006c002000500072006f0070006500720074006900650073020000019b000001b500000185000000a3fb000000120056006900650077007300200054006f006f02000001df000002110000018500000122fb000000200054006f006f006c002000500072006f0070006500720074006900650073003203000002880000011d000002210000017afb000000100044006900730070006c00610079007301000000280000022c000000dd00fffffffb0000000a0049006d006100670065000000028d000000c60000000000000000000000010000010b00000294fc0200000003fb0000001e0054006f006f006c002000500072006f00700065007200740069006500730100000041000000780000000000000000fb0000000a00560069006500770073000000003300000294000000b000fffffffb0000001200530065006c0065006300740069006f006e010000025a000000b200000000000000000000000200000490000000a9fc0100000001fb0000000a00560069006500770073030000004e00000080000002e10000019700000003000004a00000003efc0100000002fb0000000800540069006d00650000000000000004a0000002f600fffffffb0000000800540069006d00650100000000000004500000000000000000000003240000022c00000004000000040000000800000008fc0000000100000002000000010000000a0054006f006f006c00730100000000ffffffff0000000000000000
      Selection:
        collapsed: false
      Time:
        collapsed: false
      Tool Properties:
        collapsed: false
      Views:
        collapsed: false
      Width: 1215
      X: 503
      Y: 227

# 编辑view slam launch
cd ~/catkin_ws/src/ros_slam_rplidar/launch/
vim slam_laser.launch
    <!-- SLAM with lidar -->
    <launch>
      <!-- Arguments -->
      <arg name="slam_methods" default="hector" doc="slam type [gmapping, hector, karto, cartographer]"/>
      <arg name="open_rviz" default="false"/>
      <arg name="planner"  default="" doc="opt: dwa, teb"/>

      <!-- robot with lidar -->
      <include file="$(find rplidar_ros)/launch/rplidar.launch" />

      <!-- SLAM: Gmapping, Cartographer, Hector, Karto -->
      <include file="$(find ros_slam_rplidar)/launch/slam/$(arg slam_methods).launch" />

      <!-- move_base -->
      <group unless="$(eval planner == '')">
        <include file="$(find ros_slam_rplidar)/launch/move_base.launch" unless="$(eval planner == '')">
            <arg name="planner"            value="$(arg planner)"/>
        </include>
      </group>

      <!-- rviz -->
      <group if="$(arg open_rviz)">
        <node name="rviz" pkg="rviz" type="rviz" args="-d $(find ros_slam_rplidar)/rviz/slam.rviz" />
      </group>
    </launch>

# 测试hector slam并通过rviz展示
roslaunch ros_slam_rplidar slam_laser.launch open_rviz:=true

示例代码地址:https://github.com/yanjingang/ros_slam_rplidar

手持rplidar雷达大概转了转,构建出的地图:(map topic是hector_mapping发布的地图珊格数据) 

可以看到建出来的地图效果不太好,这里有个原因是我手拿着雷达移动时高度和角度都不稳定,下一步我们把它固定到小车上上再试下。

五、坦克小车SLAM建图

1、安装到树莓派

为了方便在小车上使用,我们需要把相关环境安装到树莓派上。

# 安装rplidar、hector、gmapping源码包
cd ~/ros_catkin_ws
rosinstall_generator desktop rosserial rplidar_ros hector_slam gmapping slam_gmapping --rosdistro melodic --deps --wet-only --tar > melodic-desktop-wet.rosinstall
wstool merge -t src melodic-desktop-wet.rosinstall
wstool update -t src
rosdep install -y --from-paths src --ignore-src --rosdistro melodic -r --os=debian:$(lsb_release -cs)
sudo ./src/catkin/bin/catkin_make_isolated --install -DCMAKE_BUILD_TYPE=Release --install-space /opt/ros/melodic


# 测试rplidar
roslaunch rplidar_ros view_rplidar.launch

*注:树莓派USB电流问题:

树莓派USB输出电流是1200mA,rplidar的启动电源电流需要1500mA,所以热插拔会导致系统重启,所以一定先关机再插拔rplidar。

2、构建地图并保存

# 测试slam 
roslaunch ros_slam_rplidar slam_laser.launch  open_rviz:=true
# 手动保存map
roscd ros_slam_rplidar/maps/
rosrun map_server map_saver -f map

建好的局部地图:

好了,本文就讲到这里,下一篇我们让小车脱离数据线的束缚,构建完整的地图并进行路径规划和避障。

yan 7.12  21:40

欢迎关注下方“非著名资深码农“公众号进行交流~

发表评论

邮箱地址不会被公开。