Как рассчитать ракету? - PullRequest
0 голосов
/ 30 декабря 2018

Итак, я получил 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 кажутся более или менее правильными.Только Velocity Z не может быть рассчитан так, как я пытался. В трехмерном пространстве траектория на самом деле не выглядит реалистичной.Так что под «не совсем» я подразумеваю «совсем не реально» ...

Я был бы рад за помощь.Спасибо и счастливого нового года - в соответствии с ракетой - конечно!

Ответы [ 2 ]

0 голосов
/ 31 декабря 2018

Я не знаю, какая у вас система координат

  • плоскость
  • сфера
  • эллипсоид типа WGS84

Полагаю, ваша земля плоская (вызвана вашими константами, однако ваши позиции предполагают что-то другое) ... поэтому я буду придерживаться этого пока ... У вас есть 2 проблемы:

  1. Физика Ньютона / Даламбера

    Вы странны, поскольку у вас нет умножения dt, поэтому оно работает, только если ваше обновление составляет 1 Гц.взгляните на это:

    вам не нужен ограничитель скорости в качестве воздушного трениясделаю это за вас, и вы должны ехать с ускорениями ... или силой, если вы хотите учесть и массовые изменения.

    Однако, поскольку вы работаете с землей / землей, я предполагаю, что вместо ньютоновского полета будет атмосферный полет, так чтов этом случае вам нужно управлять курсом не ускорением, а поворотом интегрированной скорости.Основное подруливающее устройство должно по-прежнему рассматриваться как ускорение.

    Столкновения не нужны в вашем случае (если ваша земля не плоская или на пути нет препятствий).

  2. Система управления ракетой

    Предлагаю использовать 3-х режимное (марковская модель) управление ракетой.

    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;
    }
//---------------------------------------------------------------------------

Возможно, вам придется немного подкорректировать константы в соответствии с вашими размерами и игровыми потребностями.Как вы можете видеть, вы можете настроить ракету довольно много, что идеально подходит для игры (технические улучшения).

Физика прямолинейна Ньютон / Даламбер (кроме поворота vel из-за крыльев) инаправляющая система работает, как описано выше.В первом состоянии ракета просто поднимается до alt0, затем она пытается повернуться к цели со скоростью dang0, сохраняя высоту, и, когда она ближе, чем dis0, она также начинает снижаться.Если ближе, чем dis1, ракета должна взорваться ...

Вот предварительный просмотр (вид сверху):

rocket flight

Белая линиялиния от земли, чтобы проверить высоту ракеты ... Ракета синего цвета, а цель красного цвета.

Математика поворота такова:

turn math

, поэтому я просто масштабировал tar-hdg, чтобы приблизительно соответствовать dang0*dt и добавлял это к исходному hdg.теперь новый курс поворачивается к цели на dang0*dt, поэтому я просто нормализую его к размеру единицы и пересчитываю скорость в этом новом направлении (поскольку крылья поворачивают скорость вместо ускорения)

Осторожно

Все используемые устройства должны быть совместимы. Я использую SI .Ваша константа 9.81 предполагает то же самое, но ваши значения позиции и цели не имеют смысла, если в метрах ... Зачем стрелять ракетой, если цель находится всего в нескольких метрах?Также значения предполагают, что ваши координаты либо не декартовы, либо земля не плоская / плоская.Также значения предполагают целые числа, надеюсь, что вместо этого у вас есть числа с плавающей точкой / двойные числа

0 голосов
/ 30 декабря 2018

Траектория будет параболой.Основные уравнения, которые достаточно хорошо объяснены здесь: https://courses.lumenlearning.com/boundless-physics/chapter/projectile-motion/

Трехмерная задача (x, y, z) может быть легко преобразована в двумерную (одноплоскостную) задачу (горизонтальную, вертикальную) дляуравнения затем возвращаются в 3D для задачи.

...