javascript-如何计算火箭?
作者:互联网
所以我得到了一个3d系统和一些坐标:
>火箭(在地面上)的起始坐标(x,y,z)
>火箭目标(也在地面上)的目标坐标(x,y,z)
我得到一些初始化值,例如:
> maximum_velocityZ = 0.5
> maximum_resVelocityXY = 0.3
>重力系数= 9.81
如何计算每个更新帧的飞行速度(velocityX,velocityY和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空间中,轨迹看起来并不真实.因此,“不是真的”我的意思是“根本不现实” …
我很乐意提供帮助.谢谢,新年快乐-与火箭相匹配-当然!
解决方法:
我不知道你是什么坐标系
>飞机
>球体
>类似于WGS84的椭球
我的猜测是您的地面是平坦的(由常数引起,但是您的位置暗示了其他东西)…所以我现在仍然坚持下去…您遇到了2个问题:
>牛顿/达朗伯物理学
您很奇怪,因为您没有dt乘法,因此仅当您的更新频率为1 Hz时,它才有效.看看这个:
> Can’t flip direction of ball without messing up gravity
您不需要限速器,因为空气摩擦会帮您解决这个问题,如果您也要考虑质量变化,则应该以加速…或“力”行驶.
但是,当您使用地面时,我假设大气飞行而不是牛顿飞行,因此在这种情况下,您需要通过加速而不是通过转动积分速度来处理航向控制.主推进器仍应作为加速度来处理.
在您的情况下,不需要碰撞(除非您的地面不是平坦的或一路上有障碍物).
>火箭引导系统
我建议使用3状态(Markovov模型)火箭控制.
>启动
首先将火箭升至安全高度,以避开障碍物,节省燃料并最大化速度
>巡航
前往目标区域(同时保持其海拔高度).只需计算投影在地面上的航向并将校正应用于火箭的航向以使其匹配(仍平行于地面).
>命中
下降时击中目标.与#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;
}
//---------------------------------------------------------------------------
您可能需要稍微调整常量以匹配您的大小和游戏需求.如您所见,您可以自定义很多火箭,非常适合游戏(技术升级).
物理学上是直截了当的牛顿/达朗伯(由于机翼而使飞机转向),导向系统的工作如上所述.在第一状态下,火箭只是升至alt0,然后尝试以dang0的转弯速度转向目标,同时保持高度,当距离dis0更近时,它也开始下降.如果比dis1更近,火箭应该爆炸…
这里预览(顶视图):
白线是从地面验证火箭高度的线.火箭是蓝色,目标是红色.
旋转数学是这样的:
所以我只是将tar-hdg缩放到大约匹配dang0 * dt并将其添加到原始hdg中.现在,新航向被转向到目标,直到dang0 * dt,所以我将其归一化为单位大小,然后将速度重新计算为这个新方向(因为机翼转向而不是加速)
当心单位
使用的所有单位必须兼容我正在使用SI.您的9.81常数表示相同,但如果以米为单位,您的位置和目标值就没有意义了.如果目标只有几米之遥,为什么还要发射火箭呢?这些值还表明您的坐标不是笛卡尔坐标系,或者地面不是平面/平面.值也表明整数希望您有浮点数/双精度数…
标签:javascript,math,calculation 来源: https://codeday.me/bug/20191013/1906983.html