refactor: migrate from DJI motors to DM motors, simplify to gimbal-only control
- Rewrite DM motor driver based on DM_6220 reference protocol (MIT/PosVel/Velocity modes) - Use velocity control mode: MCU runs angle PID with IMU feedback, motor handles speed loop - Rewrite vision protocol with 3 frame types (0xA5 auto data, 0xA6 manual data, 0xA7 command) - Decouple serial parsing (opencv module) from mode switching (robot_cmd module) - Implement dual-loop architecture: vision PID outer loop → angle ref → motor PID inner loop - Add KF/PID reset on mode switch transitions - Merge motor_reverse_flag and feedback_reverse_flag into single output_reverse flag - Remove DMMotorEnable/DMMotorStop (motor always runs, controlled by angle ref) - Remove unused modules: DJI/LK/HT/step/servo motors, chassis, shoot, referee - Add ExitRun0Mode() for STM32H723 power supply configuration - Clean up CMakeLists: 115 → 76 C source files
This commit is contained in:
+57
-81
@@ -1,99 +1,75 @@
|
||||
#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];
|
||||
VisionData_t vision_data;
|
||||
|
||||
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;
|
||||
static DaemonInstance *vision_daemon_instance;
|
||||
|
||||
/**
|
||||
* @brief 接收解包回调函数,将在bsp_usart.c中被usart rx callback调用
|
||||
* @todo 1.提高可读性,将get_protocol_info的第四个参数增加一个float类型buffer
|
||||
* 2.添加标志位解码
|
||||
*/
|
||||
static void DecodeVision()
|
||||
static uint8_t calc_checksum(uint8_t *buf, uint8_t len)
|
||||
{
|
||||
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;
|
||||
uint8_t sum = 0;
|
||||
for (uint8_t i = 0; i < len - 1; i++)
|
||||
sum += buf[i];
|
||||
return sum;
|
||||
}
|
||||
|
||||
void VisionOfflineCallback(void *owner_id)
|
||||
static void DecodeVision()
|
||||
{
|
||||
Vison_revc_flag = 0; // 清除接收标志位
|
||||
DaemonReload(vision_daemon_instance);
|
||||
|
||||
static uint32_t counter;
|
||||
float dt = DWT_GetDeltaT(&counter);
|
||||
vision_data.frequency = 1.0f / dt;
|
||||
|
||||
uint8_t *buf = cv_usart_instance->recv_buff;
|
||||
uint16_t len = cv_usart_instance->recv_buff_size;
|
||||
uint8_t sof = buf[0];
|
||||
|
||||
if (sof == VISION_SOF_AUTO && len == VISION_AUTO_LEN)
|
||||
{
|
||||
if (calc_checksum(buf, VISION_AUTO_LEN) != buf[VISION_AUTO_LEN - 1])
|
||||
return;
|
||||
memcpy(&vision_data.error_x, buf + 1, 4);
|
||||
memcpy(&vision_data.error_y, buf + 5, 4);
|
||||
vision_data.auto_updated = 1;
|
||||
}
|
||||
else if (sof == VISION_SOF_MANUAL && len == VISION_MANUAL_LEN)
|
||||
{
|
||||
if (calc_checksum(buf, VISION_MANUAL_LEN) != buf[VISION_MANUAL_LEN - 1])
|
||||
return;
|
||||
vision_data.zero_force = buf[1];
|
||||
memcpy(&vision_data.yaw_ref, buf + 2, 4);
|
||||
memcpy(&vision_data.pitch_ref, buf + 6, 4);
|
||||
vision_data.manual_updated = 1;
|
||||
}
|
||||
else if (sof == VISION_SOF_CMD && len == VISION_CMD_LEN)
|
||||
{
|
||||
if (calc_checksum(buf, VISION_CMD_LEN) != buf[VISION_CMD_LEN - 1])
|
||||
return;
|
||||
vision_data.cmd = buf[1];
|
||||
vision_data.cmd_pending = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void VisionOfflineCallback(void *id)
|
||||
{
|
||||
(void)id;
|
||||
USARTServiceInit(cv_usart_instance);
|
||||
}
|
||||
|
||||
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;
|
||||
USART_Init_Config_s conf = {
|
||||
.module_callback = DecodeVision,
|
||||
.recv_buff_size = 64,
|
||||
.usart_handle = _handle,
|
||||
};
|
||||
cv_usart_instance = USARTRegister(&conf);
|
||||
|
||||
// 为master process注册daemon,用于判断视觉通信是否离线
|
||||
Daemon_Init_Config_s daemon_conf = {
|
||||
.callback = VisionOfflineCallback, // 离线时调用的回调函数,会重启串口接收
|
||||
.owner_id = NULL,
|
||||
.callback = NULL,
|
||||
.owner_id = NULL,
|
||||
.reload_count = 10,
|
||||
};
|
||||
OPENCV_vision_daemon_instance = DaemonRegister(&daemon_conf);
|
||||
}
|
||||
vision_daemon_instance = DaemonRegister(&daemon_conf);
|
||||
}
|
||||
|
||||
+63
-10
@@ -1,22 +1,75 @@
|
||||
#ifndef OPENCV_H
|
||||
#define OPENCV_H
|
||||
|
||||
#include "bsp_usart.h"
|
||||
#include "opencv.h"
|
||||
#include "bsp_log.h"
|
||||
#include "bsp_dwt.h"
|
||||
#include "bsp_log.h"
|
||||
#include "usart.h"
|
||||
#include "robot_def.h"
|
||||
#include "daemon.h"
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/*
|
||||
* 上位机串口协议 — 三种帧类型, 通过帧头区分
|
||||
*
|
||||
* ---- 自动/视觉追踪数据帧 0xA5 (10 字节) ----
|
||||
* [SOF:0xA5][error_x:4][error_y:4][checksum:1]
|
||||
* error_x/y: float, 归一化误差, 视觉PID外环反馈值
|
||||
*
|
||||
* ---- 手动控制数据帧 0xA6 (11 字节) ----
|
||||
* [SOF:0xA6][zero_force:1][yaw_ref:4][pitch_ref:4][checksum:1]
|
||||
* zero_force: 0=正常角度控制, 1=零力/保持当前位置
|
||||
* yaw_ref/pitch_ref: float, 角度参考值 (degrees)
|
||||
*
|
||||
* ---- 命令帧 0xA7 (3 字节) ----
|
||||
* [SOF:0xA7][cmd:1][checksum:1]
|
||||
* cmd: 0x01=切换到自动模式, 0x02=切换到手动模式, 0x03=激光开, 0x04=激光关
|
||||
*
|
||||
* checksum: 帧头到数据末尾前一字节累加和取低8位
|
||||
*/
|
||||
|
||||
#define VISION_SOF_AUTO 0xA5
|
||||
#define VISION_SOF_MANUAL 0xA6
|
||||
#define VISION_SOF_CMD 0xA7
|
||||
|
||||
#define VISION_AUTO_LEN 10
|
||||
#define VISION_MANUAL_LEN 11
|
||||
#define VISION_CMD_LEN 3
|
||||
|
||||
/* 命令码 */
|
||||
#define VISION_CMD_SWITCH_AUTO 0x01
|
||||
#define VISION_CMD_SWITCH_MANUAL 0x02
|
||||
#define VISION_CMD_LASER_ON 0x03
|
||||
#define VISION_CMD_LASER_OFF 0x04
|
||||
|
||||
/* 工作模式 */
|
||||
typedef enum
|
||||
{
|
||||
VISION_MODE_AUTO = 0, // 自动/视觉追踪
|
||||
VISION_MODE_MANUAL = 1, // 手动
|
||||
} Vision_Mode_e;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* 自动模式数据 */
|
||||
float error_x;
|
||||
float error_y;
|
||||
uint8_t auto_updated; // 收到新的自动数据帧标志
|
||||
|
||||
/* 手动模式数据 */
|
||||
uint8_t zero_force;
|
||||
float yaw_ref;
|
||||
float pitch_ref;
|
||||
uint8_t manual_updated; // 收到新的手动数据帧标志
|
||||
|
||||
/* 命令 */
|
||||
uint8_t cmd; // 最新命令码
|
||||
uint8_t cmd_pending; // 有待处理命令标志
|
||||
|
||||
float frequency; // 接收频率 (Hz)
|
||||
} VisionData_t;
|
||||
|
||||
extern VisionData_t vision_data;
|
||||
|
||||
void Vision_Uart_Init(UART_HandleTypeDef *_handle);
|
||||
extern float opencv_Vision_data[12]; // 视觉数据,12个float
|
||||
extern uint8_t Vison_revc_flag; // 视觉数据接收标志位
|
||||
extern uint8_t vision_used_flag; // 视觉数据使用标志位,用于判断是否需要使用视觉数据
|
||||
extern float Vison_Frequency; // 视觉数据频率
|
||||
|
||||
|
||||
#endif // !OPENCV_H
|
||||
#endif // OPENCV_H
|
||||
|
||||
Reference in New Issue
Block a user