如何计算火箭? [英] How to calculate rocket?
问题描述
所以我得到了一个 3d系统和一些坐标:
- 开始坐标(x,y,z一枚火箭(在地面上)
- 火箭目标(也在地面上)的目标坐标(x,y,z)
我得到了一些初始值,如:
- maximum_velocityZ = 0.5
- maximum_resVelocityXY = 0.3
- gravity factor = 9.81
如何计算每个更新帧的飞行速度(velocityX,velocityY和velocityZ)
?
let maximum_velocityZ = 0.5let maximum_resVelocityXY = 0.3let gravity_factor = 9.81let rocketPosition = {x:3,y:0,z:2}让rocketTarget = {x:7,y:5,z:8}让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)让distanceY =(rocketTarget.y - rocketPosition.y)让distanceZ =(rocketTarget.z - rocketPosition.z)让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(更新,300)
此代码是我迄今为止开发的代码。我相信我走在正确的轨道上。 X和Y似乎或多或少是正确的。只有Velocity Z无法按照我尝试的方式计算。 在3D空间中,轨迹看起来并不真实。所以不是真的我的意思是根本不现实...
我很乐意提供帮助。谢谢,新年快乐 - 与火箭相匹配 - 当然!
我不知道你的坐标系是什么
- plane
- sphere
- 像这样的椭圆体WGS84
我的猜测是你的地面是平面的(从你的常数引起,但你的位置暗示其他东西)......所以我现在坚持这个......你有两个问题:
-
Newton / D'Alembert物理
你很奇怪,因为你没有
dt
乘法,所以只有当你的更新是1时它才有用赫兹。看看这个:
-
白线是从地面开始的线路,用于验证火箭的高度。 ..火箭是蓝色,目标是红色。
转向数学是这样的:
所以我只是缩放
tar-hdg
来大致匹配dang0 * dt
并将其添加到原始hdg
。现在,新标题最多转向目标dang0 * dt
所以我只需将其标准化为单位大小并重新计算速度到这个新方向(因为机翼正在转动速度而不是加速)
谨防单位
所有使用的单位必须是兼容我正在使用 SI 。你的
9.81
常数表示相同,但你的位置和目标值是没有意义的,如果在米...如果目标只有几米远,为什么射击火箭?此外,值表明您的坐标要么不是caressian,要么是地面不是平面/平面。值也表明整数希望你有浮动/双打......So I got a 3d system and some coordinates:
- Start coordinates (x, y, z) of a rocket (on the ground)
- Target coordinates (x, y, z) of the rockets target (also on the ground)
I got some initialize values like:
- maximum_velocityZ = 0.5
- maximum_resVelocityXY = 0.3
- gravity factor = 9.81
How can I calculate the flight velocitys
(velocityX, velocityY and velocityZ)
for every update frame?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)
This code is what I've developed so far. I'm sure I'm on the right track. X and Y seem to be more or less right. Only the Velocity Z can't be calculated the way I tried. In 3D space the trajectory doesn't really look realistic. So by "not really" I mean "not realistic at all"...
I would be happy for help. Thanks and a happy new year - matching to the rocket - of course!
解决方案I do not know what is you coordinate system
- plane
- sphere
- ellipsoid like WGS84
My guess is your ground is planar (induced from your constants however your positions suggest something else)... so I will stick with that for now... You got 2 problems:
Newton/D'Alembert physics
Yours is weird as you got no
dt
multiplication so it works only if your update is 1 Hz. take a look at this:you do not need speed limiter as air friction will do it for you and you should drive with accelerations ... or Force if you want to account for mass changes too.
However as you are working with ground/ground then I assume atmospheric flight instead of Newtonian so in such case you need to handle the heading control not by acceleration but by turning the integrated velocity. The main thruster should still be handled as acceleration.
The collisions are not necessary in your case (unless your ground is not planar or have obstacles along the way).
Rocket guiding system
I suggest to use 3 state (Markovov model) rocket control.
launch
Rise the rocket to safe altitude first to avoid obstacles, conserve fuel and maximize speed
cruise
Travel to the target area (while still keep its altitude). Simply compute heading projected on the ground plane and apply correction to the heading of the rocket to match it (still going parallel to ground).
hit
Hit the target while descending. Almost the same as #2 but this time you need to change altitude too...
On top of these you can add strategies to avoid detection/destruction or obstacles etc ... You can also make a fake approach from different heading to keep the launch position hidden ...
Here a simple C++ example of this approach:
//--------------------------------------------------------------------------- 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; } //---------------------------------------------------------------------------
You might need to tweak the constants a bit to match your sizes and game needs. As you can see you can customize the rocket quite a lot which is ideal for game (tech upgrades).
The physics is straight forward Newton/D'Alembert (apart the
vel
turning due to wings) and the guiding system works as described above. In first state the rocket just rise toalt0
then it try to turn towards target withdang0
turn speed while maintaining altitude and when closer thandis0
it start also descending. If closer thandis1
the rocket should explode ...Here preview (top view):
The white line is line from ground to verify the altitude of rocket ... Rocket is Blue and target is Red.
The turning math is like this:
so I just scaled
tar-hdg
to approximately matchdang0*dt
and add that to originalhdg
. now the new heading is turned towards target by up todang0*dt
so just I normalize it back to unit size and recompute velocity to this new direction (as wings are turning velocity instead of accelerating)Beware of the units
All the units used must be compatible I am using SI. Your
9.81
constant suggest the same but your position and target values makes no sense if in meters ... Why shoot rocket if target is just few meters away? Also the values suggest your coordinates are either not cartessian or ground is not planar/flat. Also the values suggest integers hope you have floats/doubles instead...这篇关于如何计算火箭?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
-