極為準確的命中做圓周運動的機器人 (轉貼)
Alisdair Owens(awo101@ecs.soton.ac.uk)
學生,University of Southampton(UK)
2002 年 5 月
在您精通了直線瞄準之后,下一步就是圓周瞄準。該系統用到的數學略高深一些,以使您能極為準確的命中做圓周運動的機器人,同時仍能保留對付直線運動的機器人的有效性。Alisdair Owens 將向您展示如何實現這一技巧,并提供示例機器人,您可以把它拿出來試玩一次。
這篇小技巧會讓您深入理解圓周瞄準的工作原理。我們會從討論基本技巧的工作原理開始,接著闡釋一個簡單的迭代,它能顯著提高準確性。我還提供源代碼,它很輕易適應在您自己的機器人中工作。
工作原理
計算做圓周運動的機器人的 change in x(x 方向上的變化)和 change in y(y 方向上的變化)的偽碼相當簡單,假定您以弧度為單位進行計算:
change in x = cos(initialheading) * radius - cos(initialheading + changeinheading) * radius
change in y = sin(initialheading + changeinheading) * radius - sin(initialheading) * radius
式中 initialheading 是敵方機器人在初始位置的方向,子彈飛行期間的方向變化為 changeinheading,我們假定它以 radius 為圓周半徑運動。
計算必要的數據
圖 1 說明了我們需要的大部分數據:r 是機器人運動所繞的圓周半徑,方向變化為 a,而 v 則是敵方機器人運動的即時速度。
圖 1. 沿圓周移動
為了要準確瞄準敵人,我們需要某些特定的數據:機器人當前的方向,每轉的方向變化,當前的速度,我們的子彈到達的時刻。我們可以使用這些數據計算出敵人轉圈的圓半徑,以及它最后的方向(即,我們的子彈到達敵人的瞬間敵人的方向)。我們計算子彈擊中位置的方法如下:
headingchangeperturn = (heading2 - heading1)/time
得到這個值,其中 time 是兩次測量的間隔時間。您還必須使結果標準化,如下面代碼中所示。time = getTime()+(range/(20-(3*firepower)))
就可以滿足需要了。其中 range 是發射時我們和敵人之間的距離,而 firepower 是我們計劃使用的射擊火力。假定子彈擊中時,目標到我方的距離不變,這個假設并不合適,但是我們在本文后面的內容中開發出迭代之前,有它就足夠了。radius = velocity/headingchangeperturn
得出這個值。 代碼
圓周路徑猜測只需要清單 1。但是,請注重假如目標的方向變化很小,那么就要使用直線瞄準。由于一旦半徑過大將導致存儲它所用的 double
溢出,因而我們使用這種方式來緩解這一風險。不過條件是方向變化比較小,我們也就不必太擔心了。
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);}
改進結果
新聞熱點
疑難解答