Physics Engine

来源:互联网 发布:手机照片手绘软件 编辑:程序博客网 时间:2024/05/17 01:47

时间:2017/3/22 大三下学期

       最近做完了一堆想要进一步学习的东西,便突然闲了下来,于是突然想用C++和OpenGL做一个赛车游戏,顺便练一下手。可是,真正上手起来发现,对于一款游戏而言,游戏引擎、几何处理是一个重要方便,但是若是想模拟出真实的运动效果,物理引擎也是少不了的。

       然而,网上关于游戏开发中遇到的汽车物理建模的资料少之又少,无奈从google发现一篇讲述特别全面的英文文章。特此翻译了其中的大部分(仍有一小部分没有翻译,因为觉得只是模拟而言,不需要太过于真实),现在拿出来分享一下。

我实现的效果:(耗时 2 天)


英文原文链接:Car Physics   

http://www.asawicki.info/Mirror/Car%20Physics%20for%20Games/Car%20Physics%20for%20Games.html

译文如下:

游戏开发中的汽车物理建模

作者:Marco Monster

翻译者:@RyuZhihao123 http://blog.csdn.net/mahabharata_) 

时间:2017/3/22 大三下学期

摘要:一个关于游戏中的汽车物理建模的介绍。

 

简介Introduction:

     This tutorial is about simulating cars in games, in other wordsvehicle physics.   

     One of the key points in simplifying vehicle physics is to handle the longtitudinal and lateral forces separately.  Longtitudinal forces operate in the direction of the car body (or in the exact opposite direction).  These are wheel force, braking force, rolling resistance and drag (= airresistance).  Together these forces control the acceleration or deceleration of the car and therefore the speed of the car.  Lateral forces allow the car to turn.  These forces are caused by sideways friction on the wheels.  We'll also have a look at the angular moment of the car and the torque caused by lateral forces.

       这是一个关于如何模拟游戏中的汽车的教程,换句话说,关于汽车物理学

       简化汽车物理模型的一个要点是为了分别独立的处理纵向横向的受力。纵向的作用力控制汽车身体的前进方向。它们包括:车轮牵引力(Wheel Force)、制动力(Braking force)、滚动摩擦力(Rolling Resistance)以及空气阻力(Drag、Air resistance)。它们共同控制着加速度(Acceleration)、减速度(Deceleration)以及车速(Speed)。横向的作用力允许汽车转向。它们包括:轮子轮胎侧向滚动的阻力。

下面,我将了解一下车辆行驶的一般情况。

 

将采用的记号和惯例NotationsAnd Conventions

        Vectors are shown in bold, we'll be using 2d vectors.  So the notation a = -b would translate to the following code snippet: 
      a.x = -b.x 
      a.y = -b.y

     Throughout this tutorial I'll be assuming that the rear wheels provide all the drive (for four wheel drives apply the neccesary adaptations).

     I'll be mainly using S.I. units (meters, kilograms, Newtons, etc.), but I've included a handy conversion table at the end for those readers more familiar with imperial measures (pounds, feet, miles, etc.) 

        我们规定,向量(Vectors)将用粗体(bold)表示。我们将使用2d向量。所以,记号“a = -b”将会被翻译成如下的代码片段:

         a.x= -b.x;

         a.y= -b.y;

         在这篇教程,我将始终假设后轮(rear wheels)提供所有的驱动力(Drive),对于四轮驱动将会做一些必要的调整。

         我将主要使用国际标准单位制(S.I units. meters,kilograms,Newtons,ets)。但是我也在文章的最后提供了一份方便的关于常见单位的转换表给读者(我没列出……因为篇幅太大,关于单位进制转化,大家高中也都学过,或者百度一下咯,谢谢体谅~)。

 

