modified: MDK-ARM/DevC.uvoptx
modified: MDK-ARM/DevC/DevC.axf modified: MDK-ARM/DevC/DevC.hex modified: User/module/config.c modified: User/module/config.h modified: User/module/gimbal.c modified: User/module/gimbal.h modified: User/module/shoot.c modified: User/task/ai.c modified: User/task/atti_esti.c modified: User/task/ctrl_gimbal.c modified: User/task/ctrl_shoot.c modified: User/task/rc.c modified: User/task/user_task.h
This commit is contained in:
parent
11ee01e9f9
commit
3ec16b82bc
@ -887,7 +887,7 @@
|
||||
<GroupNumber>7</GroupNumber>
|
||||
<FileNumber>55</FileNumber>
|
||||
<FileType>1</FileType>
|
||||
<tvExp>1</tvExp>
|
||||
<tvExp>0</tvExp>
|
||||
<tvExpOptDlg>0</tvExpOptDlg>
|
||||
<bDave2>0</bDave2>
|
||||
<PathWithFileName>../Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os2.c</PathWithFileName>
|
||||
|
||||
Binary file not shown.
11034
MDK-ARM/DevC/DevC.hex
11034
MDK-ARM/DevC/DevC.hex
File diff suppressed because it is too large
Load Diff
@ -13,7 +13,8 @@
|
||||
/* Private variables -------------------------------------------------------- */
|
||||
|
||||
/* Exported variables ------------------------------------------------------- */
|
||||
|
||||
/* 全局电机调试使能标志位,1:正常输出;0:强制禁用 */
|
||||
volatile uint8_t g_debug_motor_enable = 0;
|
||||
/**
|
||||
* @brief 机器人参数配置
|
||||
* @note 在此配置机器人参数
|
||||
|
||||
@ -12,6 +12,8 @@ extern "C" {
|
||||
#include <stdbool.h>
|
||||
#include "module/shoot.h"
|
||||
#include "module/gimbal.h"
|
||||
|
||||
extern volatile uint8_t g_debug_motor_enable;
|
||||
// #include "device/vision_bridge.h"
|
||||
/**
|
||||
* @brief 机器人参数配置结构体
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
#include "component/pid.h"
|
||||
#include "device/motor_dm.h"
|
||||
#include "device/motor_rm.h"
|
||||
|
||||
#include "module/config.h"
|
||||
/* Private typedef ---------------------------------------------------------- */
|
||||
/* Private define ----------------------------------------------------------- */
|
||||
/* Private macro ------------------------------------------------------------ */
|
||||
@ -42,13 +42,7 @@ static int8_t Gimbal_SetMode(Gimbal_t *g, Gimbal_Mode_t mode) {
|
||||
MOTOR_DM_Enable(&(g->param->pit_motor));
|
||||
|
||||
AHRS_ResetEulr(&(g->setpoint.eulr)); /* 切换模式后重置设定值 */
|
||||
// if (g->mode == GIMBAL_MODE_RELAX) {
|
||||
// if (mode == GIMBAL_MODE_ABSOLUTE) {
|
||||
// g->setpoint.eulr.yaw = g->feedback.imu.eulr.yaw;
|
||||
// } else if (mode == GIMBAL_MODE_RELATIVE) {
|
||||
// g->setpoint.eulr.yaw = g->feedback.imu.eulr.yaw;
|
||||
// }
|
||||
// }
|
||||
|
||||
g->setpoint.eulr.pit = g->feedback.imu.eulr.rol;
|
||||
g->setpoint.eulr.yaw = g->feedback.imu.eulr.yaw;
|
||||
|
||||
@ -159,8 +153,21 @@ int8_t Gimbal_Control(Gimbal_t *g, Gimbal_CMD_t *g_cmd) {
|
||||
|
||||
Gimbal_SetMode(g, g_cmd->mode);
|
||||
|
||||
/* 处理yaw控制命令,软件限位 - 使用电机绝对角度 */
|
||||
float delta_yaw = g_cmd->delta_yaw * g->dt * 1.5f;
|
||||
/* --- 计算目标增量:兼容手动模式与火控托管模式 --- */
|
||||
float delta_yaw = 0.0f;
|
||||
float delta_pit = 0.0f;
|
||||
|
||||
if (g->mode == GIMBAL_MODE_AUTO_AIM && g_cmd->vision.target_found) {
|
||||
/* 火控模式且目标已锁定:计算视觉目标角度与当前设定值的偏差 */
|
||||
delta_yaw = CircleError(g_cmd->vision.yaw, g->setpoint.eulr.yaw, M_2PI);
|
||||
delta_pit = CircleError(g_cmd->vision.pit, g->setpoint.eulr.pit, M_2PI);
|
||||
} else {
|
||||
/* 常规模式或火控模式下目标丢失:使用操作手遥控器增量 */
|
||||
delta_yaw = g_cmd->delta_yaw * g->dt * 1.5f;
|
||||
delta_pit = g_cmd->delta_pit * g->dt;
|
||||
}
|
||||
|
||||
/* --- 处理yaw控制命令,软件限位 - 使用电机绝对角度 --- */
|
||||
if (g->param->travel.yaw > 0) {
|
||||
/* 计算当前电机角度与IMU角度的偏差 */
|
||||
float motor_imu_offset = g->feedback.motor.yaw.rotor_abs_angle - g->feedback.imu.eulr.yaw;
|
||||
@ -190,8 +197,7 @@ int8_t Gimbal_Control(Gimbal_t *g, Gimbal_CMD_t *g_cmd) {
|
||||
}
|
||||
CircleAdd(&(g->setpoint.eulr.yaw), delta_yaw, M_2PI);
|
||||
|
||||
/* 处理pitch控制命令,软件限位 - 使用电机绝对角度 */
|
||||
float delta_pit = g_cmd->delta_pit * g->dt;
|
||||
/* --- 处理pitch控制命令,软件限位 - 使用电机绝对角度 --- */
|
||||
if (g->param->travel.pit > 0) {
|
||||
/* 计算当前电机角度与IMU角度的偏差 */
|
||||
float motor_imu_offset = g->feedback.motor.pit.rotor_abs_angle - g->feedback.imu.eulr.rol;
|
||||
@ -211,7 +217,7 @@ int8_t Gimbal_Control(Gimbal_t *g, Gimbal_CMD_t *g_cmd) {
|
||||
}
|
||||
CircleAdd(&(g->setpoint.eulr.pit), delta_pit, M_2PI);
|
||||
|
||||
/* 控制相关逻辑 */
|
||||
/* --- 控制相关逻辑(PID闭环计算) --- */
|
||||
float yaw_omega_set_point, pit_omega_set_point;
|
||||
switch (g->mode) {
|
||||
case GIMBAL_MODE_RELAX:
|
||||
@ -219,10 +225,11 @@ int8_t Gimbal_Control(Gimbal_t *g, Gimbal_CMD_t *g_cmd) {
|
||||
g->out.pit = 0.0f;
|
||||
break;
|
||||
|
||||
case GIMBAL_MODE_AUTO_AIM: /* 火控模式与绝对模式共用相同的空间系PID闭环 */
|
||||
case GIMBAL_MODE_ABSOLUTE:
|
||||
yaw_omega_set_point = PID_Calc(&(g->pid.yaw_angle), g->setpoint.eulr.yaw,
|
||||
g->feedback.imu.eulr.yaw, 0.0f, g->dt);
|
||||
g->out.yaw = PID_Calc(&(g->pid.pit_omega), yaw_omega_set_point,
|
||||
g->out.yaw = PID_Calc(&(g->pid.yaw_omega), yaw_omega_set_point,
|
||||
g->feedback.imu.gyro.z, 0.f, g->dt);
|
||||
|
||||
pit_omega_set_point = PID_Calc(&(g->pid.pit_angle), g->setpoint.eulr.pit,
|
||||
@ -252,10 +259,21 @@ int8_t Gimbal_Control(Gimbal_t *g, Gimbal_CMD_t *g_cmd) {
|
||||
* \param out CAN设备云台输出结构体
|
||||
*/
|
||||
void Gimbal_Output(Gimbal_t *g){
|
||||
if (g_debug_motor_enable) {
|
||||
/* 标志位为1:正常工作时的输出逻辑 */
|
||||
MOTOR_RM_SetOutput(&g->param->yaw_motor, g->out.yaw);
|
||||
MOTOR_MIT_Output_t output = {0};
|
||||
output.torque = g->out.pit * 3.0f; // 乘以减速比
|
||||
output.kd = 0.3f;
|
||||
MOTOR_RM_Ctrl(&g->param->yaw_motor);
|
||||
MOTOR_DM_MITCtrl(&g->param->pit_motor, &output);
|
||||
} else {
|
||||
/* 标志位为0:强制禁用逻辑,避免断线报错 */
|
||||
MOTOR_RM_SetOutput(&g->param->yaw_motor, 0.0f); // 大疆电机强制0电流
|
||||
|
||||
MOTOR_MIT_Output_t output = {0}; // 达妙MIT模式全零初始化 (位置/速度/扭矩/kp/kd 均为0)
|
||||
|
||||
MOTOR_RM_Ctrl(&g->param->yaw_motor);
|
||||
MOTOR_DM_MITCtrl(&g->param->pit_motor, &output);
|
||||
}
|
||||
}
|
||||
@ -15,6 +15,8 @@ extern "C" {
|
||||
#include "device/motor.h"
|
||||
#include "device/motor_dm.h"
|
||||
#include "device/motor_rm.h"
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/* Exported constants ------------------------------------------------------- */
|
||||
#define GIMBAL_OK (0) /* 运行正常 */
|
||||
@ -29,12 +31,21 @@ typedef enum {
|
||||
GIMBAL_MODE_RELAX, /* 放松模式,电机不输出。一般情况云台初始化之后的模式 */
|
||||
GIMBAL_MODE_ABSOLUTE, /* 绝对坐标系控制,控制在空间内的绝对姿态 */
|
||||
GIMBAL_MODE_RELATIVE, /* 相对坐标系控制,控制相对于底盘的姿态 */
|
||||
GIMBAL_MODE_AUTO_AIM, /* 火控系统托管模式,接收上位机或视觉算法指令 */
|
||||
} Gimbal_Mode_t;
|
||||
|
||||
/* --- 新增:视觉/AI数据结构 --- */
|
||||
typedef struct {
|
||||
float yaw; /* 视觉解算出的空间目标绝对 Yaw 角度 */
|
||||
float pit; /* 视觉解算出的空间目标绝对 Pitch 角度 */
|
||||
uint8_t target_found; /* 视觉是否已锁定目标 (0: 未锁定, 1: 锁定) */
|
||||
} Gimbal_Vision_t;
|
||||
|
||||
typedef struct {
|
||||
Gimbal_Mode_t mode;
|
||||
float delta_yaw;
|
||||
float delta_pit;
|
||||
Gimbal_Vision_t vision; /* 新增:包含视觉/AI控制数据 */
|
||||
} Gimbal_CMD_t;
|
||||
|
||||
/* 软件限位 */
|
||||
@ -76,6 +87,7 @@ typedef struct {
|
||||
AHRS_Gyro_t gyro;
|
||||
AHRS_Eulr_t eulr;
|
||||
} Gimbal_IMU_t;
|
||||
|
||||
/* 云台反馈数据的结构体,包含反馈控制用的反馈数据 */
|
||||
typedef struct {
|
||||
Gimbal_IMU_t imu;
|
||||
@ -90,6 +102,7 @@ typedef struct {
|
||||
float yaw; /* yaw轴电机输出 */
|
||||
float pit; /* pitch轴电机输出 */
|
||||
} Gimbal_Output_t;
|
||||
|
||||
/*
|
||||
* 运行的主结构体,所有这个文件里的函数都在操作这个结构体。
|
||||
* 包含了初始化参数,中间变量,输出变量。
|
||||
@ -155,13 +168,12 @@ int8_t Gimbal_Init(Gimbal_t *g, const Gimbal_Params_t *param,
|
||||
int8_t Gimbal_UpdateFeedback(Gimbal_t *gimbal);
|
||||
|
||||
int8_t Gimbal_UpdateIMU(Gimbal_t *gimbal, const Gimbal_IMU_t *imu);
|
||||
|
||||
/**
|
||||
* \brief 运行云台控制逻辑
|
||||
*
|
||||
* \param g 包含云台数据的结构体
|
||||
* \param fb 云台反馈信息
|
||||
* \param g_cmd 云台控制指令
|
||||
* \param dt_sec 两次调用的时间间隔
|
||||
*
|
||||
* \return 函数运行结果
|
||||
*/
|
||||
@ -170,11 +182,10 @@ int8_t Gimbal_Control(Gimbal_t *g, Gimbal_CMD_t *g_cmd);
|
||||
/**
|
||||
* \brief 云台输出
|
||||
*
|
||||
* \param s 包含云台数据的结构体
|
||||
* \param out CAN设备云台输出结构体
|
||||
* \param g 包含云台数据的结构体
|
||||
*/
|
||||
void Gimbal_Output(Gimbal_t *g);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@ -6,7 +6,7 @@
|
||||
#include <math.h>
|
||||
#include "bsp/time.h"
|
||||
#include "device/motor_rm.h"
|
||||
|
||||
#include "module/config.h"
|
||||
static bool last_firecmd;
|
||||
|
||||
static inline void ScaleSumTo1(float *a, float *b) {
|
||||
@ -289,6 +289,13 @@ int8_t Shoot_Control(Shoot_t *s, Shoot_CMD_t *cmd)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!g_debug_motor_enable) {
|
||||
for(int i=0;i<SHOOT_FRIC_NUM;i++) {
|
||||
MOTOR_RM_SetOutput(&s->param->fric_motor_param[i], 0.0f); // 摩擦轮强制 0 电流
|
||||
}
|
||||
MOTOR_RM_SetOutput(&s->param->trig_motor_param, 0.0f); // 拨弹电机强制 0 电流
|
||||
}
|
||||
|
||||
MOTOR_RM_Ctrl(&s->param->fric_motor_param[0]);
|
||||
last_firecmd = cmd->firecmd;
|
||||
return 0;
|
||||
|
||||
@ -21,7 +21,7 @@
|
||||
#define ID_MCU (0xC4) // MCU 数据包 (发送)
|
||||
#define ID_REF (0xA8) // 裁判系统数据包 (发送)
|
||||
#define ID_AI (0xB5) // AI 控制数据包 (接收)
|
||||
|
||||
extern uint8_t AI_mode; // AI 模式变量,供其他模块查询当前AI控制模式
|
||||
// MCU 数据结构(MCU -> 上位机)
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint8_t mode; // 0: 空闲, 1: 自瞄, 2: 小符, 3: 大符
|
||||
@ -81,38 +81,41 @@ static void AI_RxCpltCallback(void) {
|
||||
if (CRC16_Verify(ai_rx_buf, sizeof(PackageAI_t))) {
|
||||
memcpy(&ai_rx_data, ai_rx_buf, sizeof(PackageAI_t));
|
||||
|
||||
Gimbal_CMD_t ai_gimbal_cmd;
|
||||
Shoot_CMD_t ai_shoot_cmd;
|
||||
/* --- 修复 2:务必初始化局部变量 --- */
|
||||
Gimbal_Vision_t vision_data;
|
||||
memset(&vision_data, 0, sizeof(Gimbal_Vision_t));
|
||||
|
||||
/* 1. 解析指令并生成系统控制信号 */
|
||||
Shoot_CMD_t ai_shoot_cmd;
|
||||
memset(&ai_shoot_cmd, 0, sizeof(Shoot_CMD_t)); // 防止野指针走火
|
||||
|
||||
/* --- 修复 1 & 3:正确赋值视觉结构体 --- */
|
||||
switch (ai_rx_data.data.mode) {
|
||||
case 0: /* 不控制 */
|
||||
ai_gimbal_cmd.mode = GIMBAL_MODE_RELAX;
|
||||
// ai_shoot_cmd.mode = SHOOT_MODE_STOP; /* 需根据实际枚举名称修改 */
|
||||
vision_data.target_found = 0;
|
||||
// ai_shoot_cmd.mode = SHOOT_MODE_STOP;
|
||||
break;
|
||||
case 1: /* 控制云台但不开火 */
|
||||
ai_gimbal_cmd.mode = GIMBAL_MODE_ABSOLUTE;
|
||||
// ai_shoot_cmd.mode = SHOOT_MODE_READY; /* 摩擦轮开启,不拨弹 */
|
||||
vision_data.target_found = 1;
|
||||
vision_data.yaw = ai_rx_data.data.yaw;
|
||||
vision_data.pit = ai_rx_data.data.pitch;
|
||||
// ai_shoot_cmd.mode = SHOOT_MODE_READY;
|
||||
break;
|
||||
case 2: /* 控制云台且开火 */
|
||||
ai_gimbal_cmd.mode = GIMBAL_MODE_ABSOLUTE;
|
||||
// ai_shoot_cmd.mode = SHOOT_MODE_FIRE; /* 摩擦轮开启,拨弹 */
|
||||
vision_data.target_found = 1;
|
||||
vision_data.yaw = ai_rx_data.data.yaw;
|
||||
vision_data.pit = ai_rx_data.data.pitch;
|
||||
// ai_shoot_cmd.mode = SHOOT_MODE_FIRE;
|
||||
break;
|
||||
default:
|
||||
ai_gimbal_cmd.mode = GIMBAL_MODE_RELAX;
|
||||
vision_data.target_found = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
/* 云台位姿控制信号赋值 (假设协议中发下来的 yaw/pitch 直接作为速度增量) */
|
||||
ai_gimbal_cmd.delta_yaw = ai_rx_data.data.yaw;
|
||||
ai_gimbal_cmd.delta_pit = ai_rx_data.data.pitch;
|
||||
|
||||
/* 2. 将命令压入控制队列(非阻塞) */
|
||||
osMessageQueuePut(msgq.gimbal.cmd, &ai_gimbal_cmd, 0, 0);
|
||||
/* 将视觉数据发送到专属队列,不与遥控器命令冲突 */
|
||||
osMessageQueuePut(task_runtime.msgq.vision.data, &vision_data, 0, 0);
|
||||
|
||||
// 注意:若 ctrl_shoot.c 中使用的是 task_runtime.msgq.shoot.shoot_cmd,
|
||||
// 则替换为该全局结构体的队列句柄。此处采用常规 msgq 定义示范:
|
||||
osMessageQueuePut(msgq.shoot.shoot_cmd, &ai_shoot_cmd, 0, 0);
|
||||
/* 将发射指令发送到发射队列 (确保枚举名称与shoot.h对应后解开注释) */
|
||||
// osMessageQueuePut(task_runtime.msgq.shoot.shoot_cmd, &ai_shoot_cmd, 0, 0);
|
||||
}
|
||||
}
|
||||
/* 重新开启DMA定长接收 */
|
||||
@ -124,13 +127,13 @@ static void AI_RxCpltCallback(void) {
|
||||
*/
|
||||
static void AI_Send_MCU_Data(void) {
|
||||
PackageMCU_t tx_pkg;
|
||||
quat_t current_quat;
|
||||
AHRS_Quaternion_t current_quat;
|
||||
|
||||
tx_pkg.id = ID_MCU;
|
||||
memset(&tx_pkg.data, 0, sizeof(DataMCU_t));
|
||||
|
||||
/* 1. 获取四元数 (从消息队列读取) */
|
||||
if (osMessageQueueGet(msgq.ai.quat, ¤t_quat, NULL, 0) == osOK) {
|
||||
if (osMessageQueueGet(task_runtime.msgq.ai.quat, ¤t_quat, NULL, 0) == osOK) {
|
||||
tx_pkg.data.q[0] = current_quat.q0;
|
||||
tx_pkg.data.q[1] = current_quat.q1;
|
||||
tx_pkg.data.q[2] = current_quat.q2;
|
||||
@ -145,15 +148,15 @@ static void AI_Send_MCU_Data(void) {
|
||||
|
||||
/* 3. 获取发射机构与模式状态 (直接读取全局 shoot 结构体) */
|
||||
/* 模式回传,取值为实际枚举映射 */
|
||||
tx_pkg.data.mode = (uint8_t)shoot.mode;
|
||||
|
||||
//tx_pkg.data.mode = (uint8_t)shoot.mode;
|
||||
tx_pkg.data.mode = AI_mode; /* 直接回传当前AI模式,供上位机显示 */
|
||||
/* 弹速反馈:由于硬件可能无法直接测弹速,暂用摩擦轮目标转速或估算转速代替。
|
||||
若接入了裁判系统,应替换为裁判系统下发的真实弹速。 */
|
||||
tx_pkg.data.bullet_speed = shoot.target_variable.target_rpm;
|
||||
|
||||
/* 弹量统计:如有独立计数变量,可进行赋值 */
|
||||
// tx_pkg.data.bullet_count = shoot.feedback.xxxx;
|
||||
|
||||
//tx_pkg.data.bullet_count = shoot.feedback.xxxx;
|
||||
tx_pkg.data.bullet_count = -1;
|
||||
/* 4. 计算 CRC16(扣除末尾 2 字节) */
|
||||
tx_pkg.crc16 = CRC16_Calc((const uint8_t *)&tx_pkg, sizeof(PackageMCU_t) - 2, CRC16_INIT);
|
||||
|
||||
|
||||
@ -87,10 +87,10 @@ void Task_atti_esti(void *argument) {
|
||||
// &gimbal_ahrs.quat: 四元数结构体地址
|
||||
// 0: 消息优先级
|
||||
// 0: 不等待,如果队列满了直接跳过(保证实时性)
|
||||
osMessageQueuePut(msgq.ai.quat, &gimbal_ahrs.quat, 0, 0);
|
||||
osMessageQueuePut(task_runtime.msgq.ai.quat, &gimbal_ahrs.quat, 0, 0);
|
||||
|
||||
// 如果 AI 任务还需要欧拉角,也可以发送欧拉角队列
|
||||
osMessageQueuePut(msgq.ai.eulr, &eulr_to_send, 0, 0);
|
||||
osMessageQueuePut(task_runtime.msgq.ai.eulr, &eulr_to_send, 0, 0);
|
||||
BSP_PWM_SetComp(BSP_PWM_IMU_HEAT_PWM, PID_Calc(&imu_temp_ctrl_pid, 40.5f,
|
||||
bmi088.temp, 0.0f, 0.0f));
|
||||
|
||||
|
||||
@ -24,39 +24,57 @@ Gimbal_CMD_t gimbal_cmd;
|
||||
/* Private function --------------------------------------------------------- */
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
void Task_ctrl_gimbal(void *argument) {
|
||||
(void)argument; /* 未使用argument,消除警告 */
|
||||
|
||||
|
||||
/* 计算任务运行到指定频率需要等待的tick数 */
|
||||
(void)argument;
|
||||
const uint32_t delay_tick = osKernelGetTickFreq() / CTRL_GIMBAL_FREQ;
|
||||
osDelay(CTRL_GIMBAL_INIT_DELAY);
|
||||
uint32_t tick = osKernelGetTickCount();
|
||||
|
||||
osDelay(CTRL_GIMBAL_INIT_DELAY); /* 延时一段时间再开启任务 */
|
||||
|
||||
uint32_t tick = osKernelGetTickCount(); /* 控制任务运行频率的计时 */
|
||||
/* USER CODE INIT BEGIN */
|
||||
Gimbal_Init(&gimbal, &Config_GetRobotParam()->gimbal_param, CTRL_GIMBAL_FREQ);
|
||||
/* USER CODE INIT END */
|
||||
|
||||
/* 缓存最近一次收到的有效视觉数据 */
|
||||
static Gimbal_Vision_t last_vision_data = {0};
|
||||
|
||||
/* 新增:记录最后一次收到有效视觉数据的时间戳 */
|
||||
static uint32_t last_vision_update_tick = 0;
|
||||
/* 新增:视觉断线超时阈值,此处设置为 100ms */
|
||||
const uint32_t vision_timeout_ticks = osKernelGetTickFreq() / 10;
|
||||
|
||||
while (1) {
|
||||
tick += delay_tick; /* 计算下一个唤醒时刻 */
|
||||
/* USER CODE BEGIN */
|
||||
tick += delay_tick;
|
||||
|
||||
/* 1. 更新 IMU 数据 */
|
||||
if (osMessageQueueGet(task_runtime.msgq.gimbal.imu, &gimbal_imu, NULL, 0) == osOK) {
|
||||
Gimbal_UpdateIMU(&gimbal, &gimbal_imu);
|
||||
}
|
||||
|
||||
/* 2. 更新基础控制指令(这会覆盖全局 gimbal_cmd,丢失其内部的 vision 数据) */
|
||||
osMessageQueueGet(task_runtime.msgq.gimbal.cmd, &gimbal_cmd, NULL, 0);
|
||||
|
||||
/* 3. 获取并缓存 AI 视觉信号,增加超时判断逻辑 */
|
||||
Gimbal_Vision_t current_vision;
|
||||
if (osMessageQueueGet(task_runtime.msgq.vision.data, ¤t_vision, NULL, 0) == osOK) {
|
||||
last_vision_data = current_vision; /* 有新视觉包时更新缓存 */
|
||||
last_vision_update_tick = osKernelGetTickCount(); /* 更新收到数据的时间戳 */
|
||||
} else {
|
||||
/* 未收到新数据时,检查是否超时断线 */
|
||||
if ((osKernelGetTickCount() - last_vision_update_tick) > vision_timeout_ticks) {
|
||||
last_vision_data.target_found = 0; /* 超时强制视为目标丢失 */
|
||||
/* 将缓存的 yaw/pit 角度清零,避免残留脏数据干扰 */
|
||||
last_vision_data.yaw = 0.0f;
|
||||
last_vision_data.pit = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
/* 4. 强制将缓存的视觉数据挂载到当前的控制指令中 */
|
||||
gimbal_cmd.vision = last_vision_data;
|
||||
|
||||
/* 5. 执行云台计算与输出 */
|
||||
Gimbal_UpdateFeedback(&gimbal);
|
||||
|
||||
// osMessageQueueReset(task_runtime.msgq.chassis_yaw);
|
||||
osMessageQueuePut(task_runtime.msgq.chassis.yaw, &gimbal.feedback.motor.yaw, 0, 0);
|
||||
|
||||
Gimbal_Control(&gimbal, &gimbal_cmd);
|
||||
|
||||
Gimbal_Output(&gimbal);
|
||||
|
||||
/* USER CODE END */
|
||||
osDelayUntil(tick); /* 运行结束,等待下一次唤醒 */
|
||||
osDelayUntil(tick);
|
||||
}
|
||||
|
||||
}
|
||||
@ -17,6 +17,9 @@
|
||||
/* USER STRUCT BEGIN */
|
||||
Shoot_t shoot;
|
||||
Shoot_CMD_t shoot_cmd;
|
||||
extern Gimbal_CMD_t ai_gimbal_cmd;
|
||||
extern Shoot_CMD_t ai_shoot_cmd;
|
||||
extern uint8_t AI_mode; // AI 模式变量,供其他模块查询当前AI控制模式
|
||||
/* USER STRUCT END */
|
||||
|
||||
/* Private function --------------------------------------------------------- */
|
||||
|
||||
@ -19,6 +19,7 @@
|
||||
/* Private macro ------------------------------------------------------------ */
|
||||
/* Private variables -------------------------------------------------------- */
|
||||
/* USER STRUCT BEGIN */
|
||||
uint8_t AI_mode; // AI 模式变量,供其他模块查询当前AI控制模式
|
||||
DR16_t dr16;
|
||||
Shoot_CMD_t for_shoot;
|
||||
Gimbal_CMD_t cmd_for_gimbal;
|
||||
@ -59,21 +60,25 @@ void Task_rc(void *argument) {
|
||||
cmd_for_gimbal.mode = GIMBAL_MODE_RELAX;
|
||||
cmd_for_gimbal.delta_yaw = 0.0f;
|
||||
cmd_for_gimbal.delta_pit = 0.0f;
|
||||
AI_mode = 0; /* AI 模式:空闲 */
|
||||
break;
|
||||
case DR16_SW_MID:
|
||||
cmd_for_gimbal.mode = GIMBAL_MODE_ABSOLUTE;
|
||||
cmd_for_gimbal.delta_yaw = -dr16.data.ch_r_x * 5.0f;
|
||||
cmd_for_gimbal.delta_pit = dr16.data.ch_r_y * 5.0f;
|
||||
AI_mode = 0; /* AI 模式:空闲 */
|
||||
break;
|
||||
case DR16_SW_DOWN:
|
||||
cmd_for_gimbal.mode = GIMBAL_MODE_ABSOLUTE;
|
||||
cmd_for_gimbal.mode = GIMBAL_MODE_AUTO_AIM;
|
||||
cmd_for_gimbal.delta_yaw = -dr16.data.ch_r_x * 5.0f;
|
||||
cmd_for_gimbal.delta_pit = dr16.data.ch_r_y * 5.0f;
|
||||
AI_mode = 1; /* AI 模式:自动瞄准 */
|
||||
break;
|
||||
default:
|
||||
cmd_for_gimbal.mode = GIMBAL_MODE_RELAX;
|
||||
cmd_for_gimbal.delta_yaw = 0.0f;
|
||||
cmd_for_gimbal.delta_pit = 0.0f;
|
||||
AI_mode = 0; /* AI 模式:空闲 */
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@ -74,6 +74,10 @@ typedef struct {
|
||||
osMessageQueueId_t eulr;
|
||||
osMessageQueueId_t fire;
|
||||
}ai;
|
||||
/* --- 新增:视觉/AI数据消息队列 --- */
|
||||
struct {
|
||||
osMessageQueueId_t data;
|
||||
}vision;
|
||||
} msgq;
|
||||
/* USER MESSAGE END */
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user