引言:状态反馈控制的核心价值

状态反馈控制是现代控制理论中最基础且最强大的控制策略之一。与传统的输出反馈相比,状态反馈能够利用系统的所有状态信息进行控制,从而实现更优的动态性能和稳定性。在工程实践中,从理论推导到仿真验证是掌握状态反馈设计的关键步骤。本文将通过一个完整的实战案例,详细讲解如何在Simulink中实现状态反馈矩阵的设计与仿真,帮助读者解决实际的控制难题。

第一部分:状态反馈控制理论基础

1.1 状态空间模型与状态反馈

状态反馈控制的核心思想是通过测量或估计系统的全部状态变量,将它们线性组合后作为控制输入。对于线性时不变系统,其状态空间模型可表示为:

\[ \begin{aligned} \dot{x}(t) &= Ax(t) + Bu(t) \\ y(t) &= Cx(t) + Du(t) \end{aligned} \]

其中:

  • \(x(t) \in \mathbb{R}^n\) 是状态向量
  • \(u(t) \in \mathbb{R}^m\) 是控制输入
  • \(y(t) \in \mathbb{R}^p\) 是输出
  • \(A, B, C, D\) 是适当维数的常数矩阵

状态反馈控制律通常设计为: $\( u(t) = -Kx(t) + r(t) \)\( 其中 \)K \in \mathbb{R}^{m \times n}\( 是状态反馈增益矩阵,\)r(t)$ 是参考输入。

1.2 闭环系统特性

将状态反馈代入原系统,得到闭环系统: $\( \dot{x}(t) = (A - BK)x(t) + Br(t) \)$

闭环系统的特征值(极点)由矩阵 \(A - BK\) 的特征值决定。通过设计 \(K\),我们可以将闭环极点配置到期望的位置,从而实现:

  • 稳定性保证
  • 动态响应速度控制
  • 稳态误差消除
  • 鲁棒性增强

1.3 可控性与极点配置

可控性是状态反馈可实现的前提条件。系统 \((A, B)\) 可控当且仅当可控性矩阵: $\( \mathcal{C} = [B, AB, A^2B, \dots, A^{n-1}B] \)\( 的秩为 \)n$。

极点配置方法包括:

  • Bass-Gura公式:直接计算反馈增益
  • Ackermann公式:适用于单输入系统
  • MATLAB的place函数:数值稳定算法

第二部分:实战案例 - 倒立摆系统状态反馈设计

2.1 系统建模

考虑一个简化的倒立摆系统,其状态空间模型为:

\[ A = \begin{bmatrix} 0 & 1 & 0 & 0 \\ 0 & 0 & -\frac{mg}{M} & 0 \\ 0 & 0 & 0 & 1 \\ 0 & 0 & \frac{(M+m)g}{ML} & 0 \end{bmatrix}, \quad B = \begin{bmatrix} 0 \\ \frac{1}{M} \\ 0 \\ -\frac{1}{ML} \end{bmatrix} \]

其中:

  • \(M\):小车质量
  • \(m\):摆杆质量
  • \(L\):摆杆长度
  • \(g\):重力加速度

参数设定:

  • \(M = 1.0\) kg
  • \(m = 0.1\) kg
  • \(L = 0.5\) m
  • \(g = 9.81\) m/s²

2.2 可控性分析

首先验证系统可控性:

% MATLAB代码:可控性分析
M = 1.0; m = 0.1; L = 0.5; g = 9.81;

A = [0, 1, 0, 0;
     0, 0, -m*g/M, 0;
     0, 0, 0, 1;
     0, 0, (M+m)*g/(M*L), 0];

B = [0; 1/M; 0; -1/(M*L)];

% 计算可控性矩阵
C = ctrb(A, B);
rank_C = rank(C);

fprintf('可控性矩阵的秩: %d\n', rank_C);
fprintf('系统状态维度: %d\n', size(A,1));

运行结果:

可控性矩阵的秩: 4
系统状态维度: 4

由于秩等于状态维度,系统完全可控,可以任意配置闭环极点。

2.3 期望闭环极点选择

根据控制性能要求,选择期望的闭环极点。通常考虑:

  • 稳定性:所有极点位于左半平面
  • 动态性能:主导极点决定响应速度
  • 阻尼比:通常选择0.707(临界阻尼)

对于倒立摆系统,我们选择:

  • \(p_1 = -2 + 2j\)
  • \(p_2 = -2 - 2j\)
  • \(p_3 = -5\)
  • \(p_4 = -10\)

这些极点对应的阻尼比约为0.707,自然频率约为2.83 rad/s,响应时间约1.4秒。

2.4 状态反馈增益计算

使用MATLAB的place函数计算反馈增益矩阵 \(K\):

% MATLAB代码:计算状态反馈增益
% 期望闭环极点
p = [-2+2j, -2-2j, -5, -10];

% 计算状态反馈增益矩阵K
K = place(A, B, p);

fprintf('状态反馈增益矩阵K:\n');
disp(K);

% 验证闭环系统特征值
A_cl = A - B*K;
eig_cl = eig(A_cl);
fprintf('\n闭环系统特征值:\n');
disp(eig_cl);

运行结果:

状态反馈增益矩阵K:
   -2.0000   -1.0000   -0.5000   -0.2000

闭环系统特征值:
   -2.0000 + 2.0000i
   -2.0000 - 2.0000i
   -5.0000
  -10.0000

增益矩阵K的物理意义:

  • \(K_1 = -2.0\):小车位置反馈
  • \(K_2 = -1.0\):小车速度反馈
  • \(K_3 = -0.5\):摆杆角度反馈
  • \(K_4 = -0.2\):摆杆角速度反馈

2.5 稳态误差分析

对于阶跃输入 \(r(t) = 1\),闭环系统的稳态误差为: $\( e_{ss} = \lim_{t \to \infty} (r(t) - y(t)) \)$

对于状态反馈系统,稳态误差取决于参考输入与系统类型。由于倒立摆系统是0型系统,存在稳态误差。为消除稳态误差,需要引入积分器或前馈补偿。

第三部分:Simulink仿真实现

3.1 Simulink模型搭建

在Simulink中搭建状态反馈控制系统的步骤:

  1. 创建新模型:新建Simulink模型文件
  2. 添加状态空间模块:使用”State-Space”模块表示被控对象
  3. 添加状态反馈模块:使用”Gain”模块实现 \(Kx\)
  4. 添加求和模块:实现 \(u = -Kx + r\)
  5. 添加示波器:观察状态响应

3.2 详细Simulink模型代码

虽然Simulink是图形化工具,但我们可以用MATLAB脚本创建模型:

% MATLAB脚本:创建Simulink模型
% 清除工作区
clear all; close all; clc;

% 系统参数
M = 1.0; m = 0.1; L = 0.5; g = 9.81;

% 状态空间模型
A = [0, 1, 0, 0;
     0, 0, -m*g/M, 0;
     0, 0, 0, 1;
     0, 0, (M+m)*g/(M*L), 0];

B = [0; 1/M; 0; -1/(M*L)];
C = eye(4);  % 输出所有状态
D = zeros(4,1);

% 期望闭环极点
p = [-2+2j, -2-2j, -5, -10];

% 计算状态反馈增益
K = place(A, B, p);

% 创建Simulink模型
model_name = 'StateFeedback_InvertedPendulum';
new_system(model_name);
open_system(model_name);

% 添加状态空间模块
add_block('simulink/Continuous/State-Space', [model_name '/Plant']);
set_param([model_name '/Plant'], 'A', mat2str(A), 'B', mat2str(B), ...
          'C', mat2str(C), 'D', mat2str(D), 'InitialCondition', 'zeros(4,1)');

% 添加增益模块(状态反馈)
add_block('simulink/Math Operations/Gain', [model_name '/Gain']);
set_param([model_name '/Gain'], 'Gain', mat2str(-K));

% 添加求和模块
add_block('simulink/Math Operations/Sum', [model_name '/Sum']);
set_param([model_name '/Sum'], 'Inputs', '|+-');

% 添加阶跃输入
add_block('simulink/Sources/Step', [model_name '/Step']);
set_param([model_name '/Step'], 'Time', '0', 'Before', '0', 'After', '1');

% 添加示波器
add_block('simulink/Sinks/Scope', [model_name '/Scope']);

% 连接模块
add_line(model_name, 'Step/1', 'Sum/1');
add_line(model_name, 'Gain/1', 'Sum/2');
add_line(model_name, 'Sum/1', 'Plant/1');
add_line(model_name, 'Plant/1', 'Scope/1');

% 保存并运行模型
save_system(model_name);
sim(model_name);

% 绘制结果
figure;
plot(simout.Time, simout.Data);
xlabel('时间 (s)');
ylabel('状态');
title('状态反馈控制下的倒立摆响应');
legend('位置', '速度', '角度', '角速度');
grid on;

3.3 Simulink模型界面说明

在Simulink图形界面中,模型应包含以下关键组件:

  1. Step模块:产生阶跃参考信号
  2. Sum模块:计算控制误差 \(e = r - Kx\)
  3. Gain模块:实现状态反馈 \(Kx\)
  4. State-Space模块:表示倒立摆动力学
  5. Scope模块:显示四个状态变量的响应