直线行驶的物理规律Straightline physics

       First let's consider a car driving in a straight line.  Which forces are at play here?  First of all there's what the tractive force, i.e. the force delivered by the engine via the rear wheels.  The engine turns the wheels forward (actually it applies a torque on the wheel), the wheels push backwards on the road surface and, in reaction, the road surface pushes back in a forward direction.  For now, we'll just say that the tractive force is equivalent in magnitude to the variable Engineforce, which is controlled directly by the user.

    Ftraction = u * Engineforce, 
    where u is a unit vector in the direction of the car's heading.

       首先,我们考虑直线行驶中的车辆。那么有哪些力在这里起作用?首先是牵引力(tractiveforce),进一步说,是由引擎通过后轮传递的力。引擎使车轮向前转动(实际上,引擎提供力矩Torque作用在车轮上),于是,车轮向后推动地面,相对的,地面也会向前推动汽车。现在,我们可以讲:牵引力等于不断变化着的引擎力(EngineForce),可以由用户直接控制。

        牵引力:Ftraction=u * Engineforce(即:牵引力 = u * 引擎力)

        其中:u是汽车行驶方向的单位向量。

           

    If this were the only force, the car would accelerate to infinite speeds.  Clearly, this is not the case in real life.  Enter the resistance forces.  The first and usually the most important one is air resistance, a.k.a. aerodynamic drag.  This force is so important because it is proportional to the square of the velocity. When we're driving fast (and which game doesn't involve high speeds?) this becomes the most important resistance force.

    Fdrag = - Cdrag * v * |v| 
    where Cdrag is a constant and v is the velocity vector and the notation |v| refers to the magnitude of vector v

      如过这是唯一的力,汽车将会无限加速!显然,这不是现实中的情况。于是,我们引入了摩擦力(Resistance forces)。其中最常见并且最重要的就是空气阻力(air resistance/ drag)。空气阻力之所以重要是因为它与速度(velocity)的平方成正比。当我们行驶的越快,空气阻力在诸多摩擦力中的效果也越来越显著。

      空气阻力Fdrag = - Cdrag *v * |v|

      其中:Cdrag是一个常量,v是速度矢量,|v|是速率标量。前面的负号保证了空气阻力的方向和速度始终相反。

         

      

    The magnitude of the velocity vector is more commonly known as the speed. Note the difference of data type: speed is a scalar, velocity is a vector. Use something like the following code:

    speed = sqrt(v.x*v.x + v.y*v.y); 
    fdrag.x = - Cdrag * v.x * speed; 
    fdrag.y = - Cdrag * v.y * speed;

       速度矢量的数值(模)就是我们常说的速率。两者的不同在于数据类型:速率Speed是一个标量,速度velocity是一个矢量。我们使用如下的代码计算空气阻力drag:

         Speed= sqrt(v.x*v.y +v.y*v.y);

         Fdrag.x = - Cdrag*v.x * speed;

          Fdrag.y= - Cdrag * v.y * speed;


        

    Then there is the rolling resistance. This is caused by friction between the rubber and road surface as the wheels roll along and friction in the axles, etc.etc.. We'll approximate this with a force that's proportional to the velocity using another constant.

    Frr = - Crr * v 
    where Crr is a constant and v is the velocity vector.

       然后就是滚动摩擦力(RollingResistance)。这是由车轮滚动时橡胶和地面的摩擦以及车轴的摩擦导致。这里,我们将用一个与速度velocity和一个常量的乘积成正比的力来表示:

       滚动摩擦力:Frr = - Crr *V

       其中,Crr是一个常量,V是速度矢量。

        

       

     At low speeds the rolling resistance is the main resistance force, at high speeds the drag takes over in magnitude. At approx. 100 km/h (60 mph, 30 m/s) they are equal ([Zuvich]). This means Crr must be approximately 30 times the value of Cdrag

    The total longtitudinal force is the vector sum of these three forces.

    Flong =   Ftraction + Fdrag   + Frr

       显然,在低速时,滚动摩擦力Frr是主要因素,在高速时,空气阻力Fdrag占据主导地位。

       这样,在纵向方向的合力Flong由三个力的总和组成:

       加速时纵向的合力:Flong=Ftraction + Fdrag+Frr

        

       注意:如果你在直线行驶,空气阻力和滚动摩擦力将会和牵引力的方向相反。因此,在数值计算方面,你需要从牵引力中减去摩擦力。当汽车匀速行驶时,合力Flong等于0。

         于是,汽车的加速度(m/(s*s))由牛顿第二定律可以通过作用在车上的合力(牛顿N)和汽车的总重量M(千克kg)得出:

        加速度:a=Flong / M

         汽车的速度(m/s)由加速度和时间得出:

        速度:v =v+ a*dt

         这里,dt是时间的增量。

         汽车的位置相应的由速度和时间决定。

        位置p =p + v*dt;

        

        With these three forces we can simulate car acceleration fairly accurately.  Together they also determine the top speed of the car for a given engine power. There is no need to put a maximum speed anywhere in the code, it's just something that follows from the equations.  This is because the equations form a kind of negative feedback loop.  If the traction force exceeds all other forces, the car accelerates.  This means the velocity increases which causes the resistance forces to increase.  The net force decreases and therefore the acceleration decreases.  At some point the resistance forces and the engine force cancel each other out and the car has reached its top speed for that engine power.

       通过上述三个力,我们几乎可以完全准确的模拟汽车的加速过程。同时,他们也共同决定了在给定的引擎动力下的最高速度,因此我们没有必要再代码中设置一个最高时速的变量加以限制。这是因为:上面的方程来自于一种消极反馈机制。如果,牵引力(traction)超过合阻力(Fdrag+Frr),那么汽车将加速。然而随着速度增加,阻力也在增加,这导致了合力Flong减小,加速度降低。在某一时刻,合阻力和牵引力会相互抵消,达到最高速度。

        

         在上表中,X轴是车速(m/s),y轴是力(N)。其中深蓝色维持不变的是牵引力(Ftraction)。

