god-yuan-hero/User/module/vision_bridge.c
2026-01-13 05:51:31 +08:00

130 lines
4.3 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "vision_bridge.h"
#include "device/device.h"
#include "bsp/uart.h"
#include "component/crc16.h"
#include <string.h>
#include "bsp/fdcan.h"
#define AI_CMD_CAN_DLC (8u) /* 1字节mode + 3.5字节yaw + 3.5字节pit */
#define AI_CMD_ANGLE_SCALE (10000000.0f) /* 0.0000001 rad per LSB */
int8_t AI_Init(AI_t *ai, AI_Param_t *param) {
if (ai == NULL) return DEVICE_ERR_NULL;
BSP_FDCAN_Init();
memset(ai, 0, sizeof(AI_t));
ai->param = param;
BSP_FDCAN_RegisterId(ai->param->can, ai->param->vision_id, 3);
return 0;
}
int8_t AI_StartReceiving(AI_t *ai) {
if (BSP_UART_Receive(BSP_UART_AI,(uint8_t *)&ai->fromhost,sizeof(ai->fromhost), true)==HAL_OK) {
return DEVICE_OK;}
return DEVICE_ERR;
}
int8_t AI_ParseForHost(AI_t* ai, AI_RawData_t* raw_data){
ai->tohost.head[0]='M';
ai->tohost.head[1]='R';
ai->tohost.mode=raw_data->mode;
ai->tohost.pitch=raw_data->pitch;
ai->tohost.yaw=raw_data->yaw;
ai->tohost.pitch_vel=raw_data->pitch_vel;
ai->tohost.yaw_vel=raw_data->yaw_vel;
ai->tohost.q[0]=raw_data->q[0];
ai->tohost.q[1]=raw_data->q[1];
ai->tohost.q[2]=raw_data->q[2];
ai->tohost.q[3]=raw_data->q[3];
ai->tohost.bullet_count=10;
ai->tohost.bullet_speed=10.5;
ai->tohost.crc16=CRC16_Calc(((const uint8_t*)&(ai->tohost)),sizeof(ai->tohost)-sizeof(uint16_t), CRC16_INIT );
if(CRC16_Verify(((const uint8_t*)&(ai->tohost)), sizeof(ai->tohost))!=true){
return DEVICE_ERR;
}
return DEVICE_OK;
}
int8_t AI_StartSend(AI_t *ai) {
if (BSP_UART_Transmit(BSP_UART_AI,(uint8_t *)&ai->tohost,sizeof(ai->tohost), true)==HAL_OK)
return DEVICE_OK;
}
int8_t AI_Get(AI_t *ai, AI_cmd_t* outcmd) {
if(ai->fromhost.head[0]!='M'&&ai->fromhost.head[1]!='R'){
return DEVICE_ERR;
}
// CRC16_Calc(&ai->fromhost,sizeof(ai->fromhost),ai->fromhost.crc16);
if(CRC16_Verify((const uint8_t*)&(ai->fromhost), sizeof(ai->fromhost))!=true){
return DEVICE_ERR;
}
outcmd->gimbal.setpoint.pit = ai->fromhost.pitch;
outcmd->gimbal.setpoint.yaw = ai->fromhost.yaw;
outcmd->mode = ai->fromhost.mode;
outcmd->gimbal.accl.pit = ai->fromhost.pitch_acc;
outcmd->gimbal.vel.pit = ai->fromhost.pitch_vel;
outcmd->gimbal.accl.yaw = ai->fromhost.yaw_acc;
outcmd->gimbal.vel.yaw = ai->fromhost.yaw_vel;
return DEVICE_OK;
}
/* 打包并通过 CAN2 发送AI命令给下层板mode + yaw + pit */
void AI_SendCmdOnFDCAN(AI_t *ai, const AI_cmd_t *cmd) {
if (cmd == NULL) return;
/* 将float角度转换为int32_t定点数0.0000001 rad/LSB */
const int32_t yaw = (int32_t)(cmd->gimbal.setpoint.yaw * AI_CMD_ANGLE_SCALE);
const int32_t pit = (int32_t)(cmd->gimbal.setpoint.pit * AI_CMD_ANGLE_SCALE);
BSP_FDCAN_StdDataFrame_t frame = {0};
frame.id = ai->param->vision_id;
frame.dlc = AI_CMD_CAN_DLC;
/* mode(1字节) + yaw(3.5字节) + pit(3.5字节) */
frame.data[0] = cmd->mode;
frame.data[1] = (uint8_t)((yaw >> 20) & 0xFF);
frame.data[2] = (uint8_t)((yaw >> 12) & 0xFF);
frame.data[3] = (uint8_t)((yaw >> 4) & 0xFF);
frame.data[4] = (uint8_t)(((yaw & 0xF) << 4) | ((pit >> 24) & 0xF));
frame.data[5] = (uint8_t)((pit >> 16) & 0xFF);
frame.data[6] = (uint8_t)((pit >> 8) & 0xFF);
frame.data[7] = (uint8_t)(pit & 0xFF);
(void)BSP_FDCAN_TransmitStdDataFrame(ai->param->can, &frame);
}
/* 从CAN消息解析AI命令 (mode + yaw + pit) */
void AI_ParseCmdFromCan(AI_t *ai, AI_cmd_t *cmd) {
if (cmd == NULL) {
return;
}
BSP_FDCAN_Message_t msg;
if (BSP_FDCAN_GetMessage(ai->param->can, ai->param->vision_id, &msg, BSP_FDCAN_TIMEOUT_IMMEDIATE) != 0) {
return;
}
/* 解析mode (1字节) */
cmd->mode = msg.data[0];
/* 解析yaw (3.5字节) */
int32_t yaw_raw = (int32_t)((msg.data[1] << 20) | (msg.data[2] << 12) | (msg.data[3] << 4) | ((msg.data[4] >> 4) & 0xF));
if (yaw_raw & 0x08000000) yaw_raw |= 0xF0000000;
cmd->gimbal.setpoint.yaw = (float)yaw_raw / AI_CMD_ANGLE_SCALE;
/* 解析pit (3.5字节) */
int32_t pit_raw = (int32_t)(((msg.data[4] & 0xF) << 24) | (msg.data[5] << 16) | (msg.data[6] << 8) | msg.data[7]);
if (pit_raw & 0x08000000) pit_raw |= 0xF0000000;
cmd->gimbal.setpoint.pit = (float)pit_raw / AI_CMD_ANGLE_SCALE;
/* 其他字段根据需要可以初始化为0 */
cmd->gimbal.vel.yaw = 0.0f;
cmd->gimbal.vel.pit = 0.0f;
cmd->gimbal.accl.yaw = 0.0f;
cmd->gimbal.accl.pit = 0.0f;
}