ROS机器人导航一 : 从英雄联盟到ROS导航

写在前面:

这是这个系列的第一篇

本系列主要从零开始深入探索ROS(机器人操作系统)的导航和规划。

这个系列的目标,是让大家了解:

1.ROS的导航是怎么实现的

2.认识ROS里各种已有的导航算法,清楚的了解到每一个参数的作用,以及ROS的源码是怎么设计的

3.和大家一起看看学术界和工业界在导航领域的相关发展。学会如何重写ROS的源码,使用ROS的接口来实现一些导航算法/论文

本篇目标:

1.了解什么是导航(主要是室内导航)

2.游戏世界中的导航是怎么样的

3.游戏世界的导航在真实世界会遇到哪些问题


 

一、ROS导航

       本篇作为系列的第一章,我希望大家能够轻松的了解导航这个复杂而又简单的系统。

      本篇目标:大概明白ROS中的导航结构

1.1 什么是ROS:

ROS是Robot Operating System(机器操作系统)的缩写,但它并不是真正意义上的操作系统

它更像是跑在Linux系统上的一个专门给开发者提供的机器人算法、工具的合集。

引用官方的描述:

The Robot Operating System (ROS) is a set of software libraries and tools that help you build robot applications

ROS的特点有:开源, 便捷,支持多语言(主要为python和C++)

ROS在机器人行业的名声特别大,因为它大大的简化了机器人的开发流程和降低了机器人开发门槛。在我看来在ROS在机器人行业影响力就像在8年前安卓系统在手机行业的一样,它不够完善但潜力极强,因为其免费开源的性质最终将会被各大小厂商采用

 

这篇文章基于ROS - noetic版本,(在工作中,我使用的是melodic版本,其实这些临近版本都大同小异,大多数代码和框架也是通用的)

如果大家对ROS还不太了解也没关系,不会影响阅读本篇文章

 

这里有一些我收藏的了解ROS的途径:

1.ROS wiki(官网):cn/ROS - ROS Wiki 

2.B站搜索ROS查看学习视频

 

1.2 什么是导航

本系列主要聚焦于室内导航

我认为跟机器人学科接近的,是游戏

大多数游戏开发中需要使用导航,规划,AI行为等,都与机器人学科高度相近。本系列中我们只聚焦于导航领域:

导航是游戏引擎都会提供的重要组件(下面是unity和UE引擎提供的导航功能):

  

 

 

相信各位玩家,对以下这些场景可能不会陌生,这是游戏中,开发者直观地把导航路径展示给玩家看:

   

 

 

 

  

 简单来说,导航是提供一个可达路线从一个位置到另一个位置的系统。下面我们会尝试对这个系统进行解读

 

二、游戏中的导航

在本节中,一些关键术语会使用英文标记,希望给大家一个印象。因为它们对我们后续篇章进行源码分析和论文阅读十分有帮助

2.1 我们来推测一下英雄联盟的导航是怎么做的:

如果你没玩过英雄联盟,那么可以跳过这一节了,我肯定你是学霸。因为你没时间玩游戏

如果你玩过英雄联盟,那你更厉害一定是学神,因为你除了逛博客园和上班/上学,竟然还有时间玩游戏

首先我们要:

1.打开英雄联盟,开始训练模式,选取蒸汽机器人布里茨(或者其他英雄)进入游戏

2.游戏加载完成后,鼠标右键点击小龙坑进行移动,此时留意右下角小地图

      

  这时候,小地图上出现了一条白线(我们称为路径path),白线左端连接着机器人(称为起点start),白线右端是我们鼠标点击的位置小龙坑(称为目标点goal)

    • 随着机器人的移动,白线(路径)在变短,但是目标点小龙坑始终不变。
    • 白线(路径)在整个移动过程会有一定程度的改变,但始终会避开防御塔,墙体,深林,山体等阻挡前进的东西(下面把这些东西统称为障碍物obstacle)

  

2.2 我们大胆推测一下游戏的底层逻辑 

 