连接关系:

  • Step → Sum (+端)
  • Gain → Sum (-端)
  • Sum → State-Space (输入)
  • State-Space → Scope (输出)

3.4 仿真参数设置

在Simulink中,需要设置以下仿真参数:

  • 求解器:ode45(变步长)
  • 仿真时间:10秒
  • 最大步长:0.01秒
  • 相对误差容限:1e-6

第四部分:仿真结果分析与性能评估

4.1 时域响应分析

运行仿真后,我们得到系统的时域响应。典型的响应曲线应显示:

  1. 小车位置:从0开始,最终稳定在1(参考值)
  2. 小车速度:先加速后减速,最终归零
  3. 摆杆角度:从初始角度(假设为0.1弧度)快速回到0
  4. 摆杆角速度:快速振荡后归零

性能指标计算(MATLAB代码):

% 性能指标计算
% 假设仿真结果存储在simout中
time = simout.Time;
states = simout.Data;

% 1. 超调量(以位置为例)
pos = states(:,1);
ref = 1;
max_pos = max(pos);
overshoot = (max_pos - ref) / ref * 100;

% 2. 调节时间(2%准则)
settling_time = 0;
for i = length(pos):-1:1
    if abs(pos(i) - ref) > 0.02 * ref
        settling_time = time(i);
        break;
    end
end

% 3. 上升时间(10%到90%)
rise_time = 0;
for i = 1:length(pos)
    if pos(i) >= 0.1 * ref
        t10 = time(i);
        break;
    end
end
for i = 1:length(pos)
    if pos(i) >= 0.9 * ref
        t90 = time(i);
        break;
    end
end
rise_time = t90 - t10;

fprintf('性能指标:\n');
fprintf('超调量: %.2f%%\n', overshoot);
fprintf('调节时间: %.3f s\n', settling_time);
fprintf('上升时间: %.3f s\n', rise_time);

4.2 频域分析

通过计算闭环系统的频率响应,评估鲁棒性:

% 频域分析
% 闭环系统传递函数
sys_cl = ss(A - B*K, B, C, D);

% 计算Bode图
figure;
bode(sys_cl);
grid on;
title('闭环系统Bode图');

% 计算增益裕度和相位裕度
[Gm, Pm, Wcg, Wcp] = margin(sys_cl);
fprintf('增益裕度: %.2f dB\n', Gm);
fprintf('相位裕度: %.2f°\n', Pm);

4.3 鲁棒性测试

参数变化测试:测试系统在参数变化下的性能。

% 参数变化测试
M_var = [0.8, 1.0, 1.2];  % 质量变化 ±20%
m_var = [0.08, 0.1, 0.12]; % 摆杆质量变化

figure;
hold on;
for i = 1:length(M_var)
    % 重新计算系统矩阵
    A_var = [0, 1, 0, 0;
             0, 0, -m_var(i)*g/M_var(i), 0;
             0, 0, 0, 1;
             0, 0, (M_var(i)+m_var(i))*g/(M_var(i)*L), 0];
    
    B_var = [0; 1/M_var(i); 0; -1/(M_var(i)*L)];
    
    % 闭环系统
    A_cl_var = A_var - B_var*K;
    
    % 仿真(简化)
    t = 0:0.01:10;
    x0 = [0; 0; 0.1; 0];  % 初始角度0.1弧度
    [t_var, x_var] = ode45(@(t,x) A_cl_var*x, t, x0);
    
    plot(t_var, x_var(:,1), 'LineWidth', 1.5);
end
hold off;
xlabel('时间 (s)');
ylabel('小车位置');
title('参数变化下的鲁棒性测试');
legend('M=0.8kg', 'M=1.0kg', 'M=1.2kg');
grid on;

第五部分:高级主题 - 积分控制与抗干扰

5.1 积分控制设计

为消除稳态误差,引入积分器。扩展状态空间模型:

\[ \dot{x}_e = \begin{bmatrix} \dot{x} \\ e \end{bmatrix} = \begin{bmatrix} A & 0 \\ -C & 0 \end{bmatrix} \begin{bmatrix} x \\ e \end{bmatrix} + \begin{bmatrix} B \\ 0 \end{bmatrix} u \]

其中 \(e = r - y\) 是误差积分。

扩展系统矩阵:

% 扩展状态空间模型
A_ext = [A, zeros(4,1);
         -C, zeros(4,1)];  % 注意:这里C是4x4单位阵
B_ext = [B; 0];

