前言

第一次写博客,内心很激动,参加了一次智能车创意组比赛,这次带着学弟参赛,写下这篇文章是想记录自己的一些心得,能力有限,希望可以与各位交流,共同进步。
前段时间智能车创意组别的讯飞组别刚刚完成线上赛,本篇文章针对这次线上赛进行剖析,提供一下备赛思路。

正文

这次讯飞组别的线上仿真赛,讯飞官方提供了搭建环境教程,对于ROS小白来说很友好,学一些ROS的基本操作之后就可以根据教程把讯飞组的环境搭建起来了。同时值得一体的是,古月居也推出了自己的对应改组别的课程,可以在古月学院查看。因为有这两个很详细的教程所以我就不再讲怎么搭建环境了,教程都讲得很好,我们聊一聊细节,打比赛嘛,细节的处理是非常重要的,那么正文开始,“欢迎来到对抗路!”
首先我们聊一聊比赛前的小细节,小小的总结了智能车小白和智能车大佬的习惯区别,组别小白是这样的:参加比赛加入组别之后一脸懵逼,参赛队员都在抱怨看不懂,干等官方的教程,丝毫没有自己是在参加比赛的感觉,有的队员甚至还中途消失不见了。而组别大佬是:先组织好参赛队员,然后进行技术大会交流技术明确每个人的技术及其应用,如果遇到假设ros大家都不会这样的问题,那么大家合理分工进行学习,规定好任务进度,确保任务进度的稳步推进。从这一波分析,大佬在一开始的任务安排细节处理就赢了。所以还是建议大家在做比赛或是项目之前先和队友商量好一个合理的任务进度规划,明确队伍的目标,实时跟进,这样不会做着做着出现迷茫感,反而会在成功达到一个目标之后有一种成就感这会促使你更想完成下一步的工作,这就达成了良性循环。

接下来我们聊聊车,讯飞组的智能车是基于ros的移动机器人理论,那么ros的移动机器人是如何进行工作的呢?我们通过了解ros的基础知识就会知道,ros的移动机器人理论包含三部分:slam建图、amcl定位系统、导航系统。
slam建图方面:ros的slam的建图算法已经开源的有很多,这导致了大家的眼花缭乱,因为都能用,但是哪个效果更好呢,有比赛经历的同学,我推荐大家之前用哪个熟练就用哪一个,对于没有比赛经历的,我的思路是先看已经提供了什么传感器,根据传感器定算法,同时还可以考虑一下算法的复杂性,因为简单的算法复现容易。目前常用的算法有gmapping、hector、cartographer,gmapping和hector两个算法都不难,和cartographer比起来是轻量级的,配置起来相对较简单。简单说一下三个算法的差别,Gmapping是基于粒子滤波的算法,缺点是严重依赖里程计,无法适应无人机及地面不平坦的区域,无回环(激光SLAM很难做回环检测),大的场景,粒子较多的情况下,特别消耗资源,但是对于走廊型环境建图有奇效。Hector是基于高斯牛顿方法的算法(解最小二乘问题),优缺点:不需要里程计,可以适用于不平坦的复杂地形,但是需要激光雷达的刷新率很高测量噪声小,在建图时需要缓慢移动才能达到很好的效果,如果有精准的里程计信息,选择这个算法是比较可惜的,因为它无法有效使用里程计信息。Cartographer在上面提及的算法之前就是大佬的存在,Cartographer算法是基于图优化的算法,能天然的输出协方差矩阵,后端优化的输入项,具有回环检测,它能用价格低廉的的雷达得到比较准确的地图,短短几句话就让你觉得这个算法强的一批,但是它对于新手很不友好,而且参数配置很不友好,需要进行一段时间的仔细学习才能掌握,学起来比较痛苦。因为教程给出来了cartographer的使用方法,大家比赛建图并不是主要的考核部分,所以秉持会用就好的想法,用它来做比赛是很不错的,我选择的是gmapping,简单、搭建快、复现快,比赛的场景是走廊所以用gmapping很合适,减少前期问题时间专注于后面导航部分调试。测试效果还不错,上图:

定位系统:ros使用的的amcl定位,是ROS提供的一种自适应的蒙特卡罗定位方法,是一种概率统计的方法,针对已有地图使用粒子滤波器跟踪一个机器人的姿态,它解决的是机器人绑架问题。
导航方面:导航方面就是重头戏了,讯飞组是竞速组别,比的就是谁的快。所以选择一个好的导航算法是非常重要的。目前ros的movebase内置好的算法是dwa算法,dwa算法完美适配差速机器人,但是dwa有致命问题就是对时间约束不大,导致它喜欢慢慢悠悠的走,所以我们推荐使用另外一个适合竞速的算法TEB。
因为teb调参文章很多,我简单的分析一下我的参数,提示一些我认为不错的关注点。
先放一波参数:

