炮弹弹道的高精度模型及其简单应用 - [CBC]机械动力:火炮 (Create Big Cannons) - MC百科

2025-07-21 11:21:29
Avatar for adminadmin

一、前言

在这个mod中,实现大炮的精确制导确实是一件很浪漫的事,因此,我从这个mod的源代码入手,结合一些数学和物理知识,得到了炮弹弹道的高精度模型,初步解决了大炮发射参数的计算问题,粗略地研究了游戏中如何用可编程齿轮箱相对高精度地调节大炮发射参数,并进行了实战测试,效果很好。这篇教程注定是硬核的,曾经有人说过,文章里每出现一个数学公式,就会有一半的读者离开。但是这些数学公式是推导最终结果的必经之路,因此我还是决定将他们全部展示出来。如果你看不懂也没关系,我在评论区会给出计算大炮发射参数的程序的下载链接,同时也会在教程中展示程序的算法。如果我的推导过程有错误,欢迎指出,我会虚心接受,及时更正。

二、根据源代码了解炮弹发射和飞行的机制

分析炮弹的弹道,首先必须确定炮弹运动的初始条件。在MountedBigCannonContraption.java中,炮弹发射的核心代码如图所示。spawnPos对应炮弹初始位置的坐标,vec是炮弹初速度的方向向量,chargesUsed就是炮弹的初速度。回看上方代码,推测初速度大小就是装药量,初速度方向与炮口方向相同,初位置就是炮口位置。之后我插入了一些测试代码,在大炮发射时把参数输出到聊天框。重新打包后打开游戏,用各种装药、各种角度的大炮测试了一下,发现打印的各参数与猜想一致。

接着看炮弹的飞行过程中的速度变化。在AbstractCannonProjectile.java中,炮弹飞行的核心代码如图所示。Minecraft中运动的计算是离散的,每1刻(0.05s)计算一次。只要炮弹没有落地,程序就会先用上一刻的速度向量的y分量加上重力的影响(-0.05),再用重力调整后的向量数乘上一个阻力系数(0.99),作为这一刻的速度。

三、用运动学知识分析炮弹的运动

尽管运动是离散的,我们仍然将其视为连续运动进行分析。由于代码中速度的单位是m/tick,因此要格外小心。根据加速度的定义,我们得到以下两个式子(一律采用国际单位制):

炮弹始终在一个垂直于地面的平面内飞行,在这个平面内,将炮弹运动分解为竖直方向的分运动和水平方向的分运动,以竖直向上为y轴正方向,水平向前为w轴正方向,可以得到:

解这两个简单的常微分方程,得到通解:

设发射时大炮俯仰角θ,θ为正表示上仰,为负表示下俯,-π/6≤θ≤π/3(-30°≤θ≤60°),则t=0时:

设装药量为n,将根据源代码得到的 v=20n 代入初始条件,再将初始条件代入通解,得:

设坐标原点位于火炮底座的本体方块的中心,设大炮最前方的炮筒方块到火炮底座连接的炮腔方块共有k个方块(包括两端),上面两式对t从0到t积分,并加上炮弹初始位置的偏移量,得到炮弹运动的参数方程(t≥0):

消去参数t,得到炮弹运动的轨迹方程(w≥k cos θ):

下图是n=8,k=25,θ=30°时炮弹运动轨迹的图象(横坐标的x其实是w):

四、大炮发射参数的理论计算

假设火炮底座的本体方块坐标为(x0, y0, z0),目标坐标为(x1, y1, z1)。已知x轴正方向为东方,z轴正方向为南方。

1. 水平偏转角的确定

首先确定水平偏转角φ,-π<φ≤π(-180°<φ≤180°),俯视大炮,φ为正表示顺时针旋转,为负表示逆时针旋转。根据大炮炮口初始朝向的不同,需要进行分类讨论,而反正切函数又是个比较阴间的函数,不关心象限只关心符号。为了方便研究,定义一个新的二元函数atan2(y, x)(又叫四象限反正切函数):

令:

ψ的取值见下表:

初始朝向E SW Nψ0π/2π3π/2 若φ'≤-π,则φ=φ'+2π,否则φ=φ'。上述结论的推导过程略,并留作习题。至此φ的确定问题已经完全解决。

2. 俯仰角的确定

接着确定俯仰角θ。其实就是将除θ外的参数代入轨迹方程,然后解出θ。首先:

将y、w、n、k(定义请参考上一节)代入方程,此时方程中只有一个未知数θ。很遗憾的是,该方程无法求得解析解,只能使用数值方法(如二分法、牛顿法)求解。该方程在θ定义域内可能没有解(该参数下火炮无法命中目标)、有一个解或有两个解。

接下来讨论如何利用牛顿迭代法求解θ。我们要求解以下方程:

两边同时除以500,变形,然后令:

得到方程:

令:

如果λ1>λ3,可以直接宣告θ无解,因为λ1/λ3超出反余弦函数的定义域,f的定义域为∅。

如果λ1<λ3,易知f的定义域为:

其一阶导数:

将定义域放宽到(-z, z),观察图像,对函数性质作出以下未经严格证明的假设(数学水平不够):

