Quadcopter/User/module/quad_pos_control.c
2025-10-03 14:32:06 +08:00

161 lines
5.3 KiB
C

#include "quad_pos_control.h"
#include "quad_pos_control_math.h"
#include <math.h>
#define VEL_MAX_XY 5.0f // 最大XY速度
#define VEL_MAX_Z 2.0f // 最大Z速度
#define CONSTANTS_ONE_G 9.80665f // 重力加速度
// 位置PID控制器
static KPID_t pos_control_xy;
static KPID_t pos_control_z;
// 速度PID控制器
static KPID_t vel_control_xy;
static KPID_t vel_control_z;
// 位置PID参数
static const KPID_Params_t pos_params_xy = {
.k = 1.0f,
.p = 0.8f, // 调整后的位置环P增益
.i = 0.05f, // 位置环I增益
.d = 0.0f,
.i_limit = 0.5f,
.out_limit = VEL_MAX_XY,
.d_cutoff_freq = 0.0f,
.range = 0.0f
};
static const KPID_Params_t pos_params_z = {
.k = 1.0f,
.p = 1.2f, // Z轴更强的P增益
.i = 0.1f, // Z轴I增益
.d = 0.0f,
.i_limit = 0.5f,
.out_limit = VEL_MAX_Z,
.d_cutoff_freq = 0.0f,
.range = 0.0f
};
// 速度控制参数
static const VelControlParams_t vel_params = {
.xy = {
.k = 1.0f,
.p = 1.5f, // 速度环XY P增益
.i = 0.2f, // XY I增益
.d = 0.02f, // XY D增益
.i_limit = 1.0f,
.out_limit = 5.0f, // 加速度限制
.d_cutoff_freq = 20.0f,
.range = 0.0f
},
.z = {
.k = 1.0f,
.p = 2.0f, // Z轴更强的P增益
.i = 0.3f, // Z轴I增益
.d = 0.04f, // Z轴D增益
.i_limit = 1.0f,
.out_limit = 3.0f, // 加速度限制
.d_cutoff_freq = 20.0f,
.range = 0.0f
},
.hover_thrust = 0.6f, // 悬停推力
.thr_min = 0.1f, // 最小推力
.thr_max = 0.9f, // 最大推力
.thr_xy_margin = 0.1f, // 水平裕度
.g = CONSTANTS_ONE_G
};
// 辅助函数
float constrain(float val, float min_val, float max_val) {
return (val < min_val) ? min_val : ((val > max_val) ? max_val : val);
}
float vector3f_norm_sq(float x, float y, float z) {
return x*x + y*y + z*z;
}
void QuadPosControl_Init(void) {
// 初始化位置PID控制器
PID_Init(&pos_control_xy, KPID_MODE_NO_D, 100.0f, &pos_params_xy);
PID_Init(&pos_control_z, KPID_MODE_NO_D, 100.0f, &pos_params_z);
// 初始化速度PID控制器
PID_Init(&vel_control_xy, KPID_MODE_SET_D, 100.0f, &vel_params.xy);
PID_Init(&vel_control_z, KPID_MODE_SET_D, 100.0f, &vel_params.z);
}
void PositionControl(QuadPosition_t *quad_pos, float dt) {
// 计算位置误差并输出速度指令
quad_pos->vel_desire.x = quad_pos->vel_forward.x +
PID_Calc(&pos_control_xy, quad_pos->pos_desire.x,
quad_pos->pos_now.x, 0.0f, dt);
quad_pos->vel_desire.y = quad_pos->vel_forward.y +
PID_Calc(&pos_control_xy, quad_pos->pos_desire.y,
quad_pos->pos_now.y, 0.0f, dt);
quad_pos->vel_desire.z = quad_pos->vel_forward.z +
PID_Calc(&pos_control_z, quad_pos->pos_desire.z,
quad_pos->pos_now.z, 0.0f, dt);
// 限制水平速度
Vector2f vel_xy = {quad_pos->vel_desire.x, quad_pos->vel_desire.y};
Vector2f constrained_xy = constrainXY(&vel_xy, &(Vector2f){0,0}, VEL_MAX_XY);
quad_pos->vel_desire.x = constrained_xy.x;
quad_pos->vel_desire.y = constrained_xy.y;
// 限制垂直速度
quad_pos->vel_desire.z = constrain(quad_pos->vel_desire.z, -VEL_MAX_Z, VEL_MAX_Z);
}
void VelocityControl(QuadPosition_t *quad_pos, float dt) {
const VelControlParams_t *p = &vel_params;
const float g = p->g;
const float hover_thrust = p->hover_thrust;
// 1. 计算速度环PID输出 (加速度指令)
float acc_sp_x = PID_Calc(&vel_control_xy, quad_pos->vel_desire.x,
quad_pos->vel_now.x, quad_pos->vel_dot.x, dt);
float acc_sp_y = PID_Calc(&vel_control_xy, quad_pos->vel_desire.y,
quad_pos->vel_now.y, quad_pos->vel_dot.y, dt);
float acc_sp_z = PID_Calc(&vel_control_z, quad_pos->vel_desire.z,
quad_pos->vel_now.z, quad_pos->vel_dot.z, dt);
// 2. 转换为推力设定值
quad_pos->thr_sp.x = acc_sp_x * (hover_thrust / g);
quad_pos->thr_sp.y = acc_sp_y * (hover_thrust / g);
quad_pos->thr_sp.z = (acc_sp_z + g) * (hover_thrust / g);
// 3. 垂直推力限制
quad_pos->thr_sp.z = constrain(quad_pos->thr_sp.z, p->thr_min, p->thr_max);
// 4. 水平推力限制
float thr_sp_xy_norm = sqrtf(quad_pos->thr_sp.x*quad_pos->thr_sp.x +
quad_pos->thr_sp.y*quad_pos->thr_sp.y);
float thr_max_xy_sq = p->thr_max*p->thr_max - quad_pos->thr_sp.z*quad_pos->thr_sp.z;
if (thr_sp_xy_norm > 0 && thr_max_xy_sq > 0) {
float thr_max_xy = sqrtf(thr_max_xy_sq) - p->thr_xy_margin;
if (thr_sp_xy_norm > thr_max_xy) {
float scale = thr_max_xy / thr_sp_xy_norm;
quad_pos->thr_sp.x *= scale;
quad_pos->thr_sp.y *= scale;
}
}
// 5. 抗饱和处理 (使用现有PID的内部机制)
// 通过PID参数中的i_limit和out_limit实现
}
// 主控制循环
void ControlLoop(QuadPosition_t *quad_pos, float dt) {
PositionControl(quad_pos, dt); // 位置环
VelocityControl(quad_pos, dt); // 速度环
}