浅蓝色的是合阻力(Fdrag+Frr)。在低速时,空气阻力(drag)超过滚动摩擦力(Rolling Resistance),大概30m/s时两个阻力相等,在高速时,滚动摩擦力超过空气阻力。在37m/s时,合阻力与牵引力相等,这时,加速度为0,37m/s便是当前引擎动力下所能达到的最高速度。

 

关于常量取值Magic Constants

       至今为止,我们已经介绍了两个常量:Cdrag和Crr。如果你不太清楚在游戏中你应该给定什么样的数值能看起来更加真实。例如,在街机赛车游戏中,你可能更加希望你的车比现实生活中的任何车加速的更快!在另一方面,如果你担心实际模拟的效果,你可能会想让这些常量为真实情况下的取值。

 

空气阻力(Drag/Ari Resistance)由如下公式指定[来源Fluid Mechanics by Landau and Lifshitz, [Beckham] chapter 6, [Zuvich]]:

Fdrag= 0.5*Cd*A*rho*(v*v)

这里,Cd、A、rho是相关常量,我把他们一律组成上面的Cdrag(想了解具体信息的话,可以看一下原文链接,这里翻译君不做翻译啦~)

我们给出一组上面三个相关常量的具体数值来计算Cdrag。

Cdrag= 0.5*0.30*2.2*1.29 = 0.4257

我们通常让Crr等于30倍的Cdrag,即:

Crr= 30 * Cdrag = 30*0.4257 = 12.8

说实话,我无法确定Crr的值。因为我不能在任何地方找到它确切的数值。因此,用这个式子来模拟它的现实情况。

 

制动/刹车 braking

      当制动的时候,牵引力被一个相反方向的制动力(braking force)代替。此时,纵向合力由如下三个力的矢量和组成:

      制动时纵向的合力:Flong= Fbraking+Fdrag +Frr

      关于制动力的一个简化模型是:

      制动力:Fbraking = -u*Cbraking

      在这个模型中,制动力是一个常量。记住当车速降低到0时,就不要再维持制动力了,否则汽车将会向相反方向继续跑!!。

 

