奥特学园ROS笔记--7(289-325节)

目录

机器人导航

289-292节 导航各种简介

293-294节 坐标系

295节 导航条件

------------导航基本流程-------------

297节 gmapping简介

298-299节 gmapping的使用

300节 保存gmapping创建的地图

301节 读取之前保存的地图

302节 mapserver地图配置文件

303-304节 amcl定位

305节 move_base简介

306节 move_base 节点说明

307-308节 move_base 代价地图

309节 代价值计算(碰撞算法)

310-314节 move base 使用

315节 导航和建图同时

------------导航相关消息------------

316-322节 (看视频)

323-325节 深度图像转激光数据 这部分待完成


机器人导航

主要内容有:

  • 导航相关概念
  • 导航实现:机器人建图(SLAM)、地图服务、定位、路径规划....以可视化操作为主。
  • 导航消息:了解地图、里程计、雷达、摄像头等相关消息格式。

预期达成的学习目标:

  • 了解导航模块中的组成部分以及相关概念
  • 能够在仿真环境下独立完成机器人导航

289-292节 导航各种简介

总结下来,涉及的关键技术有如下五点:

  1. 全局地图(全局概览图:定位+路径规划)

  2. 自身定位(确定在地图中的位置)

  3. 路径规划(全局路径规划(起点和终点)+局部路径规划(行进过程中的路径规划))

  4. 运动控制(控制速度和方向)

  5. 环境感知(感知周围环境)

ROS 官方为了提供了一张导航功能包集的图示,该图中囊括了 ROS 导航的一些关键技术

图中左侧3个方框用于自身定位,主要分为两类:amcl和odometry,前者使用的是传感器和坐标变换,后者通过的是里程计来估算自己的位置。

中间的一个大方框用于路径规划

base_controller用于运动控制

sensor sources用于环境感知

右下角的三个标表示白色是必须的,灰色是可选的,蓝色的是

全局地图:

SLAM(simultaneous localization and mapping),也称为CML (Concurrent Mapping and Localization), 即时定位与地图构建,或并发建图与定位。SLAM问题可以描述为: 机器人在未知环境中从一个未知位置开始移动,在移动过程中根据位置估计和地图进行自身定位,同时在自身定位的基础上建造增量式地图,以绘制出外部环境的完全地图。

在 ROS 中,较为常用的 SLAM 实现也比较多,比如: gmapping、hector_slam、cartographer、rgbdslam、ORB_SLAM ....

本章介绍的是gmapping

SLAM 可以用于地图生成创建,而生成的地图还需要被保存以待后续使用,在 ROS 中保存地图的功能包是 map_server

另外注意: SLAM 虽然是机器人导航的重要技术之一,但是 二者并不等价,确切的讲,SLAM 只是实现地图构建和即时定位。

自身定位:

导航伊始和导航过程中,机器人都需要确定当前自身的位置,如果在室外,那么 GPS 是一个不错的选择,而如果室内、隧道、地下或一些特殊的屏蔽 GPS 信号的区域,由于 GPS 信号弱化甚至完全不可用,那么就必须另辟蹊径了,比如前面的 SLAM 就可以实现自身定位,除此之外,ROS 中还提供了一个用于定位的功能包: amcl

amcl(adaptiveMonteCarloLocalization)自适应的蒙特卡洛定位,是用于2D移动机器人的概率定位系统。它实现了自适应(或KLD采样)蒙特卡洛定位方法,该方法使用粒子过滤器根据已知地图跟踪机器人的姿态。

路径规划:

导航就是机器人从A点运动至B点的过程,在这一过程中,机器人需要根据目标位置计算全局运动路线,并且在运动过程中,还需要时时根据出现的一些动态障碍物调整运动路线,直至到达目标点,该过程就称之为路径规划。在 ROS 中提供了 move_base 包来实现路径规则,该功能包主要由全局路径规划或者本地路径规划组成。

运动控制:

导航功能包集假定它可以通过话题"cmd_vel"发布geometry_msgs/Twist类型的消息,这个消息基于机器人的基座坐标系,它传递的是运动命令。这意味着必须有一个节点订阅"cmd_vel"话题, 将该话题上的速度命令转换为电机命令并发送

