168 lines
5.6 KiB
C
168 lines
5.6 KiB
C
/*
|
||
* LQR控制器实现:单腿建模
|
||
*/
|
||
|
||
#include "lqr.h"
|
||
#include <string.h>
|
||
#include <stddef.h>
|
||
|
||
/* Private macros ----------------------------------------------------------- */
|
||
#define LQR_LIMIT(x, min, max) ((x) < (min) ? (min) : ((x) > (max) ? (max) : (x)))
|
||
|
||
/* Private variables -------------------------------------------------------- */
|
||
|
||
/* Private function prototypes ---------------------------------------------- */
|
||
static int8_t LQR_CalculateErrorState(LQR_t *lqr);
|
||
static float LQR_PolynomialCalc(const float *coeff, float leg_length);
|
||
|
||
/* Public functions --------------------------------------------------------- */
|
||
|
||
int8_t LQR_Init(LQR_t *lqr, LQR_GainMatrix_t *gain_matrix) {
|
||
if (lqr == NULL || gain_matrix == NULL) {
|
||
return -1;
|
||
}
|
||
|
||
/* 清零结构体 */
|
||
memset(lqr, 0, sizeof(LQR_t));
|
||
|
||
/* 设置增益矩阵 */
|
||
lqr->gain_matrix = gain_matrix;
|
||
|
||
/* 初始化当前腿长为中等值 */
|
||
lqr->current_leg_length = 0.25f;
|
||
|
||
/* 计算初始增益矩阵 */
|
||
LQR_CalculateGainMatrix(lqr, lqr->current_leg_length);
|
||
|
||
lqr->initialized = true;
|
||
|
||
return 0;
|
||
}
|
||
|
||
int8_t LQR_UpdateState(LQR_t *lqr, const LQR_State_t *current_state) {
|
||
if (lqr == NULL || current_state == NULL) {
|
||
return -1;
|
||
}
|
||
|
||
/* 更新当前状态 */
|
||
lqr->current_state = *current_state;
|
||
|
||
/* 计算状态误差 */
|
||
return LQR_CalculateErrorState(lqr);
|
||
}
|
||
|
||
int8_t LQR_SetTargetState(LQR_t *lqr, const LQR_State_t *target_state) {
|
||
if (lqr == NULL || target_state == NULL) {
|
||
return -1;
|
||
}
|
||
|
||
lqr->target_state = *target_state;
|
||
|
||
/* 重新计算状态误差 */
|
||
return LQR_CalculateErrorState(lqr);
|
||
}
|
||
|
||
int8_t LQR_CalculateGainMatrix(LQR_t *lqr, float leg_length) {
|
||
if (lqr == NULL || lqr->gain_matrix == NULL) {
|
||
return -1;
|
||
}
|
||
|
||
/* 限制腿长范围 */
|
||
leg_length = LQR_LIMIT(leg_length, 0.1f, 0.4f);
|
||
lqr->current_leg_length = leg_length;
|
||
|
||
/* 使用多项式拟合计算当前增益矩阵 */
|
||
lqr->K_matrix[0][0] = LQR_PolynomialCalc(lqr->gain_matrix->k11_coeff, leg_length); /* K11: theta */
|
||
lqr->K_matrix[0][1] = LQR_PolynomialCalc(lqr->gain_matrix->k12_coeff, leg_length); /* K12: d_theta */
|
||
lqr->K_matrix[0][2] = LQR_PolynomialCalc(lqr->gain_matrix->k13_coeff, leg_length); /* K13: x */
|
||
lqr->K_matrix[0][3] = LQR_PolynomialCalc(lqr->gain_matrix->k14_coeff, leg_length); /* K14: d_x */
|
||
lqr->K_matrix[0][4] = LQR_PolynomialCalc(lqr->gain_matrix->k15_coeff, leg_length); /* K15: phi */
|
||
lqr->K_matrix[0][5] = LQR_PolynomialCalc(lqr->gain_matrix->k16_coeff, leg_length); /* K16: d_phi */
|
||
|
||
lqr->K_matrix[1][0] = LQR_PolynomialCalc(lqr->gain_matrix->k21_coeff, leg_length); /* K21: theta */
|
||
lqr->K_matrix[1][1] = LQR_PolynomialCalc(lqr->gain_matrix->k22_coeff, leg_length); /* K22: d_theta */
|
||
lqr->K_matrix[1][2] = LQR_PolynomialCalc(lqr->gain_matrix->k23_coeff, leg_length); /* K23: x */
|
||
lqr->K_matrix[1][3] = LQR_PolynomialCalc(lqr->gain_matrix->k24_coeff, leg_length); /* K24: d_x */
|
||
lqr->K_matrix[1][4] = LQR_PolynomialCalc(lqr->gain_matrix->k25_coeff, leg_length); /* K25: phi */
|
||
lqr->K_matrix[1][5] = LQR_PolynomialCalc(lqr->gain_matrix->k26_coeff, leg_length); /* K26: d_phi */
|
||
|
||
return 0;
|
||
}
|
||
|
||
int8_t LQR_Control(LQR_t *lqr) {
|
||
if (lqr == NULL || !lqr->initialized) {
|
||
return -1;
|
||
}
|
||
|
||
/* LQR控制律: u = -K * x_error
|
||
* 其中 u = [T; Tp], x_error = x_current - x_target
|
||
*/
|
||
|
||
/* 计算轮毂力矩T */
|
||
lqr->control_output.T = -(
|
||
lqr->K_matrix[0][0] * lqr->error_state.theta +
|
||
lqr->K_matrix[0][1] * lqr->error_state.d_theta +
|
||
lqr->K_matrix[0][2] * lqr->error_state.x +
|
||
lqr->K_matrix[0][3] * lqr->error_state.d_x +
|
||
lqr->K_matrix[0][4] * lqr->error_state.phi +
|
||
lqr->K_matrix[0][5] * lqr->error_state.d_phi
|
||
);
|
||
|
||
/* 计算髋关节力矩Tp */
|
||
lqr->control_output.Tp = -(
|
||
lqr->K_matrix[1][0] * lqr->error_state.theta +
|
||
lqr->K_matrix[1][1] * lqr->error_state.d_theta +
|
||
lqr->K_matrix[1][2] * lqr->error_state.x +
|
||
lqr->K_matrix[1][3] * lqr->error_state.d_x +
|
||
lqr->K_matrix[1][4] * lqr->error_state.phi +
|
||
lqr->K_matrix[1][5] * lqr->error_state.d_phi
|
||
);
|
||
|
||
return 0;
|
||
}
|
||
|
||
int8_t LQR_Reset(LQR_t *lqr) {
|
||
if (lqr == NULL) {
|
||
return -1;
|
||
}
|
||
|
||
/* 清零状态和输出 */
|
||
memset(&lqr->current_state, 0, sizeof(LQR_State_t));
|
||
memset(&lqr->target_state, 0, sizeof(LQR_State_t));
|
||
memset(&lqr->error_state, 0, sizeof(LQR_State_t));
|
||
memset(&lqr->control_output, 0, sizeof(LQR_Output_t));
|
||
|
||
return 0;
|
||
}
|
||
|
||
/* Private functions -------------------------------------------------------- */
|
||
|
||
static int8_t LQR_CalculateErrorState(LQR_t *lqr) {
|
||
if (lqr == NULL) {
|
||
return -1;
|
||
}
|
||
|
||
/* 计算状态误差 */
|
||
lqr->error_state.theta = lqr->current_state.theta - lqr->target_state.theta;
|
||
lqr->error_state.d_theta = lqr->current_state.d_theta - lqr->target_state.d_theta;
|
||
lqr->error_state.x = lqr->current_state.x - lqr->target_state.x;
|
||
lqr->error_state.d_x = lqr->current_state.d_x - lqr->target_state.d_x;
|
||
lqr->error_state.phi = lqr->current_state.phi - lqr->target_state.phi;
|
||
lqr->error_state.d_phi = lqr->current_state.d_phi - lqr->target_state.d_phi;
|
||
|
||
return 0;
|
||
}
|
||
|
||
static float LQR_PolynomialCalc(const float *coeff, float leg_length) {
|
||
if (coeff == NULL) {
|
||
return 0.0f;
|
||
}
|
||
|
||
/* 计算3阶多项式: coeff[0]*L^3 + coeff[1]*L^2 + coeff[2]*L + coeff[3] */
|
||
float L = leg_length;
|
||
float L2 = L * L;
|
||
float L3 = L2 * L;
|
||
|
||
return coeff[0] * L3 + coeff[1] * L2 + coeff[2] * L + coeff[3];
|
||
}
|