如上图我们把游戏地图看作一个二维坐标系,横向是x轴,纵向是y轴,地图左下角是坐标(0,0) 地图右上角是坐标(100,100)

  1. 玩家点击右键游戏的某一段代码受到激发(发生了callback),通知导航模块(navigation)的代码开始工作
  2. 游戏的某一段代码捕获到鼠标指针在显示器上的位置,作为目标点goal(80,30)
  3. 游戏的某一段代码获取到了当前机器人的位置作为起点start(1,1)
  4. 游戏的某一段代码获取到了地形图(map),这个地形图上分为会阻挡前进的障碍物(obstacle),还有畅通无阻的路面/河道(free space)
  5. 导航模块结合上面获取的信息内部的规划子模块(planner)通过某种算法规划(plan)了一条能避开障碍物的白色路径(path)并显示在小地图上
  6. (不重要)机器人根据自身的移动速度(velocity)延着这个路径path开始移动,并伴随着移动播放走路的动画(机器人状态机从停止切换到运动状态)
  7. (不重要)在一定的条件下,比如靠近目标后,或者每隔一段时间,程序回到3开始再次执行,直到机器人当前坐标(current location)和goal坐标重合为止。每次重新跑到3,起点位置改变了,白线路径就会变短,(由于算法的原因新的白线与之前白线可能也会发生不同程度的偏差)

所以LOL里边导航模块大概是这样子的:

(我们只需要关注有颜色的部分:蓝色是导航模块需要的输入信息,绿色是导航模块输出的路径,红色是导航模块本体)

   

好了,上面大概推导了一下英雄联盟中的导航逻辑,从导航模块的最终目标是给出一个可行路径(LOL小地图里的白色线),这个路径能够引导机器人避开障碍并向终点移动。

问题1:如下图所示在,绿色,粉色,白色3个路径中,为什么导航系统给出的是白色的路径而不是另外两个?

回答:这个就是规划模块要做的事情的了,通常来说,这个路径会是起点start到终点goal的'最短'路径

游戏中比较常用的规划方法是一系列基于网格(grid-based)的规划方法,这些算法从早期的djstra,A*等发展到现在拥有非常多的变体,它们都经历了什么,以及具体是怎么实现的,我准备放到下一篇再和大家分享

 

(ps,以上对于英雄联盟导航是依据我在机器人领域开发的经验进行的推测,目的是更好引出后面ROS中的导航框架,实际游戏设计中因为架构,网络,效率,bug修复等原因导航可能是一个非常复杂的模块)

 

2.2 游戏导航在真实世界中遇到的问题

如果系统要给真实世界中机器人导航,会遇到哪些问题呢?

上面的游戏导航框架其实已经和ROS中的导航十分接近了,甚至于在理想情况下直接把上面的导航模块搬到ROS上都能开始指导真实世界的机器人运动了

但是游戏与我们的真实世界仍然存在一定的差异。这些差异包括但不限于:

 

2.21.动力学约束:在真实世界中,机器人受到了各种力的影响和限制,比如机器人的动力,重力,电机的阻力,轮子的摩擦力,惯性等等,一般我们会用线速度 角速度 线加速度,角加速度等来描述这些问题,

打个比方:

比如下图1中在游戏中为了迷惑对手而疯狂点地板操作,机器人在真实世界不能执行如此高速度的转头(用数学来描述:游戏中的机器人的角速度和角加速度趋近于无限大)

这个特性会导致某些(下图2)在游戏中轻松通过的急转弯,在真实世界中,机器人受到了角速度和角加速度的限制无法完成这样的操作

*真实世界的机器人好比在游戏中使用亡灵勇士塞恩,塞恩开车的时候由于车速太快无法提供足够角速度来进行转弯(下图3),这时的赛恩就受到了约束,(细心的玩家可能会注意到,塞恩开车的时候,小地图是不会有白色导航路径的)

  

2.22传感器的误差和干扰:真实世界中,机器人通过一些射线传感器(比如激光雷达,超声波,TOF相机等)来建立地图(mapping)获取自己在地图中的位置(localization), 通过惯性器件(比如陀螺仪和加速度计)来获来获取自身的方向角和倾斜度(orientation),通过码盘,霍尔盘获取轮子速度等等。不同精度的传感器能达到上万倍的价格差异。但精度再高,干扰和误差都无法完全消除。

