-
Notifications
You must be signed in to change notification settings - Fork 14
/
CBS.js
137 lines (114 loc) · 4.01 KB
/
CBS.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
class CBS {
constructor(env) {
this.env = env;
this.openSet = [];
this.closedSet = [];
}
search() {
var start = new CTNode();
//初始化
start.constraint_dict = {};
for (var agent in this.env.agent_dict) {
start.constraint_dict[agent] = new Constraints();
}
start.solution = this.env.calcSolution(false); //计算初始路径解
if (!start.solution) {
return {};
}
start.cost = this.env.calcSolutionCost(start.solution);
this.openSet.push(start);
while (this.openSet.length) {
var p = this.findMinCost(this.openSet);
_.pull(this.openSet, p);
this.closedSet.push(p);
this.env.constraint_dict = p.constraint_dict; //变换环境
var conflict = this.env.getFirstConflict(p.solution);
// console.log("conflict:", conflict);
// console.log("open1:", this.openSet);
// console.log("close1:", this.closedSet);
//如果没有冲突
if (!conflict) {
console.log('done!');
return this.generatePlan(p.solution);
}
//如果有冲突
//将冲突转化为约束
var constraint_dict = this.env.createConstraintFromConflict(conflict);
// console.log("constraint_dict:", constraint_dict);
//根据冲突分裂结点
for (var agent in constraint_dict) {
var newNode = _.cloneDeep(p);
newNode.constraint_dict[agent].addConstraint(constraint_dict[agent]);
this.env.constraint_dict = newNode.constraint_dict; //切换环境
// newNode.solution = this.env.calcSolution(); //重新计算路径解
newNode.solution = this.env.calcOneSolution(p.solution, agent)
console.log("newNode:", newNode);
if (!newNode.solution) {
continue;
}
newNode.cost = this.env.calcSolutionCost(newNode.solution);
console.log("newNode:", newNode);
console.log("cost:", newNode.cost);
if (!this.isInArray(this.openSet, newNode)) {
this.openSet.push(newNode);
}
}
// console.log("open2:", this.openSet);
// console.log("close2:", this.closedSet);
}
return -1; //无解
}
//检查CTNode是否在Set中
isInArray(tmpArr, node) {
for (var obj of tmpArr) {
if (_.isEqualWith(obj, node, this.solCmp)) {
return true;
}
}
return false;
}
solCmp(obj, other) {
var path1 = cbs.generatePlan(obj.solution);
var path2 = cbs.generatePlan(other.solution);
for (var agent in path1) {
if (JSON.stringify(path1[agent]) != JSON.stringify(path2[agent])) {
return false;
}
}
return true;
}
findMinCost(tmpSet) {
//找到cost最小的CTNode
var minNode;
var minCost = 99999;
for (var node of tmpSet) {
if (node.cost < minCost) {
minNode = node;
minCost = node.cost;
}
}
return minNode;
}
generatePlan(solution) {
var plan = {};
for (var agent in solution) {
var path = solution[agent];
var list = []
for (var state of path) {
var item = {
't': state.time,
'x': state.location.x,
'y': state.location.y
};
// var item = {};
// item[state.time] = {
// 'x': state.location.x,
// 'y': state.location.y
// };
list.push(item);
plan[agent] = list; //该条agent的执行路径
}
}
return plan;
}
}