1 什么是走线?
这不是很简单的嘛,做过车的都知道嘛。日常口语中的“走线”,就是让车在赛道上行驶出一个漂亮的轨迹,且车沿着这个轨迹跑能够速度非常快。
2 怎么才能走好线?
当然方法很多,但是我说一个疗程短见效快的:加大前瞻!
前瞻越大,走线越平滑,反应越及时,弯道切弯越狠,S走得越直。多数时候程序的调试就是在找尽可能大的前瞻,然后针对这个前瞻优化速度决策。
可是为什么大前瞻能带来好的走线效果呢,要说清楚这一点,还得费一番周折。
3 为什么加大前瞻能走好线?
首先科普一个概念:曳物线
曳物线大概是指,一点A做直线运动,另一点B的运动曲线的切线方向一直指向A,且AB的距离固定(严格的定义可以自行百科)。稍微推广一下,若A点不仅是直线运动,而是沿着赛道中心线匀速运动,此时B点的运动轨迹此处称为“广义曳物线”。
经典的小车寻迹算法,首先计算出车正前方某个距离(前瞻)处离赛道的偏移量,然后将偏移量线性映射到前轮的偏向角。假如线性映射的比例系数合适,可以看成前轮的方向正好正对着A点,故车运行的实际轨迹就是“广义曳物线”。当然这只是一个近似,实际情况要复杂得多,不过这样的近似也足矣说明问题了。
以下将沿着赛道中心线运动的A点称为曳点,广义曳物线简称为曳物线。
好了,我们现在来观察一下曳物线与其对应的曳点的轨迹的关系。
3.1 曳物线的光滑性
首先,由于曳点的轨迹是连续的(否则不能称为“轨迹”啊),车的轨迹也是连续的,所以车到曳点的向量方向是连续的。而车到曳点的向量本身就是车轨迹的切线,切线方向的连续就可以推出车的轨迹是可导的(或者说其参数方程是可导的)。于是,车以曳物线作为运动轨迹,其轨迹的光滑性得到了一定的保障。如果我们再加一个条件:曳点的轨迹也是可导的(第八届以及以前的赛道),那么就可以保证车到曳点的向量方向是可导的,即可推出车的轨迹是二阶可导。
于是我们可以得到结论:对于第八届或以前的赛道,赛道本身是可导的,那么基于经典巡线算法的小车轨迹是二阶可导的曳物线;对于第九届或第十届的有直角弯的赛道,赛道本身连续但不可导,基于经典算法的小车轨迹是一阶可导的曳物线。
这一点很重要,控制系统的光滑性越好,稳定性越高,通常的不稳定(例如震动,螺丝松动,侧滑)都是发生在间断点上的。举个例子来说,急刹车的时候,车子在完全停稳的一瞬间,人会感觉往后“弹”了一下,那就是因为加速度发生了突变,或者说加速度不可导、不光滑。
3.2 曳物线的相位响应
由于曳点在“前”,车在“后”。每当曳点发生变化时,车在离曳点还有一定距离时就已经做出了反馈,可以看成曳物系统对信号的反馈相位提前了。这一点很重要,因为小车控制系统本身是时延系统(例如信号采集的时延,芯片计算的时延,信号输出的时延,执行机构的时延),如果用现在的信号计算现在的输出,肯定来不及,容易造成冲出赛道的情况。必须用未来的信号计算当前的输出。曳物线也是用曳点(未来的状态)来决定曳物线(当前的输出)的,所以造成了相位提前这样的特点。
3.3 曳物线的频率响应
事实上,狭义的曳物线是以曳点所在直线为渐近线的曲线,曳物线最终会和曳点所在直线重合,当然重合前有一个暂态过程。而对于广义曳物线,由于曳点的轨迹时刻在变化,曳物线一直处于追随曳点的暂态过程很难渐进重合。所以当曳点的变化频率较小时,曳物线较为“容易”“追上”曳点的“节奏”,达到曳点的“振幅”;而当曳点的变化频率很快时,曳物线很难追上曳点的节奏,达不到曳点的振幅。用行话来说,就是曳物系统能响应低频信号,但是会抑制高频信号。说得再简单粗暴一点就是:曳物系统是低通滤波器。
这是相当赞的一个特性!曳物系统是低通滤波器意味着,当赛道是大跨度,大半径,长距离的类型时,曳物线基本上是严格沿着赛道中心线延伸的;当赛道是小半径急转弯(高频)时,曳物线会以一个柔和的大半径轨迹(低频)通过弯道(切弯);进而当赛道是在小范围内来回反复的类型(S弯)时,曳物线会忽略赛道的来回反复,以此达到S弯直冲的效果。而且低通滤波器的截止频率跟曳物线的曳物距离相关,换一种简单粗暴的说法就是:前瞻越大,急转弯内切越狠,S弯直冲效果越好。
综上三点,曳物线光滑性好、相位提前、是低通滤波器,导致小车沿着曳物线跑稳定性好,反应及时,弯道内切且S弯直冲。而且前瞻越大,光滑性越好,反应越及时,弯道内切越狠,S弯冲得越直……
4 坠入泥潭
我们仿佛找到了希望,原来一切都是都是前瞻啊!怪不得电磁跑得最慢啊,杆子伸得再长也没有摄像头看得远啊,怪不得光电跑不过摄像头啊,激光打得再远也还是没有摄像头看得远啊……
于是乎我们一而再再而三地提高前瞻,电磁的杆子伸得越来越长,光电的激光管功率越来越大,摄像头架得越来越高……当然我们还要克服增大前瞻过程中的无数问题:电磁的杆子越长就越晃,需要加固,于是前面越来越重,前轮压力越来越大,结果导致转向不灵敏了,又得重调主销倾角;激光打得太远了容易,相邻的光电容易看混,于是又得加透镜才看得清楚;摄像头太高了,结果导致转弯侧翻。。。我勒个去……
当然这都没什么,总能解决的,麻烦的还在后头。
前瞻太长了转弯容易过度内切出赛道,特别是在270度弯,不知道多少队栽在270度弯过度内切上。于是摄像头笑了,哥有480行数据,搞动态前瞻!
前瞻太长了,赛道的偏移量远远大于近处的,视野太窄了看不过来。光电队发大绝招了,摇头!
前瞻太长了,电磁车容易串道,也发大绝招了,双排电感!
再然后,摄像头也看不到巨大的偏移量了,上广角镜头了;激光管上坡道就看不到了,于是出现点头加摇头的二自由度光电车了;最后连电磁组都开始摇头了。
再再然后,摄像头要考虑桶形失真了,二自由度的舵机固定件已经无法用手工作坊固定了,得上机床了,电磁组的屁股上得加配重了……
当然这也都没什么,这些方法也总能实现,提升走线效果。问题在于,我们渐渐地发现增大前瞻并不是将问题的解直接向最优解靠近,而只是大致上有更优的倾向,但总在别的某些方面造成了更多的麻烦,于是乎总要增加别的补偿来解决这些麻烦。于是整个系统围绕大前瞻变得越来越复杂,参数越来越多,调节起来越来越复杂。
5 问题到底出在哪里?
诸位有没有注意到,整个走曳物线的经典寻迹算法,从头到尾,压根没有提“赛道宽度”这玩意?
这就好理解了,这个算法只知道赛道中心线,压根不知道宽度,自然会出现过度切弯导致从内测出界的现象。这不经令人思索,一个连宽度都不知道的弱智算法,怎么会出现我们之前所说的那么多好的特性呢?不仅这点,还有一件说出来另该算法闻风丧胆的致命缺点:你TMD入弯之前怎么不先走外道啊?
让我们回头来思考一下,这个曳物线算法到底是怎么产生的呢?
首先我们是根据传感器的数据得出了一个表征车相对于赛道的偏移情况,然后凭直觉将这个偏移线性(或这说是单调)映射到前轮的方向角,然后发现惊讶地发现,此时只要给后轮一个速度,小车就奇迹般地沿着赛道奔跑了。然后我们调节这个算法的各个参数,使得车奔跑的路线逐渐变优,过程中得出一些心得,遇到一些问题。然后不断调节、迭代,添加新的补偿,设计更复杂的策略,引入多的变量。
经过一段时间的调试、观察与思考,我们发现原来车走的路线是一条曳物线啊,曳点就是某个前瞻下的赛道中心点。然后我们对曳物线这个概念进行了分析,得出了其光滑性,相位响应,频率响应等特性。这些特性印证了之前调试时发现的各种现象,并且对之后的调试做出了一定的指导(兴许你没有做这番分析也不知道车在走曳物线,不过,anyway,反正最后做的事情是一样的)。
至此我们终于回过味来了:原来这个算法根本不是我们精心设计出来的!原来这个算法是我们最初凭借直觉瞎凑出来的,只不过它恰巧具有了某些很好的特性,最终使我们陷入一个局部最优的陷阱。
对该算法的审判还没完呢,我现在要给它致命一击:你T喵D压根不知道自己在赛车!!!
假设我是一个赛车教练,手下有两个学赛车的徒弟,一个笨一个聪明。笨笨实在是太笨了简直没法教,我只好对笨笨说:“你看,10米开外的赛道,看到了吗?你假想着十米开外的赛道正中间有一块红烧肉,你死死地盯住它,把方向对准它……”
biu~~~笨笨飞奔出去了。跑得还可以嘛,哎哟,不错哟!
“聪聪,你看,假想十米开外的赛道上有一块红烧肉……”
“我不喜欢吃红烧肉”
“那假想是哈根达斯”
“我也不喜欢吃雪糕”
“无所谓啦,总之是你喜欢吃的某样东西”
“你到底想说什么?不就是想告诉我过弯要切内道吗?”
“诶!!!对对对!!!对!对!对!就是这意思”
“早说嘛”
“对!对!就是切弯哦!看好你哦!”
biubiubiu~~~~
聪聪轻易地超过了笨笨,而笨笨在一个赛道较窄的弯道因切弯过度导致内轮打滑车辆失控永远地离开了我们……
好了我现在问,笨笨为什么笨啊?因为笨笨根本不知道自己在赛车,他只知道看准一个点,往那个方向跑。而聪聪知道,“曳物”只是手段,目的是要跑出一条在赛道范围内的速度最快的曲线。笨笨是盲目的,他在盯住曳点看的时候,完全不知道赛车已经过度内切了,因此他也完全不知道在入弯前要先靠外侧。聪聪则会注意路线是否在赛道内,并且一旦他奔着把总时间缩短的目标,根本不用教,他自然就能发现外侧入弯能使弯道过得更流畅。
6 答案
让我们进入这篇文章的主题(什么?还没进入主题?):你的车,真的会走线吗?不!不会,他只是在某个目标下盲目的前进,正巧,如果朝着这个目标走,能走出一条还不错的线路。其实他并不清楚自己在干什么,并没有回过头来看看自己的路线,并没有发现自己需要切弯,需要直冲S弯。他只是盲目地前进。而人在这个过程里做的事情就是,不断修改这个盲目的系统的各个参数,使它盲目地前进所留下的轨迹逐渐符合自己的预期,看起来更不错。
好了,这便是我对本文题目的解答。
不过各位看官不要担心,你们都耐着性子看到这里了,我能不给你们指明方向吗?
其实办法简单地说就一句话:让小车自己计算出最优路线!
(不行就较优路线,总之这条路线是自己计算出来的,不是瞎跑出来的)
7 路径规划
我们先揣摩一下聪聪的算法。他看到赛道后,首先是大脑对赛道有一个整体的认识(而不是只提取出一个曳点),然后在他大脑中这个虚拟的赛道上绘制一条虚拟的路径,最后控制现实中的车在实际的赛道上真实地跑出他心中绘制的那条路径。
把这个过程用程序来描述就是:先采集信号,建立出车前方一定距离内的赛道模型,在模型中规划(“规划”这个词用得非常好,翻译成英文就叫program)出一条路径,要求这条路径在赛道范围内,光滑,曲率小,最重要的要求是,如果车以最优的速度决策沿着这条路径跑,时间最短。其中这个路径的起点是车体本身,向前延伸,到前瞻处。最后呢,让车沿着这条路径跑就行了,具体做法是:把路径的起点处的切线方向直接映射到前轮方向。这样一来就好了,小车清除地知道自己应该内切,而不是盲目地追随一个点最后看起来内切了而不自知。
剩下的问题就是,如果精确地建立赛道模型,如果规划一条更好的路径。当然上面只是一个大致的描述,具体实现过程还是有点复杂的。建立赛道模型和规划最优(较优)路径等都不是一句两句能讲清楚的。具体去看我的毕设论文吧。
最后问大家一个思考题:你终于知道电磁组为什么取消赛道边界了吧?