现代控制理论课程实验三:一阶倒立摆的LQR控制器设计

在这里插入图片描述

一、实验目的

在这里插入图片描述

1、理解并掌握线性状态反馈控制的原理和方法;
2、理解并掌握LQR控制器设计方法;
3、练习控制性能比较与评估的方法。

二、实验设备与软件

实验设备

  • 倒立摆实验台

实验软件

  • MATLAB软件

三、实验原理

3.1、被控对象模型及其线性化

倒立摆系统的各量含义与关系如下表和下图。
根据牛顿定律建立系统垂直和水平方向的动力学方程,计及 u = F ,可得到

如下所示

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
该状态方程输入是加速度,输出是小车位置和摆杆角度。而小车的位置和摆杆角度以及它们的导数均可以通过传感器测量,所以在系统可控制的情况下,可以利用状态反馈综合控制器改善性能。

3.2、时不变线性连续系统的状态反馈控制与线性二次型最优控制LQR

  • 对时不变线性连续系统

在这里插入图片描述

3.3、实验平台的基本原理与使用指南

倒立摆系统的控制结构框图如下

在这里插入图片描述
“Pendulum”模块内部包含三种模块,每种模块的具体功能是通过S-Function实现的,这里不做介绍。其中“Set Car’s Vcc and Vel”模块的作用是设置小车运动的速度和加速度,“Get Car’s Position”模块的作用是读取小车当前的实际位置,“Get Pend’s Angle”的作用是角度编码器读取摆杆当前摆起的实际角度,该角度顺时针为“+”,逆时针为“-” (以竖直向下的状态为起始状态,见图1)。这里需要注意的是,由于编码器所读脉冲的正负号与实际需要的数符号相瓣,所以编码器输出经过一个负的比例增益后转化为输出角度
在这里插入图片描述

另外,在Simulink中搭建系统模型时,需要将Inverted_Pendulum_RealTime_lib中的GT400-SV Initialization模块放到编辑的模型中。

四、实验内容

动手实验与分析:

基于式(6)所示的倒立摆模型(控制摆角和位置),根据原系统的特点设计LQR最优控制器,并分析参数 和 阵的选取对系统的影响。实物实验前先进行理论分析计算(包括能控性分析和稳定性分析,指标转化计算,可以编制相应的程序计算,也可以手算),并在MATLAB/Simulink中进行离线数值计算分析,调整相关参数,合适后在倒立摆平台上做在线实验,比较仿真结果与实验结果。

4.1、MATLAB仿真结果

系统的MATLAB/Simulink仿真图如下

在这里插入图片描述

4.2、MATLAB程序如下

clear;

A = [ 0 1 0 
  • 70
    点赞
  • 151
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 79
    评论
好的,以下是一个简单的一阶倒立摆控制的 C 代码,使用了 LQR 控制: ```c #include <stdio.h> #include <math.h> #define pi 3.1415926 double m = 1.0; // 质量 double g = 9.8; // 重力 double l = 0.5; // 杆长 double A[2][2] = {{0,1},{g/l,0}}; // 系统矩阵 A double B[2] = {0,1/(m*l*l)}; // 输入矩阵 B double Q[2][2] = {{1,0},{0,1}}; // 状态权重矩阵 Q double R = 1; // 输入权重矩阵 R // 矩阵乘法 void matmul(double A[][2], double B[], double C[]) { int i, j; for (i = 0; i < 2; i++) { C[i] = 0; for (j = 0; j < 2; j++) { C[i] += A[i][j] * B[j]; } } } int main() { double x[2] = {pi/2, 0}; // 初始状态,杆子竖直向上 double u = 0; // 初始输入,不施加力 double K[2] = {0,0}; // LQR 控制器增益矩阵 K double P[2][2] = {{0,0},{0,0}}; // 代数 Riccati 方程的解 int i, j, k; int steps = 1000; // 模拟步数 double dt = 0.01; // 时间步长 // 计算代数 Riccati 方程的解 for (i = 0; i < 1000; i++) { double P_new[2][2] = {{0,0},{0,0}}; double AT[2][2], ATQ[2][2], KBRB[2][2], temp[2][2]; // 计算 AT, ATQ, KBRB for (j = 0; j < 2; j++) { for (k = 0; k < 2; k++) { AT[j][k] = A[k][j]; } } matmul(AT, Q[0], ATQ[0]); matmul(AT, Q[1], ATQ[1]); KBRB[0][0] = KBRB[1][1] = R + B[0] * K[0] + B[1] * K[1]; KBRB[0][1] = KBRB[1][0] = B[1] * K[0]; // 计算 P_new matmul(A, P[0], temp[0]); matmul(A, P[1], temp[1]); for (j = 0; j < 2; j++) { for (k = 0; k < 2; k++) { P_new[j][k] = ATQ[j][k] + P[j][0] * temp[0][k] + P[j][1] * temp[1][k] - P[j][k] * KBRB[k][k]; } } // 判断是否收敛 if (fabs(P_new[0][0] - P[0][0]) < 1e-6 && fabs(P_new[0][1] - P[0][1]) < 1e-6 && fabs(P_new[1][0] - P[1][0]) < 1e-6 && fabs(P_new[1][1] - P[1][1]) < 1e-6) { break; } // 更新 P P[0][0] = P_new[0][0]; P[0][1] = P_new[0][1]; P[1][0] = P_new[1][0]; P[1][1] = P_new[1][1]; // 计算新的 K K[0] = -1.0 / R * (B[0] * P[0][0] + B[1] * P[1][0]); K[1] = -1.0 / R * (B[0] * P[0][1] + B[1] * P[1][1]); } // 模拟控制过程 for (i = 0; i < steps; i++) { double x_new[2], u_new; double temp[2]; // 计算新的输入 matmul(K, x, &u_new); u_new = -u_new; // 更新状态 x_new[0] = x[0] + x[1] * dt; x_new[1] = x[1] + (g/l * sin(x[0]) + u) * dt; x[0] = x_new[0]; x[1] = x_new[1]; // 更新输入 u = u_new; // 输出状态 printf("%lf %lf\n", x[0], x[1]); } return 0; } ``` 代码中使用了一个简单的 LQR 控制器,通过 Riccati 方程求解控制器增益矩阵 K,然后根据当前状态计算新的输入。其中涉及到矩阵乘法和一些数学计算。
评论 79
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

编程爱好者-阿新

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值