4- LIO SAM+ Move_base 实现自主导航

遥感摆烂人 / 2024-11-13 / 原文

在前面的工作中,我们成功使用了gmapping +move_base实现自主导航,并且成功在仿真环境中运行了lio sam,今天打算结合,采用LIO-SAM建图和定位,move_base实现导航。大致内容如下:

仿真环境准备

在之前的内容中,已经介绍了仿真实验环境怎么搭建,具体可以参考链接:
https://www.cnblogs.com/binbin2002/p/18296477

LIO SAM安装配置

LIO SAM作为一个开源的紧耦合的SLAM算法,网上教程太多了,这里贴几个个人觉得写的比较好的链接:
https://py1995.blog.csdn.net/article/details/137286327?spm=1001.2014.3001.5502
https://blog.csdn.net/weixin_40653140/article/details/137235669?spm=1001.2014.3001.5506

安装Octomap Server

https://blog.csdn.net/qq_41694024/article/details/134703116?spm=1001.2014.3001.5506

Octomap的安装

采用命令的形式安装octomap server功能包

sudo apt install ros-melodic-octomap-msgs ros-melodic-octomap-ros ros-melodic-octomap-rviz-plugins ros-melodic-octomap-server

img

Octomap节点的使用,构建octomap和occupied map

我们新建一个launch文件,在launch文件中输入以下内容:

<launch>
    <node pkg="octomap_server" type="octomap_server_node" name="octomap_server">
    <!-- 地图分辨率 -->
	<param name="resolution" value="0.50" />
		
	<!-- fixed map frame (set to 'map' if SLAM or localization running!)  -->
    <!-- 静态全局地图的 frame_id,但在增量式构建地图时,需要提供输入的点云帧和静态全局帧之间的 TF 变换 -->
	<param name="frame_id" type="string" value="map" />
		
	<!-- maximum range to integrate (speedup!) -->
    <!-- 传感器最大感知范围 -->
	<param name="sensor_model/max_range" value="50.0" />
    <param name="latch" value="true" />


  
     <!--max/min height for occupancy map, should be in meters-->
     <!-- 保留的z轴范围内的点 -->
    <param name="pointcloud_max_z" value="5" />
    <param name="pointcloud_min_z" value="-1.5" />

    <!-- 机器人坐标系 base_link,滤除地面需要该 frame -->
    <param name = "base_frame_id" type = "string" value = "base_link" /> 
      <!-- filter ground plane, distance value should be big!  -->
	<param name = "filter_ground" type = "bool" value = "true" /> 

     
    <!-- 要检测为平面的 Z 轴阈值 value 值 通常大于分割值  -->
	<param name = "ground_filter/plane_distance" type = "double" value = "0.4" /> 

    <!-- 分割地面的 Z 轴阈值 value 值 ,小于该阈值被认为是平面 -->
    <param name = "ground_filter/distance" type = "double" value = "0.3" /> 
    <!-- 分割地面的角度阈值 value 值,小于该阈值的平面被认为是地面-->
    <param name="ground_filter/angle" value="0.10" />


		<!-- data source to integrate (PointCloud2) -->
	<remap from="cloud_in" to="/lio_sam/deskew/cloud_deskewed" />
		<!-- <remap from="cloud_in" to="voxel_grid/output" /> -->
	
	</node>
</launch>

这里面各个参数的含义解释:

	resolution:分辨率或精度,越小精度越高计算需要资源越庞大

	frame_id:世界坐标系的话题,即原点坐标系

	sensor_model/max_range:扫描的最大距离

	cloud_in:点云话题

	pointcloud_max_z:最大的Z扫描值

	pointcloud_min_z:最小的Z扫描值(激光雷达和垂直平面有一定距离)

当然还有地面剔除相关参数:

	filter_ground:是否采用地面去除
	
	ground_filter/plane_distance:要检测为平面的 Z 轴阈值 value 值 通常大于平面阈值
	
	ground_filter/distance:要检测为平面的z轴阈值,低于这个值被认为是平面
	
	ground_filter/angle:分割地面的的角度阈值,低于这个值的平面被认为是地面

