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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user