如何计算火箭?

How to calculate rocket?

所以我得到了一个 3d 系统 和一些坐标:


我得到了一些初始化值,例如:


如何计算每个更新帧的飞行速度(velocityX, velocityY and velocityZ)

let maximum_velocityZ = 0.5
let maximum_resVelocityXY = 0.3
let gravity_factor = 9.81

let rocketPosition = {
  x: 3,
  y: 0,
  z: 2
}
let rocketTarget = {
  x: 7,
  y: 5,
  z: 8
}
let rocketVelocity = {
  x: 0,
  y: 0,
  z: 0
}
let update = function() {
  rocketPosition.x += rocketVelocity.x
  rocketPosition.y += rocketVelocity.y
  rocketPosition.z += rocketVelocity.z

  let distanceX = (rocketTarget.x - rocketPosition.x)
  let distanceY = (rocketTarget.y - rocketPosition.y)
  let distanceZ = (rocketTarget.z - rocketPosition.z)

  let factorXY = Math.abs(distanceX / distanceY)
  rocketVelocity.x = maximum_resVelocityXY / Math.sqrt((1 / factorXY ** 2) + 1) * (distanceX > 0 ? 1 : -1)
  rocketVelocity.y = maximum_resVelocityXY / Math.sqrt((factorXY ** 2) + 1) * (distanceY > 0 ? 1 : -1)
  rocketVelocity.z = maximum_velocityZ * distanceZ;
  rocketVelocity.z /= gravity_factor;

  console.log("x:", Math.round(rocketPosition.x), "y:", Math.round(rocketPosition.y), "z:", Math.round(rocketPosition.z))
}

setInterval(update, 300)

这段代码是我到目前为止开发的。我确信我在正确的轨道上。 X 和 Y 似乎或多或少是对的。只有 Velocity Z 无法按照我尝试的方式计算。 在 3D 中 space 轨迹看起来并不真实。所以 "not really" 我的意思是 "not realistic at all"...

我很乐意提供帮助。谢谢,新年快乐 - 与火箭相配 - 当然!

轨迹将是一条抛物线。这里的基本方程式解释得很好:https://courses.lumenlearning.com/boundless-physics/chapter/projectile-motion/

3D 问题 (x, y, z) 可以很容易地转换为 2D(单平面)问题(水平、垂直),然后将方程转换为 3D 问题。

不知道你是什么坐标系

  • 飞机
  • 球体
  • 类似椭圆体 WGS84

我猜你的地面是平面的(从你的常量中得出,但是你的位置暗示了其他东西)......所以我现在会坚持......你有 2 个问题:

  1. Newton/D'阿朗伯特物理学

    你的很奇怪,因为你没有 dt 乘法,所以只有当你的更新是 1 Hz 时它才有效。看看这个:

    • Can't flip direction of ball without messing up gravity

    你不需要限速器,因为空气摩擦会为你做这件事,你应该加速驾驶......或者如果你想考虑质量变化,也可以使用力。

    然而,当你使用 ground/ground 时,我假设大气飞行而不是牛顿飞行,所以在这种情况下你需要处理航向控制而不是通过加速度,而是通过转动积分速度。主推应该还是加速处理吧

    在您的情况下不需要碰撞(除非您的地面不是平面的或沿途有障碍物)。

  2. 火箭制导系统

    我建议使用3态(马尔可夫模型)火箭控制

    1. 启动

      首先将火箭升至安全高度以避开障碍物、节省燃料并最大化速度

    2. 巡航

      前往目标区域(同时仍保持其高度)。简单地计算投射在地平面上的航向并对火箭的航向进行修正以匹配它(仍然平行于地面)。

    3. 命中

      下降时击中目标。几乎和#2一样,不过这次你也需要改变高度...


    除此之外,您还可以添加策略来避开 detection/destruction 或障碍物等...您还可以从不同航向进行伪造,以隐藏发射位置...

这是此方法的一个简单 C++ 示例:

//---------------------------------------------------------------------------
void  vector_one(double *c,double *a)
    {
    double l=sqrt((a[0]*a[0])+(a[1]*a[1])+(a[2]*a[2]));
    if (l>1e-10) l=1.0/l; else l=0.0;
    c[0]=a[0]*l;
    c[1]=a[1]*l;
    c[2]=a[2]*l;
    }