img

RVIZ显示和地图保存

发布以后,使用rostopic list可以看到octomap相关话题,也可以在rviz中选择话题名称显示。

源码编译使用

当然还可以使用源码编译的方法完成上述:相关操作参考我的github链接:https://github.com/binbin2002/octomap_with_slam

安装Pointcloud_to_Laserscan

sudo apt-get install ros-melodic-tf2-sensor-msgs

在launch文件中添加以下内容:

<?xml version="1.0"?>

<launch>
    <!-- run pointcloud_to_laserscan node -->
    <node pkg="pointcloud_to_laserscan" type="pointcloud_to_laserscan_node" name="pointcloud_to_laserscan">
						 <!-- 重映射订阅的cloud_in和发布的scan话题 -->
         <remap from="cloud_in" to="/non_ground_point"/>
    				<remap from="scan" to="base_scan"/>
					
       <rosparam>
        target_frame: base_link # Leave disabled to output scan in pointcloud frame
        transform_tolerance: 0.01
        min_height: -0.2
        max_height: 1.0

        angle_min: -3.1415926 # -M_PI
        angle_max: 3.1415926 # M_PI
        angle_increment: 0.003 # 0.17degree
        scan_time: 0.1
        range_min: 1.0
        range_max: 50
        use_inf: true
        inf_epsilon: 1.0

        # Concurrency level, affects number of pointclouds queued for processing and number of threads used
        # 0 : Detect number of cores
        # 1 : Single threaded
        # 2->inf : Parallelism level
        concurrency_level: 1
    </rosparam>

    </node>

</launch>

Move_base配置

这里只对关键内容进行进一步说明,采用官方给定的move_base文档:http://wiki.ros.org/move_base,
Move_base的核心图来讲解

img

图中,白色部分是move_base必须有的且已经实现的部分,灰色是我们可以提供的,蓝色是必须需要的。
通过查看move_base订阅和发布的topic来看,实践上我们只需要关注以下几个move_base关键的topic就行

  • /odom :Move_base订阅的里程计信息,
  • /map :Move_base订阅的地图服务信息
  • /scan:Move_base订阅的激光数据信息

在lio sam中,/odom需要remap为/lio_sam/mapping/odometry, /scan需要remap成pointcloud_to_laserscan发布的/base_scan /map则不需要变,对应的整体参数如下:参数用默认的yaml文件即可,也可根据需要自行调整。

</node>
    <node pkg="move_base" type="move_base" respawn="false" name="move_base" output="screen">
        <remap from="odom" to="/lio_sam/mapping/odometry"/>
        <remap from="scan" to="/base_scan"/>
        <remap from="cmd_vel" to="robot1/cmd_vel"/>

        <rosparam file="$(find gazebo_pioneer3at)/param/costmap_common_params.yaml" command="load" ns="global_costmap" />
        <rosparam file="$(find gazebo_pioneer3at)/param/costmap_common_params.yaml" command="load" ns="local_costmap" />
        <rosparam file="$(find gazebo_pioneer3at)/param/local_costmap_params.yaml" command="load" />
        <rosparam file="$(find gazebo_pioneer3at)/param/global_costmap_params.yaml" command="load" />
        <rosparam file="$(find gazebo_pioneer3at)/param/planner.yaml" command="load" />
        <param name="base_global_planner" value="global_planner/GlobalPlanner" />
        <param name="planner_frequency" value="1.0" />
        <param name="planner_patience" value="5.0" />
        <param name="base_local_planner" value="base_local_planner/TrajectoryPlannerROS" />
        <param name="controller_frequency" value="5.0" />
        <param name="controller_patience" value="15.0" />
        <param name="clearing_rotation_allowed" value="true" />
    </node>
		<!--  需要用navigation对应的rviz,默认rviz不能发布目标点,ps:不知道问题在哪  -->
		<node pkg="rviz" type="rviz" name="octomap_rviz" args="-d $(find gmapping)/navigation.rviz" />
		

img

运行效果截图

实验仿真环境
img

运行效果图(左 lio sam效果图 右 导航地图)
img