-
Notifications
You must be signed in to change notification settings - Fork 14
/
CBS_v2.js
152 lines (129 loc) · 4.59 KB
/
CBS_v2.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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
class CBS_v2 {
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();
}
// let t1 = millis(); //精确到毫秒
start.solution = this.env.calcSolution(true); //计算初始路径解
// let t2 = millis();
// console.log(t2-t1);
if (!start.solution) {
return {};
}
start.cost = this.env.calcSolutionCost(start.solution);
this.openSet.push(start);
var cnt = 0;
while (this.openSet.length) {
cnt++;
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("loop");
// console.log("conflict:", conflict);
// console.log("open1:", this.openSet);
// console.log("close1:", this.closedSet);
//如果没有冲突
if (!conflict) {
console.log('cbs-cnt:', cnt);
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);
newNode.nc = this.env.calcNumOfConflicts(newNode.constraint_dict);
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
// tmpSet.reverse(); //逆序
var minNode;
var minCost = 99999;
for (var node of tmpSet) {
if (node.cost < minCost) {
minNode = node;
minCost = node.cost;
}
else if (node.cost == minCost) {
if (node.nc > minNode.nc) {
minNode = node; // 在复杂地图中能起一定作用
}
}
}
// tmpSet.reverse();
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;
}
}