2. 坐标系与运动学:常用坐标系、坐标变换、火箭运动方程
搞火箭制导,第一件事不是写代码,而是把坐标系搞明白。
我见过太多新手,算法推得头头是道,一跑仿真就炸了。为什么?坐标系用错了。说白了,火箭在天上飞,你在地面看,你看到的「上下左右」和火箭感受到的「前后左右」完全是两码事。今天我们就来把这些坐标系掰扯清楚。
2.1 常用坐标系
火箭制导里常用的坐标系,其实就三个。我习惯把它们分成「地面看的」、「火箭想的」和「中间过渡的」。
2.1.1 发射坐标系
这个坐标系是固定在地面上的。原点通常选在发射点。X轴指向发射方位(正东或正北,看具体任务),Y轴垂直向上,Z轴按右手定则确定。
嗯,这里要注意:发射坐标系不是惯性系。它跟着地球自转在动。你想想看,火箭刚起飞时,它相对于发射坐标系的速度是0,但相对于地心,它已经有了一部分地球自转的速度。
我在项目中遇到过一个坑:某次仿真,我们把发射坐标系当成了惯性系来用,结果弹道偏差越来越大。后来排查才发现,地球自转带来的科里奥利力被忽略了。所以,发射坐标系只适合描述火箭相对于地面的位置和姿态,做动力学分析时一定要小心。
2.1.2 惯性坐标系
这才是真正的「不动」坐标系。通常我们用地心惯性系(ECI),原点在地心,X轴指向春分点,Z轴指向北极。
为什么需要它?因为牛顿定律只在惯性系里成立。你写运动方程,必须用惯性系。否则,那些虚拟力(离心力、科里奥利力)会让你头大。
我个人习惯:所有动力学计算都在惯性系里做,只在最后输出结果时,才转换到发射坐标系或速度坐标系。这样逻辑清晰,不容易出错。
2.1.3 速度坐标系
这个坐标系跟着火箭走。原点在火箭质心,X轴沿着速度方向,Y轴在纵向对称面内垂直于X轴,Z轴按右手定则。
为什么要搞这么个坐标系?因为气动力(升力、阻力)的定义和速度方向直接相关。阻力永远和速度方向相反,升力垂直于速度方向。你在速度坐标系里写气动力方程,简直不要太舒服。
2.2 坐标变换
坐标系之间怎么转?说白了就是旋转矩阵。我给大家总结一下最常用的几个变换。
2.2.1 发射坐标系 → 惯性坐标系
这个变换要考虑地球自转。假设发射时刻为t₀,地球自转角速度为ωₑ,那么从发射坐标系到惯性坐标系的变换矩阵为:
# Python示例:发射坐标系到惯性坐标系的变换
import numpy as np
def launch_to_inertial(lat, lon, t):
"""
lat: 发射点纬度 (rad)
lon: 发射点经度 (rad)
t: 从发射开始的时间 (s)
"""
omega_e = 7.2921150e-5 # 地球自转角速度 (rad/s)
# 先绕Z轴转经度
Rz_lon = np.array([
[np.cos(lon), -np.sin(lon), 0],
[np.sin(lon), np.cos(lon), 0],
[0, 0, 1]
])
# 再绕Y轴转纬度
Ry_lat = np.array([
[np.cos(np.pi/2 - lat), 0, np.sin(np.pi/2 - lat)],
[0, 1, 0],
[-np.sin(np.pi/2 - lat), 0, np.cos(np.pi/2 - lat)]
])
# 最后考虑地球自转
Rz_rot = np.array([
[np.cos(omega_e * t), -np.sin(omega_e * t), 0],
[np.sin(omega_e * t), np.cos(omega_e * t), 0],
[0, 0, 1]
])
return Rz_rot @ Ry_lat @ Rz_lon
2.2.2 惯性坐标系 → 速度坐标系
这个变换需要知道火箭当前的速度方向。假设速度矢量在惯性系中的分量为(vx, vy, vz),那么:
def inertial_to_velocity(v):
"""
v: 速度矢量 (3x1)
返回:从惯性系到速度系的变换矩阵
"""
v_norm = np.linalg.norm(v)
if v_norm < 1e-10:
return np.eye(3)
# 速度方向单位矢量
v_hat = v / v_norm
# 构造速度坐标系基矢量
# X轴:速度方向
x_v = v_hat
# Y轴:在纵向对称面内,垂直于X轴
# 这里假设纵向对称面由速度矢量和当地垂线决定
# 实际工程中需要更精确的定义
z_up = np.array([0, 0, 1]) # 简化处理
y_v = np.cross(z_up, x_v)
y_v = y_v / np.linalg.norm(y_v)
# Z轴:右手定则
z_v = np.cross(x_v, y_v)
# 变换矩阵(从惯性系到速度系)
C = np.vstack([x_v, y_v, z_v])
return C
2.3 火箭运动方程
好了,坐标系和变换都准备好了,现在可以写运动方程了。火箭的运动方程,说白了就是牛顿第二定律加上转动方程。
2.3.1 质心运动方程
在惯性坐标系下,火箭质心的运动方程为:
m * dv/dt = F_gravity + F_thrust + F_aero + F_control
其中:
- F_gravity:地球引力。注意不是简单的mg,要考虑地球形状和高度变化。我一般用J2模型。
- F_thrust:发动机推力。方向沿火箭纵轴,大小由发动机特性决定。
- F_aero:气动力。包括阻力和升力,在速度坐标系里计算最方便。
- F_control:控制力。来自舵面偏转或推力矢量。
2.3.2 绕质心转动方程
火箭的转动用欧拉方程描述:
I * dω/dt + ω × (I * ω) = M_aero + M_control
这里I是惯量张量,ω是角速度。M_aero是气动力矩,M_control是控制力矩。
2.3.3 完整的仿真流程
我给大家画个流程图,看看整个仿真是怎么串起来的:
2.4 代码实现示例
最后,给大家一个完整的运动方程积分示例。这个代码我用了很多年,结构清晰,适合做基础框架:
import numpy as np
from scipy.integrate import solve_ivp
def rocket_dynamics(t, state, params):
"""
火箭六自由度动力学方程
state: [x, y, z, vx, vy, vz, q0, q1, q2, q3, wx, wy, wz]
params: 火箭参数(质量、惯量、推力等)
"""
# 解包状态
pos = state[0:3]
vel = state[3:6]
quat = state[6:10] # 四元数表示姿态
omega = state[10:13] # 角速度
# 计算引力(简化模型)
r = np.linalg.norm(pos)
g = -params['mu'] / r**3 * pos
# 计算推力(假设沿箭体纵轴)
thrust_body = np.array([params['thrust'], 0, 0])
# 从箭体系到惯性系
C_body_to_inertial = quat_to_dcm(quat)
thrust_inertial = C_body_to_inertial @ thrust_body
# 计算气动力(在速度系中)
v_norm = np.linalg.norm(vel)
if v_norm > 1e-6:
# 动压
q = 0.5 * params['rho'] * v_norm**2
# 阻力(沿速度反方向)
drag = -q * params['Cd'] * params['S'] * vel / v_norm
else:
drag = np.zeros(3)
# 总力
F_total = g * params['mass'] + thrust_inertial + drag
# 加速度
acc = F_total / params['mass']
# 转动方程(在箭体系中)
I = params['I'] # 惯量张量
M_body = np.zeros(3) # 力矩(简化)
domega_body = np.linalg.inv(I) @ (M_body - np.cross(omega, I @ omega))
# 四元数导数
dquat = 0.5 * quaternion_multiply(quat, np.hstack([0, omega]))
return np.hstack([vel, acc, dquat, domega_body])
# 使用示例
params = {
'mass': 1000, # kg
'mu': 3.986e14, # 地球引力常数
'thrust': 5000, # N
'Cd': 0.3, # 阻力系数
'S': 0.5, # 参考面积
'rho': 1.2, # 大气密度
'I': np.diag([100, 200, 200]) # 惯量张量
}
# 初始状态
state0 = np.zeros(13)
state0[2] = 1000 # 初始高度1000m
state0[6] = 1 # 初始四元数(无旋转)
# 积分
sol = solve_ivp(rocket_dynamics, [0, 100], state0,
args=(params,), method='RK45', max_step=0.1)
好了,坐标系和运动学就讲到这里。这些是火箭制导的「地基」,地基打不牢,后面盖什么楼都会塌。下一节我们会进入真正的制导算法,到时候这些坐标系变换会反复用到,务必熟练掌握。
公众号:蓝海资料掘金营,微信deep3321