在您精通了直線瞄准之後
下一步就是圓周瞄准
該系統用到的數學略高深一些
以使您能極為准確的命中做圓周運動的機器人
同時仍能保留對付直線運動的機器人的有效性
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 為圓周半徑運動
計算必要的數據 圖
說明了我們需要的大部分數據
r 是機器人運動所繞的圓周半徑
方向變化為 a
而 v 則是敵方機器人運動的即時速度
圖
沿圓周移動
為了要准確瞄准敵人
我們需要某些特定的數據
機器人當前的方向
每轉的方向變化
當前的速度
我們的子彈到達的時刻
我們可以使用這些數據計算出敵人轉圈的圓半徑
以及它最後的方向(即
我們的子彈到達敵人的瞬間敵人的方向)
我們計算子彈擊中位置的方法如下
每轉的方向變化
我們用 headingchangeperturn = (heading
heading
)/time 得到這個值
其中 time 是兩次測量的間隔時間
您還必須使結果標准化
如下面代碼中所示
子彈時間
我們使用簡單的 time = getTime()+(range/(
(
*firepower))) 就可以滿足需要了
其中 range 是發射時我們和敵人之間的距離
而 firepower 是我們計劃使用的射擊火力
假定子彈擊中時
目標到我方的距離不變
這個假設並不合適
但是我們在本文後面的內容中開發出迭代之前
有它就足夠了
半徑
我們用 radius = velocity/headingchangeperturn 得出這個值
代碼
圓周路徑預測只需要清單
但是
請注意如果目標的方向變化很小
那麼就要使用直線瞄准
由於一旦半徑過大將導致存儲它所用的 double 溢出
因而我們使用這種方式來緩解這一風險
不過條件是方向變化比較小
我們也就不必太擔心了
清單
圓周瞄准代碼
public Point
D
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) >
) {
double radius = speed/changehead;
double tothead = diff * changehead;
newY = y + (Math
sin(heading + tothead) * radius)
(Math
sin(heading) * radius);
newX = x + (s(heading) * radius)
(s(heading + tothead) * radius);
}
/**if the change in heading is insignificant
use linear
path prediction**/
else {
newY = y + s(heading) * speed * diff;
newX = x + Math
sin(heading) * speed * diff;
}
return new Point
D
Double(newX
newY);
}
改進結果 如果您已經試過清單
中的代碼
那麼您會發現對付 spinbot(沿圓周移動的樣本機器人)的情況明顯好多了
但您很可能還會注意到
機器人發出的炮彈中仍有不少沒有命中目標
這不單單是因為瞄的不准
還要歸因於您對子彈要花費多長時間才能到達目標的估算不准
要提高您的技術
可以通過使用一個非常簡單的迭代來估算一下時間
然後把這個估算值送入瞄准系統得到當子彈到達目標時您與目標之間的距離的更精確的估算值
反復執行幾次這一步
您將得到近乎完美的估值
清單
迭代代碼
/**This function predicts the time of the intersection between the
bullet and the target based on a simple iteration
It then moves
the gun to the correct angle to fire on the target
**/
void doGun() {
long time;
long nextTime;
Point
D
Double p;
p = new Point
D
Double(target
x
target
y);
for (int i =
; i <
; i++){
nextTime =
(intMath
round((getRange(getX()
getY()
p
x
p
y)/(
(
*firePower))));
time = getTime() + nextTime;
p = target
guessPosition(time);
}
/**Turn the gun to the correct angle**/
double gunOffset = getGunHeadingRadians()
(Math
PI/
Math
atan
(p
y
getY()
p
x
getX()));
setTurnGunLeftRadians(normaliseBearing(gunOffset));
}
double normaliseBearing(double ang) {
if (ang > Math
PI)
ang
=
*PI;
if (ang <
Math
PI)
ang +=
*Math
PI;
return ang;
}
public double getrange(double x
double y
double x
double y
) {
double x = x
x
;
double y = y
y
;
double h = Math
sqrt( x*x + y*y );
return h;
}
改進圓周瞄准的性能 作為瞄准系統
圓周瞄准基本成形了
也就是說
既在我們能力所及范圍內又能在此基礎上更進一步的事並不多
但是
能改善性能的小改動有兩處
平均速度
您也許願意保持一個補償加速效應的移動平平均速度
而不是根據目標的最後速度進行計算
每一回合方向的平均變化
測量在每一回合內目標方向變化絕對量的平均值有助於我們對付那些不如 spinbot 有規律的目標
From:http://tw.wingwit.com/Article/program/Java/JSP/201311/19724.html