yaw_goal_tolerance: 0.6 # 目标位置的允许角度误差 0.2
xy_goal_tolerance: 0.5 # 目标位置的允许距离误差 0.1
这两个参数改变目标容忍度解决车速过快撞墙问题,我通过改这个容忍度就不撞墙了,但是我相信很多学校车速还是很快的,所以可以改变下面这个参数,约束一下。
free_goal_vel: true # 是否去除目标速度的约束 false true
这时候可能有同学就问了,我的车太快了通过改变参数已经不能解决问题了,那么就可以动手写个程序了,基本思路就是在车的控制上加一层顶层控制器,这层控制器利用机器人的里程计信息和目标点作对比,当双方差距处于一个阈值时,我们就可以进行减速或是直接急停,因为我并没有用到该方法所以并没有写程序,给大家推荐一篇大佬文章,这篇文章提供了一个程序(大佬很强哦~向大佬学习!)。
enable_homotopy_class_planning: false #激活并行规划(因为一次优化多个轨迹,占用更多的CPU资源 true
这个并行规划一定要记得关闭,它会极大地影响规划器的性能,关闭之后算力可以完美处理其他信息。
max_number_classes: 2 #4 改 2 规划出的最多轨迹数
这个参数是可以解决多个障碍堵路规划抖动问题
这里值得一体的是,大家一定要注意我的机器人模型,type:”polygon”,我使用的polygon,这个模型是比较耗费算力的,因为它每个额外的边缘都会显着增加所需的计算时间。我一开始并没有注意到这个细节,比赛提交完成后研究发现,讯飞的车其实更适合line类型的机器人模型,line模型它针对于在纵向和横向上表现出不同膨胀/长度的机器人,而讯飞的机器人模型,完美匹配,line的所需要的计算力要比polygon少的多,这有着绝对优势!

不过我们通过调试teb大家可能会发现,teb算法尽管很快了,但是依旧有缺陷,不够人性化,teb的决策还是有一部分问题的,如果障碍刁钻一点它可能会被卡住,有的时候需要利用车的玄学惯性甩过卡停位置(漂移~),而且teb的倒车不可禁止,它只能减少倒车的概率,不能彻底禁止,还有teb不能精准停车等问题,这些需要我们发挥自己的创造力,自己添加程序辅助解决。

比赛完后在查阅资料时发现teb算法更新了,在更新之后的算法里加入了这几个参数,正如注释示意,teb的维护者似乎也发现了teb算法的缺陷,加入了几个新参数,这使得teb算法更加人性化,通过使用这几个参数我发现,车对于障碍弯道的决策相对之前更加从容,遇直道加速遇弯道障碍减速的处理更加灵活,如果感兴趣大家可以试一下,不过要记得是新版teb哦~
看到很多人安利rqt工具箱的调参工具rqt_reconfigure,不知道大家会不会遇到这个问题,不管有没有,我都给大家提一嘴。

问题描述:
the rosdep view is empty: call ‘sudo rosdep init’ and ‘rosdep update’
PluginManager._load_plugin() could not load plugin “rqt_reconfigure/Param”:
Traceback (most recent call last):
File “/opt/ros/melodic/lib/python2.7/dist-packages/qt_gui/plugin_handler.py”, line 102, in load
self._load()
File “/opt/ros/melodic/lib/python2.7/dist-packages/qt_gui/plugin_handler_direct.py”, line 55, in _load
self._plugin = self._plugin_provider.load(self._instance_id.plugin_id, self._context)
File “/opt/ros/melodic/lib/python2.7/dist-packages/qt_gui/composite_plugin_provider.py”, line 72, in load
instance = plugin_provider.load(plugin_id, plugin_context)
File “/opt/ros/melodic/lib/python2.7/dist-packages/qt_gui/composite_plugin_provider.py”, line 72, in load
instance = plugin_provider.load(plugin_id, plugin_context)
File “/opt/ros/melodic/lib/python2.7/dist-packages/rqt_gui_py/ros_py_plugin_provider.py”, line 61, in load
return super(RosPyPluginProvider, self).load(plugin_id, plugin_context)
File “/opt/ros/melodic/lib/python2.7/dist-packages/qt_gui/composite_plugin_provider.py”, line 72, in load
instance = plugin_provider.load(plugin_id, plugin_context)
File “/opt/ros/melodic/lib/python2.7/dist-packages/rqt_gui/ros_plugin_provider.py”, line 106, in load
return class_ref(plugin_context)
File “/opt/ros/melodic/lib/python2.7/dist-packages/rqt_reconfigure/param_plugin.py”, line 51, in __init__
self._plugin_widget = ParamWidget(context)
File “/opt/ros/melodic/lib/python2.7/dist-packages/rqt_reconfigure/param_widget.py”, line 105, in __init__
self, rp, self.sig_sysmsg
File “/opt/ros/melodic/lib/python2.7/dist-packages/rqt_reconfigure/node_selector_widget.py”, line 102, in __init__
self._update_nodetree_pernode()
File “/opt/ros/melodic/lib/python2.7/dist-packages/rqt_reconfigure/node_selector_widget.py”, line 341, in _update_nodetree_pernode
TreenodeQstdItem.NODE_FULLPATH
File “/opt/ros/melodic/lib/python2.7/dist-packages/rqt_reconfigure/treenode_qstditem.py”, line 94, in __init__
self._set_param_name(grn_current_treenode)
File “/opt/ros/melodic/lib/python2.7/dist-packages/rqt_reconfigure/treenode_qstditem.py”, line 246, in _set_param_name
self._toplevel_treenode_name = self._list_treenode_names[0]
IndexError: list index out of range

解决方案:
将/opt/ros/melodic/lib/python2.7/dist-packages/rqt_reconfigure/node_selector_widget.py文件中第325行改为if node_name_grn in self._nodeitems or node_name_grn == ‘’:

总结

每次比赛的结束都会是新的开始,总结经验,让血的教训不断鞭策我们,祝大家日益强大!嗯~另外就是告诫大家:当我们拿到参数之后不要盲目上手,默认参数可能是坑……
最后附上视频吧!