ECBS是对CBS问题的优化,而了解CBS又得先了解A*算法,本文对以上内容进行详细介绍,主要参考文献如下
Suboptimal Variants of the Conflict-Based Search Algorithm for the Multi-Agent Pathfinding Problem
1. A*算法
关于A算法,主要参考了A*算法详解 一看就会 手把手推导 完整代码注释以及启发式搜索(heuristic search)———A*算法
A算法常用于解决最短路问题,其是Dijkstra 算法和贪婪优先算法的结合,对于评估函数f(n)而言:
- Dijkstra: 到起点的距离优先:即从起点A,沿着产生的路径,移动到网格上指定节点的移动耗费。
- 贪婪优先算法:到目标点的距离优先 :即从网格上那个节点移动到终点B的预估移动耗费
- A*算法:即前两者之和: f ( n ) = g ( n ) + h ( n ) f(n)=g(n)+h(n) f(n)=g(n)+h(n), g ( n ) g(n) g(n)即对应Dijkstra, h ( n ) h(n) h(n)即对应贪婪优先算法
这里着重强调一下 h ( n ) h(n) h(n)的含义, h ( n ) h(n) h(n)经常被称为启发式的,这样叫的原因是因为它只是个猜测。我们没办法事先知道路径的长度,因为路上可能存在各种障碍(墙,水,等等)。它计算从当前位置到目的位置之间的距离。很重要的一点,我们忽略了一切障碍物。这是对剩余距离的一个估算,而非实际值。而由于忽略了所有障碍物,所以这个值一定是当前位置到目的位置的最小值。
具体步骤:
新建open列表,open表表示当前的搜索边界,也即为用于下一步搜索的备用节点集合
新建close列表,close表存放从open表中弹出的结点
1、将源点加入open表
2、
while(OPEN!=NULL||到达goal_node)
{
从OPEN表中取f(n)最小的节点n;
if(n节点==目标节点)
break;
for(当前节点n的每个子节点X)
{
计算f(X);
if(X在open表里)
if(新的f(X)<OPEN中的f(X))
{
把n设置为X的父亲;
更新OPEN表中的f(n); //不要求记录路径的话可以直接加入open表,旧的X结点是不可能比新的先出队
}
if(X在CLOSE表里)
continue;
if(X都不在)
{
把n设置为X的父亲;
求f(X);
并将X插入OPEN表中;
}
}//endfor
将n节点插入CLOSE表中;
按照f(n)将OPEN表中的节点排序;//实际上是比较OPEN表内节点f的大小,从最小路径的节点向下进行。
}//endwhile(OPEN!=NULL)
3、保存路径,从目标点出发,按照父节点指针遍历,直到找到起点。
2. A ϵ ∗ A^*_\epsilon Aϵ∗算法
参考文献:Studies in Semi-Admissible Heuristics,主要参考了A*算法及其变种
根据论文介绍
A
ϵ
∗
A^*_\epsilon
Aϵ∗算法是一种有界次优算法。设最优代价为
C
0
C_0
C0,给定参数
ϵ
\epsilon
ϵ,使得有界次优算法的结果
C
C
C满足
C
≤
(
1
+
ϵ
)
C
0
C\leq (1+\epsilon)C_0
C≤(1+ϵ)C0。
我们知道 A* 算法每次在 O P E N OPEN OPEN表里取最小的节点进行下一步搜索。论文提到,搜索算法在搜索过程中事实上会得到许多 c o s t cost cost相近的解,A 算法每次都取最优比较费时间,多花的时间与得到的优化效果不成比例,俗称 “性价比不高”。
因此
A
ϵ
∗
A^*_\epsilon
Aϵ∗算法在A算法
O
P
E
N
OPEN
OPEN表的基础上,设计了
F
O
C
A
L
FOCAL
FOCAL表,定义如下:
F
O
C
A
L
=
n
∗
:
f
^
(
n
∗
)
≤
(
1
+
ϵ
)
m
i
n
n
∈
o
p
e
n
f
(
n
)
FOCAL=n^*:\hat{f}(n^*)\leq(1+\epsilon)min_{n\in open}f(n)
FOCAL=n∗:f^(n∗)≤(1+ϵ)minn∈openf(n)
其中
f
(
n
)
f(n)
f(n)与A算法相同,
g
(
n
)
g(n)
g(n)代表当前结点n到起点的距离,
h
(
n
)
h(n)
h(n)代表预测当前节点n到终点的距离(启发式函数)
等同于
F
O
C
A
L
FOCAL
FOCAL表将
O
P
E
N
OPEN
OPEN表中
f
(
n
)
f(n)
f(n)值小于等于
(
1
+
ϵ
)
(1+\epsilon)
(1+ϵ)倍最小
f
f
f值的所有结点放在一起,形成一个次优集体,从中再选择出最适合的那个结点。
与A算法不同的是,A算法是通过
m
i
n
f
(
n
)
minf(n)
minf(n)的结点作为下一个拓展结点,而
A
ϵ
∗
A^*_\epsilon
Aϵ∗算法是通过新的启发式函数
h
F
(
n
)
h_F(n)
hF(n)作为规则,在
F
O
C
A
L
FOCAL
FOCAL表中进行选择。
h
F
h_F
hF估计完成从结点n开始的搜索所需的计算量。(其具体含义根据后面面临的不同问题可以做出不同的设定)
总结:
A
ϵ
∗
A^*_\epsilon
Aϵ∗算法与A*算法的不同之处在于:
1.使用了参数数
ϵ
\epsilon
ϵ,从
O
P
E
N
OPEN
OPEN中选择
f
^
(
n
∗
)
≤
(
1
+
ϵ
)
m
i
n
n
∈
o
p
e
n
f
(
n
)
\hat{f}(n^*)\leq(1+\epsilon)min_{n\in open}f(n)
f^(n∗)≤(1+ϵ)minn∈openf(n)的结点,形成新集合
F
O
C
A
L
FOCAL
FOCAL,从中进行选择
2.使用了新的启发式函数
h
F
(
n
)
h_F(n)
hF(n),在
F
O
C
A
L
FOCAL
FOCAL中作为评判标准选择拓展节点。
h
(
n
)
h(n)
h(n)用于作为构建
F
O
C
A
L
FOCAL
FOCAL的评判标准,而
h
F
(
n
)
h_F(n)
hF(n)作为从
F
O
C
A
L
FOCAL
FOCAL中选择拓展节点的标准。
3. CBS算法
多智能体路径规划 (Multi-Agent Path Finding, MAPF) 研究多智能体的路径规划算法,为多机系统规划无冲突的最优路径.关于MAPF可以看这里多机器人路径规划(MAPF)综述
CBS(Conflict-Based Search) 是一种基于冲突的 MAPF 算法, CBS 算法给出 MAPF 问题的全局最优结果。参考文献为Conflict-based search for optimal multi-agent pathfinding,主要参考CBS(Conflict-Based Search)多机器人路径规划
CBS路径规划:行为上是一棵树的形式,算法的思想划分为两层,
- 底层执行各个 a g e n t agent agent的单机最短路径规划,使用传统的A*算法
- 顶层遍历底层的规划路径,检查路径是否有冲突,如果有冲突,如果有冲突的话就施加约束重新进行底层规划,直到所有底层路径没有冲突为止。
3.1 定义术语:
- p a t h path path:一条机器人的路径,也就是单机规划的结果
- s o l u t i o n solution solution:所有agent的 p a t h path path集合,也就是mapf全局规划的结果
- c o n f l i c t conflict conflict:冲突,在 s o l u t i o n solution solution中,agent之间路径可能会发生冲突,具体描述形式为( a i a_i ai, a j a_j aj, v v v, t t t),表示在 t t t这个timestep, a i a_i ai和 a j a_j aj同时占据了顶点 v v v。
- c o n s t r a i n t s constraints constraints:约束,具体描述形式为( a i a_i ai, v v v, t t t),表示在时刻 t t t, a i a_i ai不能占据顶点 v v v。
- c o s t cost cost:表示当前 s o l u t i o n solution solution,每个 a g e n t agent agent的f(n)之和
3.2 顶层
CBS算法顶层使用约束树(Search the Constraint Tree (CT))数据结构来解决底层冲突,如下图所示:
其实就是一颗树(可以设计成二叉树或者多叉树),树的每个节点除了有指向子节点的指针,还包括:
c
o
n
s
t
r
a
i
n
t
s
constraints
constraints:由
c
o
n
f
l
i
c
t
conflict
conflict得到
s
o
l
u
t
i
o
n
solution
solution:目前结点的全局路径(可能包含冲突)
c
o
s
t
cost
cost:目前结点的总代价
注意:次数的结点不是指A*算法中的agent节点,而是指CT树上面的结点:CT_node
3.3 生成树
生成树的过程就是从父节点生出子节点的过程,如下图所示
两个智能体
a
1
a_1
a1和
a
2
a_2
a2想分别从
S
1
S_1
S1和
S
2
S_2
S2出发到达
G
1
G_1
G1和
G
2
G_2
G2
在初始情况下,约束集为空,此时进行底层A*搜索,生成两个path
p
a
t
h
1
path_1
path1:
<
S
1
,
A
1
,
C
,
G
1
>
<S_1,A_1,C,G_1>
<S1,A1,C,G1>
p
a
t
h
2
path_2
path2:
<
S
2
,
B
1
,
C
,
G
2
>
<S_2,B_1,C,G_2>
<S2,B1,C,G2>
计算当前的
c
o
s
t
cost
cost=3+3=6(起点是不算的)
因此CT树的根节点
r
o
o
t
root
root如图所示:
接下来:
- 遍历当前结点的 s o l u t i o n solution solution,搜索得到 p a t h s paths paths之间的第一个冲突
- 解决冲突,两条路径在第2步时都到达了 C C C,因此将冲突拆成两个约束 ( a 1 , C , 2 ) (a_1,C,2) (a1,C,2)和 ( a 2 , C , 2 ) (a_2,C,2) (a2,C,2),分别表示 a 1 a_1 a1在第2步不能占据 C C C和 a 2 a_2 a2在第2步不能占据 C C C
- 生成子节点,将结点 r o o t root root分为两个子节点,每个子节点都继承父节点原有的约束,并赋予第2步中独有的约束
- 将子节点的约束施加到底层规划算法中,计算出新的
p
a
t
h
path
path,合并成
s
o
l
u
t
i
o
n
solution
solution,如下图:
- 计算每个子节点的全局 c o s t cost cost,左右子节点均为7,由于搜索一般从左边开始,因此优先考虑左节点,此时左节点无冲突,则为全局最优路径,算法返回。
3.4 算法伪代码流程:
可以看出,在CBS的顶层也使用了
o
p
e
n
open
open表,存放着CT树里的拓展结点,并且通过CT_node的
c
o
s
t
cost
cost值作为判断标准选择CT_node进行拓展。也就是伪代码里的
p
p
p,然后对
p
p
p进行冲突检测,如果
p
p
p中没有冲突,则返回结果。否则记录下
p
p
p中的第一个冲突,记录为
C
C
C,对于冲突对中的每一个智能体进行增加
c
o
n
s
t
r
a
i
n
t
s
constraints
constraints,并且赋给子节点
A
A
A,随后
A
A
A中对每一个agent进行A*算法求解
p
a
t
h
path
path,最后得到
A
A
A的
s
o
l
u
t
i
o
n
solution
solution并且计算
A
A
A的
c
o
s
t
cost
cost,最后将A插入顶层的
o
p
e
n
open
open表中
3.5 总结:
在CBS中,顶层设计采用的CT树的结构,并且也是通过设计 o p e n open open将拓展结点装入,并且通过CT_node的 c o s t cost cost选择新拓展结点,与A*算法一致。
在底层中,通过新拓展节点 P P P的 f i r s t _ c o n f l i c t first\_conflict first_conflict给其子节点 A A A添加分别对应的 c o n s t r a i n constrain constrain,随后子节点再分别对每个 a g e n t agent agent进行路径规划,并且计算出 A A A的 c o s t cost cost。随后将 A A A加入 o p e n open open中
4. ECBS算法
参考文献Suboptimal Variants of the Conflict-Based Search Algorithm for the Multi-Agent Pathfinding Problem主要参考ECBS多机器人路径规划
ECBS其实结构与CBS是一致的,CBS在顶层设计和底层设计中使用的是A*的策略,而ECBS在顶层和底层中使用的是 A ϵ ∗ A^*_\epsilon Aϵ∗的策略。
4.1 底层设计:
对于ECBS的底层设计,为 a g e n t agent agent a i a_i ai搜索路径使用的 O P E N OPEN OPEN表为 O P E N i OPEN_i OPENi,则 O P E N i OPEN_i OPENi中的最小 f f f值 f m i n f_{min} fmin为t a i a_i ai最优路径搜索代价 c o s t i cost_i costi的下界(Lower Bound)。对于一个CT树节点CT_node,设其为 n n n,则 n n n的 c o s t cost cost的最优解 L B ( n ) = ∑ i = 1 k f m i n ( i ) LB(n)=\sum\limits_{i=1}^{k} {f_{min}(i)} LB(n)=i=1∑kfmin(i),其中 k k k为 a g e n t agent agent的个数
在底端对 a i a_i ai使用 A ϵ ∗ A^*_\epsilon Aϵ∗算法,设置参数 ϵ \epsilon ϵ,将满足 f ^ ( n ∗ ) ≤ ( 1 + ϵ ) m i n n ∈ o p e n f ( n ) \hat{f}(n^*)\leq(1+\epsilon)min_{n\in open}f(n) f^(n∗)≤(1+ϵ)minn∈openf(n)的路径 p a t h n ∗ path_{n^*} pathn∗装入 F O C A L i FOCAL_i FOCALi,随后设置 h c h_c hc,其表示返回与先前分配的其他代理冲突最少的路径。
例如为 a 1 a_1 a1分配了路径 ( S 1 , A , G ) (S_1,A,G) (S1,A,G),那么为 a 2 a_2 a2分配道路时就要优先考虑避免第1步中位置 A A A以外的其他位置。
4.2 顶层设计:
在ECBS的顶层同样采取 A ϵ ∗ A^*_\epsilon Aϵ∗的算法,每个CT_node都返回两个值给顶层算法
- n . c o s t n.cost n.cost
- L B ( n ) LB(n) LB(n)
其中
n
.
c
o
s
t
n.cost
n.cost为CT树节点
n
n
n的代价
c
o
s
t
cost
cost,
L
B
(
n
)
LB(n)
LB(n)为
n
n
n的理想状态的代价下界
设
L
B
=
m
i
n
(
L
B
(
n
)
∣
n
∈
O
P
E
N
)
LB=min(LB(n)|n\in OPEN)
LB=min(LB(n)∣n∈OPEN),此时的
O
P
E
N
OPEN
OPEN为顶层搜索的
O
P
E
N
OPEN
OPEN表,则
L
B
LB
LB显然是全局最优代价
C
∗
C^*
C∗的下界。因此顶层的
F
O
C
A
L
FOCAL
FOCAL表的设计为
F
O
C
A
L
=
{
n
∣
n
∈
O
P
E
N
,
n
.
c
o
s
t
≤
L
B
⋅
w
}
FOCAL=\lbrace n|n\in OPEN,n.cost\leq LB\cdot w \rbrace
FOCAL={n∣n∈OPEN,n.cost≤LB⋅w}
而顶层设计也同样拥有 h c h_c hc,其含义为当前分支节点中至少有一个冲突的 a g e n t agent agent对的数量(即 a g e n t _ p a i r s agent\_pairs agent_pairs),例如当前结点 n n n存在 c o n f l i c t conflict conflict ( a 1 (a_1 (a1, a 2 a_2 a2, 1 1 1, 1 ) 1) 1)和 ( a 2 (a_2 (a2, a 3 a_3 a3, 3 3 3, 2 ) 2) 2),则存在冲突对为 ( a 1 (a_1 (a1, a 2 ) a_2) a2), ( a 2 (a_2 (a2, a 3 ) a_3) a3), h c ( n ) = 2 h_c(n)=2 hc(n)=2
其余算法逻辑与CBS一致。
4.3 总结:
顶层和底层都使用了 A ϵ ∗ A^*_\epsilon Aϵ∗算法,其中底层的 h c h_c hc表示返回与先前分配的其他代理冲突最少的路径。顶层的 h c h_c hc表示当前分支节点中至少有一个冲突的 a g e n t agent agent对的数量