θ-z(-z, θ0)θ0(θ0, z)zf(θ)-∞↑极大值↓-∞f'(θ)不关心+0-不关心f''(θ)不关心---不关心 由介值定理和单调性可知,当f(θ0)>0时,存在θ1∈(-z, θ0),θ2∈(θ0, z)使得f(θ)=0,分别对应低弹道和高弹道的俯仰角。

由牛顿迭代法的收敛定理可知,在上述情况下,选取θ10∈(-z, θ1),θ20∈(θ2, z)(即保证初值处的原函数值为负,与二阶导数值同号)进行迭代,必然收敛,可以求出θ1和θ2。

当加上[-π/6, π/3]的限制后,需要额外考虑这两个端点与z的大小关系和这两个端点的函数值的正负。这里给出一个寻找低弹道迭代初值θ10和高弹道迭代初值θ20的算法。

算法一:寻找低弹道迭代初值输入:较小量ε(可以设为0.01)输出:若低弹道无解,输出nan,否则输出低弹道迭代初值θ10步骤:1. 如果z>π/6,转2,否则转32. 如果f(-π/6)≤0,输出-π/6,否则输出nan3. 如果-z+ε==-z,输出nan(利用浮点数大数吃小数的特性,对于编译型语言,必须开启严格浮点运算)4. 如果-z+επ/3,转2,否则转32. 如果f(π/3)≤0,输出π/3,否则输出nan3. 如果z-ε==z,输出nan(利用浮点数大数吃小数的特性,对于编译型语言,必须开启严格浮点运算)4. 如果z-ε>-z且f(z-ε)≤0,输出z-ε,否则ε=ε/2,转3 利用上述算法寻找完初值后即可进行迭代求解(可别把nan送进去迭代啊)。然而目前我们只考虑了f(θ0)≥0(有解)的情况,未考虑f(θ0)<0(无解)的情况。实践中,只需在牛顿迭代法中考虑θ的定义域,当使用算法1和算法2得到的初值迭代时,一旦θ超出定义域,即可宣告无解。

算法三:考虑定义域的牛顿迭代法输入:初值θ,终止迭代条件ε(可以设为1e-6)输出:若以初值θ迭代无解,输出nan,否则输出解θ'步骤:1. 如果θ<-π/6或θ>π/3或|θ|≥z,输出nan2. θ'=θ-f(θ)/f'(θ)3. 如果|θ'-θ|<ε,输出θ',否则转44. θ=θ',转1 至此θ的确定问题也已经完全解决。

五、游戏中的简单应用

前面算得再精确,如果游戏中无法做到精准调节角度,也是没有意义的。因此我仍使用能打印信息的魔改过的mod,简单地研究了可编程齿轮箱旋转角度与大炮俯仰角的关系。

前人的研究已经指出,可编程齿轮箱旋转角度与大炮仰角改变角度不是1 : 1的关系,大炮仰角的改变角度要明显小于可编程齿轮箱的旋转角度,但还是符合某个比例关系的。我一开始采用64转的可编程齿轮箱(1倍速),发现大炮仰角的改变角度与可编程齿轮箱的旋转角度的函数关系竟然呈现阶梯型,即大部分情况下小幅度改变可编程齿轮箱旋转角度后重新实验,大炮仰角仍然不变,而在某些角度值附近大炮仰角才会发生变化。一气之下我把转速调成了1转进行实验,发现此时大炮仰角的改变角度与可编程齿轮箱的旋转角度是一一对应的,而且可编程齿轮箱旋转角度与大炮仰角改变角度大约是8 : 1的关系(即角度大约能精确到0.125°)。而在16转的情况下,虽然也会出现阶梯状,但是8 : 1的关系没有改变,经过实验,此转速下角度大约能精确到1°。也就是说,我们把算出来的角度值乘8,填入可编程齿轮箱,再以小转速执行旋转,是可以实现高精度角度调节的。同时我发现多次调节的角度是可以累加的,也满足8 : 1的关系,因此如果需要调节的角度超过45°,则可以分多次进行调节,直到转至期望角度。

水平偏转角的调节,经过多次测试,规律与上文完全一致。下面我将给出一个实际例子,展示大炮的高精度制导。

火炮底座的本体方块坐标为(-664, 2, -22),目标坐标为(-800, 10, 480),大炮初始朝南,n=8,k=25,经过计算,θ1=24.94°,θ2=38.96°,φ=15.16°。本例令θ=θ2,将θ和φ乘上8,分别输入到控制俯仰角和水平偏转角的可编程齿轮箱,转速为1转,然后装填炮弹,组装大炮,按顺序激活两个可编程齿轮箱,最后发射。可以看到炮弹十分精准地命中了目标。

六、展望

用1转转速进行角度调节,虽然很精确,但是太慢了,而提升转速又会降低精确度,这是一个矛盾。能否使用多个不同转速的可编程齿轮箱进行组合调节,进而缓解这一矛盾呢?此外,能否根据炮弹运动的参数方程和轨迹方程,推出更多的结论,进而产生更多的应用呢?但我精力有限,学业繁重,这些工作就交给后人吧(笑)。

到这里这篇教程就结束了,感谢每一个认真阅读的人,希望看完我的这篇教程后可以对大炮的精确制导有更深入的了解。运用数学和物理知识解决(游戏中的)实际问题,这大概就是工科生的浪漫吧(笑)。

Copyright © 2088 沙滩足球世界杯_足球世界杯中国 - pfw18.com All Rights Reserved.
友情链接