比较常见的传感器问题有如下这些(展开查看)

陀螺仪的零点偏移
相机画面的畸变
激光雷达的白噪声与延迟
超声波的盲区以及非线性的发射角

所有光学传感器都会或多或少的受到光线影响
所有声学传感器都会或多或少的受到声音影响
展开查看

这些小小误差造成了真实世界和游戏世界的巨大差异,每一种传感器都无法得到精确信息。有经验的工程师会在设计阶段给机器人上配置不同的传感器来取长补短。在软件上更是需要做传感器融合,这些融合大多很复杂,消耗大量算力的同时不一定能得到很好的效果。

 

2.23系统时延:真实世界中,机器人上具有算力的处理器远远不止一个CPU,通常还有大量的单片机,它们负责收集和处理传感器数据,控制机器人机械运动等。不同芯片间的信息交换,以及不同软件系统的任务切换,都会导致接收数据的时机变得更加不稳定(加强了2.22的问题),控制轮子运动也得不到不及时执行,而且这些时延并不是固定有时也难以补偿,会导致机器人无法完全按照白色路径前进。这个感觉,类似于玩lol的时候有经常性发生网络卡顿和延迟,当网络反应过来的时候可能机器人已经走远了。

 现在我们看看ROS如何从代码设计上改善上面的问题:

 

三、ROS的导航是怎么设计来解决这些问题的

3.1 ROS的导航框架

针对上面的问题2.21

相信大家都想到了解决方法,如果我们让机器人走得很慢很慢,那么再急的弯机器人不就能转过来了吗?但我们应该怎么让机器人在该快的时候快,该慢的时候慢呢?我们看看ROS怎么在架构上做了什么改动:

  1. 把上面的规划器planner改名为全局规划器(global planner),其产生白色路径我们称为全局路径(global path)
  2. 由于现实中的机器人受到动力学约束,ROS增加了一个局部规划模块(local planner)来动态控制机器人,这个局部规划器拿到前面产生的全局路径,并根据动力学约束,让机器人能够提前进行加减速,来贴合路径。
  3. *注:不同的局部规划算法用不同的方法来让机器人来贴合全局路径,甚至修改全局路径,但作为局部规划模块,它们的输出必须是线速度和角速度

  

 

 

 

针对上面的问题2.22:

由于机器人上会放置的传感器太过于多样化,ROS使用了代价地图(costmap)这个概念,costmap可以把各种传感器信息叠加再一起。

costmap的基本功能,是把经过简单处理的多种传感器的数据,通过配置的方式,一个一个叠加到地图中。

具体一点,costmap使用了子图层(layer)的概念。使用过photoshop软件或者做过视觉的同学就可能对图层这个概念比较熟悉了:

  • costmap能把地图(map)的信息复制下来,存放再某个图层中
  • 通过yaml配置文件能添加更多图层,只需要做简单的修改,就能添加/删除某个图层
  • ROS提供了不同的图层来处理不同种类的传感器数据,如果你嫌这些图层不够丰富,甚至可以根据layer的接口编写自己的图层,使用更多的方法来融合多种传感器数据
  • 所有图层根据一定的规则进行叠加(叠加规则也可以配置),并产生一个主图层(master layer),这个图层上面的信息,取代上图中的地图(map),给global planner和local planner使用

现在我们更新一下加入代价地图以后的示意图:

注意我们不再直接从地图获取地形数据了,而是从代价地图获取:

 

 

局部规划算法自然也需要地图信息,大多数时候,是为了避开动态的障碍物(比如人),ROS也给局部规划器单独配置了代价地图。

 

 现在我们已经大概了解ROS导航的构成了(还有一个恢复行为模块 recovery_behavior我们以后再做介绍),我们也了解了为什么这样子设计。(图中红色区域是ROS的导航模块,黄色的模块是必须的,紫色的模块是自行添加或删除)

ROS也设计好了接口类,方便后各位大神对这些模块进行改写。

