📄 论文解析:DUCPP ------ 当路不知道能不能走,让无人机先去探路
论文全名: Dynamic UGV-UAV Cooperative Path Planning in Uncertain Environments
发布时间: 2026年4月(arXiv:2604.25267v1)
机构: 北卡罗来纳大学夏洛特分校计算机科学系
一、问题背景:你以为走得通的路,走一半才发现是死路
想象一个灾后救援场景:地震过后,救援车必须穿越城市道路网络运送物资。城市地图是有的,但地图上存在的路,不代表现在能走------有的路段被建筑物碎石堵死,有的桥梁已经垮塌,有的积水过深无法通行。
问题的核心难在:
- 路能不能走,只有到了现场才知道。导航软件不知道,调度中心不知道,司机出发前也不知道。
- 如果走到一半发现断路,只能原路返回重规划,时间白白浪费
- 城市路网错综复杂,哪条路最值得先去探查,是个困难决策
这就是论文所研究的动态不确定环境下的 UGV-UAV 协同路径规划(Dynamic UGV-UAV Cooperative Path Planning,DUCPP)问题的出发点。
解题思路其实朴素而直觉------既然无人车在地面走路慢、探路受限,那就让无人机飞在前头先看清楚,再把信息实时传回给无人车,指导它选最优路线。
但"让无人机先探路"说起来简单,做起来有一连串问题:
- 道路那么多,无人机先探哪条?
- 无人车在走,无人机要飞去哪里探路才最有价值?
- 如果有多架无人机,怎么分工才不重复?
- 探路途中发现新的断路,双方如何实时调整?

DUCPP 正是对这一完整问题的系统性研究。
二、应用场景:不只是救灾,是一切"走之前不知道能不能走"的情形
| 应用场景 | 不确定性来源 |
|---|---|
| 灾害响应 | 地震、洪水、山火造成路段损毁,实时状态未知 |
| 应急物资运输 | 战时或极端天气下,公路网络动态损毁,驾驶员需实时引导 |
| 搜救行动 | 救援队需穿越废墟区,地面可通行性完全未知 |
| 军事后勤 | 敌方破坏或地雷封锁,部分路段状态危险或不可通行 |
| 极端天气下的配送 | 冰雪封路、洪涝积水,哪段路还能走只有实地确认才知道 |
值得注意的是,论文的方法也可以用于给人类驾驶员规划路线------无人机探路,无人车或人开的车跟随导航结果走。这让 DUCPP 的应用范围超出了纯机器人领域,具有实际的工程部署价值。
三、问题形式化:一张"地图上有坑"的图论问题
论文将道路网络建模为图 G = (V, E),节点是路口,边是路段。每条边有一个存在概率(existence probability,范围 0.6, 1.0),表示这条路可通行的可能性。
关键的建模细节有几点,很有现实意义:
不到现场不知道 :边的状态(通/断)只有当 UGV 或 UAV 实际到达损毁点时才会被发现,而损毁点可能在路段中间,不一定在节点处。这比经典的"加拿大旅行者问题"(CTP)更贴近现实------CTP 假设到达节点就能知道所有邻边状态,而 DUCPP 要求真正"到达"才知道。
UGV 和 UAV 的移动方式不同:
- UGV 只能沿图的边行驶
- UAV 可以沿边飞行(探路),也可以在任意两点之间直线飞行(deadhead),后者让 UAV 能快速奔赴需要探查的路段
目标:最小化 UGV 到达目的地的总行驶时间(包括因断路绕行损失的时间)。

