Box2D 学习:平衡车
Box2D 是暴雪公司大牛 Erin Catto 开发的开源物理引擎。有很多著名游戏使用了它,比如愤怒的小鸟、地狱边境、Tiny Wings 等。而 Unity、Cocos2d 等游戏引擎更是把它集成在其中。
为什么想起来学习 Box2D 呢?因为想在虚拟的物理世界中创建一些智能 Agent。虽然在之前的 The Nature of Code 中学习了一些基础的力、运动的实现,但没有涉及碰撞、连接等。我们当然可以自己造轮子来实现这些内容,但如果能利用已有的 Box2D 引擎,站在巨人的肩膀上,我们就能够更加专注于要做的事情,来构建智能 Agent。
Segway
学习 Box2D 最好的方法就是做个项目练练手。这次尝试的项目是在 Box2D 中建造一个平衡车,并使用控制算法让它保持平衡并听从指挥移动到指定位置。项目中我们把平衡车抽象为简单的模型,由一个柄、一根杆和一个轮子组成。轮子由一个电机控制,可以正向或者反向转动。( 项目的思路方法来自于 hardmaru 的博客 )
创建
最原始的 Box2D 是使用 C++ 实现的,这里使用的是 NOC 中的 Javascript 版本,这使得项目可以方便地发布到网络上,不过同时也丧失了很大的性能优势。然后由于 Box2D 是一个纯物理引擎不带有渲染功能,所以我们使用 p5.js 来做渲染。
创建的大体想法是先建立一些基本元素,比如长方形和圆,给它们添加上渲染方法以及对应的物理引擎元素。然后通过 Box2D 中的连接器把它们组装到一起,当然不要忘了设置一个地面。最后创建出的平衡车由于没有对于轮子的控制系统,所以会直接倒下。
这里不想讨论过多的代码实现细节,对于 Box2D 的使用方式我推荐 这个站点,对于平衡车创建的细节可以查看 源码。
PID
怎么让平衡车平衡呢?这需要使用目前广泛地应用于各种系统,平衡车、无人机的 PID 控制算法。它的主要作用就是调节系统使得系统中的某个参数值到达你的设定值。PID 分别表示了三个调节部分,比例、积分、微分,控制器的输出值就是这三者的和。
在离散的情况下,这三项的表达更为简单:
P t = K p ∗ e r r o r t ” role=”presentation”>Pt=Kp∗errort P t = K p ∗ e r r o r t I t = I t − d t + K i ∗ e r r o r t ∗ d t ” role=”presentation”>It=It−dt+Ki∗errort∗dt I t = I t − d t + K i ∗ e r r o r t ∗ d t D t = K d ∗ ( e r r o r t − e r r o r t − d t ) / d t ” role=”presentation”>Dt=Kd∗(errort−errort−dt)/dt D t = K d ∗ ( e r r o r t − e r r o r t − d t ) / d t
而最后的输出就是 u t = P t + I t + D t ” role=”presentation”>,其中 d t ” role=”presentation”> 为 1/30 秒。对于平衡车,我们把目标值定为平衡车与地面的角度,而 PID 控制的量为轮子转速的增减。
先来看下 比例控制器,它的作用很直白,就是有多少误差就去回复它。表现在平很车上就是如果车向左边倒就控制轮子向左边跑,向右边倒就向右跑。增加 K p ” role=”presentation”> 的值可以加快减小误差的速度,但是会产生震荡。
积分控制器 按照它的计算方式可以看出,它的作用就是消除所有误差的整体误差。对于平衡车由于没有什么误差的整体偏差,基本都是来回整荡,因此可以把 K i ” role=”presentation”> 系数设为 0。
微分控制器 相当于加入了阻尼,可以使震荡快速衰减,变得稳定。在我们给平衡车加入微分控制之后,它的稳定性明显增加了。
对于 PID 的调参没有进行很深入的研究,有兴趣的同学可以自己查找相关资料。接下来的目标就是如何让平衡车移动到我们指定的位置。
移动
想一下真正驾驶平衡车的情况,如果要到达目标地点,首先要身体前倾加速。到达最大速度限制后身体基本保持直立,快要到目的地时后仰减速。所以我们希望平衡车移动到目标位置的速度曲线是这样的:
对于一开始的加速,可以把 PID 的目标值设为一定的角度,而且距离目标位置越远可以适当地增大这个角度。然后当速度到达一个上限时,把目标值设回 0 度使得平衡车匀速运动。最后根据当前的速度假设一个平衡车未来会到达的位置,由于这个位置在平衡车到达目标位置前就会越过目标位置,这时如果使用这个虚拟的位置来计算目标倾角,就会得到相当于刹车的效果。
动图中顶部的曲线为平衡车的水平速度曲线。红色竖线为我们设定的目标位置,绿色竖线为假设平衡车未来会到达的位置。
So~,这就是整个小项目的全部了,有兴趣的同学可以到 Demo 页玩一下。
hertzcat
2018-09-01