/* * 射击模组 */ /* Includes ----------------------------------------------------------------- */ #include "shoot.h" #include "bsp/pwm.h" #include "bsp/time.h" #include "bsp/can.h" #include "component/pid.h" #include "component/limiter.h" #include "component/user_math.h" #include "device/motor_rm.h" #include /* Private typedef ---------------------------------------------------------- */ /* Private define ----------------------------------------------------------- */ #define BULLET_SPEED_LIMIT_17MM (25.0) /* Private macro ------------------------------------------------------------ */ /* Private variables -------------------------------------------------------- */ /* Private function -------------------------------------------------------- */ /** * \brief 设置射击模式 * * \param c 包含射击数据的结构体 * \param mode 要设置的模式 * * \return 函数运行结果 */ static int8_t Shoot_SetMode(Shoot_t *s, CMD_ShootMode_t mode) { if (s == NULL) return -1; if (mode == s->mode) return SHOOT_OK; /* 切换模式后重置PID和滤波器 */ // for (uint8_t i = 0; i < 2; i++) { // PID_Reset(s->pid.fric + i); // LowPassFilter2p_Reset(s->filter.in.fric + i, 0.0f); // LowPassFilter2p_Reset(s->filter.out.fric + i, 0.0f); // } // PID_Reset(&(s->pid.trig)); // LowPassFilter2p_Reset(&(s->filter.in.trig), 0.0f); // LowPassFilter2p_Reset(&(s->filter.out.trig), 0.0f); PID_Reset(&(s->pid.fric[0])); PID_Reset(&(s->pid.fric[1])); LowPassFilter2p_Reset(&(s->filter.in.fric[0]), 0.0f); LowPassFilter2p_Reset(&(s->filter.in.fric[1]), 0.0f); LowPassFilter2p_Reset(&(s->filter.out.fric[0]), 0.0f); LowPassFilter2p_Reset(&(s->filter.out.fric[1]), 0.0f); PID_Reset(&(s->pid.trig)); LowPassFilter2p_Reset(&(s->filter.in.trig), 0.0f); LowPassFilter2p_Reset(&(s->filter.out.trig), 0.0f); // while (fabsf(CircleError(s->setpoint.trig_angle, s->feedback.trig_angle, // M_2PI)) >= M_2PI / s->param->num_trig_tooth / 2.0f) { // CircleAdd(&(s->setpoint.trig_angle), M_2PI / s->param->num_trig_tooth, // M_2PI); // } if (mode == SHOOT_MODE_LOADED) s->fire_ctrl.to_shoot = 0; s->mode = mode; return 0; } // static float Shoot_CalcRPMFromSpeed(float speed, float radius, float *rpm) { // if (rpm == NULL) return -1; // if (radius <= 0.0f) return -2; // /* 限制弹丸速度 */ // speed = Limit_Abs(speed, BULLET_SPEED_LIMIT_17MM); // /* 计算转速 */ // *rpm = speed / (2.0f * M_PI * radius) * 60.0f; // return 0; // } /* Exported functions ------------------------------------------------------- */ /** * \brief 初始化射击 * * \param s 包含射击数据的结构体 * \param param 包含射击参数的结构体指针 * \param target_freq 任务预期的运行频率 * * \return 函数运行结果 */ int8_t Shoot_Init(Shoot_t *s, const Shoot_Params_t *param, float target_freq) { if (s == NULL) return -1; s->param = param; /* 初始化参数 */ s->mode = SHOOT_MODE_RELAX; /* 设置默认模式 */ PID_Init(&(s->pid.fric[0]), KPID_MODE_NO_D, target_freq, &(param->fric_pid_param)); PID_Init(&(s->pid.fric[1]), KPID_MODE_NO_D, target_freq, &(param->fric_pid_param)); PID_Init(&(s->pid.trig), KPID_MODE_CALC_D, target_freq, &(param->trig_pid_param)); LowPassFilter2p_Init(&(s->filter.in.fric[0]), target_freq, param->low_pass_cutoff_freq.in.fric); LowPassFilter2p_Init(&(s->filter.in.fric[1]), target_freq, param->low_pass_cutoff_freq.in.fric); LowPassFilter2p_Init(&(s->filter.out.fric[0]), target_freq, param->low_pass_cutoff_freq.out.fric); LowPassFilter2p_Init(&(s->filter.out.fric[1]), target_freq, param->low_pass_cutoff_freq.out.fric); LowPassFilter2p_Init(&(s->filter.in.trig), target_freq, param->low_pass_cutoff_freq.in.trig); LowPassFilter2p_Init(&(s->filter.out.trig), target_freq, param->low_pass_cutoff_freq.out.trig); BSP_CAN_Init(); MOTOR_RM_Register(s->param->fric_motor_param[0]); MOTOR_RM_Register(s->param->fric_motor_param[1]); MOTOR_RM_Register(s->param->trig_motor_param); return SHOOT_OK; } /** * \brief 更新射击的反馈信息 * * \param s 包含射击数据的结构体 * * \return 函数运行结果 */ int8_t Shoot_UpdateFeedback(Shoot_t *s) { if (s == NULL) return -1; MOTOR_RM_Update(s->param->fric_motor_param[0]); MOTOR_RM_Update(s->param->fric_motor_param[1]); MOTOR_RM_Update(s->param->trig_motor_param); MOTOR_RM_t *motor; motor = MOTOR_RM_GetMotor(s->param->fric_motor_param[0]); s->feedback.fric[0] = motor->feedback; motor = MOTOR_RM_GetMotor(s->param->fric_motor_param[1]); s->feedback.fric[1] = motor->feedback; motor = MOTOR_RM_GetMotor(s->param->trig_motor_param); s->feedback.trig = motor->feedback; return SHOOT_OK; } /** * \brief 运行射击控制逻辑 * * \param s 包含射击数据的结构体 * \param s_cmd 射击控制指令 * * \return 函数运行结果 */ int8_t Shoot_Control(Shoot_t *s, Shoot_CMD_t *s_cmd) { if (s == NULL) return -1; if (s_cmd == NULL) return -1; Shoot_SetMode(s, s_cmd->mode); /* 设置射击模式 */ /* 计算摩擦轮转速的目标值 */ // 根据弹丸射速计算转速,这里需要实现具体的计算逻辑 // s->setpoint.fric_rpm[0] = calculate_rpm_from_speed(s_cmd->bullet_speed); // s->setpoint.fric_rpm[1] = -s->setpoint.fric_rpm[0]; switch (s->mode) { case SHOOT_MODE_RELAX: MOTOR_RM_SetOutput(s->param->fric_motor_param[0], 0.0f); MOTOR_RM_SetOutput(s->param->fric_motor_param[1], 0.0f); MOTOR_RM_SetOutput(s->param->trig_motor_param, 0.0f); break; case SHOOT_MODE_SAFE: /*摩擦轮速度环到0,拨弹位置环到设定位置*/ s->setpoint.fric_rpm[0] = 0.0f; s->setpoint.fric_rpm[1] = 0.0f; break; case SHOOT_MODE_LOADED: // TODO: 实现上膛模式的控制逻辑 break; } return SHOOT_OK; } /** * \brief 射击输出值 * * \param s 包含射击数据的结构体 */ void Shoot_Output(Shoot_t *s) { if (s == NULL) return; MOTOR_RM_Ctrl(s->param->fric_motor_param[0]); }