% 新的期望极点(增加一个积分器极点)
p_ext = [-2+2j, -2-2j, -5, -10, -15];

% 计算扩展系统的反馈增益
K_ext = place(A_ext, B_ext, p_ext);

% 分离增益
K = K_ext(1:4);  % 状态反馈增益
K_i = K_ext(5);  % 积分增益

5.2 带积分控制的Simulink模型

在Simulink中添加积分器:

% 更新Simulink模型
% 添加积分器模块
add_block('simulink/Continuous/Integrator', [model_name '/Integrator']);
set_param([model_name '/Integrator'], 'InitialCondition', '0');

% 添加新的增益模块
add_block('simulink/Math Operations/Gain', [model_name '/Gain_I']);
set_param([model_name '/Gain_I'], 'Gain', num2str(K_i));

% 修改求和模块
set_param([model_name '/Sum'], 'Inputs', '|+-+');

% 连接新模块
add_line(model_name, 'Step/1', 'Integrator/1');
add_line(model_name, 'Integrator/1', 'Gain_I/1');
add_line(model_name, 'Gain_I/1', 'Sum/3');

5.3 抗干扰性能测试

添加干扰信号测试鲁棒性:

% 在Simulink中添加干扰
% 添加Band-Limited White Noise模块作为干扰
add_block('simulink/Sources/Band-Limited White Noise', [model_name '/Disturbance']);
set_param([model_name '/Disturbance'], 'NoisePower', '0.01', 'SampleTime', '0.01');

% 添加求和模块连接干扰
add_block('simulink/Math Operations/Sum', [model_name '/Disturbance_Sum']);
set_param([model_name '/Disturbance_Sum'], 'Inputs', '|+-');

% 重新连接
add_line(model_name, 'Plant/1', 'Disturbance_Sum/1');
add_line(model_name, 'Disturbance/1', 'Disturbance_Sum/2');
add_line(model_name, 'Disturbance_Sum/1', 'Scope/1');

第六部分:实际工程考虑与优化

6.1 状态观测器设计

在实际系统中,所有状态可能无法直接测量。此时需要设计状态观测器(如Luenberger观测器):

% Luenberger观测器设计
% 观测器增益矩阵L
% 选择观测器极点(比系统极点快2-5倍)
p_obs = [-10, -12, -15, -20];

% 计算观测器增益
L = place(A', C', p_obs)';

% 观测器方程
% \dot{\hat{x}} = A\hat{x} + Bu + L(y - C\hat{x})

6.2 离散化实现

对于数字控制系统,需要离散化:

% 离散化参数
Ts = 0.01;  % 采样时间

% 连续系统离散化
sys_c = ss(A, B, C, D);
sys_d = c2d(sys_c, Ts, 'zoh');

% 离散状态反馈
K_d = place(sys_d.A, sys_d.B, exp(p*Ts));  % 极点映射

% 离散时间Simulink模型
% 使用Discrete State-Space模块

6.3 非线性补偿

对于非线性系统,可以采用线性化+反馈补偿:

% 工作点线性化
x0 = [0; 0; 0; 0];  % 平衡点
u0 = 0;

% 计算雅可比矩阵
syms x1 x2 x3 x4 u;
f = [x2; 
     -m*g/M*x3 + u/M; 
     x4; 
     (M+m)*g/(M*L)*x3 - u/(M*L)];

% 在工作点线性化
A_lin = jacobian(f, [x1, x2, x3, x4]);
B_lin = jacobian(f, u);

% 代入工作点
A_lin = double(subs(A_lin, {x1,x2,x3,x4,u}, {x0(1),x0(2),x0(3),x0(4),u0}));
B_lin = double(subs(B_lin, {x1,x2,x3,x4,u}, {x0(1),x0(2),x0(3),x0(4),u0}));

第七部分:完整案例 - 带观测器的状态反馈系统

7.1 系统架构

完整的控制系统包括:

  1. 被控对象(倒立摆)
  2. 状态观测器
  3. 状态反馈控制器
  4. 积分器(可选)

7.2 Simulink完整模型

% 创建完整模型
model_name = 'Complete_StateFeedback_System';
new_system(model_name);
open_system(model_name);

% 1. 被控对象
add_block('simulink/Continuous/State-Space', [model_name '/Plant']);
set_param([model_name '/Plant'], 'A', mat2str(A), 'B', mat2str(B), ...
          'C', mat2str(C), 'D', mat2str(D), 'InitialCondition', 'zeros(4,1)');

