DM4310上车测试成功,图传链路测试成功
This commit is contained in:
parent
28234a395f
commit
c17f3f6cb7
|
@ -46,7 +46,7 @@ void MX_USART1_UART_Init(void)
|
|||
|
||||
/* USER CODE END USART1_Init 1 */
|
||||
huart1.Instance = USART1;
|
||||
huart1.Init.BaudRate = 921600;
|
||||
huart1.Init.BaudRate = 115200;
|
||||
huart1.Init.WordLength = UART_WORDLENGTH_8B;
|
||||
huart1.Init.StopBits = UART_STOPBITS_1;
|
||||
huart1.Init.Parity = UART_PARITY_NONE;
|
||||
|
|
|
@ -311,6 +311,7 @@ void ChassisTask()
|
|||
// chassis_feedback_data.bullet_speed = referee_data->GameRobotState.shooter_id1_17mm_speed_limit;
|
||||
// chassis_feedback_data.rest_heat = referee_data->PowerHeatData.shooter_heat0;
|
||||
|
||||
chassis_feedback_data.cap_power = cap->cap_msg.power;
|
||||
// 推送反馈消息
|
||||
#ifdef ONE_BOARD
|
||||
PubPushMessage(chassis_pub, (void *)&chassis_feedback_data);
|
||||
|
|
|
@ -9,13 +9,15 @@
|
|||
#include "message_center.h"
|
||||
#include "general_def.h"
|
||||
#include "dji_motor.h"
|
||||
#include "dm4310.h"
|
||||
#include "auto_aim.h"
|
||||
#include "vision_transfer.h"
|
||||
// bsp
|
||||
#include "bsp_dwt.h"
|
||||
#include "bsp_log.h"
|
||||
|
||||
// 私有宏,自动将编码器转换成角度值
|
||||
#define YAW_ALIGN_ANGLE (YAW_CHASSIS_ALIGN_ECD * ECD_ANGLE_COEF_DJI) // 对齐时的角度,0-360
|
||||
#define YAW_ALIGN_ANGLE (YAW_CHASSIS_ALIGN_ECD * RAD_2_DEGREE) // 对齐时的角度,0-360,使用达妙电机
|
||||
#define PTICH_HORIZON_ANGLE (PITCH_HORIZON_ECD * ECD_ANGLE_COEF_DJI) // pitch水平时电机的角度,0-360
|
||||
|
||||
/* cmd应用包含的模块实例指针和交互信息存储*/
|
||||
|
@ -36,6 +38,7 @@ static Chassis_Upload_Data_s chassis_fetch_data; // 从底盘应用接收的反
|
|||
static RC_ctrl_t *rc_data; // 遥控器数据,初始化时返回
|
||||
//static Vision_Recv_s *vision_recv_data; // 视觉接收数据指针,初始化时返回
|
||||
//static Vision_Send_s vision_send_data; // 视觉发送数据
|
||||
static VT_ctrl_t *vt_data; // 图传链路下发的键鼠遥控数据 与遥控器数据格式保持一致
|
||||
RecievePacket_t *vision_recv_data; // 视觉接收数据指针,初始化时返回
|
||||
SendPacket_t vision_send_data; // 视觉发送数据
|
||||
|
||||
|
@ -57,6 +60,7 @@ static Shoot_Upload_Data_s shoot_fetch_data; // 从发射获取的反馈信息
|
|||
|
||||
static Robot_Status_e robot_state; // 机器人整体工作状态
|
||||
static referee_info_t* referee_data; // 用于获取裁判系统的数据
|
||||
static referee_info_vt_t* referee_vt_data;
|
||||
extern float horizontal_angle;
|
||||
//static int target_index = -1;
|
||||
static uint16_t base_HP;
|
||||
|
@ -64,7 +68,8 @@ static uint16_t base_HP;
|
|||
void RobotCMDInit()
|
||||
{
|
||||
rc_data = RemoteControlInit(&huart3); // 修改为对应串口,注意如果是自研板dbus协议串口需选用添加了反相器的那个
|
||||
vision_recv_data = VisionInit(&huart1); // 视觉通信串口
|
||||
vision_recv_data = VisionInit(); // 视觉通信,用的是USB通讯
|
||||
vt_data = VTRefereeInit(&huart1);
|
||||
|
||||
gimbal_cmd_pub = PubRegister("gimbal_cmd", sizeof(Gimbal_Ctrl_Cmd_s));
|
||||
gimbal_feed_sub = SubRegister("gimbal_feed", sizeof(Gimbal_Upload_Data_s));
|
||||
|
@ -142,6 +147,7 @@ static void update_ui_data()
|
|||
ui_data.shoot_mode = shoot_cmd_send.shoot_mode;
|
||||
ui_data.Chassis_Power_Data.chassis_power_mx = referee_data->GameRobotState.chassis_power_limit;
|
||||
ui_data.Vision_fire = aim_select.suggest_fire;
|
||||
//ui_data.Chassis_Power_Data.cap_power =
|
||||
}
|
||||
static void pitch_limit()
|
||||
{
|
||||
|
@ -149,8 +155,9 @@ static void pitch_limit()
|
|||
// gimbal_cmd_send.pitch -= 0.1f;
|
||||
// if(gimbal_fetch_data.pitch_motor_total_angle < horizontal_angle - 4000)
|
||||
// gimbal_cmd_send.pitch += 0.1f;
|
||||
if(gimbal_cmd_send.pitch>18) gimbal_cmd_send.pitch = 18;
|
||||
if(gimbal_cmd_send.pitch<-38) gimbal_cmd_send.pitch = -38;
|
||||
//@TODO:把限位去掉了,记得加回来
|
||||
// if(gimbal_cmd_send.pitch>18) gimbal_cmd_send.pitch = 18;
|
||||
// if(gimbal_cmd_send.pitch<-38) gimbal_cmd_send.pitch = -38;
|
||||
}
|
||||
static void auto_aim_mode()
|
||||
{
|
||||
|
@ -225,12 +232,14 @@ static void RemoteControlSet()
|
|||
shoot_cmd_send.friction_mode = FRICTION_ON;
|
||||
chassis_cmd_send.chassis_mode = CHASSIS_ROTATE;
|
||||
gimbal_cmd_send.gimbal_mode = GIMBAL_GYRO_MODE;
|
||||
|
||||
}
|
||||
else if (switch_is_mid(rc_data[TEMP].rc.switch_right)) // 右侧开关状态[中],底盘跟随云台
|
||||
{
|
||||
shoot_cmd_send.friction_mode = FRICTION_OFF;
|
||||
chassis_cmd_send.chassis_mode = CHASSIS_NO_FOLLOW;
|
||||
chassis_cmd_send.chassis_mode = CHASSIS_FOLLOW_GIMBAL_YAW;
|
||||
gimbal_cmd_send.gimbal_mode = GIMBAL_GYRO_MODE;
|
||||
shoot_cmd_send.tele_mode = TELE_CLOSE;
|
||||
}
|
||||
|
||||
// 云台参数,确定云台控制数据
|
||||
|
@ -257,8 +266,10 @@ static void RemoteControlSet()
|
|||
|
||||
// 发射参数
|
||||
if (switch_is_up(rc_data[TEMP].rc.switch_right)) // 右侧开关状态[上],调整水平pitch参数
|
||||
{
|
||||
gimbal_cmd_send.gimbal_mode = ADJUST_PITCH_MODE;
|
||||
// 弹舱舵机控制,待添加servo_motor模块,开启
|
||||
shoot_cmd_send.tele_mode = TELE_OPEN;
|
||||
}// 弹舱舵机控制,待添加servo_motor模块,开启
|
||||
else
|
||||
; // 弹舱舵机控制,待添加servo_motor模块,关闭
|
||||
|
||||
|
@ -390,6 +401,15 @@ static void MouseKeySet()
|
|||
shoot_cmd_send.friction_mode = FRICTION_ON;
|
||||
break;
|
||||
}
|
||||
switch (rc_data[TEMP].key_count[KEY_PRESS][Key_Q] % 2) // Q键开关摩擦轮
|
||||
{
|
||||
case 0:
|
||||
shoot_cmd_send.tele_mode = TELE_CLOSE;
|
||||
break;
|
||||
default:
|
||||
shoot_cmd_send.tele_mode = TELE_OPEN;
|
||||
break;
|
||||
}
|
||||
switch (rc_data[TEMP].key_count[KEY_PRESS][Key_E] % 2) // E键开关小陀螺
|
||||
{
|
||||
case 0:
|
||||
|
@ -415,8 +435,31 @@ static void MouseKeySet()
|
|||
|
||||
pitch_limit();
|
||||
death_check();
|
||||
|
||||
}
|
||||
/**
|
||||
* @brief 输入为(图传链路)键鼠时模式和控制量设置
|
||||
*
|
||||
*/
|
||||
static void VTMouseKeySet()
|
||||
{
|
||||
chassis_cmd_send.vx = vt_data[TEMP].key[KEY_PRESS].a * 1500 - vt_data[TEMP].key[KEY_PRESS].d * 1500; // 系数待测
|
||||
chassis_cmd_send.vy = vt_data[TEMP].key[KEY_PRESS].w * 800 - vt_data[TEMP].key[KEY_PRESS].s * 800;
|
||||
|
||||
gimbal_cmd_send.yaw -= (float)vt_data[TEMP].mouse.x / 660 * 5; // 系数待测
|
||||
gimbal_cmd_send.pitch += (float)vt_data[TEMP].mouse.y / 660 * 10;
|
||||
|
||||
|
||||
switch (vt_data[TEMP].key_count[KEY_PRESS][Key_F] % 2) // F键开关摩擦轮
|
||||
{
|
||||
case 0:
|
||||
shoot_cmd_send.friction_mode = FRICTION_OFF;
|
||||
break;
|
||||
default:
|
||||
shoot_cmd_send.friction_mode = FRICTION_ON;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 紧急停止,包括遥控器左上侧拨轮打满/重要模块离线/双板通信失效等
|
||||
|
@ -468,8 +511,8 @@ void RobotCMDTask()
|
|||
switch_is_mid(rc_data[TEMP].rc.switch_left)) // 遥控器左侧开关状态为[下],[中],遥控器控制
|
||||
RemoteControlSet();
|
||||
else if (switch_is_up(rc_data[TEMP].rc.switch_left)) // 遥控器左侧开关状态为[上],键盘控制
|
||||
MouseKeySet();
|
||||
|
||||
//MouseKeySet();
|
||||
VTMouseKeySet();
|
||||
EmergencyHandler(); // 处理模块离线和遥控器急停等紧急情况
|
||||
|
||||
// 设置视觉发送数据,还需增加加速度和角速度数据
|
||||
|
|
|
@ -2,6 +2,9 @@
|
|||
#define ROBOT_CMD_H
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief 机器人核心控制任务初始化,会被RobotInit()调用
|
||||
*
|
||||
|
|
|
@ -24,13 +24,13 @@ void GimbalInit()
|
|||
// YAW
|
||||
Motor_Init_Config_s yaw_config = {
|
||||
.can_init_config = {
|
||||
.can_handle = &hcan1,
|
||||
.can_handle = &hcan2,
|
||||
.tx_id = 0x01,
|
||||
.rx_id = 0x43,
|
||||
},
|
||||
.controller_param_init_config = {
|
||||
.angle_PID = {
|
||||
.Kp = 0.5, // 8
|
||||
.Kp = 0.5f,//0.5, // 8
|
||||
.Ki = 0,
|
||||
.Kd = 0,
|
||||
.Improve = PID_Trapezoid_Intergral | PID_Integral_Limit | PID_Derivative_On_Measurement,
|
||||
|
@ -39,8 +39,8 @@ void GimbalInit()
|
|||
.MaxOut = 500,
|
||||
},
|
||||
.speed_PID = {
|
||||
.Kp = 0.5f, // 70
|
||||
.Ki = 0.2f, // 200
|
||||
.Kp = 3,//0.5f,
|
||||
.Ki = 0,//0.2f,
|
||||
.Kd = 0,//10
|
||||
.Improve = PID_Trapezoid_Intergral | PID_Integral_Limit | PID_Derivative_On_Measurement,
|
||||
.IntegralLimit = 3000,
|
||||
|
@ -51,8 +51,8 @@ void GimbalInit()
|
|||
.other_speed_feedback_ptr = &gimba_IMU_data->Gyro[2],
|
||||
},
|
||||
.controller_setting_init_config = {
|
||||
.angle_feedback_source = MOTOR_FEED,
|
||||
.speed_feedback_source = MOTOR_FEED,
|
||||
.angle_feedback_source = OTHER_FEED,
|
||||
.speed_feedback_source = OTHER_FEED,
|
||||
.outer_loop_type = ANGLE_LOOP,
|
||||
.close_loop_type = ANGLE_LOOP |SPEED_LOOP,
|
||||
.motor_reverse_flag = MOTOR_DIRECTION_NORMAL,
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
|
||||
/* 机器人重要参数定义,注意根据不同机器人进行修改,浮点数需要以.0或f结尾,无符号以u结尾 */
|
||||
// 云台参数
|
||||
#define YAW_CHASSIS_ALIGN_ECD 295 // 云台和底盘对齐指向相同方向时的电机编码器值,若对云台有机械改动需要修改
|
||||
#define YAW_CHASSIS_ALIGN_ECD 2.691132 // 云台和底盘对齐指向相同方向时的电机position值,需要加上PI,因为单圈角度计算里增加了PI若对云台有机械改动需要修改
|
||||
#define YAW_ECD_GREATER_THAN_4096 1 // ALIGN_ECD值是否大于4096,是为1,否为0;用于计算云台偏转角度
|
||||
#define PITCH_HORIZON_ECD 3412 // 云台处于水平位置时编码器值,若对云台有机械改动需要修改
|
||||
#define PITCH_MAX_ANGLE 0 // 云台竖直方向最大角度 (注意反馈如果是陀螺仪,则填写陀螺仪的角度)
|
||||
|
@ -111,9 +111,9 @@ typedef enum
|
|||
|
||||
typedef enum
|
||||
{
|
||||
LID_OPEN = 0, // 弹舱盖打开
|
||||
LID_CLOSE, // 弹舱盖关闭
|
||||
} lid_mode_e;
|
||||
TELE_OPEN = 0, // 弹舱盖打开
|
||||
TELE_CLOSE, // 弹舱盖关闭
|
||||
} tele_mode_e;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
|
@ -127,8 +127,8 @@ typedef enum
|
|||
// 功率限制,从裁判系统获取,是否有必要保留?
|
||||
typedef struct
|
||||
{ // 功率控制
|
||||
float chassis_power_mx;
|
||||
float last_power_mx;
|
||||
uint16_t chassis_power_mx;
|
||||
float cap_power;
|
||||
} Chassis_Power_Data_s;
|
||||
|
||||
/* ----------------CMD应用发布的控制数据,应当由gimbal/chassis/shoot订阅---------------- */
|
||||
|
@ -167,7 +167,7 @@ typedef struct
|
|||
{
|
||||
shoot_mode_e shoot_mode;
|
||||
loader_mode_e load_mode;
|
||||
lid_mode_e lid_mode;
|
||||
tele_mode_e tele_mode;
|
||||
friction_mode_e friction_mode;
|
||||
float bullet_speed; // 发射周期
|
||||
uint8_t rest_heat;
|
||||
|
@ -189,7 +189,7 @@ typedef struct
|
|||
// float real_vx;
|
||||
// float real_vy;
|
||||
// float real_wz;
|
||||
|
||||
float cap_power;
|
||||
uint8_t rest_heat; // 剩余枪口热量
|
||||
Enemy_Color_e enemy_color; // 0 for blue, 1 for red
|
||||
|
||||
|
|
|
@ -9,13 +9,16 @@
|
|||
|
||||
|
||||
/* 对于双发射机构的机器人,将下面的数据封装成结构体即可,生成两份shoot应用实例 */
|
||||
static DJIMotorInstance *friction_l, *friction_r,*friction_z, *loader; // 拨盘电机
|
||||
static DJIMotorInstance *friction_l, *friction_r,*friction_z, *loader,*telescope; // 拨盘电机
|
||||
// static servo_instance *lid; 需要增加弹舱盖
|
||||
|
||||
static Publisher_t *shoot_pub;
|
||||
static Shoot_Ctrl_Cmd_s shoot_cmd_recv; // 来自cmd的发射控制信息
|
||||
static Subscriber_t *shoot_sub;
|
||||
static Shoot_Upload_Data_s shoot_feedback_data; // 来自cmd的发射控制信息
|
||||
float Kp=2;
|
||||
float Ki=1;
|
||||
float Kd=0;
|
||||
|
||||
static float stop_location;
|
||||
// dwt定时,计算冷却用
|
||||
|
@ -33,8 +36,8 @@ void ShootInit()
|
|||
},
|
||||
.controller_param_init_config = {
|
||||
.speed_PID = {
|
||||
.Kp = 2, // 20
|
||||
.Ki = 1, // 1
|
||||
.Kp = 6, // 20
|
||||
.Ki = 0, // 1
|
||||
.Kd = 0,
|
||||
.Improve = PID_Integral_Limit,
|
||||
.IntegralLimit = 10000,
|
||||
|
@ -112,6 +115,39 @@ void ShootInit()
|
|||
};
|
||||
loader = DJIMotorInit(&loader_config);
|
||||
|
||||
// 倍镜电机
|
||||
Motor_Init_Config_s telescope_config = {
|
||||
.can_init_config = {
|
||||
.can_handle = &hcan2,
|
||||
.tx_id = 7,
|
||||
},
|
||||
.controller_param_init_config = {
|
||||
.angle_PID = {
|
||||
.Kp = 10, // 10
|
||||
.Ki = 0,
|
||||
.Kd = 0,
|
||||
.MaxOut = 15000,
|
||||
},
|
||||
.speed_PID = {
|
||||
.Kp = 3, // 10
|
||||
.Ki = 0, // 1
|
||||
.Kd = 0,
|
||||
.Improve = PID_Integral_Limit,
|
||||
.IntegralLimit = 5000,
|
||||
.MaxOut = 30000,
|
||||
},
|
||||
},
|
||||
.controller_setting_init_config = {
|
||||
.angle_feedback_source = MOTOR_FEED,
|
||||
.speed_feedback_source = MOTOR_FEED,
|
||||
.outer_loop_type = SPEED_LOOP, // 初始化成SPEED_LOOP,让倍镜停在原地,防止拨盘上电时乱转
|
||||
.close_loop_type = SPEED_LOOP | ANGLE_LOOP,
|
||||
.motor_reverse_flag = MOTOR_DIRECTION_NORMAL, // 注意方向设置
|
||||
},
|
||||
.motor_type = M2006 // 英雄使用m3508
|
||||
};
|
||||
telescope = DJIMotorInit(&telescope_config);
|
||||
|
||||
shoot_pub = PubRegister("shoot_feed", sizeof(Shoot_Upload_Data_s));
|
||||
shoot_sub = SubRegister("shoot_cmd", sizeof(Shoot_Ctrl_Cmd_s));
|
||||
}
|
||||
|
@ -130,7 +166,9 @@ void ShootTask()
|
|||
{
|
||||
// 从cmd获取控制数据
|
||||
SubGetMessage(shoot_sub, &shoot_cmd_recv);
|
||||
|
||||
friction_z->motor_controller.speed_PID.Kp=friction_r->motor_controller.speed_PID.Kp = Kp;
|
||||
friction_z->motor_controller.speed_PID.Ki=friction_r->motor_controller.speed_PID.Ki = Ki;
|
||||
friction_z->motor_controller.speed_PID.Kd=friction_r->motor_controller.speed_PID.Kd = Kd;
|
||||
// 对shoot mode等于SHOOT_STOP的情况特殊处理,直接停止所有电机(紧急停止)
|
||||
if (shoot_cmd_recv.shoot_mode == SHOOT_OFF)
|
||||
{
|
||||
|
@ -138,6 +176,7 @@ void ShootTask()
|
|||
DJIMotorStop(friction_r);
|
||||
DJIMotorStop(friction_z);
|
||||
DJIMotorStop(loader);
|
||||
DJIMotorStop(telescope);
|
||||
}
|
||||
else // 恢复运行
|
||||
{
|
||||
|
@ -145,6 +184,7 @@ void ShootTask()
|
|||
DJIMotorEnable(friction_r);
|
||||
DJIMotorEnable(friction_z);
|
||||
DJIMotorEnable(loader);
|
||||
DJIMotorEnable(telescope);
|
||||
}
|
||||
// 如果上一次触发单发或3发指令的时间加上不应期仍然大于当前时间(尚未休眠完毕),直接返回即可
|
||||
// 单发模式主要提供给能量机关激活使用(以及英雄的射击大部分处于单发)
|
||||
|
@ -198,8 +238,8 @@ void ShootTask()
|
|||
if (shoot_cmd_recv.friction_mode == FRICTION_ON)
|
||||
{
|
||||
// DJIMotorSetRef(friction_l, 39000);
|
||||
DJIMotorSetRef(friction_r, 39000);
|
||||
DJIMotorSetRef(friction_z, 39000);//39000/6 = 6500
|
||||
DJIMotorSetRef(friction_r, 36000);
|
||||
DJIMotorSetRef(friction_z, 36000);//39000/6 = 6500
|
||||
}
|
||||
else // 关闭摩擦轮
|
||||
{
|
||||
|
@ -209,13 +249,15 @@ void ShootTask()
|
|||
}
|
||||
|
||||
// 开关弹舱盖
|
||||
if (shoot_cmd_recv.lid_mode == LID_CLOSE)
|
||||
if (shoot_cmd_recv.tele_mode == TELE_CLOSE)
|
||||
{
|
||||
//...
|
||||
DJIMotorOuterLoop(telescope, ANGLE_LOOP);
|
||||
DJIMotorSetRef(telescope, 0);
|
||||
}
|
||||
else if (shoot_cmd_recv.lid_mode == LID_OPEN)
|
||||
else if (shoot_cmd_recv.tele_mode == TELE_OPEN)
|
||||
{
|
||||
//...
|
||||
DJIMotorOuterLoop(telescope, ANGLE_LOOP);
|
||||
DJIMotorSetRef(telescope, 1620);
|
||||
}
|
||||
|
||||
// 反馈数据,目前暂时没有要设定的反馈数据,后续可能增加应用离线监测以及卡弹反馈
|
||||
|
|
|
@ -141,9 +141,9 @@ static void DecodeVision(uint16_t recv_len)
|
|||
}
|
||||
|
||||
/* 视觉通信初始化 */
|
||||
RecievePacket_t *VisionInit(UART_HandleTypeDef *_handle)
|
||||
RecievePacket_t *VisionInit(void)
|
||||
{
|
||||
UNUSED(_handle); // 仅为了消除警告
|
||||
// UNUSED(_handle); // 仅为了消除警告
|
||||
USB_Init_Config_s conf = {.rx_cbk = DecodeVision};
|
||||
vis_recv_buff = USBInit(conf);
|
||||
|
||||
|
|
|
@ -114,7 +114,7 @@ typedef __packed struct
|
|||
* @param handle 用于和视觉通信的串口handle(C板上一般为USART1,丝印为USART2,4pin)
|
||||
*/
|
||||
//Vision_Recv_s *VisionInit(UART_HandleTypeDef *_handle);
|
||||
RecievePacket_t *VisionInit(UART_HandleTypeDef *_handle);
|
||||
RecievePacket_t *VisionInit(void);
|
||||
|
||||
/**
|
||||
* @brief 发送视觉数据
|
||||
|
|
|
@ -46,7 +46,7 @@ static void DMMotorDecode(CANInstance *motor_can)
|
|||
tmp = (uint16_t)((rxbuff[1] << 8) | rxbuff[2]);
|
||||
measure->position = uint_to_float(tmp, DM_P_MIN, DM_P_MAX, 16);
|
||||
|
||||
measure->angle_single_round = ECD_ANGLE_COEF_DM * (measure->position+3.141593);
|
||||
measure->angle_single_round = RAD_2_DEGREE * (measure->position+3.141593);
|
||||
|
||||
tmp = (uint16_t)((rxbuff[3] << 4) | rxbuff[4] >> 4);
|
||||
measure->velocity = uint_to_float(tmp, DM_V_MIN, DM_V_MAX, 12);
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
#define DM_V_MAX 45.0f
|
||||
#define DM_T_MIN (-18.0f)
|
||||
#define DM_T_MAX 18.0f
|
||||
#define ECD_ANGLE_COEF_DM 57.324840f // (360/2PI),将编码器值转化为角度制
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
|
|
@ -83,6 +83,8 @@ typedef enum
|
|||
ID_robot_hurt = 0x0206, // 伤害状态数据
|
||||
ID_shoot_data = 0x0207, // 实时射击数据
|
||||
ID_student_interactive = 0x0301, // 机器人间交互数据
|
||||
ID_custom_robot = 0x302, // 自定义控制器数据(图传链路)
|
||||
ID_remote_control = 0x304, // 键鼠遥控数据(图传链路)
|
||||
} CmdID_e;
|
||||
|
||||
/* 命令码数据段长,根据官方协议来定义长度,还有自定义数据长度 */
|
||||
|
@ -101,6 +103,8 @@ typedef enum
|
|||
LEN_robot_hurt = 1, // 0x0206
|
||||
LEN_shoot_data = 7, // 0x0207
|
||||
LEN_receive_data = 6 + Communicate_Data_LEN, // 0x0301
|
||||
LEN_self_control = 12, // 0x0304
|
||||
LEN_remote_control = 12, // 0x0304
|
||||
|
||||
} JudgeDataLength_e;
|
||||
|
||||
|
@ -222,6 +226,20 @@ typedef struct
|
|||
float bullet_speed;
|
||||
} ext_shoot_data_t;
|
||||
|
||||
/****************************图传链路数据****************************/
|
||||
/* ID: 0x0304 Byte: 7 图传链路键鼠遥控数据 */
|
||||
typedef struct
|
||||
{
|
||||
int16_t mouse_x;
|
||||
int16_t mouse_y;
|
||||
int16_t mouse_z;
|
||||
int8_t left_button_down;
|
||||
int8_t right_button_down;
|
||||
uint16_t keyboard_value;
|
||||
uint16_t reserved;
|
||||
}vision_transfer_t;
|
||||
/****************************图传链路数据****************************/
|
||||
|
||||
/****************************机器人交互数据****************************/
|
||||
/****************************机器人交互数据****************************/
|
||||
/* 发送的内容数据段最大为 113 检测是否超出大小限制?实际上图形段不会超,数据段最多30个,也不会超*/
|
||||
|
|
|
@ -142,7 +142,7 @@ static void RobotModeTest(Referee_Interactive_info_t *_Interactive_data) // 测
|
|||
_Interactive_data->gimbal_mode = GIMBAL_ZERO_FORCE;
|
||||
_Interactive_data->shoot_mode = SHOOT_ON;
|
||||
_Interactive_data->friction_mode = FRICTION_ON;
|
||||
_Interactive_data->lid_mode = LID_OPEN;
|
||||
_Interactive_data->tele_mode = TELE_OPEN;
|
||||
_Interactive_data->Chassis_Power_Data.chassis_power_mx += 3.5;
|
||||
if (_Interactive_data->Chassis_Power_Data.chassis_power_mx >= 18)
|
||||
_Interactive_data->Chassis_Power_Data.chassis_power_mx = 0;
|
||||
|
@ -154,7 +154,7 @@ static void RobotModeTest(Referee_Interactive_info_t *_Interactive_data) // 测
|
|||
_Interactive_data->gimbal_mode = GIMBAL_FREE_MODE;
|
||||
_Interactive_data->shoot_mode = SHOOT_OFF;
|
||||
_Interactive_data->friction_mode = FRICTION_OFF;
|
||||
_Interactive_data->lid_mode = LID_CLOSE;
|
||||
_Interactive_data->tele_mode = TELE_CLOSE;
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
|
@ -163,7 +163,7 @@ static void RobotModeTest(Referee_Interactive_info_t *_Interactive_data) // 测
|
|||
_Interactive_data->gimbal_mode = GIMBAL_GYRO_MODE;
|
||||
_Interactive_data->shoot_mode = SHOOT_ON;
|
||||
_Interactive_data->friction_mode = FRICTION_ON;
|
||||
_Interactive_data->lid_mode = LID_OPEN;
|
||||
_Interactive_data->tele_mode = TELE_OPEN;
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
|
@ -172,7 +172,7 @@ static void RobotModeTest(Referee_Interactive_info_t *_Interactive_data) // 测
|
|||
_Interactive_data->gimbal_mode = GIMBAL_ZERO_FORCE;
|
||||
_Interactive_data->shoot_mode = SHOOT_OFF;
|
||||
_Interactive_data->friction_mode = FRICTION_OFF;
|
||||
_Interactive_data->lid_mode = LID_CLOSE;
|
||||
_Interactive_data->tele_mode = TELE_CLOSE;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -311,16 +311,16 @@ static void UIChangeCheck(Referee_Interactive_info_t *_Interactive_data)
|
|||
_Interactive_data->friction_last_mode = _Interactive_data->friction_mode;
|
||||
}
|
||||
|
||||
if (_Interactive_data->lid_mode != _Interactive_data->lid_last_mode)
|
||||
if (_Interactive_data->tele_mode != _Interactive_data->tele_last_mode)
|
||||
{
|
||||
_Interactive_data->Referee_Interactive_Flag.lid_flag = 1;
|
||||
_Interactive_data->lid_last_mode = _Interactive_data->lid_mode;
|
||||
_Interactive_data->tele_last_mode = _Interactive_data->tele_mode;
|
||||
}
|
||||
|
||||
if (_Interactive_data->Chassis_Power_Data.chassis_power_mx != _Interactive_data->Chassis_last_Power_Data.last_power_mx)
|
||||
if (_Interactive_data->Chassis_Power_Data.chassis_power_mx != _Interactive_data->Chassis_last_Power_Data.chassis_power_mx)
|
||||
{
|
||||
_Interactive_data->Referee_Interactive_Flag.Power_flag = 1;
|
||||
_Interactive_data->Chassis_last_Power_Data.last_power_mx = _Interactive_data->Chassis_Power_Data.chassis_power_mx;
|
||||
_Interactive_data->Chassis_last_Power_Data.chassis_power_mx = _Interactive_data->Chassis_Power_Data.chassis_power_mx;
|
||||
}
|
||||
if (_Interactive_data->Vision_fire != _Interactive_data->last_Vision_fire)
|
||||
{
|
||||
|
|
|
@ -38,7 +38,8 @@ typedef struct
|
|||
ext_robot_hurt_t RobotHurt; // 0x0206
|
||||
ext_shoot_data_t ShootData; // 0x0207
|
||||
|
||||
// 自定义交互数据的接收
|
||||
vision_transfer_t VisionTransfer;
|
||||
// 自定义交互数据的接收
|
||||
Communicate_ReceiveData_t ReceiveData;
|
||||
|
||||
uint8_t init_flag;
|
||||
|
@ -66,7 +67,7 @@ typedef struct
|
|||
gimbal_mode_e gimbal_mode; // 云台模式
|
||||
shoot_mode_e shoot_mode; // 发射模式设置
|
||||
friction_mode_e friction_mode; // 摩擦轮关闭
|
||||
lid_mode_e lid_mode; // 弹舱盖打开
|
||||
tele_mode_e tele_mode; // 弹舱盖打开
|
||||
Chassis_Power_Data_s Chassis_Power_Data; // 功率控制
|
||||
uint8_t Vision_fire;
|
||||
|
||||
|
@ -76,7 +77,7 @@ typedef struct
|
|||
gimbal_mode_e gimbal_last_mode;
|
||||
shoot_mode_e shoot_last_mode;
|
||||
friction_mode_e friction_last_mode;
|
||||
lid_mode_e lid_last_mode;
|
||||
tele_mode_e tele_last_mode;
|
||||
Chassis_Power_Data_s Chassis_last_Power_Data;
|
||||
uint8_t last_Vision_fire;
|
||||
|
||||
|
|
|
@ -0,0 +1,162 @@
|
|||
/**
|
||||
* @file rm_referee.C
|
||||
* @author kidneygood (you@domain.com)
|
||||
* @brief
|
||||
* @version 0.1
|
||||
* @date 2022-11-18
|
||||
*
|
||||
* @copyright Copyright (c) 2022
|
||||
*
|
||||
*/
|
||||
|
||||
#include "vision_transfer.h"
|
||||
#include "string.h"
|
||||
#include "crc_ref.h"
|
||||
#include "bsp_usart.h"
|
||||
#include "task.h"
|
||||
#include "daemon.h"
|
||||
#include "bsp_log.h"
|
||||
#include "cmsis_os.h"
|
||||
#include "remote_control.h"
|
||||
|
||||
#define RE_RX_BUFFER_SIZE 128u // 裁判系统接收缓冲区大小
|
||||
|
||||
static USARTInstance *vt_usart_instance; // 裁判系统串口实例
|
||||
static DaemonInstance *vision_transfer_daemon; // 裁判系统守护进程
|
||||
static referee_info_vt_t referee_info_vt; // 裁判系统数据
|
||||
static VT_ctrl_t vt_ctrl[2]; //[0]:当前数据TEMP,[1]:上一次的数据LAST.用于按键持续按下和切换的判断
|
||||
/**
|
||||
* @brief 读取裁判数据,中断中读取保证速度
|
||||
* @param buff: 读取到的裁判系统原始数据
|
||||
* @retval 是否对正误判断做处理
|
||||
* @attention 在此判断帧头和CRC校验,无误再写入数据,不重复判断帧头
|
||||
*/
|
||||
static void JudgeReadVTData(uint8_t *buff)
|
||||
{
|
||||
uint16_t judge_length; // 统计一帧数据长度
|
||||
if (buff == NULL) // 空数据包,则不作任何处理
|
||||
return;
|
||||
|
||||
// 写入帧头数据(5-byte),用于判断是否开始存储裁判数据
|
||||
memcpy(&referee_info_vt.FrameHeader, buff, LEN_HEADER);
|
||||
|
||||
// 判断帧头数据(0)是否为0xA5
|
||||
if (buff[SOF] == REFEREE_SOF)
|
||||
{
|
||||
// 帧头CRC8校验
|
||||
if (Verify_CRC8_Check_Sum(buff, LEN_HEADER) == TRUE)
|
||||
{
|
||||
// 统计一帧数据长度(byte),用于CR16校验
|
||||
judge_length = buff[DATA_LENGTH] + LEN_HEADER + LEN_CMDID + LEN_TAIL;
|
||||
// 帧尾CRC16校验
|
||||
if (Verify_CRC16_Check_Sum(buff, judge_length) == TRUE)
|
||||
{
|
||||
// 2个8位拼成16位int
|
||||
referee_info_vt.CmdID = (buff[6] << 8 | buff[5]);
|
||||
// 解析数据命令码,将数据拷贝到相应结构体中(注意拷贝数据的长度)
|
||||
// 第8个字节开始才是数据 data=7
|
||||
switch (referee_info_vt.CmdID)
|
||||
{
|
||||
case ID_custom_robot: //0x0302
|
||||
memcpy(&referee_info_vt.ReceiveData, (buff + DATA_Offset), LEN_self_control);
|
||||
break;
|
||||
case ID_remote_control: //0x0304
|
||||
memcpy(&referee_info_vt.VisionTransfer, (buff + DATA_Offset), LEN_remote_control);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 首地址加帧长度,指向CRC16下一字节,用来判断是否为0xA5,从而判断一个数据包是否有多帧数据
|
||||
if (*(buff + sizeof(xFrameHeader) + LEN_CMDID + referee_info_vt.FrameHeader.DataLength + LEN_TAIL) == 0xA5)
|
||||
{ // 如果一个数据包出现了多帧数据,则再次调用解析函数,直到所有数据包解析完毕
|
||||
JudgeReadVTData(buff + sizeof(xFrameHeader) + LEN_CMDID + referee_info_vt.FrameHeader.DataLength + LEN_TAIL);
|
||||
}
|
||||
}
|
||||
}
|
||||
static void vt_to_rc(void)
|
||||
{
|
||||
// 鼠标解析
|
||||
vt_ctrl[TEMP].mouse.x = referee_info_vt.VisionTransfer.mouse_x; //!< Mouse X axis
|
||||
vt_ctrl[TEMP].mouse.y = referee_info_vt.VisionTransfer.mouse_y; //!< Mouse Y axis
|
||||
vt_ctrl[TEMP].mouse.press_l = referee_info_vt.VisionTransfer.left_button_down; //!< Mouse Left Is Press ?
|
||||
vt_ctrl[TEMP].mouse.press_r = referee_info_vt.VisionTransfer.right_button_down; //!< Mouse Right Is Press ?
|
||||
|
||||
// 位域的按键值解算,直接memcpy即可,注意小端低字节在前,即lsb在第一位,msb在最后
|
||||
*(uint16_t *)&vt_ctrl[TEMP].key[KEY_PRESS] = referee_info_vt.VisionTransfer.keyboard_value;
|
||||
|
||||
if (vt_ctrl[TEMP].key[KEY_PRESS].ctrl) // ctrl键按下
|
||||
vt_ctrl[TEMP].key[KEY_PRESS_WITH_CTRL] = vt_ctrl[TEMP].key[KEY_PRESS];
|
||||
else
|
||||
memset(&vt_ctrl[TEMP].key[KEY_PRESS_WITH_CTRL], 0, sizeof(Key_t));
|
||||
if (vt_ctrl[TEMP].key[KEY_PRESS].shift) // shift键按下
|
||||
vt_ctrl[TEMP].key[KEY_PRESS_WITH_SHIFT] = vt_ctrl[TEMP].key[KEY_PRESS];
|
||||
else
|
||||
memset(&vt_ctrl[TEMP].key[KEY_PRESS_WITH_SHIFT], 0, sizeof(Key_t));
|
||||
|
||||
uint16_t key_now = vt_ctrl[TEMP].key[KEY_PRESS].keys, // 当前按键是否按下
|
||||
key_last = vt_ctrl[LAST].key[KEY_PRESS].keys, // 上一次按键是否按下
|
||||
key_with_ctrl = vt_ctrl[TEMP].key[KEY_PRESS_WITH_CTRL].keys, // 当前ctrl组合键是否按下
|
||||
key_with_shift = vt_ctrl[TEMP].key[KEY_PRESS_WITH_SHIFT].keys, // 当前shift组合键是否按下
|
||||
key_last_with_ctrl = vt_ctrl[LAST].key[KEY_PRESS_WITH_CTRL].keys, // 上一次ctrl组合键是否按下
|
||||
key_last_with_shift = vt_ctrl[LAST].key[KEY_PRESS_WITH_SHIFT].keys; // 上一次shift组合键是否按下
|
||||
|
||||
for (uint16_t i = 0, j = 0x1; i < 16; j <<= 1, i++)
|
||||
{
|
||||
if (i == 4 || i == 5) // 4,5位为ctrl和shift,直接跳过
|
||||
continue;
|
||||
// 如果当前按键按下,上一次按键没有按下,且ctrl和shift组合键没有按下,则按键按下计数加1(检测到上升沿)
|
||||
if ((key_now & j) && !(key_last & j) && !(key_with_ctrl & j) && !(key_with_shift & j))
|
||||
vt_ctrl[TEMP].key_count[KEY_PRESS][i]++;
|
||||
// 当前ctrl组合键按下,上一次ctrl组合键没有按下,则ctrl组合键按下计数加1(检测到上升沿)
|
||||
if ((key_with_ctrl & j) && !(key_last_with_ctrl & j))
|
||||
vt_ctrl[TEMP].key_count[KEY_PRESS_WITH_CTRL][i]++;
|
||||
// 当前shift组合键按下,上一次shift组合键没有按下,则shift组合键按下计数加1(检测到上升沿)
|
||||
if ((key_with_shift & j) && !(key_last_with_shift & j))
|
||||
vt_ctrl[TEMP].key_count[KEY_PRESS_WITH_SHIFT][i]++;
|
||||
}
|
||||
|
||||
memcpy(&vt_ctrl[LAST], &vt_ctrl[TEMP], sizeof(VT_ctrl_t)); // 保存上一次的数据,用于按键持续按下和切换的判断
|
||||
}
|
||||
|
||||
/*裁判系统串口接收回调函数,解析数据 */
|
||||
static void VTRefereeRxCallback()
|
||||
{
|
||||
DaemonReload(vision_transfer_daemon);
|
||||
JudgeReadVTData(vt_usart_instance->recv_buff);
|
||||
vt_to_rc();
|
||||
}
|
||||
// 裁判系统丢失回调函数,重新初始化裁判系统串口
|
||||
static void VTRefereeLostCallback(void *arg)
|
||||
{
|
||||
USARTServiceInit(vt_usart_instance);
|
||||
LOGWARNING("[rm_ref] lost referee vision data ");
|
||||
}
|
||||
|
||||
/* 裁判系统通信初始化 */
|
||||
VT_ctrl_t *VTRefereeInit(UART_HandleTypeDef *vt_usart_handle)
|
||||
{
|
||||
USART_Init_Config_s conf;
|
||||
conf.module_callback = VTRefereeRxCallback;
|
||||
conf.usart_handle = vt_usart_handle;
|
||||
conf.recv_buff_size = RE_RX_BUFFER_SIZE; // mx 255(u8)
|
||||
vt_usart_instance = USARTRegister(&conf);
|
||||
|
||||
Daemon_Init_Config_s daemon_conf = {
|
||||
.callback = VTRefereeLostCallback,
|
||||
.owner_id = vt_usart_instance,
|
||||
.reload_count = 30, // 0.3s没有收到数据,则认为丢失,重启串口接收
|
||||
};
|
||||
vision_transfer_daemon = DaemonRegister(&daemon_conf);
|
||||
|
||||
return &vt_ctrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 裁判系统数据发送函数
|
||||
* @param
|
||||
*/
|
||||
void VTRefereeSend(uint8_t *send, uint16_t tx_len)
|
||||
{
|
||||
USARTSend(vt_usart_instance, send, tx_len, USART_TRANSFER_DMA);
|
||||
osDelay(115);
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
#ifndef VISION_TRANSFER_H
|
||||
#define VISION_TRANSFER_H
|
||||
|
||||
#include "usart.h"
|
||||
#include "referee_protocol.h"
|
||||
#include "robot_def.h"
|
||||
#include "bsp_usart.h"
|
||||
#include "FreeRTOS.h"
|
||||
#include "remote_control.h"
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
// 此结构体包含裁判系统接收数据以及UI绘制与机器人车间通信的相关信息
|
||||
typedef struct
|
||||
{
|
||||
|
||||
xFrameHeader FrameHeader; // 接收到的帧头信息
|
||||
uint16_t CmdID;
|
||||
|
||||
vision_transfer_t VisionTransfer;
|
||||
Communicate_ReceiveData_t ReceiveData;
|
||||
|
||||
uint8_t init_flag;
|
||||
|
||||
} referee_info_vt_t;
|
||||
|
||||
#pragma pack()
|
||||
|
||||
/**
|
||||
* @brief 裁判系统通信初始化,该函数会初始化裁判系统串口,开启中断
|
||||
*
|
||||
* @param vt_usart_handle 串口handle,C板一般用串口6
|
||||
* @return referee_info_t* 返回裁判系统反馈的数据,包括热量/血量/状态等
|
||||
*/
|
||||
VT_ctrl_t *VTRefereeInit(UART_HandleTypeDef *referee_usart_handle);
|
||||
|
||||
/**
|
||||
* @brief UI绘制和交互数的发送接口,由UI绘制任务和多机通信函数调用
|
||||
* @note 内部包含了一个实时系统的延时函数,这是因为裁判系统接收CMD数据至高位10Hz
|
||||
*
|
||||
* @param send 发送数据首地址
|
||||
* @param tx_len 发送长度
|
||||
*/
|
||||
void VTRefereeSend(uint8_t *send, uint16_t tx_len);
|
||||
|
||||
#endif // !REFEREE_H
|
|
@ -5,15 +5,21 @@
|
|||
#include "stdlib.h"
|
||||
#include "daemon.h"
|
||||
#include "bsp_log.h"
|
||||
#include "referee_protocol.h"
|
||||
#include "rm_referee.h"
|
||||
|
||||
#define REMOTE_CONTROL_FRAME_SIZE 18u // 遥控器接收的buffer大小
|
||||
|
||||
// 遥控器数据
|
||||
static RC_ctrl_t rc_ctrl[2]; //[0]:当前数据TEMP,[1]:上一次的数据LAST.用于按键持续按下和切换的判断
|
||||
|
||||
|
||||
static uint8_t rc_init_flag = 0; // 遥控器初始化标志位
|
||||
|
||||
// 遥控器拥有的串口实例,因为遥控器是单例,所以这里只有一个,就不封装了
|
||||
// 第二个串口实例,有可能出现问题
|
||||
static USARTInstance *rc_usart_instance;
|
||||
|
||||
static DaemonInstance *rc_daemon_instance;
|
||||
|
||||
/**
|
||||
|
@ -134,4 +140,4 @@ uint8_t RemoteControlIsOnline()
|
|||
if (rc_init_flag)
|
||||
return DaemonIsOnline(rc_daemon_instance);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -113,6 +113,20 @@ typedef struct
|
|||
uint8_t key_count[3][16];
|
||||
} RC_ctrl_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
struct
|
||||
{
|
||||
int16_t x;
|
||||
int16_t y;
|
||||
uint8_t press_l;
|
||||
uint8_t press_r;
|
||||
} mouse;
|
||||
|
||||
Key_t key[3];
|
||||
uint8_t key_count[3][16];
|
||||
}VT_ctrl_t; //图传链路下发的遥控数据
|
||||
|
||||
/* ------------------------- Internal Data ----------------------------------- */
|
||||
|
||||
/**
|
||||
|
@ -123,6 +137,7 @@ typedef struct
|
|||
*/
|
||||
RC_ctrl_t *RemoteControlInit(UART_HandleTypeDef *rc_usart_handle);
|
||||
|
||||
|
||||
/**
|
||||
* @brief 检查遥控器是否在线,若尚未初始化也视为离线
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue