極為準(zhǔn)確的命中做圓周運動的機器人 (轉(zhuǎn)貼)
Alisdair Owens(awo101@ecs.soton.ac.uk)
學(xué)生,University of Southampton(UK)
2002 年 5 月
在您精通了直線瞄準(zhǔn)之后,下一步就是圓周瞄準(zhǔn)。該系統(tǒng)用到的數(shù)學(xué)略高深一些,以使您能極為準(zhǔn)確的命中做圓周運動的機器人,同時仍能保留對付直線運動的機器人的有效性。Alisdair Owens 將向您展示如何實現(xiàn)這一技巧,并提供示例機器人,您可以把它拿出來試玩一次。
這篇小技巧會讓您深入理解圓周瞄準(zhǔn)的工作原理。我們會從討論基本技巧的工作原理開始,接著闡釋一個簡單的迭代,它能顯著提高準(zhǔn)確性。我還提供源代碼,它很輕易適應(yīng)在您自己的機器人中工作。
工作原理
計算做圓周運動的機器人的 change in x(x 方向上的變化)和 change in y(y 方向上的變化)的偽碼相當(dāng)簡單,假定您以弧度為單位進行計算:
change in x = cos(initialheading) * radius - cos(initialheading + changeinheading) * radius change in y = sin(initialheading + changeinheading) * radius - sin(initialheading) * radius 式中 initialheading 是敵方機器人在初始位置的方向,子彈飛行期間的方向變化為 changeinheading,我們假定它以 radius 為圓周半徑運動。
計算必要的數(shù)據(jù)
圖 1 說明了我們需要的大部分?jǐn)?shù)據(jù):r 是機器人運動所繞的圓周半徑,方向變化為 a,而 v 則是敵方機器人運動的即時速度。
圖 1. 沿圓周移動
為了要準(zhǔn)確瞄準(zhǔn)敵人,我們需要某些特定的數(shù)據(jù):機器人當(dāng)前的方向,每轉(zhuǎn)的方向變化,當(dāng)前的速度,我們的子彈到達的時刻。我們可以使用這些數(shù)據(jù)計算出敵人轉(zhuǎn)圈的圓半徑,以及它最后的方向(即,我們的子彈到達敵人的瞬間敵人的方向)。我們計算子彈擊中位置的方法如下:
headingchangeperturn = (heading2 - heading1)/time 得到這個值,其中 time 是兩次測量的間隔時間。您還必須使結(jié)果標(biāo)準(zhǔn)化,如下面代碼中所示。time = getTime()+(range/(20-(3*firepower))) 就可以滿足需要了。其中 range 是發(fā)射時我們和敵人之間的距離,而 firepower 是我們計劃使用的射擊火力。假定子彈擊中時,目標(biāo)到我方的距離不變,這個假設(shè)并不合適,但是我們在本文后面的內(nèi)容中開發(fā)出迭代之前,有它就足夠了。radius = velocity/headingchangeperturn 得出這個值。 代碼
圓周路徑猜測只需要清單 1。但是,請注重假如目標(biāo)的方向變化很小,那么就要使用直線瞄準(zhǔn)。由于一旦半徑過大將導(dǎo)致存儲它所用的 double 溢出,因而我們使用這種方式來緩解這一風(fēng)險。不過條件是方向變化比較小,我們也就不必太擔(dān)心了。
public Point2D.Double guessPosition(long when) { /**time is when our scan data was PRodUCed. when is the time that we think the bullet will reach the target. diff is the difference between the two **/ double diff = when - time; double newX, newY; /**if there is a significant change in heading, use circular path prediction**/ if (Math.abs(changehead) > 0.00001) { double radius = speed/changehead; double tothead = diff * changehead; newY = y + (Math.sin(heading + tothead) * radius) - (Math.sin(heading) * radius); newX = x + (Math.cos(heading) * radius) - (Math.cos(heading + tothead) * radius); } /**if the change in heading is insignificant, use linear path prediction**/ else { newY = y + Math.cos(heading) * speed * diff; newX = x + Math.sin(heading) * speed * diff; } return new Point2D.Double(newX, newY);}改進結(jié)果
新聞熱點
疑難解答