2. 坐标系与姿态表示:地心惯性坐标系、本体坐标系、欧拉角、四元数、方向余弦矩阵

做卫星仿真,第一件事不是写代码,而是把坐标系搞明白。我见过太多新手,代码写得飞起,结果姿态算出来全是错的——最后发现是坐标系搞反了。说白了,坐标系就是卫星的「世界观」,你用什么尺子量,结果就长什么样。

这一节,我们聊聊卫星仿真里最常用的几个坐标系,以及怎么描述卫星「转了多少、朝向哪」。嗯,内容有点干,但都是硬通货。

2.1 地心惯性坐标系(ECI)

地心惯性坐标系,简称 ECI。你可以把它想象成宇宙里的一个「绝对参考系」——它不跟着地球转。

它的定义是这样的:

  • 原点:地球质心
  • X 轴:指向春分点(就是太阳从南往北穿过赤道那一点)
  • Z 轴:指向北极(地球自转轴方向)
  • Y 轴:右手定则,X 叉乘 Z 得到

为什么需要它?因为卫星的轨道运动,在惯性系里描述最方便。牛顿定律只适用于惯性系,你想想看,如果坐标系跟着地球转,那卫星的受力分析就多了一堆科里奥利力,多麻烦。

我个人的习惯:在仿真里,所有轨道积分、太阳位置计算,一律在 ECI 下做。等算完了,再转到其他坐标系去用。

小提示:常用的 ECI 系有 J2000 和 TEME 两种。J2000 是标准版本,TEME 是两行轨道根数(TLE)用的。如果你用 TLE 数据,记得用 TEME,别混了。我曾经在这上面吃过亏,算出来的星下点偏了十几公里。

2.2 本体坐标系(Body Frame)

本体坐标系,就是「长在卫星身上的坐标系」。它跟着卫星一起转。

定义很简单:

  • 原点:卫星质心
  • X 轴:通常指向卫星飞行方向(前向)
  • Y 轴:指向卫星右侧
  • Z 轴:指向地面(或天顶,看具体定义)

为什么需要它?因为卫星上的传感器、推力器、太阳帆板,都是固定在卫星本体上的。你要知道「太阳帆板朝哪」,就得用本体坐标系。

我做过一个项目,卫星上装了 4 个反作用飞轮,每个飞轮的安装方向都不一样。如果不把飞轮的力矩从本体坐标系转到惯性系,控制律根本没法写。

2.3 方向余弦矩阵(DCM)

方向余弦矩阵,说白了就是一个 3x3 的旋转矩阵。它能把一个向量从一个坐标系转到另一个坐标系。

假设你有一个向量 v 在坐标系 A 里表示为 v_A,你想知道它在坐标系 B 里长什么样:

v_B = C_AB * v_A

其中 C_AB 就是方向余弦矩阵。它的每一列,其实就是坐标系 A 的基向量在坐标系 B 里的投影。

举个例子:

import numpy as np

# 绕 Z 轴转 30 度
theta = np.radians(30)
C = np.array([
    [np.cos(theta), np.sin(theta), 0],
    [-np.sin(theta), np.cos(theta), 0],
    [0, 0, 1]
])

v_A = np.array([1, 0, 0])
v_B = C @ v_A
print(v_B)  # 输出:[0.866, -0.5, 0]

注意:方向余弦矩阵是正交矩阵,它的逆等于它的转置。也就是说,C_BA = C_AB^T。这个性质在仿真里非常有用——你只需要存一个矩阵,来回转就行了。

2.4 欧拉角

欧拉角,可能是最直观的姿态表示法。它用三个角度来描述旋转:

  • 滚转角(Roll):绕 X 轴转
  • 俯仰角(Pitch):绕 Y 轴转
  • 偏航角(Yaw):绕 Z 轴转

但这里有个坑——旋转顺序。同样是 (30°, 20°, 10°),按 ZYX 顺序转和按 XYZ 顺序转,结果完全不同。

我建议你统一用 ZYX 顺序(先偏航、再俯仰、最后滚转),这是航空航天领域的惯例。

from scipy.spatial.transform import Rotation as R

# 欧拉角转方向余弦矩阵
euler = [30, 20, 10]  # 单位:度
r = R.from_euler('zyx', euler, degrees=True)
C = r.as_matrix()
print(C)

避坑指南:欧拉角有个著名的「万向锁」问题。当俯仰角接近 ±90° 时,滚转和偏航会变得无法区分。我当年做半物理仿真时,就因为这个 bug 查了整整两天。所以,如果你要做大角度机动,别用欧拉角,用四元数。

2.5 四元数

四元数,是姿态仿真的「瑞士军刀」。它没有万向锁,计算效率高,插值平滑。

一个四元数长这样:

q = [q0, q1, q2, q3]

其中 q0 是标量部分,[q1, q2, q3] 是向量部分。它满足:

q0^2 + q1^2 + q2^2 + q3^2 = 1

四元数乘法的规则有点绕,但别怕,直接用库:

from scipy.spatial.transform import Rotation as R
import numpy as np

# 定义两个旋转
q1 = R.from_euler('z', 30, degrees=True).as_quat()
q2 = R.from_euler('y', 45, degrees=True).as_quat()

# 四元数乘法:先转 q1,再转 q2
q_total = R.from_quat(q2) * R.from_quat(q1)
print(q_total.as_quat())

我的经验:在仿真里,我通常用四元数做姿态积分,用方向余弦矩阵做坐标变换,用欧拉角做可视化。各取所长,别死磕一种。

2.6 知识体系总览

下面这张图,是我自己总结的坐标系与姿态表示的核心逻辑。你照着这个思路走,基本不会乱。

坐标系与姿态表示 - 知识体系 坐标系 地心惯性坐标系 (ECI) 本体坐标系 (Body Frame) 绝对参考 vs 随体参考 姿态表示方法 方向余弦矩阵 (DCM) 欧拉角 (Roll/Pitch/Yaw) 四元数 (Quaternion) 仿真中的应用 轨道积分 → ECI 系 姿态控制 → 本体系 ↔ ECI 系 核心原则:先定坐标系,再选表示法,最后做变换

2.7 总结与建议

这一节内容不少,我帮你捋一下重点:

  • ECI 系:做轨道计算用,别偷懒
  • 本体系:做姿态控制用,传感器数据都在这里
  • DCM:做坐标变换用,简单直接
  • 欧拉角:做可视化用,但小心万向锁
  • 四元数:做姿态积分用,稳定可靠

我个人建议,刚开始做仿真时,先把 ECI 和本体系之间的 DCM 写对。这一步对了,后面所有姿态计算都不会跑偏。嗯,就这些,动手试试吧。


专注资料整理