最近在准备第二十一届全国大学生智能汽车竞赛,尤其是新设立的“智慧医疗”组别,很多同学都在问:“这个新赛道到底怎么玩?能不能美美拿下国一?” 作为一个经历过几届竞赛的老队员,我深知从一个好想法到一辆稳定完赛的智能车,中间隔着无数个调试的夜晚和踩不完的“坑”。智慧医疗组别不仅要求车模跑得快、跑得稳,更核心的是要完成一系列模拟的医疗任务,比如物资配送、病患识别、环境消杀等,这对算法的综合设计和工程实现能力提出了更高要求。
本文就将以第二十一届智能汽车竞赛“智慧医疗”组别为核心,为你拆解备赛全流程。无论你是刚刚组队的新手,还是想优化方案冲击更高奖项的团队,都能从中找到清晰的路径。我们将从赛题解读、硬件选型、软件框架、核心算法到调试心得,一步步构建一个具备竞争力的智能车系统,并分享那些决定成败的细节与“避坑”指南。
1. 智慧医疗赛题深度解读与备赛核心思路
全国大学生智能汽车竞赛的“智慧医疗”组别,是一个高度融合了自动控制、机器视觉、嵌入式开发和场景化任务的应用型赛道。它模拟了医院等医疗场景下的自动化流程,考察参赛队伍在复杂、非结构化环境中,综合运用多种技术解决实际问题的能力。
1.1 赛题核心要求与任务分析
根据第二十一届竞赛的规则精神,智慧医疗组别的核心通常围绕以下几个任务展开,各队伍需仔细研读当年发布的详细规则文档:
- 循迹与导航:车模需在铺有引导线的赛道上稳定行驶。这是基础,但赛道可能包含十字、环岛、坡道等元素,并需要与任务点结合。
- 目标识别与交互:这是“智慧医疗”的精华。车模需要识别特定的视觉标签,例如:
- 药品/物资标签:识别不同颜色、形状或数字的标签,模拟分拣药品。
- 病患标识:识别二维码或AprilTag,获取“病患”ID或位置信息。
- 任务点标识:识别地面或立杆上的标识,触发相应动作(如停车、转向、抓取)。
- 机械臂操作:车模通常需要搭载一个轻量级机械臂或舵机云台,用于完成:
- 抓取与放置:从指定位置抓取“药品”(可能是积木块、小球)并运送到目标区域。
- 按压/触发:模拟对医疗设备的操作。
- 路径规划与决策:车模需要根据识别到的任务信息,动态规划行驶路径。例如,识别到“3号病房需药品A”,车模需自主规划前往药品A存放区,取药后再前往3号病房的路径。
备赛核心思路:绝不能将各个模块孤立开发。必须建立“感知-决策-控制-执行”的闭环系统思维。视觉识别的结果要能实时、准确地转化为控制指令(速度、转向、机械臂动作),同时车辆的稳定运行又是准确执行任务的前提。
1.2 技术栈选择与团队分工建议
一个高效的团队是成功的一半。建议4-5人组队,分工可参考如下:
- 硬件与机械组(1-2人):
- 负责车模底盘改装、电机驱动、电源管理。
- 设计并搭建机械臂、云台、抓取机构。核心原则:轻量化、刚性强、动作可靠。过多的重量和晃动是速度和精度的天敌。
- 传感器选型与安装:摄像头、激光雷达(如果规则允许)、编码器、陀螺仪等。
- 嵌入式与控制组(1-2人):
- 主控芯片编程(如STM32、K210、OpenMV等)。
- 实现电机PID控制,保证车速和转向的平稳性。
- 处理传感器数据(编码器测速、陀螺仪融合)。
- 作为下位机,接收上位机的决策指令并执行。
- 视觉与算法组(1-2人):
- 负责摄像头图像采集、预处理。
- 开发目标识别算法(如颜色识别、形状识别、二维码/AprilTag识别)。
- 实现简单的视觉巡线或辅助定位。
- 在上位机(如树莓派、Jetson Nano)上运行,并将识别结果发送给决策模块。
- 决策与系统集成(全员参与,由队长或核心成员牵头):
- 设计整车的软件架构和通信协议(如UART、CAN、TCP/IP)。
- 编写决策状态机,统筹视觉、定位、任务信息。
- 进行系统联调,优化整体性能。
主控选择:常见方案有“STM32 + OpenMV/ K210”(性价比高,适合入门)和“STM32 + 树莓派/Jetson Nano”(算力强,适合复杂视觉和决策)。智慧医疗组对视觉处理要求较高,推荐后者。
2. 硬件平台搭建与核心传感器配置
“工欲善其事,必先利其器”。一个稳定可靠的硬件平台是所有算法得以施展的基础。
2.1 车模选型与底盘改装
竞赛官方通常有指定的车模平台(如C型、D型车模)。在规则允许范围内,可以进行以下优化:
- 降低重心:将电池、主控板等重物尽量放低,提高高速过弯稳定性。
- 强化结构:检查并加固车模底盘连接处,防止长期运行后松动。
- 轮胎处理:清洁轮胎,必要时使用专用胶水增加抓地力。这是提升循迹性能成本最低、效果最显著的方法之一。
- 电机与驱动:确保电机驱动板(如TB6612、DRV8833)电流充足,并做好散热。PID调速的响应速度很大程度上取决于驱动性能。
2.2 视觉系统搭建
这是智慧医疗组的“眼睛”,其配置至关重要。
- 摄像头选型:
- 全局快门摄像头:优于卷帘快门,在车模移动时能有效减少图像畸变,推荐使用。
- 分辨率与帧率:1080p @ 30fps 或 720p @ 60fps 通常是够用的。更高的帧率有助于减少运动模糊。
- 安装位置:前瞻距离要合适。太近,反应时间不足;太远,图像中赛道占比太小,易受干扰。通常安装在车头前方15-25厘米,高度10-15厘米处。必须牢固,任何抖动都会导致识别失败。
- 机械臂与云台:
- 舵机选型:选择金属齿轮、扭矩足够的舵机(如MG996R)。数字舵机比模拟舵机控制精度更高。
- 结构设计:使用轻质材料(如碳纤维杆、3D打印件)。设计时要进行运动学仿真,确保工作空间能覆盖所有任务点。
- 示例:一个简单的二自由度舵机云台代码(STM32 HAL库):
// 文件路径:Core/Src/servo.c #include “servo.h” #include “tim.h” // 舵机控制函数,将角度转换为PWM占空比 // 假设使用TIM2 CH1, PWM周期20ms,0.5ms-2.5ms对应0-180度 void Servo_SetAngle(TIM_HandleTypeDef *htim, uint32_t Channel, float angle) { if (angle > 180.0f) angle = 180.0f; if (angle < 0.0f) angle = 0.0f; // 计算脉冲宽度 (单位:微秒) uint32_t pulse_us = 500 + (angle / 180.0f) * 2000; // 500us ~ 2500us // 计算对应的CCR值 (假设时钟频率为84MHz,预分频PSC=83,则计数器频率为1MHz,1计数=1us) uint32_t ccr_value = pulse_us; // 因为1计数=1us __HAL_TIM_SET_COMPARE(htim, Channel, ccr_value); } // 控制云台到指定位置 void Gimbal_MoveTo(float pan_angle, float tilt_angle) { Servo_SetAngle(&htim2, TIM_CHANNEL_1, pan_angle); // 水平舵机 Servo_SetAngle(&htim2, TIM_CHANNEL_2, tilt_angle); // 垂直舵机 HAL_Delay(300); // 等待舵机运动到位,时间根据舵机速度调整 }
2.3 电源系统设计
稳定的电源是系统稳定的基石。务必做好:
- 隔离与稳压:电机驱动电路与主控、传感器电路应使用不同的稳压模块(如LM2596、DCDC降压模块)供电,避免电机启停对数字电路造成干扰。
- 电容缓冲:在电机驱动电源输入端并联大容量电解电容(如1000uF),吸收瞬间大电流。
- 电压监控:实时监测电池电压,设置低压报警,防止电池过放。
3. 软件架构设计与核心算法实现
一个清晰的软件架构能极大提升开发效率和调试便利性。
3.1 系统软件架构
推荐采用上下位机协作的架构:
- 下位机(STM32):负责实时性要求高的任务。
- 电机PID控制
- 编码器读数
- 陀螺仪数据融合(获取车体姿态)
- 舵机PWM生成
- 与上位机通信
- 上位机(树莓派等):负责计算密集型任务。
- 图像采集与处理
- 视觉识别(目标、赛道)
- 决策状态机
- 路径规划
- 向下位机发送控制指令
通信协议:上下位机之间通常通过串口(UART)通信,定义简单高效的协议。例如:
// 协议帧格式:帧头(0xAA) + 命令字(1字节) + 数据长度(1字节) + 数据(N字节) + 校验和(1字节) + 帧尾(0x55) // 命令字示例: // 0x01: 上位机发送速度指令 (数据:左轮速度,右轮速度) // 0x02: 上位机发送舵机指令 (数据:舵机ID,角度值) // 0x11: 下位机上传传感器数据 (数据:编码器值,陀螺仪角度)3.2 核心算法:视觉识别与循迹
1. 赛道循迹(基础): 对于智慧医疗组,循迹可能不是最难的,但必须是最稳的。因为任务执行点往往在特定位置,停车不准一切白费。
- 图像处理流程:灰度化 -> 高斯滤波去噪 -> 二值化 -> 形态学操作(可选)。
- 巡线算法:推荐使用“扫线法”。从图像底部向上,逐行寻找赛道左右边线,计算中心线偏差。
# 文件路径:上位机脚本 /vision/lane_detection.py (Python + OpenCV示例) import cv2 import numpy as np def find_lane_center(binary_img): height, width = binary_img.shape center_line = [] for row in range(height-1, -1, -10): # 从下往上,每隔10行扫一次 row_pixels = binary_img[row, :] # 找到白色(赛道)区域的左右边界 white_indices = np.where(row_pixels == 255)[0] if len(white_indices) > 20: # 有效区域需有一定宽度 left_bound = white_indices[0] right_bound = white_indices[-1] lane_center = (left_bound + right_bound) // 2 center_line.append((lane_center, row)) # 计算与图像中心的横向偏差 deviation = lane_center - width // 2 # 可以将deviation发送给下位机用于转向控制 return center_line # 主循环中 ret, frame = cap.read() gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) blurred = cv2.GaussianBlur(gray, (5,5), 0) _, binary = cv2.threshold(blurred, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU) # 自适应阈值 center_points = find_lane_center(binary)
2. 目标识别(关键):
- 颜色/形状识别:用于识别简单的药品标签或任务点。
def find_color_object(frame, lower_bound, upper_bound): hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) mask = cv2.inRange(hsv, lower_bound, upper_bound) contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) for cnt in contours: area = cv2.contourArea(cnt) if area > 500: # 面积阈值过滤噪声 x, y, w, h = cv2.boundingRect(cnt) # 计算中心点,可以返回给决策系统 center_x = x + w//2 center_y = y + h//2 return (center_x, center_y, area) return None - 二维码/AprilTag识别:用于识别病患ID等精确信息。推荐使用成熟的库,如
pyzbar、apriltag。from pyzbar import pyzbar def decode_qr_code(image): barcodes = pyzbar.decode(image) for barcode in barcodes: barcode_data = barcode.data.decode(“utf-8”) barcode_type = barcode.type # 将识别到的数据(如“Patient_03”)送入决策系统 return barcode_data return None
3.3 决策与状态机设计
这是整车的“大脑”。设计一个清晰的状态机(State Machine)是管理复杂任务流程的最佳实践。
# 文件路径:上位机脚本 /decision/state_machine.py class CarStateMachine: def __init__(self): self.current_state = “LANE_FOLLOWING” self.task_list = [] # 从二维码识别到的任务队列,如 [('PICKUP', 'A'), ('DELIVER', '3')] self.current_target = None def update(self, vision_data, sensor_data): """根据输入更新状态""" if self.current_state == “LANE_FOLLOWING”: self._state_lane_following(vision_data) elif self.current_state == “APPROACHING_TASK”: self._state_approaching_task(vision_data) elif self.current_state == “EXECUTING_TASK”: self._state_executing_task() # ... 其他状态 def _state_lane_following(self, vision_data): # 正常巡线 if vision_data[‘qr_code’] is not None: # 识别到任务二维码,解析并加入任务队列 new_task = self._parse_task(vision_data[‘qr_code’]) self.task_list.append(new_task) # 如果这是第一个任务,切换到接近任务点状态 if len(self.task_list) == 1: self.current_target = self.task_list[0] self.current_state = “APPROACHING_TASK” # 发送巡线控制指令给下位机 def _state_approaching_task(self, vision_data): # 根据视觉定位,精确控制车辆行驶到任务点前 if self._is_target_reached(vision_data): self.current_state = “EXECUTING_TASK” self._send_stop_command() # 发送微调控制指令 def _state_executing_task(self): # 控制机械臂执行抓取或放置动作 self._execute_arm_action(self.current_target[‘action’], self.current_target[‘object’]) # 动作完成后,从队列中移除当前任务 self.task_list.pop(0) # 判断是否有下一个任务 if self.task_list: self.current_target = self.task_list[0] self.current_state = “APPROACHING_TASK” else: self.current_state = “LANE_FOLLOWING”4. 系统调试与性能优化实战
调试是智能车竞赛中最耗时、也最能体现工程能力的环节。
4.1 分模块调试流程
- 底盘单独调:不装任何任务机构,先让车能稳定跑完基础赛道。重点调电机PID参数(Kp, Ki, Kd)和转向伺服参数。记录最大稳定速度。
- 视觉单独调:固定车模,用上位机软件实时显示摄像头画面和处理结果。调整二值化阈值、颜色HSV范围、识别区域ROI,确保在不同光照下都能稳定识别。
- 机械臂单独调:手动发送角度指令,测试机械臂的运动范围、精度和重复性。优化抓取机构的机械设计。
- 通信联调:编写简单的测试脚本,让上下位机互相发送测试数据,确保协议解析正确,无丢包错包。
- 低速融合调试:以很低的速度,让车带着机械臂巡线,并在模拟任务点尝试触发动作。观察各模块协作是否正常。
- 全速优化:逐步提高车速,同时优化决策逻辑和动作时序。核心原则:在稳定性的基础上追求速度。
4.2 常见问题与排查清单
| 问题现象 | 可能原因 | 排查思路与解决方案 |
|---|---|---|
| 车模跑偏或摆动 | 1. 左右轮电机PID参数不一致 2. 轮胎摩擦力差异 3. 陀螺仪安装不水平或数据未校准 4. 摄像头安装歪斜 | 1. 分别测试左右轮空转,校准PID。 2. 清洁或更换轮胎,确保一致。 3. 上电静止时校准陀螺仪零偏。 4. 调整摄像头,使其中线与车体中轴线平行。 |
| 视觉识别不稳定(时好时坏) | 1. 环境光照变化 2. 摄像头抖动 3. 二值化阈值固定,不适应全场 4. 图像处理耗时过长,帧率低 | 1. 考虑补光灯,或使用自适应阈值算法。 2. 加固摄像头支架,使用防抖材料。 3. 改用动态阈值或HSV颜色空间过滤。 4. 优化代码,减少不必要的运算,降低图像分辨率。 |
| 机械臂抓取失败 | 1. 定位不准,车未停正 2. 机械臂重复精度差 3. 抓取机构设计有缺陷(太紧/太松) 4. 动作时序与车体晃动未配合 | 1. 优化最终停车阶段的视觉伺服控制。 2. 更换更好舵机,或加入位置反馈。 3. 重新设计末端执行器,如使用自适应夹爪、电磁铁等。 4. 停车后延迟一段时间,待车体稳定再执行抓取。 |
| 上下位机通信异常 | 1. 波特率不匹配 2. 协议解析错误 3. 缓冲区溢出 4. 线路干扰 | 1. 确认双方波特率、数据位、停止位、校验位完全一致。 2. 使用串口助手工具收发测试,逐字节核对。 3. 增加通信协议中的帧序号和应答机制。 4. 使用屏蔽线,电源隔离。 |
| 任务执行逻辑混乱 | 1. 状态机设计有漏洞,状态切换条件不严谨 2. 传感器数据更新慢于决策周期 3. 异常情况(如识别失败)未处理 | 1. 绘制详细的状态转移图,覆盖所有可能分支。 2. 在决策前判断数据是否新鲜(加时间戳)。 3. 为每个状态添加超时和错误处理,能回退到安全状态。 |
4.3 冲刺阶段的优化技巧
- 动态速度控制:直线加速,入弯提前减速,出弯线性加速。根据赛道曲率实时调整期望速度。
- 前瞻距离自适应:高速时使用更远的前瞻,提前预判;低速精细操作时使用近前瞻,提高精度。
- 任务并行处理:在驶向一个任务点的途中,提前处理下一个任务点的图像识别,减少停车等待时间。
- 代码与参数固化:比赛前,将所有可变的参数(如PID值、颜色阈值)固化到代码中,或存储在可靠的配置文件中。比赛现场只允许进行微调。
- 制定应急预案:准备几套备用的核心参数(如针对强光、弱光的视觉参数)。比赛时若环境突变,可快速切换。
5. 技术报告撰写与比赛现场要点
“国一”队伍不仅车跑得好,报告也要写得好,现场表现更要稳。
5.1 技术报告撰写核心
技术报告是评审专家了解你工作深度和完整性的关键。第二十一届竞赛对技术报告有明确要求,务必仔细阅读官方通知。
- 结构清晰:摘要、引言、方案总体设计、硬件设计、软件算法、调试优化、总结与展望、参考文献。
- 突出创新点:在方案设计、算法优化、机械结构上,你的独特思考是什么?哪怕是一个很小的参数自适应方法,只要有效,就是亮点。
- 数据支撑:多用图表说话。系统框图、电路图、算法流程图、调试数据曲线图(如PID响应曲线)、识别效果对比图。
- 细节详实:关键算法的公式、代码片段(重要部分)、参数表,都要给出。
- 格式规范:严格按照组委会要求的格式排版,包括字体、字号、页边距、图表标注等。
5.2 比赛现场流程与心态管理
- 检录与车模检查:提前准备好技术报告、车模检查视频(如需)、学生证等材料。车模尺寸、重量、传感器数量等必须符合规则。
- 场地适应性调试:官方练习时间极其宝贵。带上你的调试工具(笔记本、USB线、螺丝刀、备用零件)。快速完成以下步骤:
- 灯光适应:立即测试现场光线,调整摄像头曝光、增益或切换备用视觉参数。
- 赛道适应:试跑,感受赛道摩擦力和坡道,微调速度参数。
- 任务点验证:到每个任务点前,测试识别和机械臂动作是否可靠。
- 比赛轮次:
- 第一次发车:求稳!使用保守的参数,确保完赛拿到基础分。观察车模表现,记录问题。
- 后续发车:在稳的基础上,逐步提速,尝试更激进的策略。每次跑完,立即分析数据,针对性调整。
- 心态调整:比赛时出现问题是常态。关键是有预案、不慌乱。如果一次运行中途失败,迅速定位是硬件问题(如接头松动)还是软件问题(如某个状态卡死),并在下次发车前解决。
冲击“国一”的路上没有捷径,它是对团队技术广度、深度、工程实践能力和临场心态的综合考验。智慧医疗组别尤其强调系统的智能性和任务的完成度。从读懂赛题开始,扎实走好硬件选型、算法开发、系统集成、迭代调试的每一步,重视技术文档的梳理,最后在赛场上沉着应对。
希望这篇长文能为你和你的团队提供一个清晰的备赛框架。记住,每一个熬夜调试的夜晚,每一次解决问题的欣喜,都是通往领奖台的阶梯。祝你在第二十一届全国大学生智能汽车竞赛中,乘风破浪,美美拿下理想的奖项!如果在具体实现中遇到任何难题,欢迎在评论区交流讨论。