基于hal库写一段lqr控制代码
时间: 2023-12-10 08:40:42 浏览: 66
好的,下面是一段使用HAL库实现LQR控制的代码:
```c
#include "main.h"
#include "stm32f4xx_hal.h"
#include <math.h>
/* 定义LQR控制器参数 */
#define Q1 1.0f
#define Q2 1.0f
#define R1 0.1f
#define R2 0.1f
/* 定义系统模型参数 */
#define M1 1.0f
#define M2 2.0f
#define L1 1.0f
#define L2 2.0f
#define g 9.81f
/* 定义控制输入变量 */
volatile float u1 = 0.0f;
volatile float u2 = 0.0f;
/* 定义状态变量 */
volatile float theta1 = 0.0f;
volatile float theta2 = 0.0f;
volatile float dtheta1 = 0.0f;
volatile float dtheta2 = 0.0f;
/* 定义状态反馈控制器参数 */
volatile float K1[2] = {0.0f, 0.0f};
volatile float K2[2] = {0.0f, 0.0f};
/* 定义状态反馈控制器计算函数 */
void LQRController(volatile float *state, volatile float *control) {
/* 计算状态反馈增益矩阵 */
float A[4][4] = {{0, 0, 1, 0}, {0, 0, 0, 1}, {-(M1+M2)*g/M1/L1, -M2*L2/L1*g*cos(state[0]-state[1])/M1/L1, 0, 0}, {M2*L1/L2*g*cos(state[0]-state[1])/M1/L2, M2*g/M1/L2, 0, 0}};
float B[4][2] = {{0, 0}, {0, 0}, {1/M1, 0}, {0, 1/M2}};
float Q[4][4] = {{Q1, 0, 0, 0}, {0, Q2, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}};
float R[2][2] = {{R1, 0}, {0, R2}};
float P[4][4] = {{0}};
float K[2][4] = {{0}};
/* 使用LQR控制器计算控制输入 */
for (int i = 0; i < 100; i++) {
/* 计算P矩阵 */
for (int j = 0; j < 10; j++) {
float tmp[4][4];
float tmp2[4][4];
float tmp3[4][4];
float tmp4[4][4];
float tmp5[4][4];
memcpy(tmp, A, sizeof(A));
memcpy(tmp2, B, sizeof(B));
memcpy(tmp3, K, sizeof(K));
memcpy(tmp4, Q, sizeof(Q));
matrix_transpose(tmp2, 2, 4);
matrix_transpose(tmp3, 4, 2);
matrix_multiply(tmp, P, tmp5, 4, 4, 4, 4);
matrix_multiply(tmp3, tmp2, tmp4, 4, 2, 2, 4);
matrix_multiply(tmp4, tmp5, P, 2, 4, 4, 4);
matrix_add(P, Q, P, 4, 4);
}
/* 计算K矩阵 */
matrix_inverse(R, 2);
matrix_multiply(B, P, K, 4, 2, 2, 4);
matrix_multiply(K, R, K, 2, 4, 4, 2);
/* 更新控制输入 */
matrix_multiply(K, state, control, 2, 4, 4, 1);
}
}
/* 主函数 */
int main(void) {
/* 初始化HAL库 */
HAL_Init();
/* 初始化系统时钟 */
SystemClock_Config();
/* 初始化GPIO */
MX_GPIO_Init();
/* 初始化定时器 */
MX_TIM2_Init();
MX_TIM3_Init();
/* 启动定时器 */
HAL_TIM_Base_Start_IT(&htim2);
HAL_TIM_Base_Start_IT(&htim3);
/* 进入主循环 */
while (1) {
/* 计算状态反馈控制器 */
float state[4] = {theta1, theta2, dtheta1, dtheta2};
float control[2] = {0.0f, 0.0f};
LQRController(state, control);
u1 = control[0];
u2 = control[1];
/* 更新系统状态 */
float ddtheta1 = (u1 - M2*L1*dtheta1*dtheta1*sin(theta1-theta2) - (M1+M2)*g*sin(theta1))/((M1+M2)*L1 - M2*L1*cos(theta1-theta2)*cos(theta1-theta2));
float ddtheta2 = (u2 - M2*L2*dtheta2*dtheta2*sin(theta1-theta2) - M2*g*sin(theta2)*cos(theta1-theta2))/((M1+M2)*L2 - M2*L2*cos(theta1-theta2)*cos(theta1-theta2));
dtheta1 += ddtheta1 * 0.001f;
dtheta2 += ddtheta2 * 0.001f;
theta1 += dtheta1 * 0.001f;
theta2 += dtheta2 * 0.001f;
/* 延时一段时间 */
HAL_Delay(1);
}
}
/* 定义GPIO初始化函数 */
void MX_GPIO_Init(void) {
/* GPIO 初始化结构体 */
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* 开启GPIOA时钟 */
__HAL_RCC_GPIOA_CLK_ENABLE();
/* 配置PA0和PA1为模拟输入 */
GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
/* 定义定时器2初始化函数 */
void MX_TIM2_Init(void) {
/* 定时器初始化结构体 */
TIM_HandleTypeDef htim2 = {0};
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
/* 开启时钟 */
__HAL_RCC_TIM2_CLK_ENABLE();
/* 配置定时器参数 */
htim2.Instance = TIM2;
htim2.Init.Prescaler = 83;
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = 999;
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
HAL_TIM_Base_Init(&htim2);
/* 配置时钟源 */
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig);
/* 配置定时器主从模式 */
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig);
/* 配置中断 */
HAL_NVIC_SetPriority(TIM2_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(TIM2_IRQn);
}
/* 定义定时器3初始化函数 */
void MX_TIM3_Init(void) {
/* 定时器初始化结构体 */
TIM_HandleTypeDef htim3 = {0};
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
/* 开启时钟 */
__HAL_RCC_TIM3_CLK_ENABLE();
/* 配置定时器参数 */
htim3.Instance = TIM3;
htim3.Init.Prescaler = 83;
htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
htim3.Init.Period = 999;
htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
HAL_TIM_Base_Init(&htim3);
/* 配置时钟源 */
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
HAL_TIM_ConfigClockSource(&htim3, &sClockSourceConfig);
/* 配置定时器主从模式 */
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig);
/* 配置中断 */
HAL_NVIC_SetPriority(TIM3_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(TIM3_IRQn);
}
/* 中断处理函数:定时器2 */
void TIM2_IRQHandler(void) {
/* 清除中断标志 */
__HAL_TIM_CLEAR_FLAG(&htim2, TIM_FLAG_UPDATE);
/* 读取模拟输入值 */
float adc1 = HAL_ADC_GetValue(&hadc1);
float adc2 = HAL_ADC_GetValue(&hadc2);
/* 将模拟输入值转换为状态变量 */
theta1 = adc1 / 4095.0f * 3.1416f;
theta2 = adc2 / 4095.0f * 3.1416f;
}
/* 中断处理函数:定时器3 */
void TIM3_IRQHandler(void) {
/* 清除中断标志 */
__HAL_TIM_CLEAR_FLAG(&htim3, TIM_FLAG_UPDATE);
/* 计算状态变量 */
float ddtheta1 = (u1 - M2*L1*dtheta1*dtheta1*sin(theta1-theta2) - (M1+M2)*g*sin(theta1))/((M1+M2)*L1 - M2*L1*cos(theta1-theta2)*cos(theta1-theta2));
float ddtheta2 = (u2 - M2*L2*dtheta2*dtheta2*sin(theta1-theta2) - M2*g*sin(theta2)*cos(theta1-theta2))/((M1+M2)*L2 - M2*L2*cos(theta1-theta2)*cos(theta1-theta2));
dtheta1 += ddtheta1 * 0.001f;
dtheta2 += ddtheta2 * 0.001f;
theta1 += dtheta1 * 0.001f;
theta2 += dtheta2 * 0.001f;
}
/* 定义矩阵转置函数 */
void matrix_transpose(float *matrix, int n, int m) {
float tmp[n][m];
memcpy(tmp, matrix, sizeof(float)*n*m);
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
matrix[i*m+j] = tmp[j*n+i];
}
}
}
/* 定义矩阵乘法函数 */
void matrix_multiply(float *matrix1, float *matrix2, float *result, int n, int m, int p, int q) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < q; j++) {
result[i*q+j] = 0;
for (int k = 0; k < m; k++) {
result[i*q+j] += matrix1[i*m+k] * matrix2[k*q+j];
}
}
}
}
/* 定义矩阵加法函数 */
void matrix_add(float *matrix1, float *matrix2, float *result, int n, int m) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
result[i*m+j] = matrix1[i*m+j] + matrix2[i*m+j];
}
}
}
/* 定义矩阵求逆函数 */
void matrix_inverse(float *matrix, int n) {
/* 构造单位矩阵 */
float unit[n][n];
memset(unit, 0, sizeof(unit));
for (int i = 0; i < n; i++) {
unit[i][i] = 1.0f;
}
/* 对矩阵进行高斯-约旦消元法求解 */
for (int i = 0; i < n; i++) {
/* 选取主元素 */
float pivot = matrix[i*n+i];
/* 对主元素所在列进行消元 */
for (int j = 0; j < n; j++) {
if (j == i) {
continue;
}
float factor = matrix[j*n+i] / pivot;
for (int k = 0; k < n; k++) {
matrix[j*n+k] -= factor * matrix[i*n+k];
unit[j][k] -= factor * unit[i][k];
}
}
/* 对主元素所在行进行消元 */
for (int j = 0; j < n; j++) {
matrix[i*n+j] /= pivot;
unit[i][j] /= pivot;
}
}
/* 将结果保存到原矩阵中 */
memcpy(matrix, unit, sizeof(float)*n*n);
}
```
注意,这段代码是对双摆系统进行LQR控制的实现,需要根据实际系统参数进行修改。同时,该代码中使用了一些自定义的矩阵计算函数,需要自行实现。
阅读全文