大学生机器人比赛实战(二)软件篇

大学生机器人比赛深度开发指南:核心技术详解与实战代码解析

作为参加过多次机器人竞赛的选手,我将详细剖析比赛中的核心技术实现,包括软件架构设计、实时系统应用、各大赛事代码特点以及性能优化技巧。本指南将帮助你从代码层面深入理解如何打造一个冠军级机器人系统。

一、机器人软件架构设计

1.1 分层架构设计

一个完整的比赛机器人通常采用分层架构设计:

复制代码
应用层(比赛策略)
  ↓
业务逻辑层(任务调度)
  ↓
功能模块层(视觉/控制/通信)
  ↓
硬件抽象层(HAL)
  ↓
硬件层(传感器/执行器)

典型头文件组织

c 复制代码
// hal_uart.h - 硬件抽象层
void UART_Init(uint32_t baudrate);
void UART_Send(uint8_t *data, uint16_t len);

// driver_motor.h - 功能模块层
void Motor_SetSpeed(uint8_t id, int16_t speed);

// task_control.h - 业务逻辑层
void Control_Task(void *params);

// strategy.h - 应用层
void Strategy_Update(GameState *game);

1.2 实时性保障方案

中断优先级配置(STM32为例)

c 复制代码
void NVIC_Configuration(void)
{
    HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0); // 系统滴答最高优先级
    HAL_NVIC_SetPriority(EXTI0_IRQn, 1, 0);   // 紧急传感器中断
    HAL_NVIC_SetPriority(TIM3_IRQn, 2, 0);    // 电机控制定时器
    HAL_NVIC_SetPriority(USART1_IRQn, 3, 0);  // 通信中断
}

二、RTOS在比赛中的应用

2.1 何时使用RTOS?

需要RTOS的场景

  • 多任务并行处理(如视觉+控制+通信)
  • 复杂状态机管理
  • 需要精确时序控制
  • 系统资源需要动态管理

可以不用RTOS的情况

  • 简单循迹/搬运机器人
  • 单任务循环就能满足需求
  • 硬件资源极其有限

2.2 FreeRTOS实战配置

CubeMX配置示例

  1. 选择TIM6作为时基源(1kHz)
  2. 启用FreeRTOS支持
  3. 设置堆大小(≥10KB)
  4. 创建关键任务:
    • 控制任务(优先级3)
    • 视觉任务(优先级2)
    • 通信任务(优先级1)

任务创建代码

c 复制代码
void StartDefaultTask(void const *argument)
{
    // 创建控制任务
    osThreadDef(ControlTask, Control_Task, osPriorityHigh, 0, 512);
    osThreadCreate(osThread(ControlTask), NULL);
    
    // 创建视觉任务
    osThreadDef(VisionTask, Vision_Task, osPriorityNormal, 0, 1024);
    osThreadCreate(osThread(VisionTask), NULL);
    
    // 空闲任务中可以监控系统状态
    for(;;) {
        vTaskDelay(1000);
        printf("CPU Usage: %.1f%%\n", osGetCPUUsage());
    }
}

三、各大赛事代码特点详解

3.1 RoboMaster步兵机器人代码架构

典型控制流程

c 复制代码
// 云台控制任务
void Gimbal_Task(void *params)
{
    while(1) {
        // 1. 获取目标信息
        TargetInfo target = Vision_GetTarget();
        
        // 2. PID控制计算
        PID_Calc(&yaw_pid, target.yaw_angle);
        PID_Calc(&pitch_pid, target.pitch_angle);
        
        // 3. 电机输出
        Motor_SetAngle(YAW_MOTOR, yaw_pid.output);
        Motor_SetAngle(PITCH_MOTOR, pitch_pid.output);
        
        // 4. 射击决策
        if(target.valid && target.distance < 3.0f) {
            Shoot_Control(1); // 单发射击
        }
        
        osDelay(2); // 500Hz控制频率
    }
}

关键技术点

  1. 双闭环PID控制(位置环+速度环)
  2. 弹道补偿算法
  3. 超级电容能量管理
  4. 装甲健康度监测

3.2 ROBOCON机械臂控制代码

运动学逆解实现

c 复制代码
// 机械臂逆运动学计算
ArmAngles IK_Calculate(Point3D target)
{
    ArmAngles angles;
    
    // 第一关节角度计算
    angles.base = atan2(target.y, target.x);
    
    // 第二三关节角度计算(几何法)
    float L = sqrt(target.x*target.x + target.y*target.y);
    float D = sqrt(L*L + (target.z - BASE_HEIGHT)*(target.z - BASE_HEIGHT));
    angles.shoulder = acos((UPPER_ARM*UPPER_ARM + D*D - LOWER_ARM*LOWER_ARM) 
                          / (2*UPPER_ARM*D)) 
                     + atan2(target.z - BASE_HEIGHT, L);
    
    angles.elbow = acos((UPPER_ARM*UPPER_ARM + LOWER_ARM*LOWER_ARM - D*D)
                      / (2*UPPER_ARM*LOWER_ARM));
    
    return angles;
}

