Files
Gimbal/modules/opencv/opencv.c
T
2026-05-29 17:36:34 +08:00

99 lines
3.2 KiB
C

#include "opencv.h"
#include "daemon.h"
#define FRAME_SOF 0xA5
#define FRAME_PAYLOAD_LEN (2+2+4*12) // 52
#define FRAME_FULL_LEN (1+1+FRAME_PAYLOAD_LEN) //54
float opencv_Vision_data[12];
uint8_t Vison_revc_flag = 0; // 视觉数据接收标志位
uint8_t vision_used_flag = 0; // 视觉数据使用标志位,用于判断是否需要使用视觉数据
float Vison_Frequency; // 视觉数据接收频率,单位Hz
static USARTInstance *cv_usart_instance;
static DaemonInstance *OPENCV_vision_daemon_instance;
/**
* @brief 接收解包回调函数,将在bsp_usart.c中被usart rx callback调用
* @todo 1.提高可读性,将get_protocol_info的第四个参数增加一个float类型buffer
* 2.添加标志位解码
*/
static void DecodeVision()
{
DaemonReload(OPENCV_vision_daemon_instance); // 喂狗,防止离线
static uint32_t counter;
float dt = DWT_GetDeltaT(&counter);
Vison_Frequency = 1.0f / dt; // 计算频率
const uint16_t len = cv_usart_instance->recv_buff_size;
uint16_t flag_register;
uint8_t *buf = cv_usart_instance->recv_buff;
if (len != FRAME_FULL_LEN) {
// 长度不符
LOGERROR("Vision frame length error");
return;
}
if (buf[0] != FRAME_SOF) {
// SOF 错误
LOGERROR("Vision frame SOF error");
return;
}
uint8_t payload_len = buf[1];
if (payload_len != FRAME_PAYLOAD_LEN) {
// Payload 长度不符
LOGERROR("Vision frame payload length error");
return;
}
// 解析命令号和 flags(小端)
uint16_t cmd_id = buf[2] | (buf[3] << 8);
uint16_t flags = buf[4] | (buf[5] << 8);
// 解析 12 个 float
for (int i = 0; i < 12; i++) {
// 从 buf[6 + 4*i] 连续读 4 字节
memcpy(&opencv_Vision_data[i], buf + 6 + 4*i, sizeof(float));
}
// // 解析任务标志位(拟合最接近的int)
// int last_task_cmd = Vison_task_cmd;
// Vison_task_cmd = (int)(Vison_data[10] + 0.5f);
// if (Vison_task_cmd != last_task_cmd) {
// Vison_task_changed = 1; // 任务命令变化
// }
Vison_revc_flag = 1; // 设置接收标志位
// vision_used_flag = 1; // 设置视觉数据使用标志位
//解析暂停标志位
// run = (int)(Vison_data[11] + 0.5f);
// 处理...
// printf("Got frame: cmd=0x%04X flags=0x%04X\n", cmd_id, flags);
// for (int i = 0; i < 12; i += 2) {
// printf(" coord %d: (%.3f, %.3f)\n",
// i/2, data[i], data[i+1]);
// float a = data[0];
// TODO: code to resolve flag_register;
}
void VisionOfflineCallback(void *owner_id)
{
Vison_revc_flag = 0; // 清除接收标志位
}
void Vision_Uart_Init(UART_HandleTypeDef *_handle)
{
USART_Init_Config_s conf;
conf.module_callback = DecodeVision;
conf.recv_buff_size = 54;
conf.usart_handle = _handle;
cv_usart_instance = USARTRegister(&conf);
// 为master process注册daemon,用于判断视觉通信是否离线
Daemon_Init_Config_s daemon_conf = {
.callback = VisionOfflineCallback, // 离线时调用的回调函数,会重启串口接收
.owner_id = NULL,
.reload_count = 10,
};
OPENCV_vision_daemon_instance = DaemonRegister(&daemon_conf);
}