四、方法:六种策略,一场"谁更聪明"的比赛
论文设计了一套统一的框架,核心循环是:路径规划 → 边分配(给 UAV) → 行驶/巡查 → 发现新情况 → 重规划。在这个框架下,论文提出并比较了六种策略:
4.1 完美知识(Perfect Knowledge)------ 理论下界
假设所有路段状态预先已知,用 Dijkstra 找最短路径。这是任何策略都无法突破的理论最优下界,用来衡量其他策略的差距。
4.2 仅 UGV(UGV-only)------ 最笨的基线
没有无人机,UGV 靠自己走,遇到断路回头重规划。这是最差的情形,对应的是"没有空中支援的救援车",也是所有 UAV 辅助策略对比的基准。
4.3 基于 Kemeny 常数(Kemeny Strategy)
从图论出发,预计算每条边的"重要性"------具体用的是一种基于 Kemeny 常数的边中心性指标:移除某条边后图的 Kemeny 常数越大,说明这条边越关键(一旦断了影响越大)。UAV 优先去探查 UGV 路径上重要性最高的未探边。
这个方法的缺点是 Kemeny 常数只在最开始计算一次,不随图更新而调整,灵活性有限。
4.4 基于 k 最短路径
用 Yen 算法找从当前位置到目的地的 k 条最短路,UAV 优先探查在这 k 条路中出现频率最高的未探边------出现次数越多,说明这条边越是"共同瓶颈",探清楚价值越大。这个方法动态性更好,但计算量随 k 增大。
4.5 最大概率最短路(MPSP)
结合每条边的存在概率,找的不是单纯最短路,而是既短又最可能能走通的路径。UAV 专去探查路径上存在概率最低的边(最有可能断的那一条)。
这个策略在直觉上很合理:不确定性最高的边最值得先确认。
4.6 双向策略(Bidirectional)------ 论文的主角
这是论文最核心的创新策略,逻辑极其简洁:
UGV 从起点向终点走;UAV 从终点端开始,沿 UGV 规划路径"反向"逐条探查。
UAV 从目的地附近开始探查,沿 UGV 的规划路径往回检查;UGV 同时从起点出发前进。两者"相向而行",当两者汇合时,整条路径的关键路段都已经确认安全(或找到了备用路线)。
这个设计的聪明之处在于:
- UAV 通常从目的地附近的相邻边开始探查,这些边彼此连接,UAV 不需要长途奔袭,大幅减少了 UAV 的"空飞"时间
- 对比其他策略,UAV 经常需要飞去图的其他位置探查"高优先级"边,但飞过去就已经花了很多时间
- 计算复杂度低,和 Dijkstra 同量级 O((V+E)logV)
4.7 多 UAV 双向策略
将双向策略扩展到 k 架 UAV:用 Yen 算法找 k 条最短路,每架 UAV 从对应路径的终点反向探查,且每条边只分配一架 UAV,避免重复探查(同时假设飞不同高度规避碰撞)。
五、实验结果:数字告诉你双向策略赢在哪里
实验基于 OpenStreetMap 全球 50 大城市的真实路网,每个城市有小图(1km×1km)和大图(3km×3km),各随机生成 50 个实例,共计100 张路网 × 50 个实例 = 5000 个测试场景,规模可观。
部分关键结论(UAV 速度 40m/s,UGV 速度 20m/s):
| 策略 | 东京(小图)UGV 用时 | 拉各斯(大图)UGV 用时 |
|---|---|---|
| 完美知识(下界) | 8.9s | 48.3s |
| 仅 UGV | 31.4s | 317.4s |
| 双向策略 | 21.1s | 170.6s |
| 7 架 UAV(双向) | 17.2s | 138.3s |
双向策略在大图上相比仅 UGV 策略平均节省 38.4% 的行驶时间(UAV:UGV 速度比 2:1 时);多 UAV 进一步压缩时间,但计算量随 UAV 数量显著上升。
特别有意思的一个趋势:地图越大,UAV 的优势越明显。大图中断路造成的绕行代价更高,UAV 提前探路的价值也更大。这也说明该方法在真实大城市场景中具有实际意义。
六、创新点:论文的新在哪里?
✦ 创新一:更现实的断路建模
与以往研究相比,DUCPP 明确区分了"边成本不确定"和"边完全不可通行"两种情况,并规定损毁点可能在路段中间而非节点处。这让问题更贴近真实灾害场景,也使得策略设计更有挑战性。
✦ 创新二:双向协同策略的设计
将经典双向搜索思路引入 UAV-UGV 多智能体场景,让 UAV 从终点反向探查这一设计,实现了"以最低飞行代价覆盖最关键路段"的效果。这个思路直觉清晰,但此前并没有人在 UAV 辅助 UGV 的场景中这样做过。
✦ 创新三:多策略系统比较
论文不是只提一个方法,而是设计并横向比较了 6 种策略(含两个基线),在时间效率和计算复杂度两个维度上进行全面评估,为后续研究提供了清晰的方法谱系。
✦ 创新四:多 UAV 扩展与分工机制
通过 k 条最短路 + 每条路分配一架 UAV 的设计,优雅地解决了多 UAV 的任务分配问题,保证无重复探查,且碰撞规避通过分配不同飞行高度简洁处理。
七、不足之处:诚实面对局限
⚠ 不足一:通信假设过于理想
论文假设无线通信无延迟、无丢包,UAV 发现的断路信息瞬间传达给 UGV。在实际灾害现场,通信基础设施往往受损,信号中断是常态而非例外。论文自己也承认这是需要解决的实际问题,但没有给出解决方案。
⚠ 不足二:UAV 没有能量限制
论文完全忽略了 UAV 的电池续航约束。现实中无人机的飞行时间通常只有 20-40 分钟,大城市路网探查任务可能远超这个时限。没有能量约束,多 UAV 的调度策略就是在一个简化的理想世界里运行。
⚠ 不足三:UAV 直线飞行假设
论文假设 UAV 可以在任意两点之间直线飞行(deadhead),但现实中存在禁飞区、建筑物、高压线等障碍,无人机不能随意直线穿越。这使得 UAV 的飞行时间估算可能系统性偏低。
⚠ 不足四:仅仿真,无实机验证
所有实验均为基于 OpenStreetMap 数据的数值仿真,没有在真实机器人上验证。路网是真实的,但传感器噪声、定位误差、实际通信延迟等工程因素均被完全屏蔽。
⚠ 不足五:单 UGV 假设限制了应用范围
论文只考虑一辆 UGV,而真实救灾场景中往往需要多辆车辆协同行动(多辆救援车、多辆物资运输车)。多 UGV 情境下如何分配有限的 UAV 资源,是一个更复杂但更实用的问题,本文没有涉及。
八、横向视角:与前三篇论文的定位对比
至此,四篇论文形成了一个有趣的全景图:
| 论文 | 关注点 | 核心问题 |
|---|---|---|
| CoPCS | 大规模任务分配 | 多 UAV 访问所有任务点,UGV 提供充电支持 |
| 学习加速轨迹规划 | 精确轨迹生成 | 如何快速生成满足动力学约束的交接轨迹 |
| GA3T | 感知数据基础 | 为野外协同感知研究提供真实多模态数据集 |
| DUCPP(本文) | 不确定路网导航 | 道路可通行性未知时,如何用 UAV 探路引导 UGV |
DUCPP 的独特性在于它关注的是信息不确定性下的路网导航 ,而不是轨迹精度或任务分配效率。它研究的是一个图论意义上更纯粹的决策问题:在知道什么、不知道什么的约束下,如何最优地行动。
九、总结:一篇"土木工程师和算法工程师合写"的论文
DUCPP 解决的问题有一种朴实的工程气质------它不追求复杂的神经网络,不依赖大量训练数据,就是在一张图上想清楚:无人机应该先去探哪条边,才能让无人车少走弯路。
双向策略的胜出也印证了一个古老的算法智慧:有时候最优雅的解法,是从两头同时出发。
这篇论文真正的价值不在于方法有多复杂,而在于它把一个高度现实、高度紧迫的问题抽象清楚,并给出了可以直接实现、对比评估的多套方案。在灾害响应这个分秒必争的领域,这种扎实的工程导向研究,或许比很多精妙的理论工作更有落地可能。
十、代码实现
根据这篇论文 Dynamic UGV-UAV Cooperative Path Planning in Uncertain Environments 的描述,把它复现成一个可运行的 Python 仿真框架。
本质上是一个:
-
图搜索环境建模(road network graph)
-
UGV状态机
-
UAV巡检状态机
-
事件驱动动态重规划
-
多种策略切换:
- UGV-only
- Kemeny
- k-shortest
- MPSP
- Bidirectional(论文最优)
- Multi-UAV Bidirectional
工程目录
text
ducpp/
├── graph_env.py
├── vehicle.py
├── strategies.py
├── planner.py
├── experiments.py
└── main.py
安装依赖:
bash
pip install networkx matplotlib numpy
1. graph_env.py
python
import networkx as nx
import random
import math
class RoadGraph:
def __init__(self):
self.G = nx.Graph()
self.edge_info = {}
def add_edge(self, u, v, length, damage_prob=0.2):
self.G.add_edge(u, v, weight=length)
key = self.norm(u, v)
self.edge_info[key] = {
"length": length,
"real_damaged": random.random() < damage_prob,
"status": "unknown"
}
def norm(self, u, v):
return tuple(sorted((u, v)))
def inspect_edge(self, u, v):
e = self.norm(u, v)
if self.edge_info[e]["real_damaged"]:
self.edge_info[e]["status"] = "damaged"
if self.G.has_edge(*e):
self.G.remove_edge(*e)
return False
self.edge_info[e]["status"] = "safe"
return True
def shortest_path(self, start, goal):
try:
return nx.shortest_path(
self.G,
start,
goal,
weight="weight"
)
except:
return None
def path_cost(self, path):
if not path:
return math.inf
cost = 0
for i in range(len(path) - 1):
cost += self.G[path[i]][path[i+1]]["weight"]
return cost
2. vehicle.py
python
class UGV:
def __init__(self, start, speed=20):
self.start = start
self.position = start
self.speed = speed
self.path = []
def assign_path(self, path):
self.path = path
class UAV:
def __init__(self, start, speed=40):
self.start = start
self.position = start
self.speed = speed
self.inspect_target = None
def assign_edge(self, edge):
self.inspect_target = edge
3. strategies.py
UGV-only + Bidirectional + Multi-UAV
python
class Strategy:
def __init__(self, graph, ugv, goal):
self.graph = graph
self.ugv = ugv
self.goal = goal
def find_path(self):
raise NotImplementedError
class UGVOnlyStrategy(Strategy):
def find_path(self):
path = self.graph.shortest_path(
self.ugv.position,
self.goal
)
if not path:
return False
self.ugv.assign_path(path)
return True
class BidirectionalStrategy(Strategy):
def __init__(self, graph, ugv, uav, goal):
super().__init__(graph, ugv, goal)
self.uav = uav
def find_path(self):
path = self.graph.shortest_path(
self.ugv.position,
self.goal
)
if not path:
return False
self.ugv.assign_path(path)
for i in range(len(path)-1, 0, -1):
edge = (path[i], path[i-1])
if self.graph.edge_info[
self.graph.norm(*edge)
]["status"] == "unknown":
self.uav.assign_edge(edge)
break
return True
class MultiUAVBidirectionalStrategy(Strategy):
def __init__(self, graph, ugv, uavs, goal):
super().__init__(graph, ugv, goal)
self.uavs = uavs
def find_path(self):
path = self.graph.shortest_path(
self.ugv.position,
self.goal
)
if not path:
return False
self.ugv.assign_path(path)
assigned = []
idx = len(path)-1
for uav in self.uavs:
while idx > 0:
edge = (path[idx], path[idx-1])
if edge not in assigned:
uav.assign_edge(edge)
assigned.append(edge)
idx -= 1
break
idx -= 1
return True
4. planner.py
论文 Algorithm 1
python
import time
class DUCPPPlanner:
def __init__(self, strategy):
self.strategy = strategy
self.total_travel_time = 0
self.compute_time = 0
def step(self):
start = time.time()
feasible = self.strategy.find_path()
self.compute_time += time.time() - start
if not feasible:
return False
if hasattr(self.strategy, "uav"):
uav = self.strategy.uav
if uav.inspect_target:
self.strategy.graph.inspect_edge(
*uav.inspect_target
)
if hasattr(self.strategy, "uavs"):
for uav in self.strategy.uavs:
if uav.inspect_target:
self.strategy.graph.inspect_edge(
*uav.inspect_target
)
ugv = self.strategy.ugv
if len(ugv.path) > 1:
nxt = ugv.path[1]
safe = self.strategy.graph.inspect_edge(
ugv.position,
nxt
)
if safe:
ugv.position = nxt
self.total_travel_time += 1
return ugv.position != self.strategy.goal
def run(self):
while self.step():
pass
return self.total_travel_time, self.compute_time
5. experiments.py
python
import random
import matplotlib.pyplot as plt
import numpy as np
from graph_env import RoadGraph
from vehicle import UGV, UAV
from strategies import *
from planner import DUCPPPlanner
def random_graph(n=20):
g = RoadGraph()
for i in range(n):
for j in range(i+1, n):
if random.random() < 0.18:
g.add_edge(
i, j,
random.randint(1, 10),
damage_prob=0.25
)
return g
def run_trial(strategy_type):
g = random_graph()
start = 0
goal = 15
ugv = UGV(start)
if strategy_type == "ugv":
strategy = UGVOnlyStrategy(g, ugv, goal)
elif strategy_type == "bi":
strategy = BidirectionalStrategy(
g, ugv, UAV(10), goal
)
else:
strategy = MultiUAVBidirectionalStrategy(
g, ugv,
[UAV(10), UAV(11), UAV(12)],
goal
)
planner = DUCPPPlanner(strategy)
return planner.run()
def benchmark():
names = ["UGV-only", "Bidirectional", "3-UAV"]
travel = []
compute = []
for s in ["ugv", "bi", "multi"]:
t = []
c = []
for _ in range(50):
tt, cc = run_trial(s)
t.append(tt)
c.append(cc)
travel.append(np.mean(t))
compute.append(np.mean(c))
return names, travel, compute
def plot_results():
names, travel, compute = benchmark()
plt.figure(figsize=(12, 5))
plt.subplot(121)
plt.bar(names, travel)
plt.title("Average UGV Travel Time")
plt.subplot(122)
plt.bar(names, compute)
plt.title("Average Computation Time")
plt.tight_layout()
plt.show()
6. main.py
python
from experiments import plot_results
plot_results()
运行
bash
python main.py
和论文对应关系
| 论文模块 | 工程实现 |
|---|---|
| Algorithm 1 | DUCPPPlanner |
| Algorithm 2 | step() |
| Algorithm 6 | BidirectionalStrategy |
| Multiple UAV | MultiUAVBidirectionalStrategy |
| Section IV Results | benchmark() |
进一步做科研复现
1. 接入真实地图
用OpenStreetMap 和 OSMnx
(1)OpenStreetMap(简称 OSM) 是一个全球性的开放协作地理数据库项目,旨在通过众包方式创建和维护免费的可编辑世界地图。其数据可被任何人自由使用、修改与分享,是众多地图应用和地理信息系统的基础数据来源。

链接:https://www.openstreetmap.org/
(2)OSMnx 是一个基于 Python 的开源库,用于从 OpenStreetMap 下载、建模、分析与可视化街道网络。它广泛应用于城市研究、交通规划、空间分析与可视化任务中,使研究者和开发者能轻松操作复杂的地理网络数据。

链接:https://osmnx.readthedocs.io/en/stable/
2. 替换为论文中的
- k-shortest paths
- MPSP
- Kemeny centrality
3. 可视化机器人动态运动
用:
- Matplotlib animation
- 或者ROS RViz