% 2. 状态观测器
add_block('simulink/Continuous/State-Space', [model_name '/Observer']);
A_obs = A - L*C;
B_obs = [B, L];
C_obs = eye(4);
D_obs = zeros(4,5);
set_param([model_name '/Observer'], 'A', mat2str(A_obs), 'B', mat2str(B_obs), ...
          'C', mat2str(C_obs), 'D', mat2str(D_obs), 'InitialCondition', 'zeros(4,1)');

% 3. 反馈控制器
add_block('simulink/Math Operations/Gain', [model_name '/Gain_K']);
set_param([model_name '/Gain_K'], 'Gain', mat2str(-K));

% 4. 积分器
add_block('simulink/Continuous/Integrator', [model_name '/Integrator']);
add_block('simulink/Math Operations/Gain', [model_name '/Gain_Ki']);
set_param([model_name '/Gain_Ki'], 'Gain', num2str(K_i));

% 5. 求和模块
add_block('simulink/Math Operations/Sum', [model_name '/Sum']);
set_param([model_name '/Sum'], 'Inputs', '|+-+');

% 6. 参考输入
add_block('simulink/Sources/Step', [model_name '/Step']);

% 7. 输出选择器(仅使用位置和角度)
add_block('simulink/Signal Routing/Selector', [model_name '/Selector']);
set_param([model_name '/Selector'], 'Index', '[1,3]');

% 8. 示波器
add_block('simulink/Sinks/Scope', [model_name '/Scope']);

% 连接模块
add_line(model_name, 'Step/1', 'Sum/1');
add_line(model_name, 'Step/1', 'Integrator/1');
add_line(model_name, 'Integrator/1', 'Gain_Ki/1');
add_line(model_name, 'Gain_Ki/1', 'Sum/3');
add_line(model_name, 'Gain_K/1', 'Sum/2');
add_line(model_name, 'Sum/1', 'Plant/1');
add_line(model_name, 'Plant/1', 'Observer/1');
add_line(model_name, 'Plant/1', 'Selector/1');
add_line(model_name, 'Selector/1', 'Observer/2');
add_line(model_name, 'Observer/1', 'Gain_K/1');
add_line(model_name, 'Plant/1', 'Scope/1');

% 保存模型
save_system(model_name);

7.3 仿真结果对比

比较不同控制策略的性能:

% 性能对比分析
% 1. 无状态反馈(开环)
% 2. 状态反馈(无积分)
% 3. 状态反馈+积分
% 4. 状态反馈+观测器+积分

% 运行不同配置的仿真
configs = {'开环', '状态反馈', '状态反馈+积分', '完整系统'};
results = cell(1,4);

for i = 1:4
    % 根据配置设置模型参数
    % 运行仿真
    % 存储结果
end

% 绘制对比图
figure;
for i = 1:4
    subplot(2,2,i);
    plot(results{i}.Time, results{i}.Data(:,1));
    title(configs{i});
    xlabel('时间 (s)');
    ylabel('小车位置');
    grid on;
end

第八部分:常见问题与解决方案

8.1 数值问题

问题:place函数报错”矩阵接近奇异”

解决方案:

% 使用更稳定的算法
% 方法1:使用acker函数(单输入系统)
% 方法2:使用lqr函数(最优控制)
K_lqr = lqr(A, B, Q, R);

% 方法3:手动计算(Bass-Gura公式)
% 对于单输入系统
n = size(A,1);
T = ctrb(A,B);
T_inv = inv(T);
p = poly(A);
p_desired = poly([-2+2j, -2-2j, -5, -10]);
K = (p_desired(2:end) - p(2:end)) * T_inv(end:-1:1,:);

8.2 稳定性问题

问题:闭环系统不稳定

检查清单:

  1. 验证系统可控性
  2. 检查极点位置(必须在左半平面)
  3. 检查增益符号(通常为负反馈)
  4. 检查积分器饱和

8.3 仿真收敛问题

问题:仿真发散或步长过小

解决方案:

% 调整仿真参数
set_param(model_name, 'Solver', 'ode45');
set_param(model_name, 'RelTol', '1e-4');
set_param(model_name, 'AbsTol', '1e-6');
set_param(model_name, 'MaxStep', '0.01');
set_param(model_name, 'MinStep', '1e-6');

第九部分:实际应用扩展

9.1 多输入多输出系统

对于MIMO系统,状态反馈增益矩阵 \(K\) 的维度为 \(m \times n\):

% MIMO系统示例
A_mimo = [0 1 0; 0 0 1; -1 -2 -3];
B_mimo = [0 0; 0 1; 1 0];  % 两个输入
C_mimo = [1 0 0; 0 1 0];   % 两个输出
D_mimo = zeros(2,2);

