4. 基于四元数的太阳翼姿态控制

任务定义

本案例要求设计一个基于四元数的太阳翼对日定向控制器。卫星本体姿态用四元数表示,目标姿态为使太阳翼法线指向太阳方向。控制器需利用四元数误差直接计算控制力矩,避免使用欧拉角带来的奇异性问题。输入为当前姿态四元数与目标姿态四元数,输出为三轴控制力矩,并通过仿真验证姿态收敛过程。

四元数姿态误差定义

设当前姿态四元数为 q = [q0, q1, q2, q3]^T(标量在前),目标姿态四元数为 q_d。姿态误差四元数定义为:

q_err = q_d^{-1} ⊗ q

其中 q_d^{-1} 为共轭四元数(单位四元数逆等于共轭),⊗ 为四元数乘法。当 q_err 的矢量部分趋近于零时,当前姿态收敛到目标姿态。控制器采用如下形式:

τ = -K_p · sign(q0_err) · q_vec_err - K_d · ω

其中 q_vec_err = [q1_err, q2_err, q3_err]^T,ω 为角速度,K_p、K_d 为正定增益矩阵。符号项 sign(q0_err) 保证误差始终沿最短旋转路径收敛,避免绕远路。

代码实现


import numpy as np
from scipy.integrate import solve_ivp

def quat_mult(q1, q2):
    """四元数乘法,q = [q0, q1, q2, q3]"""
    w1, x1, y1, z1 = q1
    w2, x2, y2, z2 = q2
    return np.array([
        w1*w2 - x1*x2 - y1*y2 - z1*z2,
        w1*x2 + x1*w2 + y1*z2 - z1*y2,
        w1*y2 - x1*z2 + y1*w2 + z1*x2,
        w1*z2 + x1*y2 - y1*x2 + z1*w2
    ])

def quat_conj(q):
    """四元数共轭"""
    return np.array([q[0], -q[1], -q[2], -q[3]])

def quat_normalize(q):
    """归一化四元数"""
    norm = np.linalg.norm(q)
    return q / norm if norm > 0 else np.array([1.0, 0, 0, 0])

def quat_to_rotation_matrix(q):
    """四元数转旋转矩阵(用于验证)"""
    w, x, y, z = q
    return np.array([
        [1-2*(y*y+z*z), 2*(x*y-z*w), 2*(x*z+y*w)],
        [2*(x*y+z*w), 1-2*(x*x+z*z), 2*(y*z-x*w)],
        [2*(x*z-y*w), 2*(y*z+x*w), 1-2*(x*x+y*y)]
    ])

def satellite_dynamics(t, state, Kp, Kd, q_d, J):
    """卫星姿态动力学与运动学方程"""
    # state = [q0, q1, q2, q3, wx, wy, wz]
    q = state[0:4]
    omega = state[4:7]
    
    # 归一化四元数(防止数值漂移)
    q = quat_normalize(q)
    
    # 计算姿态误差四元数
    q_err = quat_mult(quat_conj(q_d), q)
    q_err = quat_normalize(q_err)
    
    # 控制器:τ = -Kp * sign(q0_err) * q_vec_err - Kd * ω
    q_vec_err = q_err[1:4]
    sign_q0 = np.sign(q_err[0])
    if sign_q0 == 0:
        sign_q0 = 1.0  # 避免零值
    tau = -Kp @ (sign_q0 * q_vec_err) - Kd @ omega
    
    # 姿态运动学(四元数微分方程)
    omega_quat = np.array([0, omega[0], omega[1], omega[2]])
    q_dot = 0.5 * quat_mult(q, omega_quat)
    
    # 刚体动力学(欧拉方程)
    omega_dot = np.linalg.inv(J) @ (tau - np.cross(omega, J @ omega))
    
    return np.concatenate([q_dot, omega_dot])

