【问题标题】:How to calculate rocket?如何计算火箭?
【发布时间】:2018-12-30 14:22:28
【问题描述】:

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

  • 火箭(在地面上)的起始坐标(x、y、z)
  • 火箭目标的目标坐标 (x, y, z)(也在地面上)

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

  • maximum_velocityZ = 0.5
  • maximum_resVelocityXY = 0.3
  • 重力系数 = 9.81

如何计算每个更新帧的飞行速度(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 似乎或多或少是正确的。只有速度 Z 无法按照我尝试的方式计算。 在 3D 空间中,轨迹看起来并不真实。所以“不是真的”我的意思是“根本不现实”......

我很乐意寻求帮助。谢谢,新年快乐 - 当然是与火箭相匹配!

【问题讨论】:

  • 提示:让它适用于 xy 平面(例如,如 Projectile motion 所示)。一旦这样做了,您就可以旋转坐标系,而不是尝试在运动计算中使用三个维度。
  • @jonas00 我按照承诺完成了 C++ 示例......我用新代码和预览动画更新了我的答案......幸运的是,我能够避免任何三角函数的可怕性,也没有使用矩阵只是简单的向量.. .

标签: javascript math calculation


【解决方案1】:

不知道你是什么坐标系

  • 平面
  • 球体
  • 类似 WGS84 的椭球体

我的猜测是你的地面是平面的(由你的常数引起,但你的位置暗示了其他东西)......所以我现在会坚持下去......你有两个问题:

  1. 牛顿/达朗贝尔物理学

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

    您不需要限速器,因为空气摩擦会为您做到这一点,如果您也想考虑质量变化,您应该加速驾驶......或者 Force。

    但是,当您使用地面/地面时,我假设大气飞行而不是牛顿飞行,因此在这种情况下,您需要通过转动积分速度而不是加速度来处理航向控制。主推进器仍应作为加速度处理。

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

  2. 火箭引导系统

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

    1. 启动

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

    2. 巡航

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

    3. 命中

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


    除此之外,您还可以添加策略来避免检测/破坏或障碍物等...您还可以从不同的航向伪造方法以隐藏发射位置...

这里是这种方法的一个简单 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 常量建议相同,但如果以米为单位,您的位置和目标值毫无意义......如果目标距离只有几米远,为什么要发射火箭?此外,这些值表明您的坐标不是笛卡尔坐标,或者地面不是平面/平面。这些值还建议整数希望你有浮点数/双精度数...

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

    • 感谢您的回答。我已经查看了您的来源,但必须诚实地说,我在将公式适当地应用于我的问题时遇到了问题——不仅仅是因为 3d-2d 问题。正如我所说 - 无论如何感谢您的帮助。
    • 火箭不是弹丸......轨迹不同......而且火箭通常会跟踪目标......弹丸不会改变太多的轨迹......更不用说很多弹丸会飞在螺旋轨迹中(有时甚至从弓上射出的箭也会这样做)......所以该链接仅适用于一组非常特殊的情况。通过集成,您不需要任何测角学,并且方程在任何维度上都非常简单......因此转换为 2D 而不是转换回 3D 对于游戏来说不是很实用(除非在纸上由人类解决)
    猜你喜欢
    • 2023-02-22
    • 2015-05-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-12
    相关资源
    最近更新 更多