From c17f41b2679efa20e3561db809af95ef1216de49 Mon Sep 17 00:00:00 2001 From: yxming66 <2389287465@qq.com> Date: Mon, 15 Dec 2025 22:25:00 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E4=BF=9D=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .clangd | 3 +- User/module/cmd_v2/cmd.c | 295 ++++++++++++++++++++++++++++++ User/module/cmd_v2/cmd.h | 173 ++++++++++++++++++ User/module/cmd_v2/cmd_adapter.c | 181 ++++++++++++++++++ User/module/cmd_v2/cmd_adapter.h | 111 +++++++++++ User/module/cmd_v2/cmd_behavior.c | 174 ++++++++++++++++++ User/module/cmd_v2/cmd_behavior.h | 69 +++++++ User/module/cmd_v2/cmd_example.c | 153 ++++++++++++++++ User/module/cmd_v2/cmd_types.h | 177 ++++++++++++++++++ 9 files changed, 1334 insertions(+), 2 deletions(-) create mode 100644 User/module/cmd_v2/cmd.c create mode 100644 User/module/cmd_v2/cmd.h create mode 100644 User/module/cmd_v2/cmd_adapter.c create mode 100644 User/module/cmd_v2/cmd_adapter.h create mode 100644 User/module/cmd_v2/cmd_behavior.c create mode 100644 User/module/cmd_v2/cmd_behavior.h create mode 100644 User/module/cmd_v2/cmd_example.c create mode 100644 User/module/cmd_v2/cmd_types.h diff --git a/.clangd b/.clangd index cfc956a..89d4e90 100644 --- a/.clangd +++ b/.clangd @@ -2,7 +2,7 @@ CompileFlags: Add: - '-ferror-limit=0' - '-Wno-implicit-int' - - "-I/usr/lib/arm-none-eabi/include" + - '-I/usr/lib/arm-none-eabi/include' CompilationDatabase: build/Debug Diagnostics: Suppress: @@ -10,4 +10,3 @@ Diagnostics: - unknown_typename - unknown_typename_suggest - typename_requires_specqual - diff --git a/User/module/cmd_v2/cmd.c b/User/module/cmd_v2/cmd.c new file mode 100644 index 0000000..82dbc1f --- /dev/null +++ b/User/module/cmd_v2/cmd.c @@ -0,0 +1,295 @@ +/* + * CMD 模块 V2 - 主控制模块实现 + */ +#include "cmd.h" +#include "bsp/time.h" +#include +#include + +/* ========================================================================== */ +/* 内部辅助函数 */ +/* ========================================================================== */ + +/* 从RC输入生成底盘命令 */ +static void CMD_RC_BuildChassisCmd(CMD_Context_t *ctx, const CMD_RawInput_t *input) { + CMD_RCModeMap_t *map = &ctx->config->rc_mode_map; + + /* 根据左拨杆位置选择模式 */ + switch (input->sw[0]) { + case CMD_SW_UP: + ctx->chassis.cmd.mode = map->sw_left_up; + break; + case CMD_SW_MID: + ctx->chassis.cmd.mode = map->sw_left_mid; + break; + case CMD_SW_DOWN: + ctx->chassis.cmd.mode = map->sw_left_down; + break; + default: + ctx->chassis.cmd.mode = CHASSIS_MODE_RELAX; + break; + } + + /* 摇杆控制移动 */ + ctx->chassis.cmd.ctrl_vec.vx = input->joy_right.x; + ctx->chassis.cmd.ctrl_vec.vy = input->joy_right.y; +} + +/* 从RC输入生成云台命令 */ +static void CMD_RC_BuildGimbalCmd(CMD_Context_t *ctx, const CMD_RawInput_t *input) { + CMD_RCModeMap_t *map = &ctx->config->rc_mode_map; + + /* 根据拨杆选择云台模式 */ + switch (input->sw[0]) { + case CMD_SW_UP: + ctx->gimbal.cmd.mode = map->gimbal_sw_up; + break; + case CMD_SW_MID: + ctx->gimbal.cmd.mode = map->gimbal_sw_mid; + break; + case CMD_SW_DOWN: + ctx->gimbal.cmd.mode = map->gimbal_sw_down; + break; + default: + ctx->gimbal.cmd.mode = GIMBAL_MODE_RELAX; + break; + } + + /* 左摇杆控制云台 */ + ctx->gimbal.cmd.delta_yaw = -input->joy_left.x * 2.0f; + ctx->gimbal.cmd.delta_pit = -input->joy_left.y * 1.5f; +} + +/* 从RC输入生成射击命令 */ +static void CMD_RC_BuildShootCmd(CMD_Context_t *ctx, const CMD_RawInput_t *input) { + if (input->online) { + ctx->shoot.cmd.mode = SHOOT_MODE_SINGLE; + } else { + ctx->shoot.cmd.mode = SHOOT_MODE_SAFE; + } + + /* 根据右拨杆控制射击 */ + switch (input->sw[1]) { + case CMD_SW_DOWN: + ctx->shoot.cmd.ready = true; + ctx->shoot.cmd.firecmd = true; + break; + case CMD_SW_MID: + ctx->shoot.cmd.ready = true; + ctx->shoot.cmd.firecmd = false; + break; + case CMD_SW_UP: + default: + ctx->shoot.cmd.ready = false; + ctx->shoot.cmd.firecmd = false; + break; + } +} + +/* 从PC输入生成底盘命令 */ +static void CMD_PC_BuildChassisCmd(CMD_Context_t *ctx, const CMD_RawInput_t *input) { + CMD_Sensitivity_t *sens = &ctx->config->sensitivity; + + if (!input->online) { + ctx->chassis.cmd.mode = CHASSIS_MODE_RELAX; + return; + } + + ctx->chassis.cmd.mode = CHASSIS_MODE_FOLLOW_GIMBAL; + + /* WASD控制移动 */ + ctx->chassis.cmd.ctrl_vec.vx = 0.0f; + ctx->chassis.cmd.ctrl_vec.vy = 0.0f; + + if (CMD_KEY_PRESSED(&input->keyboard, CMD_KEY_W)) { + ctx->chassis.cmd.ctrl_vec.vy += sens->move_sens; + } + if (CMD_KEY_PRESSED(&input->keyboard, CMD_KEY_S)) { + ctx->chassis.cmd.ctrl_vec.vy -= sens->move_sens; + } + if (CMD_KEY_PRESSED(&input->keyboard, CMD_KEY_A)) { + ctx->chassis.cmd.ctrl_vec.vx -= sens->move_sens; + } + if (CMD_KEY_PRESSED(&input->keyboard, CMD_KEY_D)) { + ctx->chassis.cmd.ctrl_vec.vx += sens->move_sens; + } + + /* 加速/减速 */ + if (CMD_KEY_PRESSED(&input->keyboard, CMD_KEY_SHIFT)) { + ctx->chassis.cmd.ctrl_vec.vx *= sens->move_fast_mult; + ctx->chassis.cmd.ctrl_vec.vy *= sens->move_fast_mult; + } + if (CMD_KEY_PRESSED(&input->keyboard, CMD_KEY_CTRL)) { + ctx->chassis.cmd.ctrl_vec.vx *= sens->move_slow_mult; + ctx->chassis.cmd.ctrl_vec.vy *= sens->move_slow_mult; + } +} + +/* 从PC输入生成云台命令 */ +static void CMD_PC_BuildGimbalCmd(CMD_Context_t *ctx, const CMD_RawInput_t *input) { + CMD_Sensitivity_t *sens = &ctx->config->sensitivity; + + if (!input->online) { + ctx->gimbal.cmd.mode = GIMBAL_MODE_RELAX; + return; + } + + ctx->gimbal.cmd.mode = GIMBAL_MODE_ABSOLUTE; + + /* 鼠标控制云台 */ + ctx->gimbal.cmd.delta_yaw = (float)-input->mouse.x * ctx->timer.dt * sens->mouse_sens; + ctx->gimbal.cmd.delta_pit = (float)input->mouse.y * ctx->timer.dt * sens->mouse_sens * 1.5f; +} + +/* 从PC输入生成射击命令 */ +static void CMD_PC_BuildShootCmd(CMD_Context_t *ctx, const CMD_RawInput_t *input) { + if (!input->online) { + ctx->shoot.cmd.mode = SHOOT_MODE_SAFE; + return; + } + + ctx->shoot.cmd.ready = true; + ctx->shoot.cmd.firecmd = input->mouse.l_click; +} + +/* 离线安全模式 */ +static void CMD_SetOfflineMode(CMD_Context_t *ctx) { + ctx->chassis.cmd.mode = CHASSIS_MODE_RELAX; + ctx->gimbal.cmd.mode = GIMBAL_MODE_RELAX; + ctx->shoot.cmd.mode = SHOOT_MODE_SAFE; +} + +/* ========================================================================== */ +/* 公开API实现 */ +/* ========================================================================== */ + +int8_t CMD_Init(CMD_Context_t *ctx, CMD_Config_t *config) { + if (ctx == NULL || config == NULL) { + return CMD_ERR_NULL; + } + + memset(ctx, 0, sizeof(CMD_Context_t)); + ctx->config = config; + + /* 初始化适配器 */ + CMD_Adapter_InitAll(); + + /* 初始化行为处理器 */ + CMD_Behavior_Init(); + + return CMD_OK; +} + +int8_t CMD_UpdateInput(CMD_Context_t *ctx) { + if (ctx == NULL) { + return CMD_ERR_NULL; + } + + /* 保存上一帧输入 */ + memcpy(ctx->last_input, ctx->input, sizeof(ctx->input)); + + /* 更新所有输入源 */ + for (int i = 0; i < CMD_SRC_NUM; i++) { + CMD_Adapter_GetInput((CMD_InputSource_t)i, &ctx->input[i]); + } + + return CMD_OK; +} + +int8_t CMD_Arbitrate(CMD_Context_t *ctx) { + if (ctx == NULL) { + return CMD_ERR_NULL; + } + + /* 智能仲裁算法:优先级 PC > RC > NUC */ + CMD_InputSource_t candidates[] = {CMD_SRC_PC, CMD_SRC_RC, CMD_SRC_NUC}; + const int num_candidates = sizeof(candidates) / sizeof(candidates[0]); + + /* 如果当前输入源仍然在线且有效,保持使用 */ + if (ctx->active_source < CMD_SRC_NUM && + ctx->active_source != CMD_SRC_REF && + ctx->input[ctx->active_source].online) { + goto seize; + } + + /* 否则选择第一个可用的控制输入源 */ + for (int i = 0; i < num_candidates; i++) { + CMD_InputSource_t src = candidates[i]; + if (ctx->input[src].online) { + ctx->active_source = src; + } + } + ctx->chassis.source = ctx->active_source; + ctx->gimbal.source = ctx->active_source; + ctx->shoot.source = ctx->active_source; + + seize: + + + + + /* 没有可用输入源 */ + ctx->active_source = CMD_SRC_NUM; + return CMD_OK; +} + +int8_t CMD_GenerateCommands(CMD_Context_t *ctx) { + if (ctx == NULL) { + return CMD_ERR_NULL; + } + + /* 更新时间 */ + uint64_t now_us = BSP_TIME_Get_us(); + ctx->timer.now = now_us / 1000000.0f; + ctx->timer.dt = (now_us - ctx->timer.last_us) / 1000000.0f; + ctx->timer.last_us = now_us; + + /* 没有有效输入源 */ + if (ctx->active_source >= CMD_SRC_NUM) { + CMD_SetOfflineMode(ctx); + return CMD_ERR_NO_INPUT; + } + + const CMD_RawInput_t *active_input = &ctx->input[ctx->active_source]; + const CMD_RawInput_t *last_input = &ctx->last_input[ctx->active_source]; + + /* 根据输入源类型生成命令 */ + switch (ctx->active_source) { + case CMD_SRC_RC: + CMD_RC_BuildChassisCmd(ctx, active_input); + CMD_RC_BuildGimbalCmd(ctx, active_input); + CMD_RC_BuildShootCmd(ctx, active_input); + break; + + case CMD_SRC_PC: + CMD_PC_BuildChassisCmd(ctx, active_input); + CMD_PC_BuildGimbalCmd(ctx, active_input); + CMD_PC_BuildShootCmd(ctx, active_input); + + /* 处理行为 */ + CMD_Behavior_ProcessAll(ctx, active_input, last_input, CMD_MODULE_ALL); + break; + + case CMD_SRC_NUC: + /* TODO: NUC输入处理 */ + break; + + default: + CMD_SetOfflineMode(ctx); + return CMD_ERR_SOURCE; + } + + return CMD_OK; +} + +int8_t CMD_Update(CMD_Context_t *ctx) { + int8_t ret; + + ret = CMD_UpdateInput(ctx); + if (ret != CMD_OK) return ret; + + CMD_Arbitrate(ctx); + + ret = CMD_GenerateCommands(ctx); + return ret; +} diff --git a/User/module/cmd_v2/cmd.h b/User/module/cmd_v2/cmd.h new file mode 100644 index 0000000..a0abc43 --- /dev/null +++ b/User/module/cmd_v2/cmd.h @@ -0,0 +1,173 @@ +/* + * CMD 模块 V2 - 主控制模块 + * 统一的命令控制接口 + */ +#pragma once + +#include "cmd_types.h" +#include "cmd_adapter.h" +#include "cmd_behavior.h" + +/* 引入输出模块的命令类型 */ +#include "module/chassis.h" +#include "module/gimbal.h" +#include "module/shoot.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* ========================================================================== */ +/* 输出命令结构 */ +/* ========================================================================== */ + +/* 每个模块的输出包含源信息和命令 */ +typedef struct { + CMD_InputSource_t source; + Chassis_CMD_t cmd; +} CMD_ChassisOutput_t; + +typedef struct { + CMD_InputSource_t source; + Gimbal_CMD_t cmd; +} CMD_GimbalOutput_t; + +typedef struct { + CMD_InputSource_t source; + Shoot_CMD_t cmd; +} CMD_ShootOutput_t; + +/* ========================================================================== */ +/* 配置结构 */ +/* ========================================================================== */ + +/* 灵敏度配置 */ +typedef struct { + float mouse_sens; /* 鼠标灵敏度 */ + float move_sens; /* 移动灵敏度 */ + float move_fast_mult; /* 快速移动倍率 */ + float move_slow_mult; /* 慢速移动倍率 */ +} CMD_Sensitivity_t; + +/* RC模式映射配置 - 定义开关位置到模式的映射 */ +typedef struct { + /* 左拨杆映射 - 底盘模式 */ + Chassis_Mode_t sw_left_up; + Chassis_Mode_t sw_left_mid; + Chassis_Mode_t sw_left_down; + + /* 右拨杆映射 - 云台/射击模式 */ + Gimbal_Mode_t gimbal_sw_up; + Gimbal_Mode_t gimbal_sw_mid; + Gimbal_Mode_t gimbal_sw_down; +} CMD_RCModeMap_t; + +/* 整体配置 */ +typedef struct { + /* 输入源优先级,索引越小优先级越高 */ + CMD_InputSource_t source_priority[CMD_SRC_NUM]; + + /* 灵敏度设置 */ + CMD_Sensitivity_t sensitivity; + + /* RC模式映射 */ + CMD_RCModeMap_t rc_mode_map; + + /* 是否启用PC输入 */ + bool enable_pc_input; +} CMD_Config_t; + +/* ========================================================================== */ +/* 主控制上下文 */ +/* ========================================================================== */ + +typedef struct { + float now; + float dt; + uint64_t last_us; +} CMD_Timer_t; + +typedef struct CMD_Context { + /* 配置 */ + CMD_Config_t *config; + + /* 时间 */ + CMD_Timer_t timer; + + /* 当前帧和上一帧的原始输入 */ + CMD_RawInput_t input[CMD_SRC_NUM]; + CMD_RawInput_t last_input[CMD_SRC_NUM]; + + /* 仲裁后的活跃输入源 */ + CMD_InputSource_t active_source; + + /* 输出 */ + CMD_ChassisOutput_t chassis; + CMD_GimbalOutput_t gimbal; + CMD_ShootOutput_t shoot; + +} CMD_Context_t; + +/* ========================================================================== */ +/* 主API接口 */ +/* ========================================================================== */ + +/** + * @brief 初始化CMD模块 + * @param ctx CMD上下文 + * @param config 配置指针 + * @return CMD_OK成功,其他失败 + */ +int8_t CMD_Init(CMD_Context_t *ctx, CMD_Config_t *config); + +/** + * @brief 更新所有输入源的数据 + * @param ctx CMD上下文 + * @return CMD_OK成功 + */ +int8_t CMD_UpdateInput(CMD_Context_t *ctx); + +/** + * @brief 执行仲裁,决定使用哪个输入源 + * @param ctx CMD上下文 + * @return 选中的输入源 + */ +int8_t CMD_Arbitrate(CMD_Context_t *ctx); + +/** + * @brief 生成所有模块的控制命令 + * @param ctx CMD上下文 + * @return CMD_OK成功 + */ +int8_t CMD_GenerateCommands(CMD_Context_t *ctx); + +/** + * @brief 一键更新(包含UpdateInput + Arbitrate + GenerateCommands) + * @param ctx CMD上下文 + * @return CMD_OK成功 + */ +int8_t CMD_Update(CMD_Context_t *ctx); + +/* ========================================================================== */ +/* 输出获取接口 */ +/* ========================================================================== */ + +/* 获取底盘命令 */ +static inline Chassis_CMD_t* CMD_GetChassisCmd(CMD_Context_t *ctx) { + return &ctx->chassis.cmd; +} + +/* 获取云台命令 */ +static inline Gimbal_CMD_t* CMD_GetGimbalCmd(CMD_Context_t *ctx) { + return &ctx->gimbal.cmd; +} + +/* 获取射击命令 */ +static inline Shoot_CMD_t* CMD_GetShootCmd(CMD_Context_t *ctx) { + return &ctx->shoot.cmd; +} + +#ifdef __cplusplus +} +#endif diff --git a/User/module/cmd_v2/cmd_adapter.c b/User/module/cmd_v2/cmd_adapter.c new file mode 100644 index 0000000..4ca382b --- /dev/null +++ b/User/module/cmd_v2/cmd_adapter.c @@ -0,0 +1,181 @@ +/* + * CMD 模块 V2 - 输入适配器实现 + */ +#include "cmd_adapter.h" +#include + +/* ========================================================================== */ +/* 适配器存储 */ +/* ========================================================================== */ +static CMD_InputAdapter_t *g_adapters[CMD_SRC_NUM] = {0}; + +/* ========================================================================== */ +/* DR16 适配器实现 */ +/* ========================================================================== */ +#if CMD_RC_DEVICE_TYPE == 0 + +int8_t CMD_DR16_Init(void *data) { + DR16_t *dr16 = (DR16_t *)data; + return DR16_Init(dr16); +} + +int8_t CMD_DR16_RC_GetInput(void *data, CMD_RawInput_t *output) { + DR16_t *dr16 = (DR16_t *)data; + + memset(output, 0, sizeof(CMD_RawInput_t)); + + output->online = dr16->header.online; + + /* 遥控器摇杆映射 */ + output->joy_left.x = dr16->data.rc.ch_l_x; + output->joy_left.y = dr16->data.rc.ch_l_y; + output->joy_right.x = dr16->data.rc.ch_r_x; + output->joy_right.y = dr16->data.rc.ch_r_y; + + /* 拨杆映射 */ + switch (dr16->data.rc.sw_l) { + case DR16_SW_UP: output->sw[0] = CMD_SW_UP; break; + case DR16_SW_MID: output->sw[0] = CMD_SW_MID; break; + case DR16_SW_DOWN: output->sw[0] = CMD_SW_DOWN; break; + default: output->sw[0] = CMD_SW_ERR; break; + } + switch (dr16->data.rc.sw_r) { + case DR16_SW_UP: output->sw[1] = CMD_SW_UP; break; + case DR16_SW_MID: output->sw[1] = CMD_SW_MID; break; + case DR16_SW_DOWN: output->sw[1] = CMD_SW_DOWN; break; + default: output->sw[1] = CMD_SW_ERR; break; + } + + /* 拨轮映射 */ + output->dial = dr16->data.rc.ch_res; + + return CMD_OK; +} + +int8_t CMD_DR16_PC_GetInput(void *data, CMD_RawInput_t *output) { + DR16_t *dr16 = (DR16_t *)data; + + memset(output, 0, sizeof(CMD_RawInput_t)); + + output->online = dr16->header.online; + + /* PC端鼠标映射 */ + output->mouse.x = dr16->data.pc.mouse.x; + output->mouse.y = dr16->data.pc.mouse.y; + output->mouse.l_click = dr16->data.pc.mouse.l_click; + output->mouse.r_click = dr16->data.pc.mouse.r_click; + + /* 键盘映射 */ + output->keyboard.bitmap = dr16->data.pc.keyboard.value; + + return CMD_OK; +} + +bool CMD_DR16_IsOnline(void *data) { + DR16_t *dr16 = (DR16_t *)data; + return dr16->header.online; +} + +/* 定义适配器实例 */ +CMD_DEFINE_ADAPTER(DR16_RC, dr16, CMD_SRC_RC, CMD_DR16_Init, CMD_DR16_RC_GetInput, CMD_DR16_IsOnline) +CMD_DEFINE_ADAPTER(DR16_PC, dr16, CMD_SRC_PC, CMD_DR16_Init, CMD_DR16_PC_GetInput, CMD_DR16_IsOnline) + +#endif /* CMD_RC_DEVICE_TYPE == 0 */ + +/* ========================================================================== */ +/* AT9S 适配器实现 (示例框架) */ +/* ========================================================================== */ +#if CMD_RC_DEVICE_TYPE == 1 + +int8_t CMD_AT9S_Init(void *data) { + AT9S_t *at9s = (AT9S_t *)data; + return AT9S_Init(at9s); +} + +int8_t CMD_AT9S_GetInput(void *data, CMD_RawInput_t *output) { + AT9S_t *at9s = (AT9S_t *)data; + + memset(output, 0, sizeof(CMD_RawInput_t)); + + output->online = at9s->header.online; + + /* TODO: 按照AT9S的数据格式进行映射 */ + output->joy_left.x = at9s->data.rc.ch_l_x; + output->joy_left.y = at9s->data.rc.ch_l_y; + output->joy_right.x = at9s->data.rc.ch_r_x; + output->joy_right.y = at9s->data.rc.ch_r_y; + + /* 拨杆映射需要根据AT9S的实际定义 */ + + return CMD_OK; +} + +bool CMD_AT9S_IsOnline(void *data) { + AT9S_t *at9s = (AT9S_t *)data; + return at9s->header.online; +} + +CMD_DEFINE_ADAPTER(AT9S, at9s, CMD_SRC_RC, CMD_AT9S_Init, CMD_AT9S_GetInput, CMD_AT9S_IsOnline) + +#endif /* CMD_RC_DEVICE_TYPE == 1 */ + +/* ========================================================================== */ +/* 适配器管理实现 */ +/* ========================================================================== */ + +int8_t CMD_Adapter_Register(CMD_InputAdapter_t *adapter) { + if (adapter == NULL || adapter->source >= CMD_SRC_NUM) { + return CMD_ERR_NULL; + } + g_adapters[adapter->source] = adapter; + return CMD_OK; +} + +int8_t CMD_Adapter_InitAll(void) { + /* 注册编译时选择的RC设备适配器 */ +#if CMD_RC_DEVICE_TYPE == 0 + /* DR16 支持 RC 和 PC 输入 */ + CMD_Adapter_Register(&g_adapter_DR16_RC); + CMD_Adapter_Register(&g_adapter_DR16_PC); +#elif CMD_RC_DEVICE_TYPE == 1 + /* AT9S 目前只支持 RC 输入 */ + CMD_Adapter_Register(&g_adapter_AT9S); +#endif + + /* 初始化所有已注册的适配器 */ + for (int i = 0; i < CMD_SRC_NUM; i++) { + if (g_adapters[i] != NULL && g_adapters[i]->init != NULL) { + g_adapters[i]->init(g_adapters[i]->device_data); + } + } + + return CMD_OK; +} + +int8_t CMD_Adapter_GetInput(CMD_InputSource_t source, CMD_RawInput_t *output) { + if (source >= CMD_SRC_NUM || output == NULL) { + return CMD_ERR_NULL; + } + + CMD_InputAdapter_t *adapter = g_adapters[source]; + if (adapter == NULL || adapter->get_input == NULL) { + memset(output, 0, sizeof(CMD_RawInput_t)); + output->online = false; + return CMD_ERR_NO_INPUT; + } + + return adapter->get_input(adapter->device_data, output); +} + +bool CMD_Adapter_IsOnline(CMD_InputSource_t source) { + if (source >= CMD_SRC_NUM) { + return false; + } + + CMD_InputAdapter_t *adapter = g_adapters[source]; + if (adapter == NULL || adapter->is_online == NULL) { + return false; + } + + return adapter->is_online(adapter->device_data); +} diff --git a/User/module/cmd_v2/cmd_adapter.h b/User/module/cmd_v2/cmd_adapter.h new file mode 100644 index 0000000..4fbbc47 --- /dev/null +++ b/User/module/cmd_v2/cmd_adapter.h @@ -0,0 +1,111 @@ +/* + * CMD 模块 V2 - 输入适配器接口 + * 定义设备到统一输入结构的转换接口 + */ +#pragma once + +#include "cmd_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* ========================================================================== */ +/* 适配器接口定义 */ +/* ========================================================================== */ + +/* 适配器操作函数指针类型 */ +typedef int8_t (*CMD_AdapterInitFunc)(void *device_data); +typedef int8_t (*CMD_AdapterGetInputFunc)(void *device_data, CMD_RawInput_t *output); +typedef bool (*CMD_AdapterIsOnlineFunc)(void *device_data); + +/* 适配器描述结构 */ +typedef struct { + const char *name; /* 适配器名称 */ + CMD_InputSource_t source; /* 对应的输入源 */ + void *device_data; /* 设备数据指针 */ + CMD_AdapterInitFunc init; /* 初始化函数 */ + CMD_AdapterGetInputFunc get_input; /* 获取输入函数 */ + CMD_AdapterIsOnlineFunc is_online; /* 在线检测函数 */ +} CMD_InputAdapter_t; + +/* ========================================================================== */ +/* 适配器注册宏 */ +/* ========================================================================== */ + +/* + * 声明适配器 + * 使用示例: + * CMD_DECLARE_ADAPTER(DR16, dr16, DR16_t) + * + * 会生成: + * - extern DR16_t dr16; // 设备实例声明 + * - int8_t CMD_DR16_Init(void *data); + * - int8_t CMD_DR16_GetInput(void *data, CMD_RawInput_t *output); + * - bool CMD_DR16_IsOnline(void *data); + */ +#define CMD_DECLARE_ADAPTER(NAME, var, TYPE) \ + extern TYPE var; \ + int8_t CMD_##NAME##_Init(void *data); \ + int8_t CMD_##NAME##_GetInput(void *data, CMD_RawInput_t *output); \ + bool CMD_##NAME##_IsOnline(void *data); + +/* + * 定义适配器实例 + * 使用示例: + * CMD_DEFINE_ADAPTER(DR16_RC, dr16, CMD_SRC_RC, CMD_DR16_Init, CMD_DR16_RC_GetInput, CMD_DR16_RC_IsOnline) + */ +#define CMD_DEFINE_ADAPTER(NAME, var, source_enum, init_func, get_func, online_func) \ + static CMD_InputAdapter_t g_adapter_##NAME = { \ + .name = #NAME, \ + .source = source_enum, \ + .device_data = (void*)&var, \ + .init = init_func, \ + .get_input = get_func, \ + .is_online = online_func, \ + }; + +/* ========================================================================== */ +/* RC设备适配器配置 */ +/* ========================================================================== */ + +/* 选择使用的RC设备 - 只需修改这里 */ +#define CMD_RC_DEVICE_TYPE 0 /* 0:DR16, 1:AT9S, 2:VT13 */ + +#if CMD_RC_DEVICE_TYPE == 0 + #include "device/dr16.h" + CMD_DECLARE_ADAPTER(DR16_RC, dr16, DR16_t) + CMD_DECLARE_ADAPTER(DR16_PC, dr16, DR16_t) + #define CMD_RC_ADAPTER_NAME DR16 + #define CMD_RC_ADAPTER_VAR dr16 +#elif CMD_RC_DEVICE_TYPE == 1 + #include "device/at9s_pro.h" + CMD_DECLARE_ADAPTER(AT9S, at9s, AT9S_t) + #define CMD_RC_ADAPTER_NAME AT9S + #define CMD_RC_ADAPTER_VAR at9s +#elif CMD_RC_DEVICE_TYPE == 2 + #include "device/vt13.h" + CMD_DECLARE_ADAPTER(VT13, vt13, VT13_t) + #define CMD_RC_ADAPTER_NAME VT13 + #define CMD_RC_ADAPTER_VAR vt13 +#endif + +/* ========================================================================== */ +/* 适配器管理接口 */ +/* ========================================================================== */ + +/* 初始化所有适配器 */ +int8_t CMD_Adapter_InitAll(void); + +/* 获取指定输入源的原始输入 */ +int8_t CMD_Adapter_GetInput(CMD_InputSource_t source, CMD_RawInput_t *output); + +/* 检查输入源是否在线 */ +bool CMD_Adapter_IsOnline(CMD_InputSource_t source); + +/* 注册适配器 (运行时注册,可选) */ +int8_t CMD_Adapter_Register(CMD_InputAdapter_t *adapter); + +#ifdef __cplusplus +} +#endif diff --git a/User/module/cmd_v2/cmd_behavior.c b/User/module/cmd_v2/cmd_behavior.c new file mode 100644 index 0000000..7dd4814 --- /dev/null +++ b/User/module/cmd_v2/cmd_behavior.c @@ -0,0 +1,174 @@ +/* + * CMD 模块 V2 - 行为处理器实现 + */ +#include "cmd_behavior.h" +#include "cmd.h" +#include + +/* ========================================================================== */ +/* 行为配置表 */ +/* ========================================================================== */ + +/* 行为处理函数实现 */ +int8_t CMD_Behavior_Handle_FORE(CMD_Context_t *ctx) { + ctx->chassis.cmd.ctrl_vec.vy += ctx->config->sensitivity.move_sens; + return CMD_OK; +} + +int8_t CMD_Behavior_Handle_BACK(CMD_Context_t *ctx) { + ctx->chassis.cmd.ctrl_vec.vy -= ctx->config->sensitivity.move_sens; + return CMD_OK; +} + +int8_t CMD_Behavior_Handle_LEFT(CMD_Context_t *ctx) { + ctx->chassis.cmd.ctrl_vec.vx -= ctx->config->sensitivity.move_sens; + return CMD_OK; +} + +int8_t CMD_Behavior_Handle_RIGHT(CMD_Context_t *ctx) { + ctx->chassis.cmd.ctrl_vec.vx += ctx->config->sensitivity.move_sens; + return CMD_OK; +} + +int8_t CMD_Behavior_Handle_ACCELERATE(CMD_Context_t *ctx) { + ctx->chassis.cmd.ctrl_vec.vx *= ctx->config->sensitivity.move_fast_mult; + ctx->chassis.cmd.ctrl_vec.vy *= ctx->config->sensitivity.move_fast_mult; + return CMD_OK; +} + +int8_t CMD_Behavior_Handle_DECELERATE(CMD_Context_t *ctx) { + ctx->chassis.cmd.ctrl_vec.vx *= ctx->config->sensitivity.move_slow_mult; + ctx->chassis.cmd.ctrl_vec.vy *= ctx->config->sensitivity.move_slow_mult; + return CMD_OK; +} + +int8_t CMD_Behavior_Handle_FIRE(CMD_Context_t *ctx) { + ctx->shoot.cmd.firecmd = true; + return CMD_OK; +} + +int8_t CMD_Behavior_Handle_FIRE_MODE(CMD_Context_t *ctx) { + ctx->shoot.cmd.mode = (ctx->shoot.cmd.mode + 1) % SHOOT_MODE_NUM; + return CMD_OK; +} + +int8_t CMD_Behavior_Handle_ROTOR(CMD_Context_t *ctx) { + if (ctx->chassis.cmd.mode == CHASSIS_MODE_ROTOR) { + ctx->chassis.cmd.mode = CHASSIS_MODE_FOLLOW_GIMBAL; + } else { + ctx->chassis.cmd.mode = CHASSIS_MODE_ROTOR; + ctx->chassis.cmd.mode_rotor = ROTOR_MODE_RAND; + } + return CMD_OK; +} + +int8_t CMD_Behavior_Handle_AUTOAIM(CMD_Context_t *ctx) { + /* TODO: 自瞄模式切换 */ + return CMD_OK; +} + +/* 行为配置表 - 由宏生成 */ +static const CMD_BehaviorConfig_t g_behavior_configs[] = { + CMD_BEHAVIOR_TABLE(BUILD_BEHAVIOR_CONFIG) +}; + +#define BEHAVIOR_CONFIG_COUNT (sizeof(g_behavior_configs) / sizeof(g_behavior_configs[0])) + +/* ========================================================================== */ +/* API实现 */ +/* ========================================================================== */ + +int8_t CMD_Behavior_Init(void) { + /* 当前静态配置,无需初始化 */ + return CMD_OK; +} + +bool CMD_Behavior_IsTriggered(const CMD_RawInput_t *current, + const CMD_RawInput_t *last, + const CMD_BehaviorConfig_t *config) { + if (config == NULL || current == NULL) { + return false; + } + + bool now_pressed = false; + bool last_pressed = false; + + /* 处理特殊按键 */ + switch (config->key) { + case CMD_KEY_NONE: + return false; + + case CMD_KEY_L_CLICK: + now_pressed = current->mouse.l_click; + last_pressed = last ? last->mouse.l_click : false; + break; + + case CMD_KEY_R_CLICK: + now_pressed = current->mouse.r_click; + last_pressed = last ? last->mouse.r_click : false; + break; + + case CMD_KEY_M_CLICK: + now_pressed = current->mouse.m_click; + last_pressed = last ? last->mouse.m_click : false; + break; + + default: + if (config->key < CMD_KEY_NUM) { + now_pressed = CMD_KEY_PRESSED(¤t->keyboard, config->key); + last_pressed = last ? CMD_KEY_PRESSED(&last->keyboard, config->key) : false; + } + break; + } + + /* 根据触发类型判断 */ + switch (config->trigger) { + case CMD_ACTIVE_PRESSED: + return now_pressed; + + case CMD_ACTIVE_RISING_EDGE: + return now_pressed && !last_pressed; + + case CMD_ACTIVE_FALLING_EDGE: + return !now_pressed && last_pressed; + + default: + return false; + } +} + +int8_t CMD_Behavior_ProcessAll(CMD_Context_t *ctx, + const CMD_RawInput_t *current, + const CMD_RawInput_t *last, + CMD_ModuleMask_t active_modules) { + if (ctx == NULL || current == NULL) { + return CMD_ERR_NULL; + } + + for (size_t i = 0; i < BEHAVIOR_CONFIG_COUNT; i++) { + const CMD_BehaviorConfig_t *config = &g_behavior_configs[i]; + + /* 检查模块掩码 */ + if ((config->module_mask & active_modules) == 0) { + continue; + } + + /* 检查是否触发 */ + if (CMD_Behavior_IsTriggered(current, last, config)) { + if (config->handler != NULL) { + config->handler(ctx); + } + } + } + + return CMD_OK; +} + +const CMD_BehaviorConfig_t* CMD_Behavior_GetConfig(CMD_Behavior_t behavior) { + for (size_t i = 0; i < BEHAVIOR_CONFIG_COUNT; i++) { + if (g_behavior_configs[i].behavior == behavior) { + return &g_behavior_configs[i]; + } + } + return NULL; +} diff --git a/User/module/cmd_v2/cmd_behavior.h b/User/module/cmd_v2/cmd_behavior.h new file mode 100644 index 0000000..049cb7e --- /dev/null +++ b/User/module/cmd_v2/cmd_behavior.h @@ -0,0 +1,69 @@ +/* + * CMD 模块 V2 - 行为处理器 + * 实现PC端按键到行为的映射和处理 + */ +#pragma once + +#include "cmd_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* ========================================================================== */ +/* 行为处理器接口 */ +/* ========================================================================== */ + +/* 行为处理函数类型 */ +struct CMD_Context; /* 前向声明 */ +typedef int8_t (*CMD_BehaviorHandler)(struct CMD_Context *ctx); + +/* 行为配置项 */ +typedef struct { + CMD_Behavior_t behavior; /* 行为枚举 */ + uint8_t key; /* 绑定的按键 */ + CMD_TriggerType_t trigger; /* 触发类型 */ + CMD_ModuleMask_t module_mask; /* 影响的模块 */ + CMD_BehaviorHandler handler; /* 处理函数 */ +} CMD_BehaviorConfig_t; + +/* ========================================================================== */ +/* 行为表生成宏 */ +/* ========================================================================== */ + +/* 从宏表生成配置数组 */ +#define BUILD_BEHAVIOR_CONFIG(name, key, trigger, mask) \ + { CMD_BEHAVIOR_##name, key, trigger, mask, CMD_Behavior_Handle_##name }, + +/* 声明所有行为处理函数 */ +#define DECLARE_BEHAVIOR_HANDLER(name, key, trigger, mask) \ + int8_t CMD_Behavior_Handle_##name(struct CMD_Context *ctx); + +/* 展开声明 */ +CMD_BEHAVIOR_TABLE(DECLARE_BEHAVIOR_HANDLER) +#undef DECLARE_BEHAVIOR_HANDLER + +/* ========================================================================== */ +/* 行为处理器API */ +/* ========================================================================== */ + +/* 初始化行为处理器 */ +int8_t CMD_Behavior_Init(void); + +/* 检查行为是否被触发 */ +bool CMD_Behavior_IsTriggered(const CMD_RawInput_t *current, + const CMD_RawInput_t *last, + const CMD_BehaviorConfig_t *config); + +/* 处理所有触发的行为 */ +int8_t CMD_Behavior_ProcessAll(struct CMD_Context *ctx, + const CMD_RawInput_t *current, + const CMD_RawInput_t *last, + CMD_ModuleMask_t active_modules); + +/* 获取行为配置 */ +const CMD_BehaviorConfig_t* CMD_Behavior_GetConfig(CMD_Behavior_t behavior); + +#ifdef __cplusplus +} +#endif diff --git a/User/module/cmd_v2/cmd_example.c b/User/module/cmd_v2/cmd_example.c new file mode 100644 index 0000000..4779c56 --- /dev/null +++ b/User/module/cmd_v2/cmd_example.c @@ -0,0 +1,153 @@ +/* + * CMD 模块 V2 - 使用示例和配置模板 + * + * 本文件展示如何配置和使用新的CMD模块 + */ +#include "cmd.h" + +/* ========================================================================== */ +/* 配置示例 */ +/* ========================================================================== */ + +/* 默认配置 */ +static CMD_Config_t g_cmd_config = { + /* 输入源优先级:RC > PC > NUC > REF */ + .source_priority = { + CMD_SRC_RC, + CMD_SRC_PC, + CMD_SRC_NUC, + CMD_SRC_REF, + }, + + /* 灵敏度设置 */ + .sensitivity = { + .mouse_sens = 0.8f, + .move_sens = 1.0f, + .move_fast_mult = 1.5f, + .move_slow_mult = 0.5f, + }, + + /* RC拨杆模式映射 */ + .rc_mode_map = { + /* 左拨杆控制底盘模式 */ + .sw_left_up = CHASSIS_MODE_BREAK, + .sw_left_mid = CHASSIS_MODE_FOLLOW_GIMBAL, + .sw_left_down = CHASSIS_MODE_ROTOR, + + /* 用于云台模式 */ + .gimbal_sw_up = GIMBAL_MODE_ABSOLUTE, + .gimbal_sw_mid = GIMBAL_MODE_ABSOLUTE, + .gimbal_sw_down = GIMBAL_MODE_RELATIVE, + }, + + .enable_pc_input = true, +}; + +/* CMD上下文 */ +static CMD_Context_t g_cmd_ctx; + +/* ========================================================================== */ +/* 任务示例 */ +/* ========================================================================== */ + +/* + * 初始化示例 + */ +void Example_CMD_Init(void) { + CMD_Init(&g_cmd_ctx, &g_cmd_config); +} + +/* + * 任务循环示例 + */ +void Example_CMD_Task(void) { + /* 一键更新 */ + CMD_Update(&g_cmd_ctx); + + /* 获取命令发送到各模块 */ + Chassis_CMD_t *chassis_cmd = CMD_GetChassisCmd(&g_cmd_ctx); + Gimbal_CMD_t *gimbal_cmd = CMD_GetGimbalCmd(&g_cmd_ctx); + Shoot_CMD_t *shoot_cmd = CMD_GetShootCmd(&g_cmd_ctx); + + /* 使用命令... */ + (void)chassis_cmd; + (void)gimbal_cmd; + (void)shoot_cmd; +} + +/* ========================================================================== */ +/* 架构说明 */ +/* ========================================================================== */ + +/* + * ## 新架构优势 + * + * ### 1. 统一的输入抽象层 (CMD_RawInput_t) + * - 所有设备(DR16/AT9S/VT13等)都转换成相同格式 + * - 上层代码无需关心具体设备类型 + * - 添加新设备只需实现适配器,不改动主逻辑 + * + * ### 2. 适配器模式 + * - 每个设备一个适配器文件 + * - 实现 Init, GetInput, IsOnline 三个函数 + * - 通过宏选择编译哪个适配器 + * + * ### 3. X-Macro配置表 + * - CMD_INPUT_SOURCE_TABLE: 配置输入源 + * - CMD_OUTPUT_MODULE_TABLE: 配置输出模块 + * - CMD_BEHAVIOR_TABLE: 配置按键行为映射 + * - 编译时生成枚举、配置数组、处理函数 + * + * ### 4. 行为驱动设计 + * - 行为与按键解耦 + * - 运行时可修改映射 + * - 支持边沿触发和持续触发 + * + * ### 5. 清晰的分层 + * + * ┌──────────────────────────────────────┐ + * │ 应用层 (cmd.c) │ + * │ - CMD_Update() │ + * │ - 仲裁、命令生成 │ + * └──────────────┬───────────────────────┘ + * │ + * ┌──────────────▼───────────────────────┐ + * │ 行为处理层 (cmd_behavior.c) │ + * │ - 按键触发检测 │ + * │ - 行为函数调用 │ + * └──────────────┬───────────────────────┘ + * │ + * ┌──────────────▼───────────────────────┐ + * │ 抽象输入层 (cmd_types.h) │ + * │ - CMD_RawInput_t │ + * │ - 统一的摇杆、开关、键鼠结构 │ + * └──────────────┬───────────────────────┘ + * │ + * ┌──────────────▼───────────────────────┐ + * │ 适配器层 (cmd_adapter.c) │ + * │ - DR16_Adapter │ + * │ - AT9S_Adapter │ + * │ - 设备数据 → CMD_RawInput_t │ + * └──────────────────────────────────────┘ + * + * ## 扩展指南 + * + * ### 添加新遥控器设备 + * 1. 在 cmd_adapter.h 中添加宏定义选项 + * 2. 在 cmd_adapter.c 中实现三个适配器函数 + * 3. 修改 CMD_RC_DEVICE_TYPE 宏选择新设备 + * + * ### 添加新输入源(如自定义协议) + * 1. 在 CMD_INPUT_SOURCE_TABLE 添加条目 + * 2. 实现对应的适配器 + * 3. 在 CMD_GenerateCommands 添加处理分支 + * + * ### 添加新行为 + * 1. 在 CMD_BEHAVIOR_TABLE 添加条目 + * 2. 实现 CMD_Behavior_Handle_XXX 函数 + * + * ### 添加新输出模块 + * 1. 在 CMD_OUTPUT_MODULE_TABLE 添加条目 + * 2. 在 CMD_Context_t 中添加输出成员 + * 3. 实现对应的 BuildXXXCmd 函数 + */ diff --git a/User/module/cmd_v2/cmd_types.h b/User/module/cmd_v2/cmd_types.h new file mode 100644 index 0000000..ff1646f --- /dev/null +++ b/User/module/cmd_v2/cmd_types.h @@ -0,0 +1,177 @@ +/* + * CMD 模块 V2 - 类型定义 + * 统一的输入/输出抽象层 + */ +#pragma once + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* ========================================================================== */ +/* 错误码定义 */ +/* ========================================================================== */ +#define CMD_OK (0) +#define CMD_ERR_NULL (-1) +#define CMD_ERR_MODE (-2) +#define CMD_ERR_SOURCE (-3) +#define CMD_ERR_NO_INPUT (-4) + +/* ========================================================================== */ +/* 输入源配置宏表 */ +/* ========================================================================== */ +/* + * 使用方法:在config中定义需要启用的输入源 + * 格式: X(枚举名, 优先级, 适配器初始化函数, 获取数据函数) + */ +#define CMD_INPUT_SOURCE_TABLE(X) \ + X(RC, 0, CMD_RC_AdapterInit, CMD_RC_GetInput) \ + X(PC, 1, CMD_PC_AdapterInit, CMD_PC_GetInput) \ + X(NUC, 2, CMD_NUC_AdapterInit, CMD_NUC_GetInput) \ + X(REF, 3, CMD_REF_AdapterInit, CMD_REF_GetInput) + +/* 输出模块配置宏表 */ +#define CMD_OUTPUT_MODULE_TABLE(X) \ + X(CHASSIS, Chassis_CMD_t, chassis) \ + X(GIMBAL, Gimbal_CMD_t, gimbal) \ + X(SHOOT, Shoot_CMD_t, shoot) + +/* ========================================================================== */ +/* 统一输入数据结构 */ +/* ========================================================================== */ + +/* 摇杆数据 - 统一为-1.0 ~ 1.0 */ +typedef struct { + float x; + float y; +} CMD_Joystick_t; + +/* 开关位置 */ +typedef enum { + CMD_SW_ERR = 0, + CMD_SW_UP, + CMD_SW_MID, + CMD_SW_DOWN, +} CMD_SwitchPos_t; + +/* 鼠标数据 */ +typedef struct { + int16_t x; /* 鼠标X轴移动速度 */ + int16_t y; /* 鼠标Y轴移动速度 */ + int16_t z; /* 鼠标滚轮 */ + bool l_click; /* 左键 */ + bool r_click; /* 右键 */ + bool m_click; /* 中键 */ +} CMD_Mouse_t; + +/* 键盘数据 - 最多支持32个按键 */ +typedef struct { + uint32_t bitmap; /* 按键位图 */ +} CMD_Keyboard_t; + +/* 键盘按键索引 */ +typedef enum { + CMD_KEY_W = 0, CMD_KEY_S, CMD_KEY_A, CMD_KEY_D, + CMD_KEY_SHIFT, CMD_KEY_CTRL, CMD_KEY_Q, CMD_KEY_E, + CMD_KEY_R, CMD_KEY_F, CMD_KEY_G, CMD_KEY_Z, + CMD_KEY_X, CMD_KEY_C, CMD_KEY_V, CMD_KEY_B, + CMD_KEY_NUM +} CMD_KeyIndex_t; + +/* 裁判系统数据 */ +typedef struct { + uint8_t game_status; /* 比赛状态 */ +} CMD_Referee_t; + +/* 统一的原始输入结构 - 所有设备适配后都转换成这个格式 */ +typedef struct { + bool online; + + /* 遥控器部分 */ + CMD_Joystick_t joy_left; /* 左摇杆 */ + CMD_Joystick_t joy_right; /* 右摇杆 */ + CMD_SwitchPos_t sw[4]; /* 最多4个拨杆 */ + float dial; /* 拨轮 */ + + /* PC部分 */ + CMD_Mouse_t mouse; + CMD_Keyboard_t keyboard; + + /* NUC部分 */ + /* 暂无定义,预留扩展 */ + + /* REF部分 - 裁判系统数据 */ + CMD_Referee_t referee; +} CMD_RawInput_t; + +/* ========================================================================== */ +/* 输入源枚举 */ +/* ========================================================================== */ +#define ENUM_INPUT_SOURCE(name, ...) CMD_SRC_##name, +typedef enum { + CMD_INPUT_SOURCE_TABLE(ENUM_INPUT_SOURCE) + CMD_SRC_NUM +} CMD_InputSource_t; +#undef ENUM_INPUT_SOURCE + +/* ========================================================================== */ +/* 模块掩码 */ +/* ========================================================================== */ +typedef enum { + CMD_MODULE_NONE = 0, + CMD_MODULE_CHASSIS = (1 << 0), + CMD_MODULE_GIMBAL = (1 << 1), + CMD_MODULE_SHOOT = (1 << 2), + CMD_MODULE_ALL = 0x07 +} CMD_ModuleMask_t; + +/* ========================================================================== */ +/* 行为定义 */ +/* ========================================================================== */ +/* 行为-按键映射宏表 */ +#define CMD_BEHAVIOR_TABLE(X) \ + X(FORE, CMD_KEY_W, CMD_ACTIVE_PRESSED, CMD_MODULE_CHASSIS) \ + X(BACK, CMD_KEY_S, CMD_ACTIVE_PRESSED, CMD_MODULE_CHASSIS) \ + X(LEFT, CMD_KEY_A, CMD_ACTIVE_PRESSED, CMD_MODULE_CHASSIS) \ + X(RIGHT, CMD_KEY_D, CMD_ACTIVE_PRESSED, CMD_MODULE_CHASSIS) \ + X(ACCELERATE, CMD_KEY_SHIFT, CMD_ACTIVE_PRESSED, CMD_MODULE_CHASSIS) \ + X(DECELERATE, CMD_KEY_CTRL, CMD_ACTIVE_PRESSED, CMD_MODULE_CHASSIS) \ + X(FIRE, CMD_KEY_NONE, CMD_ACTIVE_PRESSED, CMD_MODULE_SHOOT) \ + X(FIRE_MODE, CMD_KEY_B, CMD_ACTIVE_RISING_EDGE, CMD_MODULE_SHOOT) \ + X(ROTOR, CMD_KEY_E, CMD_ACTIVE_RISING_EDGE, CMD_MODULE_CHASSIS) \ + X(AUTOAIM, CMD_KEY_R, CMD_ACTIVE_RISING_EDGE, CMD_MODULE_GIMBAL | CMD_MODULE_SHOOT) + +/* 触发类型 */ +typedef enum { + CMD_ACTIVE_PRESSED, /* 按住时触发 */ + CMD_ACTIVE_RISING_EDGE, /* 按下瞬间触发 */ + CMD_ACTIVE_FALLING_EDGE, /* 松开瞬间触发 */ +} CMD_TriggerType_t; + +/* 特殊按键值 */ +#define CMD_KEY_NONE 0xFF +#define CMD_KEY_L_CLICK 0xFE +#define CMD_KEY_R_CLICK 0xFD +#define CMD_KEY_M_CLICK 0xFC + +/* 行为枚举 - 由宏表自动生成 */ +#define ENUM_BEHAVIOR(name, key, trigger, mask) CMD_BEHAVIOR_##name, +typedef enum { + CMD_BEHAVIOR_TABLE(ENUM_BEHAVIOR) + CMD_BEHAVIOR_NUM +} CMD_Behavior_t; +#undef ENUM_BEHAVIOR + +/* ========================================================================== */ +/* 键盘辅助宏 */ +/* ========================================================================== */ +#define CMD_KEY_PRESSED(kb, key) (((kb)->bitmap >> (key)) & 1) +#define CMD_KEY_SET(kb, key) ((kb)->bitmap |= (1 << (key))) +#define CMD_KEY_CLEAR(kb, key) ((kb)->bitmap &= ~(1 << (key))) + +#ifdef __cplusplus +} +#endif From f1a40995544256abe8151f71e232affdc3430c04 Mon Sep 17 00:00:00 2001 From: yxming66 <2389287465@qq.com> Date: Wed, 17 Dec 2025 01:37:22 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E6=96=B0cmd=E5=A5=BD=E4=BD=BF=E4=BA=86?= =?UTF-8?q?=EF=BC=8C=E7=8E=B0=E5=9C=A8=E5=BC=80=E5=A7=8B=E4=BC=98=E5=8C=96?= =?UTF-8?q?input?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 4 +- User/device/dr16.h | 3 +- User/device/vt13.h | 3 +- User/module/cmd.c | 703 ------------------------------ User/module/cmd.h | 236 ---------- User/module/cmd_v2/cmd.c | 38 +- User/module/cmd_v2/cmd.h | 20 +- User/module/cmd_v2/cmd_adapter.c | 12 +- User/module/cmd_v2/cmd_behavior.c | 22 +- User/module/cmd_v2/cmd_example.c | 15 +- User/module/cmd_v2/cmd_types.h | 10 +- User/module/config.c | 75 ++-- User/module/config.h | 4 +- User/task/cmd.c | 31 +- 14 files changed, 122 insertions(+), 1054 deletions(-) delete mode 100644 User/module/cmd.c delete mode 100644 User/module/cmd.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 342d8b5..993ec50 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,7 +41,7 @@ add_subdirectory(cmake/stm32cubemx) target_link_directories(${CMAKE_PROJECT_NAME} PRIVATE # Add user defined library search paths ) - +file(GLOB SINGLE_CHAR_FILES "User/module/cmd_v2/*.c") # Add sources to executable target_sources(${CMAKE_PROJECT_NAME} PRIVATE # Add user sources here @@ -77,7 +77,7 @@ target_sources(${CMAKE_PROJECT_NAME} PRIVATE User/module/config.c User/module/gimbal.c User/module/shoot.c - User/module/cmd.c + ${SINGLE_CHAR_FILES} # User/task sources User/task/atti_esti.c User/task/blink.c diff --git a/User/device/dr16.h b/User/device/dr16.h index 74588ac..5d42dc9 100644 --- a/User/device/dr16.h +++ b/User/device/dr16.h @@ -88,9 +88,8 @@ typedef struct{ bool r_click; /* 右键 */ } mouse; /* 鼠标值 */ - union { + struct { bool key[DR16_KEY_NUM]; /* 键盘按键值 */ - uint16_t value; /* 键盘按键值的位映射 */ } keyboard; }DR16_DataPC_t; typedef struct { diff --git a/User/device/vt13.h b/User/device/vt13.h index c450967..7b17635 100644 --- a/User/device/vt13.h +++ b/User/device/vt13.h @@ -100,9 +100,8 @@ typedef struct { bool r_click; /* 右键 */ } mouse; /* 鼠标值 */ - union { + struct { bool key[VT13_KEY_NUM]; /* 键盘按键值 */ - uint16_t value; /* 键盘按键值的位映射 */ } keyboard; uint16_t res; /* 保留,未启用 */ diff --git a/User/module/cmd.c b/User/module/cmd.c deleted file mode 100644 index 8769d15..0000000 --- a/User/module/cmd.c +++ /dev/null @@ -1,703 +0,0 @@ -/* - 控制命令 -*/ -#include "module/cmd.h" - -#include -#include -#include "bsp/time.h" -#include "module/gimbal.h" - -/*************************************************************************************************************************************/ -/****************************************************************RC*******************************************************************/ -/*************************************************************************************************************************************/ -/* Private macro ------------------------------------------------------------ */ -/* 声明外部rc数据变量 */ -#define CMDMACRO_EXTERNAL_RCDATA(name, NAME) extern NAME##_t name; - -#define CMDMACRO_NAME_EXPANSION_1(name, NAME) name -/* 声明CMD结构体的RC数据变量 */ -#define CMDMACRO_VAR_RCDATA(name, NAME) NAME##_DataRC_t name; -/* 宏生成Cmd_RC_Get函数内容 */ -#define CMDMACRO_Cmd_RC_Get(name, NAME) \ - c->input.rc.name= name.data.rc; \ - c->input.rc.online=name.header.online; \ - c->input.rc.type=CMD_RCTypeTable_Index; - -CMD_RCType_TABLE(CMDMACRO_EXTERNAL_RCDATA) -/* Private typedef ---------------------------------------------------------- */ -/* Private define ----------------------------------------------------------- */ - -/* Private variables -------------------------------------------------------- */ -/*静态缓冲区*/ - -/* Private function -------------------------------------------------------- */ -int8_t Cmd_RC_Get(CMD_t *c, CMD_RCType_TABLE(CMDMACRO_NAME_EXPANSION)){ - // bool online= dr16->header.online; - // rc_buffer.dr16=dr16->data.rc; - // c->input.rc.online=online; - // c->input.rc.type=CMD_RCTypeTable_Index; - CMD_RCType_TABLE(CMDMACRO_Cmd_RC_Get); - return CMD_OK; -} - -int8_t Cmd_RC_BuildChassisCommandFromInput(CMD_t *c) { - if (c == NULL) { - return CMD_ERR_NULL; // 参数错误 - } -#if CMD_RCTypeTable_Index == 0 - switch (c->input.rc.dr16.sw_l) { - case DR16_SW_DOWN: - c->output.chassis.cmd.mode = CHASSIS_MODE_ROTOR; - break; - case DR16_SW_MID: - c->output.chassis.cmd.mode = CHASSIS_MODE_FOLLOW_GIMBAL; - break; - case DR16_SW_UP: - c->output.chassis.cmd.mode = CHASSIS_MODE_BREAK; - break; - default: - c->output.chassis.cmd.mode = CHASSIS_MODE_RELAX; - break; - } - c->output.chassis.cmd.ctrl_vec.vx = c->input.rc.dr16.ch_r_x; - c->output.chassis.cmd.ctrl_vec.vy = c->input.rc.dr16.ch_r_y; -#elif CMD_RCTypeTable_Index == 1 - switch (c->input.rc.data->at9s.key_E) { - case AT9S_CMD_SW_DOWN: - c->output.chassis.cmd.mode = CHASSIS_MODE_RELAX; - break; - case AT9S_CMD_SW_MID: - c->output.chassis.cmd.mode = CHASSIS_MODE_FOLLOW_GIMBAL; - break; - case AT9S_CMD_SW_UP: - c->output.chassis.cmd.mode = CHASSIS_MODE_ROTOR; - break; - default: - c->output.chassis.cmd.mode = CHASSIS_MODE_RELAX; - break; - } - c->output.chassis.cmd.ctrl_vec.vx = c->input.rc.data->at9s.ch_r_x; - c->output.chassis.cmd.ctrl_vec.vy = c->input.rc.data->at9s.ch_r_y; -#endif - return CMD_OK; -} - -int8_t Cmd_RC_BuildGimbalCommandFromInput(CMD_t *c) { - if (c == NULL) { - return CMD_ERR_NULL; // 参数错误 - } -#if CMD_RCTypeTable_Index == 0 - switch (c->input.rc.dr16.sw_l) { - case DR16_SW_DOWN: - c->output.gimbal.cmd.mode = GIMBAL_MODE_RELATIVE; - c->output.gimbal.cmd.delta_yaw = -c->input.rc.dr16.ch_l_x * 2.0f; - c->output.gimbal.cmd.delta_pit = -c->input.rc.dr16.ch_l_y * 1.5f; - break; - case DR16_SW_MID: - c->output.gimbal.cmd.mode = GIMBAL_MODE_ABSOLUTE; - c->output.gimbal.cmd.delta_yaw = -c->input.rc.dr16.ch_l_x * 2.0f; - c->output.gimbal.cmd.delta_pit = -c->input.rc.dr16.ch_l_y * 1.5f; - break; - case DR16_SW_UP: - c->output.gimbal.cmd.mode = GIMBAL_MODE_ABSOLUTE; - c->output.gimbal.cmd.delta_yaw = -c->input.rc.dr16.ch_l_x * 2.0f; - c->output.gimbal.cmd.delta_pit = -c->input.rc.dr16.ch_l_y * 1.5f; - break; - default: - c->output.gimbal.cmd.mode = GIMBAL_MODE_RELAX; - c->output.gimbal.cmd.delta_yaw = 0.0f; - c->output.gimbal.cmd.delta_pit = 0.0f; - break; - } -#elif CMD_RCTypeTable_Index == 1 - switch (c->input.rc.data->at9s.key_G) { - case AT9S_CMD_SW_DOWN: - c->output.gimbal.cmd.mode = GIMBAL_MODE_RELAX; - c->output.gimbal.cmd.delta_yaw = 0.0f; - c->output.gimbal.cmd.delta_pit = 0.0f; - break; - case AT9S_CMD_SW_MID: - c->output.gimbal.cmd.mode = GIMBAL_MODE_ABSOLUTE; - c->output.gimbal.cmd.delta_yaw = -c->input.rc.data->at9s.ch_l_x * 2.0f; - c->output.gimbal.cmd.delta_pit = -c->input.rc.data->at9s.ch_l_y * 1.5f; - break; - case AT9S_CMD_SW_UP: - c->output.gimbal.cmd.mode = GIMBAL_MODE_ABSOLUTE; - c->output.gimbal.cmd.delta_yaw = -c->input.rc.data->at9s.ch_l_x * 2.0f; - c->output.gimbal.cmd.delta_pit = -c->input.rc.data->at9s.ch_l_y * 1.5f; - break; - default: - c->output.gimbal.cmd.mode = GIMBAL_MODE_RELAX; - c->output.gimbal.cmd.delta_yaw = 0.0f; - c->output.gimbal.cmd.delta_pit = 0.0f; - break; - } -#endif - return CMD_OK; -} - - -int8_t Cmd_RC_BuildShootCommandFromInput(CMD_t *c) { - if (c == NULL) { - return CMD_ERR_NULL; // 参数错误 - } -#if CMD_RCTypeTable_Index == 0 - if (c->input.rc.online) { - c->output.shoot.cmd.mode=SHOOT_MODE_SINGLE; - } else { - c->output.shoot.cmd.mode=SHOOT_MODE_SAFE; - } - switch (c->input.rc.dr16.sw_r) { - case DR16_SW_DOWN: - c->output.shoot.cmd.ready = true; - c->output.shoot.cmd.firecmd = true; - break; - case DR16_SW_MID: - c->output.shoot.cmd.ready = true; - c->output.shoot.cmd.firecmd = false; - break; - case DR16_SW_UP: - c->output.shoot.cmd.ready = false; - c->output.shoot.cmd.firecmd = false; - break; - default: - c->output.shoot.cmd.ready = false; - c->output.shoot.cmd.firecmd = false; - break; - } -#elif CMD_RCTypeTable_Index == 1 - c->output.shoot.cmd.online = c->input.rc.online; - switch (c->input.rc.data->at9s.key_C) { - case AT9S_CMD_SW_DOWN: - c->output.shoot.cmd.ready = true; - c->output.shoot.cmd.firecmd = true; - break; - case AT9S_CMD_SW_MID: - c->output.shoot.cmd.ready = true; - c->output.shoot.cmd.firecmd = false; - break; - case AT9S_CMD_SW_UP: - c->output.shoot.cmd.ready = false; - c->output.shoot.cmd.firecmd = false; - break; - default: - c->output.shoot.cmd.ready = false; - c->output.shoot.cmd.firecmd = false; - break; - } - switch (c->input.rc.data->at9s.key_D) { - case AT9S_CMD_SW_DOWN: - c->output.shoot.cmd.mode=SHOOT_MODE_SINGLE; - break; - case AT9S_CMD_SW_UP: - c->output.shoot.cmd.mode=SHOOT_MODE_BURST; - break; - default: - c->output.shoot.cmd.mode=SHOOT_MODE_SAFE; - break; - } -#endif - return CMD_OK; -} -/* Exported functions ------------------------------------------------------- */ - - -/*************************************************************************************************************************************/ -/*****************************************************************PC******************************************************************/ -/*************************************************************************************************************************************/ -#ifndef CMD_NOPC_FLAG -/* Private macro ------------------------------------------------------------ */ -#define CMD_PCBehavior_TABLE(X) \ - X(FORE, CMD_MODULE_CHASSIS) \ - X(BACK, CMD_MODULE_CHASSIS) \ - X(LEFT, CMD_MODULE_CHASSIS) \ - X(RIGHT, CMD_MODULE_CHASSIS) \ - X(ACCELERATE, CMD_MODULE_CHASSIS) \ - X(DECELEBRATE, CMD_MODULE_CHASSIS) \ - X(FIRE, CMD_MODULE_SHOOT) \ - X(FIRE_MODE, CMD_MODULE_SHOOT) \ - X(BUFF, CMD_MODULE_SHOOT) \ - X(AUTOAIM, CMD_MODULE_GIMBAL | CMD_MODULE_SHOOT) \ - X(OPENCOVER, CMD_MODULE_SHOOT) \ - X(ROTOR, CMD_MODULE_CHASSIS) \ - X(REVTRIG, CMD_MODULE_SHOOT) \ - X(FOLLOWGIMBAL35, CMD_MODULE_CHASSIS) \ - X(GIMBAL_MODE, CMD_MODULE_GIMBAL) - -/* 行为处理函数声明宏 */ -#define CMDMACRO_FOR_DECLARE_BEHAVIOR_HANDLER_FUNCTION(BEHAVIOR, MODULE_MASK) \ - static int8_t Cmd_PC_HandleBehavior##BEHAVIOR(CMD_t *c); -/* 行为处理函数指针数组构建宏 */ -#define CMDMACRO_FOR_BUILD_BEHAVIOR_HANDLER_ARRAY(BEHAVIOR, MODULE_MASK) \ - {CMD_BEHAVIOR_##BEHAVIOR, Cmd_PC_HandleBehavior##BEHAVIOR}, -/* 行为模块映射表构建宏 */ -#define CMDMACRO_FOR_BUILD_MODULE_TABLE(BEHAVIOR, MODULE_MASK) \ - [CMD_BEHAVIOR_##BEHAVIOR] = MODULE_MASK, -/* 行为处理函数声明 */ -CMD_PCBehavior_TABLE(CMDMACRO_FOR_DECLARE_BEHAVIOR_HANDLER_FUNCTION) - -/* 宏展开函数内容 */ -#define CMDMACRO_Cmd_PC_Get(name, NAME) \ - c->input.pc.online=name.header.online;\ - c->input.pc.name= name.data.pc; -#define CMDMACRO_PC_IsBehaviorTriggered(name, NAME) \ - CMD_PCValue_t value = CMD_PC_BehaviorToValue(c, behavior); \ - CMD_TriggerType_t active = CMD_PC_BehaviorToActive(c, behavior); \ - bool now_key_pressed, last_key_pressed; \ - /* 按下按键为鼠标左、右键 */ \ - if (value == CMD_L_CLICK) { \ - now_key_pressed = c->input.pc.name.mouse.l_click; \ - last_key_pressed = c->input.pc.last##name.mouse.l_click; \ - } else if (value == CMD_R_CLICK) { \ - now_key_pressed = c->input.pc.name.mouse.r_click; \ - last_key_pressed = c->input.pc.last##name.mouse.r_click; \ - } else { \ - now_key_pressed = c->input.pc.name.keyboard.key[value]; \ - last_key_pressed = c->input.pc.last##name.keyboard.key[value]; \ - } \ - switch (active) { \ - case CMD_ACTIVE_RISING_EDGE: \ - return !now_key_pressed && last_key_pressed; \ - case CMD_ACTIVE_FALLING_EDGE: \ - return now_key_pressed && !last_key_pressed; \ - case CMD_ACTIVE_PRESSED: \ - return now_key_pressed; \ - } \ - return false; -#define CMDMACRO_PC_BuildChassisCommandFromInput(name, NAME) \ - if (c->input.pc.online) {c->output.chassis.cmd.mode = CHASSIS_MODE_FOLLOW_GIMBAL;} \ - else {c->output.chassis.cmd.mode = CHASSIS_MODE_RELAX;} \ - c->output.chassis.cmd.ctrl_vec.vx = 0.0f; \ - c->output.chassis.cmd.ctrl_vec.vy = 0.0f; \ - for (size_t i = 0; i < CMD_BEHAVIOR_NUM; i++) { \ - CMD_ModuleMask_t moduleMask = behaviorModuleTable[i]; \ - if (CMD_PC_IsMaskMatch(c, moduleMask)) { \ - if (CMD_PC_IsBehaviorTriggered(c, i)) { \ - behaviorHandlerFuncTable[i].func(c); \ - } \ - } \ - }\ - return CMD_OK; -#define CMDMACRO_PC_BuildGimbalCommandFromInput(name, NAME) \ - static bool init = false; \ - if (!init) {c->output.gimbal.cmd.mode = GIMBAL_MODE_ABSOLUTE;init=!init;}\ - if(!c->input.pc.online) {c->output.gimbal.cmd.mode = GIMBAL_MODE_RELAX;} \ - c->output.gimbal.cmd.delta_yaw = (float)-c->input.pc.name.mouse.x * c->timer.dt * c->params->pc.sensitivity.sens_mouse; \ - c->output.gimbal.cmd.delta_pit = (float)1.5f*c->input.pc.name.mouse.y * c->timer.dt * c->params->pc.sensitivity.sens_mouse; \ - for (size_t i = 0; i < CMD_BEHAVIOR_NUM; i++) { \ - CMD_ModuleMask_t moduleMask = behaviorModuleTable[i]; \ - if (CMD_PC_IsMaskMatch(c, moduleMask)) { \ - if (CMD_PC_IsBehaviorTriggered(c, i)) { \ - behaviorHandlerFuncTable[i].func(c); \ - } \ - } \ - }\ - return CMD_OK; -#define CMDMACRO_PC_BuildShootCommandFromInput(name, NAME) \ - if (!c->input.pc.online) {c->output.shoot.cmd.mode = SHOOT_MODE_SAFE;} \ - c->output.shoot.cmd.ready = true; \ - c->output.shoot.cmd.firecmd = false; \ - for (size_t i = 0; i < CMD_BEHAVIOR_NUM; i++) { \ - CMD_ModuleMask_t moduleMask = behaviorModuleTable[i]; \ - if (CMD_PC_IsMaskMatch(c, moduleMask)) { \ - if (CMD_PC_IsBehaviorTriggered(c, i)) { \ - behaviorHandlerFuncTable[i].func(c); \ - } \ - } \ - } \ - return CMD_OK;\ - memcpy(c->input.pc.last##name.keyboard.key, c->input.pc.name.keyboard.key, sizeof(c->input.pc.name.keyboard.key)); \ - c->input.pc.last##name.mouse.l_click = c->input.pc.name.mouse.l_click; \ - c->input.pc.last##name.mouse.r_click = c->input.pc.name.mouse.r_click; -/* Private typedef ---------------------------------------------------------- */ -typedef int8_t (*CMD_BehaviorFunc)(CMD_t *c); -typedef struct { - CMD_Behavior_t behavior; - CMD_BehaviorFunc func; -} CMD_BehaviorHandlerFunc_t; - -/* Private variables -------------------------------------------------------- */ -/* 行为处理函数指针数组 */ -CMD_BehaviorHandlerFunc_t behaviorHandlerFuncTable[CMD_BEHAVIOR_NUM] = { - CMD_PCBehavior_TABLE(CMDMACRO_FOR_BUILD_BEHAVIOR_HANDLER_ARRAY) -}; -/* 行为模块映射表 */ -static const CMD_ModuleMask_t behaviorModuleTable[CMD_BEHAVIOR_NUM] = { - CMD_PCBehavior_TABLE(CMDMACRO_FOR_BUILD_MODULE_TABLE) -}; -/* Private function -------------------------------------------------------- */ -int8_t Cmd_PC_Get(CMD_t *c, CMD_RCType_TABLE(CMDMACRO_NAME_EXPANSION)){ - CMD_RCType_TABLE(CMDMACRO_Cmd_PC_Get); - return CMD_OK; -} - -static int8_t Cmd_PC_HandleBehaviorFORE(CMD_t *c){ - c->output.chassis.cmd.ctrl_vec.vy += c->params->pc.sensitivity.move_sense; - return CMD_OK; -} -static int8_t Cmd_PC_HandleBehaviorBACK(CMD_t *c){ - c->output.chassis.cmd.ctrl_vec.vy -= c->params->pc.sensitivity.move_sense; - return CMD_OK; -} -static int8_t Cmd_PC_HandleBehaviorLEFT(CMD_t *c){ - c->output.chassis.cmd.ctrl_vec.vx -= c->params->pc.sensitivity.move_sense; - return CMD_OK; -} -static int8_t Cmd_PC_HandleBehaviorRIGHT(CMD_t *c){ - c->output.chassis.cmd.ctrl_vec.vx += c->params->pc.sensitivity.move_sense; - return CMD_OK; -} -static int8_t Cmd_PC_HandleBehaviorACCELERATE(CMD_t *c){ - c->output.chassis.cmd.ctrl_vec.vx *= c->params->pc.sensitivity.move_fast_sense; - c->output.chassis.cmd.ctrl_vec.vy *= c->params->pc.sensitivity.move_fast_sense; - return CMD_OK; -} -static int8_t Cmd_PC_HandleBehaviorDECELEBRATE(CMD_t *c){ - c->output.chassis.cmd.ctrl_vec.vx *= c->params->pc.sensitivity.move_slow_sense; - c->output.chassis.cmd.ctrl_vec.vy *= c->params->pc.sensitivity.move_slow_sense; - return CMD_OK; -} -static int8_t Cmd_PC_HandleBehaviorFIRE(CMD_t *c){ - c->output.shoot.cmd.firecmd = true; - return CMD_OK; -} -static int8_t Cmd_PC_HandleBehaviorFIRE_MODE(CMD_t *c){ - c->output.shoot.cmd.mode++; - c->output.shoot.cmd.mode %= SHOOT_MODE_NUM; - return CMD_OK; -} -static int8_t Cmd_PC_HandleBehaviorBUFF(CMD_t *c){ -// if (cmd->ai_status == AI_STATUS_HITSWITCH) { -// CMD_RefereeAdd(&(cmd->referee), CMD_UI_HIT_SWITCH_STOP); -// cmd->host_overwrite = false; -// cmd->ai_status = AI_STATUS_STOP; -// } else if (cmd->ai_status == AI_STATUS_AUTOAIM) { -// // 自瞄模式中切换失败提醒 -// } else { -// CMD_RefereeAdd(&(cmd->referee), CMD_UI_HIT_SWITCH_START); -// cmd->ai_status = AI_STATUS_HITSWITCH; -// cmd->host_overwrite = true; -// } - return CMD_OK; -} -static int8_t Cmd_PC_HandleBehaviorAUTOAIM(CMD_t *c){ -// if (cmd->ai_status == AI_STATUS_AUTOAIM) { -// cmd->host_overwrite = false; -// cmd->ai_status = AI_STATUS_STOP; -// CMD_RefereeAdd(&(cmd->referee), CMD_UI_AUTO_AIM_STOP); -// } else { -// cmd->ai_status = AI_STATUS_AUTOAIM; -// cmd->host_overwrite = true; -// CMD_RefereeAdd(&(cmd->referee), CMD_UI_AUTO_AIM_START); -// } - return CMD_OK; -} -static int8_t Cmd_PC_HandleBehaviorOPENCOVER(CMD_t *c){ -// c->shoot.cover_open = !c->shoot.cover_open; - return CMD_OK; -} -static int8_t Cmd_PC_HandleBehaviorROTOR(CMD_t *c){ - c->output.chassis.cmd.mode = CHASSIS_MODE_ROTOR; - c->output.chassis.cmd.mode_rotor = ROTOR_MODE_RAND; - return CMD_OK; -} -static int8_t Cmd_PC_HandleBehaviorREVTRIG(CMD_t *c){ -// c->output.shoot.cmd.reverse_trig = true; - return CMD_OK; -} -static int8_t Cmd_PC_HandleBehaviorFOLLOWGIMBAL35(CMD_t *c){ - c->output.chassis.cmd.mode = CHASSIS_MODE_FOLLOW_GIMBAL_35; - return CMD_OK; -} -static int8_t Cmd_PC_HandleBehaviorGIMBAL_MODE(CMD_t *c){ - - c->output.gimbal.cmd.mode++; - c->output.gimbal.cmd.mode %= GIMBAL_MODE_NUM; - while (c->output.gimbal.cmd.mode<=0) {c->output.gimbal.cmd.mode++;} - return CMD_OK; -} - -static inline CMD_PCValue_t CMD_PC_BehaviorToValue(CMD_t *c, - CMD_Behavior_t behavior) { - return c->params->pc.map.key_map[behavior].key; -} - -static inline CMD_TriggerType_t CMD_PC_BehaviorToActive(CMD_t *c, - CMD_Behavior_t behavior) { - return c->params->pc.map.key_map[behavior].trigger_type; -} - -static inline bool CMD_PC_IsMaskMatch(CMD_t *c, CMD_ModuleMask_t module_mask) { - /* 构建当前各模块输入源状态的掩码 */ - CMD_ModuleMask_t current_pc_mask = 0; - if (c->output.chassis.source == CMD_SRC_PC) current_pc_mask |= CMD_MODULE_CHASSIS; - if (c->output.gimbal.source == CMD_SRC_PC) current_pc_mask |= CMD_MODULE_GIMBAL; - if (c->output.shoot.source == CMD_SRC_PC) current_pc_mask |= CMD_MODULE_SHOOT; - - /* 检测并集 */ - return (module_mask & current_pc_mask) == module_mask; - /* 检测交集 */ -// return (module_mask & current_pc_mask) != 0; -} - -static inline bool CMD_PC_IsBehaviorTriggered(CMD_t *c, CMD_Behavior_t behavior) { - if (c == NULL) { - return CMD_ERR_NULL; // 参数错误 - } - CMD_RCType_TABLE(CMDMACRO_PC_IsBehaviorTriggered); -} - -static int8_t Cmd_PC_BuildChassisCommandFromInput(CMD_t *c) { - if (c == NULL) { - return CMD_ERR_NULL; // 参数错误 - } - CMD_RCType_TABLE(CMDMACRO_PC_BuildChassisCommandFromInput); -} - -static int8_t Cmd_PC_BuildGimbalCommandFromInput(CMD_t *c) { - if (c == NULL) { - return CMD_ERR_NULL; // 参数错误 - } - CMD_RCType_TABLE(CMDMACRO_PC_BuildGimbalCommandFromInput); -} - -static int8_t Cmd_PC_BuildShootCommandFromInput(CMD_t *c) { - if (c == NULL) { - return CMD_ERR_NULL; // 参数错误 - } - CMD_RCType_TABLE(CMDMACRO_PC_BuildShootCommandFromInput); -} -#else -static int8_t Cmd_PC_Get(CMD_Input_PC_t *pc) { - pc->online=false; - return CMD_OK; -} -static int8_t Cmd_PC_BuildChassisCommandFromInput(CMD_t *c) { - if (c == NULL) { - return CMD_ERR_NULL; // 参数错误 - } - return CMD_OK; -} -static int8_t Cmd_PC_BuildGimbalCommandFromInput(CMD_t *c) { - if (c == NULL) { - return CMD_ERR_NULL; // 参数错误 - } - return CMD_OK; -} -static int8_t Cmd_PC_BuildShootCommandFromInput(CMD_t *c) { - if (c == NULL) { - return CMD_ERR_NULL; // 参数错误 - } - return CMD_OK; -} -#endif - -/*************************************************************************************************************************************/ -/****************************************************************NUC******************************************************************/ -/*************************************************************************************************************************************/ - -/* Includes ----------------------------------------------------------------- */ -/* Private typedef ---------------------------------------------------------- */ -/* Private define ----------------------------------------------------------- */ -/* Private macro ------------------------------------------------------------ */ -/* Private variables -------------------------------------------------------- */ -/* Private function -------------------------------------------------------- */ -int8_t Cmd_NUC_Get(CMD_Input_NUC_t *nuc) { - nuc->online=0; - return CMD_OK; -} -/* Exported functions ------------------------------------------------------- */ - -int8_t Cmd_NUC_BuildChassisCommandFromInput(CMD_t *c) { - if (c == NULL) { - return CMD_ERR_NULL; // 参数错误 - } - return CMD_OK; -} - -int8_t Cmd_NUC_BuildGimbalCommandFromInput(CMD_t *c) { - if (c == NULL) { - return CMD_ERR_NULL; // 参数错误 - } - return CMD_OK; -} -int8_t Cmd_NUC_BuildShootCommandFromInput(CMD_t *c) { - if (c == NULL) { - return CMD_ERR_NULL; // 参数错误 - } - return CMD_OK; -} - -/*************************************************************************************************************************************/ -/***************************************************************REF*******************************************************************/ -/*************************************************************************************************************************************/ - -/* Includes ----------------------------------------------------------------- */ -/* Private typedef ---------------------------------------------------------- */ -/* Private define ----------------------------------------------------------- */ -/* Private macro ------------------------------------------------------------ */ -/* Private variables -------------------------------------------------------- */ -/* Private function -------------------------------------------------------- */ -int8_t Cmd_REF_Get(CMD_Input_REF_t *nuc) { - nuc->online=0; - return CMD_OK; -} -/* Exported functions ------------------------------------------------------- */ - -int8_t Cmd_REF_BuildChassisCommandFromInput(CMD_t *c) { - if (c == NULL) { - return CMD_ERR_NULL; // 参数错误 - } - return CMD_OK; -} - -int8_t Cmd_REF_BuildGimbalCommandFromInput(CMD_t *c) { - if (c == NULL) { - return CMD_ERR_NULL; // 参数错误 - } - return CMD_OK; -} -int8_t Cmd_REF_BuildShootCommandFromInput(CMD_t *c) { - if (c == NULL) { - return CMD_ERR_NULL; // 参数错误 - } - return CMD_OK; -} -/*************************************************************************************************************************************/ -/***************************************************************仲裁器****************************************************************/ -/*************************************************************************************************************************************/ - -/* Includes ----------------------------------------------------------------- */ -/* Private typedef ---------------------------------------------------------- */ -/* Private define ----------------------------------------------------------- */ -/* Private macro ------------------------------------------------------------ */ -/* Private variables -------------------------------------------------------- */ -/* Private function -------------------------------------------------------- */ -static inline bool Cmd_isREFOnline(CMD_t *c){return c->input.ref.online;} -static inline bool Cmd_isNUCOnline(CMD_t *c){return c->input.nuc.online;} -static inline bool Cmd_isRCOnline(CMD_t *c){return c->input.rc.online;} -static inline bool Cmd_isPCOnline(CMD_t *c){return c->input.pc.online;} -CMD_InputSource_t Cmd_GetHighestPrioritySource(CMD_t *c) { - for (int i = 0; i < CMD_SRC_NUM; i++) { - CMD_InputSource_t source = c->params->sourcePriorityConfigs[i]; - switch (source) { - case CMD_SRC_REF: - if (Cmd_isREFOnline(c)) { - return CMD_SRC_REF; - } - break; - case CMD_SRC_NUC: - if (Cmd_isNUCOnline(c)) { - return CMD_SRC_NUC; - } - break; - case CMD_SRC_RC: - if (Cmd_isRCOnline(c)) { - return CMD_SRC_RC; - } - break; - case CMD_SRC_PC: - if (Cmd_isPCOnline(c)) { - return CMD_SRC_PC; - } - break; - case CMD_SRC_NUM: - return CMD_ERR_SOURCE; - } - } - return CMD_ERR_SOURCE; -} - -int8_t Cmd_Arbiter(CMD_t *c) { - if (c == NULL) { - return CMD_ERR_NULL; // 参数错误 - } - CMD_InputSource_t source = Cmd_GetHighestPrioritySource(c); - c->output.chassis.source = source; - c->output.gimbal.source = source; - c->output.shoot.source = source; - return CMD_OK; -} - -int8_t Cmd_Switch_RCorPC(CMD_t *c) { - if (c == NULL) { - return CMD_ERR_NULL; // 参数错误 - } - - return CMD_OK; -} - -/*************************************************************************************************************************************/ -/***************************************************************主结构*****************************************************************/ -/*************************************************************************************************************************************/ - -/* Includes ----------------------------------------------------------------- */ -/* Private typedef ---------------------------------------------------------- */ -typedef int8_t (*CMD_BuildCommandFunc)(CMD_t *c); -typedef struct { - CMD_InputSource_t source; - CMD_BuildCommandFunc chassisFunc; - CMD_BuildCommandFunc gimbalFunc; - CMD_BuildCommandFunc shootFunc; -} CMD_SourceHandler_t; -/* Private macro ------------------------------------------------------------ */ -/* Private variables -------------------------------------------------------- */ -CMD_SourceHandler_t sourceHandlers[CMD_SRC_NUM] = { - {CMD_SRC_RC, Cmd_RC_BuildChassisCommandFromInput, Cmd_RC_BuildGimbalCommandFromInput, Cmd_RC_BuildShootCommandFromInput}, - {CMD_SRC_PC, Cmd_PC_BuildChassisCommandFromInput, Cmd_PC_BuildGimbalCommandFromInput, Cmd_PC_BuildShootCommandFromInput}, - {CMD_SRC_NUC, Cmd_NUC_BuildChassisCommandFromInput, Cmd_NUC_BuildGimbalCommandFromInput, Cmd_NUC_BuildShootCommandFromInput}, - {CMD_SRC_REF, Cmd_REF_BuildChassisCommandFromInput, Cmd_REF_BuildGimbalCommandFromInput, Cmd_REF_BuildShootCommandFromInput}, -}; -/* Private function -------------------------------------------------------- */ -int8_t Cmd_OFFLINE(CMD_t *c) { - if (c == NULL) { - return CMD_ERR_NULL; // 参数错误 - } - c->output.chassis.cmd.mode =CHASSIS_MODE_RELAX; - c->output.gimbal.cmd.mode =GIMBAL_MODE_RELAX; - c->output.shoot.cmd.mode =SHOOT_MODE_SAFE; - return CMD_OK; -} -/* Exported functions ------------------------------------------------------- */ -int8_t Cmd_Init(CMD_t *c, CMD_Params_t *params) { - if (c == NULL || params == NULL) { - return CMD_ERR_NULL; // 参数错误 - } - c->params = params; - return CMD_OK; -} - -int8_t Cmd_Get(CMD_t *c, - CMD_RCType_TABLE(CMDMACRO_NAME_EXPANSION)){ - // CMD_Input_NUC_t *nuc, - // CMD_Input_REF_t *ref) { - if (c == NULL) { - return CMD_ERR_NULL; // 参数错误 - } - Cmd_RC_Get(c,CMD_RCType_TABLE(CMDMACRO_NAME_EXPANSION_1)); - Cmd_PC_Get(c,CMD_RCType_TABLE(CMDMACRO_NAME_EXPANSION_1)); - // Cmd_NUC_Get(&c->input.nuc); - // Cmd_REF_Get(&c->input.ref); - - return CMD_OK; -} - -int8_t Cmd_GenerateCommand(CMD_t *c) { - if (c == NULL) { - return CMD_ERR_NULL; // 参数错误 - } - Cmd_Arbiter(c); - - c->timer.now =BSP_TIME_Get_us() / 1000000.0f; - c->timer.dt =(BSP_TIME_Get_us() - c->timer.last) / 1000000.0f; - c->timer.last =BSP_TIME_Get_us(); - if (c->output.chassis.source >= CMD_SRC_NUM || c->output.gimbal.source >= CMD_SRC_NUM || c->output.shoot.source >= CMD_SRC_NUM) { - Cmd_OFFLINE(c); - return CMD_ERR_SOURCE; // 输入源错误 - } - sourceHandlers[c->output.chassis.source].chassisFunc(c); - sourceHandlers[c->output.gimbal.source].gimbalFunc(c); - sourceHandlers[c->output.shoot.source].shootFunc(c); - return CMD_OK; -} diff --git a/User/module/cmd.h b/User/module/cmd.h deleted file mode 100644 index 9757230..0000000 --- a/User/module/cmd.h +++ /dev/null @@ -1,236 +0,0 @@ -/* - 控制命令 -*/ -#pragma once - -#include -#ifdef __cplusplus -extern "C" { -#endif -/* Includes ----------------------------------------------------------------- */ -#include "module/chassis.h" -#include "module/gimbal.h" -#include "module/shoot.h" -#if CMD_RCTypeTable_Index == 0 -#include "device/dr16.h" -#elif CMD_RCTypeTable_Index == 1 -#include "device/at9s_pro.h" -#elif CMD_RCTypeTable_Index == 2 -#include "device/vt13.h" -#endif - -/* Exported constants ------------------------------------------------------- */ -#define CMD_OK (0) /* 运行正常 */ -#define CMD_ERR_NULL (-1) /* 运行时发现NULL指针 */ -#define CMD_ERR_ERR (-2) /* 运行时发现了其他错误 */ -#define CMD_ERR_SOURCE (-3) /* 运行时配置了不存在的输入源 */ - -/* Exported macro ----------------------------------------------------------- */ -#define CMD_RCTypeTable_Index 0 /* 0:DR16 1:AT9S 2:VT13 */ - -#if CMD_RCTypeTable_Index == 0 -#define CMD_RCType_TABLE(X) X(dr16, DR16) -#elif CMD_RCTypeTable_Index == 1 -#define CMD_RCType_TABLE(X) X(at9s, AT9S) -#elif CMD_RCTypeTable_Index == 2 -#define CMD_RCType_TABLE(X) X(vt13, VT13) -#endif - -#if CMD_RCTypeTable_Index == 1 -#define CMD_NOPC_FLAG -#endif -#define CMDMACRO_NAME_EXPANSION(name, NAME) NAME##_t name -#define CMDMACRO_VAR_RCDATA(name, NAME) NAME##_DataRC_t name; -#define CMDMACRO_VAR_PCDATA(name, NAME) NAME##_DataPC_t name; -#define CMDMACRO_VAR_LASTPCDATA(name, NAME) NAME##_DataPC_t last##name; -/* Exported types ----------------------------------------------------------- */ -#define CMD_REFEREE_MAX_NUM (3) /* 发送命令限定的最大数量 */ -/* 输入源枚举 */ -typedef enum { - CMD_SRC_RC=0, /* 遥控器 */ - CMD_SRC_PC, /* 键盘鼠标 */ - CMD_SRC_NUC, /* 上位机 */ - CMD_SRC_REF, /* 裁判系统 */ - CMD_SRC_NUM -} CMD_InputSource_t; - -/* RC part begin-------------------------------------- */ - -typedef struct { - bool online; - enum {DR16=0, AT9S} type; - CMD_RCType_TABLE(CMDMACRO_VAR_RCDATA) - #undef CMDMACRO_VAR_RCDATA -} CMD_Input_RC_t;//或者这里直接把CMD_Input_RC_t前向声明了,看哪个好看 - -/* RC part end---------------------------------------- */ - -/* PC part begin-------------------------------------- */ -typedef enum { - CMD_MODULE_NONE = 0, - CMD_MODULE_CHASSIS = (1 << 0), - CMD_MODULE_GIMBAL = (1 << 1), - CMD_MODULE_SHOOT = (1 << 2), - CMD_MODULE_ALL = (CMD_MODULE_CHASSIS | CMD_MODULE_GIMBAL | CMD_MODULE_SHOOT) -} CMD_ModuleMask_t; -/* 键盘按键值 */ -typedef enum { - CMD_KEY_W = 0, - CMD_KEY_S, - CMD_KEY_A, - CMD_KEY_D, - CMD_KEY_SHIFT, - CMD_KEY_CTRL, - CMD_KEY_Q, - CMD_KEY_E, - CMD_KEY_R, - CMD_KEY_F, - CMD_KEY_G, - CMD_KEY_Z, - CMD_KEY_X, - CMD_KEY_C, - CMD_KEY_V, - CMD_KEY_B, - CMD_L_CLICK, - CMD_R_CLICK, - CMD_M_CLICK, - CMD_KEY_NUM, -} CMD_PCValue_t; -typedef enum { - CMD_ACTIVE_RISING_EDGE, /* 按下时触发 */ - CMD_ACTIVE_FALLING_EDGE, /* 抬起时触发 */ - CMD_ACTIVE_PRESSED, /* 按住时触发 */ -} CMD_TriggerType_t; - -/* 行为值序列 */ -typedef enum { - CMD_BEHAVIOR_FORE = 0, /* 向前 */ - CMD_BEHAVIOR_BACK, /* 向后 */ - CMD_BEHAVIOR_LEFT, /* 向左 */ - CMD_BEHAVIOR_RIGHT, /* 向右 */ - CMD_BEHAVIOR_ACCELERATE, /* 加速 */ - CMD_BEHAVIOR_DECELEBRATE, /* 减速 */ - CMD_BEHAVIOR_FIRE, /* 开火 */ - CMD_BEHAVIOR_FIRE_MODE, /* 切换开火模式 */ - CMD_BEHAVIOR_BUFF, /* 打符模式 */ - CMD_BEHAVIOR_AUTOAIM, /* 自瞄模式 */ - CMD_BEHAVIOR_OPENCOVER, /* 弹舱盖开关 */ - CMD_BEHAVIOR_ROTOR, /* 小陀螺模式 */ - CMD_BEHAVIOR_REVTRIG, /* 反转拨弹 */ - CMD_BEHAVIOR_FOLLOWGIMBAL35, /* 跟随云台呈35度 */ - CMD_BEHAVIOR_GIMBAL_MODE, /* 切换云台模式 */ - CMD_BEHAVIOR_NUM, -} CMD_Behavior_t; -typedef struct { - CMD_PCValue_t key; - CMD_TriggerType_t trigger_type; -} CMD_KeyMapItem_t; - -/* 行为映射的对应按键数组 */ -typedef struct { - CMD_KeyMapItem_t key_map[CMD_BEHAVIOR_NUM]; -} CMD_KeyMap_Params_t; - -typedef struct { - float sens_mouse; /* 鼠标灵敏度 */ - float move_sense; /* 移动灵敏度 */ - float move_fast_sense; /* 快速移动灵敏度 */ - float move_slow_sense; /* 慢速移动灵敏度 */ -} CMD_PC_Sensitivity_t; - -typedef struct { - CMD_KeyMap_Params_t map; /* 按键映射行为命令 */ - CMD_PC_Sensitivity_t sensitivity; /* PC灵敏度设置 */ -}CMD_PCParams_t; -#ifndef CMD_NOPC_FLAG -typedef struct { - bool online; - CMD_RCType_TABLE(CMDMACRO_VAR_PCDATA) - CMD_RCType_TABLE(CMDMACRO_VAR_LASTPCDATA) - #undef CMDMACRO_VAR_PCDATA - #undef CMDMACRO_VAR_LASTPCDATA -}CMD_Input_PC_t; -#else - typedef struct { - bool online; -}CMD_Input_PC_t; -#endif -/* PC part end---------------------------------------- */ - -/* NUC part begin------------------------------------- */ -typedef struct { - bool online; - struct { - float delta_yaw; - float delta_pit; - }gimbal; - struct { - float expectedSpeed; - bool fire; - }shoot; -}CMD_Input_NUC_t; - -/* NUC part end--------------------------------------- */ - -/* REF part begin------------------------------------- */ -typedef struct { - bool online; -}CMD_Input_REF_t; - -/* REF part begin------------------------------------- */ - -/* 底盘控制命令 */ -typedef struct { - CMD_InputSource_t source; - Chassis_CMD_t cmd; -} CMD_Output_CHASSIS_t; - -/* 云台控制命令 */ -typedef struct { - CMD_InputSource_t source; - Gimbal_CMD_t cmd; -} CMD_Output_GIMBAL_t; - -/* 射击控制命令 */ -typedef struct { - CMD_InputSource_t source; - Shoot_CMD_t cmd; -} CMD_Output_SHOOT_t; - -typedef struct { - CMD_Input_RC_t rc; - CMD_Input_PC_t pc; - CMD_Input_NUC_t nuc; - CMD_Input_REF_t ref; -} CMD_Input_t; -typedef struct { - CMD_Output_CHASSIS_t chassis; - CMD_Output_GIMBAL_t gimbal; - CMD_Output_SHOOT_t shoot; -} CMD_Output_t; - -typedef struct { - CMD_InputSource_t sourcePriorityConfigs[CMD_SRC_NUM];/* 输入源优先级配置 */ - CMD_PCParams_t pc; -} CMD_Params_t; - -typedef struct { - float now; - float dt; - uint64_t last; -} CMD_Timer_t; -typedef struct { - CMD_Timer_t timer; - CMD_Params_t *params; - - CMD_Input_t input; - CMD_Output_t output; -} CMD_t; - -/* Exported functions prototypes -------------------------------------------- */ -int8_t Cmd_Init(CMD_t *c, CMD_Params_t *params); -int8_t Cmd_Get(CMD_t *c, CMD_RCType_TABLE(CMDMACRO_NAME_EXPANSION)); -int8_t Cmd_GenerateCommand(CMD_t *c); -#ifdef __cplusplus -} -#endif diff --git a/User/module/cmd_v2/cmd.c b/User/module/cmd_v2/cmd.c index 82dbc1f..f64b596 100644 --- a/User/module/cmd_v2/cmd.c +++ b/User/module/cmd_v2/cmd.c @@ -11,7 +11,7 @@ /* ========================================================================== */ /* 从RC输入生成底盘命令 */ -static void CMD_RC_BuildChassisCmd(CMD_Context_t *ctx, const CMD_RawInput_t *input) { +static void CMD_RC_BuildChassisCmd(CMD_t *ctx, const CMD_RawInput_t *input) { CMD_RCModeMap_t *map = &ctx->config->rc_mode_map; /* 根据左拨杆位置选择模式 */ @@ -36,7 +36,7 @@ static void CMD_RC_BuildChassisCmd(CMD_Context_t *ctx, const CMD_RawInput_t *inp } /* 从RC输入生成云台命令 */ -static void CMD_RC_BuildGimbalCmd(CMD_Context_t *ctx, const CMD_RawInput_t *input) { +static void CMD_RC_BuildGimbalCmd(CMD_t *ctx, const CMD_RawInput_t *input) { CMD_RCModeMap_t *map = &ctx->config->rc_mode_map; /* 根据拨杆选择云台模式 */ @@ -61,7 +61,7 @@ static void CMD_RC_BuildGimbalCmd(CMD_Context_t *ctx, const CMD_RawInput_t *inpu } /* 从RC输入生成射击命令 */ -static void CMD_RC_BuildShootCmd(CMD_Context_t *ctx, const CMD_RawInput_t *input) { +static void CMD_RC_BuildShootCmd(CMD_t *ctx, const CMD_RawInput_t *input) { if (input->online) { ctx->shoot.cmd.mode = SHOOT_MODE_SINGLE; } else { @@ -87,7 +87,7 @@ static void CMD_RC_BuildShootCmd(CMD_Context_t *ctx, const CMD_RawInput_t *input } /* 从PC输入生成底盘命令 */ -static void CMD_PC_BuildChassisCmd(CMD_Context_t *ctx, const CMD_RawInput_t *input) { +static void CMD_PC_BuildChassisCmd(CMD_t *ctx, const CMD_RawInput_t *input) { CMD_Sensitivity_t *sens = &ctx->config->sensitivity; if (!input->online) { @@ -126,7 +126,7 @@ static void CMD_PC_BuildChassisCmd(CMD_Context_t *ctx, const CMD_RawInput_t *inp } /* 从PC输入生成云台命令 */ -static void CMD_PC_BuildGimbalCmd(CMD_Context_t *ctx, const CMD_RawInput_t *input) { +static void CMD_PC_BuildGimbalCmd(CMD_t *ctx, const CMD_RawInput_t *input) { CMD_Sensitivity_t *sens = &ctx->config->sensitivity; if (!input->online) { @@ -142,7 +142,7 @@ static void CMD_PC_BuildGimbalCmd(CMD_Context_t *ctx, const CMD_RawInput_t *inpu } /* 从PC输入生成射击命令 */ -static void CMD_PC_BuildShootCmd(CMD_Context_t *ctx, const CMD_RawInput_t *input) { +static void CMD_PC_BuildShootCmd(CMD_t *ctx, const CMD_RawInput_t *input) { if (!input->online) { ctx->shoot.cmd.mode = SHOOT_MODE_SAFE; return; @@ -153,7 +153,7 @@ static void CMD_PC_BuildShootCmd(CMD_Context_t *ctx, const CMD_RawInput_t *input } /* 离线安全模式 */ -static void CMD_SetOfflineMode(CMD_Context_t *ctx) { +static void CMD_SetOfflineMode(CMD_t *ctx) { ctx->chassis.cmd.mode = CHASSIS_MODE_RELAX; ctx->gimbal.cmd.mode = GIMBAL_MODE_RELAX; ctx->shoot.cmd.mode = SHOOT_MODE_SAFE; @@ -163,12 +163,12 @@ static void CMD_SetOfflineMode(CMD_Context_t *ctx) { /* 公开API实现 */ /* ========================================================================== */ -int8_t CMD_Init(CMD_Context_t *ctx, CMD_Config_t *config) { +int8_t CMD_Init(CMD_t *ctx, CMD_Config_t *config) { if (ctx == NULL || config == NULL) { return CMD_ERR_NULL; } - memset(ctx, 0, sizeof(CMD_Context_t)); + memset(ctx, 0, sizeof(CMD_t)); ctx->config = config; /* 初始化适配器 */ @@ -180,7 +180,7 @@ int8_t CMD_Init(CMD_Context_t *ctx, CMD_Config_t *config) { return CMD_OK; } -int8_t CMD_UpdateInput(CMD_Context_t *ctx) { +int8_t CMD_UpdateInput(CMD_t *ctx) { if (ctx == NULL) { return CMD_ERR_NULL; } @@ -196,12 +196,12 @@ int8_t CMD_UpdateInput(CMD_Context_t *ctx) { return CMD_OK; } -int8_t CMD_Arbitrate(CMD_Context_t *ctx) { +int8_t CMD_Arbitrate(CMD_t *ctx) { if (ctx == NULL) { return CMD_ERR_NULL; } - /* 智能仲裁算法:优先级 PC > RC > NUC */ + /* 自动仲裁:优先级 PC > RC > NUC */ CMD_InputSource_t candidates[] = {CMD_SRC_PC, CMD_SRC_RC, CMD_SRC_NUC}; const int num_candidates = sizeof(candidates) / sizeof(candidates[0]); @@ -217,23 +217,23 @@ int8_t CMD_Arbitrate(CMD_Context_t *ctx) { CMD_InputSource_t src = candidates[i]; if (ctx->input[src].online) { ctx->active_source = src; + break; + }else { + ctx->active_source = CMD_SRC_NUM; + continue; } } ctx->chassis.source = ctx->active_source; ctx->gimbal.source = ctx->active_source; ctx->shoot.source = ctx->active_source; + /* 优先级抢占逻辑 */ seize: - - - - /* 没有可用输入源 */ - ctx->active_source = CMD_SRC_NUM; return CMD_OK; } -int8_t CMD_GenerateCommands(CMD_Context_t *ctx) { +int8_t CMD_GenerateCommands(CMD_t *ctx) { if (ctx == NULL) { return CMD_ERR_NULL; } @@ -282,7 +282,7 @@ int8_t CMD_GenerateCommands(CMD_Context_t *ctx) { return CMD_OK; } -int8_t CMD_Update(CMD_Context_t *ctx) { +int8_t CMD_Update(CMD_t *ctx) { int8_t ret; ret = CMD_UpdateInput(ctx); diff --git a/User/module/cmd_v2/cmd.h b/User/module/cmd_v2/cmd.h index a0abc43..fbed0a2 100644 --- a/User/module/cmd_v2/cmd.h +++ b/User/module/cmd_v2/cmd.h @@ -74,8 +74,6 @@ typedef struct { /* RC模式映射 */ CMD_RCModeMap_t rc_mode_map; - /* 是否启用PC输入 */ - bool enable_pc_input; } CMD_Config_t; /* ========================================================================== */ @@ -107,7 +105,7 @@ typedef struct CMD_Context { CMD_GimbalOutput_t gimbal; CMD_ShootOutput_t shoot; -} CMD_Context_t; +} CMD_t; /* ========================================================================== */ /* 主API接口 */ @@ -119,52 +117,52 @@ typedef struct CMD_Context { * @param config 配置指针 * @return CMD_OK成功,其他失败 */ -int8_t CMD_Init(CMD_Context_t *ctx, CMD_Config_t *config); +int8_t CMD_Init(CMD_t *ctx, CMD_Config_t *config); /** * @brief 更新所有输入源的数据 * @param ctx CMD上下文 * @return CMD_OK成功 */ -int8_t CMD_UpdateInput(CMD_Context_t *ctx); +int8_t CMD_UpdateInput(CMD_t *ctx); /** * @brief 执行仲裁,决定使用哪个输入源 * @param ctx CMD上下文 * @return 选中的输入源 */ -int8_t CMD_Arbitrate(CMD_Context_t *ctx); +int8_t CMD_Arbitrate(CMD_t *ctx); /** * @brief 生成所有模块的控制命令 * @param ctx CMD上下文 * @return CMD_OK成功 */ -int8_t CMD_GenerateCommands(CMD_Context_t *ctx); +int8_t CMD_GenerateCommands(CMD_t *ctx); /** * @brief 一键更新(包含UpdateInput + Arbitrate + GenerateCommands) * @param ctx CMD上下文 * @return CMD_OK成功 */ -int8_t CMD_Update(CMD_Context_t *ctx); +int8_t CMD_Update(CMD_t *ctx); /* ========================================================================== */ /* 输出获取接口 */ /* ========================================================================== */ /* 获取底盘命令 */ -static inline Chassis_CMD_t* CMD_GetChassisCmd(CMD_Context_t *ctx) { +static inline Chassis_CMD_t* CMD_GetChassisCmd(CMD_t *ctx) { return &ctx->chassis.cmd; } /* 获取云台命令 */ -static inline Gimbal_CMD_t* CMD_GetGimbalCmd(CMD_Context_t *ctx) { +static inline Gimbal_CMD_t* CMD_GetGimbalCmd(CMD_t *ctx) { return &ctx->gimbal.cmd; } /* 获取射击命令 */ -static inline Shoot_CMD_t* CMD_GetShootCmd(CMD_Context_t *ctx) { +static inline Shoot_CMD_t* CMD_GetShootCmd(CMD_t *ctx) { return &ctx->shoot.cmd; } diff --git a/User/module/cmd_v2/cmd_adapter.c b/User/module/cmd_v2/cmd_adapter.c index 4ca382b..a529620 100644 --- a/User/module/cmd_v2/cmd_adapter.c +++ b/User/module/cmd_v2/cmd_adapter.c @@ -7,8 +7,8 @@ /* ========================================================================== */ /* 适配器存储 */ /* ========================================================================== */ -static CMD_InputAdapter_t *g_adapters[CMD_SRC_NUM] = {0}; - +// static CMD_InputAdapter_t *g_adapters[CMD_SRC_NUM] = {0}; +CMD_InputAdapter_t *g_adapters[CMD_SRC_NUM] = {0}; /* ========================================================================== */ /* DR16 适配器实现 */ /* ========================================================================== */ @@ -66,7 +66,7 @@ int8_t CMD_DR16_PC_GetInput(void *data, CMD_RawInput_t *output) { output->mouse.r_click = dr16->data.pc.mouse.r_click; /* 键盘映射 */ - output->keyboard.bitmap = dr16->data.pc.keyboard.value; + output->keyboard.bitmap = dr16->raw_data.key; return CMD_OK; } @@ -75,10 +75,10 @@ bool CMD_DR16_IsOnline(void *data) { DR16_t *dr16 = (DR16_t *)data; return dr16->header.online; } - +extern DR16_t cmd_dr16; /* 定义适配器实例 */ -CMD_DEFINE_ADAPTER(DR16_RC, dr16, CMD_SRC_RC, CMD_DR16_Init, CMD_DR16_RC_GetInput, CMD_DR16_IsOnline) -CMD_DEFINE_ADAPTER(DR16_PC, dr16, CMD_SRC_PC, CMD_DR16_Init, CMD_DR16_PC_GetInput, CMD_DR16_IsOnline) +CMD_DEFINE_ADAPTER(DR16_RC, cmd_dr16, CMD_SRC_RC, CMD_DR16_Init, CMD_DR16_RC_GetInput, CMD_DR16_IsOnline) +CMD_DEFINE_ADAPTER(DR16_PC, cmd_dr16, CMD_SRC_PC, CMD_DR16_Init, CMD_DR16_PC_GetInput, CMD_DR16_IsOnline) #endif /* CMD_RC_DEVICE_TYPE == 0 */ diff --git a/User/module/cmd_v2/cmd_behavior.c b/User/module/cmd_v2/cmd_behavior.c index 7dd4814..f174565 100644 --- a/User/module/cmd_v2/cmd_behavior.c +++ b/User/module/cmd_v2/cmd_behavior.c @@ -10,49 +10,49 @@ /* ========================================================================== */ /* 行为处理函数实现 */ -int8_t CMD_Behavior_Handle_FORE(CMD_Context_t *ctx) { +int8_t CMD_Behavior_Handle_FORE(CMD_t *ctx) { ctx->chassis.cmd.ctrl_vec.vy += ctx->config->sensitivity.move_sens; return CMD_OK; } -int8_t CMD_Behavior_Handle_BACK(CMD_Context_t *ctx) { +int8_t CMD_Behavior_Handle_BACK(CMD_t *ctx) { ctx->chassis.cmd.ctrl_vec.vy -= ctx->config->sensitivity.move_sens; return CMD_OK; } -int8_t CMD_Behavior_Handle_LEFT(CMD_Context_t *ctx) { +int8_t CMD_Behavior_Handle_LEFT(CMD_t *ctx) { ctx->chassis.cmd.ctrl_vec.vx -= ctx->config->sensitivity.move_sens; return CMD_OK; } -int8_t CMD_Behavior_Handle_RIGHT(CMD_Context_t *ctx) { +int8_t CMD_Behavior_Handle_RIGHT(CMD_t *ctx) { ctx->chassis.cmd.ctrl_vec.vx += ctx->config->sensitivity.move_sens; return CMD_OK; } -int8_t CMD_Behavior_Handle_ACCELERATE(CMD_Context_t *ctx) { +int8_t CMD_Behavior_Handle_ACCELERATE(CMD_t *ctx) { ctx->chassis.cmd.ctrl_vec.vx *= ctx->config->sensitivity.move_fast_mult; ctx->chassis.cmd.ctrl_vec.vy *= ctx->config->sensitivity.move_fast_mult; return CMD_OK; } -int8_t CMD_Behavior_Handle_DECELERATE(CMD_Context_t *ctx) { +int8_t CMD_Behavior_Handle_DECELERATE(CMD_t *ctx) { ctx->chassis.cmd.ctrl_vec.vx *= ctx->config->sensitivity.move_slow_mult; ctx->chassis.cmd.ctrl_vec.vy *= ctx->config->sensitivity.move_slow_mult; return CMD_OK; } -int8_t CMD_Behavior_Handle_FIRE(CMD_Context_t *ctx) { +int8_t CMD_Behavior_Handle_FIRE(CMD_t *ctx) { ctx->shoot.cmd.firecmd = true; return CMD_OK; } -int8_t CMD_Behavior_Handle_FIRE_MODE(CMD_Context_t *ctx) { +int8_t CMD_Behavior_Handle_FIRE_MODE(CMD_t *ctx) { ctx->shoot.cmd.mode = (ctx->shoot.cmd.mode + 1) % SHOOT_MODE_NUM; return CMD_OK; } -int8_t CMD_Behavior_Handle_ROTOR(CMD_Context_t *ctx) { +int8_t CMD_Behavior_Handle_ROTOR(CMD_t *ctx) { if (ctx->chassis.cmd.mode == CHASSIS_MODE_ROTOR) { ctx->chassis.cmd.mode = CHASSIS_MODE_FOLLOW_GIMBAL; } else { @@ -62,7 +62,7 @@ int8_t CMD_Behavior_Handle_ROTOR(CMD_Context_t *ctx) { return CMD_OK; } -int8_t CMD_Behavior_Handle_AUTOAIM(CMD_Context_t *ctx) { +int8_t CMD_Behavior_Handle_AUTOAIM(CMD_t *ctx) { /* TODO: 自瞄模式切换 */ return CMD_OK; } @@ -137,7 +137,7 @@ bool CMD_Behavior_IsTriggered(const CMD_RawInput_t *current, } } -int8_t CMD_Behavior_ProcessAll(CMD_Context_t *ctx, +int8_t CMD_Behavior_ProcessAll(CMD_t *ctx, const CMD_RawInput_t *current, const CMD_RawInput_t *last, CMD_ModuleMask_t active_modules) { diff --git a/User/module/cmd_v2/cmd_example.c b/User/module/cmd_v2/cmd_example.c index 4779c56..300bb64 100644 --- a/User/module/cmd_v2/cmd_example.c +++ b/User/module/cmd_v2/cmd_example.c @@ -10,15 +10,7 @@ /* ========================================================================== */ /* 默认配置 */ -static CMD_Config_t g_cmd_config = { - /* 输入源优先级:RC > PC > NUC > REF */ - .source_priority = { - CMD_SRC_RC, - CMD_SRC_PC, - CMD_SRC_NUC, - CMD_SRC_REF, - }, - +static CMD_Config_t g_cmd_config = { /* 灵敏度设置 */ .sensitivity = { .mouse_sens = 0.8f, @@ -40,11 +32,10 @@ static CMD_Config_t g_cmd_config = { .gimbal_sw_down = GIMBAL_MODE_RELATIVE, }, - .enable_pc_input = true, }; /* CMD上下文 */ -static CMD_Context_t g_cmd_ctx; +static CMD_t g_cmd_ctx; /* ========================================================================== */ /* 任务示例 */ @@ -148,6 +139,6 @@ void Example_CMD_Task(void) { * * ### 添加新输出模块 * 1. 在 CMD_OUTPUT_MODULE_TABLE 添加条目 - * 2. 在 CMD_Context_t 中添加输出成员 + * 2. 在 CMD_t 中添加输出成员 * 3. 实现对应的 BuildXXXCmd 函数 */ diff --git a/User/module/cmd_v2/cmd_types.h b/User/module/cmd_v2/cmd_types.h index ff1646f..c009c88 100644 --- a/User/module/cmd_v2/cmd_types.h +++ b/User/module/cmd_v2/cmd_types.h @@ -28,10 +28,10 @@ extern "C" { * 格式: X(枚举名, 优先级, 适配器初始化函数, 获取数据函数) */ #define CMD_INPUT_SOURCE_TABLE(X) \ - X(RC, 0, CMD_RC_AdapterInit, CMD_RC_GetInput) \ - X(PC, 1, CMD_PC_AdapterInit, CMD_PC_GetInput) \ - X(NUC, 2, CMD_NUC_AdapterInit, CMD_NUC_GetInput) \ - X(REF, 3, CMD_REF_AdapterInit, CMD_REF_GetInput) + X(RC, CMD_RC_AdapterInit, CMD_RC_GetInput) \ + X(PC, CMD_PC_AdapterInit, CMD_PC_GetInput) \ + X(NUC, CMD_NUC_AdapterInit, CMD_NUC_GetInput) \ + X(REF, CMD_REF_AdapterInit, CMD_REF_GetInput) /* 输出模块配置宏表 */ #define CMD_OUTPUT_MODULE_TABLE(X) \ @@ -139,7 +139,7 @@ typedef enum { X(RIGHT, CMD_KEY_D, CMD_ACTIVE_PRESSED, CMD_MODULE_CHASSIS) \ X(ACCELERATE, CMD_KEY_SHIFT, CMD_ACTIVE_PRESSED, CMD_MODULE_CHASSIS) \ X(DECELERATE, CMD_KEY_CTRL, CMD_ACTIVE_PRESSED, CMD_MODULE_CHASSIS) \ - X(FIRE, CMD_KEY_NONE, CMD_ACTIVE_PRESSED, CMD_MODULE_SHOOT) \ + X(FIRE, CMD_KEY_L_CLICK, CMD_ACTIVE_PRESSED, CMD_MODULE_SHOOT) \ X(FIRE_MODE, CMD_KEY_B, CMD_ACTIVE_RISING_EDGE, CMD_MODULE_SHOOT) \ X(ROTOR, CMD_KEY_E, CMD_ACTIVE_RISING_EDGE, CMD_MODULE_CHASSIS) \ X(AUTOAIM, CMD_KEY_R, CMD_ACTIVE_RISING_EDGE, CMD_MODULE_GIMBAL | CMD_MODULE_SHOOT) diff --git a/User/module/config.c b/User/module/config.c index 206c654..fcc0719 100644 --- a/User/module/config.c +++ b/User/module/config.c @@ -6,7 +6,7 @@ #include "module/config.h" #include "bsp/can.h" #include "device/motor_dm.h" -#include "module/cmd.h" +#include "module/cmd_v2/cmd.h" #include /* Private typedef ---------------------------------------------------------- */ /* Private define ----------------------------------------------------------- */ @@ -196,7 +196,7 @@ Config_RobotParam_t robot_config = { .reverse = false, }, .yaw_motor = { - .can = BSP_CAN_1, + .can = BSP_CAN_2, .can_id = 0x50, .master_id = 0x60, .module = MOTOR_DM_J4310, @@ -363,39 +363,58 @@ Config_RobotParam_t robot_config = { }, }, }, + // .cmd_param={ + // .sourcePriorityConfigs={ + // CMD_SRC_RC, + // CMD_SRC_PC, + // CMD_SRC_NUC, + // CMD_SRC_REF + // }, + // .pc.map = { /*1<cmd_param); + CMD_Init(&cmd, &Config_GetRobotParam()->cmd_param); /* USER CODE INIT END */ while (1) { @@ -57,19 +57,20 @@ void Task_cmd(void *argument) { #elif CMD_RCTypeTable_Index == 1 osMessageQueueGet(task_runtime.msgq.cmd.rc, &cmd_at9s, NULL, 0); #endif - Cmd_Get(&cmd,cmd_dr16); - Cmd_GenerateCommand(&cmd); - cmd_for_shoot=cmd.output.shoot.cmd; - cmd_for_chassis=cmd.output.chassis.cmd; - cmd_for_gimbal=cmd.output.gimbal.cmd; + CMD_Update(&cmd); + + /* 获取命令发送到各模块 */ + cmd_for_chassis = CMD_GetChassisCmd(&cmd); + cmd_for_gimbal = CMD_GetGimbalCmd(&cmd); + cmd_for_shoot = CMD_GetShootCmd(&cmd); osMessageQueueReset(task_runtime.msgq.gimbal.cmd); - osMessageQueuePut(task_runtime.msgq.gimbal.cmd, &cmd_for_gimbal, 0, 0); + osMessageQueuePut(task_runtime.msgq.gimbal.cmd, cmd_for_gimbal, 0, 0); osMessageQueueReset(task_runtime.msgq.shoot.cmd); - osMessageQueuePut(task_runtime.msgq.shoot.cmd, &cmd_for_shoot, 0, 0); + osMessageQueuePut(task_runtime.msgq.shoot.cmd, cmd_for_shoot, 0, 0); osMessageQueueReset(task_runtime.msgq.chassis.cmd); - osMessageQueuePut(task_runtime.msgq.chassis.cmd, &cmd_for_chassis, 0, 0); + osMessageQueuePut(task_runtime.msgq.chassis.cmd, cmd_for_chassis, 0, 0); /* USER CODE END */ osDelayUntil(tick); /* 运行结束,等待下一次唤醒 */ } -} +} \ No newline at end of file From 50bb9d8619eb3983b6e6c467aa5df9dd1e48456d Mon Sep 17 00:00:00 2001 From: yxming66 <2389287465@qq.com> Date: Thu, 18 Dec 2025 02:51:36 +0800 Subject: [PATCH 3/3] =?UTF-8?q?cmdV2=E6=88=90=E5=8A=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- User/module/cmd_v2/cmd.c | 242 ++++++++++++++---------------- User/module/cmd_v2/cmd.h | 17 ++- User/module/cmd_v2/cmd_adapter.c | 51 +++---- User/module/cmd_v2/cmd_behavior.c | 126 ++++++++-------- User/module/cmd_v2/cmd_behavior.h | 2 +- User/module/cmd_v2/cmd_types.h | 111 ++++++++------ User/module/config.c | 4 +- ozone/hero.jdebug | 24 ++- ozone/hero.jdebug.user | 108 ++++++------- 9 files changed, 344 insertions(+), 341 deletions(-) diff --git a/User/module/cmd_v2/cmd.c b/User/module/cmd_v2/cmd.c index f64b596..74b3093 100644 --- a/User/module/cmd_v2/cmd.c +++ b/User/module/cmd_v2/cmd.c @@ -11,152 +11,133 @@ /* ========================================================================== */ /* 从RC输入生成底盘命令 */ -static void CMD_RC_BuildChassisCmd(CMD_t *ctx, const CMD_RawInput_t *input) { +static void CMD_RC_BuildChassisCmd(CMD_t *ctx) { CMD_RCModeMap_t *map = &ctx->config->rc_mode_map; /* 根据左拨杆位置选择模式 */ - switch (input->sw[0]) { + switch (ctx->input.rc.sw[0]) { case CMD_SW_UP: - ctx->chassis.cmd.mode = map->sw_left_up; + ctx->output.chassis.cmd.mode = map->sw_left_up; break; case CMD_SW_MID: - ctx->chassis.cmd.mode = map->sw_left_mid; + ctx->output.chassis.cmd.mode = map->sw_left_mid; break; case CMD_SW_DOWN: - ctx->chassis.cmd.mode = map->sw_left_down; + ctx->output.chassis.cmd.mode = map->sw_left_down; break; default: - ctx->chassis.cmd.mode = CHASSIS_MODE_RELAX; + ctx->output.chassis.cmd.mode = CHASSIS_MODE_RELAX; break; } /* 摇杆控制移动 */ - ctx->chassis.cmd.ctrl_vec.vx = input->joy_right.x; - ctx->chassis.cmd.ctrl_vec.vy = input->joy_right.y; + ctx->output.chassis.cmd.ctrl_vec.vx = ctx->input.rc.joy_right.x; + ctx->output.chassis.cmd.ctrl_vec.vy = ctx->input.rc.joy_right.y; } /* 从RC输入生成云台命令 */ -static void CMD_RC_BuildGimbalCmd(CMD_t *ctx, const CMD_RawInput_t *input) { +static void CMD_RC_BuildGimbalCmd(CMD_t *ctx) { CMD_RCModeMap_t *map = &ctx->config->rc_mode_map; /* 根据拨杆选择云台模式 */ - switch (input->sw[0]) { + switch (ctx->input.rc.sw[0]) { case CMD_SW_UP: - ctx->gimbal.cmd.mode = map->gimbal_sw_up; + ctx->output.gimbal.cmd.mode = map->gimbal_sw_up; break; case CMD_SW_MID: - ctx->gimbal.cmd.mode = map->gimbal_sw_mid; + ctx->output.gimbal.cmd.mode = map->gimbal_sw_mid; break; case CMD_SW_DOWN: - ctx->gimbal.cmd.mode = map->gimbal_sw_down; + ctx->output.gimbal.cmd.mode = map->gimbal_sw_down; break; default: - ctx->gimbal.cmd.mode = GIMBAL_MODE_RELAX; + ctx->output.gimbal.cmd.mode = GIMBAL_MODE_RELAX; break; } /* 左摇杆控制云台 */ - ctx->gimbal.cmd.delta_yaw = -input->joy_left.x * 2.0f; - ctx->gimbal.cmd.delta_pit = -input->joy_left.y * 1.5f; + ctx->output.gimbal.cmd.delta_yaw = -ctx->input.rc.joy_left.x * 2.0f; + ctx->output.gimbal.cmd.delta_pit = -ctx->input.rc.joy_left.y * 1.5f; } /* 从RC输入生成射击命令 */ -static void CMD_RC_BuildShootCmd(CMD_t *ctx, const CMD_RawInput_t *input) { - if (input->online) { - ctx->shoot.cmd.mode = SHOOT_MODE_SINGLE; +static void CMD_RC_BuildShootCmd(CMD_t *ctx) { + if (ctx->input.online[CMD_SRC_RC]) { + ctx->output.shoot.cmd.mode = SHOOT_MODE_SINGLE; } else { - ctx->shoot.cmd.mode = SHOOT_MODE_SAFE; + ctx->output.shoot.cmd.mode = SHOOT_MODE_SAFE; } /* 根据右拨杆控制射击 */ - switch (input->sw[1]) { + switch (ctx->input.rc.sw[1]) { case CMD_SW_DOWN: - ctx->shoot.cmd.ready = true; - ctx->shoot.cmd.firecmd = true; + ctx->output.shoot.cmd.ready = true; + ctx->output.shoot.cmd.firecmd = true; break; case CMD_SW_MID: - ctx->shoot.cmd.ready = true; - ctx->shoot.cmd.firecmd = false; + ctx->output.shoot.cmd.ready = true; + ctx->output.shoot.cmd.firecmd = false; break; case CMD_SW_UP: default: - ctx->shoot.cmd.ready = false; - ctx->shoot.cmd.firecmd = false; + ctx->output.shoot.cmd.ready = false; + ctx->output.shoot.cmd.firecmd = false; break; } } /* 从PC输入生成底盘命令 */ -static void CMD_PC_BuildChassisCmd(CMD_t *ctx, const CMD_RawInput_t *input) { - CMD_Sensitivity_t *sens = &ctx->config->sensitivity; +static void CMD_PC_BuildChassisCmd(CMD_t *ctx) { - if (!input->online) { - ctx->chassis.cmd.mode = CHASSIS_MODE_RELAX; + if (!ctx->input.online[CMD_SRC_PC]) { + ctx->output.chassis.cmd.mode = CHASSIS_MODE_RELAX; return; } - ctx->chassis.cmd.mode = CHASSIS_MODE_FOLLOW_GIMBAL; + ctx->output.chassis.cmd.mode = CHASSIS_MODE_FOLLOW_GIMBAL; /* WASD控制移动 */ - ctx->chassis.cmd.ctrl_vec.vx = 0.0f; - ctx->chassis.cmd.ctrl_vec.vy = 0.0f; - - if (CMD_KEY_PRESSED(&input->keyboard, CMD_KEY_W)) { - ctx->chassis.cmd.ctrl_vec.vy += sens->move_sens; - } - if (CMD_KEY_PRESSED(&input->keyboard, CMD_KEY_S)) { - ctx->chassis.cmd.ctrl_vec.vy -= sens->move_sens; - } - if (CMD_KEY_PRESSED(&input->keyboard, CMD_KEY_A)) { - ctx->chassis.cmd.ctrl_vec.vx -= sens->move_sens; - } - if (CMD_KEY_PRESSED(&input->keyboard, CMD_KEY_D)) { - ctx->chassis.cmd.ctrl_vec.vx += sens->move_sens; - } - - /* 加速/减速 */ - if (CMD_KEY_PRESSED(&input->keyboard, CMD_KEY_SHIFT)) { - ctx->chassis.cmd.ctrl_vec.vx *= sens->move_fast_mult; - ctx->chassis.cmd.ctrl_vec.vy *= sens->move_fast_mult; - } - if (CMD_KEY_PRESSED(&input->keyboard, CMD_KEY_CTRL)) { - ctx->chassis.cmd.ctrl_vec.vx *= sens->move_slow_mult; - ctx->chassis.cmd.ctrl_vec.vy *= sens->move_slow_mult; - } + ctx->output.chassis.cmd.ctrl_vec.vx = 0.0f; + ctx->output.chassis.cmd.ctrl_vec.vy = 0.0f; + CMD_Behavior_ProcessAll(ctx, &ctx->input, &ctx->last_input, CMD_MODULE_CHASSIS); } /* 从PC输入生成云台命令 */ -static void CMD_PC_BuildGimbalCmd(CMD_t *ctx, const CMD_RawInput_t *input) { +static void CMD_PC_BuildGimbalCmd(CMD_t *ctx) { CMD_Sensitivity_t *sens = &ctx->config->sensitivity; - if (!input->online) { - ctx->gimbal.cmd.mode = GIMBAL_MODE_RELAX; + if (!ctx->input.online[CMD_SRC_PC]) { + ctx->output.gimbal.cmd.mode = GIMBAL_MODE_RELAX; return; } - ctx->gimbal.cmd.mode = GIMBAL_MODE_ABSOLUTE; + ctx->output.gimbal.cmd.mode = GIMBAL_MODE_ABSOLUTE; /* 鼠标控制云台 */ - ctx->gimbal.cmd.delta_yaw = (float)-input->mouse.x * ctx->timer.dt * sens->mouse_sens; - ctx->gimbal.cmd.delta_pit = (float)input->mouse.y * ctx->timer.dt * sens->mouse_sens * 1.5f; + ctx->output.gimbal.cmd.delta_yaw = (float)-ctx->input.pc.mouse.x * ctx->timer.dt * sens->mouse_sens; + ctx->output.gimbal.cmd.delta_pit = (float)ctx->input.pc.mouse.y * ctx->timer.dt * sens->mouse_sens * 1.5f; + CMD_Behavior_ProcessAll(ctx, &ctx->input, &ctx->last_input, CMD_MODULE_GIMBAL); } /* 从PC输入生成射击命令 */ -static void CMD_PC_BuildShootCmd(CMD_t *ctx, const CMD_RawInput_t *input) { - if (!input->online) { - ctx->shoot.cmd.mode = SHOOT_MODE_SAFE; +static void CMD_PC_BuildShootCmd(CMD_t *ctx) { + if (!ctx->input.online[CMD_SRC_PC]) { + ctx->output.shoot.cmd.mode = SHOOT_MODE_SAFE; return; } - ctx->shoot.cmd.ready = true; - ctx->shoot.cmd.firecmd = input->mouse.l_click; + ctx->output.shoot.cmd.ready = true; + ctx->output.shoot.cmd.firecmd = ctx->input.pc.mouse.l_click; + + CMD_Behavior_ProcessAll(ctx, &ctx->input, &ctx->last_input, CMD_MODULE_SHOOT); + } /* 离线安全模式 */ static void CMD_SetOfflineMode(CMD_t *ctx) { - ctx->chassis.cmd.mode = CHASSIS_MODE_RELAX; - ctx->gimbal.cmd.mode = GIMBAL_MODE_RELAX; - ctx->shoot.cmd.mode = SHOOT_MODE_SAFE; + ctx->output.chassis.cmd.mode = CHASSIS_MODE_RELAX; + ctx->output.gimbal.cmd.mode = GIMBAL_MODE_RELAX; + ctx->output.shoot.cmd.mode = SHOOT_MODE_SAFE; } /* ========================================================================== */ @@ -186,16 +167,32 @@ int8_t CMD_UpdateInput(CMD_t *ctx) { } /* 保存上一帧输入 */ - memcpy(ctx->last_input, ctx->input, sizeof(ctx->input)); + memcpy(&ctx->last_input, &ctx->input, sizeof(ctx->input)); /* 更新所有输入源 */ for (int i = 0; i < CMD_SRC_NUM; i++) { - CMD_Adapter_GetInput((CMD_InputSource_t)i, &ctx->input[i]); + CMD_Adapter_GetInput((CMD_InputSource_t)i, &ctx->input); } return CMD_OK; } +typedef void (*CMD_BuildCommandFunc)(CMD_t *cmd); +typedef struct { + CMD_InputSource_t source; + CMD_BuildCommandFunc chassisFunc; + CMD_BuildCommandFunc gimbalFunc; + CMD_BuildCommandFunc shootFunc; +} CMD_SourceHandler_t; +CMD_SourceHandler_t sourceHandlers[CMD_SRC_NUM] = { + {CMD_SRC_RC, CMD_RC_BuildChassisCmd, CMD_RC_BuildGimbalCmd, CMD_RC_BuildShootCmd}, + {CMD_SRC_PC, CMD_PC_BuildChassisCmd, CMD_PC_BuildGimbalCmd, CMD_PC_BuildShootCmd}, + {CMD_SRC_NUC, NULL, NULL, NULL}, + {CMD_SRC_REF, NULL, NULL, NULL}, +}; + + uint8_t last_shift = 0, last_v = 0; + uint8_t now_shift = 0, now_v = 0; int8_t CMD_Arbitrate(CMD_t *ctx) { if (ctx == NULL) { return CMD_ERR_NULL; @@ -208,14 +205,14 @@ int8_t CMD_Arbitrate(CMD_t *ctx) { /* 如果当前输入源仍然在线且有效,保持使用 */ if (ctx->active_source < CMD_SRC_NUM && ctx->active_source != CMD_SRC_REF && - ctx->input[ctx->active_source].online) { + ctx->input.online[ctx->active_source]) { goto seize; } /* 否则选择第一个可用的控制输入源 */ for (int i = 0; i < num_candidates; i++) { CMD_InputSource_t src = candidates[i]; - if (ctx->input[src].online) { + if (ctx->input.online[src]) { ctx->active_source = src; break; }else { @@ -223,63 +220,56 @@ int8_t CMD_Arbitrate(CMD_t *ctx) { continue; } } - ctx->chassis.source = ctx->active_source; - ctx->gimbal.source = ctx->active_source; - ctx->shoot.source = ctx->active_source; + ctx->output.chassis.source = ctx->active_source; + ctx->output.gimbal.source = ctx->active_source; + ctx->output.shoot.source = ctx->active_source; /* 优先级抢占逻辑 */ seize: - - return CMD_OK; + // 检查PC输入,按下一次shift和v,切换active_source在RC和PC之间 + CMD_Behavior_ProcessAll(ctx, &ctx->input, &ctx->last_input, CMD_MODULE_NONE); + // if (ctx->input.online[CMD_SRC_PC]) { + // now_shift = CMD_KEY_PRESSED(&ctx->input.pc.keyboard, CMD_KEY_SHIFT); + // now_v = CMD_KEY_PRESSED(&ctx->input.pc.keyboard, CMD_KEY_V); + // // 检测本帧按下(上升沿) + // if (now_shift && !last_shift && now_v && !last_v) { + // if (ctx->active_source == CMD_SRC_PC && ctx->input.online[CMD_SRC_RC]) { + // ctx->active_source = CMD_SRC_RC; + // } else if (ctx->active_source == CMD_SRC_RC && ctx->input.online[CMD_SRC_PC]) { + // ctx->active_source = CMD_SRC_PC; + // } + // ctx->output.chassis.source = ctx->active_source; + // ctx->output.gimbal.source = ctx->active_source; + // ctx->output.shoot.source = ctx->active_source; + // } + // last_shift = now_shift; + // last_v = now_v; + // } + + return CMD_OK; } int8_t CMD_GenerateCommands(CMD_t *ctx) { - if (ctx == NULL) { - return CMD_ERR_NULL; - } - - /* 更新时间 */ - uint64_t now_us = BSP_TIME_Get_us(); - ctx->timer.now = now_us / 1000000.0f; - ctx->timer.dt = (now_us - ctx->timer.last_us) / 1000000.0f; - ctx->timer.last_us = now_us; - - /* 没有有效输入源 */ - if (ctx->active_source >= CMD_SRC_NUM) { - CMD_SetOfflineMode(ctx); - return CMD_ERR_NO_INPUT; - } - - const CMD_RawInput_t *active_input = &ctx->input[ctx->active_source]; - const CMD_RawInput_t *last_input = &ctx->last_input[ctx->active_source]; - - /* 根据输入源类型生成命令 */ - switch (ctx->active_source) { - case CMD_SRC_RC: - CMD_RC_BuildChassisCmd(ctx, active_input); - CMD_RC_BuildGimbalCmd(ctx, active_input); - CMD_RC_BuildShootCmd(ctx, active_input); - break; - - case CMD_SRC_PC: - CMD_PC_BuildChassisCmd(ctx, active_input); - CMD_PC_BuildGimbalCmd(ctx, active_input); - CMD_PC_BuildShootCmd(ctx, active_input); - - /* 处理行为 */ - CMD_Behavior_ProcessAll(ctx, active_input, last_input, CMD_MODULE_ALL); - break; - - case CMD_SRC_NUC: - /* TODO: NUC输入处理 */ - break; - - default: - CMD_SetOfflineMode(ctx); - return CMD_ERR_SOURCE; - } - - return CMD_OK; + if (ctx == NULL) { + return CMD_ERR_NULL; + } + + /* 更新时间 */ + uint64_t now_us = BSP_TIME_Get_us(); + ctx->timer.now = now_us / 1000000.0f; + ctx->timer.dt = (now_us - ctx->timer.last_us) / 1000000.0f; + ctx->timer.last_us = now_us; + + /* 没有有效输入源 */ + if (ctx->active_source >= CMD_SRC_NUM) { + CMD_SetOfflineMode(ctx); + return CMD_ERR_NO_INPUT; + } + + sourceHandlers[ctx->output.gimbal.source].gimbalFunc(ctx); + sourceHandlers[ctx->output.chassis.source].chassisFunc(ctx); + sourceHandlers[ctx->output.shoot.source].shootFunc(ctx); + return CMD_OK; } int8_t CMD_Update(CMD_t *ctx) { diff --git a/User/module/cmd_v2/cmd.h b/User/module/cmd_v2/cmd.h index fbed0a2..c70c46f 100644 --- a/User/module/cmd_v2/cmd.h +++ b/User/module/cmd_v2/cmd.h @@ -83,7 +83,7 @@ typedef struct { typedef struct { float now; float dt; - uint64_t last_us; + uint32_t last_us; } CMD_Timer_t; typedef struct CMD_Context { @@ -94,17 +94,18 @@ typedef struct CMD_Context { CMD_Timer_t timer; /* 当前帧和上一帧的原始输入 */ - CMD_RawInput_t input[CMD_SRC_NUM]; - CMD_RawInput_t last_input[CMD_SRC_NUM]; + CMD_RawInput_t input; + CMD_RawInput_t last_input; /* 仲裁后的活跃输入源 */ CMD_InputSource_t active_source; /* 输出 */ + struct { CMD_ChassisOutput_t chassis; CMD_GimbalOutput_t gimbal; CMD_ShootOutput_t shoot; - + } output; } CMD_t; /* ========================================================================== */ @@ -153,17 +154,17 @@ int8_t CMD_Update(CMD_t *ctx); /* 获取底盘命令 */ static inline Chassis_CMD_t* CMD_GetChassisCmd(CMD_t *ctx) { - return &ctx->chassis.cmd; -} + return &ctx->output.chassis.cmd; + } /* 获取云台命令 */ static inline Gimbal_CMD_t* CMD_GetGimbalCmd(CMD_t *ctx) { - return &ctx->gimbal.cmd; + return &ctx->output.gimbal.cmd; } /* 获取射击命令 */ static inline Shoot_CMD_t* CMD_GetShootCmd(CMD_t *ctx) { - return &ctx->shoot.cmd; + return &ctx->output.shoot.cmd; } #ifdef __cplusplus diff --git a/User/module/cmd_v2/cmd_adapter.c b/User/module/cmd_v2/cmd_adapter.c index a529620..bc7986e 100644 --- a/User/module/cmd_v2/cmd_adapter.c +++ b/User/module/cmd_v2/cmd_adapter.c @@ -22,32 +22,32 @@ int8_t CMD_DR16_Init(void *data) { int8_t CMD_DR16_RC_GetInput(void *data, CMD_RawInput_t *output) { DR16_t *dr16 = (DR16_t *)data; - memset(output, 0, sizeof(CMD_RawInput_t)); + memset(&output->rc, 0, sizeof(CMD_RawInput_RC_t)); - output->online = dr16->header.online; + output->online[CMD_SRC_RC] = dr16->header.online; /* 遥控器摇杆映射 */ - output->joy_left.x = dr16->data.rc.ch_l_x; - output->joy_left.y = dr16->data.rc.ch_l_y; - output->joy_right.x = dr16->data.rc.ch_r_x; - output->joy_right.y = dr16->data.rc.ch_r_y; + output->rc.joy_left.x = dr16->data.rc.ch_l_x; + output->rc.joy_left.y = dr16->data.rc.ch_l_y; + output->rc.joy_right.x = dr16->data.rc.ch_r_x; + output->rc.joy_right.y = dr16->data.rc.ch_r_y; /* 拨杆映射 */ switch (dr16->data.rc.sw_l) { - case DR16_SW_UP: output->sw[0] = CMD_SW_UP; break; - case DR16_SW_MID: output->sw[0] = CMD_SW_MID; break; - case DR16_SW_DOWN: output->sw[0] = CMD_SW_DOWN; break; - default: output->sw[0] = CMD_SW_ERR; break; + case DR16_SW_UP: output->rc.sw[0] = CMD_SW_UP; break; + case DR16_SW_MID: output->rc.sw[0] = CMD_SW_MID; break; + case DR16_SW_DOWN: output->rc.sw[0] = CMD_SW_DOWN; break; + default: output->rc.sw[0] = CMD_SW_ERR; break; } switch (dr16->data.rc.sw_r) { - case DR16_SW_UP: output->sw[1] = CMD_SW_UP; break; - case DR16_SW_MID: output->sw[1] = CMD_SW_MID; break; - case DR16_SW_DOWN: output->sw[1] = CMD_SW_DOWN; break; - default: output->sw[1] = CMD_SW_ERR; break; + case DR16_SW_UP: output->rc.sw[1] = CMD_SW_UP; break; + case DR16_SW_MID: output->rc.sw[1] = CMD_SW_MID; break; + case DR16_SW_DOWN: output->rc.sw[1] = CMD_SW_DOWN; break; + default: output->rc.sw[1] = CMD_SW_ERR; break; } /* 拨轮映射 */ - output->dial = dr16->data.rc.ch_res; + output->rc.dial = dr16->data.rc.ch_res; return CMD_OK; } @@ -55,18 +55,18 @@ int8_t CMD_DR16_RC_GetInput(void *data, CMD_RawInput_t *output) { int8_t CMD_DR16_PC_GetInput(void *data, CMD_RawInput_t *output) { DR16_t *dr16 = (DR16_t *)data; - memset(output, 0, sizeof(CMD_RawInput_t)); + memset(&output->pc, 0, sizeof(CMD_RawInput_PC_t)); - output->online = dr16->header.online; + output->online[CMD_SRC_PC] = dr16->header.online; /* PC端鼠标映射 */ - output->mouse.x = dr16->data.pc.mouse.x; - output->mouse.y = dr16->data.pc.mouse.y; - output->mouse.l_click = dr16->data.pc.mouse.l_click; - output->mouse.r_click = dr16->data.pc.mouse.r_click; + output->pc.mouse.x = dr16->data.pc.mouse.x; + output->pc.mouse.y = dr16->data.pc.mouse.y; + output->pc.mouse.l_click = dr16->data.pc.mouse.l_click; + output->pc.mouse.r_click = dr16->data.pc.mouse.r_click; /* 键盘映射 */ - output->keyboard.bitmap = dr16->raw_data.key; + output->pc.keyboard.bitmap = dr16->raw_data.key; return CMD_OK; } @@ -95,9 +95,9 @@ int8_t CMD_AT9S_Init(void *data) { int8_t CMD_AT9S_GetInput(void *data, CMD_RawInput_t *output) { AT9S_t *at9s = (AT9S_t *)data; - memset(output, 0, sizeof(CMD_RawInput_t)); + memset(output, 0, sizeof(CMD_RawInput_RC_t)); - output->online = at9s->header.online; + output->online[CMD_SRC_RC] = at9s->header.online; /* TODO: 按照AT9S的数据格式进行映射 */ output->joy_left.x = at9s->data.rc.ch_l_x; @@ -159,8 +159,7 @@ int8_t CMD_Adapter_GetInput(CMD_InputSource_t source, CMD_RawInput_t *output) { CMD_InputAdapter_t *adapter = g_adapters[source]; if (adapter == NULL || adapter->get_input == NULL) { - memset(output, 0, sizeof(CMD_RawInput_t)); - output->online = false; + output->online[adapter->source] = false; return CMD_ERR_NO_INPUT; } diff --git a/User/module/cmd_v2/cmd_behavior.c b/User/module/cmd_v2/cmd_behavior.c index f174565..1b0773f 100644 --- a/User/module/cmd_v2/cmd_behavior.c +++ b/User/module/cmd_v2/cmd_behavior.c @@ -3,6 +3,7 @@ */ #include "cmd_behavior.h" #include "cmd.h" +#include "module/gimbal.h" #include /* ========================================================================== */ @@ -11,55 +12,52 @@ /* 行为处理函数实现 */ int8_t CMD_Behavior_Handle_FORE(CMD_t *ctx) { - ctx->chassis.cmd.ctrl_vec.vy += ctx->config->sensitivity.move_sens; + ctx->output.chassis.cmd.ctrl_vec.vy += ctx->config->sensitivity.move_sens; return CMD_OK; } int8_t CMD_Behavior_Handle_BACK(CMD_t *ctx) { - ctx->chassis.cmd.ctrl_vec.vy -= ctx->config->sensitivity.move_sens; + ctx->output.chassis.cmd.ctrl_vec.vy -= ctx->config->sensitivity.move_sens; return CMD_OK; } int8_t CMD_Behavior_Handle_LEFT(CMD_t *ctx) { - ctx->chassis.cmd.ctrl_vec.vx -= ctx->config->sensitivity.move_sens; + ctx->output.chassis.cmd.ctrl_vec.vx -= ctx->config->sensitivity.move_sens; return CMD_OK; } int8_t CMD_Behavior_Handle_RIGHT(CMD_t *ctx) { - ctx->chassis.cmd.ctrl_vec.vx += ctx->config->sensitivity.move_sens; + ctx->output.chassis.cmd.ctrl_vec.vx += ctx->config->sensitivity.move_sens; return CMD_OK; } int8_t CMD_Behavior_Handle_ACCELERATE(CMD_t *ctx) { - ctx->chassis.cmd.ctrl_vec.vx *= ctx->config->sensitivity.move_fast_mult; - ctx->chassis.cmd.ctrl_vec.vy *= ctx->config->sensitivity.move_fast_mult; + ctx->output.chassis.cmd.ctrl_vec.vx *= ctx->config->sensitivity.move_fast_mult; + ctx->output.chassis.cmd.ctrl_vec.vy *= ctx->config->sensitivity.move_fast_mult; return CMD_OK; } int8_t CMD_Behavior_Handle_DECELERATE(CMD_t *ctx) { - ctx->chassis.cmd.ctrl_vec.vx *= ctx->config->sensitivity.move_slow_mult; - ctx->chassis.cmd.ctrl_vec.vy *= ctx->config->sensitivity.move_slow_mult; + ctx->output.chassis.cmd.ctrl_vec.vx *= ctx->config->sensitivity.move_slow_mult; + ctx->output.chassis.cmd.ctrl_vec.vy *= ctx->config->sensitivity.move_slow_mult; return CMD_OK; } int8_t CMD_Behavior_Handle_FIRE(CMD_t *ctx) { - ctx->shoot.cmd.firecmd = true; + ctx->output.shoot.cmd.firecmd = true; return CMD_OK; } int8_t CMD_Behavior_Handle_FIRE_MODE(CMD_t *ctx) { - ctx->shoot.cmd.mode = (ctx->shoot.cmd.mode + 1) % SHOOT_MODE_NUM; + ctx->output.shoot.cmd.mode = (ctx->output.shoot.cmd.mode + 1) % SHOOT_MODE_NUM; return CMD_OK; } int8_t CMD_Behavior_Handle_ROTOR(CMD_t *ctx) { - if (ctx->chassis.cmd.mode == CHASSIS_MODE_ROTOR) { - ctx->chassis.cmd.mode = CHASSIS_MODE_FOLLOW_GIMBAL; - } else { - ctx->chassis.cmd.mode = CHASSIS_MODE_ROTOR; - ctx->chassis.cmd.mode_rotor = ROTOR_MODE_RAND; - } - return CMD_OK; + ctx->output.chassis.cmd.mode = CHASSIS_MODE_ROTOR; + ctx->output.chassis.cmd.mode_rotor = ROTOR_MODE_RAND; + ctx->output.gimbal.cmd.mode = GIMBAL_MODE_RELATIVE; + return CMD_OK; } int8_t CMD_Behavior_Handle_AUTOAIM(CMD_t *ctx) { @@ -67,12 +65,28 @@ int8_t CMD_Behavior_Handle_AUTOAIM(CMD_t *ctx) { return CMD_OK; } +int8_t CMD_Behavior_Handle_CHECKSOURCERCPC(CMD_t *ctx) { + /* TODO: 切换RC和PC输入源 */ + if (ctx->active_source == CMD_SRC_PC) { + ctx->active_source = CMD_SRC_RC; + ctx->output.chassis.source = CMD_SRC_RC; + ctx->output.gimbal.source = CMD_SRC_RC; + ctx->output.shoot.source = CMD_SRC_RC; + } else if(ctx->active_source == CMD_SRC_RC) { + ctx->active_source = CMD_SRC_PC; + ctx->output.chassis.source = CMD_SRC_PC; + ctx->output.gimbal.source = CMD_SRC_PC; + ctx->output.shoot.source = CMD_SRC_PC; + } + return CMD_OK; +} + /* 行为配置表 - 由宏生成 */ static const CMD_BehaviorConfig_t g_behavior_configs[] = { CMD_BEHAVIOR_TABLE(BUILD_BEHAVIOR_CONFIG) }; -#define BEHAVIOR_CONFIG_COUNT (sizeof(g_behavior_configs) / sizeof(g_behavior_configs[0])) +// #define BEHAVIOR_CONFIG_COUNT (sizeof(g_behavior_configs) / sizeof(g_behavior_configs[0])) /* ========================================================================== */ /* API实现 */ @@ -90,51 +104,37 @@ bool CMD_Behavior_IsTriggered(const CMD_RawInput_t *current, return false; } - bool now_pressed = false; - bool last_pressed = false; - - /* 处理特殊按键 */ - switch (config->key) { - case CMD_KEY_NONE: + bool now_pressed = false; + bool last_pressed = false; + + // 鼠标特殊按键处理 + if (config->key == (CMD_KEY_L_CLICK)) { + now_pressed = current->pc.mouse.l_click; + last_pressed = last ? last->pc.mouse.l_click : false; + } else if (config->key == (CMD_KEY_R_CLICK)) { + now_pressed = current->pc.mouse.r_click; + last_pressed = last ? last->pc.mouse.r_click : false; + } else if (config->key == (CMD_KEY_M_CLICK)) { + now_pressed = current->pc.mouse.m_click; + last_pressed = last ? last->pc.mouse.m_click : false; + } else if (config->key == 0) { return false; - - case CMD_KEY_L_CLICK: - now_pressed = current->mouse.l_click; - last_pressed = last ? last->mouse.l_click : false; - break; - - case CMD_KEY_R_CLICK: - now_pressed = current->mouse.r_click; - last_pressed = last ? last->mouse.r_click : false; - break; - - case CMD_KEY_M_CLICK: - now_pressed = current->mouse.m_click; - last_pressed = last ? last->mouse.m_click : false; - break; - - default: - if (config->key < CMD_KEY_NUM) { - now_pressed = CMD_KEY_PRESSED(¤t->keyboard, config->key); - last_pressed = last ? CMD_KEY_PRESSED(&last->keyboard, config->key) : false; - } - break; - } - - /* 根据触发类型判断 */ - switch (config->trigger) { - case CMD_ACTIVE_PRESSED: - return now_pressed; - - case CMD_ACTIVE_RISING_EDGE: - return now_pressed && !last_pressed; - - case CMD_ACTIVE_FALLING_EDGE: - return !now_pressed && last_pressed; - - default: - return false; - } + } else { + // 多按键组合检测 + now_pressed = ((current->pc.keyboard.bitmap & config->key) == config->key); + last_pressed = last ? ((last->pc.keyboard.bitmap & config->key) == config->key) : false; + } + + switch (config->trigger) { + case CMD_ACTIVE_PRESSED: + return now_pressed; + case CMD_ACTIVE_RISING_EDGE: + return now_pressed && !last_pressed; + case CMD_ACTIVE_FALLING_EDGE: + return !now_pressed && last_pressed; + default: + return false; + } } int8_t CMD_Behavior_ProcessAll(CMD_t *ctx, @@ -148,7 +148,7 @@ int8_t CMD_Behavior_ProcessAll(CMD_t *ctx, for (size_t i = 0; i < BEHAVIOR_CONFIG_COUNT; i++) { const CMD_BehaviorConfig_t *config = &g_behavior_configs[i]; - /* 检查模块掩码 */ + /* 过滤模块掩码 */ if ((config->module_mask & active_modules) == 0) { continue; } diff --git a/User/module/cmd_v2/cmd_behavior.h b/User/module/cmd_v2/cmd_behavior.h index 049cb7e..fda9074 100644 --- a/User/module/cmd_v2/cmd_behavior.h +++ b/User/module/cmd_v2/cmd_behavior.h @@ -21,7 +21,7 @@ typedef int8_t (*CMD_BehaviorHandler)(struct CMD_Context *ctx); /* 行为配置项 */ typedef struct { CMD_Behavior_t behavior; /* 行为枚举 */ - uint8_t key; /* 绑定的按键 */ + uint32_t key; /* 绑定的按键 */ CMD_TriggerType_t trigger; /* 触发类型 */ CMD_ModuleMask_t module_mask; /* 影响的模块 */ CMD_BehaviorHandler handler; /* 处理函数 */ diff --git a/User/module/cmd_v2/cmd_types.h b/User/module/cmd_v2/cmd_types.h index c009c88..961ea29 100644 --- a/User/module/cmd_v2/cmd_types.h +++ b/User/module/cmd_v2/cmd_types.h @@ -39,6 +39,17 @@ extern "C" { X(GIMBAL, Gimbal_CMD_t, gimbal) \ X(SHOOT, Shoot_CMD_t, shoot) + +/* ========================================================================== */ +/* 输入源枚举 */ +/* ========================================================================== */ +#define ENUM_INPUT_SOURCE(name, ...) CMD_SRC_##name, +typedef enum { + CMD_INPUT_SOURCE_TABLE(ENUM_INPUT_SOURCE) + CMD_SRC_NUM +} CMD_InputSource_t; +#undef ENUM_INPUT_SOURCE + /* ========================================================================== */ /* 统一输入数据结构 */ /* ========================================================================== */ @@ -74,10 +85,10 @@ typedef struct { /* 键盘按键索引 */ typedef enum { - CMD_KEY_W = 0, CMD_KEY_S, CMD_KEY_A, CMD_KEY_D, - CMD_KEY_SHIFT, CMD_KEY_CTRL, CMD_KEY_Q, CMD_KEY_E, - CMD_KEY_R, CMD_KEY_F, CMD_KEY_G, CMD_KEY_Z, - CMD_KEY_X, CMD_KEY_C, CMD_KEY_V, CMD_KEY_B, + CMD_KEY_W = (1 << 0), CMD_KEY_S = (1 << 1), CMD_KEY_A = (1 << 2), CMD_KEY_D = (1 << 3), + CMD_KEY_SHIFT = (1 << 4), CMD_KEY_CTRL = (1 << 5), CMD_KEY_Q = (1 << 6), CMD_KEY_E = (1 << 7), + CMD_KEY_R = (1 << 8), CMD_KEY_F = (1 << 9), CMD_KEY_G = (1 << 10), CMD_KEY_Z = (1 << 11), + CMD_KEY_X = (1 << 12), CMD_KEY_C = (1 << 13), CMD_KEY_V = (1 << 14), CMD_KEY_B = (1 << 15), CMD_KEY_NUM } CMD_KeyIndex_t; @@ -86,64 +97,72 @@ typedef struct { uint8_t game_status; /* 比赛状态 */ } CMD_Referee_t; +typedef struct { + CMD_Joystick_t joy_left; /* 左摇杆 */ + CMD_Joystick_t joy_right; /* 右摇杆 */ + CMD_SwitchPos_t sw[4]; /* 4个拨杆 */ + float dial; /* 拨轮 */ +} CMD_RawInput_RC_t; + +typedef struct { + CMD_Mouse_t mouse; + CMD_Keyboard_t keyboard; +} CMD_RawInput_PC_t; + +typedef struct { + int a; +} CMD_RawInput_NUC_t; + +typedef struct { + CMD_Referee_t referee; +} CMD_RawInput_REF_t; + /* 统一的原始输入结构 - 所有设备适配后都转换成这个格式 */ typedef struct { - bool online; - + bool online[CMD_SRC_NUM]; + /* 遥控器部分 */ - CMD_Joystick_t joy_left; /* 左摇杆 */ - CMD_Joystick_t joy_right; /* 右摇杆 */ - CMD_SwitchPos_t sw[4]; /* 最多4个拨杆 */ - float dial; /* 拨轮 */ - + CMD_RawInput_RC_t rc; + /* PC部分 */ - CMD_Mouse_t mouse; - CMD_Keyboard_t keyboard; - + CMD_RawInput_PC_t pc; + /* NUC部分 */ /* 暂无定义,预留扩展 */ - - /* REF部分 - 裁判系统数据 */ - CMD_Referee_t referee; -} CMD_RawInput_t; + CMD_RawInput_NUC_t nuc; -/* ========================================================================== */ -/* 输入源枚举 */ -/* ========================================================================== */ -#define ENUM_INPUT_SOURCE(name, ...) CMD_SRC_##name, -typedef enum { - CMD_INPUT_SOURCE_TABLE(ENUM_INPUT_SOURCE) - CMD_SRC_NUM -} CMD_InputSource_t; -#undef ENUM_INPUT_SOURCE + /* REF部分 - 裁判系统数据 */ + CMD_RawInput_REF_t ref; +} CMD_RawInput_t; /* ========================================================================== */ /* 模块掩码 */ /* ========================================================================== */ typedef enum { - CMD_MODULE_NONE = 0, - CMD_MODULE_CHASSIS = (1 << 0), - CMD_MODULE_GIMBAL = (1 << 1), - CMD_MODULE_SHOOT = (1 << 2), - CMD_MODULE_ALL = 0x07 + CMD_MODULE_NONE = (1 << 0), + CMD_MODULE_CHASSIS = (1 << 1), + CMD_MODULE_GIMBAL = (1 << 2), + CMD_MODULE_SHOOT = (1 << 3), + CMD_MODULE_ALL = 0x0E } CMD_ModuleMask_t; /* ========================================================================== */ /* 行为定义 */ /* ========================================================================== */ /* 行为-按键映射宏表 */ +#define BEHAVIOR_CONFIG_COUNT (11) #define CMD_BEHAVIOR_TABLE(X) \ - X(FORE, CMD_KEY_W, CMD_ACTIVE_PRESSED, CMD_MODULE_CHASSIS) \ - X(BACK, CMD_KEY_S, CMD_ACTIVE_PRESSED, CMD_MODULE_CHASSIS) \ - X(LEFT, CMD_KEY_A, CMD_ACTIVE_PRESSED, CMD_MODULE_CHASSIS) \ - X(RIGHT, CMD_KEY_D, CMD_ACTIVE_PRESSED, CMD_MODULE_CHASSIS) \ - X(ACCELERATE, CMD_KEY_SHIFT, CMD_ACTIVE_PRESSED, CMD_MODULE_CHASSIS) \ - X(DECELERATE, CMD_KEY_CTRL, CMD_ACTIVE_PRESSED, CMD_MODULE_CHASSIS) \ - X(FIRE, CMD_KEY_L_CLICK, CMD_ACTIVE_PRESSED, CMD_MODULE_SHOOT) \ - X(FIRE_MODE, CMD_KEY_B, CMD_ACTIVE_RISING_EDGE, CMD_MODULE_SHOOT) \ - X(ROTOR, CMD_KEY_E, CMD_ACTIVE_RISING_EDGE, CMD_MODULE_CHASSIS) \ - X(AUTOAIM, CMD_KEY_R, CMD_ACTIVE_RISING_EDGE, CMD_MODULE_GIMBAL | CMD_MODULE_SHOOT) - + X(FORE, CMD_KEY_W, CMD_ACTIVE_PRESSED, CMD_MODULE_CHASSIS) \ + X(BACK, CMD_KEY_S, CMD_ACTIVE_PRESSED, CMD_MODULE_CHASSIS) \ + X(LEFT, CMD_KEY_A, CMD_ACTIVE_PRESSED, CMD_MODULE_CHASSIS) \ + X(RIGHT, CMD_KEY_D, CMD_ACTIVE_PRESSED, CMD_MODULE_CHASSIS) \ + X(ACCELERATE, CMD_KEY_SHIFT, CMD_ACTIVE_PRESSED, CMD_MODULE_CHASSIS) \ + X(DECELERATE, CMD_KEY_CTRL, CMD_ACTIVE_PRESSED, CMD_MODULE_CHASSIS) \ + X(FIRE, CMD_KEY_L_CLICK, CMD_ACTIVE_PRESSED, CMD_MODULE_SHOOT) \ + X(FIRE_MODE, CMD_KEY_B, CMD_ACTIVE_RISING_EDGE, CMD_MODULE_SHOOT) \ + X(ROTOR, CMD_KEY_E, CMD_ACTIVE_PRESSED, CMD_MODULE_CHASSIS) \ + X(AUTOAIM, CMD_KEY_R, CMD_ACTIVE_RISING_EDGE, CMD_MODULE_GIMBAL | CMD_MODULE_SHOOT) \ + X(CHECKSOURCERCPC, CMD_KEY_CTRL|CMD_KEY_SHIFT|CMD_KEY_V, CMD_ACTIVE_RISING_EDGE, CMD_MODULE_NONE) /* 触发类型 */ typedef enum { CMD_ACTIVE_PRESSED, /* 按住时触发 */ @@ -153,9 +172,9 @@ typedef enum { /* 特殊按键值 */ #define CMD_KEY_NONE 0xFF -#define CMD_KEY_L_CLICK 0xFE -#define CMD_KEY_R_CLICK 0xFD -#define CMD_KEY_M_CLICK 0xFC +#define CMD_KEY_L_CLICK (1 << 31) +#define CMD_KEY_R_CLICK (1 << 30) +#define CMD_KEY_M_CLICK (1 << 29) /* 行为枚举 - 由宏表自动生成 */ #define ENUM_BEHAVIOR(name, key, trigger, mask) CMD_BEHAVIOR_##name, diff --git a/User/module/config.c b/User/module/config.c index fcc0719..8b5baef 100644 --- a/User/module/config.c +++ b/User/module/config.c @@ -189,14 +189,14 @@ Config_RobotParam_t robot_config = { .gyro = 1000.0f, }, .pit_motor ={ - .can = BSP_CAN_2, + .can = BSP_CAN_1, .can_id = 0x2, .master_id = 0x12, .module = MOTOR_DM_J4310, .reverse = false, }, .yaw_motor = { - .can = BSP_CAN_2, + .can = BSP_CAN_1, .can_id = 0x50, .master_id = 0x60, .module = MOTOR_DM_J4310, diff --git a/ozone/hero.jdebug b/ozone/hero.jdebug index 8338e09..9b4610d 100644 --- a/ozone/hero.jdebug +++ b/ozone/hero.jdebug @@ -5,7 +5,7 @@ ********************************************************************** File : -Created : 02. Nov 2025 13:12 +Created : 16. Dec 2025 21:10 Ozone Version : V3.40b */ @@ -32,7 +32,6 @@ void OnProjectLoad (void) { // // User settings // - Edit.SysVar (VAR_HSS_SPEED, "200 Hz"); File.Open ("D:/CUBEMX/hero/god-yuan-hero/build/Debug/hero.elf"); } @@ -338,8 +337,25 @@ void AfterTargetDownload (void) { ********************************************************************** */ void _SetupTarget(void) { + unsigned int SP; + unsigned int PC; + unsigned int VectorTableAddr; + + VectorTableAddr = Elf.GetBaseAddr(); // - // this function is intentionally empty because both inital PC and - // initial SP were chosen not to be set + // Set up initial stack pointer // + SP = Target.ReadU32(VectorTableAddr); + if (SP != 0xFFFFFFFF) { + Target.SetReg("SP", SP); + } + // + // Set up entry point PC + // + PC = Elf.GetEntryPointPC(); + if (PC != 0xFFFFFFFF) { + Target.SetReg("PC", PC); + } else { + Util.Error("Project script error: failed to set up entry point PC", 1); + } } \ No newline at end of file diff --git a/ozone/hero.jdebug.user b/ozone/hero.jdebug.user index f3a8f50..e69cc88 100644 --- a/ozone/hero.jdebug.user +++ b/ozone/hero.jdebug.user @@ -1,78 +1,56 @@ -Breakpoint=D:/CUBEMX/hero/god-yuan-hero/User/module/shoot.c:367:7, State=BP_STATE_DISABLED -GraphedExpression="(((shoot).feedback).fric[0]).rotor_speed", Color=#e56a6f -GraphedExpression="(((shoot).feedback).fric[1]).rotor_speed", Color=#35792b -GraphedExpression="(((shoot).feedback).fric[2]).rotor_speed", Color=#769dda -GraphedExpression="(((shoot).feedback).fric[3]).rotor_speed", Color=#b14f0d -GraphedExpression="(((shoot).feedback).fric[4]).rotor_speed", Color=#b3c38e -GraphedExpression="(((shoot).feedback).fric[5]).rotor_speed", Color=#ab7b05 -GraphedExpression="(shoot).errtosee", Color=#7fd3b7, Show=0 -OpenDocument="memcpy.c", FilePath="/build/gnu-tools-for-stm32_13.3.rel1.20250523-0900/src/newlib/newlib/libc/string/memcpy.c", Line=0 -OpenDocument="can.c", FilePath="D:/CUBEMX/hero/god-yuan-hero/User/bsp/can.c", Line=69 -OpenDocument="tasks.c", FilePath="D:/CUBEMX/hero/god-yuan-hero/Middlewares/Third_Party/FreeRTOS/Source/tasks.c", Line=3419 -OpenDocument="device.h", FilePath="D:/CUBEMX/hero/god-yuan-hero/User/device/device.h", Line=5 -OpenDocument="cmd.h", FilePath="D:/CUBEMX/hero/god-yuan-hero/User/module/cmd.h", Line=60 -OpenDocument="cmd.c", FilePath="D:/CUBEMX/hero/god-yuan-hero/User/module/cmd.c", Line=416 -OpenDocument="cmd.c", FilePath="D:/CUBEMX/hero/god-yuan-hero/User/task/cmd.c", Line=0 -OpenDocument="pid.h", FilePath="D:/CUBEMX/hero/god-yuan-hero/User/component/pid.h", Line=53 +Breakpoint=D:/CUBEMX/hero/god-yuan-hero/User/module/cmd_v2/cmd_adapter.c:32, State=BP_STATE_DISABLED +Breakpoint=D:/CUBEMX/hero/god-yuan-hero/User/module/cmd_v2/cmd.c:249:16, State=BP_STATE_DISABLED +GraphedExpression="(cmd).active_source", DisplayFormat=DISPLAY_FORMAT_DEC, Color=#e56a6f +GraphedExpression="(((cmd).output).chassis).source", DisplayFormat=DISPLAY_FORMAT_DEC, Color=#35792b +GraphedExpression="((((cmd).input).pc).keyboard).bitmap", DisplayFormat=DISPLAY_FORMAT_DEC, Color=#769dda, Show=0 +GraphedExpression="((dr16).raw_data).key", DisplayFormat=DISPLAY_FORMAT_DEC, Color=#b14f0d, Show=0 +OpenDocument="stm32f4xx_hal_can.c", FilePath="D:/CUBEMX/hero/god-yuan-hero/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_can.c", Line=1614 OpenDocument="startup_stm32f407xx.s", FilePath="D:/CUBEMX/hero/god-yuan-hero/startup_stm32f407xx.s", Line=48 -OpenDocument="motor_dm.h", FilePath="D:/CUBEMX/hero/god-yuan-hero/User/device/motor_dm.h", Line=45 -OpenDocument="can.h", FilePath="D:/CUBEMX/hero/god-yuan-hero/User/bsp/can.h", Line=0 -OpenDocument="shoot.h", FilePath="D:/CUBEMX/hero/god-yuan-hero/User/module/shoot.h", Line=78 -OpenDocument="ctrl_gimbal.c", FilePath="D:/CUBEMX/hero/god-yuan-hero/User/task/ctrl_gimbal.c", Line=11 -OpenDocument="main.c", FilePath="D:/CUBEMX/hero/god-yuan-hero/Core/Src/main.c", Line=60 -OpenDocument="rc.c", FilePath="D:/CUBEMX/hero/god-yuan-hero/User/task/rc.c", Line=0 -OpenDocument="shoot.c", FilePath="D:/CUBEMX/hero/god-yuan-hero/User/module/shoot.c", Line=346 -OpenDocument="config.c", FilePath="D:/CUBEMX/hero/god-yuan-hero/User/module/config.c", Line=0 -OpenDocument="config.h", FilePath="D:/CUBEMX/hero/god-yuan-hero/User/module/config.h", Line=0 -OpenDocument="chassis.h", FilePath="D:/CUBEMX/hero/god-yuan-hero/User/module/chassis.h", Line=133 -OpenDocument="stm32f4xx_hal_dma.c", FilePath="D:/CUBEMX/hero/god-yuan-hero/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma.c", Line=710 -OpenDocument="stm32f4xx_hal_can.c", FilePath="D:/CUBEMX/hero/god-yuan-hero/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_can.c", Line=1994 -OpenDocument="stm32f4xx_hal_msp.c", FilePath="D:/CUBEMX/hero/god-yuan-hero/Core/Src/stm32f4xx_hal_msp.c", Line=28 -OpenDocument="usart.c", FilePath="D:/CUBEMX/hero/god-yuan-hero/Core/Src/usart.c", Line=179 -OpenDocument="ctrl_chassis.c", FilePath="D:/CUBEMX/hero/god-yuan-hero/User/task/ctrl_chassis.c", Line=6 -OpenDocument="gimbal.c", FilePath="D:/CUBEMX/hero/god-yuan-hero/User/module/gimbal.c", Line=0 +OpenDocument="memcpy.c", FilePath="/build/gnu-tools-for-stm32_13.3.rel1.20250523-0900/src/newlib/newlib/libc/string/memcpy.c", Line=0 +OpenDocument="dma.c", FilePath="D:/CUBEMX/hero/god-yuan-hero/Core/Src/dma.c", Line=21 OpenDocument="ctrl_shoot.c", FilePath="D:/CUBEMX/hero/god-yuan-hero/User/task/ctrl_shoot.c", Line=2 -OpenDocument="user_task.c", FilePath="D:/CUBEMX/hero/god-yuan-hero/User/task/user_task.c", Line=0 -OpenDocument="stm32f4xx_it.c", FilePath="D:/CUBEMX/hero/god-yuan-hero/Core/Src/stm32f4xx_it.c", Line=83 +OpenDocument="pid.h", FilePath="D:/CUBEMX/hero/god-yuan-hero/User/component/pid.h", Line=60 +OpenDocument="can.c", FilePath="D:/CUBEMX/hero/god-yuan-hero/User/bsp/can.c", Line=60 +OpenDocument="cmsis_os2.c", FilePath="D:/CUBEMX/hero/god-yuan-hero/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os2.c", Line=382 +OpenDocument="time.c", FilePath="D:/CUBEMX/hero/god-yuan-hero/User/bsp/time.c", Line=18 +OpenDocument="tasks.c", FilePath="D:/CUBEMX/hero/god-yuan-hero/Middlewares/Third_Party/FreeRTOS/Source/tasks.c", Line=3419 +OpenDocument="queue.c", FilePath="D:/CUBEMX/hero/god-yuan-hero/Middlewares/Third_Party/FreeRTOS/Source/queue.c", Line=1425 +OpenDocument="cmd_adapter.c", FilePath="D:/CUBEMX/hero/god-yuan-hero/User/module/cmd_v2/cmd_adapter.c", Line=88 +OpenDocument="cmd.c", FilePath="D:/CUBEMX/hero/god-yuan-hero/User/module/cmd_v2/cmd.c", Line=81 +OpenDocument="cmd_behavior.c", FilePath="D:/CUBEMX/hero/god-yuan-hero/User/module/cmd_v2/cmd_behavior.c", Line=43 +OpenDocument="cmd.c", FilePath="D:/CUBEMX/hero/god-yuan-hero/User/task/cmd.c", Line=28 +OpenDocument="rc.c", FilePath="D:/CUBEMX/hero/god-yuan-hero/User/task/rc.c", Line=0 +OpenDocument="main.c", FilePath="D:/CUBEMX/hero/god-yuan-hero/Core/Src/main.c", Line=60 OpenToolbar="Debug", Floating=0, x=0, y=0 -OpenWindow="Registers 1", DockArea=RIGHT, x=0, y=1, w=726, h=515, TabPos=2, TopOfStack=0, FilterBarShown=0, TotalValueBarShown=0, ToolBarShown=0, FilteredItems=[], RefreshRate=1 +OpenWindow="Registers 1", DockArea=RIGHT, x=0, y=1, w=726, h=509, TabPos=1, TopOfStack=0, FilterBarShown=0, TotalValueBarShown=0, ToolBarShown=0, FilteredItems=[], RefreshRate=1 OpenWindow="Source Files", DockArea=LEFT, x=0, y=0, w=301, h=919, TabPos=0, TopOfStack=1, FilterBarShown=0, TotalValueBarShown=0, ToolBarShown=0 -OpenWindow="Disassembly", DockArea=RIGHT, x=0, y=0, w=726, h=403, FilterBarShown=0, TotalValueBarShown=0, ToolBarShown=0 -OpenWindow="Watched Data 1", DockArea=RIGHT, x=0, y=1, w=726, h=515, TabPos=1, TopOfStack=1, FilterBarShown=0, TotalValueBarShown=0, ToolBarShown=0 +OpenWindow="Disassembly", DockArea=RIGHT, x=0, y=0, w=726, h=409, FilterBarShown=0, TotalValueBarShown=0, ToolBarShown=0 +OpenWindow="Watched Data 1", DockArea=RIGHT, x=0, y=1, w=726, h=509, TabPos=0, TopOfStack=1, FilterBarShown=0, TotalValueBarShown=0, ToolBarShown=0 OpenWindow="Functions", DockArea=LEFT, x=0, y=0, w=301, h=919, TabPos=1, TopOfStack=0, FilterBarShown=0, TotalValueBarShown=0, ToolBarShown=0 -OpenWindow="Data Sampling", DockArea=BOTTOM, x=1, y=0, w=291, h=536, TabPos=0, TopOfStack=1, FilterBarShown=0, TotalValueBarShown=0, ToolBarShown=0, VisibleTab=0, UniformSampleSpacing=0 -OpenWindow="Timeline", DockArea=BOTTOM, x=0, y=0, w=2268, h=555, FilterBarShown=0, TotalValueBarShown=0, ToolBarShown=1, DataPaneShown=1, PowerPaneShown=0, CodePaneShown=0, PinCursor="Cursor Movable", TimePerDiv="500 ms / Div", TimeStampFormat="Time", DataGraphDrawAsPoints=0, DataGraphLegendShown=1, DataGraphUniformSampleSpacing=0, DataGraphLegendPosition="34;98", DataGraphShowNamesAtCursor=0, PowerGraphDrawAsPoints=0, PowerGraphLegendShown=0, PowerGraphAvgFilterTime=Off, PowerGraphAvgFilterLen=Off, PowerGraphUniformSampleSpacing=0, PowerGraphLegendPosition="1266;0", CodeGraphLegendShown=0, CodeGraphLegendPosition="1282;0" -OpenWindow="Console", DockArea=BOTTOM, x=1, y=0, w=291, h=536, TabPos=1, TopOfStack=0, FilterBarShown=0, TotalValueBarShown=0, ToolBarShown=0 -OpenWindow="Watched Data 2", DockArea=RIGHT, x=0, y=1, w=726, h=515, TabPos=0, TopOfStack=0, FilterBarShown=0, TotalValueBarShown=0, ToolBarShown=0 +OpenWindow="Data Sampling", DockArea=BOTTOM, x=1, y=0, w=984, h=536, TabPos=0, TopOfStack=1, FilterBarShown=0, TotalValueBarShown=0, ToolBarShown=0, VisibleTab=0, UniformSampleSpacing=0 +OpenWindow="Timeline", DockArea=BOTTOM, x=0, y=0, w=1575, h=555, FilterBarShown=0, TotalValueBarShown=0, ToolBarShown=1, DataPaneShown=1, PowerPaneShown=0, CodePaneShown=0, PinCursor="Cursor Movable", TimePerDiv="1 s / Div", TimeStampFormat="Time", DataGraphDrawAsPoints=0, DataGraphLegendShown=1, DataGraphUniformSampleSpacing=0, DataGraphLegendPosition="91;96", DataGraphShowNamesAtCursor=0, PowerGraphDrawAsPoints=0, PowerGraphLegendShown=0, PowerGraphAvgFilterTime=Off, PowerGraphAvgFilterLen=Off, PowerGraphUniformSampleSpacing=0, PowerGraphLegendPosition="1630;0", CodeGraphLegendShown=0, CodeGraphLegendPosition="1581;0" +OpenWindow="Console", DockArea=BOTTOM, x=1, y=0, w=984, h=536, TabPos=1, TopOfStack=0, FilterBarShown=0, TotalValueBarShown=0, ToolBarShown=0 SmartViewPlugin="", Page="", Toolbar="Hidden", Window="SmartView 1" -TableHeader="Watched Data 2", SortCol="Expression", SortOrder="ASCENDING", VisibleCols=["Expression";"Value";"Location";"Refresh"], ColWidths=[170;352;100;104] -TableHeader="Watched Data 1", SortCol="Expression", SortOrder="ASCENDING", VisibleCols=["Expression";"Value";"Location";"Refresh"], ColWidths=[250;282;91;100] -TableHeader="Registers 1", SortCol="Name", SortOrder="ASCENDING", VisibleCols=["Name";"Value";"Description"], ColWidths=[120;144;462] -TableHeader="Functions", SortCol="Name", SortOrder="ASCENDING", VisibleCols=["Name";"Address";"Size";"#Insts";"Source"], ColWidths=[1594;104;100;100;100] -TableHeader="Power Sampling", SortCol="None", SortOrder="ASCENDING", VisibleCols=["Index";"Time";"Ch 0"], ColWidths=[100;100;100] -TableHeader="RegisterSelectionDialog", SortCol="None", SortOrder="ASCENDING", VisibleCols=[], ColWidths=[] +TableHeader="Registers 1", SortCol="Name", SortOrder="ASCENDING", VisibleCols=["Name";"Value";"Description"], ColWidths=[120;144;294] +TableHeader="Functions", SortCol="Name", SortOrder="ASCENDING", VisibleCols=["Name";"Address";"Size";"#Insts";"Source"], ColWidths=[1594;104;100;100;798] TableHeader="Source Files", SortCol="File", SortOrder="ASCENDING", VisibleCols=["File";"Status";"Size";"#Insts";"Path"], ColWidths=[215;100;100;100;1014] -TableHeader="Data Sampling Table", SortCol="None", SortOrder="ASCENDING", VisibleCols=["Index";"Time";" (((shoot).feedback).fric[0]).rotor_speed";" (((shoot).feedback).fric[1]).rotor_speed";" (((shoot).feedback).fric[2]).rotor_speed";" (((shoot).feedback).fric[3]).rotor_speed";" (((shoot).feedback).fric[4]).rotor_speed";" (((shoot).feedback).fric[5]).rotor_speed";" (shoot).errtosee"], ColWidths=[100;100;100;100;100;100;100;100;100] -TableHeader="Data Sampling Setup", SortCol="Expression", SortOrder="ASCENDING", VisibleCols=["Expression";"Type";"Value";"Min";"Max";"Average";"# Changes";"Min. Change";"Max. Change"], ColWidths=[118;100;100;100;100;124;110;126;126] +TableHeader="Data Sampling Table", SortCol="None", SortOrder="ASCENDING", VisibleCols=["Index";"Time";" (cmd).active_source";" (((cmd).output).chassis).source";" ((((cmd).input).pc).keyboard).bitmap";" ((dr16).raw_data).key"], ColWidths=[100;100;100;100;100;100] +TableHeader="Data Sampling Setup", SortCol="Expression", SortOrder="ASCENDING", VisibleCols=["Expression";"Type";"Value";"Min";"Max";"Average";"# Changes";"Min. Change";"Max. Change"], ColWidths=[118;234;100;100;100;124;110;144;126] +TableHeader="Power Sampling", SortCol="None", SortOrder="ASCENDING", VisibleCols=["Index";"Time";"Ch 0"], ColWidths=[100;100;100] +TableHeader="Watched Data 1", SortCol="Expression", SortOrder="ASCENDING", VisibleCols=["Expression";"Value";"Location";"Refresh"], ColWidths=[250;282;91;100] +TableHeader="RegisterSelectionDialog", SortCol="None", SortOrder="ASCENDING", VisibleCols=[], ColWidths=[] TableHeader="TargetExceptionDialog", SortCol="Name", SortOrder="ASCENDING", VisibleCols=["Name";"Value";"Address";"Description"], ColWidths=[200;100;100;366] -WatchedExpression="0x20008DD8", Window=Watched Data 1 -WatchedExpression="cmd", RefreshRate=5, Window=Watched Data 1 -WatchedExpression="robot_config", RefreshRate=5, Window=Watched Data 1 -WatchedExpression="shoot", RefreshRate=5, Window=Watched Data 1 -WatchedExpression="at9s", RefreshRate=5, Window=Watched Data 1 WatchedExpression="dr16", RefreshRate=5, Window=Watched Data 1 -WatchedExpression="shoot_cmd", RefreshRate=5, Window=Watched Data 1 -WatchedExpression="chassis", RefreshRate=5, Window=Watched Data 1 -WatchedExpression="chassis_cmd", RefreshRate=5, Window=Watched Data 1 -WatchedExpression="gimbal_cmd", RefreshRate=5, Window=Watched Data 1 -WatchedExpression="gimbal", RefreshRate=5, Window=Watched Data 1 -WatchedExpression="at9s_out", RefreshRate=5, Window=Watched Data 1 WatchedExpression="cmd_dr16", RefreshRate=5, Window=Watched Data 1 -WatchedExpression="rc_buffer", RefreshRate=5, Window=Watched Data 1 -WatchedExpression="cmd", RefreshRate=5, Window=Watched Data 2 -WatchedExpression="cmd_dr16", Window=Watched Data 2 -WatchedExpression="dr16", RefreshRate=5, Window=Watched Data 2 -WatchedExpression="gimbal", RefreshRate=5, Window=Watched Data 2 \ No newline at end of file +WatchedExpression="cmd", RefreshRate=5, Window=Watched Data 1 +WatchedExpression="g_adapters", RefreshRate=5, Window=Watched Data 1 +WatchedExpression="cmd_for_chassis", RefreshRate=5, Window=Watched Data 1 +WatchedExpression="shoot_cmd", RefreshRate=5, Window=Watched Data 1 +WatchedExpression="cmd_for_gimbal", RefreshRate=5, Window=Watched Data 1 +WatchedExpression="last_shift", Window=Watched Data 1 +WatchedExpression="now_shift", Window=Watched Data 1 +WatchedExpression="last_v", Window=Watched Data 1 +WatchedExpression="now_v", Window=Watched Data 1 \ No newline at end of file