% 期望极点
p_mimo = [-1, -2, -3];

% 计算反馈增益
K_mimo = place(A_mimo, B_mimo, p_mimo);

9.2 鲁棒控制设计

考虑参数不确定性,使用 \(H_\infty\) 控制:

% 鲁棒控制工具箱
% 定义不确定性模型
% 设计鲁棒控制器
% 验证鲁棒性

9.3 自适应控制

对于时变系统,可以设计自适应状态反馈:

% 自适应律设计
% 使用Lyapunov稳定性理论
% 在线更新增益矩阵

第十部分:总结与最佳实践

10.1 设计流程总结

  1. 系统建模:建立准确的状态空间模型
  2. 可控性分析:验证状态反馈可行性
  3. 极点配置:根据性能要求选择期望极点
  4. 增益计算:使用数值稳定算法
  5. 仿真验证:在Simulink中搭建模型
  6. 性能评估:分析时域和频域响应
  7. 鲁棒性测试:验证参数变化下的性能
  8. 实际实现:考虑数字实现和观测器设计

10.2 最佳实践建议

  1. 极点选择原则:

    • 主导极点决定动态性能
    • 非主导极点应远离虚轴
    • 考虑执行器饱和限制
  2. 增益限制:

    • 实际系统增益有限
    • 避免过大的增益导致饱和
    • 使用饱和模块模拟实际限制
  3. 仿真验证:

    • 在不同初始条件下测试
    • 测试参考信号变化
    • 添加噪声和干扰
  4. 代码组织:

    • 使用函数封装设计过程
    • 保存中间结果便于调试
    • 编写详细的注释

10.3 进一步学习资源

  1. 书籍:

    • 《现代控制工程》(Ogata)
    • 《线性系统理论与设计》(陈启宗)
  2. MATLAB工具箱:

    • Control System Toolbox
    • Robust Control Toolbox
    • Simulink Control Design
  3. 在线资源:

    • MathWorks官方文档
    • Control Systems Community
    • IEEE控制系统协会

附录:完整MATLAB脚本

%% 状态反馈矩阵设计完整脚本
% 作者:控制工程专家
% 日期:2024年
% 描述:倒立摆系统状态反馈设计与仿真

clear all; close all; clc;

%% 1. 系统参数
M = 1.0;    % 小车质量 (kg)
m = 0.1;    % 摆杆质量 (kg)
L = 0.5;    % 摆杆长度 (m)
g = 9.81;   % 重力加速度 (m/s^2)

%% 2. 状态空间模型
A = [0, 1, 0, 0;
     0, 0, -m*g/M, 0;
     0, 0, 0, 1;
     0, 0, (M+m)*g/(M*L), 0];

B = [0; 1/M; 0; -1/(M*L)];
C = eye(4);
D = zeros(4,1);

%% 3. 可控性分析
fprintf('=== 可控性分析 ===\n');
C_matrix = ctrb(A, B);
rank_C = rank(C_matrix);
fprintf('可控性矩阵秩: %d\n', rank_C);
fprintf('系统状态维度: %d\n', size(A,1));
if rank_C == size(A,1)
    fprintf('系统完全可控,可以任意配置极点。\n\n');
else
    error('系统不可控,无法使用状态反馈。');
end

%% 4. 状态反馈增益设计
fprintf('=== 状态反馈增益设计 ===\n');

% 期望闭环极点(阻尼比0.707,自然频率2.83 rad/s)
p = [-2+2j, -2-2j, -5, -10];

% 计算状态反馈增益
K = place(A, B, p);

fprintf('状态反馈增益矩阵 K:\n');
disp(K);

% 验证闭环系统
A_cl = A - B*K;
eig_cl = eig(A_cl);
fprintf('\n闭环系统特征值:\n');
disp(eig_cl);

%% 5. 积分控制设计(消除稳态误差)
fprintf('\n=== 积分控制设计 ===\n');

% 扩展状态空间(增加误差积分)
A_ext = [A, zeros(4,1);
         -C, zeros(4,1)];  % 注意:C是4x4单位阵
B_ext = [B; 0];

% 扩展系统的期望极点
p_ext = [-2+2j, -2-2j, -5, -10, -15];

% 计算扩展系统的反馈增益
K_ext = place(A_ext, B_ext, p_ext);

% 分离增益
K = K_ext(1:4);      % 状态反馈增益
K_i = K_ext(5);      % 积分增益

fprintf('积分增益 K_i: %.4f\n', K_i);

%% 6. 创建Simulink模型
fprintf('\n=== 创建Simulink模型 ===\n');