环境感知:

感知周围环境信息,比如: 摄像头、激光雷达、编码器...,摄像头、激光雷达可以用于感知外界环境的深度信息,编码器可以感知电机的转速信息,进而可以获取速度信息并生成里程计信息。

在导航功能包集中,环境感知也是一重要模块实现,它为其他模块提供了支持。其他模块诸如: SLAM、amcl、move_base 都需要依赖于环境感知。

293-294节 坐标系

定位实现需要依赖于机器人自身,机器人需要逆向推导参考系原点并计算坐标系相对关系,该过程实现常用方式有两种:

  • 通过里程计定位:时时收集机器人的速度信息计算并发布机器人坐标系与父级参考系的相对关系。
  • 通过传感器定位:通过传感器收集外界环境信息通过匹配计算并发布机器人坐标系与父级参考系的相对关系。

里程计定位:

  • 优点:里程计定位信息是连续的,没有离散的跳跃。
  • 缺点:里程计存在累计误差,不利于长距离或长期定位。

传感器定位:

  • 优点:比里程计定位更精准;
  • 缺点:传感器定位会出现跳变的情况,且传感器定位在标志物较少的环境下,其定位精度会大打折扣。

两种方式在导航中都会经常使用。两种定位方式优缺点互补,应用时一般二者结合使用。

坐标系变换

上述两种定位实现中,机器人坐标系一般使用机器人模型中的根坐标系(base_link 或 base_footprint),里程计定位时,父级坐标系一般称之为 odom,如果通过传感器定位,父级参考系一般称之为 map。当二者结合使用时,map 和 odom 都是机器人模型根坐标系的父级,这是不符合坐标变换中"单继承"的原则的,所以,一般会将转换关系设置为: map-doom-base_link或base_footprint(即map是odom的父级)。         

295节 导航条件

硬件:差速的、底盘上有一个单线激光雷达、最好是正方形或者圆形

软件:ROS安装、上一节的仿真环境可以正常执行。

------------导航基本流程-------------

本节内容主要介绍导航的完整性实现,旨在掌握机器人导航的基本流程,该章涉及的主要内容如下:

  • SLAM建图(选用较为常见的gmapping)

  • 地图服务(可以保存和重现地图)

  • 机器人定位

  • 路径规划

  • 上述流程介绍完毕,还会对功能进一步集成实现探索式的SLAM建图。

准备工作

请先安装相关的ROS功能包:

  • 安装 gmapping 包(用于构建地图):sudo apt install ros-<ROS版本>-gmapping

  • 安装地图服务包(用于保存与读取地图):sudo apt install ros-<ROS版本>-map-server

  • 安装 navigation 包(用于定位以及路径规划):sudo apt install ros-<ROS版本>-navigation

新建功能包,并导入依赖: gmapping map_server amcl move_base

297节 gmapping简介

gmapping 功能包中的核心节点是:slam_gmapping。为了方便调用,需要先了解该节点订阅的话题、发布的话题、服务以及相关参数。

订阅的Topic:

tf (tf/tfMessage):用于雷达、底盘与里程计之间的坐标变换消息。

scan(sensor_msgs/LaserScan):SLAM所需的雷达信息。

发布的Topic:
map_metadata(nav_msgs/MapMetaData):地图元数据,包括地图的宽度、高度、分辨率等,该消息会固定更新。

map(nav_msgs/OccupancyGrid):地图栅格数据,一般会在rviz中以图形化的方式显示。

~entropy(std_msgs/Float64):机器人姿态分布熵估计(值越大,不确定性越大)。

服务:

dynamic_map(nav_msgs/GetMap):用于获取地图数据。

参数:

~base_frame(string, default:"base_link"):机器人基坐标系。

~map_frame(string, default:"map"):地图坐标系。

~odom_frame(string, default:"odom"):里程计坐标系。

~map_update_interval(float, default: 5.0):地图更新频率,根据指定的值设计更新间隔。

~maxUrange(float, default: 80.0):激光探测的最大可用范围(超出此阈值,被截断)。

~maxRange(float):激光探测的最大范围

.... 参数较多,上述是几个较为常用的参数,其他参数介绍可参考官网。