运动规划算法

c 复制代码
// 梯形速度规划
void Trapezoidal_Plan(float current_pos, float target_pos, float max_speed, float max_acc)
{
    static float current_speed = 0;
    float distance = target_pos - current_pos;
    float stop_distance = current_speed*current_speed / (2*max_acc);
    
    if(fabs(distance) < stop_distance) {
        // 减速阶段
        current_speed -= max_acc * CONTROL_PERIOD;
    } 
    else if(fabs(current_speed) < max_speed) {
        // 加速阶段
        current_speed += max_acc * CONTROL_PERIOD;
    }
    
    // 位置更新
    current_pos += current_speed * CONTROL_PERIOD;
}

3.3 电赛智能车控制代码

模糊PID控制实现

c 复制代码
// 模糊PID控制器
float Fuzzy_PID(float error, float error_rate)
{
    // 模糊化输入
    int e_level = Fuzzy_Map(error, -10, 10, 7); // 7个等级
    int ec_level = Fuzzy_Map(error_rate, -5, 5, 7);
    
    // 查模糊规则表
    const int rule[7][7] = {
        {1,1,1,2,2,3,3},
        {1,1,2,2,3,3,4},
        // ... 其他规则
    };
    int level = rule[e_level][ec_level];
    
    // 去模糊化
    float delta_kp = level * 0.1f; // 比例系数调整
    
    // 动态调整PID参数
    pid.Kp = BASE_KP + delta_kp;
    return PID_Calculate(&pid, error);
}

图像处理优化技巧

c 复制代码
// 快速巡线算法
void Find_TrackLine(uint8_t *image, int width, int height)
{
    int center = width / 2;
    int left_edge = 0;
    int right_edge = width - 1;
    
    // 从中间向左右搜索边界
    for(int i = 0; i < height; i++) {
        uint8_t *row = image + i * width;
        
        // 向左搜索
        for(int j = center; j > 0; j--) {
            if(row[j] - row[j-1] > THRESHOLD) {
                left_edge = j;
                break;
            }
        }
        
        // 向右搜索
        for(int j = center; j < width-1; j++) {
            if(row[j] - row[j+1] > THRESHOLD) {
                right_edge = j;
                break;
            }
        }
        
        center = (left_edge + right_edge) / 2;
        Draw_CenterLine(center);
    }
}

四、高级功能实现

4.1 视觉识别优化

OpenMV代码示例

python 复制代码
# 色块识别与追踪
import sensor, image, time

# 初始化摄像头
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
sensor.skip_frames(time = 2000)

# 定义目标颜色阈值
red_threshold = (30, 100, 15, 127, 15, 127)

while(True):
    img = sensor.snapshot()
    
    # 寻找色块
    blobs = img.find_blobs([red_threshold], 
                          pixels_threshold=100, 
                          area_threshold=100, 
                          merge=True)
    
    if blobs:
        max_blob = max(blobs, key=lambda b: b.pixels())
        
        # 计算目标在图像中的位置
        img.draw_rectangle(max_blob.rect())
        img.draw_cross(max_blob.cx(), max_blob.cy())
        
        # 计算偏航角度(假设摄像头水平FOV=60度)
        yaw_angle = (max_blob.cx() - img.width()/2) * 60.0 / img.width()
        print("Yaw Angle: %.1f" % yaw_angle)

4.2 通信协议设计

自定义串口协议

c 复制代码
#pragma pack(1) // 单字节对齐
typedef struct {
    uint8_t head;    // 0xAA
    uint8_t type;    // 数据类型
    uint16_t len;    // 数据长度
    uint8_t data[32];// 数据内容
    uint16_t crc;    // CRC校验
} UART_Frame;

// 帧解析函数
int UART_Parse(uint8_t *buf, int len)
{
    UART_Frame *frame = (UART_Frame *)buf;
    
    // 校验帧头
    if(frame->head != 0xAA) return -1;
    
    // 校验CRC
    if(CRC_Check(buf, sizeof(UART_Frame)-2, frame->crc) != 0) {
        return -2;
    }
    
    // 处理数据
    switch(frame->type) {
        case VISION_DATA:
            memcpy(&vision_data, frame->data, sizeof(vision_data));
            break;
        case GAME_STATE:
            game_state = *(GameState*)frame->data;
            break;
    }
    
    return 0;
}

4.3 运动控制优化

速度前馈控制