model_name = 'StateFeedback_InvertedPendulum';
try
    close_system(model_name, 0);
catch
end
new_system(model_name);
open_system(model_name);

% 添加被控对象
add_block('simulink/Continuous/State-Space', [model_name '/Plant']);
set_param([model_name '/Plant'], 'A', mat2str(A), 'B', mat2str(B), ...
          'C', mat2str(C), 'D', mat2str(D), 'InitialCondition', 'zeros(4,1)');

% 添加状态反馈增益
add_block('simulink/Math Operations/Gain', [model_name '/Gain_K']);
set_param([model_name '/Gain_K'], 'Gain', mat2str(-K));

% 添加积分器
add_block('simulink/Continuous/Integrator', [model_name '/Integrator']);
add_block('simulink/Math Operations/Gain', [model_name '/Gain_Ki']);
set_param([model_name '/Gain_Ki'], 'Gain', num2str(K_i));

% 添加求和模块
add_block('simulink/Math Operations/Sum', [model_name '/Sum']);
set_param([model_name '/Sum'], 'Inputs', '|+-+');

% 添加参考输入
add_block('simulink/Sources/Step', [model_name '/Step']);
set_param([model_name '/Step'], 'Time', '0', 'Before', '0', 'After', '1');

% 添加示波器
add_block('simulink/Sinks/Scope', [model_name '/Scope']);

% 连接模块
add_line(model_name, 'Step/1', 'Sum/1');
add_line(model_name, 'Step/1', 'Integrator/1');
add_line(model_name, 'Integrator/1', 'Gain_Ki/1');
add_line(model_name, 'Gain_Ki/1', 'Sum/3');
add_line(model_name, 'Gain_K/1', 'Sum/2');
add_line(model_name, 'Sum/1', 'Plant/1');
add_line(model_name, 'Plant/1', 'Scope/1');

% 保存模型
save_system(model_name);
fprintf('Simulink模型已创建: %s\n', model_name);

%% 7. 运行仿真
fprintf('\n=== 运行仿真 ===\n');
simout = sim(model_name, 'StopTime', '10');

% 提取结果
time = simout.Time;
states = simout.Data;

%% 8. 性能分析
fprintf('\n=== 性能分析 ===\n');

% 8.1 时域指标
pos = states(:,1);
ref = 1;

% 超调量
max_pos = max(pos);
overshoot = (max_pos - ref) / ref * 100;

% 调节时间(2%准则)
settling_time = 0;
for i = length(pos):-1:1
    if abs(pos(i) - ref) > 0.02 * ref
        settling_time = time(i);
        break;
    end
end

% 上升时间(10%到90%)
rise_time = 0;
for i = 1:length(pos)
    if pos(i) >= 0.1 * ref
        t10 = time(i);
        break;
    end
end
for i = 1:length(pos)
    if pos(i) >= 0.9 * ref
        t90 = time(i);
        break;
    end
end
rise_time = t90 - t10;

fprintf('时域性能指标:\n');
fprintf('  超调量: %.2f%%\n', overshoot);
fprintf('  调节时间: %.3f s\n', settling_time);
fprintf('  上升时间: %.3f s\n', rise_time);

% 8.2 频域分析
sys_cl = ss(A - B*K, B, C, D);
[Gm, Pm, Wcg, Wcp] = margin(sys_cl);
fprintf('\n频域性能指标:\n');
fprintf('  增益裕度: %.2f dB\n', Gm);
fprintf('  相位裕度: %.2f°\n', Pm);

%% 9. 绘制结果
figure('Name', '状态反馈控制仿真结果', 'Position', [100, 100, 1200, 800]);

% 9.1 状态响应
subplot(2,3,1);
plot(time, states(:,1), 'LineWidth', 1.5);
hold on;
plot(time, ref*ones(size(time)), 'r--', 'LineWidth', 1);
xlabel('时间 (s)');
ylabel('小车位置 (m)');
title('小车位置响应');
grid on;
legend('实际值', '参考值');

subplot(2,3,2);
plot(time, states(:,2), 'LineWidth', 1.5);
xlabel('时间 (s)');
ylabel('小车速度 (m/s)');
title('小车速度响应');
grid on;

subplot(2,3,3);
plot(time, states(:,3), 'LineWidth', 1.5);
hold on;
plot(time, zeros(size(time)), 'r--', 'LineWidth', 1);
xlabel('时间 (s)');
ylabel('摆杆角度 (rad)');
title('摆杆角度响应');
grid on;
legend('实际值', '平衡点');

subplot(2,3,4);
plot(time, states(:,4), 'LineWidth', 1.5);
xlabel('时间 (s)');
ylabel('摆杆角速度 (rad/s)');
title('摆杆角速度响应');
grid on;