重量转换Weight Transfer

       译者按:略,这里没有翻译,因为模拟过程完全可以没有这一步也能实现很好的效果!但是我在实现我的游戏的过程中,尝试使用到这里的知识,觉得还挺好玩的。可以做出汽车切换状态时的缓冲效果,更加真实。但是稍微有点难度,如果想了解的,可以直接从上文给出的英文原链接中了解。


引擎动力EngineForce // 上文中的牵引力Fdirve的具体解释

         在前面有提及到引擎提供一个确切的动力,这其实是一种简化。实际上,引擎提供的是力矩(Torque)。力矩等于力乘以距离,是一种转动效应。如果你施加10N的力在距离转动轴0.3m处,你将得到一个3N*m的力矩。这等效于1N的力和距离转轴3m处的力矩。在两种情况下杠杆效应是相同的。

         引擎提供的力矩取决于引擎的转速(the speed at which the engine is turning),通常表达为rpm(转/分钟)。力矩和转速不是简单的线性关系,而是通常以一条力矩曲线表示(曲线的具体形状和高度因引擎不同而异,这取决于引擎测试)。这里一个5.7Liter、V8引擎的示例:

 

         注意:力矩曲线(黄色Torquecurve)的峰值在大约4400rpm出现,此时力矩最值为350lb-ft(约475N*m)。马力曲线(紫色Power curve)的峰值在大约5600rpm处出现,此时马力最值为345hp(257kW)。在这个特定的情况下,曲线仅仅被限制在1000~6000rpm的范围内,因为这是引擎的工作区间。低于1000rpm,引擎会熄火。高于6000rpm(也被称作“红线”),你就会毁了这台机器。

         哦,顺便提一下,这个图表是在给定转速下,发动机所能提供的最大力矩!实际力矩则依赖于你的节流阀(throttle?)的位置等因素。

         其中,我们最关心的可能是上面的力矩曲线,但是很多人也发现马力曲线也相当有意思。你可以使用下面的等式来描述马力hp和力矩torque(单位:英尺*磅)之间的关系:

         hp= torque * rpm / 5252;

         由于这个关系,两条曲线通常在5252rpm处交汇。你可以在上面的图表中验证一下。

         这里也有用国际单位制的对应图表(力矩:牛*米N*m,马力:千瓦kiloWatt),曲线的形状是相似的,但是相应的比例会不同(也因此他们不会再相交!)

        

         引擎产生的力矩在作用到后轮之前通过齿轮和差速器(齿轮传动装置)被修改。杠杆比例通过一个依赖于齿轮比(gearratios)的因素增加力矩。

         不幸的是,相当多的能量在这个过程中丢失。多达30%的能量转化为热能散失。这也就是所谓的70%转化率。让我说明一下我提及的是一个典型的数据,我没有任何特定车辆的实际数值。

         作用在后轮轴承上的力矩(torque)除以车轮半径(wheelradius)就是轮胎作用在地面上的力。(力等于力矩除以距离)

         顺便提一下,如果你想要搞通过那些神秘的轮胎产品标号来查询轮胎半径,可以看一下《The Wheel and Tyre Bible》http://www.carbibles.com。它也提供了一个非常方便的小计算器。例如:它能告诉我们P275/40ZR-18后轮的“Convette牌”车的空载半径是34cm。

        

         下面给出一个通过引擎力矩得到两个后轮作用在地面的纵向推动力的公式:

        牵引力:Fdrive= u*Tengine * Xg* Xd * n /Rw

         其中:u是车的方向,Tengine是在给定转速下的引擎力矩,Xg是齿轮比(gearratio),Xd是差分率,n是转换效率,Rw是车轮半径。

         一个例子:引擎转速为2500rpm,观察上面的曲线可知引擎力矩为448N*m,齿轮比是2.66(1档位),差分率是3.42,能量转换效率为0.7(也许!),车轮半径为0.34m。车子重量为1500Kg。

         此时,提供的推动力Fdrive就是(448*2.66*3.42*0.7/0.34=)8391N。

 