*ROS导航框架中还有一个恢复策略模块(recovery behaivors),它能给用户自定义一些遇到意外的自动恢复共嗯。非必须,这里暂时进行省略。

3.2 ROS导航仿真配置

  • ROS使用gazebo组件能给我们机器人在现实世界的仿真,我们会使用到gazebo组件来进行真实世界机器人仿真
  • 我们还需要使用可视化软件(类似lol中的小地图),rviz组件来进行场景的可视化
  • 我们还需要使用到AMCL模块进行导航的辅助定位

我们的主角机器人他有点残疾,双脚被替换成了轮子

在机器人动力分类上,他是一个二轮差动机器人(diff-drive)。没有脚,用两个轮子进行运动

*差动机器人的特点是两个轮子可以单独执行不同速度的运动。

  • 如果两个轮子速度相同且大于0,那么机器人前进
  • 如果其中一个轮子的速度比另一个轮子大,那么机器人转弯
  • 如果两个轮子速度相同但是方向相反,那么机器人自转

 

关于整个ROS工程,费了一点时间东拼西凑把机器人的基本框架搭起来了。

*要运行这个代码,是需要已经安装好了ROS-noetic版本。由于ROS系统安装过程本身比较繁琐,在这短短的篇幅就不做介绍了。

 

我的git仓库链接:https://github.com/DennLiang/ROS_navigation_denn.git

下载后需要把仓库放在工作空间的src路径下,如图:

 

 

 

 

·关于地图,我花了一点时间复刻了LOL的地图, 总所周知,LOL是一个只有下路的游戏,所以这里也只复刻了下路野区部分:

相信我不说大家也能看出来,绿色是下路,黄色是城墙下方的小门,红色区域是下路红buff区,蓝色区域是小龙坑。简直和原图一摸一样

 

 

 

·关于导航模块,这里使用我认为比较合理的配置方式,如果是各位已经熟悉ros的大佬,可能会觉得跟官网还有其地方看到的配置不太一样。这样的做法看起来麻烦,但更灵活。跟我们上面说的导航框架一一对应。全局规划这里使用A*算法,局部规划使用了DWA算法,这两个算法ROS都已经提供并且开放了源码。如果想深入了解它们的详细内容,大家记得留意后续篇章的更新哦

 

 

 

 ·关于ROS源码:为了方便大家查看和后续篇章的讲解,我也把ROS的导航包navigation源码 和 tf坐标变换源码 下载到工程中了:

 

 

 

 

四、大功告成,开始导航!

在工作空间中,使用catkin_make进行编译:

 

 

新建终端1:

  • 配置全局变量: source ./devel/setup.bash
  • 运行机器人仿真(机器人描述文件):roslaunch urdf_gazebo_02 demo02_car.launch

新建终端2:

  • 配置全局变量: source ./devel/setup.bash
  • 运行机器人导航(包括了定位AMCL 和 Move base两部分):roslaunch nav_dev nav08_amcl_with_navigation.launch

点击打开的rviz窗口中的2D Nav Goal按钮来控制机器人:

还记得在第二节中机器人在基地向小龙坑移动的动图吗:

 

 

我们在真实世界中复刻一下机器人从基地走到龙坑的过程(见动图):

机器人附近的彩色区域是局部地图(local costmap)的范围,可以简单的理解为战争迷雾(游戏中英雄只看到自己附近的敌人,在黑影中的敌人看不到)

大家可以通过对比观察到真实世界中和游戏中的机器人运动的差异,

  • 比如由于受到激光雷达的白噪声影响,AMCL定位精度的影响,机器人附近地图的墙壁会发生不同程度的抖动
  • 比如由于DWA算法的关系,机器人在某些狭窄的路口提前进行了减速。

 

 

 

 

好了,本篇到这里结束了,下一篇中我们会通过阅读论文和源码,一起来看看全局规划算法在学术界上和工程领域都得到了一些怎么样的发展,也期待各位读者继续关注更新哦

今天是2022年第2天,祝大家在新年许的愿望全部实现,拜拜了

 

 

 

 

  

 

posted @ 2022-01-02 19:48  HongYi_Liang  阅读(1189)  评论(3编辑  收藏  举报