298-299节 gmapping的使用

launch文件实现

创建文件并且编写代码

<launch>
<param name="use_sim_time" value="true"/>   <!-- 仿真环境下将该参数设置为true -->
    <node pkg="gmapping" type="slam_gmapping" name="slam_gmapping" output="screen">
      <remap from="scan" to="scan"/>    <!-- 设置雷达话题,之前仿真环境中我们设置的名称就叫scan -->

      <!-- 关键参数:坐标系 -->
      <param name="base_frame" value="base_footprint"/><!--底盘坐标系-->
      <param name="odom_frame" value="odom"/> <!--里程计坐标系-->
      <param name="map_frame" value="map"/> <!--地图坐标系-->
      
      
      <param name="map_update_interval" value="5.0"/>   <!-- 地图更新时间 -->
      <param name="maxUrange" value="16.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="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="1.0"/>
      <param name="angularUpdate" value="0.5"/>
      <param name="temporalUpdate" value="3.0"/>
      <param name="resampleThreshold" value="0.5"/>
      <param name="particles" value="30"/>
      <param name="xmin" value="-50.0"/>
      <param name="ymin" value="-50.0"/>
      <param name="xmax" value="50.0"/>
      <param name="ymax" value="50.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>

    <node pkg="joint_state_publisher" name="joint_state_publisher" type="joint_state_publisher" />
    <node pkg="robot_state_publisher" name="robot_state_publisher" type="robot_state_publisher" />

    <node pkg="rviz" type="rviz" name="rviz" />
    <!-- 可以保存 rviz 配置并后期直接使用-->
    <!--
    <node pkg="rviz" type="rviz" name="rviz" args="-d $(find my_nav_sum)/rviz/gmapping.rviz"/>
    -->
</launch>

执行

1:先启动 Gazebo 仿真环境,启动了之前的环境:

 2.然后再启动地图绘制的 launch 文件,执行上节写好的launch文件

3.启动键盘控制节点

rosrun teleop_twist_keyboard teleop_twist_keyboard.py

4.在 rviz 中添加组件,显示栅格地图

 然后环绕一圈即可建图

这里可以发现odom的tf坐标是指向map的,这也印证了之前293节讲的内容

300节 保存gmapping创建的地图

上一节我们已经实现通过gmapping的构建地图并在rviz中显示了地图,不过,上一节中地图数据是保存在内存中的,当节点关闭时,数据也会被一并释放,我们需要将栅格地图序列化到的磁盘以持久化存储,后期还要通过反序列化读取磁盘的地图数据再执行后续操作。在ROS中,地图数据的序列化与反序列化可以通过 map_server 功能包实现。

map_server功能包中提供了两个节点: map_saver 和 map_server,前者用于将栅格地图保存到磁盘,后者读取磁盘的栅格地图并以服务的方式提供出去。

地图保存到launch文件:

<launch>
    <arg name="filename" value="$(find mycar_nav)/map/nav" />
    <node name="map_save" pkg="map_server" type="map_saver" args="-f $(arg filename)" />
</launch>

这里将mycar_nav改为我们自己的nav_demo,然后创建map文件夹运行即可

301节 读取之前保存的地图

launch文件内容

<launch>
    <!-- 设置地图的配置文件 -->
    <arg name="map" default="nav.yaml" />  <!-- nav.yaml是根据之前保存生成的文件名称来动态指定的 -->
    <!-- 运行地图服务器,并且加载设置的地图-->
    <node name="map_server" pkg="map_server" type="map_server" args="$(find nav_demo)/map/$(arg map)"/>
    <!-- <node name="map_server" pkg="map_server" type="map_server" args="$(find nav_demo)/map/nav.yaml"/> -->
</launch>

这个launch文件运行之后就会把我们的保存好的地图通过默认的topic发布出去,然后再rviz中利用topic来查看即可

我们运行这个launch文件

然后命令行输入rviz打开一个空白的rviz,add map即可看到之前保存的地图

302节 mapserver地图配置文件

本节主要介绍之前保存地图所产生的yaml文件里面的内容

这个yaml保存的是图像的各种信息,可以对其进行修改来调整map在rviz中的各种显示

