✨ 长期致力于在轨服务、组合体航天器、姿态接管控制、数据驱动控制、学习控制研究工作,擅长数据搜集与处理、建模仿真、程序编写、仿真设计。
✅ 专业定制毕设、代码
如需沟通交流,点击《获取方式


(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))

Logo

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

更多推荐