在您精通了直线瞄准之后下一步就是圆周瞄准该系统用到的数学略高深一些以使您能极为准确的命中做圆周运动的机器人同时仍能保留对付直线运动的机器人的有效性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 PointDDouble guessPosition(long when) { /**time is when our scan data was producedwhen is the time that we think the bullet will reach the targetdiff 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 (Mathabs(changehead) > ) { double radius = speed/changehead; double tothead = diff * changehead; newY = y + (Mathsin(heading + tothead) * radius) (Mathsin(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 + Mathsin(heading) * speed * diff; } return new PointDDouble(newX newY); } 改进结果 如果您已经试过清单 中的代码那么您会发现对付 spinbot(沿圆周移动的样本机器人)的情况明显好多了但您很可能还会注意到机器人发出的炮弹中仍有不少没有命中目标这不单单是因为瞄的不准还要归因于您对子弹要花费多长时间才能到达目标的估算不准要提高您的技术可以通过使用一个非常简单的迭代来估算一下时间然后把这个估算值送入瞄准系统得到当子弹到达目标时您与目标之间的距离的更精确的估算值反复执行几次这一步您将得到近乎完美的估值 清单 迭代代码 /**This function predicts the time of the intersection between the bullet and the target based on a simple iterationIt then moves the gun to the correct angle to fire on the target**/ void doGun() { long time; long nextTime; PointDDouble p; p = new PointDDouble(targetx targety); for (int i = ; i < ; i++){ nextTime = (intMathround((getRange(getX()getY()pxpy)/((*firePower)))); time = getTime() + nextTime; p = targetguessPosition(time); } /**Turn the gun to the correct angle**/ double gunOffset = getGunHeadingRadians() (MathPI/ Mathatan(py getY() px getX())); setTurnGunLeftRadians(normaliseBearing(gunOffset)); } double normaliseBearing(double ang) { if (ang > MathPI) ang = *PI; if (ang < MathPI) ang += *MathPI; return ang; } public double getrange(double xdouble y double xdouble y) { double x = xx; double y = yy; double h = Mathsqrt( x*x + y*y ); return h; } 改进圆周瞄准的性能 作为瞄准系统圆周瞄准基本成形了也就是说既在我们能力所及范围内又能在此基础上更进一步的事并不多但是能改善性能的小改动有两处 平均速度您也许愿意保持一个补偿加速效应的移动平平均速度而不是根据目标的最后速度进行计算 每一回合方向的平均变化测量在每一回合内目标方向变化绝对量的平均值有助于我们对付那些不如 spinbot 有规律的目标 |