image: /home/gzy/ROS/autolabor/demo5_ws/src/nav_demo/map/nav.pgm  #声明地图图片资源的路径(相对或者绝对路径,这里是绝对)
resolution: 0.050000                            #地图刻度尺 单位是米/像素 这里是一个像素代表5cm
origin: [-50.000000, -50.000000, 0.000000]  #地图的位姿信息,相对于rviz中原点的位姿,三个值分别对应x、y和偏航角度
occupied_thresh: 0.65                     #占用阈值
free_thresh: 0.196                        #空闲阈值  这两者阈值结合用于判断某个像素是不是障碍物,
#障碍物一般判断规则:白色的可通行区域,黑色是障碍物,蓝灰色是未知区域
#地图中每个像素都有取值[0,255],白色255 黑色0
#根据像素值计算一个比例p=(255-x)/255  (x是像素的取值)  白色就是0,黑色就是1,灰色就是结余0-1之间
#判断是否是障碍物 p>occupied_thresh(占用阈值) 就是障碍物   小于就是自由通行区域
negate: 0                           #是否取反,地图上白色的变成黑色黑色变成白色

303-304节 amcl定位

在ROS的导航功能包集navigation中提供了 amcl 功能包,用于实现导航中的机器人定位。

简介:

AMCL(adaptive Monte Carlo Localization) 是用于2D移动机器人的概率定位系统,它实现了自适应(或KLD采样)蒙特卡洛定位方法,可以根据已有地图使用粒子滤波器推算机器人位置。

amcl已经被集成到了navigation包,navigation安装前面也有介绍,命令如下:

sudo apt install ros-<ROS版本>-navigation

使用

编写amcl相关的launch文件:

这里我们可以使用以下命令来查看amcl的模板来直接复制修改即可

<launch>
<node pkg="amcl" type="amcl" name="amcl" output="screen">
  <!-- Publish scans from best pose at a max of 10 Hz -->
  <param name="odom_model_type" value="diff"/><!-- 里程计模式为差分 -->
  <param name="odom_alpha5" value="0.1"/>
  <param name="transform_tolerance" value="0.2" />
  <param name="gui_publish_rate" value="10.0"/>
  <param name="laser_max_beams" value="30"/>
  <param name="min_particles" value="500"/>
  <param name="max_particles" value="5000"/>
  <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"/>
  <!-- translation std dev, m -->
  <param name="odom_alpha3" value="0.8"/>
  <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_lambda_short" value="0.1"/>
  <param name="laser_model_type" value="likelihood_field"/>
  <!-- <param name="laser_model_type" value="beam"/> -->
  <param name="laser_likelihood_max_dist" value="2.0"/>
  <param name="update_min_d" value="0.2"/>
  <param name="update_min_a" value="0.5"/>

  <param name="odom_frame_id" value="odom"/><!-- 里程计坐标系 -->
  <param name="base_frame_id" value="base_footprint"/><!-- 添加机器人基坐标系 -->
  <param name="global_frame_id" value="map"/><!-- 添加地图坐标系 -->

  <param name="resample_interval" value="1"/>
  <param name="transform_tolerance" value="0.1"/>
  <param name="recovery_alpha_slow" value="0.0"/>
  <param name="recovery_alpha_fast" value="0.0"/>
</node>
</launch>

test.launch 文件:

<!-- 测试文件 -->
<launch>
    <!-- 启动rviz -->
    <node pkg="joint_state_publisher" name="joint_state_publisher" type="joint_state_publisher" />
    <node pkg="robot_state_publisher" name="robot_state_publisher" type="robot_state_publisher" />
    <node pkg="rviz" type="rviz" name="rviz" />

    <!-- 运行地图服务器,并且加载设置的地图 nav03的内容-->
    <arg name="map" default="nav.yaml" />
    <node name="map_server" pkg="map_server" type="map_server" args="$(find nav_demo)/map/$(arg map)"/>
    
    <!-- 启动AMCL节点 -->
    <include file="$(find nav_demo)/launch/nav04_amcl.launch" />

</launch>

1.先启动 Gazebo 仿真环境  demo03_env.launch

2.启动键盘控制节点:

rosrun teleop_twist_keyboard teleop_twist_keyboard.py