//---------------------------------------------------------------------------
// Z=0 plane is ground, Z+ is up
const double g=9.81;                // [m/s^2] Earth's gravity
const double acc0=20.0;             // [m/s^2] rocket main thruster acceleration
const double kv2 =0.002;            // [-] rocket air friction coeff (speed limiter)
const double alt0=50.0;             // [m] rocket safe altitude
const double dis0=100.0;            // [m] rocket safe distance to target
const double dis1= 10.0;            // [m] rocket explosion distance to target
const double dang0=375.0*M_PI/180.0;// [rad/s] rocket turn speed per yaw/roll/pitch
// Rocket
double dst[3]={+90.0,-50.0,0.0};    // [m] target position
double pos[3]={-100.0,200.0,0.0};   // [m] rocket position
double vel[3]={  0.0,  0.0,0.0};    // [m/s] rocket velocity
double acc[3]={  0.0,  0.0,0.0};    // [m/s^2] rocket acceleration
enum{
    _state_none=0,
    _state_launch,                  // rise to alt0
    _state_cruise,                  // get near target but maintain alt0
    _state_hit,                     // descend and hit
    };
int state=_state_launch;
void update(double dt)              // update rocket after dt [sec] has passed
    {
    int i;
    double v,a,hdg[3],tar[3];
    // guiding system
    if (state==_state_none)
        {
        for (i=0;i<3;i++) vel[i]=0.0;
        for (i=0;i<3;i++) acc[i]=0.0;
        return;
        }
    if (state==_state_launch)
        {
        // init heading to Up
        for (i=0;i<3;i++) hdg[i]=0.0; hdg[2]=1.0;
        if (pos[2]>=alt0) state=_state_cruise;
        }
    v=sqrt((vel[0]*vel[0])+(vel[1]*vel[1])+(vel[2]*vel[2]));// |vel|
    if ((state==_state_cruise)||(state==_state_hit))
        {
        vector_one(hdg,vel);                        // heading
        for (i=0;i<3;i++) tar[i]=dst[i]-pos[i];     // to target
        a=sqrt((tar[0]*tar[0])+(tar[1]*tar[1])+(tar[2]*tar[2])); // distance to target
        if (state==_state_cruise)
            {
            tar[2]=0;                               // no altitude change
            if (a<=dis0) state=_state_hit;
            }
        else{
            if (a<=dis1) state=_state_none;         // here you shoul add exlosion code
            }
        vector_one(tar,tar);
        // a = angle between hdg and tar [rad]
        for (a=0.0,i=0;i<3;i++) a+=hdg[i]*tar[i];
        a=fabs(acos(a));
        // approximate turn up to dang0
        if (a>1e-10) a=dt*dang0/a; else a=0.0;
        for (i=0;i<3;i++) hdg[i]=hdg[i]+a*(tar[i]-hdg[i]);
        vector_one(hdg,hdg);                        // new heading
        for (i=0;i<3;i++) vel[i]=v*hdg[i];          // new vel
        }
    // physics
    for (i=0;i<3;i++) acc[i] =-kv2*vel[i]*v;        // air friction (k*|vel|^2)
    for (i=0;i<3;i++) acc[i]+=hdg[i]*acc0;          // rocket thrust
    acc[2]-=g;                                      // gravity
    // Newton/D'Alembert simulation
    for (i=0;i<3;i++) vel[i]+=acc[i]*dt;
    for (i=0;i<3;i++) pos[i]+=vel[i]*dt;
    }
//---------------------------------------------------------------------------

您可能需要稍微调整常量以匹配您的大小和游戏需求。如您所见,您可以对火箭进行大量自定义,这非常适合游戏(技术升​​级)。

物理学是直截了当的 Newton/D'Alembert(除了 vel 由于机翼而转向)并且引导系统如上所述工作。在第一种状态下,火箭刚刚上升到 alt0,然后它尝试以 dang0 转弯速度转向目标,同时保持高度,当比 dis0 更近时,它也开始下降。如果比 dis1 近,火箭应该会爆炸 ...

此处预览(顶视图):

白线是从地面开始验证火箭高度的线...火箭是蓝色的,目标是红色的。

转数是这样的:

所以我只是缩放 tar-hdg 以大致匹配 dang0*dt 并将其添加到原始 hdg。现在新航向转向目标最多 dang0*dt 所以我将它归一化回单位大小并重新计算这个新方向的速度(因为机翼正在转向速度而不是加速)

注意单位

所有使用的单位必须兼容我正在使用 SI。您的 9.81 常量表示相同,但​​如果以米为单位,您的位置和目标值就没有意义……如果目标只有几米远,为什么要发射火箭?此外,这些值表明您的坐标不是笛卡尔坐标或地面不是 planar/flat。此外,值建议整数希望你有 floats/doubles 而不是...