Physics Engine - Car Games [ 物理引擎 - 賽車遊戲 ]

時間: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必須由用戶指定。車速取決於直線行駛情況下的速率。通過這些量,我們就可以計算弧線半徑和加速度!汽車的速率(標量)不受轉向影響,僅僅影響了速度矢量的方向。

關於高速情況下的,轉向,則爲慣性原理,原文最後僅僅做了簡單的講述,這個不多贅述了……。

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章