3.启动上一步中集成地图服务、amcl 与 rviz 的 test.launch 文件;

4.在启动的 rviz 中,添加RobotModel、Map组件,分别显示机器人模型与地图,添加 posearray 插件,设置topic为particlecloud来显示 amcl 预估的当前机器人的位姿,箭头越是密集,说明当前机器人处于此位置的概率越高;

5.通过键盘控制机器人运动,会发现 posearray 也随之而改变

305节 move_base简介

毋庸置疑的,路径规划是导航中的核心功能之一,在ROS的导航功能包集navigation中提供了 move_base 功能包,用于实现此功能。

move_base 功能包提供了基于动作(action:即在移动过程中要进行进度的报告)的路径规划实现,move_base 可以根据给定的目标点,控制机器人底盘运动至目标位置,并且在运动过程中会连续反馈机器人自身的姿态与目标点的状态信息。如前所述(7.1)move_base主要由全局路径规划与本地路径规划组成。

move_base已经被集成到了navigation包,navigation安装前面也有介绍,命令如下:

sudo apt install ros-<ROS版本>-navigation

306节 move_base 节点说明

7.2.4 导航实现04_路径规划 · Autolabor-ROS机器人入门课程《ROS理论与实践》零基础教程

307-308节 move_base 代价地图

给图中每个像素设置一个代价值,比如254就是一定会发生碰撞,80、90之类的就是可能会发生碰撞,这就是代价地图。从而可以根据像素的代价值来规划路径。

机器人导航(尤其是路径规划模块)是依赖于地图的,地图在SLAM时已经有所介绍了,ROS中的地图其实就是一张图片,这张图片有宽度、高度、分辨率等元数据,在图片中使用灰度值来表示障碍物存在的概率。不过SLAM构建的地图在导航中是不可以直接使用的,因为:

 1 SLAM构建的地图是静态地图,而导航过程中,障碍物信息是可变的,可能障碍物被移走了,也可能添加了新的障碍物,导航中需要时时的获取障碍物信息;

2 在靠近障碍物边缘时,虽然此处是空闲区域,但是机器人在进入该区域后可能由于其他一些因素,比如:惯性、或者不规则形体的机器人转弯时可能会与障碍物产生碰撞,安全起见,最好在地图的障碍物边缘设置警戒区,尽量禁止机器人进入...

所以,静态地图无法直接应用于导航,其基础之上需要添加一些辅助信息的地图,比如时时获取的障碍物数据,基于静态地图添加的膨胀区等数据。

组成:

代价地图有两张:global_costmap(全局代价地图) 和 local_costmap(本地代价地图),前者用于全局路径规划,后者用于本地路径规划。

两张代价地图都可以多层叠加,一般有以下层级:

  • 静态层:SLAM绘制的静态地图。

  • 障碍物层:导航中传感器感知的障碍物。

  • 膨胀层:在以上两层地图上进行膨胀(向外扩张),以避免机器人的外壳会撞上障碍物。

  • 自定义层:根据业务自己设置的一些地图数据,比如可以在导航的过程中添加一个之前slam建图的时候没有建的虚拟墙。

309节 代价值计算(碰撞算法)

上图中,横轴是距离机器人中心的距离,纵轴是代价地图中栅格的灰度值。

  • 致命障碍:栅格值为254,此时障碍物与机器人中心重叠,必然发生碰撞;
  • 内切障碍:栅格值为253,此时障碍物处于机器人的内切圆内,必然发生碰撞;
  • 外切障碍:栅格值为[128,252],此时障碍物处于其机器人的外切圆内,处于碰撞临界,不一定发生碰撞;
  • 非自由空间:栅格值为(0,127],此时机器人处于障碍物附近,属于危险警戒区,进入此区域,将来可能会发生碰撞;
  • 自由区域:栅格值为0,此处机器人可以自由通过;
  • 未知区域:栅格值为255,还没探明是否有障碍物。

310-314节 move base 使用

路径规划算法在move_base功能包的move_base节点中已经封装完毕了,但是还不可以直接调用,因为算法虽然已经封装了,但是该功能包面向的是各种类型支持ROS的机器人,不同类型机器人可能大小尺寸不同,传感器不同,速度不同,应用场景不同....最后可能会导致不同的路径规划结果,那么在调用路径规划节点之前,我们还需要配置机器人参数。具体实现如下:

1 先编写launch文件模板

<launch>
    <!-- 启动movebase节点 -->
    <node pkg="move_base" type="move_base" respawn="false" name="move_base" output="screen" clear_params="true">
        <rosparam file="$(find nav_demo)/param/costmap_common_params.yaml" command="load" ns="global_costmap" />
        <rosparam file="$(find nav_demo)/param/costmap_common_params.yaml" command="load" ns="local_costmap" />
        <rosparam file="$(find nav_demo)/param/local_costmap_params.yaml" command="load" />
        <rosparam file="$(find nav_demo)/param/global_costmap_params.yaml" command="load" />
        <rosparam file="$(find nav_demo)/param/base_local_planner_params.yaml" command="load" />
    </node>

</launch>

2 编写配置文件

在nav_demo下创建上面launch文件中的param文件夹和四个文件

 然后分辨编写四个文件

4.2.1costmap_common_params.yaml

该文件是move_base 在全局路径规划与本地路径规划时调用的通用参数,包括:机器人的尺寸、距离障碍物的安全距离、传感器信息等。配置参考如下:

#机器人几何参,如果机器人是圆形,设置 robot_radius,如果是其他形状设置 footprint
robot_radius: 0.12 #圆形
# footprint: [[-0.12, -0.12], [-0.12, 0.12], [0.12, 0.12], [0.12, -0.12]] #其他形状

obstacle_range: 3.0 # 用于障碍物探测,比如: 值为 3.0,意味着检测到距离小于 3 米的障碍物时,就会引入代价地图
raytrace_range: 3.5 # 用于清除障碍物,比如:值为 3.5,意味着清除代价地图中 3.5 米以外的障碍物


#膨胀半径,扩展在碰撞区域以外的代价区域,使得机器人规划路径避开障碍物
inflation_radius: 0.2
#代价比例系数,越大则代价值越小
cost_scaling_factor: 3.0

#地图类型
map_type: costmap
#导航包所需要的传感器
observation_sources: scan
#对传感器的坐标系和数据进行配置。这个也会用于代价地图添加和清除障碍物。例如,你可以用激光雷达传感器用于在代价地图添加障碍物,再添加kinect用于导航和清除障碍物。
scan: {sensor_frame: laser, data_type: LaserScan, topic: scan, marking: true, clearing: true}

4.2.2global_costmap_params.yaml

该文件用于全局代价地图参数设置:

global_costmap:
  global_frame: map #地图坐标系
  robot_base_frame: base_footprint #机器人坐标系
  # 以此实现坐标变换

  update_frequency: 1.0 #代价地图更新频率
  publish_frequency: 1.0 #代价地图的发布频率
  transform_tolerance: 0.5 #等待坐标变换发布信息的超时时间

  static_map: true # 是否使用一个地图或者地图服务器来初始化全局代价地图,如果不使用静态地图,这个参数为false.

4.2.3local_costmap_params.yaml

该文件用于局部代价地图参数设置:

local_costmap:
  global_frame: odom #里程计坐标系
  robot_base_frame: base_footprint #机器人坐标系

  update_frequency: 10.0 #代价地图更新频率
  publish_frequency: 10.0 #代价地图的发布频率
  transform_tolerance: 0.5 #等待坐标变换发布信息的超时时间

  static_map: false  #不需要静态地图,可以提升导航效果
  rolling_window: true #是否使用动态窗口,默认为false,在静态的全局地图中,地图不会变化
  width: 3 # 局部地图宽度 单位是 m
  height: 3 # 局部地图高度 单位是 m
  resolution: 0.05 # 局部地图分辨率 单位是 m,一般与静态地图分辨率保持一致

4.2.4base_local_planner_params

基本的局部规划器参数配置,这个配置文件设定了机器人的最大和最小速度限制值,也设定了加速度的阈值。

TrajectoryPlannerROS:

