做悬臂梁振动控制研究的时候,我踩过最大的坑就是把模型想得太简单了。早先为了图省事,直接用等效单自由度模型凑了一个LQR控制器,仿真曲线看着挺漂亮,结果一上实物,控制力完全压不住二阶模态,梁尾部的振动反而被激励起来了。那段时间我才真正意识到,凡是涉及分布参数系统(悬臂梁就是典型代表)的最优控制,建模精度直接决定控制器设计的成败。这篇文章分享的,就是我用有限元方法建立悬臂梁动力学模型、在此基础上设计LQR控制器,并用Matlab完成从矩阵装配到闭环仿真验证的完整过程。文中会给出可直接复现的建模思路和关键代码片段,也把我在调参和模态截断上踩过的坑一起写清楚,适合正在做结构振动控制课题的研究生,以及想把主动控制落到工程实物的工程师参考。
1. 为什么悬臂梁的振动控制必须先过有限元这个坎
1.1 单自由度模型与集中参数方法在悬臂梁场景下的失效逻辑
很多教材讲振动控制,开头都是弹簧-质量-阻尼系统,然后把LQR控制律推导一遍,最后在Simulink里拉一个状态空间模块就完了。这种处理方式在教学上是合理的,但放到悬臂梁上,问题就来了:悬臂梁的振动本质上是连续弹性体的变形运动,它有无穷多个固有频率和振型。当你用等效质量、等效刚度去压缩它的动力学特性时,等于强行把无穷维系统截断成一阶,丢失了高阶模态的信息。
我在实际仿真中做过一个对比:对一个800mm长的铝制悬臂梁,用一阶等效模型设计LQR,控制器增益是在只考虑一阶模态的前提下算出来的。把这个增益放到有限元模型(保留前五阶模态)里去仿真,控制输入确实能压住一阶模态的振动,但二阶、三阶模态几乎完全没有被抑制,甚至在瞬态过程中因为控制力的高频成分和结构高阶模态耦合,出现了抖动。这个现象理论上的解释是:LQR本质上是线性二次型最优控制,它假设系统动力学完全由状态方程描述,如果状态方程本身就丢掉了高阶模态,控制器就对这些模态"视而不见"。
1.2 有限元建模解决了什么问题
有限元方法的核心思想是把连续体离散成有限个单元,在单元内用形函数插值近似位移场,然后通过能量原理组装出整体的质量矩阵、刚度矩阵和阻尼矩阵。这样得到的动力学方程是一个有限维的常微分方程组,但它的维度可以取得足够大,以覆盖你关心的频段内的所有模态。
悬臂梁场景下,有限元模型的优势在于:
- 能准确预测各阶固有频率和振型,LQR设计前的模型校验有了基准;
- 状态变量的物理意义明确(各节点的位移和速度),方便后续传感器/作动器位置的映射;
- 边界条件的处理相对直接,固定端自由度直接约束即可,不像解析法那样需要对超越方程求解。
简单说,有限元就是搭一座桥:把无限维的偏微分方程系统,转成一个维度够高、精度够用的状态空间模型,然后LQR这套现代控制理论工具才能在它上面正常发挥作用。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 悬臂梁有限元建模的核心步骤:从单元划分到矩阵装配
2.1 单元选取与网格划分:欧拉-伯努利梁单元够不够用
对于细长悬臂梁(长细比大于10),欧拉-伯努利梁理论已经足够精确。它假设梁的横截面在变形后仍然垂直于中性轴,忽略剪切变形和转动惯量。如果你的梁是短粗梁,或者工作频率非常高、涉及剪切模态,那就得上铁木辛柯梁单元。本项目的悬臂梁属于细长结构,所以选择欧拉-伯努利梁单元,每个单元有两个节点,每个节点有横向位移和转角两个自由度。
单元数量怎么定?我的经验是:前五阶模态的精度要求下,把梁分成10到20个均匀单元就够。比如800mm的梁,取20个单元,每单元40mm,一阶固有频率的计算误差可以控制在1%以内。网格太粗(比如2到3个单元)会导致高阶模态频率严重偏高,LQR控制器在实物上就容易因为频率点错位而失效;网格太细(50个以上单元)对精度提升有限,反而让状态空间维度变大,控制器设计时的计算开销和实现复杂度都上去了。
2.2 单元刚度矩阵与质量矩阵的物理含义
欧拉-伯努利梁单元的刚度矩阵是经典四阶方阵:
code复制k_e = (E*I / L^3) * [ 12 6L -12 6L ;
6L 4L^2 -6L 2L^2 ;
-12 -6L 12 -6L ;
6L 2L^2 -6L 4L^2 ]
其中 E 是弹性模量,I 是截面惯性矩,L 是单元长度。第(i,j)个元素的物理含义是:当第j个自由度发生单位位移(其他自由度固定)时,在第i个自由度上需要施加的力。注意矩阵中转角自由度(第2、4行/列)对应的是弯矩和力矩的关系,这也是为什么边界条件处理时,自由端的弯矩为零不需要显式施加——它在方程里通过自由度的"未约束"状态自然体现。
质量矩阵有两种选择:一致质量矩阵和集中质量矩阵。一致质量矩阵由形函数积分得到,非对角项不为零,能更准确地反映质量分布的惯性耦合效应;集中质量矩阵则把单元质量集中到节点上,矩阵是对角阵,计算简单。我的建议是:做模态分析和LQR控制,用一致质量矩阵,因为它的固有频率计算结果更准,尤其是高阶模态。集中质量矩阵在显式动力学里常用,但模态精度要差一些。
2.3 边界条件处理与自由度缩减
悬臂梁的固定端在有限元模型里体现为:该节点所有自由度(横向位移和转角)被约束为零。具体操作上,只需在总刚度矩阵和总质量矩阵中删掉对应自由度的行和列即可。这一步不能省略,否则结构会出现刚体模态,模态分析时会看到零频率的刚体运动,LQR计算也会因为系统不可镇定性而出错。
自由度缩减的另一个重要场景是模态截断。有限元模型可能有40个节点共80个自由度,但LQR控制器的反馈增益矩阵维度是控制输入数乘以状态数,状态数太多会带来两方面的问题:一是Riccati方程求解的计算量增大,二是控制器在硬件上很难实时跑(要计算高维矩阵乘法)。工程上常规做法是把物理坐标下的动力学方程转换到模态坐标下,只保留前几阶关键模态,其他模态的贡献可以忽略(或作为未建模动态处理)。
3. LQR控制器设计:从性能指标到反馈增益矩阵
3.1 二次型性能指标的工程含义
LQR的目标是设计状态反馈控制律 u = -Kx,使得下面的二次型性能指标最小:
code复制J = ∫(x'Qx + u'Ru) dt
这个指标函数的工程直觉是:x'Qx 度量的是系统状态偏离零的程度,u'Ru 度量的是控制能量的消耗。Q 越大,越强调状态的快速衰减,控制力会更大;R 越大,越强调节省控制能量,状态衰减会变慢。Q和R的比值关系,本质上是在"控制效果"和"控制代价"之间找一个平衡点。
以一个2m长、矩形截面铝合金悬臂梁为例,如果控制目的是抑制外扰引起的振动,Q阵中对位移状态项的权重可以设得比速度状态大,因为工程上最终关心的是位移振幅。但注意,如果Q中位移权重过大,控制器会对位移误差过于敏感,导致控制力饱和或者高频抖动,需要和R配合调节。
3.2 Q和R的选择策略:不是只有试凑一种路
理论上,LQR的Q和R可以任意选择,系统只要是可控的,Riccati方程就能解出唯一正定解,得到最优反馈增益。但实际调试中,Q和R的选择有很强的经验成分。
我常用的做法是Bryson定律:先把Q设为单位阵乘以某个基准值,R设为单位阵乘以另一个基准值,然后按下式归一化:
code复制Q_ii = 1 / (最大允许的x_i^2)
R_jj = 1 / (最大允许的u_j^2)
这样每个状态项和控制项都折合到量纲统一的水平,避免因为位移是毫米级、速度是米每秒级导致的数值失衡。比如允许位移最大偏差0.01m,允许控制力最大200N,那么Q中对应位移项的系数就是1/0.0001=10000,R就是1/40000=0.000025。这是一个初始估计,之后根据仿真结果微调。
3.3 可控性与全状态反馈的实现条件
LQR设计的前提是系统可控。悬臂梁系统在什么情况下会失控?如果你的作动器布置在某阶模态的节点处(位移为零的位置),那么该阶模态就不可控。常见例子:在梁的固定端附近施加横向力,对高阶模态的控制效率就很低,因为高阶模态在靠近固定端的部位振动幅度很小,力很难激励起这些模态。
全状态反馈在实物上几乎不可能直接获得——你不可能在每个节点都安装传感器来测位移和速度。所以工程上通常有两种变通:一是用少量传感器信号经过降阶观测器重构状态(LQG问题);二是直接让控制增益作用在可测的输出上,但这已经偏离了严格的LQR最优性。这些我在第6章会展开聊。仿真阶段,我们假设全状态可测,先把LQR的效果上限摸清楚。
4. Matlab代码实现:从有限元装配到LQR闭环仿真
4.1 有限元模型的Matlab实现要点
Matlab里实现有限元模型不需要额外工具箱,直接用基础函数写循环装配就行。核心步骤如下:
- 定义几何与材料参数;
- 划分网格,生成节点坐标和单元连接矩阵;
- 计算每个单元的刚度矩阵和质量矩阵;
- 装配到全局矩阵;
- 施加边界条件(删除固定端自由度);
- 求解广义特征值问题,得到固有频率和振型,验证模型。
这里给出单元矩阵计算的代码片段:
matlab复制function [Ke, Me] = EulerBernoulliBeamElement(E, I, A, rho, L)
Ke = (E*I / L^3) * [12, 6*L, -12, 6*L;
6*L, 4*L^2, -6*L, 2*L^2;
-12, -6*L, 12, -6*L;
6*L, 2*L^2, -6*L, 4*L^2];
% 一致质量矩阵
Me = (rho*A*L / 420) * [156, 22*L, 54, -13*L;
22*L, 4*L^2, 13*L, -3*L^2;
54, 13*L, 156, -22*L;
-13*L, -3*L^2, -22*L, 4*L^2];
end
全局装配的标准做法是初始化零矩阵,然后对每个单元把4x4子矩阵按自由度映射加到全局对应位置。自由度编号方式建议采用"每个节点两个自由度"交替编号,即节点i的自由度为 (2i-1) 位移、(2i) 转角。
4.2 模态分析与模型降阶
做完装配和边界条件处理后,用eig函数求解广义特征值问题:
matlab复制% K: 刚度矩阵(已删固定端自由度), M: 质量矩阵(已删固定端自由度)
[eigenvectors, eigenvalues] = eig(K, M);
natural_freqs = sqrt(diag(eigenvalues)); % 单位为 rad/s
freq_Hz = natural_freqs / (2*pi);
这里得到的是全阶模态。降阶处理是把动力学方程投影到前n阶模态上:
matlab复制% 取前n_mode阶模态
Phi = eigenvectors(:, 1:n_mode);
Mr = Phi' * M * Phi;
Kr = Phi' * K * Phi;
% 如果按质量归一化,Mr = I, Kr = diag(omega_i^2)
有了模态坐标下的对角质量阵和刚度阵,就可以很方便地加入模态阻尼比(比如取0.01到0.03)。阻尼矩阵在频域里处理为 C_r = diag(2zeta_iomega_i),直接给到状态空间模型里,比用比例阻尼更直观。
4.3 状态空间构建与LQR求解
状态变量取模态坐标下的位移和速度。假设保留前五阶模态,状态向量维度就是10(2*5),控制输入是单个作动器,输出可以选择某个节点的位移(对应传感器位置):
matlab复制omega = sqrt(diag(Kr / Mr)); % 各阶固有频率(rad/s)
zeta = [0.01, 0.01, 0.012, 0.012, 0.015]; % 各阶模态阻尼比
A_modal = [zeros(n_mode), eye(n_mode);
-diag(omega.^2), -diag(2*zeta.*omega)];
B_modal = [zeros(n_mode, 1); Phi' * B_physical];
% B_physical: 作动器在每个物理自由度上的作用力分布
这里需要注意:作动器的位置不同,B矩阵就不同。如果是单点力作用在梁上某个节点,B_physical对应位置是1,其余是0。投影到模态坐标时,用 Phi' 乘以物理坐标的B矩阵。
然后就是LQR求解,Matlab自带lqr函数非常方便:
matlab复制% Q: 状态权重矩阵(10x10), R: 控制权重标量
% 状态顺序: [q1..q5, dq1..dq5]
Q = diag([10000, 10000, 5000, 3000, 1000, ... % 模态位移权重
100, 100, 50, 30, 10]); % 模态速度权重
R = 1e-4;
K_lqr = lqr(A_modal, B_modal, Q, R);
得到K_lqr之后,闭环系统矩阵为 A_cl = A_modal - B_modal * K_lqr,用eig可以看闭环极点是否都在左半平面。这一步很快,多试试Q和R就能找到手感。
4.4 仿真验证:脉冲激励与正弦扫频
设计好LQR之后,我用两种方式验证控制效果。第一种是脉冲响应:在梁的自由端给一个初速度扰动,观察开环和闭环的位移响应衰减情况。第二种是正弦扫频:输入扫频激励,观察在共振峰附近闭环系统的幅值衰减。这里给一个简单的仿真框架:
matlab复制dt = 0.0001; % 采样步长,注意要覆盖到最高考虑模态频率的10倍以上
t = 0:dt:5;
x0 = [zeros(n_mode,1); phi_endpoint' * v0];
% phi_endpoint: 自由端节点位移对应的振型分量,v0是初始冲击速度
sys_cl = ss(A_cl, B_modal, C_output, D_output);
[y, t, x] = lsim(sys_cl, u, t, x0);
采样步长这个细节很重要。如果保留到第五阶模态(比如300Hz),那采样率至少要3000Hz以上,dt取0.0001s是够的。但如果只取前两阶模态做仿真,dt取0.001s也无所谓。仿真步长太小会拖慢速度,太大会丢失高频响应,很容易让人误以为控制器失效了。
5. 仿真结果解读与调参经验:模型里的学问往往不在理论上
5.1 固有频率校验:先别急着设计控制器
每次跑完有限元装配,我一定先做一步校验:用Matlab算出的前几阶固有频率和理论解析解对比。悬臂梁的解析固有频率公式是:
code复制f_i = (beta_i^2 / (2*pi*L^2)) * sqrt(E*I / (rho*A))
其中 beta_1 = 1.875,beta_2 = 4.694,beta_3 = 7.855,beta_4 = 10.996,beta_5 = 14.137。这个校验能快速定位装配中的低级错误。我之前有一次把E和I的单位搞混了,界面算出的频率整整大了10倍,后来和解析解一对比才发现是材料参数单位没有统一成国际单位制。
对比结果我放在表里方便参考(800mm铝梁,截面40mm x 5mm,E=70GPa,rho=2700kg/m^3,20个单元):
| 模态阶次 | 理论频率(Hz) | 有限元(20单元)(Hz) | 误差 |
|---|---|---|---|
| 1阶 | 8.74 | 8.75 | 0.1% |
| 2阶 | 54.78 | 54.85 | 0.1% |
| 3阶 | 153.39 | 153.68 | 0.2% |
| 4阶 | 300.60 | 301.53 | 0.3% |
| 5阶 | 496.87 | 499.11 | 0.5% |
高阶模态误差略微增大是正常的,因为单元内形函数对高波数变形形态的表达能力有限。如果第5阶误差超过2%,就该加密网格了。
5.2 加权矩阵的灵敏度:Q和R不是线性调节那么直觉
调Q和R时,我记录过几组参数的效果对比。同样是脉冲激励下自由端位移衰减到1%所需的时间,以及峰值控制力:
| Q位移权重 | R | 衰减时间(s) | 峰值控制力(N) |
|---|---|---|---|
| 10000 | 1e-4 | 1.85 | 8.2 |
| 5000 | 1e-4 | 2.41 | 6.1 |
| 10000 | 1e-3 | 3.92 | 2.8 |
| 5000 | 1e-3 | 5.36 | 2.1 |
可以看到,R增大的效果是控制力更温和,但代价是衰减时间变长。Q的影响类似但没那么陡。这个表的意义在于:调参时不要一次性大改,数量级层面微调。我习惯固定R,先扫一下Q的对数量级,找到衰减时间拐点,再微调R把峰值控制力压到作动器限幅之内。
5.3 模态截断的边界:保留多少阶模态才算够
这个问题取决于你关心的频带和控制带宽。具体操作上,先画出系统从控制输入到位移输出的频响函数(Bode图),看看哪些模态在输入-输出通道中是显著的。如果某个高阶模态在频响中几乎没有峰,那它对LQR设计的影响就可以忽略。
我的建议是至少保留到控制器带宽的1.5到2倍频率处。例如作动器的执行带宽是100Hz,那建模至少要覆盖到150~200Hz,对应到例子里就是前三到四阶模态。保留太多模态的问题在于:高频模态的建模误差大,控制器会把控制能量泄漏到这些不准确的模态上,实物上可能引起高频抖振。所以模态截断不是在"越多越好"和"越少越好"之间取中间值,而是根据控制带宽的物理约束来确定下限,根据建模精度上限来确定不超过多少。
5.4 阻尼比假设对控制器的重大影响
仿真里我用的模态阻尼比是zeta=0.01~0.015,这是铝结构在大气环境下的典型值。但这个值对LQR设计有直接影响:LQR算出的增益是在你给系统设定的阻尼比基础上叠加主动阻尼。如果实物梁的阻尼比和仿真假设差太远(比如装配了摩擦阻尼器,或环境湿度变化导致粘性增加),控制器的表现会明显偏离仿真。所以在做任何控制设计之前,通过实验模态分析(EMA)实测一下阻尼比很有必要。仿真里可以大胆假设,实物里就必须实测。
6. 从仿真到实物悬臂梁控制:模型里不会告诉你的差距
6.1 传感器与作动器的非共位问题
数学推导里,全状态反馈假设每个模态的状态都是已知且可控的。实物上,传感器(应变片/加速度计)和作动器(压电片/音圈电机)安装在特定物理位置,它们与模态坐标之间存在一个映射关系。如果传感器恰好位于某阶模态的节点附近,那么该阶模态在输出里几乎不可观测,控制器就"看不见"这阶模态的振动,更谈不上抑制。
更麻烦的是非共位控制(传感器和作动器不在同一位置)会引入额外相位滞后。频响上看,作动器到传感器的传递函数在某些频段可能呈现非最小相位特性,这时候LQR的全状态反馈框架需要额外小心——因为控制器增益是基于状态估计设计的,而估计器的收敛速度直接影响整个闭环的稳定性。
6.2 时滞与零阶保持器效应
数字控制器从采样到输出,必然存在时滞。这个时滞在连续系统设计中常常被忽略,但在实物上,它会把LQR设计的相位裕度吃掉一截。简单估算:如果控制周期是1ms,而系统第5阶模态频率是500Hz(周期2ms),一个控制周期的时滞在该模态频率下造成的相位滞后大约是180度——这足以让本来稳定的闭环变得不稳定。
工程上通常采取两个对策:一是降低控制带宽,让LQR增益不针对过高的模态做强化控制(这又回到了模态截断的讨论);二是用Smith预估器或状态观测器来补偿时滞。后者在实际嵌入式实现中更常见。
6.3 压电作动器的建模与限幅处理
如果采用压电片作动器,模型的输入通道不能简单理解成施加一个集中力。压电片通过粘结层将应变传递给梁体,等效于在梁上施加一个弯矩对,这个弯矩在有限元模型里需要被正确映射到节点力上。很多人在这一步出的问题最大——直接用点力模型替代压电片作用,得到的B矩阵和实际物理过程相差很大,LQR增益设计得再完美,实物上表现不出来。
此外,压电作动器有电压限制(一般不超过几百伏)和退极化风险,控制力输出必须做饱和限幅。LQR本身没有考虑输入饱和,如果仿真中控制力峰值经常达到限幅值,就需要在仿真里加入饱和环节重跑,或者改用带输入约束的最优控制方法。
6.4 扩展方向:LQG与H∞的取舍
LQR在仿真里效果很好,但实物中全状态测量做不到时,自然延伸是LQG:加Kalman滤波器做状态估计。需要注意的是,LQG的分离定理只有在系统线性、噪声高斯、代价函数二次型的条件下成立,而悬臂梁系统的建模误差、非线性摩擦等因素会破坏这个最优性。实践中,LQG的鲁棒性往往不如直接基于输出反馈的H∞控制。如果你发现实物实验里控制效果和仿真差距太大,先不要急着加复杂算法,先回头确认两点:有限元模型的频率误差是否控制在5%以内,作动器在不同频率下的实际输出力是否和建模时假设的一致。这两点确认好了,通常LQR的理论效果在实物上能复现七八成,剩下的两三成是传感器噪声、时滞和环境扰动带来的,再考虑进阶算法不迟。
7. 可以直接用的Matlab代码框架:核心流程整理
最后给出一段从有限元到LQR的完整流程代码,方便需要的人直接套用修改。代码里保留了必要的注释,其中参数部分需要根据你的梁的实际尺寸修改。
matlab复制% 悬臂梁有限元建模与LQR控制 - 主程序
clear; clc; close all;
% ---------- 1. 材料与几何参数 ----------
E = 70e9; % 弹性模量(Pa)
rho = 2700; % 密度(kg/m^3)
L_total = 0.8; % 梁总长度(m)
b = 0.04; % 截面宽度(m)
h = 0.005; % 截面高度(m)
I = b * h^3 / 12; % 截面惯性矩(m^4)
A = b * h; % 截面面积(m^2)
% ---------- 2. 网格划分 ----------
n_elem = 20; % 单元数
L_elem = L_total / n_elem;
n_nodes = n_elem + 1;
n_dof = 2 * n_nodes; % 每节点2个自由度: 位移+转角
% 节点坐标
node_coords = linspace(0, L_total, n_nodes);
% 单元连接: 每行存储该单元的两个节点编号
elem_nodes = [(1:n_elem)', (2:n_elem+1)'];
% ---------- 3. 全局矩阵初始化与装配 ----------
K_global = zeros(n_dof, n_dof);
M_global = zeros(n_dof, n_dof);
for e = 1:n_elem
[Ke, Me] = EulerBernoulliBeamElement(E, I, A, rho, L_elem);
n1 = elem_nodes(e, 1);
n2 = elem_nodes(e, 2);
% 自由度映射: 节点n1的位移/转角 = 2*n1-1, 2*n1
dof_map = [2*n1-1, 2*n1, 2*n2-1, 2*n2];
K_global(dof_map, dof_map) = K_global(dof_map, dof_map) + Ke;
M_global(dof_map, dof_map) = M_global(dof_map, dof_map) + Me;
end
% ---------- 4. 施加固定端边界条件 ----------
% 固定端为第1个节点,约束其位移和转角
fixed_dofs = [1, 2];
free_dofs = setdiff(1:n_dof, fixed_dofs);
K = K_global(free_dofs, free_dofs);
M = M_global(free_dofs, free_dofs);
% ---------- 5. 模态分析 ----------
[eigvec, eigval] = eig(K, M);
omega = sqrt(diag(eigval)); % rad/s
freq_Hz = omega / (2*pi);
% 排序
[freq_Hz, idx] = sort(freq_Hz);
eigvec = eigvec(:, idx);
disp('前5阶固有频率(Hz):');
disp(freq_Hz(1:5)');
% ---------- 6. 模态截断与状态空间构建 ----------
n_modes = 5;
Phi = eigvec(:, 1:n_modes); % 模态振型(自由度缩减后)
Mr = Phi' * M * Phi; % 模态质量矩阵
Kr = Phi' * K * Phi; % 模态刚度矩阵
omega_modes = sqrt(diag(Kr / Mr));
zeta = [0.01, 0.01, 0.012, 0.012, 0.015];
% 状态空间矩阵: 状态x = [q; dq],q为模态坐标
n_state = 2 * n_modes;
A = [zeros(n_modes), eye(n_modes);
-diag(omega_modes.^2), -diag(2*zeta.*omega_modes)];
% 作动器作用位置: 自由端节点(最后一个节点)施加横向力
force_node = n_nodes; % 自由端节点编号
force_dof_global = 2*force_node - 1; % 横向位移自由度(全局编号)
% 在缩减自由度空间中的位置
force_dof_free = find(free_dofs == force_dof_global);
B_phys = zeros(length(free_dofs), 1);
B_phys(force_dof_free) = 1; % 单位集中力
B = [zeros(n_modes, 1); Phi' * B_phys];
% 输出: 自由端位移 (传感器位置与作动器相同 = 共位)
C_phys = zeros(1, length(free_dofs));
C_phys(force_dof_free) = 1;
C = [C_phys * Phi, zeros(1, n_modes)];
D = 0;
% ---------- 7. LQR设计 ----------
Q = diag([10000, 10000, 5000, 3000, 1000, 100, 100, 50, 30, 10]);
R = 1e-4;
K_lqr = lqr(A, B, Q, R);
% ---------- 8. 闭环仿真 ----------
A_cl = A - B * K_lqr;
sys_open = ss(A, B, C, D);
sys_closed = ss(A_cl, B, C, D);
% 脉冲扰动: 初始状态在模态坐标中,自由端有初速度
v0 = 0.1; % m/s
x0_modes = Phi' * zeros(length(free_dofs), 1); % 初始位移=0
x0_vel = Phi' * (C_phys * Phi)'; % 近似:给自由端初速度
x0 = [x0_modes; Phi' * (zeros(length(free_dofs),1) + ...
(1:length(free_dofs) == force_dof_free)' * v0)];
dt = 1e-4;
t = 0:dt:5;
[y_open, t] = impulse(sys_open, t);
[y_close, t] = impulse(sys_closed, t);
% 这里演示用impulse即可,初值响应也可以用initial
figure;
subplot(2,1,1);
plot(t, y_open, 'b'); hold on;
plot(t, y_close, 'r'); grid on;
xlabel('时间(s)'); ylabel('自由端位移(m)');
legend('开环', 'LQR闭环'); title('自由端脉冲响应');
代码里我特意保留了自由端初速度激励和脉冲响应两种验证方式。初值响应用来自定义初始状态,更贴近"给梁敲了一下"的物理场景,和实验对照起来比较直观。
使用这段代码时,有几个改动点需要你注意:一是作动器和传感器的位置直接对应force_dof_global和C_phys的定义,改动位置时不要只改注释;二是Q矩阵的前5个对角元对应模态位移权重,后5个对应模态速度权重,如果n_modes改了,Q的维度要同步调整;三是模态阻尼比zeta,有实验数据就换实测值,没实验数据先用0.01量级。按这个框架,把参数替换成你自己的梁,应该半天内就能跑出一组能用的LQR控制器。
