mirror of
https://gitee.com/dlmu-cone/bf_original_balance_chassis
synced 2026-07-24 03:27:45 +08:00
199 lines
6.4 KiB
C
199 lines
6.4 KiB
C
// app
|
|
#include "balance.h"
|
|
#include "linkNleg.h"
|
|
#include "robot_def.h"
|
|
#include "general_def.h"
|
|
#include "ins_task.h"
|
|
#include "HT04.h"
|
|
#include "LK9025.h"
|
|
#include "controller.h"
|
|
#include "can_comm.h"
|
|
#include "super_cap.h"
|
|
#include "user_lib.h"
|
|
#include "remote_control.h"
|
|
#include "referee_task.h"
|
|
#include "stdint.h"
|
|
#include "arm_math.h" // 需要用到较多三角函数
|
|
#include "bsp_dwt.h"
|
|
#include "bsp_log.h"
|
|
#include "lqr_calc.h"
|
|
|
|
// 计时变量
|
|
static uint32_t balance_dwt_cnt;
|
|
static float del_t;
|
|
|
|
// 底盘拥有的实例模块
|
|
static INS_t *Chassis_IMU_data;
|
|
static RC_ctrl_t *rc_data; // 底盘单独调试用
|
|
static Chassis_Ctrl_Cmd_s chassis_cmd_recv;
|
|
|
|
// 四个关节电机和两个驱动轮电机
|
|
static HTMotorInstance *lf, *lb, *rf, *rb, *joint[4]; // 指针数组方便传参和调试
|
|
static LKMotorInstance *l_driven, *r_driven, *driven[2];
|
|
|
|
// 两个腿的参数,0为左腿,1为右腿
|
|
static LinkNPodParam l_side, r_side;
|
|
static ChassisParam chassis;
|
|
|
|
// 底盘状态
|
|
static Robot_Status_e chassis_status;
|
|
|
|
|
|
void BalanceInit()
|
|
{
|
|
rc_data = RemoteControlInit(&huart3);
|
|
Chassis_IMU_data = INS_Init();
|
|
|
|
// 关节电机
|
|
Motor_Init_Config_s joint_conf = {
|
|
// 写一个,剩下的修改方向和id即可
|
|
.can_init_config = {
|
|
.can_handle = &hcan1},
|
|
.controller_setting_init_config = {
|
|
.close_loop_type = OPEN_LOOP,
|
|
.outer_loop_type = OPEN_LOOP,
|
|
.motor_reverse_flag = FEEDBACK_DIRECTION_NORMAL,
|
|
.angle_feedback_source = MOTOR_FEED,
|
|
.speed_feedback_source = MOTOR_FEED,
|
|
},
|
|
.motor_type = HT04};
|
|
joint_conf.can_init_config.tx_id = 1;
|
|
joint_conf.can_init_config.rx_id = 11;
|
|
joint[LF] = lf = HTMotorInit(&joint_conf);
|
|
joint_conf.can_init_config.tx_id = 2;
|
|
joint_conf.can_init_config.rx_id = 12;
|
|
joint[LB] = lb = HTMotorInit(&joint_conf);
|
|
joint_conf.can_init_config.tx_id = 3;
|
|
joint_conf.can_init_config.rx_id = 13;
|
|
joint[RF] = rf = HTMotorInit(&joint_conf);
|
|
joint_conf.can_init_config.tx_id = 4;
|
|
joint_conf.can_init_config.rx_id = 14;
|
|
joint[RB] = rb = HTMotorInit(&joint_conf);
|
|
|
|
// 驱动轮电机
|
|
Motor_Init_Config_s driven_conf = {
|
|
// 写一个,剩下的修改方向和id即可
|
|
.can_init_config.can_handle = &hcan2,
|
|
.controller_setting_init_config = {
|
|
.angle_feedback_source = MOTOR_FEED,
|
|
.speed_feedback_source = MOTOR_FEED,
|
|
.outer_loop_type = OPEN_LOOP,
|
|
.close_loop_type = OPEN_LOOP,
|
|
.motor_reverse_flag = MOTOR_DIRECTION_NORMAL,
|
|
},
|
|
.motor_type = LK9025,
|
|
};
|
|
driven_conf.can_init_config.tx_id = 1;
|
|
driven[RD] = r_driven = LKMotorInit(&driven_conf);
|
|
driven_conf.can_init_config.tx_id = 2;
|
|
driven[LD] = l_driven = LKMotorInit(&driven_conf);
|
|
|
|
// 状态初始化
|
|
chassis_status = ROBOT_READY;
|
|
DWT_GetDeltaT(&balance_dwt_cnt);
|
|
}
|
|
|
|
static void EnableAllMotor() /* 打开所有电机 */
|
|
{
|
|
for (uint8_t i = 0; i < JOINT_CNT; i++) // 打开关节电机
|
|
HTMotorEnable(joint[i]);
|
|
for (uint8_t i = 0; i < DRIVEN_CNT; i++) // 打开驱动电机
|
|
LKMotorEnable(driven[i]);
|
|
}
|
|
|
|
/* 切换底盘遥控器控制和云台双板控制 */
|
|
static void ControlSwitch()
|
|
{
|
|
// 右侧拨杆向下,进入遥控器底盘控制,此时不响应云台控制指令
|
|
if (switch_is_down(rc_data->rc.switch_right) && RemoteControlIsOnline())
|
|
{
|
|
if (rc_data->rc.rocker_l1 < -600)
|
|
{
|
|
chassis_cmd_recv.chassis_mode = CHASSIS_RESET;
|
|
chassis_cmd_recv.vx = 0.005 * (float)rc_data[TEMP].rc.rocker_r1; // speed x, unit m/s
|
|
}
|
|
else
|
|
{
|
|
chassis_cmd_recv.chassis_mode = CHASSIS_FREE_DEBUG; // 自由转动&前后
|
|
chassis_cmd_recv.vx = 0.002 * (float)rc_data[TEMP].rc.rocker_r1; // speed x, unit m/s
|
|
}
|
|
}
|
|
else
|
|
chassis_cmd_recv.chassis_mode = CHASSIS_ZERO_FORCE; // 皆离线,急停
|
|
}
|
|
|
|
|
|
// 工作状态设定
|
|
static void WokingStateSet()
|
|
{
|
|
if (chassis_cmd_recv.chassis_mode == CHASSIS_ZERO_FORCE) // 未收到遥控器和云台指令底盘进入急停
|
|
{
|
|
for (uint8_t i = 0; i < JOINT_CNT; i++)
|
|
HTMotorStop(joint[i]);
|
|
for (uint8_t i = 0; i < DRIVEN_CNT; i++)
|
|
LKMotorStop(driven[i]);
|
|
return; // 关闭所有电机,发送的指令为零
|
|
}
|
|
|
|
// 运动模式
|
|
EnableAllMotor();
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief 将电机和imu的数据组装为LinkNPodParam结构体和chassisParam结构体
|
|
*
|
|
* @note HT04电机上电的编码器位置为零(校准过),请看Link2Pod()的note,以及HT04.c中的电机解码部分
|
|
* @note 海泰04电机顺时针旋转为正; LK9025电机逆时针旋转为正,此处皆需要转换为模型中给定的正方向
|
|
*
|
|
*/
|
|
static void ParamAssemble()
|
|
{
|
|
// 机体参数,视为平面刚体
|
|
chassis.pitch = Chassis_IMU_data->Pitch * DEGREE_2_RAD;
|
|
chassis.pitch_w = Chassis_IMU_data->Gyro[0];
|
|
chassis.yaw = Chassis_IMU_data->YawTotalAngle * DEGREE_2_RAD;
|
|
chassis.wz = Chassis_IMU_data->Gyro[2];
|
|
chassis.roll = Chassis_IMU_data->Roll * DEGREE_2_RAD;
|
|
chassis.roll_w = Chassis_IMU_data->Gyro[1];
|
|
|
|
// HT04电机的角度是顺时针为正,LK9025电机的角度是逆时针为正
|
|
l_side.phi1 = PI + LIMIT_LINK_RAD - lb->measure.total_angle;
|
|
l_side.phi1_w = -lb->measure.speed_rads;
|
|
l_side.phi4 = -lf->measure.total_angle - LIMIT_LINK_RAD;
|
|
l_side.phi4_w = -lf->measure.speed_rads;
|
|
l_side.w_ecd = l_driven->measure.speed_rads;
|
|
|
|
r_side.phi1 = PI + LIMIT_LINK_RAD + rb->measure.total_angle;
|
|
r_side.phi1_w = rb->measure.speed_rads;
|
|
r_side.phi4 = rf->measure.total_angle - LIMIT_LINK_RAD;
|
|
r_side.phi4_w = rf->measure.speed_rads;
|
|
r_side.w_ecd = -r_driven->measure.speed_rads;
|
|
}
|
|
|
|
static void WattLimitSet() /* 设定运动模态的输出 */
|
|
{
|
|
LKMotorSetRef(l_driven, 195.3125 * l_side.T_wheel);
|
|
LKMotorSetRef(r_driven, 195.3125 * -r_side.T_wheel);
|
|
}
|
|
|
|
void BalanceTask()
|
|
{
|
|
del_t = DWT_GetDeltaT(&balance_dwt_cnt);
|
|
|
|
// 切换遥控器控制or云台板控制
|
|
ControlSwitch();
|
|
// 设置目标参数和工作模式
|
|
WokingStateSet();
|
|
// 参数组装
|
|
ParamAssemble();
|
|
// 将五连杆映射成单杆
|
|
Link2Leg(&l_side, &chassis);
|
|
Link2Leg(&r_side, &chassis);
|
|
// 根据单杆计算处的角度和杆长,计算反馈增益
|
|
CalcLQR(&l_side, &chassis);
|
|
CalcLQR(&r_side, &chassis);
|
|
|
|
// 运动模态,电机输出映射和限幅
|
|
WattLimitSet();
|
|
} |