# Robot Configuration Parameters
  max_vel_x: 0.5 # X 方向最大速度
  min_vel_x: 0.1 # X 方向最小速速

  max_vel_theta:  1.0 # 
  min_vel_theta: -1.0
  min_in_place_vel_theta: 1.0

  acc_lim_x: 1.0 # X 加速限制
  acc_lim_y: 0.0 # Y 加速限制
  acc_lim_theta: 0.6 # 角速度加速限制

# Goal Tolerance Parameters,目标公差
  xy_goal_tolerance: 0.10
  yaw_goal_tolerance: 0.05

# Differential-drive robot configuration
# 是否是全向移动机器人
  holonomic_robot: false

# Forward Simulation Parameters,前进模拟参数
  sim_time: 0.8
  vx_samples: 18
  vtheta_samples: 20
  sim_granularity: 0.05

3 集成导航相关的launch文件

这里创建一个launch文件用于集成

<!-- 集成导航相关的launch文件 -->
<launch>
    <!-- 设置地图服务 -->
    <include file="$(find nav_demo)/launch/nav03_map_server.launch" />

    <!-- 启动AMCL节点 -->
    <include file="$(find nav_demo)/launch/nav04_amcl.launch" />

    <!-- 运行move_base节点 -->
    <include file="$(find nav_demo)/launch/nav05_path.launch" />

    <!-- 运行rviz -->
    <node pkg="joint_state_publisher" name="joint_state_publisher" type="joint_state_publisher" />
    <node pkg="robot_state_publisher" name="robot_state_publisher" type="robot_state_publisher" />
    <node pkg="rviz" type="rviz" name="rviz" />

</launch>

4 测试

先启动 Gazebo 仿真环境

启动导航相关的 launch 文件

添加Rviz组件(参考演示结果),可以将配置数据保存,后期直接调用

这里将其保存到config中以便于之后使用。

上图中点击2d Nav Goal即可在地图上设置目标点,机器人就可以移动了。

 导航

这里再在之前的基础上add一个map,设置其topic为本地对应的topic即可查看本地代价地图

再添加两个路径的显示,一个是局部路径规划(黄色),一个是全局规划(绿色)

关于配置文件的编写,可以参考一些成熟的机器人的路径规划实现,比如: turtlebot3,github链接:turtlebot3/turtlebot3_navigation/param at master · ROBOTIS-GIT/turtlebot3 · GitHub,先下载这些配置文件备用。

以上配置在实操中,可能会出现机器人在本地路径规划时与全局路径规划不符而进入膨胀区域出现假死的情况,如何尽量避免这种情形呢?

全局路径规划与本地路径规划虽然设置的参数是一样的,但是二者路径规划和避障的职能不同,可以采用不同的参数设置策略:

  • 全局代价地图可以将膨胀半径和障碍物系数设置的偏大一些;
  • 本地代价地图可以将膨胀半径和障碍物系数设置的偏小一些。

这样,在全局路径规划时,规划的路径会尽量远离障碍物,而本地路径规划时,机器人即便偏离全局路径也会和障碍物之间保留更大的自由空间,从而避免了陷入“假死”的情形。

如何修改半径和系数:在local_costmap_params.yaml和global_costmap_params.yaml中加入costmap_common_params.yaml中的这段代码并且进行修改,原来costmap_common_params.yaml中的这段代码给它删除。

#膨胀半径,扩展在碰撞区域以外的代价区域,即将障碍物等的体积扩大一圈从而来防止碰撞
inflation_radius: 0.2
#代价比例系数,越大则代价值越小   
cost_scaling_factor: 3.0

 这个时候就可以发现全局的膨胀(蓝色)大于局部(黑色)的膨胀,而我们运行的时候参考的是全局的。

315节 导航和建图同时

之前导航实现01_SLAM建图中,我们是通过键盘控制机器人移动实现建图的,而后续又介绍了机器人的自主移动实现,那么可不可以将二者结合,实现机器人自主移动的SLAM建图呢?

上述需求是可行的。虽然可能会有疑问,导航时需要地图信息,之前导航实现时,是通过 map_server 包的 map_server 节点来发布地图信息的,如果不先通过SLAM建图,那么如何发布地图信息呢?SLAM建图过程中本身就会时时发布地图信息,所以无需再使用map_server,SLAM已经发布了话题为 /map 的地图消息了,且导航需要定位模块,SLAM本身也是可以实现定位的。