齿轮比GearRatios

         下面给出的齿轮比适用于CorvetteC5 hardtop车型

(来源:http://www.idavette.net/facts/c5specs/)

 

第一档g1: 2.66

第二档g2: 1.78

第三档g3: 1.30

第四档g4: 1.00

第五档g5:   0.74

第六档g6:   0.50

倒车档gR:   2.90

差分率Xd:  3.42

 

曲线运动Curves:

         好啦,现在对于直线运动的知识已经足够啦。那么来点转向的小餐怎么样?

         首先,一个需要始终记在心中的是:低速下转向和高速下转向的模拟是不同的。在低速行驶时(例如,停车场中的打方向),轮子更多的向他们指向的方向运动。为了模拟这种情况,你需要一些几何学和动力学知识。你不必考虑受力和重量。

         在高速行驶时,有一点值得注意:在车轮向一个方向运动的同时,它们也在向另一个方向运动(我理解为惯性!)。换句话说,轮子可能会拥有一个与车轮方向不同的速度。这意味着,存在着一个和车轮方向成一定夹角的速度分量,这是由摩擦导致的。正常情况下,一个车轮被设计成能够轻松的向一个特定方向滚动,但是侧向推动轮子由于摩擦力的存在是非常困难的。在高速转向时,轮子将被侧向推动,我们必须将它考虑在内。

首先看一下低速的情况 (我的模拟仅仅用这个(;′⌒`))

在这种情形下,我们可以假设轮子只能向它指向的方向运动。轮子能够滚动,但是不能侧向滑动。如果前轮转向delta角度,并且汽车维持匀速运动,那么汽车将会做圆弧运动。假设有许多直线汽车中心位置垂直速度方向向曲线内侧延伸,那么两条直线的交汇处,便是圆心。

         这能够被下面的截图很容易的说明。注意绿色直线都交汇于一点(汽车转向围绕的中心)。你可能注意到前轮并不是沿着同样的角度,外侧的轮子比内侧的车轮转过的更少。这也发生在现实生活中,汽车的控制系统被设计成将车轮转过不同的角度。对于汽车物理模拟,这一点显得不那么重要。我将仅仅关注控制前面内侧车轮转过的角度而忽略另一侧。

        

         弧线的半径由下图所示的几何规律决定:

        

         (译者注解:这里的两个灰色方块是两个车轮)。前后轮轴承间的距离已知且记为L。汽车运动轨迹半径记为R。图中显示了一个由弧线中心、两个车轮组成的三角形。假定前轮转过delta,那么其中各处的角度便如图所示。也因此便有如下关系:

        L= R*sin(delta);

         即R=L/sin(delta):※

         注意:如果转向角度detla是0,那么弧线半径是无限大,即我们将会直线行驶。

        

         好啦,现在我们如何已经可以通过转向角度delta得到弧线半径R了。下一步就是计算角速度,即汽车转向的速率。角速度通常用希腊字母ω表示,单位弧度/秒。他可以非常简单的去定义:如果我们以速率v、沿半径为R的曲线匀速驾驶,我们多久可以跑完一个圆?只需要圆周长度除以速率即可。在这段时间里,汽车将绕一个圆形路线完整的走一圈。换句话说:

         角加速度: ω=v/R

         通过使用最后的这两个公式,我们知道汽车在特定速度、特定转动角度下能转动多快。对于低速情况下,这就是我们所有需要的知识。转动角度delta必须由用户指定。车速取决于直线行驶情况下的速率。通过这些量,我们就可以计算弧线半径和加速度!汽车的速率(标量)不受转向影响,仅仅影响了速度矢量的方向。

关于高速情况下的,转向,则为惯性原理,原文最后仅仅做了简单的讲述,这个不多赘述了……。

 

 

 

 

 

2 0
原创粉丝点击