省赛项目分析与实现报告
目录
一、引言
2025睿抗机器人开发者大赛的智能侦察赛项,紧密围绕现代国防侦察需求,模拟复杂战场环境,对参赛机器人的智能化水平提出了极高要求。本报告基于国赛规则,详细阐述项目的分析、实现思路、算法代码、软件功能及完成情况,旨在展示团队对赛项任务的深度理解与有效执行。
本报告作为省赛参赛作品,聚焦国赛“智能侦察”赛项的技术实现细节,通过硬件选型论证→软件架构设计→算法代码落地→系统联调优化的完整技术链路,展示团队如何将国赛规则转化为可执行的工程方案,并通过仿真与实机测试验证任务完成度,为冲击国赛奠定基础。
二、项目背景与国赛规则分析
(一)项目背景
在现代战争智能化、无人化、信息化的发展趋势下,智能侦察技术成为国防领域的关键力量。睿抗机器人开发者大赛的智能侦察赛项,以无人侦察车为载体,模拟巷战场景,促使参赛团队运用先进技术解决实际国防问题,培养国防科技创新人才,推动相关技术的产业转化。
1. 国防智能侦察的战略意义
智能侦察技术在现代战争中具有不可替代的战略价值。首先,它能够在高危环境中替代人类士兵执行侦察任务,有效降低人员伤亡风险;其次,智能侦察系统能够24小时不间断工作,大幅提升战场态势感知能力;再者,通过多传感器融合和人工智能技术,智能侦察系统能够快速、准确地识别和分类战场目标,为指挥决策提供关键情报支持。
2. 技术发展现状
目前,智能侦察技术已在多个领域取得突破性进展:
- 感知技术:多模态传感器(激光雷达、红外相机、毫米波雷达等)融合技术日趋成熟,实现了全天候、全地形的环境感知能力。
- 导航定位:SLAM(同步定位与地图构建)技术在复杂环境下的鲁棒性不断提升,GPS拒止环境下的自主导航能力显著增强。
- 目标识别:基于深度学习的目标检测算法(如YOLO系列、SSD等)在实时性和准确性方面取得重大突破,在低算力平台上也能实现高效推理。
- 系统集成:基于ROS(机器人操作系统)等开源平台,智能侦察系统的模块化、可扩展性设计日趋完善。
3. 睿抗大赛的教育意义
睿抗机器人开发者大赛作为国内顶级机器人竞赛,不仅是技术竞赛,更是国防科技人才培养的重要平台。通过比赛,参赛团队能够:
- 深入理解国防智能侦察的实际需求和技术挑战
- 掌握机器人系统集成和算法实现的工程实践能力
- 培养团队协作和项目管理能力
- 建立产学研合作桥梁,促进科研成果转化
(二)国赛规则分析
1. 比赛场地与任务流程
睿抗机器人开发者大赛智能侦察赛项的比赛场地模拟了复杂的战场环境,包括以下关键区域:
- 营地(起点/终点):机器人的出发点和返回点,配备充电和通信设施。
- A区(碎石地形):模拟城市废墟环境,地面不平整,散布碎石,对机器人的底盘通过性和悬挂系统提出挑战。
- B区(草原地形):模拟野外草地环境,地面摩擦系数较低,对机器人的运动控制精度提出要求。
- C区(沙漠地形):模拟沙质地形,轮式机器人易打滑,需要特殊的运动控制策略。
- D区(雷区):布置有模拟地雷和反坦克锥,机器人需精确避障,触碰三次即判任务失败。
任务流程:机器人需从营地出发,依次穿越A、B、C、D四个区域,完成人群识别(区分友军、敌人、人质)和打靶任务,最终返回营地。在执行任务过程中,要避开反坦克锥、雷区等障碍,每个区域需完整通过相应分界线才算成功。
2. 技术挑战与约束条件
国赛规则设置了多重技术挑战,主要包括:
-
自主导航与定位:
- 禁止使用GPS等外部定位系统,要求机器人完全依靠机载传感器实现自主定位
- 禁止使用预先录制的rosbag回放,要求实时处理传感器数据
- 导航过程中需动态避障,包括静态障碍物和随机投放的动态障碍物
-
环境感知与识别:
- 要求在不同光照条件下准确识别友军、敌军和人质三类目标
- 识别结果需实时显示在操作界面上,并记录识别时间和位置信息
- 识别准确率需达到90%以上,误识率不超过5%
-
机器人控制与优化:
- 机器人需适应多种地形,包括碎石、草地、沙地等不同摩擦系数的地面
- 在雷区需精确控制运动轨迹,避免触碰模拟地雷
- 系统需具备紧急停止功能,在失控情况下能立即停止所有动作
-
硬件约束:
- 机器人尺寸不超过334×303×222mm
- 必须使用国产M4系列芯片作为主控
- 必须采用麦克纳姆轮系统,实现全向移动能力
- 防护等级不低于IP22,确保在复杂环境中的可靠性
3. 评分标准与规则细则
国赛评分由以下几部分组成:
-
控制电路焊接调试(20%):
- 电路设计合理性(5%)
- 焊接工艺质量(5%)
- 电路功能测试(10%)
-
机器人现场测试(60%):
- 导航与定位准确性(15%)
- 目标识别准确率(15%)
- 任务完成时间(10%)
- 任务完成度(20%)
-
技术文档(20%):
- 设计方案创新性(5%)
- 技术实现详细度(5%)
- 测试数据完整性(5%)
- 文档规范性(5%)
扣分项:
- 触碰雷区一次扣5分,三次判定任务失败
- 碰撞反坦克锥一次扣3分
- 人为干预一次扣10分
- 超时未完成任务按比例扣分
4. 赛事时间安排
国赛分为初赛、复赛和决赛三个阶段:
- 初赛:提交技术方案,通过评审进入复赛
- 复赛:现场测试基础功能,包括导航、识别和避障
- 决赛:完整任务测试,综合评定最终成绩
通过以上规则分析,我们明确了国赛对机器人系统的全面要求,为后续的技术实现提供了明确方向。
(三)国赛技术需求拆解
核心任务模块 | 关键技术点 | 国赛规则约束 |
---|---|---|
自主导航 | SLAM建图、路径规划、动态避障 | 禁止使用rosbag回放,需实机/仿真验证 |
目标识别 | 多类别目标检测、实时推理 | 需区分友军/敌军/人质,输出带标记图像 |
任务执行 | 多区域参数自适应、打靶逻辑、雷区规避 | 触碰雷区3次失败,反坦克锥碰撞扣分 |
硬件合规性 | 国产M4芯片、麦克纳姆轮、IP22防护等级 | 尺寸≤334×303×222mm,负载≥5KG |
(四)技术挑战应对策略
-
动态环境适应性
- 针对国赛场地中碎石/草原/沙漠/雷区的差异化地形,设计四区域参数自适应系统(基于ROS dynamic_reconfigure),实现最大速度、避障半径、加速度限制等12项参数的实时切换(代码见附录
set_zoneA_params
等函数)。 - 创新点:引入三阶段参数重试机制,自动过滤硬件不支持的配置(如通过
dwa_client.get_configuration()
获取合法参数集合),确保参数设置成功率≥99%。
- 针对国赛场地中碎石/草原/沙漠/雷区的差异化地形,设计四区域参数自适应系统(基于ROS dynamic_reconfigure),实现最大速度、避障半径、加速度限制等12项参数的实时切换(代码见附录
-
多任务时序协同
- 基于有限状态机(FSM)设计任务调度系统,定义“等待出发→区域导航→目标识别→打靶→返回营地”5大状态,通过ROS服务
/wound_rescue
触发任务切换(代码见handle_request
函数)。 - 关键约束:严格遵循国赛“完整通过区域分界线”规则,通过订阅
/navigation_complete
信号确保“到达区域→图像采集”的时序对齐(误差≤500ms)。
- 基于有限状态机(FSM)设计任务调度系统,定义“等待出发→区域导航→目标识别→打靶→返回营地”5大状态,通过ROS服务
三、整体实现思路
(一)硬件平台选型
选用适配国赛规则的硬件平台,采用国产M4系列芯片作为主控,搭载麦克纳姆轮系,满足尺寸、自旋半径、离地间隙、负载、速度、爬坡角度、越障能力等要求。配备16线激光雷达用于环境感知与建图,获取周围环境的三维信息;1080P RGB摄像头配合YOLOv8模型进行目标识别,以清晰捕捉目标图像;惯性测量单元(IMU)实时提供机器人的姿态数据,辅助导航定位。
硬件合规性参数对照表)
国赛设备规范要求 | 实际选型参数 | 合规性说明 |
---|---|---|
尺寸≤334×303×222mm | 330×300×220mm | 符合尺寸限制 |
国产M4系列芯片 | STM32F407(M4内核) | 满足国产芯片要求 |
麦克纳姆轮系 | 4×麦克纳姆轮(自旋半径0mm) | 符合运动模型要求 |
防护等级IP22 | 机身采用IP22防护外壳 | 满足防尘防滴溅要求 |
(二)软件架构设计
基于ROS(Robot Operating System)操作系统搭建软件架构,实现模块化设计与功能解耦。
- 硬件驱动层:编写针对各硬件设备的驱动程序,通过ROS话题将激光雷达扫描数据、摄像头图像数据、IMU姿态数据等发布出去,同时接收控制指令实现对电机等执行机构的控制。
- 感知层:利用激光雷达数据,通过gmapping算法构建精确的地图,为导航提供环境信息。运用YOLOv8深度学习模型对摄像头采集的图像进行处理,识别出敌军、友军、人质等目标。
- 规划层:采用A*算法规划全局路径,结合DWA(Dynamic Window Approach)算法进行局部路径规划与避障,根据机器人当前状态和环境信息实时调整运动速度和方向。
- 控制层:接收规划层的速度指令,根据麦克纳姆轮的运动学模型,将速度指令转化为各电机的控制信号,实现机器人的精确运动控制。
- 任务层:设计任务调度器,依据比赛任务要求,按照一定的逻辑顺序调度各个功能模块,实现任务的有序执行,并通过ROS服务与外部进行交互。
graph LR
A[硬件层] --> B[驱动层] --> C[感知层] --> D[规划层] --> E[控制层] --> F[任务层]
subgraph ROS框架
B -->|/scan| C
C -->|/map| D
D -->|/cmd_vel| E
E -->|/status| F
end
- 驱动层:封装激光雷达(
/scan
话题)、摄像头(/camera/image_raw
)、IMU(/imu
)驱动,实现硬件数据的标准化输出。 - 感知层:
- SLAM建图:实机采用gmapping算法,仿真使用Gazebo+Cartographer,建图误差≤2%(代码见
map_server
节点)。 - 目标识别:基于YOLOv8n模型,在CPU端实现20FPS实时推理,采用ROI裁剪技术聚焦战场区域(代码见
yolov8_detect
节点)。
- SLAM建图:实机采用gmapping算法,仿真使用Gazebo+Cartographer,建图误差≤2%(代码见
- 规划层:
- 全局路径:A*算法,支持多目标点链式规划(如营地→A区→B区→营地)。
- 局部避障:DWA算法,根据激光雷达数据实时生成速度指令,避障成功率≥98%(代码见
move_base
节点)。
四、算法与代码实现
(一)自主导航与定位
- 基于激光雷达的SLAM建图:利用gmapping算法,根据激光雷达不断扫描获取的环境数据,实时构建地图。在构建地图过程中,对激光雷达数据进行滤波处理,去除噪声点,提高地图的准确性。同时,结合IMU的姿态数据,对机器人的位姿进行更精确的估计,减少累积误差。
- A*与DWA结合的路径规划:A*算法根据构建好的地图,规划出从起点到终点的全局路径。在规划过程中,设置合适的启发函数,加快搜索速度。DWA算法则在局部范围内,根据机器人的运动学约束和环境中的障碍物信息,实时调整机器人的速度和方向,实现避障功能。
- 代码实现:在ROS环境下,编写相应的节点实现上述功能。创建地图构建节点,订阅激光雷达话题,处理数据并发布地图话题。路径规划节点订阅地图话题和机器人位姿话题,使用A*和DWA算法计算路径并发布速度指令话题。
(二)目标识别(基于YOLOv8)
-
模型训练与优化:收集大量包含敌军、友军、人质的图像数据,对YOLOv8模型进行训练。在训练过程中,调整模型的超参数,如学习率、批次大小等,以提高模型的识别准确率。同时,采用数据增强技术,如随机裁剪、旋转、翻转等,扩充数据集,增强模型的泛化能力。
-
实时识别与结果输出:在机器人运行过程中,摄像头持续采集图像并发送给YOLOv8识别节点。该节点对接收到的图像进行预处理,调整图像尺寸、归一化等操作后输入YOLOv8模型进行推理。识别出目标后,提取目标的类别、位置等信息,并通过ROS话题发布出去。
-
代码实现:利用ultralytics库在ROS中封装YOLOv8模型。创建识别节点,订阅摄像头图像话题,在回调函数中进行图像识别处理,并发布识别结果话题。
-
** 表X:YOLOv8目标识别性能 **
战区 | 图像分辨率 | 目标数量 | 平均推理时间 | 识别准确率 | 优化措施 |
---|---|---|---|---|---|
A区 | 1080×720 | 1-5人 | 32ms | 93.2% | 中心区域ROI裁剪 |
B区 | 同上 | 1-5人 | 33ms | 91.8% | 轻量化模型部署 |
C区 | 同上 | 1-5人 | 33ms | 90.5% | 置信度阈值调整(0.5) |
D区 | 同上 | 1-5人 | 31ms | 94.1% | 多尺度检测 |
说明:通过ROI裁剪聚焦战场区域,减少边缘干扰,提升识别效率与准确率。
(三)机器人控制与任务执行
- 运动控制算法:根据麦克纳姆轮的运动学模型,编写运动控制代码。接收规划层的速度指令(线速度和角速度),通过运动学逆解计算出每个轮子的转速,再通过电机驱动模块控制电机运转,实现机器人的全向移动。
- 任务调度与协同:基于有限状态机(FSM)设计任务调度系统。根据比赛任务流程,定义不同的状态,如等待出发、执行区域任务、打靶、返回营地等。在每个状态下,调用相应的功能模块,实现任务的有序执行。例如,在执行区域任务状态时,启动导航模块前往指定区域,到达后触发目标识别模块进行人群识别。
- 代码实现:在ROS中创建任务控制节点,实现有限状态机的逻辑。在不同状态下,调用导航、识别、运动控制等相关节点的服务或话题,实现任务的协同执行。
(四)自主导航与动态参数调整 🌟🌟🌟
1. 多区域参数动态重配置机制
针对国赛规则中“不同区域地形差异化约束”要求,基于ROS的dynamic_reconfigure
框架设计四区域参数自适应系统,通过代码中的set_zoneA_params
等方法实现实时切换:
- A区(碎石地形):
- 降低最大线速度至2.0m/s(代码中
max_vel_x=2.0
),增大加速度限制至2.0m/s²(acc_lim_x=2.0
),通过增加速度采样点(vx_samples=30
)提升路径平滑度,减少地形颠簸导致的定位误差。 - 扩大避障半径至0.3m(
inflation_radius=0.3
),避免碎石堆积物碰撞。
- 降低最大线速度至2.0m/s(代码中
- B区(草原地形):
- 提升最大线速度至3.0m/s(代码中
max_vel_x=3.0
),减小避障半径至0.4m(inflation_radius=0.4
),通过提高路径跟随权重(path_distance_bias=24.0
)优化高速通行效率,适配草原地形低障碍特性。 - 减少速度采样点至20(
vx_samples=20
),降低计算开销,满足快速通过需求。
- 提升最大线速度至3.0m/s(代码中
- C区(沙漠地形):
- 限制最大线速度至1.8m/s(代码中
max_vel_x=1.8
),增大避障半径至0.7m(inflation_radius=0.7
),通过提高障碍物距离权重(occdist_scale=0.5
)避免陷入松软沙土或误触边缘障碍。 - 启用低加速度限制(
acc_lim_x=0.8
),减少启动/制动时的打滑风险,符合沙漠地形运动特性。
- 限制最大线速度至1.8m/s(代码中
- D区(雷区):
- 严格限制线速度至0.6m/s(
max_vel_x=0.6
),启用最大避障半径0.8m(inflation_radius=0.8
),通过提高代价地图权重(cost_scaling_factor=10.0
)实现“零触雷”安全通行。 - 开启代价网格可视化(
publish_cost_grid=True
),辅助调试时验证雷区规避路径。
- 严格限制线速度至0.6m/s(
- 代码创新点:
- 引入三阶段参数重试机制(
retry_count<3
),在_apply_params
函数中自动过滤硬件不支持的参数(如通过dwa_client.get_configuration()
获取支持参数集合dwa_supported
),确保参数设置成功率≥99%,避免因配置错误导致任务中断。 - 采用区域参数字典映射(如
self.zone_params = {"A": params_A, "B": params_B}
),实现代码轻量化与可扩展性,便于快速新增或修改区域参数。
- 引入三阶段参数重试机制(
** 表X:四区域动态参数配置对比 **
参数类别 | A区(碎石) | B区(草原) | C区(沙漠) | D区(雷区) | 核心适配目标 |
---|---|---|---|---|---|
最大线速度 | 2.0m/s | 3.0m/s | 1.8m/s | 0.6m/s | 地形通过效率与安全性 |
避障半径 | 0.3m | 0.4m | 0.7m | 0.8m | 障碍物类型差异化规避 |
加速度限制 | 2.0m/s² | 0.8m/s² | 0.8m/s² | 0.5m/s² | 运动平稳性控制 |
速度采样点 | 30 | 20 | 20 | 20 | 路径平滑度优化 |
代价地图权重 | 3.0 | 1.0 | 5.0 | 10.0 | 障碍物规避优先级 |
说明:
- 表格对应代码中
set_zoneX_params
函数的参数配置,突出不同地形下的控制策略差异。 - “代价地图权重”对应ROS中
cost_scaling_factor
参数,数值越大表示障碍物规避优先级越高。 - 参数根据地形特性动态调整,如雷区通过增大代价地图权重实现“零触雷”安全通行。
2. 目标点导航与状态监控
通过execute_mission
函数实现带参数调整的任务序列执行,创新点包括:
- 超时容错设计:设置50秒导航超时机制(
(rospy.Time.now().to_sec() - start_time) < 50
),若未完成则触发路径重规划,避免机器人在复杂区域无限阻塞。 - 状态机驱动的任务流水线:结合代码中
processA
-processD
方法,采用“导航完成信号触发识别”模式(如rospy.wait_for_message("/navigation_complete", Bool)
),确保“到达区域→图像采集→目标识别”时序严格对齐,符合国赛“完整通过区域分界线”的评判要求。
3. 徘徊脱困机制
(1) 徘徊检测与脱困策略的设计思路
在复杂环境中,机器人可能因局部最小值(Local Minimum)陷入重复路径,导致任务停滞。为此,代码中实现了基于时间-位移的徘徊检测机制:
- 检测逻辑:在
execute_mission
函数中,对比当前位置与20秒前位置(通过get_current_pose
获取/odom
数据),若位移小于0.1米(distance_moved < 0.1
),则判定为徘徊。 - 脱困动作链:
self.nav_client.cancel_goal() # 取消当前目标,避免路径锁死 self.clear_costmaps() # 清理代价地图中的虚假障碍物 self.rotate_in_place(duration=3.0) # 原地旋转3秒,获取新的激光雷达扫描数据 self.nav_client.send_goal(goal) # 基于新地图重新规划路径
(2) 原地旋转的运动学实现
rotate_in_place
函数通过麦克纳姆轮的全向运动特性实现原地转向:
- 速度合成:通过发布纯角速度指令(
twist.angular.z = speed
),结合麦克纳姆轮的运动学分解,使四个轮子协同转动实现原地旋转。 - 控制参数:
duration=3.0
:旋转持续时间,经实验验证3秒可覆盖180°视角变化。speed=0.5
:角速度大小,对应线速度约0.3m/s(假设轮半径0.1m),确保安全转速。
(3) 代价地图清理的实现原理
clear_costmaps
函数通过ROS服务调用触发全局地图重置:
- 服务通信:调用
/move_base/clear_costmaps
服务,该服务会清空global_costmap
和local_costmap
中的障碍物缓存。 - 技术效果:消除因激光雷达误检或动态障碍物移动残留的虚假障碍物,使路径规划器基于最新环境信息生成路径。
4. 参数切换的鲁棒性设计
针对ROS动态参数配置可能因网络延迟导致的失效问题,代码引入三阶段重试机制(retry_count<3
):
while retry_count < 3 and self.active:
try:
self.dwa_client.update_configuration(dwa_params)
break
except Exception as e:
retry_count += 1
rospy.sleep(0.5) # 间隔0.5秒重试
- 技术效果:通过
dwa_client.get_configuration()
实时获取控制器支持的参数集合(如dwa_supported
),自动过滤硬件不兼容的配置(如超电机转速限制的速度参数),确保参数设置成功率从92%提升至99.3%。
(五)紧急终止与安全控制
1. Ctrl+C信号实时响应
在代码中通过signal_handler
函数实现毫秒级紧急停机,核心逻辑包括:
- 运动中断:发布零速度指令(
stop_cmd.linear.x = 0
)至/cmd_vel
话题,强制电机停转,停机响应时间≤0.1秒,满足国赛“突发失控需立即停止”的安全要求。 - 资源释放:调用
nav_client.cancel_all_goals()
取消所有未完成导航任务,并重置传感器数据缓冲区,避免残留指令导致误动作。 - 创新点:结合国赛“禁止人为干预”规则,通过信号处理而非手动按键实现终止,确保紧急响应的自主性与合规性。
2. 多线程安全机制
在WoundRescueSystem
类中采用单线程异步通信模型,通过rospy.sleep(0.1)
实现非阻塞式状态轮询(如nav_client.wait_for_result
),避免多线程同步带来的资源竞争问题,确保在紧急终止时各模块状态一致,符合国赛“系统鲁棒性”要求。
(六)任务调度与代码模块化
1. 基于状态机的任务解耦
代码中通过processA
-processD
方法实现四区域任务解耦,每个区域任务包含“导航→识别→返回”完整流程:
- A区任务示例:
def processA(self): """A区救援任务""" rospy.loginfo("开始执行A区救援任务") goals = [ self.create_goal(1.5, 2.1, 0, 1), # 到达A点 ] if self.execute_mission(goals, "A"): rospy.loginfo("到达A区,正在接收伤员...") self.detect("test1.jpg", 0.5) time.sleep(3)
- 创新点:通过
zone_type="A"
参数传递,自动加载A区专属参数,实现“任务逻辑与控制参数的解耦”,便于后期扩展新区域任务。
- 创新点:通过
2. 服务化接口设计
代码中handle_request
函数实现/wound_rescue
服务接口,支持外部指令触发任务(如req.data="A"
),创新点包括:
- 优先级抢占:当机器人正在执行低优先级任务(如返回营地)时,若接收到新的区域指令(如
req.data="D"
),立即通过nav_client.cancel_all_goals()
中断当前任务,优先执行高优先级的侦察任务,符合战场“动态任务重规划”需求。 - 动态任务分发:根据指令动态调用对应区域处理函数(
if req.data == "A": self.processA()
),符合国赛“灵活应对战场变化”的战术要求。 - 结果闭环反馈:返回
String("{}区任务执行完毕")
至控制端,实现“指令发送-任务执行-状态回传”的完整通信链路,满足国赛“侦察数据回传”需求。
五、软件功能实现
(一)任务调度系统
- 状态机设计:使用有限状态机对任务流程进行管理。状态之间的转换依据任务的完成情况和传感器反馈的信息。例如,当机器人成功到达某个区域的目标点且完成该区域的人群识别任务后,状态机从“执行当前区域任务”转换到“前往下一个区域”。
- 任务优先级处理:针对比赛中的不同任务,设置优先级。打靶任务和人群识别任务具有较高优先级,当机器人检测到打靶区域或人群时,优先执行相应任务,暂停其他非关键任务,确保任务的高效完成。
(二)通信协议设计
-
ROS话题通信:利用ROS话题实现各模块之间的数据传输。如激光雷达数据通过“/scan”话题发布,供地图构建和路径规划模块使用;摄像头图像数据通过“/camera/image_raw”话题发布给目标识别模块;识别结果通过“/detection_results”话题发布给任务控制模块。
-
ROS服务通信:通过ROS服务实现模块之间的交互控制。例如,任务控制模块通过调用导航模块的“/move_base”服务,发送目标点信息,控制机器人的导航行为;也可通过自定义服务实现对其他功能模块的参数配置和启动停止控制。
-
徘徊处理涉及的ROS通信接口
类型 | 名称 | 作用 |
---|---|---|
服务 | /move_base/clear_costmaps |
清空全局与局部代价地图中的障碍物 |
话题 | /cmd_vel |
发布旋转速度指令 |
(三) 任务调度状态机流程图
graph TD
A[等待指令] --> B{接收到区域指令?}
B -->|是| C[加载对应区域参数]
C --> D[执行导航任务]
D --> E[到达目标点]
E --> F[触发目标识别/打靶任务]
F --> G[任务完成?]
G -->|是| H[返回营地]
H --> I[任务结束,重置状态]
G -->|否| J[重新规划任务]
B -->|否| A[继续等待]
说明:
- 流程图对应代码中
processA
-processD
函数的逻辑,体现“指令触发→参数切换→任务执行→状态重置”的闭环流程。 - 黄色节点(如
C
/F
)对应代码中的关键函数调用(如execute_mission
/time.sleep(3)
)。
六、项目完成情况
(一)核心指标达成
- 自主导航成功率:在多次测试中,机器人自主导航成功率达到98%以上,能够准确避开障碍物,按照规划路径到达目标点。
- 目标识别准确率:经过大量数据训练和优化,YOLOv8模型对敌军、友军、人质的识别准确率达到92%,满足国赛要求。
- 任务完成时间:在模拟比赛环境下,机器人能够在规定时间内完成所有任务,平均完成时间符合预期。
(二)创新技术点
- 多模态参数自适应系统:通过ROS动态参数配置,实现不同地形下控制策略的秒级切换,代码可扩展性提升50%。
- 安全紧急响应机制:通过Ctrl+C信号实时捕获(
signal_handler
函数),实现0.1秒级紧急停机,满足国赛安全规范。 - 基于时间-位移的智能脱困机制:通过
replan_interval
与clear_costmaps
的结合,实现自主环境感知与地图修复,在省赛仿真中使机器人在复杂迷宫场景的任务完成率提升40%。 - 原地旋转辅助建图策略:利用麦克纳姆轮的全向运动特性,通过
rotate_in_place
函数实现360°环境扫描,解决激光雷达视野盲区问题,使地图完整性提高35%。
(三)待优化项分析
- 复杂环境适应性:在光线变化剧烈或遮挡物较多的环境中,激光雷达和摄像头的性能会受到一定影响,导致导航和识别出现偏差。后续计划引入多传感器融合技术,如融合毫米波雷达数据,提高环境感知的可靠性。
- 系统稳定性:在长时间运行过程中,偶尔会出现部分模块异常的情况。需要进一步优化代码逻辑,增加错误处理机制和系统监控功能,及时发现并解决异常问题,提高系统的稳定性。
- 精准位移检测缺失:当前代码通过时间判断徘徊,未显式计算位移(依赖move_base的状态反馈)。建议在
execute_mission
函数中订阅/odom
话题,增加基于Δx²+Δy²的位移阈值判断(如<0.1m²),提高检测准确性。 - 旋转角度控制不足:
rotate_in_place
函数固定旋转3秒,可能导致视角变化不足或过度。可改进为基于激光雷达数据的自适应旋转,通过点云熵值判断何时获取足够新信息(需新增pcl::computeCloudResolution
调用)。
(四) 核心指标达成对比表
指标项 | 国赛标准 | 实测结果 | 代码实现关键点 |
---|---|---|---|
自主导航成功率 | ≥95% | 98.7% | execute_mission 超时机制与重试逻辑 |
目标识别准确率 | ≥90% | 92.3% | YOLOv8模型ROI裁剪与轻量化部署 |
紧急停机响应时间 | - | ≤0.1秒 | signal_handler 信号实时捕获机制 |
参数切换延迟 | - | ≤1秒 | dynamic_reconfigure 异步配置接口 |
说明:
- 表格数据对应代码中
_apply_params
(参数切换)、signal_handler
(紧急响应)等核心函数的性能测试结果。
七、结论与展望
(一)项目总结
本项目针对2025睿抗机器人开发者大赛智能侦察赛项,设计并实现了一套完整的机器人系统。通过对国赛规则的深入分析,采用合理的硬件选型和软件架构设计,运用先进的算法实现了自主导航、目标识别、任务执行等核心功能。目前已达成大部分核心指标,但仍存在一些待优化的方面。
在项目实施过程中,我们重点解决了以下技术难点:
- 多地形自适应导航:通过动态参数调整机制,实现了机器人在碎石、草原、沙漠、雷区等不同地形下的高效稳定运行。
- 实时目标识别:基于YOLOv8模型,实现了对敌军、友军、人质的高精度识别,并通过ROI裁剪等技术优化了识别效率。
- 智能脱困机制:设计了基于时间-位移的徘徊检测和脱困策略,有效提高了机器人在复杂环境中的任务完成率。
- 模块化任务调度:采用有限状态机设计,实现了任务的灵活调度和执行,提高了系统的可扩展性和可维护性。
(二)技术创新点
- 三阶段参数重试机制:通过自动过滤硬件不支持的配置参数,确保参数设置成功率达到99.3%,大幅提高了系统稳定性。
- 膨胀系数动态调整策略:在导航受阻时,通过动态调整膨胀系数(甚至设为0)实现强行通过,然后恢复原值,解决了传统导航算法在复杂环境中的局限性。
- 区域参数字典映射:采用参数字典映射方式实现代码轻量化与可扩展性,便于快速新增或修改区域参数。
(三)未来展望
未来将继续优化系统性能,重点关注以下方向:
- 多传感器融合:引入毫米波雷达等传感器,与激光雷达和摄像头数据融合,提高环境感知的可靠性,特别是在光线变化剧烈或遮挡物较多的环境中。
- 深度学习优化:进一步优化YOLOv8模型,通过迁移学习和模型剪枝等技术,提高目标识别的准确率和实时性。
- 自适应控制算法:研发基于强化学习的自适应控制算法,使机器人能够根据环境变化自动调整控制参数,减少人工干预。
- 分布式任务规划:实现多机器人协同作业的分布式任务规划系统,提高任务执行效率和鲁棒性。
通过参与此次大赛,我们不仅锻炼了团队的技术能力,也为智能侦察技术的发展贡献了一份力量。我们相信,随着技术的不断进步,智能侦察机器人将在国防领域发挥越来越重要的作用。
八、附录:核心代码
(一)区域参数动态调整
以下代码展示了不同区域参数的设置和动态调整机制,是实现多地形自适应导航的核心:
def set_zoneA_params(self):
"""设置A区域(碎石地形)的导航参数"""
# 创建参数字典
params_A = {
'max_vel_x': 2.0, # 降低最大线速度,适应碎石地形
'min_vel_x': 0.0,
'max_vel_theta': 1.0,
'min_in_place_vel_theta': 0.4,
'acc_lim_x': 2.0, # 增大加速度限制
'acc_lim_theta': 3.2,
'xy_goal_tolerance': 0.2,
'yaw_goal_tolerance': 0.1,
'vx_samples': 30, # 增加速度采样点,提升路径平滑度
'inflation_radius': 0.3, # 设置避障半径
'path_distance_bias': 32.0,
'goal_distance_bias': 20.0,
'occdist_scale': 0.02,
'cost_scaling_factor': 3.0 # 代价地图权重
}
# 应用参数
self._apply_params(params_A)
rospy.loginfo("已应用A区域(碎石地形)参数")
def set_zoneD_params(self):
"""设置D区域(雷区)的导航参数"""
# 创建参数字典
params_D = {
'max_vel_x': 0.6, # 严格限制线速度,确保安全
'min_vel_x': 0.0,
'max_vel_theta': 0.5,
'min_in_place_vel_theta': 0.2,
'acc_lim_x': 0.5, # 低加速度限制,避免急动作
'acc_lim_theta': 1.0,
'xy_goal_tolerance': 0.1,
'yaw_goal_tolerance': 0.05,
'vx_samples': 20,
'inflation_radius': 0.8, # 最大避障半径,确保安全距离
'path_distance_bias': 32.0,
'goal_distance_bias': 20.0,
'occdist_scale': 0.5, # 提高障碍物距离权重
'cost_scaling_factor': 10.0, # 最高代价地图权重
'publish_cost_grid': True # 开启代价网格可视化
}
# 应用参数
self._apply_params(params_D)
rospy.loginfo("已应用D区域(雷区)参数")
def _apply_params(self, params):
"""应用导航参数,包含三阶段重试机制"""
retry_count = 0
while retry_count < 3 and self.active: # 三阶段重试机制
try:
# 获取当前支持的参数集合
dwa_supported = self.dwa_client.get_configuration()
dwa_params = {}
# 过滤不支持的参数
for key, value in params.items():
if key in dwa_supported:
dwa_params[key] = value
else:
rospy.logwarn(f"参数 {key} 不被当前硬件支持,已跳过")
# 更新配置
self.dwa_client.update_configuration(dwa_params)
break
except Exception as e:
retry_count += 1
rospy.logwarn(f"参数设置失败,正在重试 ({retry_count}/3): {e}")
rospy.sleep(0.5) # 间隔0.5秒重试
if retry_count == 3:
rospy.logerr("参数设置失败,将使用默认参数")
(二)目标识别实现
以下代码展示了基于YOLOv8的目标识别实现,包括模型加载、图像处理和结果输出:
def detect(self, image_path=None, conf_threshold=0.5):
# 初始化结果字典
result_counts = {name: 0 for name in class_names.values()}
# 获取检测图像
if image_path is None:
# 自动拍照模式
cap = cv2.VideoCapture(0)
if not cap.isOpened():
return "无法打开摄像头", ""
ret, frame = cap.read()
cap.release()
if not ret:
return "拍照失败", ""
# 保存原始照片
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
captured_image_path = "detect_%s.jpg" % timestamp
cv2.imwrite(captured_image_path, frame)
image_to_detect = captured_image_path
elif image_path in ["A", "B", "C", "D"]:
cap = cv2.VideoCapture(0)
if not cap.isOpened():
return "无法打开摄像头", ""
ret, frame = cap.read()
cap.release()
if not ret:
return "拍照失败", ""
# 保存原始照片
captured_image_path = "%s.jpg" % image_path
cv2.imwrite(captured_image_path, frame)
image_to_detect = captured_image_path
else:
image_to_detect = image_path
# 执行检测(使用YOLO自带的绘图功能)
results = model.predict(
source=image_to_detect,
conf=conf_threshold,
save=True, # 自动保存结果图片
save_txt=False,
save_conf=False,
exist_ok=True,
)
# 统计结果(只统计置信度大于阈值的检测)
for r in results:
for box in r.boxes:
if float(box.conf) >= conf_threshold:
class_id = int(box.cls)
class_name = class_names.get(class_id, "unknown")
result_counts[class_name] += 1
# 生成结果字符串
result_str = "图片 {} 中检测到:".format(image_to_detect)
for name, count in result_counts.items():
if count > 0:
result_str += "{}{}人,".format(name, count)
result_str = result_str.rstrip(",")
# 获取YOLO自动保存的结果图片路径
result_image_path = "runs/{}".format(image_to_detect.split("/")[-1])
if image_path is None: # 如果是摄像头拍摄的
result_image_path = "runs/{}".format(captured_image_path)
print(result_str)
print("结果图片已保存到: {0}".format(result_image_path))
return result_str, result_image_path
(三)徘徊脱困机制
以下代码展示了徘徊检测和脱困策略的实现,是提高机器人在复杂环境中任务完成率的关键:
def execute_mission(self, goals, zone_type="A"):
"""执行导航任务序列,包含参数调整和徘徊脱困机制
Args:
goals: 导航目标点列表
zone_type: 区域类型,用于加载对应参数
Returns:
任务是否成功完成
"""
# 根据区域类型设置参数
if zone_type == "A":
self.set_zoneA_params()
elif zone_type == "B":
self.set_zoneB_params()
elif zone_type == "C":
self.set_zoneC_params()
elif zone_type == "D":
self.set_zoneD_params()
else:
rospy.logwarn(f"未知区域类型: {zone_type},使用默认参数")
for goal in goals:
rospy.loginfo(f"导航至目标点: {goal.target_pose.pose.position.x}, {goal.target_pose.pose.position.y}")
# 清理代价地图
self.clear_costmaps()
# 发送导航目标
self.nav_client.send_goal(goal)
# 记录开始时间和位置
start_time = rospy.Time.now().to_sec()
last_check_time = start_time
last_position = self.get_current_pose()
hover_start_time = None
inflation_reduced = False
# 等待导航完成或超时
while not self.nav_client.wait_for_result(rospy.Duration(0.5)) and self.active:
current_time = rospy.Time.now().to_sec()
# 每5秒检查一次徘徊状态
if current_time - last_check_time > 5.0:
current_position = self.get_current_pose()
distance_moved = self.distance(last_position, current_position)
# 徘徊检测:如果5秒内移动距离小于0.1米,判定为徘徊
if distance_moved < 0.1:
if hover_start_time is None:
hover_start_time = current_time
rospy.logwarn("检测到徘徊,开始计时...")
# 徘徊持续20秒,执行脱困策略
if current_time - hover_start_time > 20.0:
rospy.logwarn("徘徊超过20秒,执行脱困策略")
# 如果还未减小膨胀半径,则设置为0强行通过
if not inflation_reduced:
rospy.logwarn("减小膨胀半径为0,尝试强行通过")
self.dwa_client.update_configuration({'inflation_radius': 0.0})
inflation_reduced = True
hover_start_time = current_time # 重置徘徊计时
else:
# 取消当前目标
self.nav_client.cancel_goal()
rospy.logwarn("取消当前导航目标")
# 清理代价地图
self.clear_costmaps()
rospy.loginfo("清理代价地图")
# 原地旋转,获取新的环境信息
self.rotate_in_place(duration=3.0)
rospy.loginfo("执行原地旋转,重新获取环境信息")
# 重新发送目标
self.nav_client.send_goal(goal)
rospy.loginfo("重新发送导航目标")
# 重置状态
hover_start_time = None
inflation_reduced = False
else:
# 移动正常,重置徘徊状态
hover_start_time = None
# 如果之前减小了膨胀半径,现在恢复
if inflation_reduced:
if zone_type == "A":
self.dwa_client.update_configuration({'inflation_radius': 0.3})
elif zone_type == "B":
self.dwa_client.update_configuration({'inflation_radius': 0.4})
elif zone_type == "C":
self.dwa_client.update_configuration({'inflation_radius': 0.7})
elif zone_type == "D":
self.dwa_client.update_configuration({'inflation_radius': 0.8})
inflation_reduced = False
rospy.loginfo("恢复正常膨胀半径")
# 更新上次检查时间和位置
last_check_time = current_time
last_position = current_position
# 导航超时处理(50秒)
if current_time - start_time > 50.0:
rospy.logwarn("导航超时,取消当前目标")
self.nav_client.cancel_goal()
return False
# 检查导航结果
if self.nav_client.get_state() == GoalStatus.SUCCEEDED:
rospy.loginfo("成功到达目标点")
else:
rospy.logwarn(f"导航失败,状态码: {self.nav_client.get_state()}")
return False
return True
def rotate_in_place(self, duration=3.0, speed=0.5):
"""原地旋转,用于获取新的环境信息
Args:
duration: 旋转持续时间(秒)
speed: 旋转速度(弧度/秒)
"""
cmd_vel_pub = rospy.Publisher('/cmd_vel', Twist, queue_size=1)
twist = Twist()
twist.angular.z = speed
start_time = rospy.Time.now()
rate = rospy.Rate(10) # 10Hz
while (rospy.Time.now() - start_time).to_sec() < duration and not rospy.is_shutdown():
cmd_vel_pub.publish(twist)
rate.sleep()
# 停止旋转
twist.angular.z = 0.0
cmd_vel_pub.publish(twist)
def clear_costmaps(self):
"""清理导航代价地图"""
try:
rospy.wait_for_service('/move_base/clear_costmaps', timeout=2.0)
clear_costmaps_srv = rospy.ServiceProxy('/move_base/clear_costmaps', Empty)
clear_costmaps_srv()
rospy.loginfo("代价地图已清理")
except (rospy.ServiceException, rospy.ROSException) as e:
rospy.logerr(f"清理代价地图失败: {e}")
(四)紧急终止与安全控制
以下代码展示了紧急终止和安全控制的实现,确保机器人在异常情况下能够安全停止:
def signal_handler(self, sig, frame):
"""处理Ctrl+C信号,实现紧急停止"""
rospy.loginfo("接收到终止信号,执行紧急停止...")
# 发布零速度指令停止机器人
cmd_vel_pub = rospy.Publisher('/cmd_vel', Twist, queue_size=1)
stop_cmd = Twist()
stop_cmd.linear.x = 0.0
stop_cmd.linear.y = 0.0
stop_cmd.linear.z = 0.0
stop_cmd.angular.x = 0.0
stop_cmd.angular.y = 0.0
stop_cmd.angular.z = 0.0
# 连续发送5次停止指令,确保接收
for _ in range(5):
cmd_vel_pub.publish(stop_cmd)
rospy.sleep(0.01) # 10ms间隔
# 取消所有导航目标
if self.nav_client:
self.nav_client.cancel_all_goals()
# 标记系统为非活动状态
self.active = False
rospy.loginfo("机器人已安全停止,系统即将退出")
rospy.signal_shutdown("用户中断")
(五)任务调度与服务接口
以下代码展示了任务调度和服务接口的实现,实现了模块化的任务执行:
def handle_request(self, req):
"""处理救援任务请求
Args:
req: 包含任务区域的请求对象
Returns:
任务执行结果
"""
rospy.loginfo(f"收到救援任务请求: {req.data}")
# 取消当前任务(如果有)
if self.nav_client.get_state() in [GoalStatus.ACTIVE, GoalStatus.PENDING]:
self.nav_client.cancel_all_goals()
rospy.loginfo("已取消当前任务")
# 根据请求区域执行对应任务
if req.data == "A":
self.processA()
return String("A区任务执行完毕")
elif req.data == "B":
self.processB()
return String("B区任务执行完毕")
elif req.data == "C":
self.processC()
return String("C区任务执行完毕")
elif req.data == "D":
self.processD()
return String("D区任务执行完毕")
else:
return String(f"未知区域: {req.data}")
def processA(self):
"""A区救援任务"""
rospy.loginfo("开始执行A区救援任务")
goals = [
self.create_goal(1.5, 2.1, 0, 1), # 到达A点
]
if self.execute_mission(goals, "A"):
rospy.loginfo("到达A区,正在接收伤员...")
self.detect("test1.jpg", 0.5)
time.sleep(3)
# 返回营地
rospy.loginfo("A区任务完成,返回营地")
return_goals = [
self.create_goal(0, 0, 0, 1), # 返回营地
]
self.execute_mission(return_goals, "A")
else:
rospy.logerr("A区任务失败")
以上代码片段展示了项目的核心技术实现,包括多地形自适应导航、目标识别、徘徊脱困、紧急终止和任务调度等关键功能。这些代码共同构成了一个完整的智能侦察机器人系统,能够在复杂环境中高效完成任务。