def simulate_sun_pointing():
    """仿真太阳翼对日定向控制"""
    # 卫星转动惯量 (kg·m²)
    J = np.diag([10.0, 12.0, 8.0])
    
    # 控制器增益
    Kp = np.diag([2.0, 2.0, 2.0])
    Kd = np.diag([5.0, 5.0, 5.0])
    
    # 目标姿态:太阳方向在卫星本体系中的期望指向
    # 假设太阳方向在惯性系中为 [1,0,0],卫星初始姿态使太阳翼法线偏离
    # 目标四元数(使本体x轴指向太阳)
    q_d = np.array([1.0, 0.0, 0.0, 0.0])  # 单位四元数,零姿态
    
    # 初始状态:姿态偏离30度,初始角速度为零
    angle = np.radians(30)
    axis = np.array([0, 1, 0])  # 绕y轴旋转30度
    q_init = np.array([np.cos(angle/2), 
                       axis[0]*np.sin(angle/2),
                       axis[1]*np.sin(angle/2),
                       axis[2]*np.sin(angle/2)])
    omega_init = np.array([0.0, 0.0, 0.0])
    state0 = np.concatenate([q_init, omega_init])
    
    # 时间范围
    t_span = (0, 30)
    t_eval = np.linspace(0, 30, 300)
    
    # 求解微分方程
    sol = solve_ivp(satellite_dynamics, t_span, state0, 
                    args=(Kp, Kd, q_d, J), t_eval=t_eval,
                    rtol=1e-8, atol=1e-10)
    
    return sol

# 运行仿真
sol = simulate_sun_pointing()

# 计算姿态误差角随时间变化(用于验证)
def compute_error_angle(q, q_d):
    """计算当前姿态与目标姿态之间的旋转角"""
    q_err = quat_mult(quat_conj(q_d), q)
    q_err = quat_normalize(q_err)
    # 旋转角 = 2*arccos(|q0_err|)
    angle = 2 * np.arccos(np.clip(np.abs(q_err[0]), -1.0, 1.0))
    return np.degrees(angle)

error_angles = []
for i in range(len(sol.t)):
    q = sol.y[0:4, i]
    q = quat_normalize(q)
    error_angles.append(compute_error_angle(q, q_d))

# 输出最终误差角(预期输出,非实测)
final_error = error_angles[-1]
print(f"仿真时间: {sol.t[-1]:.1f}s")
print(f"最终姿态误差角: {final_error:.4f}°")
print(f"最大角速度: {np.max(np.abs(sol.y[4:7, :])):.4f} rad/s")

落地与验证

运行环境:Python 3.8+,需安装 numpy 和 scipy。将上述代码保存为 quat_attitude_control.py,在终端执行 python quat_attitude_control.py。

验证方法:观察程序输出的最终姿态误差角。若控制器设计正确,误差角应随时间收敛至接近零(小于0.1°)。同时可绘制误差角随时间变化曲线,应呈现单调衰减趋势。由于本案例未提供真实执行环境,上述输出为基于代码逻辑的预期结果,实际运行时应以真实输出为准。

判定标准:仿真结束时姿态误差角小于初始误差的5%(即小于1.5°),且角速度趋于零,则判定控制律有效。若误差不收敛或发散,需检查增益参数是否合理(Kp与Kd的比值应满足阻尼条件)。

四元数姿态控制闭环框图 姿态误差计算 q_err = q_d⁻¹ ⊗ q 控制器 τ = -Kp·sgn(q0)·q_vec - Kd·ω 卫星动力学 J·ω̇ + ω×(J·ω) = τ 四元数运动学 q̇ = ½ q ⊗ [0, ω] q_err τ ω q (当前姿态) q_d (目标) ω (反馈) 四元数误差避免欧拉角奇异 | sign(q0)项保证最短旋转路径 | 仿真验证误差角收敛至零

关键说明

本实现采用单位四元数表示姿态,控制器直接使用四元数误差矢量部分,避免了欧拉角在90°附近出现的奇异问题。仿真中设置初始偏差30°,控制器增益取Kp=2、Kd=5(临界阻尼附近),预期在约15秒内收敛。若需调整响应速度,可按ζ=Kd/(2√Kp)关系修改增益。代码中quat_to_rotation_matrix函数可用于将结果转换为旋转矩阵以验证指向精度,但核心控制律不依赖该转换,确保全姿态范围内无奇异。