该过程实现比较简单,步骤如下:

  1. 编写launch文件,集成SLAM与move_base相关节点;
  2. 执行launch文件并测试。

这里我们只需要包含之前写的两个文件即可

<!-- 集成slam和导航 实现机器人自主移动的地图构建 -->

<launch>
    <!-- 启动SLAM节点 -->
    <include file="$(find nav_demo)/launch/nav01_slam.launch" />

    <!-- 运行move_base节点 -->
    <include file="$(find nav_demo)/launch/nav05_path.launch" />

</launch>

 这里需要注意的是args要进行修改,加载的文件是后来保存的

    <node pkg="rviz" type="rviz" name="rviz" args="-d $(find nav_demo)/config/nav_test.rviz"/>

测试

1.首先运行gazebo仿真环境;

2.然后执行刚刚编写的launch文件

3.在rviz中通过2D Nav Goal设置目标点,机器人开始自主移动并建图了;

4.最后可以使用 map_server 保存地图。

------------导航相关消息------------

在导航功能包集中包含了诸多节点,毋庸置疑的,不同节点之间的通信使用到了消息中间件(数据载体),在上一节的实现中,这些消息已经在rviz中做了可视化处理,比如:地图、雷达、摄像头、里程计、路径规划...的相关消息在rviz中提供了相关组件,本部分主要介绍这些消息(message)的具体格式。

316-322节 (看视频)

这部分内容介绍的就是各种功能对应发布的的消息的具体内容

这样的具体的解释是为了对其二次开发,就可以利用message的消息来对其进行修改

7.3.1 导航之地图 · Autolabor-ROS机器人入门课程《ROS理论与实践》零基础教程

323-325节 深度图像转激光数据 这部分待完成

本节介绍ROS中的一个功能包:depthimage_to_laserscan,顾名思义,该功能包可以将深度图像信息转换成激光雷达信息,应用场景如下:

在诸多SLAM算法中,一般都需要订阅激光雷达数据用于构建地图,因为激光雷达可以感知周围环境的深度信息,而深度相机也具备感知深度信息的功能,且最初激光雷达价格比价比较昂贵,那么在传感器选型上可以选用深度相机代替激光雷达吗?

答案是可以的,不过二者发布的消息类型是完全不同的,如果想要实现传感器的置换,那么就需要将深度相机发布的三维的图形信息转换成二维的激光雷达信息,这一功能就是通过depthimage_to_laserscan来实现的。

转换原理是将深度相机图像中的随机截取一行深度信息从而转化为二维的雷达信息。

优点:深度相机的成本一般低于激光雷达,可以降低硬件成本;

缺点: 深度相机较之于激光雷达无论是检测范围还是精度都有不小的差距,SLAM效果可能不如激光雷达理想。

使用:

安装:

sudo apt-get install ros-melodic-depthimage-to-laserscan

编写launch文件执行,将深度信息转换成雷达信息

<launch>
    <node pkg="depthimage_to_laserscan" type="depthimage_to_laserscan" name="depthimage_to_laserscan">
        <remap from="image" to="/camera/depth/image_raw" />
        <param name="output_frame_id" value="camera"  />
    </node>
</launch>

订阅的话题需要根据深度相机发布的话题设置,output_frame_id需要与深度相机的坐标系一致。

注:经过信息转换之后,深度相机也将发布雷达数据,为了不产生混淆,可以注释掉 xacro 文件中的关于激光雷达的部分内容。

流程如下:

1.先启动 Gazebo 仿真环境;

2.启动转换节点;

3.再启动地图绘制的 launch 文件;

4.启动键盘键盘控制节点,用于控制机器人运动建图;

rosrun teleop_twist_keyboard teleop_twist_keyboard.py

5.在 rviz 中添加组件,显示栅格地图最后,就可以通过键盘控制gazebo中的机器人运动,同时,在rviz中可以显示gmapping发布的栅格地图数据了,但是,前面也介绍了,由于精度和检测范围的原因,尤其再加之环境的特征点偏少,建图效果可能并不理想,建图中甚至会出现地图偏移的情况。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值