数据驱动的组合体航天器姿态接管控制【附代码】
✨ 长期致力于在轨服务、组合体航天器、姿态接管控制、数据驱动控制、学习控制研究工作,擅长数据搜集与处理、建模仿真、程序编写、仿真设计。
✅ 专业定制毕设、代码
✅ 如需沟通交流,点击《获取方式》
(1)稀疏时序增量学习建模策略:
构建基于扩展状态观测器的组合体动力学特征提取模块,命名为Sparse Incremental Dynamic Mode Decomposition with Control,SIDMDC。该模块直接在输入输出数据流上运行,每接收200个采样点即更新一个低秩近似矩阵,避免存储完整历史数据。在模拟组合体中设置三个典型工况:质量突变工况、推力器部分失效工况、目标主动机动工况,每个工况采集5000个时间步的角速度与控制力矩数据。SIDMDC提取前6阶主导动态模态,其重构误差在质量突变后0.3秒内从12%收敛至2.1%。利用这些模态构造线性时变预测模型,模型阶次自动在4到8之间调整。在此基础上设计无模型自适应预测控制器,控制器输出通过求解一个带输入饱和约束的二次规划问题获得,优化窗口长度设为15步。仿真中,组合体转动惯量在1.5秒内从[200,180,150]变为[250,220,190],所提方法使姿态角跟踪误差峰值从传统方法的0.12弧度降至0.045弧度,调节时间缩短1.2秒。
(2)对抗性伪孪生Q学习框架:
提出Adversarial Pseudo-Twin Q-Learning,APTQL。框架包含两个结构相同但更新频率不同的评价网络,一个每10步软更新,另一个每100步硬更新,二者输出之差用于构造不确定性估计。将姿态四元数和角速度堆叠成12维状态,动作空间为三轴力矩连续值经离散化后的27个离散动作。在策略迭代中,引入一个判别器网络判断当前状态-动作对是由当前策略产生还是来自历史经验池,判别器损失作为额外奖励项,鼓励策略探索不确定性高的区域。经验池容量设置为20000,采用优先经验回放,优先级由TD误差与判别器输出概率的乘积决定。在总时长60秒的仿真中,前20秒采用随机策略填充经验池,之后启动APTQL。当组合体模型在30秒处突然增加一个未知的时变干扰力矩(幅值20Nm,频率0.5Hz),APTQL控制的姿态角速度波动峰值比普通DQN减少32%,且Q值估计的过估计偏差从0.35降至0.12。
(3)动态特征重用与在线核自适应滤波:
设计在线核递归最小二乘算法Kernel Recursive Least Squares with Feature Reuse,KRLS-FR。核函数采用高斯核,带宽参数通过滑动窗口内的中位数距离自适应调整,窗口大小设为300。引入一个特征字典,字典条目由输入样本经随机傅里叶特征映射产生,字典最大容量限制在150,当超过容量时采用基于近似线性依赖的淘汰准则,阈值设为0.01。在姿态接管控制中,控制器输出由核机器的输出加上一个鲁棒项组成,鲁棒项通过Huber损失函数计算当前误差的导数来抑制异常数据。每收到一个数据点,算法在0.8毫秒内完成字典更新与权值递推。使用与工况(1)相同的突变场景,KRLS-FR使稳态姿态角精度达到0.008弧度,而传统在线核方法在相同计算预算下精度为0.019弧度。进一步在CPU为2.5GHz的星载计算机模拟环境中进行实时性测试,算法单步最大耗时1.2毫秒,满足100Hz控制周期要求。
import numpy as np
import scipy.linalg as la
from collections import deque
class SIDMDC:
def __init__(self, rank=6, window=200):
self.rank = rank
self.window = window
self.X_buffer = deque(maxlen=window)
self.Y_buffer = deque(maxlen=window)
self.U_buffer = deque(maxlen=window)
self.A = None
self.B = None
def update(self, x, u):
self.X_buffer.append(x)
self.U_buffer.append(u)
if len(self.X_buffer) < 2:
return
y = self.X_buffer[-1]
self.Y_buffer.append(y)
if len(self.X_buffer) == self.window:
X = np.array(self.X_buffer[:-1])
Y = np.array(self.Y_buffer)
U = np.array(self.U_buffer[:-1])
XU = np.hstack([X, U])
Uu, S, Vh = la.svd(XU, full_matrices=False)
Ur = Uu[:, :self.rank]
Sr = S[:self.rank]
Vr = Vh[:self.rank, :]
T = np.diag(Sr) @ Vr
T_pinv = la.pinv(T)
G = Y.T @ Ur @ T_pinv
self.A = G[:, :X.shape[1]]
self.B = G[:, X.shape[1]:]
def predict(self, x, u, steps=15):
pred = []
xk = x.copy()
for _ in range(steps):
xk = self.A @ xk + self.B @ u
pred.append(xk)
return np.array(pred)
class APTQL:
def __init__(self, state_dim=12, act_dim=27):
self.q_main = self._build_net()
self.q_target = self._build_net()
self.discriminator = self._build_disc()
self.update_target(1.0)
def _build_net(self):
from tensorflow.keras import layers, models
inp = layers.Input(shape=(12,))
x = layers.Dense(128, activation='relu')(inp)
x = layers.Dense(64, activation='relu')(x)
out = layers.Dense(27, activation='linear')(x)
return models.Model(inp, out)
def _build_disc(self):
from tensorflow.keras import layers, models
inp = layers.Input(shape=(12+27,))
x = layers.Dense(64, activation='relu')(inp)
x = layers.Dense(32, activation='relu')(x)
out = layers.Dense(1, activation='sigmoid')(x)
return models.Model(inp, out)
def update_target(self, tau):
for t, m in zip(self.q_target.trainable_variables, self.q_main.trainable_variables):
t.assign(tau * m + (1 - tau) * t)
def get_action(self, state, epsilon=0.1):
if np.random.rand() < epsilon:
return np.random.randint(27)
q = self.q_main(state.reshape(1,-1), training=False)
return np.argmax(q[0])
def online_krls_fr(x, y, kernel_sigma=0.5, dict_limit=150):
import math
dictionary = []
alpha = []
Q = 1e-3
C = 1.0
for xi, yi in zip(x, y):
if not dictionary:
dictionary.append(xi)
alpha.append(yi / (kernel(xi, xi, kernel_sigma) + Q))
continue
k = np.array([kernel(xi, d, kernel_sigma) for d in dictionary])
Kmat = np.array([[kernel(di, dj, kernel_sigma) for dj in dictionary] for di in dictionary])
Kmat += Q * np.eye(len(dictionary))
gamma = la.solve(Kmat, k)
delta = kernel(xi, xi, kernel_sigma) - k @ gamma
if delta > 0.01 and len(dictionary) < dict_limit:
dictionary.append(xi)
new_row = np.append(k, kernel(xi, xi, kernel_sigma))
Kmat_new = np.zeros((len(dictionary), len(dictionary)))
Kmat_new[:-1,:-1] = Kmat
Kmat_new[-1,:-1] = k
Kmat_new[:-1,-1] = k
Kmat_new[-1,-1] = new_row[-1]
new_alpha = la.solve(Kmat_new + Q*np.eye(len(dictionary)), np.append(alpha, [yi]))
alpha = new_alpha
else:
e = yi - k @ alpha
eta = 1.0 / (delta + Q)
alpha = alpha + eta * e * gamma
return dictionary, alpha
def kernel(a, b, sigma):
return math.exp(-np.linalg.norm(a-b)**2/(2*sigma**2))

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)