@ -1,3 +1,8 @@
/**
* @ file balance_chassis . c
* @ brief 平 衡 底 盘 控 制 模 块
*/
# include "module/balance_chassis.h"
# include "bsp/can.h"
# include "bsp/time.h"
@ -9,61 +14,70 @@
# include <stddef.h>
# include <string.h>
/* Private defines ---------------------------------------------------------- */
# define LIMIT(x, min, max) ((x) < (min) ? (min) : ((x) > (max) ? (max) : (x)))
# define WHEEL_RADIUS 0.068f /* 轮子半径 (m) */
# define MAX_ACCELERATION 2.0f /* 最大加速度 (m/s²) */
# define WHEEL_GEAR_RATIO 4.0f /* 轮毂电机扭矩 */
# define BASE_LEG_LENGTH 0.12f /* 基础腿长 (m) */
# define LEG_LENGTH_RANGE 0.22f /* 腿长调节范围 (m) */
# define MIN_LEG_LENGTH 0.10f /* 最小腿长 (m) */
# define MAX_LEG_LENGTH 0.42f /* 最大腿长 (m) */
# define NON_CONTACT_THETA 0.16f /* 离地时的摆角目标 (rad) */
# define LEFT_BASE_FORCE 60.0f /* 左腿基础支撑力 (N) */
# define RIGHT_BASE_FORCE 65.0f /* 右腿基础支撑力 (N) */
/* Private function prototypes ---------------------------------------------- */
static int8_t Chassis_MotorEnable ( Chassis_t * c ) ;
static int8_t Chassis_MotorRelax ( Chassis_t * c ) ;
static int8_t Chassis_SetMode ( Chassis_t * c , Chassis_Mode_t mode ) ;
static void Chassis_UpdateChassisState ( Chassis_t * c ) ;
static void Chassis_ResetControllers ( Chassis_t * c ) ;
static void Chassis_SelectYawZeroPoint ( Chassis_t * c ) ;
/* Private functions -------------------------------------------------------- */
/**
* @ brief 使 能 所 有 电 机
* @ param c 底 盘 结 构 体 指 针
* @ return
* @ return 操 作 结 果
*/
static int8_t Chassis_MotorEnable ( Chassis_t * c ) {
if ( c = = NULL )
return CHASSIS_ERR_NULL ;
if ( c = = NULL ) return CHASSIS_ERR_NULL ;
for ( int i = 0 ; i < 4 ; i + + ) {
MOTOR_LZ_Param_t * joint_param = & c - > param - > joint_param [ i ] ;
MOTOR_LZ_Enable ( joint_param ) ;
MOTOR_LZ_Enable ( & c - > param - > joint_param [ i ] ) ;
}
for ( int i = 0 ; i < 2 ; i + + ) {
MOTOR_LK_Param_t * wheel_param = & c - > param - > wheel_param [ i ] ;
MOTOR_LK_MotorOn ( wheel_param ) ;
MOTOR_LK_MotorOn ( & c - > param - > wheel_param [ i ] ) ;
}
return CHASSIS_OK ;
}
/**
* @ brief 放 松 所 有 电 机
* @ param c 底 盘 结 构 体 指 针
* @ return 操 作 结 果
*/
static int8_t Chassis_MotorRelax ( Chassis_t * c ) {
if ( c = = NULL )
return CHASSIS_ERR_NULL ;
if ( c = = NULL ) return CHASSIS_ERR_NULL ;
for ( int i = 0 ; i < 4 ; i + + ) {
MOTOR_LZ_Param_t * joint_param = & c - > param - > joint_param [ i ] ;
MOTOR_LZ_Relax ( joint_param ) ;
MOTOR_LZ_Relax ( & c - > param - > joint_param [ i ] ) ;
}
for ( int i = 0 ; i < 2 ; i + + ) {
MOTOR_LK_Param_t * wheel_param = & c - > param - > wheel_param [ i ] ;
MOTOR_LK_Relax ( wheel_param ) ;
MOTOR_LK_Relax ( & c - > param - > wheel_param [ i ] ) ;
}
return CHASSIS_OK ;
}
static int8_t Chassis_SetMode ( Chassis_t * c , Chassis_Mode_t mode ) {
if ( c = = NULL )
return CHASSIS_ERR_NULL ; /* 主结构体不能为空 */
if ( mode = = c - > mode )
return CHASSIS_OK ; /* 模式未改变直接返回 */
// 特殊处理: 从JUMP切换到WHELL_LEG_BALANCE时不重置
// 但从WHELL_LEG_BALANCE切换到JUMP时, 需要重置以触发新的跳跃
if ( c - > mode = = CHASSIS_MODE_JUMP & & mode = = CHASSIS_MODE_WHELL_LEG_BALANCE ) {
c - > mode = mode ;
return CHASSIS_OK ;
}
if ( c - > mode = = CHASSIS_MODE_WHELL_LEG_BALANCE & & mode = = CHASSIS_MODE_JUMP ) {
c - > mode = mode ;
c - > state = 0 ; // 重置状态,确保每次切换模式时都重新初始化
c - > jump_time = 0 ; // 重置跳跃时间, 切换到JUMP模式时会触发新跳跃
return CHASSIS_OK ;
}
Chassis_MotorEnable ( c ) ;
/**
* @ brief 重 置 所 有 控 制 器
* @ param c 底 盘 结 构 体 指 针
*/
static void Chassis_ResetControllers ( Chassis_t * c ) {
/* 重置PID控制器 */
PID_Reset ( & c - > pid . leg_length [ 0 ] ) ;
PID_Reset ( & c - > pid . leg_length [ 1 ] ) ;
PID_Reset ( & c - > pid . yaw ) ;
@ -71,105 +85,116 @@ static int8_t Chassis_SetMode(Chassis_t *c, Chassis_Mode_t mode) {
PID_Reset ( & c - > pid . tp [ 0 ] ) ;
PID_Reset ( & c - > pid . tp [ 1 ] ) ;
// 双零点自动选择逻辑( 使用user_math的CircleError函数)
float current_yaw = c - > feedback . yaw . rotor_abs_angle ;
float zero_point_1 = c - > param - > mech_zero_yaw ;
float zero_point_2 = zero_point_1 + M_PI ; // 第二个零点, 相差180度
/* 重置LQR控制器 */
LQR_Reset ( & c - > lqr [ 0 ] ) ;
LQR_Reset ( & c - > lqr [ 1 ] ) ;
// 使用CircleError计算到两个零点的角度差( 范围为M_2PI)
float error_to_zero1 = CircleError ( zero_point_1 , current_yaw , M_2PI ) ;
float error_to_zero2 = CircleError ( zero_point_2 , current_yaw , M_2PI ) ;
// 选择误差绝对值更小的零点作为目标,并记录是否使用了第二个零点
if ( fabsf ( error_to_zero1 ) < = fabsf ( error_to_zero2 ) ) {
c - > yaw_control . target_yaw = zero_point_1 ;
c - > yaw_control . is_reversed = false ; // 使用第一个零点,不反转
} else {
c - > yaw_control . target_yaw = zero_point_2 ;
c - > yaw_control . is_reversed = true ; // 使用第二个零点,需要反转前后方向
/* 重置滤波器 */
for ( int i = 0 ; i < 4 ; i + + ) {
LowPassFilter2p_Reset ( & c - > filter . joint_out [ i ] , 0.0f ) ;
}
for ( int i = 0 ; i < 2 ; i + + ) {
LowPassFilter2p_Reset ( & c - > filter . wheel_out [ i ] , 0.0f ) ;
}
// 清空位移
/* 清空机体状态 */
c - > chassis_state . position_x = 0.0f ;
c - > chassis_state . velocity_x = 0.0f ;
c - > chassis_state . last_velocity_x = 0.0f ;
c - > chassis_state . target_x = 0.0f ;
c - > chassis_state . target_velocity_x = 0.0f ;
c - > chassis_state . last_target_velocity_x = 0.0f ;
}
LQR_Reset ( & c - > lqr [ 0 ] ) ;
LQR_Reset ( & c - > lqr [ 1 ] ) ;
/**
* @ brief 选 择 yaw轴零点 ( 双 零 点 自 动 选 择 )
* @ param c 底 盘 结 构 体 指 针
*/
static void Chassis_SelectYawZeroPoint ( Chassis_t * c ) {
float current_yaw = c - > feedback . yaw . rotor_abs_angle ;
float zero_point_1 = c - > param - > mech_zero_yaw ;
float zero_point_2 = zero_point_1 + M_PI ;
LowPassFilter2p_Reset ( & c - > filter . joint_out [ 0 ] , 0.0f ) ;
LowPassFilter2p_Reset ( & c - > filter . joint_out [ 1 ] , 0.0f ) ;
LowPassFilter2p_Reset ( & c - > filter . joint_out [ 2 ] , 0.0f ) ;
LowPassFilter2p_Reset ( & c - > filter . joint_out [ 3 ] , 0.0f ) ;
LowPassFilter2p_Reset ( & c - > filter . wheel_out [ 0 ] , 0.0f ) ;
LowPassFilter2p_Reset ( & c - > filter . wheel_out [ 1 ] , 0.0f ) ;
float error_to_zero1 = CircleError ( zero_point_1 , current_yaw , M_2PI ) ;
float error_to_zero2 = CircleError ( zero_point_2 , current_yaw , M_2PI ) ;
if ( fabsf ( error_to_zero1 ) < = fabsf ( error_to_zero2 ) ) {
c - > yaw_control . target_yaw = zero_point_1 ;
c - > yaw_control . is_reversed = false ;
} else {
c - > yaw_control . target_yaw = zero_point_2 ;
c - > yaw_control . is_reversed = true ;
}
}
/**
* @ brief 设 置 底 盘 模 式
* @ param c 底 盘 结 构 体 指 针
* @ param mode 目 标 模 式
* @ return 操 作 结 果
*/
static int8_t Chassis_SetMode ( Chassis_t * c , Chassis_Mode_t mode ) {
if ( c = = NULL ) return CHASSIS_ERR_NULL ;
if ( mode = = c - > mode ) return CHASSIS_OK ;
Chassis_MotorEnable ( c ) ;
Chassis_ResetControllers ( c ) ;
Chassis_SelectYawZeroPoint ( c ) ;
c - > mode = mode ;
c - > state = 0 ; // 重置状态,确保每次切换模式时都重新初始化
c - > jump_time = 0 ; // 重置跳跃时间, 切换到JUMP模式时会触发新跳跃
c - > wz_multi = 0.0f ;
return CHASSIS_OK ;
}
/* 更新机体状态估计 */
/**
* @ brief 更 新 机 体 状 态 估 计
* @ param c 底 盘 结 构 体 指 针
*/
static void Chassis_UpdateChassisState ( Chassis_t * c ) {
if ( c = = NULL )
return ;
if ( c = = NULL ) return ;
// 从轮子编码器估计机体速度 (参考C++代码)
float left_wheel_speed_dps = c - > feedback . wheel [ 0 ] . rotor_speed ; // dps (度每秒)
float right_wheel_speed_dps =
c - > feedback . wheel [ 1 ] . rotor_speed ; // dps (度每秒)
/* 从轮子编码器估计机体速度 */
float left_speed_dps = c - > feedback . wheel [ 0 ] . rotor_speed ;
float right_speed_dps = c - > feedback . wheel [ 1 ] . rotor_speed ;
// 将dps转换为rad/s
float left_ wheel_speed = left_wheel_speed_dps * M_PI / 180.0f ; // rad/s
float right_ wheel_speed = right_wheel_speed_dps * M_PI / 180.0f ; // rad/s
/* 将dps转换为rad/s, 再转为线速度 */
float left_ linear_vel = left_speed_dps * ( M_PI / 180.0f ) * WHEEL_RADIUS ;
float right_ linear_vel = right_speed_dps * ( M_PI / 180.0f ) * WHEEL_RADIUS ;
float wheel_radius = 0.068f ;
float left_wheel_linear_vel = left_wheel_speed * wheel_radius ;
float right_wheel_linear_vel = right_wheel_speed * wheel_radius ;
// 机体x方向速度 (轮子中心速度)
/* 更新机体速度和位置 */
c - > chassis_state . last_velocity_x = c - > chassis_state . velocity_x ;
c - > chassis_state . velocity_x =
( left_wheel_linear_vel + right_wheel_linear_vel ) / 2.0f ;
// 在跳跃模式的起跳和收腿阶段暂停位移积分,避免轮子空转导致的位移误差
if ( ! ( c - > mode = = CHASSIS_MODE_JUMP & & ( c - > state = = 2 | | c - > state = = 3 ) ) ) {
// 积分得到位置
c - > chassis_state . velocity_x = ( left_linear_vel + right_linear_vel ) / 2.0f ;
c - > chassis_state . position_x + = c - > chassis_state . velocity_x * c - > dt ;
}
}
/* Public functions --------------------------------------------------------- */
/**
* @ brief 初 始 化 底 盘
* @ param c 底 盘 结 构 体 指 针
* @ param param 底 盘 参 数 指 针
* @ param target_freq 目 标 控 制 频 率
* @ return 操 作 结 果
*/
int8_t Chassis_Init ( Chassis_t * c , Chassis_Params_t * param , float target_freq ) {
if ( c = = NULL | | param = = NULL | | target_freq < = 0.0f ) {
return - 1 ; // 参数错误
return CHASSIS_ERR ;
}
c - > param = param ;
c - > param = param ;
c - > mode = CHASSIS_MODE_RELAX ;
/* 初始化can */
/* 初始化CAN */
BSP_CAN_Init ( ) ;
/* 初始化和注册所有 电机*/
/* 初始化和注册电机 */
MOTOR_LZ_Init ( ) ;
// 注册关节电机
for ( int i = 0 ; i < 4 ; i + + ) {
if ( MOTOR_LZ_Register ( & c - > param - > joint_param [ i ] ) ! = DEVICE_OK ) {
return DEVICE_ERR ;
}
}
// 注册轮子电机
for ( int i = 0 ; i < 2 ; i + + ) {
if ( MOTOR_LK_Register ( & c - > param - > wheel_param [ i ] ) ! = DEVICE_OK ) {
return DEVICE_ERR ;
@ -182,11 +207,9 @@ int8_t Chassis_Init(Chassis_t *c, Chassis_Params_t *param, float target_freq) {
VMC_Init ( & c - > vmc_ [ 0 ] , & param - > vmc_param [ 0 ] , target_freq ) ;
VMC_Init ( & c - > vmc_ [ 1 ] , & param - > vmc_param [ 1 ] , target_freq ) ;
/*初始化pid*/
PID_Init ( & c - > pid . leg_length [ 0 ] , KPID_MODE_CALC_D , target_freq ,
& param - > leg_length ) ;
PID_Init ( & c - > pid . leg_length [ 1 ] , KPID_MODE_CALC_D , target_freq ,
& param - > leg_length ) ;
/* 初始化PID控制器 */
PID_Init ( & c - > pid . leg_length [ 0 ] , KPID_MODE_CALC_D , target_freq , & param - > leg_length ) ;
PID_Init ( & c - > pid . leg_length [ 1 ] , KPID_MODE_CALC_D , target_freq , & param - > leg_length ) ;
PID_Init ( & c - > pid . yaw , KPID_MODE_CALC_D , target_freq , & param - > yaw ) ;
PID_Init ( & c - > pid . roll , KPID_MODE_CALC_D , target_freq , & param - > roll ) ;
PID_Init ( & c - > pid . tp [ 0 ] , KPID_MODE_CALC_D , target_freq , & param - > tp ) ;
@ -196,52 +219,50 @@ int8_t Chassis_Init(Chassis_t *c, Chassis_Params_t *param, float target_freq) {
LQR_Init ( & c - > lqr [ 0 ] , & param - > lqr_gains ) ;
LQR_Init ( & c - > lqr [ 1 ] , & param - > lqr_gains ) ;
LowPassFilter2p_Init ( & c - > filter . joint_out [ 0 ] , target_freq ,
param - > low_pass_cutoff_freq . out ) ;
LowPassFilter2p_Init ( & c - > filter . joint_out [ 1 ] , target_freq ,
param - > low_pass_cutoff_freq . out ) ;
LowPassFilter2p_Init ( & c - > filter . joint_out [ 2 ] , target_freq ,
param - > low_pass_cutoff_freq . out ) ;
LowPassFilter2p_Init ( & c - > filter . joint_out [ 3 ] , target_freq ,
param - > low_pass_cutoff_freq . out ) ;
LowPassFilter2p_Init ( & c - > filter . wheel_out [ 0 ] , target_freq ,
param - > low_pass_cutoff_freq . out ) ;
LowPassFilter2p_Init ( & c - > filter . wheel_out [ 1 ] , target_freq ,
param - > low_pass_cutoff_freq . out ) ;
Chassis_MotorEnable ( c ) ;
/*初始化机体状态*/
c - > chassis_state . position_x = 0.0f ;
c - > chassis_state . velocity_x = 0.0f ;
c - > chassis_state . last_velocity_x = 0.0f ;
c - > chassis_state . target_x = 0.0f ;
c - > chassis_state . target_velocity_x = 0.0f ;
c - > chassis_state . last_target_velocity_x = 0.0f ;
/* 初始化滤波器 */
for ( int i = 0 ; i < 4 ; i + + ) {
LowPassFilter2p_Init ( & c - > filter . joint_out [ i ] , target_freq , param - > low_pass_cutoff_freq . out ) ;
}
for ( int i = 0 ; i < 2 ; i + + ) {
LowPassFilter2p_Init ( & c - > filter . wheel_out [ i ] , target_freq , param - > low_pass_cutoff_freq . out ) ;
}
/*初始化yaw控制状态*/
c - > yaw_control . target_yaw = 0.0f ;
c - > yaw_control . current_yaw = 0.0f ;
c - > yaw_control . yaw_force = 0.0f ;
c - > yaw_control .is_reversed = false ;
Chassis_MotorEnable ( c ) ;
/* 初始化状态变量 */
memset ( & c - > chassis_state , 0 , sizeof ( c - > chassis_state ) ) ;
memset ( & c - > yaw_control , 0 , sizeof ( c - > yaw_control ) ) ;
return CHASSIS_OK ;
}
/**
* @ brief 更 新 底 盘 反 馈 数 据
* @ param c 底 盘 结 构 体 指 针
* @ return 操 作 结 果
*/
int8_t Chassis_UpdateFeedback ( Chassis_t * c ) {
if ( c = = NULL ) {
return - 1 ; // 参数错误
}
// 更新所有电机数据
if ( c = = NULL ) return CHASSIS_ERR_NULL ;
/* 更新所有电机数据 */
MOTOR_LZ_UpdateAll ( ) ;
MOTOR_LK_UpdateAll ( ) ;
// 更新反馈数据
/* 更新关节电机反馈 */
for ( int i = 0 ; i < 4 ; i + + ) {
MOTOR_LZ_t * joint_motor = MOTOR_LZ_GetMotor ( & c - > param - > joint_param [ i ] ) ;
if ( joint_motor ! = NULL ) {
c - > feedback . joint [ i ] = joint_motor - > motor . feedback ;
}
/* 机械零点调整 */
if ( c - > feedback . joint [ i ] . rotor_abs_angle > M_PI ) {
c - > feedback . joint [ i ] . rotor_abs_angle - = M_2PI ;
}
c - > feedback . joint [ i ] . rotor_abs_angle = - c - > feedback . joint [ i ] . rotor_abs_angle ;
}
/* 更新轮子电机反馈 */
for ( int i = 0 ; i < 2 ; i + + ) {
MOTOR_LK_t * wheel_motor = MOTOR_LK_GetMotor ( & c - > param - > wheel_param [ i ] ) ;
if ( wheel_motor ! = NULL ) {
@ -249,57 +270,44 @@ int8_t Chassis_UpdateFeedback(Chassis_t *c) {
}
}
for ( int i = 0 ; i < 4 ; i + + ) {
// 机械零点调整
if ( c - > feedback . joint [ i ] . rotor_abs_angle > M_PI ) {
c - > feedback . joint [ i ] . rotor_abs_angle - = M_2PI ;
}
c - > feedback . joint [ i ] . rotor_abs_angle =
- c - > feedback . joint [ i ] . rotor_abs_angle ; // 机械零点调整
}
// for (int i = 0; i < 4; i++) {
// c->feedback.joint[i] = virtual_chassis.data.joint[i];
// if (c->feedback.joint[i].rotor_abs_angle > M_PI) {
// c->feedback.joint[i].rotor_abs_angle -= M_2PI;
// }
// c->feedback.joint[i].rotor_abs_angle =
// -c->feedback.joint[i].rotor_abs_angle; // 机械零点调整
// }
// for (int i = 0; i < 2; i++) {
// c->feedback.wheel[i] = virtual_chassis.data.wheel[i];
// }
// c->feedback.imu.accl = virtual_chassis.data.imu.accl;
// c->feedback.imu.gyro = virtual_chassis.data.imu.gyro;
// c->feedback.imu.euler = virtual_chassis.data.imu.euler;
// 更新机体状态估计
/* 更新机体状态估计 */
Chassis_UpdateChassisState ( c ) ;
return 0 ;
return CHASSIS_OK ;
}
/**
* @ brief 更 新 IMU数据
* @ param c 底 盘 结 构 体 指 针
* @ param imu IMU数据
* @ return 操 作 结 果
*/
int8_t Chassis_UpdateIMU ( Chassis_t * c , const Chassis_IMU_t imu ) {
if ( c = = NULL ) {
return - 1 ; // 参数错误
}
if ( c = = NULL ) return CHASSIS_ERR_NULL ;
c - > feedback . imu = imu ;
return 0 ;
return CHASSIS_OK ;
}
/**
* @ brief 底 盘 控 制 主 函 数
* @ param c 底 盘 结 构 体 指 针
* @ param c_cmd 控 制 指 令
* @ return 操 作 结 果
*/
int8_t Chassis_Control ( Chassis_t * c , const Chassis_CMD_t * c_cmd ) {
if ( c = = NULL | | c_cmd = = NULL ) {
return CHASSIS_ERR_NULL ; // 参数错误
}
c - > dt = ( BSP_TIME_Get_us ( ) - c - > lask_wakeup ) /
1000000.0f ; /* 计算两次调用的时间间隔,单位秒 */
if ( c = = NULL | | c_cmd = = NULL ) return CHASSIS_ERR_NULL ;
/* 计算时间间隔 */
c - > dt = ( BSP_TIME_Get_us ( ) - c - > lask_wakeup ) / 1000000.0f ;
c - > lask_wakeup = BSP_TIME_Get_us ( ) ;
/* 设置底盘模式 */
if ( Chassis_SetMode ( c , c_cmd - > mode ) ! = CHASSIS_OK ) {
return CHASSIS_ERR_MODE ; // 设置模式失败
return CHASSIS_ERR_MODE ;
}
/* VMC正解算 */
VMC_ForwardSolve ( & c - > vmc_ [ 0 ] , c - > feedback . joint [ 0 ] . rotor_abs_angle ,
c - > feedback . joint [ 1 ] . rotor_abs_angle ,
c - > feedback . imu . euler . pit , c - > feedback . imu . gyro . y ) ;
@ -307,21 +315,15 @@ int8_t Chassis_Control(Chassis_t *c, const Chassis_CMD_t *c_cmd) {
c - > feedback . joint [ 2 ] . rotor_abs_angle ,
c - > feedback . imu . euler . pit , c - > feedback . imu . gyro . y ) ;
/* 根据底盘模式执行不同的控制逻辑 */
/* 根据模式执行控制 */
switch ( c - > mode ) {
case CHASSIS_MODE_RELAX :
// 放松模式,电机不输出
Chassis_MotorRelax ( c ) ;
Chassis_LQRControl ( c , c_cmd ) ;
break ;
case CHASSIS_MODE_RECOVER : {
float fn , tp ;
fn = - 20.0f ;
tp = 0.0f ;
float fn = - 20.0f , tp = 0.0f ;
Chassis_LQRControl ( c , c_cmd ) ;
VMC_InverseSolve ( & c - > vmc_ [ 0 ] , fn , tp ) ;
@ -330,59 +332,15 @@ int8_t Chassis_Control(Chassis_t *c, const Chassis_CMD_t *c_cmd) {
VMC_GetJointTorques ( & c - > vmc_ [ 1 ] , & c - > output . joint [ 3 ] , & c - > output . joint [ 2 ] ) ;
c - > output . wheel [ 0 ] = c_cmd - > move_vec . vx * 0.2f ;
c - > output . wheel [ 1 ] = c_cmd - > move_vec . vx * 0.2f ;
Chassis_Output ( c ) ; // 统一输出
Chassis_Output ( c ) ;
} break ;
case CHASSIS_MODE_JUMP :
// 跳跃模式状态机
// 状态转换: 0(准备)->1(0.3s)->2(0.2s)->3(0.3s)->0(完成)
// jump_time == 0: 未开始跳跃
// jump_time == 1: 已完成跳跃(不再触发)
// jump_time > 1: 跳跃进行中
// 检测是否需要开始新的跳跃( state为0且jump_time为0)
if ( c - > state = = 0 & & c - > jump_time = = 0 ) {
// 开始跳跃, 进入state 1
c - > state = 1 ;
c - > jump_time = BSP_TIME_Get_us ( ) ;
}
// 只有在跳跃进行中时才处理状态转换( jump_time > 1)
if ( c - > jump_time > 1 ) {
// 计算已经过的时间(微秒)
uint64_t elapsed_us = BSP_TIME_Get_us ( ) - c - > jump_time ;
// 状态转换逻辑
if ( c - > state = = 1 & & elapsed_us > = 300000 ) {
// state 1 保持0.3s后转到state 2
c - > state = 2 ;
c - > jump_time = BSP_TIME_Get_us ( ) ; // 重置计时
} else if ( c - > state = = 2 & & elapsed_us > = 230000 ) {
// state 2 保持0.25s后转到state 3, 确保腿部充分伸展
c - > state = 3 ;
c - > jump_time = BSP_TIME_Get_us ( ) ; // 重置计时
} else if ( c - > state = = 3 & & elapsed_us > = 500000 ) {
// state 3 保持0.4s后转到state 0, 确保收腿到最高
c - > state = 0 ;
c - > jump_time = 1 ; // 设置为1, 表示已完成跳跃, 不再触发
}
}
// 执行LQR控制( 包含PID腿长控制)
Chassis_LQRControl ( c , c_cmd ) ;
Chassis_Output ( c ) ; // 统一输出
break ;
case CHASSIS_MODE_WHELL_LEG_BALANCE :
case CHASSIS_MODE_ROTOR :
// 执行LQR控制( 包含PID腿长控制)
Chassis_LQRControl ( c , c_cmd ) ;
Chassis_Output ( c ) ; // 统一输出
Chassis_Output ( c ) ;
break ;
break ;
default :
return CHASSIS_ERR_MODE ;
}
@ -390,18 +348,19 @@ int8_t Chassis_Control(Chassis_t *c, const Chassis_CMD_t *c_cmd) {
return CHASSIS_OK ;
}
/**
* @ brief 底 盘 输 出
* @ param c 底 盘 结 构 体 指 针
*/
void Chassis_Output ( Chassis_t * c ) {
if ( c = = NULL )
return ;
c - > output . joint [ 0 ] =
LowPassFilter2p_Apply ( & c - > filter . joint_out [ 0 ] , c - > output . joint [ 0 ] ) ;
c - > output . joint [ 1 ] =
LowPassFilter2p_Apply ( & c - > filter . joint_out [ 1 ] , c - > output . joint [ 1 ] ) ;
c - > output . joint [ 2 ] =
LowPassFilter2p_Apply ( & c - > filter . joint_out [ 2 ] , c - > output . joint [ 2 ] ) ;
c - > output . joint [ 3 ] =
LowPassFilter2p_Apply ( & c - > filter . joint_out [ 3 ] , c - > output . joint [ 3 ] ) ;
if ( c = = NULL ) return ;
/* 关节输出滤波 */
for ( int i = 0 ; i < 4 ; i + + ) {
c - > output . joint [ i ] = LowPassFilter2p_Apply ( & c - > filter . joint_out [ i ] , c - > output . joint [ i ] ) ;
}
/* 发送关节控制指令 */
MOTOR_LZ_MotionParam_t motion_param = {
. torque = 0.0f ,
. target_angle = 0.0f ,
@ -409,71 +368,52 @@ void Chassis_Output(Chassis_t *c) {
. kp = 0.0f ,
. kd = 0.0f ,
} ;
for ( int i = 0 ; i < 4 ; i + + ) {
motion_param . torque = c - > output . joint [ i ] ;
MOTOR_LZ_MotionControl ( & c - > param - > joint_param [ i ] , & motion_param ) ;
}
c - > output . wheel [ 0 ] =
LowPassFilter2p_Apply ( & c - > filter . wheel_out [ 0 ] , c - > output . wheel [ 0 ] ) ;
c - > output . wheel [ 1 ] =
LowPassFilter2p_Apply ( & c - > filter . wheel_out [ 1 ] , c - > output . wheel [ 1 ] ) ;
/* 轮子输出滤波并发送 */
for ( int i = 0 ; i < 2 ; i + + ) {
c - > output . wheel [ i ] = LowPassFilter2p_Apply ( & c - > filter . wheel_out [ i ] , c - > output . wheel [ i ] ) ;
}
MOTOR_LK_SetOutput ( & c - > param - > wheel_param [ 0 ] , c - > output . wheel [ 0 ] ) ;
MOTOR_LK_SetOutput ( & c - > param - > wheel_param [ 1 ] , c - > output . wheel [ 1 ] ) ;
// Virtual_Chassis_SendWheelCommand(&virtual_chassis, c->output.wheel[0],
// c->output.wheel[1]);
// Virtual_Chassis_SendWheelCommand(&virtual_chassis, 0.0f,
// 0.0f); // 暂时不让轮子动
}
/**
* @ brief LQR控制
* @ param c 底 盘 结 构 体 指 针
* @ param c_cmd 控 制 指 令
* @ return 操 作 结 果
*/
int8_t Chassis_LQRControl ( Chassis_t * c , const Chassis_CMD_t * c_cmd ) {
if ( c = = NULL | | c_cmd = = NULL ) {
return CHASSIS_ERR_NULL ;
}
if ( c = = NULL | | c_cmd = = NULL ) return CHASSIS_ERR_NULL ;
/* 运动参数( 参考C++版本的状态估计) */
static float xhat = 0.0f , x_dot_hat = 0.0f ;
float target_dot_x = 0.0f ;
float max_acceleration = 2.0f ; // 最大加速度限制: 3 m/s²
// 简化的速度估计( 后续可以改进为C++版本的复杂滤波)
x_dot_hat = c - > chassis_state . velocity_x ;
xhat = c - > chassis_state . position_x ;
// 目标速度设定(原始期望速度)
float raw_vx = c_cmd - > move_vec . vx * 2 ;
// 根据零点选择情况决定是否反转前后方向
/* ==================== 速度控制 ==================== */
float raw_vx = c_cmd - > move_vec . vx * 2.0f ;
float desired_velocity = c - > yaw_control . is_reversed ? - raw_vx : raw_vx ;
// 加速度限制处理
float velocity_change =
desired_velocity - c - > chassis_state . last_target_velocity_x ;
float max_velocity_change = max_acceleration * c - > dt ; // 最大允许的速度变化
/* 加速度限制 */
float velocity_change = desired_velocity - c - > chassis_state . last_target_velocity_x ;
float max_velocity_change = MAX_ACCELERATION * c - > dt ;
velocity_change = LIMIT ( velocity_change , - max_velocity_change , max_velocity_change ) ;
// 限制速度变化率(加速度限制)
if ( velocity_change > max_velocity_change ) {
velocity_change = max_velocity_change ;
} else if ( velocity_change < - max_velocity_change ) {
velocity_change = - max_velocity_change ;
}
// 应用加速度限制后的目标速度
target_dot_x = c - > chassis_state . last_target_velocity_x + velocity_change ;
float target_dot_x = c - > chassis_state . last_target_velocity_x + velocity_change ;
c - > chassis_state . target_velocity_x = target_dot_x ;
c - > chassis_state . last_target_velocity_x = target_dot_x ;
// 更新目标位置
c - > chassis_state . target_x + = target_dot_x * c - > dt ;
/* 分别计算左右腿的LQR控制 */
/* 构建当前状态 */
LQR_State_t current_state = { 0 } ;
current_state . theta = c - > vmc_ [ 0 ] . leg . theta;
current_state . d_theta = c - > vmc_ [ 0 ] . leg . d_theta ;
current_state . x = xhat ;
current_state . d_x = x_dot_hat ;
current_state . phi = c - > feedback . imu . euler . pit ;
current_state . d_phi = - c - > feedback . imu . gyro . x ;
/* ==================== 状态更新 ==================== */
LQR_State_t current_state = {
. theta = c - > vmc_ [ 0 ] . leg . theta ,
. d_theta = c - > vmc_ [ 0 ] . leg . d_theta ,
. x = c - > chassis_state . position_x ,
. d_x = c - > chassis_state . velocity_x ,
. phi = c - > feedback . imu . euler . pit ,
. d_phi = - c - > feedback . imu . gyro . x ,
} ;
LQR_UpdateState ( & c - > lqr [ 0 ] , & current_state ) ;
@ -481,251 +421,140 @@ int8_t Chassis_LQRControl(Chassis_t *c, const Chassis_CMD_t *c_cmd) {
current_state . d_theta = c - > vmc_ [ 1 ] . leg . d_theta ;
LQR_UpdateState ( & c - > lqr [ 1 ] , & current_state ) ;
/* 根据 当前 腿长更新增益矩阵 */
/* 根据 腿长更新增益矩阵 */
LQR_CalculateGainMatrix ( & c - > lqr [ 0 ] , c - > vmc_ [ 0 ] . leg . L0 ) ;
LQR_CalculateGainMatrix ( & c - > lqr [ 1 ] , c - > vmc_ [ 1 ] . leg . L0 ) ;
/* 构建目标状态 */
LQR_State_t target_state = { 0 } ;
/* ==================== 目标状态 ==================== */
LQR_State_t target_state = {
. theta = 0.0f ,
. d_theta = 0.0f ,
. phi = - 0.2f ,
. d_phi = 0.0f ,
. x = c - > chassis_state . target_x ,
. d_x = c - > chassis_state . target_velocity_x ,
} ;
// 在跳跃收腿阶段强制摆角目标为0, 确保落地时腿部竖直
if ( c - > mode = = CHASSIS_MODE_JUMP & & c - > state = = 3 ) {
target_state . theta = 0.0f ; // 强制摆杆角度为0, 确保腿部竖直
} else {
target_state . theta = 0.00 ; // 目标摆杆角度
}
target_state . d_theta = 0.0f ; // 目标摆杆角速度
target_state . phi = - 0.2f ; // 目标俯仰角
target_state . d_phi = 0.0f ; // 目标俯仰角速度
target_state . x = 0.0f ; // 目标位置
target_state . d_x = 0.0f ; // 目标速度
if ( c - > mode ! = CHASSIS_MODE_ROTOR ) {
/* ==================== Yaw轴控制 ==================== */
c - > yaw_control . current_yaw = c - > feedback . yaw . rotor_abs_angle ;
// 双零点自动选择逻辑( 考虑手动控制偏移, 使用CircleError函数)
float manual_offset = c_cmd - > move_vec . vy * M_PI_2 ;
float base_target_1 = c - > param - > mech_zero_yaw + manual_offset ;
float base_target_2 = c - > param - > mech_zero_yaw + M_PI + manual_offset ;
// 使用CircleError计算到两个目标的角度误差
float error_to_target1 = CircleError ( base_target_1 , c - > yaw_control . current_yaw , M_2PI ) ;
float error_to_target2 = CircleError ( base_target_2 , c - > yaw_control . current_yaw , M_2PI ) ;
// 选择误差绝对值更小的目标,并更新反转状态
if ( fabsf ( error_to_target1 ) < = fabsf ( error_to_target2 ) ) {
c - > yaw_control . target_yaw = base_target_1 ;
c - > yaw_control . is_reversed = false ; // 使用第一个零点,不反转
c - > yaw_control . is_reversed = false ;
} else {
c - > yaw_control . target_yaw = base_target_2 ;
c - > yaw_control . is_reversed = true ; // 使用第二个零点,需要反转前后方向
c - > yaw_control . is_reversed = true ;
}
// c->yaw_control.yaw_force =
// PID_Calc(&c->pid.yaw, c->yaw_control.target_yaw,
// c->feedback.yaw.rotor_abs_angle, 0.0f, c->dt);
c - > yaw_control . yaw_force = 0.0f ; // 关闭偏航控制
} else {
// 小陀螺模式:使用速度环控制
c - > yaw_control . current_yaw = c - > feedback . imu . euler . yaw ;
// 渐增旋转速度, 最大角速度约6.9 rad/s( 约400度/秒)
c - > wz_multi + = 0.005f ;
if ( c - > wz_multi > 1.2f )
c - > wz_multi = 1.2f ;
// 目标角速度( rad/s) , 可根据需要调整最大速度
float target_yaw_velocity = c - > wz_multi * 1.0f ; // 最大约7.2 rad/s
// 当前角速度反馈来自IMU陀螺仪
float current_yaw_velocity = c - > feedback . imu . gyro . z ;
// 使用PID控制角速度, 输出力矩
c - > yaw_control . yaw_force =
PID_Calc ( & c - > pid . yaw , target_yaw_velocity ,
current_yaw_velocity , 0.0f , c - > dt ) ;
}
c - > yaw_control . yaw_force = PID_Calc ( & c - > pid . yaw , c - > yaw_control . target_yaw ,
c - > feedback . yaw . rotor_abs_angle , 0.0f , c - > dt ) ;
/* ==================== 左腿LQR控制 ==================== */
if ( c - > vmc_ [ 0 ] . leg . is_ground_contact ) {
/* 更新LQR状态 */
LQR_SetTargetState ( & c - > lqr [ 0 ] , & target_state ) ;
LQR_Control ( & c - > lqr [ 0 ] ) ;
} else {
// 在跳跃收腿阶段强制摆角目标为0, 其他情况为0.16f
float non_contact_theta = ( c - > mode = = CHASSIS_MODE_JUMP & & c - > state = = 3 ) ? 0.0f : 0.16f ;
target_state . theta = non_contact_theta ; // 非接触时的腿摆角目标
target_state . theta = NON_CONTACT_THETA ;
LQR_SetTargetState ( & c - > lqr [ 0 ] , & target_state ) ;
c - > lqr [ 0 ] . control_output . T = 0.0f ;
c - > lqr [ 0 ] . control_output . Tp =
c - > lqr [ 0 ] . K_matrix [ 1 ] [ 0 ] * ( - c - > vmc_ [ 0 ] . leg . theta + non_contact_theta ) +
c - > lqr [ 0 ] . K_matrix [ 1 ] [ 1 ] * ( - c - > vmc_ [ 0 ] . leg . d_theta + 0.0f ) ;
c - > yaw_control . yaw_force = 0.0f ; // 单腿离地时关闭偏航控制
c - > lqr [ 0 ] . K_matrix [ 1 ] [ 0 ] * ( - c - > vmc_ [ 0 ] . leg . theta + NON_CONTACT_THETA ) +
c - > lqr [ 0 ] . K_matrix [ 1 ] [ 1 ] * ( - c - > vmc_ [ 0 ] . leg . d_theta ) ;
c - > yaw_control . yaw_force = 0.0f ;
}
/* ==================== 右腿LQR控制 ==================== */
if ( c - > vmc_ [ 1 ] . leg . is_ground_contact ) {
LQR_SetTargetState ( & c - > lqr [ 1 ] , & target_state ) ;
LQR_Control ( & c - > lqr [ 1 ] ) ;
} else {
// 在跳跃收腿阶段强制摆角目标为0, 其他情况为0.16f
float non_contact_theta = ( c - > mode = = CHASSIS_MODE_JUMP & & c - > state = = 3 ) ? 0.0f : 0.16f ;
target_state . theta = non_contact_theta ; // 非接触时的腿摆角目标
target_state . theta = NON_CONTACT_THETA ;
LQR_SetTargetState ( & c - > lqr [ 1 ] , & target_state ) ;
c - > lqr [ 1 ] . control_output . T = 0.0f ;
c - > lqr [ 1 ] . control_output . Tp =
c - > lqr [ 1 ] . K_matrix [ 1 ] [ 0 ] * ( - c - > vmc_ [ 1 ] . leg . theta + non_contact_theta ) +
c - > lqr [ 1 ] . K_matrix [ 1 ] [ 1 ] * ( - c - > vmc_ [ 1 ] . leg . d_theta + 0.0f ) ;
c - > yaw_control . yaw_force = 0.0f ; // 单腿离地时关闭偏航控制
c - > lqr [ 1 ] . K_matrix [ 1 ] [ 0 ] * ( - c - > vmc_ [ 1 ] . leg . theta + NON_CONTACT_THETA ) +
c - > lqr [ 1 ] . K_matrix [ 1 ] [ 1 ] * ( - c - > vmc_ [ 1 ] . leg . d_theta ) ;
c - > yaw_control . yaw_force = 0.0f ;
}
/* 轮毂力矩输出( 参考C++版本的减速比) */
// 在跳跃的起跳和收腿阶段强制关闭轮子输出,防止离地时轮子猛转
if ( c - > mode = = CHASSIS_MODE_JUMP & & ( c - > state = = 2 | | c - > state = = 3 ) ) {
c - > output . wheel [ 0 ] = 0.0f ;
c - > output . wheel [ 1 ] = 0.0f ;
} else {
c - > output . wheel [ 0 ] =
c - > lqr [ 0 ] . control_output . T / 4.5f + c - > yaw_control . yaw_force ;
c - > output . wheel [ 1 ] =
c - > lqr [ 1 ] . control_output . T / 4.5f - c - > yaw_control . yaw_force ;
}
/* 腿长控制和VMC逆解算( 使用PID控制) */
float virtual_force [ 2 ] ;
float target_L0 [ 2 ] ;
float leg_d_length [ 2 ] ; // 腿长变化率
/* ==================== 轮毂输出 ==================== */
c - > output . wheel [ 0 ] = c - > lqr [ 0 ] . control_output . T / WHEEL_GEAR_RATIO + c - > yaw_control . yaw_force ;
c - > output . wheel [ 1 ] = c - > lqr [ 1 ] . control_output . T / WHEEL_GEAR_RATIO - c - > yaw_control . yaw_force ;
/* 横滚角PID补偿计算 */
// 使用PID控制器计算横滚角补偿长度, 目标横滚角为0
float roll_compensation_length =
PID_Calc ( & c - > pid . roll , 0.0f , c - > feedback . imu . euler . rol ,
/* ==================== 横滚角补偿 ==================== */
float roll_compensation = PID_Calc ( & c - > pid . roll , 0.0f , c - > feedback . imu . euler . rol ,
c - > feedback . imu . gyro . x , c - > dt ) ;
// 限制补偿长度范围,防止过度补偿
// 如果任一腿离地,限制补偿长度
if ( ! c - > vmc_ [ 0 ] . leg . is_ground_contact | | ! c - > vmc_ [ 1 ] . leg . is_ground_contact ) {
if ( roll_compensation_length > 0.02f )
roll_compensation_length = 0.02f ;
if ( roll_compensation_length < - 0.02f )
roll_compensation_length = - 0.02f ;
} else {
if ( roll_compensation_length > 0.05f )
roll_compensation_length = 0.05f ;
if ( roll_compensation_length < - 0.05f )
roll_compensation_length = - 0.05f ;
}
/* 限制补偿范围 */
float max_compensation = ( c - > vmc_ [ 0 ] . leg . is_ground_contact & & c - > vmc_ [ 1 ] . leg . is_ground_contact )
? 0.05f : 0.02f ;
roll_compensation = LIMIT ( roll_compensation , - max_compensation , max_compensation ) ;
// 目标腿长设定(包含横滚角补偿)
switch ( c - > state ) {
case 0 : // 正常状态,根据高度指令调节腿长
target_L0 [ 0 ] = 0.12f + c_cmd - > height * 0.22f + roll_compensation_length ; // 左腿:基础腿长 + 高度调节 + 横滚补偿
target_L0 [ 1 ] = 0.12f + c_cmd - > height * 0.22f - roll_compensation_length ; // 右腿:基础腿长 + 高度调节 - 横滚补偿
break ;
case 1 : // 准备阶段,腿长收缩
target_L0 [ 0 ] = 0.14f + roll_compensation_length ; // 左腿:收缩到较短腿长 + 横滚补偿
target_L0 [ 1 ] = 0.14f - roll_compensation_length ; // 右腿:收缩到较短腿长 - 横滚补偿
break ;
case 2 : // 起跳阶段,腿长快速伸展
target_L0 [ 0 ] = 0.65f ; // 左腿:伸展到最大腿长(跳跃时不进行横滚补偿)
target_L0 [ 1 ] = 0.65f ; // 右腿:伸展到最大腿长(跳跃时不进行横滚补偿)
break ;
case 3 : // 收腿阶段,腿长收缩到最高
target_L0 [ 0 ] = 0.06f ; // 左腿:收缩到最短腿长(确保收腿到最高)
target_L0 [ 1 ] = 0.06f ; // 右腿:收缩到最短腿长(确保收腿到最高)
break ;
default :
target_L0 [ 0 ] = 0.16f + c_cmd - > height * 0.22f + roll_compensation_length ;
target_L0 [ 1 ] = 0.16f + c_cmd - > height * 0.22f - roll_compensation_length ;
break ;
}
/* ==================== 腿长控制 ==================== */
float target_L0 [ 2 ] ;
target_L0 [ 0 ] = BASE_LEG_LENGTH + c_cmd - > height * LEG_LENGTH_RANGE + roll_compensation ;
target_L0 [ 1 ] = BASE_LEG_LENGTH + c_cmd - > height * LEG_LENGTH_RANGE - roll_compensation ;
// 腿长限幅:根据跳跃状态调整限制范围
if ( c - > mode = = CHASSIS_MODE_JUMP & & c - > state = = 3 ) {
// 在跳跃收腿阶段,允许更短的腿长,确保收腿到最高
if ( target_L0 [ 0 ] < 0.06f ) target_L0 [ 0 ] = 0.06f ;
if ( target_L0 [ 1 ] < 0.06f ) target_L0 [ 1 ] = 0.06f ;
} else {
// 正常情况下的腿长限制: 最短0.10, 最长0.42m
if ( target_L0 [ 0 ] < 0.10f ) target_L0 [ 0 ] = 0.10f ;
if ( target_L0 [ 1 ] < 0.10f ) target_L0 [ 1 ] = 0.10f ;
}
if ( target_L0 [ 0 ] > 0.42f ) target_L0 [ 0 ] = 0.42f ;
if ( target_L0 [ 1 ] > 0.42f ) target_L0 [ 1 ] = 0.42f ;
/* 腿长限幅 */
target_L0 [ 0 ] = LIMIT ( target_L0 [ 0 ] , MIN_LEG_LENGTH , MAX_LEG_LENGTH ) ;
target_L0 [ 1 ] = LIMIT ( target_L0 [ 1 ] , MIN_LEG_LENGTH , MAX_LEG_LENGTH ) ;
// 获取腿长变化率
/* 获取腿长变化率 */
float leg_d_length [ 2 ] ;
VMC_GetVirtualLegState ( & c - > vmc_ [ 0 ] , NULL , NULL , & leg_d_length [ 0 ] , NULL ) ;
VMC_GetVirtualLegState ( & c - > vmc_ [ 1 ] , NULL , NULL , & leg_d_length [ 1 ] , NULL ) ;
/* 左右腿摆角相互补偿( 参考C++版本的Delta_Tp机制) */
/* ==================== 左右腿摆角同步补偿 ==================== */
float Delta_Tp [ 2 ] ;
// 使用tp_pid进行左右腿摆角同步控制
// 左腿补偿力矩: 使左腿theta向右腿theta靠拢
Delta_Tp [ 0 ] = c - > vmc_ [ 0 ] . leg . L0 * 10.0f *
PID_Calc ( & c - > pid . tp [ 0 ] , c - > vmc_ [ 1 ] . leg . theta ,
c - > vmc_ [ 0 ] . leg . theta , c - > vmc_ [ 0 ] . leg . d_theta , c - > dt ) ;
// 右腿补偿力矩: 使右腿theta向左腿theta靠拢( 符号相反)
Delta_Tp [ 1 ] = c - > vmc_ [ 1 ] . leg . L0 * 10.0f *
PID_Calc ( & c - > pid . tp [ 1 ] , c - > vmc_ [ 0 ] . leg . theta ,
c - > vmc_ [ 1 ] . leg . theta , c - > vmc_ [ 1 ] . leg . d_theta , c - > dt ) ;
// 左腿控制
{
// 使用PID进行腿长控制
float pid_output = PID_Calc ( & c - > pid . leg_length [ 0 ] , target_L0 [ 0 ] ,
/* ==================== 左腿VMC控制 ==================== */
float pid_output_left = PID_Calc ( & c - > pid . leg_length [ 0 ] , target_L0 [ 0 ] ,
c - > vmc_ [ 0 ] . leg . L0 , leg_d_length [ 0 ] , c - > dt ) ;
float virtual_force_left = c - > lqr [ 0 ] . control_output . Tp * sinf ( c - > vmc_ [ 0 ] . leg . theta ) +
pid_output_left + LEFT_BASE_FORCE ;
// 腿长控制力 = LQR摆杆力矩的径向分量 + PID腿长控制输出 + 基础支撑力
virtual_force [ 0 ] =
( c - > lqr [ 0 ] . control_output . Tp ) * sinf ( c - > vmc_ [ 0 ] . leg . theta ) +
pid_output + 60.0f ;
// VMC逆解算( 包含摆角补偿)
if ( VMC_InverseSolve ( & c - > vmc_ [ 0 ] , virtual_force [ 0 ] ,
if ( VMC_InverseSolve ( & c - > vmc_ [ 0 ] , virtual_force_left ,
c - > lqr [ 0 ] . control_output . Tp + Delta_Tp [ 0 ] ) = = 0 ) {
VMC_GetJointTorques ( & c - > vmc_ [ 0 ] , & c - > output . joint [ 0 ] ,
& c - > output . joint [ 1 ] ) ;
VMC_GetJointTorques ( & c - > vmc_ [ 0 ] , & c - > output . joint [ 0 ] , & c - > output . joint [ 1 ] ) ;
} else {
// VMC失败, 设为0力矩
c - > output . joint [ 0 ] = 0.0f ;
c - > output . joint [ 1 ] = 0.0f ;
}
}
// 右腿控制
{
// 使用PID进行腿长控制
float pid_output = PID_Calc ( & c - > pid . leg_length [ 1 ] , target_L0 [ 1 ] ,
/* ==================== 右腿VMC控制 ==================== */
float pid_output_right = PID_Calc ( & c - > pid . leg_length [ 1 ] , target_L0 [ 1 ] ,
c - > vmc_ [ 1 ] . leg . L0 , leg_d_length [ 1 ] , c - > dt ) ;
float virtual_force_right = c - > lqr [ 1 ] . control_output . Tp * sinf ( c - > vmc_ [ 1 ] . leg . theta ) +
pid_output_right + RIGHT_BASE_FORCE ;
// 腿长控制力 = LQR摆杆力矩的径向分量 + PID腿长控制输出 + 基础支撑力
virtual_force [ 1 ] =
( c - > lqr [ 1 ] . control_output . Tp ) * sinf ( c - > vmc_ [ 1 ] . leg . theta ) +
pid_output + 65.0f ;
// VMC逆解算( 包含摆角补偿)
if ( VMC_InverseSolve ( & c - > vmc_ [ 1 ] , virtual_force [ 1 ] ,
if ( VMC_InverseSolve ( & c - > vmc_ [ 1 ] , virtual_force_right ,
c - > lqr [ 1 ] . control_output . Tp + Delta_Tp [ 1 ] ) = = 0 ) {
VMC_GetJointTorques ( & c - > vmc_ [ 1 ] , & c - > output . joint [ 3 ] ,
& c - > output . joint [ 2 ] ) ;
VMC_GetJointTorques ( & c - > vmc_ [ 1 ] , & c - > output . joint [ 3 ] , & c - > output . joint [ 2 ] ) ;
} else {
// VMC失败, 设为0力矩
c - > output . joint [ 2 ] = 0.0f ;
c - > output . joint [ 3 ] = 0.0f ;
}
}
/* 安全限制 */
/* ==================== 安全限制 ==================== */
for ( int i = 0 ; i < 2 ; i + + ) {
if ( fabsf ( c - > output . wheel [ i ] ) > 1.0f ) {
c - > output . wheel [ i ] = ( c - > output . wheel [ i ] > 0 ) ? 1.0f : - 1.0f ;
c - > output . wheel [ i ] = LIMIT ( c - > output . wheel [ i ] , - 1.0f , 1.0f ) ;
}
}
for ( int i = 0 ; i < 4 ; i + + ) {
if ( fabsf ( c - > output . joint [ i ] ) > 15.0f ) {
c - > output . joint [ i ] = ( c - > output . joint [ i ] > 0 ) ? 15.0f : - 15.0f ;
}
c - > output . joint [ i ] = LIMIT ( c - > output . joint [ i ] , - 15.0f , 15.0f ) ;
}
return CHASSIS_OK ;
}