c 复制代码
void Motor_Control(float target_pos, float current_pos)
{
    static float last_pos = 0;
    float speed = (current_pos - last_pos) / CONTROL_PERIOD;
    last_pos = current_pos;
    
    // PID控制
    float error = target_pos - current_pos;
    float pid_out = PID_Calculate(&pid, error);
    
    // 速度前馈
    float feedforward = speed * FF_GAIN;
    
    // 输出叠加
    float output = pid_out + feedforward;
    PWM_SetDuty(output);
}

五、调试与优化技巧

5.1 实时调试方法

SWD调试配置

  1. 在CubeMX中启用SWD接口(SWCLK+SWDIO)
  2. 在Keil/IAR中配置调试选项:
    • 选择ST-Link调试器
    • 设置复位模式为"硬件复位"
    • 启用"运行到main()"

实时变量监控

c 复制代码
// 在Watch窗口添加这些变量
volatile float motor_speed;   // 加volatile防止优化
volatile int32_t encoder_val;
volatile uint8_t system_state;

5.2 性能优化技巧

关键代码优化

c 复制代码
// 优化前
for(int i=0; i<100; i++) {
    value += array[i] * coefficients[i];
}

// 优化后(使用指针+循环展开)
int *p = array;
int *c = coefficients;
int sum = 0;
for(int i=0; i<100; i+=4) {
    sum += p[0]*c[0] + p[1]*c[1] + p[2]*c[2] + p[3]*c[3];
    p += 4;
    c += 4;
}

内存优化策略

  1. 使用内存池管理动态内存
  2. 关键数据结构对齐到32位
  3. 启用编译器优化(-O2/-O3)
  4. 使用DMA减少CPU开销

六、比赛经验总结

6.1 开发流程建议

  1. 需求分析阶段(1周):

    • 详细分析比赛规则
    • 确定技术指标(速度/精度等)
    • 制定测试方案
  2. 原型开发阶段(2周):

    • 搭建最小系统
    • 验证核心算法
    • 完成基本功能
  3. 系统集成阶段(1周):

    • 模块联调
    • 性能优化
    • 编写技术报告
  4. 测试改进阶段(持续):

    • 模拟比赛环境测试
    • 收集数据改进算法
    • 完善故障处理机制

6.2 常见问题解决方案

电机控制异常

  1. 检查电源电压是否稳定
  2. 验证PWM信号是否正确
  3. 检查编码器接线
  4. 调整PID参数(先P后D最后I)

视觉识别不稳定

  1. 优化光照条件
  2. 增加图像滤波
  3. 采用多帧验证机制
  4. 使用深度学习替代传统算法

通信丢包问题

  1. 降低波特率测试
  2. 增加数据校验
  3. 优化天线位置
  4. 采用重传机制

通过本指南的系统学习,你将掌握机器人比赛开发的核心技术要点。记住,优秀的比赛作品=扎实的基础+创新的设计+充分的测试。建议从简单功能开始,逐步迭代完善,最终打造出具备竞争力的机器人系统!

相关推荐
wuyk5556 小时前
4.树:一对多的层次数据结构
开发语言·数据结构·stm32·单片机
天空'之城8 小时前
单片机基础核心知识点汇总(五)
单片机·嵌入式硬件
神经智研社11 小时前
ROS2-第十七章:网络通信,win11系统 通过镜像配置 打通 WSL 下的ros2与 同局域网(同IP段)的里其它设备上的ros2通信
机器人·机器人环境搭建·win11 ros2 开发环境
Nomarsgo13 小时前
机器视觉+六轴机械臂智能制造解决方案——基于联控Lionconit RMC-610构建视觉计算与机器人协同控制平台
科技·机器人·自动化·汽车·电脑·制造
双星系统13 小时前
双臂机器人迎来广阔应用风口!既是工业柔性主力,也是人形机器人优质上肢配件
人工智能·机器人
恒锐丰-罗生13 小时前
SS8103 芯片解析:45V 同步整流降压半桥恒流驱动控制器 大功率光源国产优选 告别低灰闪烁!
驱动开发·嵌入式硬件·硬件工程
zhangrelay14 小时前
ROS 2 Lyrical 第9章 计算机视觉与摄像头应用
linux·笔记·学习·ubuntu·机器人·ros2
FakeOccupational14 小时前
【电路笔记 STM32】stm32f103 实现HAL_UART_Transmit_DMA + 普通模式/连续模式的 UART DMA 收发
笔记·stm32·嵌入式硬件
wuyk55515 小时前
第 6 章 FOC 完整系统整合:从算法到真机跑起来
c语言·开发语言·stm32·单片机·嵌入式硬件
恒锐丰科技韩生15 小时前
率能 SS6810H|10‑32V 双通道 H 桥步进电机驱动 ETSSOP20 打印机安防舞台灯光专用
嵌入式硬件·硬件工程