ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

基于误差四元数的滑模姿态跟踪控制设计与仿真实现

基于误差四元数的滑模姿态跟踪控制设计与仿真实现 简介面向飞行器姿态控制中普遍存在的万向节死锁与外部扰动问题这套资源以误差四元数作为姿态误差描述方式结合滑模控制策略提供MATLAB源码和配套CAJ格式文献可支撑姿态跟踪系统建模、控制器设计与仿真验证适合航空航天专业学生、控制算法工程师以及有一定MATLAB/Simulink基础的研究人员。压缩包共2个文件包含1个m脚本和1个CAJ文献整体大小34KB体量虽小但功能闭环m脚本对应核心控制算法与仿真流程CAJ文献用于补充理论推导和背景知识。已有445人浏览学习说明这一主题具有较稳定的参考热度。具体内容上源码展示了滑模面定义、滑模切换函数设计、控制增益选取、飞行器动力学模型与坐标系转换并可在Simulink中加入陀螺仪、加速度计模型及外部扰动模拟静止、平飞、翻滚等工况通过姿态角变化、误差四元数轨迹和控制器输出评估响应速度、稳态精度与抗干扰能力这份可直接运行的示例对理解理论并复现实验很有帮助。 搞飞行器姿态控制的人应该都听说过四元数滑模这个组合。但真正动手把“误差四元数”和“滑模控制器”凑到一个系统里做姿态跟踪并且把参数调稳、把抖振压下去这里面还是有不少门道的。最近我在一套四旋翼仿真平台上完整跑了一遍这个方案从数学推导到Simulink搭模型再到参数整定踩了不少坑也沉淀了一些经验。这篇就把整个实现思路、关键公式的来龙去脉、以及几个容易翻车的细节一次性讲清楚。1. 先把问题说清楚姿态跟踪到底在跟踪什么1.1 不是“稳定姿态”而是“追着期望姿态跑”很多人一开始会把姿态控制和姿态跟踪搞混。姿态稳定是让飞行器从一个任意姿态回到某个固定姿态比如水平悬停。姿态跟踪则更难一点——期望姿态本身是随时间变化的飞行器要像一个训练有素的追随者时刻咬住目标姿态。典型的场景就是无人机做航线规划时机体要根据期望的欧拉角序列或四元数轨迹不断调整自己的朝向。这个问题的核心矛盾在于误差怎么定义。如果用欧拉角做误差万向节锁问题会在某些姿态附近让系统直接失去一个转动自由度控制律在那个区域会变得很不稳定。用旋转矩阵做误差又太冗余9个元素只有3个自由度计算效率不高也不方便直接设计李雅普诺夫函数。四元数则是个恰到好处的工具——4个参数、3个约束、无奇异几何意义清晰插值也容易。1.2 为什么是误差四元数而不是绝对四元数刚开始做的时候我也想过直接用当前姿态四元数和期望姿态四元数的差值代数减法来当误差不行吗答案是不行。四元数的减法在数学上没有物理意义因为姿态空间本身就是流形结构两个姿态之间的“差距”应该是一个旋转也就是从当前姿态旋转到期望姿态所需要的那个旋转量这对应的是四元数的乘法关系。具体来说设当前姿态四元数为 \(q\)期望姿态四元数为 \(q_d\)那么误差四元数定义为\[ q_e q_d^{-1} \otimes q \]这里的 \(\otimes\) 是四元数乘法\(q_d^{-1}\) 是 \(q_d\) 的共轭对于单位四元数共轭就是逆。这样定义出来的 \(q_e\) 表示“从期望姿态到当前姿态的旋转偏差”。如果 \(q_e\) 的标量部分接近1向量部分接近0说明当前姿态和期望姿态几乎重合反之向量部分的大小和方向就直观地反映了偏了多少、往哪个方向偏。这个定义方式是整个控制器设计的基石后面所有滑模面、控制律、李雅普诺夫分析都建立在它之上。2. 从模型到误差动力学控制律设计前必须完成的推导2.1 飞行器姿态动力学方程刚体飞行器的姿态动力学可以用欧拉方程描述\[ J \dot{\omega} -\omega \times (J \omega) \tau d \]其中 \(J\) 是转动惯量矩阵\(\omega\) 是角速度向量体坐标系下\(\tau\) 是控制力矩\(d\) 是外部扰动比如气动力矩、陀螺力矩等。运动学方程则用四元数形式\[ \dot{q} \frac{1}{2} q \otimes \omega_q \]这里的 \(\omega_q [0, \omega^T]^T\) 是角速度的四元数形式标量部分为0。如果需要更精确的模型还得加上执行器动态、陀螺效应等但对于控制器设计阶段的仿真这两个方程已经够用了。我在仿真里还额外加了一个常值加周期扰动用来模拟常值风扰和电机振动带来的周期性力矩——不加扰动测试的控制器实战意义不大。2.2 误差四元数的动力学推导既然误差定义为 \(q_e q_d^{-1} \otimes q\)那它的时间导数也需要推出来。这个推导不复杂但要特别细心符号错一个后面全乱。对两边求导\[ \dot{q}_e \dot{q}_d^{-1} \otimes q q_d^{-1} \otimes \dot{q} \]利用 \(q_d^{-1} \otimes q_d 1\) 可得 \(\dot{q}_d^{-1} -q_d^{-1} \otimes \dot{q}_d \otimes q_d^{-1}\)。代入运动学方程整理后会得到误差四元数的运动学\[ \dot{q}_e \frac{1}{2} q_e \otimes \tilde{\omega}_q \]其中 \(\tilde{\omega} \omega - \tilde{R}^T \omega_d\) 是角速度误差\(\tilde{R}\) 是误差四元数对应的旋转矩阵\(\omega_d\) 是期望角速度。这个角速度误差的物理含义是当前角速度减去“期望角速度转换到当前坐标系下的值”。因为它是在体坐标系下定义的所以我们的控制力矩可以直接用到它上面不用再做坐标变换。2.3 角速度误差动力学将 \(\tilde{\omega}\) 对时间求导得到\[ J \dot{\tilde{\omega}} -\omega \times (J \omega) \tau d - J( \dot{\tilde{R}}^T \omega_d \tilde{R}^T \dot{\omega}_d ) \]这一项在滑模控制律设计时会被当作“已知非线性项”来抵消。需要注意的是\(\tilde{R}\) 的导数涉及叉乘推导时要格外小心建议用符号工具箱验算一遍再手写进代码。到这里整个误差系统就变成了两个状态\(q_e\) 和 \(\tilde{\omega}\)。接下来滑模控制器的设计就是围绕这两个状态展开的。3. 滑模控制器设计误差四元数是怎么被“塞”进滑模面的3.1 滑模面怎么选滑模面切换面的设计是滑模控制最核心的一步。对于姿态跟踪系统一个经典的选择是\[ s \tilde{\omega} \lambda q_{ev} \]其中 \(q_{ev}\) 是误差四元数的向量部分\(\lambda 0\) 是待调参数。为什么这么选从物理上看当系统滑上这个面即 \(s 0\)时角速度误差和姿态误差向量部分成正比。这意味着只要姿态还有偏差系统就会产生一个与之方向一致的角速度误差来“纠正”它。可以把它想象成一根弹簧偏差越大拉动速度越快\(\lambda\) 就是弹簧刚度。从数学上看当 \(s 0\) 时\(\tilde{\omega} -\lambda q_{ev}\)代入误差四元数运动学可以证明 \(q_{ev}\) 会指数收敛到0且标量部分收敛到1。也就是说滑模面上的系统是稳定的这保证了滑模控制的“滑动阶段”是牢靠的。3.2 趋近律选择与等效控制有了滑模面下一步是设计控制律让系统从任意初始状态快速到达滑模面。常用的是等速趋近律或者指数趋近律。我采用的是指数趋近律\[ \dot{s} -k \cdot \text{sgn}(s) - \epsilon s \]其中 \(k 0\) 是切换增益\(\epsilon 0\) 是指数趋近系数。\(\epsilon s\) 项让系统在距离滑模面较远时快速趋近\(k \cdot \text{sgn}(s)\) 项保证在滑模面附近仍能抵抗扰动维持滑模运动。控制律的推导套路就是“等效控制加切换控制”。先令 \(\dot{s} 0\) 且忽略扰动解得等效控制 \(\tau_{eq}\)然后加上切换项 \(\tau_{sw}\) 就得到完整的控制律\[ \tau \tau_{eq} \tau_{sw} \]\[ \tau_{eq} \omega \times (J\omega) - J \lambda \dot{q}_{ev} - J( \dot{\tilde{R}}^T \omega_d \tilde{R}^T \dot{\omega}_d ) \]\[ \tau_{sw} J(-k \cdot \text{sgn}(s) - \epsilon s) \]这里的 \(J\) 乘到切换项上是为了在稳定性分析时把惯量矩阵消掉好让李雅普诺夫导数的形式变干净。3.3 稳定性分析为什么这一套能收敛选取李雅普诺夫候选函数\[ V \frac{1}{2} s^T J s \]求导并代入控制律假设扰动上界已知且 \(k |d|\)得到\[ \dot{V} -s^T J \epsilon s - k |s| s^T d \]进一步放缩\[ \dot{V} \le -\epsilon \lambda_{\min}(J) |s|^2 - (k - |d|)|s| \]只要 \(k |d|\)\(\dot{V}\) 严格负定系统就能在有限时间内到达滑模面并沿滑模面收敛到姿态误差零点和角速度误差零点。这一步在论文里可能只需要几行字但实际设计时怎么选 \(k\) 是个权衡问题。\(k\) 太小扰动一来系统就脱离滑模面鲁棒性丧失\(k\) 太大执行器饱和加上严重抖振电机和结构都受不了。后面仿真部分我再具体说怎么调。4. 仿真实现与参数整定从公式到能跑的代码4.1 Simulink整体架构在Simulink里搭这套系统我建议分五个模块期望轨迹生成器输出期望四元数 \(q_d\)、期望角速度 \(\omega_d\) 和期望角加速度 \(\dot{\omega}_d\)误差计算模块根据当前 \(q\) 和 \(q_d\) 计算误差四元数 \(q_e\)用四元数乘法实现滑模控制器根据 \(q_e\) 和 \(\tilde{\omega}\) 计算控制力矩飞行器模型动力学运动学积分扰动注入模块模拟外部干扰仿真参数我用的是一套小型四旋翼的典型值参数符号数值惯量矩阵Jdiag(0.005, 0.005, 0.009) kg·m²滑模面系数λ2.0切换增益k0.5指数趋近系数ε5.0扰动上界|d|≤0.2 N·m注意仿真中的 \(k\) 是含惯量矩阵的因为切换项前面乘了 \(J\)所以实际施加到系统上的切换力矩幅值是 \(J \cdot k\)也就是0.0025到0.0045 N·m的量级。即使扰动上界标称0.2切换力矩也不需要太大因为等效控制已经抵消了大部分系统动力学。这一点很多人搞混——以为 \(k\) 直接就是切换力矩。4.2 核心代码实现下面给出控制器的MATLAB函数核心代码这个写法比较通用可直接嵌入MATLAB Function模块function tau sliding_controller(qe, omega_tilde, q, omega, qd, omega_d, omega_d_dot, J, lambda, k, eps) % qe, omega_tilde: 误差四元数和角速度误差 % q: 当前姿态qd: 期望姿态 % omega: 当前角速度omega_d: 期望角速度omega_d_dot: 期望角加速度 % 从误差四元数构造误差旋转矩阵 Re quat2rotm(qe); % 注意输入格式按实际需求调整 % 计算滑模面 s omega_tilde lambda * qe(2:4); % 误差四元数向量部分导数简化版 qev_dot 0.5 * (qe(4) * omega_tilde cross(qe(2:4), omega_tilde)); % 注完整推导需包含 qe 标量部分动力学这里做了简化 % 等效控制 tau_eq cross(omega, J*omega) - J * lambda * qev_dot - J * (cross(omega, omega_d) omega_d_dot); % 切换控制 tau_sw J * (-k * sign(s) - eps * s); % 总控制力矩 tau tau_eq tau_sw; end这里的quat2rotm需要根据实际四元数顺序调整Simulink里可能直接用slerp相关的工具函数更方便。我实际用的是自己写的四元数转矩阵函数避免踩MATLAB版本差异的坑。4.3 参数整定的四个阶段参数整定我建议遵循以下顺序别想着一步到位第一阶段只调 \(\lambda\)。把 \(k\) 和 \(\epsilon\) 设成较小值观察姿态误差能不能收敛。\(\lambda\) 太小系统响应慢误差收敛得拖泥带水\(\lambda\) 太大滑模面附近会产生高频振荡。我的经验是 \(\lambda\) 从1.0开始每次翻倍观察系统有没有振荡找到一个临界值再往回调30%。第二阶段调 \(\epsilon\)。这个参数影响远离滑模面时的趋近速度。\(\epsilon\) 太小到达滑模面的时间长\(\epsilon\) 太大系统会在趋近过程中出现超调。我把 \(\epsilon\) 从0.1往上加观察到达时间的变化最后锁定在5.0附近。第三阶段调 \(k\)。这个最麻烦。先给系统加已知扰动逐步增大 \(k\) 直到姿态误差稳态精度满足要求。注意观察控制力矩曲线如果出现明显的“锯齿波”说明 \(k\) 已经过大了。第四阶段边界层处理。实际应用里没人敢用纯 \(\text{sgn}\) 函数我改用饱和函数\(\text{sat}\)或双曲正切函数 \(\tanh\) 来替代边界层厚度 \(\Delta\) 取0.01到0.05之间。这样会损失一定的稳态精度但换来的抖振抑制效果非常明显。用 \(\tanh\) 的好处是连续可导对后续的仿真分析和控制器平滑性都有帮助。5. 常见问题与调试技巧实录5.1 问题一四元数归一化漂移这是新手最容易忽略的问题。四元数在积分过程中因为离散步长、数值误差等原因模长会逐渐偏离1。如果不做归一化误差四元数的计算会越来越不准确最终散掉。解决办法在每个仿真步长结束或误差计算之前强制做一次归一化q q / norm(q);这个操作看似简单却决定了整个仿真能不能稳定跑完。特别是长时间仿真哪怕每天漂移0.001跑上几分钟积累的误差也足够导致控制器发疯。5.2 问题二误差四元数的“双重覆盖”陷阱四元数有双重表示特性\(q\) 和 \(-q\) 表示同一个姿态。如果期望轨迹生成器有时输出正的 \(q_d\)有时输出负的 \(q_d\)比如通过插值得到四元数序列时出现符号跳变那么计算出的误差四元数会突然产生一个“假装”偏航了360度的巨大误差导致控制器瞬间饱和。解决办法每次计算 \(q_e\) 后检查标量部分如果 \(q_{e0} 0\)就对 \(q_e\) 取负。这样保证误差四元数始终走“短路径”避免符号跳变引发的控制量突变。5.3 问题三控制力矩中的交叉耦合项被忽略怎么办有些简化模型为了调试方便会丢掉 \(-\omega \times (J\omega)\) 这一项。在小角速度场景下可能问题不大但做大幅度姿态机动时这个耦合项产生的力矩可能比控制力矩本身还大。我的建议是前期为了 Debug 可以忽略但这个项必须保留在代码里只是先用“假”的惯量矩阵跑通流程再换上真实惯量矩阵验证鲁棒性。这样定位问题时可以把因素一个个排除掉。5.4 问题四滑模面求导引入测量噪声放大滑模面里包含 \(\tilde{\omega}\)而 \(\tilde{\omega}\) 的计算需要用到 \(\omega_d\) 的导数。如果期望角速度是从测量信号里估算的求导噪声会被滑模趋近律里的 \(\epsilon s\) 项放大导致电机转速波动。解决办法期望轨迹这边不要直接用微分而是用解析表达式或者截止频率合适的低通滤波器。同时在滑模面后面加一阶滤波时间常数取0.01s左右能明显抑制高频噪声对控制力矩的影响。5.5 经典问题速查表现象可能原因排查与解决姿态误差持续振荡\(k\) 过大或 \(\lambda\) 过大先降 \(k\)再降 \(\lambda\)逐步逼近控制力矩饱和切换增益 \(k\) 设置太大或 \(q_e\) 符号跳变减小 \(k\)检查误差四元数符号稳态误差无法消除边界层 \(\Delta\) 太大减小 \(\Delta\)或改用自适应滑模面仿真中途发散四元数未归一化或步长过大检查归一化步骤减小步长至0.001s以下跟踪大角度机动时震荡忽略 \(-\omega \times (J\omega)\)保留耦合项或引入前馈补偿最后分享一个实践经验我在实际调试中发现滑模控制的参数整定是有“手感”的不要死磕理论值。先用阶跃期望输入试看系统的上升时间和超调确定一个大致可用的参数组合再切换到连续轨迹用更贴近真实任务的工况做微调。另外仿真里用的边界层厚度 \(\Delta\) 到了真机上往往还要再加大一点。因为仿真里的测量噪声和延迟只是理想化的模型真机上的电源波动、安装误差、陀螺仪温漂都会带来额外的高频干扰。边界层本质上是在“鲁棒性”和“精度”之间做取舍你要明确知道自己愿意用多少精度换多强的鲁棒性。最后提一个快速验证技巧在仿真里直接注入一个“阶跃外部扰动”观察 \(s\) 曲线。如果 \(s\) 被扰动推开后能快速拉回到0附近说明切换增益还有余量如果拉回来很慢说明 \(k\) 不够得往上调。这个方法比单纯看姿态误差曲线更能直接反映滑模控制的鲁棒性——别忘了滑模控制的核心竞争力就是让系统“贴”在滑模面上而不是单纯追求姿态误差小。这套基于误差四元数的滑模姿态跟踪系统我在仿真平台上已经反复验证过很多次了对参数不确定性、外部扰动和模型失配都有不错的容忍度。做这个方向的朋友建议你也试试先搭一个干净的纯运动学仿真不考虑动力学把滑模面和误差定义吃透再加上动力学和扰动调试效率会高很多。本文还有配套的精品资源点击获取
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进