/* 控制命令 */ #include "module/cmd.h" #include #include /*************************************************************************************************************************************/ /***************************************************************仲裁器****************************************************************/ /*************************************************************************************************************************************/ /* Includes ----------------------------------------------------------------- */ /* Private typedef ---------------------------------------------------------- */ /* Private define ----------------------------------------------------------- */ /* Private macro ------------------------------------------------------------ */ /* Private variables -------------------------------------------------------- */ /* Private function -------------------------------------------------------- */ bool isREFOnline(CMD_t *c){return c->inputData.ref.online;} bool isNUCOnline(CMD_t *c){return c->inputData.nuc.online;} bool isRCOnline(CMD_t *c){return c->inputData.rc.online;} bool isPCOnline(CMD_t *c){return c->inputData.pc.online;} void PriorityConfigsRanking(CMD_Param_t *param) { static bool init=false; if(init) return; for (int i = 0; i < CMD_SRC_NUM - 1; i++) { for (int j = 0; j < CMD_SRC_NUM - i - 1; j++) { if (param->sourcePriorityConfigs[j].priority < param->sourcePriorityConfigs[j + 1].priority) { CMD_SourcePriorityConfig_t temp = param->sourcePriorityConfigs[j]; param->sourcePriorityConfigs[j] = param->sourcePriorityConfigs[j + 1]; param->sourcePriorityConfigs[j + 1] = temp; } } } init=!init; } CMD_InputSource_t getHighestPrioritySource(CMD_t *c) { for (int i = 0; i < CMD_SRC_NUM; i++) { CMD_InputSource_t source = c->params.sourcePriorityConfigs[i].source; switch (source) { case CMD_SRC_REFEREE: if (isREFOnline(c)) { return CMD_SRC_REFEREE; } break; case CMD_SRC_NUC: if (isNUCOnline(c)) { return CMD_SRC_NUC; } break; case CMD_SRC_RC: if (isRCOnline(c)) { return CMD_SRC_RC; } break; case CMD_SRC_PC: if (isPCOnline(c)) { return CMD_SRC_PC; } } } return CMD_SRC_ERR; } int8_t Cmd_Arbiter(CMD_t *c) { if (c == NULL) { return CMD_ERR_NULL; // 参数错误 } PriorityConfigsRanking(&c->params); CMD_InputSource_t source = getHighestPrioritySource(c); c->outCmd.chassis.source = source; c->outCmd.gimbal.source = source; c->outCmd.shoot.source = source; return CMD_OK; } /* Exported functions ------------------------------------------------------- */ /*************************************************************************************************************************************/ /****************************************************************RC*******************************************************************/ /*************************************************************************************************************************************/ /* API ---------------------------------------------------------------------- */ /* Mrobot生成 */ #define RC_SELECT_Index 1 /* 扩展接口 */ #if RC_SELECT_Index == 0 #define FOR_EACH_RC(X) X(dr16, DR16) #elif RC_SELECT_Index == 1 #define FOR_EACH_RC(X) X(at9s, AT9S) #endif /* Includes ----------------------------------------------------------------- */ #if RC_SELECT_Index == 0 #include "device/dr16.h" #elif RC_SELECT_Index == 1 #include "device/at9s_pro.h" #endif /* Private typedef ---------------------------------------------------------- */ /* Private define ----------------------------------------------------------- */ /* Private macro ------------------------------------------------------------ */ #define RC_X_FIELD_MACRO(name, NAME) DEVICE_##NAME##_t name; #define RC_X_EXTERN_MACRO(name, NAME) extern DEVICE_##NAME##_t name##_out; #define RC_X_COPYDEFINE_MACRO(name, NAME) \ static void copy_##name(rc_inputdata_u *dst) { dst->name = name##_out; } #define RC_X_COPYREFERENCE_MACRO(name, NAME) copy_##name, union rc_inputdata_u{ FOR_EACH_RC(RC_X_FIELD_MACRO) }; FOR_EACH_RC(RC_X_EXTERN_MACRO) FOR_EACH_RC(RC_X_COPYDEFINE_MACRO) /* Private variables -------------------------------------------------------- */ /*静态缓冲区*/ static rc_inputdata_u rc_buffer; /* Private function -------------------------------------------------------- */ int8_t Cmd_Get_rc(CMD_InputData_RC_t *rc) { FOR_EACH_RC(RC_X_COPYREFERENCE_MACRO)(&rc_buffer); rc->inputData = &rc_buffer; rc->type = RC_SELECT_Index; return CMD_OK; } int8_t Cmd_BuildChassisCommandFromInput_rc(CMD_t *c) { if (c == NULL) { return CMD_ERR_NULL; // 参数错误 } #if RC_SELECT_Index == 0 c->input_rc.inputData->dr16.data = #elif RC_SELECT_Index == 1 switch (c->inputData.rc.inputData->at9s.data.key_E) { case AT9S_CMD_SW_DOWN: c->outCmd.chassis.cmd.mode = CHASSIS_MODE_RELAX; break; case AT9S_CMD_SW_MID: c->outCmd.chassis.cmd.mode = CHASSIS_MODE_FOLLOW_GIMBAL; break; case AT9S_CMD_SW_UP: c->outCmd.chassis.cmd.mode = CHASSIS_MODE_ROTOR; break; default: c->outCmd.chassis.cmd.mode = CHASSIS_MODE_RELAX; break; } c->outCmd.chassis.cmd.ctrl_vec.vx = c->inputData.rc.inputData->at9s.data.ch_l_y; c->outCmd.chassis.cmd.ctrl_vec.vy = c->inputData.rc.inputData->at9s.data.ch_l_x; c->outCmd.chassis.cmd.ctrl_vec.wz = c->inputData.rc.inputData->at9s.data.ch_r_x; #endif return CMD_OK; } int8_t Cmd_BuildGimbalCommandFromInput_rc(CMD_t *c) { if (c == NULL) { return CMD_ERR_NULL; // 参数错误 } #if RC_SELECT_Index == 0 c->input_rc.inputData->dr16.data = #elif RC_SELECT_Index == 1 switch (c->inputData.rc.inputData->at9s.data.key_G) { case AT9S_CMD_SW_DOWN: c->outCmd.gimbal.cmd.mode = GIMBAL_MODE_RELAX; c->outCmd.gimbal.cmd.delta_yaw = 0.0f; c->outCmd.gimbal.cmd.delta_pit = 0.0f; break; case AT9S_CMD_SW_MID: c->outCmd.gimbal.cmd.mode = GIMBAL_MODE_ABSOLUTE; c->outCmd.gimbal.cmd.delta_yaw = -at9s_out.data.ch_l_x * 2.0f; c->outCmd.gimbal.cmd.delta_pit = -at9s_out.data.ch_l_y * 1.5f; break; case AT9S_CMD_SW_UP: c->outCmd.gimbal.cmd.mode = GIMBAL_MODE_ABSOLUTE; c->outCmd.gimbal.cmd.delta_yaw = -at9s_out.data.ch_l_x * 2.0f; c->outCmd.gimbal.cmd.delta_pit = -at9s_out.data.ch_l_y * 1.5f; break; default: c->outCmd.gimbal.cmd.mode = GIMBAL_MODE_RELAX; c->outCmd.gimbal.cmd.delta_yaw = 0.0f; c->outCmd.gimbal.cmd.delta_pit = 0.0f; break; } #endif return CMD_OK; } int8_t Cmd_BuildShootCommandFromInput_rc(CMD_t *c) { if (c == NULL) { return CMD_ERR_NULL; // 参数错误 } #if RC_SELECT_Index == 0 c->input_rc.inputData->dr16.data = #elif RC_SELECT_Index == 1 switch (c->inputData.rc.inputData->at9s.data.key_C) { case AT9S_CMD_SW_DOWN: c->outCmd.shoot.cmd.online = at9s_out.online; c->outCmd.shoot.cmd.ready = true; c->outCmd.shoot.cmd.firecmd = true; break; case AT9S_CMD_SW_MID: c->outCmd.shoot.cmd.online = at9s_out.online; c->outCmd.shoot.cmd.ready = true; c->outCmd.shoot.cmd.firecmd = false; break; case AT9S_CMD_SW_UP: c->outCmd.shoot.cmd.online = at9s_out.online; c->outCmd.shoot.cmd.ready = false; c->outCmd.shoot.cmd.firecmd = false; break; default: c->outCmd.shoot.cmd.online = at9s_out.online; c->outCmd.shoot.cmd.ready = false; c->outCmd.shoot.cmd.firecmd = false; break; } #endif return CMD_OK; } /* Exported functions ------------------------------------------------------- */ /*************************************************************************************************************************************/ /*****************************************************************PC******************************************************************/ /*************************************************************************************************************************************/ /* Includes ----------------------------------------------------------------- */ /* Private typedef ---------------------------------------------------------- */ typedef int8_t (*CMD_BehaviorFunc)(CMD_t *c); typedef struct { CMD_Behavior_t behavior; CMD_BehaviorFunc func; } CMD_BehaviorHandlerFunc_t; /* Private define ----------------------------------------------------------- */ /* Private macro ------------------------------------------------------------ */ #define PC_MACRO_BEHAVIOR_TABLE(X) \ X(FORE) \ X(BACK) \ X(LEFT) \ X(RIGHT) \ X(ACCELERATE) \ X(DECELEBRATE) \ X(FIRE) \ X(FIRE_MODE) \ X(BUFF) \ X(AUTOAIM) \ X(OPENCOVER) \ X(ROTOR) \ X(REVTRIG) \ X(FOLLOWGIMBAL35) #define PC_MACRO_FOR_DECLARE_HANDLER_FUNCTION(BEHAVIOR) \ static int8_t Cmd_PC_HandleBehavior##BEHAVIOR(CMD_t *c); #define PC_MACRO_FOR_BUILD_BEHAVIOR_HANDLER_ARRAY(BEHAVIOR) \ {CMD_BEHAVIOR_##BEHAVIOR, Cmd_PC_HandleBehavior##BEHAVIOR}, PC_MACRO_BEHAVIOR_TABLE(PC_MACRO_FOR_DECLARE_HANDLER_FUNCTION) /* Private variables -------------------------------------------------------- */ CMD_BehaviorHandlerFunc_t behaviorHandlerFunc[] = { PC_MACRO_BEHAVIOR_TABLE(PC_MACRO_FOR_BUILD_BEHAVIOR_HANDLER_ARRAY) }; /* Private function -------------------------------------------------------- */ static int8_t Cmd_PC_HandleBehaviorFORE(CMD_t *c){ c->outCmd.chassis.cmd.ctrl_vec.vy += c->params.pc.sensitivity.move_sense; return CMD_OK; } static int8_t Cmd_PC_HandleBehaviorBACK(CMD_t *c){ c->outCmd.chassis.cmd.ctrl_vec.vy -= c->params.pc.sensitivity.move_sense; return CMD_OK; } static int8_t Cmd_PC_HandleBehaviorLEFT(CMD_t *c){ c->outCmd.chassis.cmd.ctrl_vec.vx -= c->params.pc.sensitivity.move_sense; return CMD_OK; } static int8_t Cmd_PC_HandleBehaviorRIGHT(CMD_t *c){ c->outCmd.chassis.cmd.ctrl_vec.vx += c->params.pc.sensitivity.move_sense; return CMD_OK; } static int8_t Cmd_PC_HandleBehaviorACCELERATE(CMD_t *c){ c->outCmd.chassis.cmd.ctrl_vec.vx *= c->params.pc.sensitivity.move_fast_sense; c->outCmd.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->outCmd.chassis.cmd.ctrl_vec.vx *= c->params.pc.sensitivity.move_slow_sense; c->outCmd.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->outCmd.shoot.cmd.firecmd = true; return CMD_OK; } static int8_t Cmd_PC_HandleBehaviorFIRE_MODE(CMD_t *c){ c->outCmd.shoot.cmd.mode++; c->outCmd.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->outCmd.chassis.cmd.mode = CHASSIS_MODE_ROTOR; c->outCmd.chassis.cmd.mode_rotor = ROTOR_MODE_RAND; return CMD_OK; } static int8_t Cmd_PC_HandleBehaviorREVTRIG(CMD_t *c){ // c->outCmd.shoot.cmd.reverse_trig = true; return CMD_OK; } static int8_t Cmd_PC_HandleBehaviorFOLLOWGIMBAL35(CMD_t *c){ c->outCmd.chassis.cmd.mode = CHASSIS_MODE_FOLLOW_GIMBAL_35; return CMD_OK; } static inline CMD_KeyValue_t CMD_BehaviorToKey(CMD_t *c, CMD_Behavior_t behavior) { return c->params.pc.map.key_map[behavior].key; } static inline CMD_TriggerType_t CMD_BehaviorToActive(CMD_t *c, CMD_Behavior_t behavior) { return c->params.pc.map.key_map[behavior].trigger_type; } int8_t Cmd_Get_pc(CMD_InputData_PC_t *pc) { pc->online = false; // pc->data= return CMD_OK; } static bool CMD_BehaviorOccurredRc(CMD_t *c, CMD_Behavior_t behavior) { CMD_KeyValue_t key = CMD_BehaviorToKey(c, behavior); CMD_TriggerType_t active = CMD_BehaviorToActive(c, behavior); bool now_key_pressed, last_key_pressed; /* 按下按键为鼠标左、右键 */ if (key == CMD_L_CLICK) { now_key_pressed = c->inputData.pc.data.mouse.l_click; last_key_pressed = c->inputData.pc.lastData.mouse.l_click; } else if (key == CMD_R_CLICK) { now_key_pressed = c->inputData.pc.data.mouse.r_click; last_key_pressed = c->inputData.pc.lastData.mouse.r_click; } else { now_key_pressed = c->inputData.pc.data.key & (1u << key); last_key_pressed = c->inputData.pc.lastData.key & (1u << key); } 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; } } /* Exported functions ------------------------------------------------------- */ static void CMD_PcLogic(CMD_t *c, float dt_sec) { c->outCmd.gimbal.cmd.mode = GIMBAL_MODE_ABSOLUTE; c->outCmd.gimbal.cmd.delta_yaw = (float)c->inputData.pc.data.mouse.x * dt_sec * c->params.pc.sensitivity.sens_mouse; c->outCmd.gimbal.cmd.delta_pit = (float)c->inputData.pc.data.mouse.y * dt_sec * c->params.pc.sensitivity.sens_mouse; c->outCmd.chassis.cmd.ctrl_vec.vx = c->outCmd.chassis.cmd.ctrl_vec.vy = 0.0f; c->outCmd.shoot.cmd.firecmd = false; for (size_t i = 0; i < CMD_BEHAVIOR_NUM; i++) { if (CMD_BehaviorOccurredRc(&c, behaviorHandlerFunc[i].behavior)) { behaviorHandlerFunc[i].func(c); } } c->inputData.pc.lastData.key = c->inputData.pc.data.key; c->inputData.pc.lastData.mouse.l_click = c->inputData.pc.data.mouse.l_click; c->inputData.pc.lastData.mouse.r_click = c->inputData.pc.data.mouse.r_click; } int8_t Cmd_BuildChassisCommandFromInput_pc(CMD_t *c) { if (c == NULL) { return CMD_ERR_NULL; // 参数错误 } return CMD_OK; } int8_t Cmd_BuildGimbalCommandFromInput_pc(CMD_t *c) { if (c == NULL) { return CMD_ERR_NULL; // 参数错误 } return CMD_OK; } int8_t Cmd_BuildShootCommandFromInput_pc(CMD_t *c) { if (c == NULL) { return CMD_ERR_NULL; // 参数错误 } c->outCmd.shoot.cmd.firecmd = false; for (size_t i = 0; i < CMD_BEHAVIOR_NUM; i++) { if (CMD_BehaviorOccurredRc(&c, behaviorHandlerFunc[i].behavior)) { behaviorHandlerFunc[i].func(c); } } c->inputData.pc.lastData.key = c->inputData.pc.data.key; c->inputData.pc.lastData.mouse.l_click = c->inputData.pc.data.mouse.l_click; c->inputData.pc.lastData.mouse.r_click = c->inputData.pc.data.mouse.r_click; return CMD_OK; } /*************************************************************************************************************************************/ /****************************************************************NUC******************************************************************/ /*************************************************************************************************************************************/ /* Includes ----------------------------------------------------------------- */ /* Private typedef ---------------------------------------------------------- */ /* Private define ----------------------------------------------------------- */ /* Private macro ------------------------------------------------------------ */ /* Private variables -------------------------------------------------------- */ /* Private function -------------------------------------------------------- */ /* Exported functions ------------------------------------------------------- */ int8_t Cmd_BuildChassisCommandFromInput_nuc(CMD_t *c) { if (c == NULL) { return CMD_ERR_NULL; // 参数错误 } return CMD_OK; } int8_t Cmd_BuildGimbalCommandFromInput_nuc(CMD_t *c) { if (c == NULL) { return CMD_ERR_NULL; // 参数错误 } return CMD_OK; } int8_t Cmd_BuildShootCommandFromInput_nuc(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 -------------------------------------------------------- */ /* Exported functions ------------------------------------------------------- */ int8_t Cmd_BuildChassisCommandFromInput_referee(CMD_t *c) { if (c == NULL) { return CMD_ERR_NULL; // 参数错误 } return CMD_OK; } int8_t Cmd_BuildGimbalCommandFromInput_referee(CMD_t *c) { if (c == NULL) { return CMD_ERR_NULL; // 参数错误 } return CMD_OK; } int8_t Cmd_BuildShootCommandFromInput_referee(CMD_t *c) { if (c == NULL) { return CMD_ERR_NULL; // 参数错误 } return CMD_OK; } /*************************************************************************************************************************************/ /***************************************************************分发命令***************************************************************/ /*************************************************************************************************************************************/ /* Includes ----------------------------------------------------------------- */ /* Private typedef ---------------------------------------------------------- */ /* Private define ----------------------------------------------------------- */ /* Private macro ------------------------------------------------------------ */ /* Private variables -------------------------------------------------------- */ /* Private function -------------------------------------------------------- */ /* Exported functions ------------------------------------------------------- */ 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; CMD_SourceHandler_t sourceHandlers[CMD_SRC_NUM] = { {CMD_SRC_RC, Cmd_BuildChassisCommandFromInput_rc, Cmd_BuildGimbalCommandFromInput_rc, Cmd_BuildShootCommandFromInput_rc}, {CMD_SRC_PC, Cmd_BuildChassisCommandFromInput_pc, Cmd_BuildGimbalCommandFromInput_pc, Cmd_BuildShootCommandFromInput_pc}, {CMD_SRC_NUC, Cmd_BuildChassisCommandFromInput_nuc, Cmd_BuildGimbalCommandFromInput_nuc, Cmd_BuildShootCommandFromInput_nuc}, {CMD_SRC_REFEREE, Cmd_BuildChassisCommandFromInput_referee, Cmd_BuildGimbalCommandFromInput_referee, Cmd_BuildShootCommandFromInput_referee}, }; int8_t Cmd_GenerateCommand(CMD_t *c) { if (c == NULL) { return CMD_ERR_NULL; // 参数错误 } Cmd_Arbiter(c); switch (c->outCmd.chassis.source) { case CMD_SRC_RC: sourceHandlers[CMD_SRC_RC].chassisFunc(c); break; case CMD_SRC_PC: sourceHandlers[CMD_SRC_PC].chassisFunc(c); break; case CMD_SRC_NUC: sourceHandlers[CMD_SRC_NUC].chassisFunc(c); break; case CMD_SRC_REFEREE: sourceHandlers[CMD_SRC_REFEREE].chassisFunc(c); break; default: break; } switch (c->outCmd.gimbal.source) { case CMD_SRC_RC: sourceHandlers[CMD_SRC_RC].gimbalFunc(c); break; case CMD_SRC_PC: sourceHandlers[CMD_SRC_PC].gimbalFunc(c); break; case CMD_SRC_NUC: sourceHandlers[CMD_SRC_NUC].gimbalFunc(c); break; case CMD_SRC_REFEREE: sourceHandlers[CMD_SRC_REFEREE].gimbalFunc(c); break; default: break; } switch (c->outCmd.shoot.source) { case CMD_SRC_RC: sourceHandlers[CMD_SRC_RC].shootFunc(c); break; case CMD_SRC_PC: sourceHandlers[CMD_SRC_PC].shootFunc(c); break; case CMD_SRC_NUC: sourceHandlers[CMD_SRC_NUC].shootFunc(c); break; case CMD_SRC_REFEREE: sourceHandlers[CMD_SRC_REFEREE].shootFunc(c); break; default: break; } return CMD_OK; }