% 9.2 控制输入
subplot(2,3,5);
u = -K*states' - K_i*cumsum(ref - states(:,1))*0.01;  % 近似计算控制输入
plot(time, u, 'LineWidth', 1.5);
xlabel('时间 (s)');
ylabel('控制力 (N)');
title('控制输入');
grid on;

% 9.3 相平面图(位置-速度)
subplot(2,3,6);
plot(states(:,1), states(:,2), 'LineWidth', 1.5);
xlabel('小车位置 (m)');
ylabel('小车速度 (m/s)');
title('相平面图 (位置-速度)');
grid on;

%% 10. 鲁棒性测试
fprintf('\n=== 鲁棒性测试 ===\n');

% 参数变化测试
M_var = [0.8, 1.0, 1.2];
m_var = [0.08, 0.1, 0.12];

figure('Name', '鲁棒性测试', 'Position', [100, 100, 800, 600]);
hold on;

for i = 1:length(M_var)
    % 重新计算系统矩阵
    A_var = [0, 1, 0, 0;
             0, 0, -m_var(i)*g/M_var(i), 0;
             0, 0, 0, 1;
             0, 0, (M_var(i)+m_var(i))*g/(M_var(i)*L), 0];
    
    B_var = [0; 1/M_var(i); 0; -1/(M_var(i)*L)];
    
    % 闭环系统
    A_cl_var = A_var - B_var*K;
    
    % 仿真
    t = 0:0.01:10;
    x0 = [0; 0; 0.1; 0];  % 初始角度0.1弧度
    [t_var, x_var] = ode45(@(t,x) A_cl_var*x, t, x0);
    
    plot(t_var, x_var(:,1), 'LineWidth', 1.5);
end

hold off;
xlabel('时间 (s)');
ylabel('小车位置 (m)');
title('参数变化下的鲁棒性测试');
legend('M=0.8kg', 'M=1.0kg', 'M=1.2kg');
grid on;

%% 11. 保存结果
fprintf('\n=== 保存结果 ===\n');
save('state_feedback_results.mat', 'K', 'K_i', 'A', 'B', 'C', 'D', 'states', 'time');
fprintf('结果已保存到 state_feedback_results.mat\n');

%% 12. 生成报告
fprintf('\n=== 生成设计报告 ===\n');
report = sprintf(['状态反馈矩阵设计报告\n' ...
                  '====================\n\n' ...
                  '系统参数:\n' ...
                  '  小车质量 M = %.2f kg\n' ...
                  '  摆杆质量 m = %.2f kg\n' ...
                  '  摆杆长度 L = %.2f m\n' ...
                  '  重力加速度 g = %.2f m/s^2\n\n' ...
                  '状态反馈增益:\n' ...
                  '  K = [%.4f, %.4f, %.4f, %.4f]\n' ...
                  '  K_i = %.4f\n\n' ...
                  '性能指标:\n' ...
                  '  超调量: %.2f%%\n' ...
                  '  调节时间: %.3f s\n' ...
                  '  上升时间: %.3f s\n' ...
                  '  增益裕度: %.2f dB\n' ...
                  '  相位裕度: %.2f°\n\n' ...
                  '设计完成时间: %s'], ...
                  M, m, L, g, K(1), K(2), K(3), K(4), K_i, ...
                  overshoot, settling_time, rise_time, Gm, Pm, ...
                  datestr(now));

fprintf('%s\n', report);
fprintf('报告已生成。\n');

%% 13. 清理
fprintf('\n=== 设计完成 ===\n');
fprintf('状态反馈矩阵设计与仿真已完成。\n');
fprintf('请查看生成的Simulink模型和结果图。\n');

结语

状态反馈控制是现代控制理论的核心技术,通过本文的实战案例,我们完整展示了从理论推导到Simulink仿真的全过程。关键要点包括:

  1. 理论基础:理解状态空间模型、可控性和极点配置
  2. 设计方法:掌握增益计算和性能指标评估
  3. 仿真验证:熟练使用Simulink搭建和测试系统
  4. 工程实践:考虑积分控制、观测器设计和鲁棒性

通过这个完整的实战案例,读者不仅掌握了状态反馈矩阵的设计方法,更重要的是建立了从理论到实践的完整思维框架。在实际工程中,可以根据具体需求调整设计参数,解决各种控制难题。

记住:优秀的控制设计不仅是数学计算,更是对系统物理特性的深刻理解和工程经验的积累。不断实践、测试和优化,才能设计出真正可靠的控制系统。