零点感觉还可以...

This commit is contained in:
fcl
2026-03-21 18:44:25 +08:00
committed by guoxy06
parent 277b3a11c0
commit df0e1f4b1f
5 changed files with 64 additions and 39 deletions

View File

@@ -230,7 +230,7 @@ static void RemoteControlSet()
shoot_cmd_send.friction_mode = FRICTION_OFF;
// 拨弹控制,遥控器固定为一种拨弹模式,可自行选择
if (rc_data[TEMP].rc.dial < -500)
shoot_cmd_send.load_mode = LOAD_BURSTFIRE;
shoot_cmd_send.load_mode = LOAD_1_BULLET;
else
shoot_cmd_send.load_mode = LOAD_STOP;
// 射频控制,固定每秒1发,后续可以根据左侧拨轮的值大小切换射频,

View File

@@ -14,7 +14,9 @@ static Publisher_t *gimbal_pub; // 云台应用消息发布者
static Subscriber_t *gimbal_sub; // cmd控制消息订阅者
static Gimbal_Upload_Data_s gimbal_feedback_data; // 回传给cmd的云台状态信息
static Gimbal_Ctrl_Cmd_s gimbal_cmd_recv; // 来自cmd的控制信息
static float last_yaw_angle = 0.0f; // 保护模式前的yaw角度
// static float last_pitch_angle = 0.0f; // 保护模式前的pitch角度
uint8_t in_protection_mode = 0; // 是否在保护模式
void GimbalInit()
{
gimba_IMU_data = INS_Init(); // IMU先初始化,获取姿态数据指针赋给yaw电机的其他数据来源
@@ -117,11 +119,25 @@ void GimbalTask()
{
// 停止
case GIMBAL_ZERO_FORCE:
// 进入保护模式时记录当前角度
if (!in_protection_mode) {
last_yaw_angle = gimba_IMU_data->YawTotalAngle;
// last_pitch_angle = gimba_IMU_data->Pitch;
in_protection_mode = 1;
}
DJIMotorStop(yaw_motor);
DJIMotorStop(pitch_motor);
break;
// 使用陀螺仪的反馈,底盘根据yaw电机的offset跟随云台或视觉模式采用
case GIMBAL_GYRO_MODE: // 后续只保留此模式
// 从保护模式退出时
if (in_protection_mode) {
// 计算零飘导致的角度误差
float angle_error = gimba_IMU_data->YawTotalAngle - last_yaw_angle;
// 补偿目标角度,避免突然旋转
gimbal_cmd_recv.yaw -= angle_error;
in_protection_mode = 0;
}
DJIMotorEnable(yaw_motor);
DJIMotorEnable(pitch_motor);
DJIMotorChangeFeed(yaw_motor, ANGLE_LOOP, OTHER_FEED);

View File

@@ -41,9 +41,9 @@
#define STEERING_CHASSIS_ALIGN_ANGLE_RF STEERING_CHASSIS_ALIGN_ECD_RF / 8192.f * 360.f // 舵轮 A 对齐角度
#define STEERING_CHASSIS_ALIGN_ANGLE_LB STEERING_CHASSIS_ALIGN_ECD_LB / 8192.f * 360.f // 舵轮 D 对齐角度
// 发射参数
#define ONE_BULLET_DELTA_ANGLE 36 // 发射一发弹丸拨盘转动的距离,由机械设计图纸给出
#define REDUCTION_RATIO_LOADER 36.0f // 拨盘电机的减速比,英雄需要修改为3508的19.0f
#define NUM_PER_CIRCLE 10 // 拨盘一圈的装载量
#define ONE_BULLET_DELTA_ANGLE 51.0f // 发射一发弹丸拨盘转动的距离,由机械设计图纸给出
#define REDUCTION_RATIO_LOADER 19.0f // 拨盘电机的减速比,英雄需要修改为3508的19.0f
#define NUM_PER_CIRCLE 7 // 拨盘一圈的装载量
// 机器人底盘修改的参数,单位为mm(毫米)
#define WHEEL_BASE 350 // 纵向轴距(前进后退方向)
#define TRACK_WIDTH 300 // 横向轮距(左右平移方向)
@@ -178,6 +178,7 @@ typedef struct
Bullet_Speed_e bullet_speed; // 弹速枚举
uint8_t rest_heat;
float shoot_rate; // 连续发射的射频,unit per s,发/秒
float dead_time; // 每发弹丸的间隔时间,unit ms,毫秒
} Shoot_Ctrl_Cmd_s;
/* ----------------gimbal/shoot/chassis发布的反馈数据----------------*/

View File

@@ -68,33 +68,36 @@ void ShootInit()
.controller_param_init_config = {
.angle_PID = {
// 如果启用位置环来控制发弹,需要较大的I值保证输出力矩的线性度否则出现接近拨出的力矩大幅下降
.Kp = 10, // 10
.Ki = 0,
.Kd = 0,
.MaxOut = 200,
.Kp = 50,
.Ki = 0,
.Kd = 0,
.Improve = PID_Trapezoid_Intergral | PID_Integral_Limit | PID_Derivative_On_Measurement | PID_DerivativeFilter | PID_ErrorHandle,
.IntegralLimit = 10000,
.MaxOut = 15000,
.Derivative_LPF_RC = 0.01,
},
.speed_PID = {
.Kp = 10, // 10
.Ki = 1, // 1
.Kd = 0,
.Improve = PID_Integral_Limit,
.IntegralLimit = 5000,
.MaxOut = 5000,
.Kp = 5, // 10
.Ki = 100, // 1
.Kd = 0,
.Improve = PID_Trapezoid_Intergral | PID_Integral_Limit | PID_Derivative_On_Measurement,
.IntegralLimit = 10000,
.MaxOut = 15000,
},
.current_PID = {
.Kp = 0.7, // 0.7
.Ki = 0.1, // 0.1
.Kd = 0,
.Improve = PID_Integral_Limit,
.IntegralLimit = 5000,
.MaxOut = 5000,
.Kp = 0.7, // 0.7
.Ki = 0, // 0.1
.Kd = 0,
.Improve = PID_Integral_Limit,
.IntegralLimit = 10000,
.MaxOut = 15000,
},
},
.controller_setting_init_config = {
.angle_feedback_source = MOTOR_FEED, .speed_feedback_source = MOTOR_FEED,
.outer_loop_type = SPEED_LOOP, // 初始化成SPEED_LOOP,让拨盘停在原地,防止拨盘上电时乱转
.close_loop_type = CURRENT_LOOP | SPEED_LOOP,
.motor_reverse_flag = MOTOR_DIRECTION_NORMAL, // 注意方向设置为拨盘的拨出的击发方向
.close_loop_type = CURRENT_LOOP | SPEED_LOOP| ANGLE_LOOP,
.motor_reverse_flag = MOTOR_DIRECTION_REVERSE, // 注意方向设置为拨盘的拨出的击发方向
},
.motor_type = M2006 // 英雄使用m3508
};
@@ -126,8 +129,8 @@ void ShootTask()
// 如果上一次触发单发或3发指令的时间加上不应期仍然大于当前时间(尚未休眠完毕),直接返回即可
// 单发模式主要提供给能量机关激活使用(以及英雄的射击大部分处于单发)
// if (hibernate_time + dead_time > DWT_GetTimeline_ms())
// return;
if (hibernate_time + dead_time > DWT_GetTimeline_ms())
return;
// 若不在休眠状态,根据robotCMD传来的控制模式进行拨盘电机参考值设定和模式切换
switch (shoot_cmd_recv.load_mode)
@@ -138,11 +141,16 @@ void ShootTask()
DJIMotorSetRef(loader, 0); // 同时设定参考值为0,这样停止的速度最快
break;
// 单发模式,根据鼠标按下的时间,触发一次之后需要进入不响应输入的状态(否则按下的时间内可能多次进入,导致多次发射)
case LOAD_1_BULLET: // 激活能量机关/干扰对方用,英雄用.
DJIMotorOuterLoop(loader, ANGLE_LOOP); // 切换到角度环
DJIMotorSetRef(loader, loader->measure.total_angle + ONE_BULLET_DELTA_ANGLE); // 控制量增加一发弹丸的角度
hibernate_time = DWT_GetTimeline_ms(); // 记录触发指令的时间
dead_time = 150; // 完成1发弹丸发射的时间
case LOAD_1_BULLET: // 激活能量机关/干扰对方用,英雄用.
DJIMotorOuterLoop(loader, ANGLE_LOOP); // 切换到角度环
static float last_target_angle = 0; // 存储上次的目标角度
if (dead_time == 0) { // 第一次触发
last_target_angle = loader->measure.total_angle;
}
last_target_angle += ONE_BULLET_DELTA_ANGLE * REDUCTION_RATIO_LOADER; // 每次都在上次目标角度基础上增加固定角度
DJIMotorSetRef(loader, last_target_angle);
hibernate_time = DWT_GetTimeline_ms(); // 记录触发指令的时间
dead_time = shoot_cmd_recv.dead_time; // 完成1发弹丸发射的时间
break;
// 三连发,如果不需要后续可能删除
case LOAD_3_BULLET:
@@ -175,20 +183,20 @@ void ShootTask()
switch (shoot_cmd_recv.bullet_speed)
{
case SMALL_AMU_15:
DJIMotorSetRef(friction_l, 30000);
DJIMotorSetRef(friction_r, 30000);
DJIMotorSetRef(friction_l, 58000);
DJIMotorSetRef(friction_r, 58000);
break;
case SMALL_AMU_18:
DJIMotorSetRef(friction_l, 30000);
DJIMotorSetRef(friction_r, 30000);
DJIMotorSetRef(friction_l, 58000);
DJIMotorSetRef(friction_r, 58000);
break;
case SMALL_AMU_30:
DJIMotorSetRef(friction_l, 50000);
DJIMotorSetRef(friction_r, 50000);
DJIMotorSetRef(friction_l, 58000);
DJIMotorSetRef(friction_r, 58000);
break;
default: // 当前为了调试设定的默认值4000,因为还没有加入裁判系统无法读取弹速.
DJIMotorSetRef(friction_l, 30000);
DJIMotorSetRef(friction_r, 30000);
DJIMotorSetRef(friction_l, 58000);
DJIMotorSetRef(friction_r, 58000);
break;
}
}