/* * LQR控制器实现:单腿建模 */ #include "lqr.h" #include #include /* 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]; }