1 package nl.tudelft.goal.ut2004.floydwarshall;
2
3
4 import java.util.ArrayList;
5 import java.util.HashMap;
6 import java.util.List;
7 import java.util.Map;
8 import java.util.logging.Level;
9 import java.util.logging.Logger;
10
11 import javax.vecmath.Point3d;
12
13 import cz.cuni.amis.pogamut.base.agent.navigation.IPathFuture;
14 import cz.cuni.amis.pogamut.base.agent.navigation.IPathPlanner;
15 import cz.cuni.amis.pogamut.base.agent.navigation.impl.PrecomputedPathFuture;
16 import cz.cuni.amis.pogamut.unreal.communication.messages.UnrealId;
17 import cz.cuni.amis.pogamut.ut2004.agent.module.sensor.NavigationGraphBuilder;
18 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.NavPoint;
19 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.NavPointNeighbourLink;
20 import cz.cuni.amis.pogamut.ut2004.communication.translator.shared.events.MapPointListObtained;
21 import cz.cuni.amis.pogamut.ut2004.utils.LinkFlag;
22 import cz.cuni.amis.utils.collections.MyCollections;
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46 public class FloydWarshallMap implements IPathPlanner<NavPoint> {
47
48 public static class PathMatrixNode {
49
50 private float distance = Float.POSITIVE_INFINITY;
51 private Integer viaNode = null;
52 private List<NavPoint> path = null;
53
54
55
56
57 public PathMatrixNode() {
58 }
59
60 public PathMatrixNode(float distance) {
61 this.distance = distance;
62 }
63
64 public float getDistance() {
65 return distance;
66 }
67
68 public void setDistance(float distance) {
69 this.distance = distance;
70 }
71
72
73
74
75
76
77 public Integer getViaNode() {
78 return viaNode;
79 }
80
81 public void setViaNode(Integer indice) {
82 this.viaNode = indice;
83 }
84
85 public List<NavPoint> getPath() {
86 return path;
87 }
88
89 public void setPath(List<NavPoint> path) {
90 this.path = path;
91 }
92
93 }
94
95
96
97
98 public static final int BAD_EDGE_FLAG = LinkFlag.FLY.get()
99 | LinkFlag.LADDER.get() | LinkFlag.PROSCRIBED.get()
100 | LinkFlag.SWIM.get() | LinkFlag.PLAYERONLY.get();
101
102 public static boolean isWalkable(int flag) {
103 return ((flag & BAD_EDGE_FLAG) == 0) && ((flag & LinkFlag.SPECIAL.get()) == 0);
104 }
105
106
107
108
109 protected int badEdgeFlag = 0;
110
111
112
113
114 protected Map<UnrealId, Integer> navPointIndices;
115
116
117
118
119
120
121
122
123 protected Map<Integer, NavPoint> indicesNavPoints;
124
125
126 protected PathMatrixNode[][] pathMatrix;
127
128
129
130
131 protected Object mutex = new Object();
132
133
134
135
136 private Logger log;
137
138 public FloydWarshallMap(Logger log) {
139 this(BAD_EDGE_FLAG, log);
140 }
141
142 public FloydWarshallMap(int badEdgeFlag, Logger log) {
143 this.badEdgeFlag = badEdgeFlag;
144 this.log = log;
145 }
146
147
148
149
150
151 public void refreshPathMatrix(List<NavPoint> navPoints) {
152 synchronized(mutex) {
153 if (log.isLoggable(Level.FINE)) log.fine(this + ": Refreshing path matrix...");
154 performFloydWarshall(navPoints);
155 if (log.isLoggable(Level.WARNING)) log.warning(this + ": Path matrix refreshed!");
156 }
157 }
158
159 protected void performFloydWarshall(MapPointListObtained map) {
160 List<NavPoint> navPoints = MyCollections.asList(map.getNavPoints().values());
161 performFloydWarshall(navPoints);
162 }
163
164 protected void performFloydWarshall(List<NavPoint> navPoints) {
165 if (log.isLoggable(Level.FINE)) log.fine(this + ": Beginning Floyd-Warshall algorithm...");
166 long start = System.currentTimeMillis();
167
168
169 int size = navPoints.size();
170 navPointIndices = new HashMap<UnrealId, Integer>(size);
171 indicesNavPoints = new HashMap<Integer, NavPoint>(size);
172 pathMatrix = new PathMatrixNode[size][size];
173
174
175 for (int i = 0; i < navPoints.size(); ++i) {
176 navPointIndices.put(navPoints.get(i).getId(), i);
177 indicesNavPoints.put(i, navPoints.get(i));
178 }
179
180
181 for (int i = 0; i < size; i++) {
182 for (int j = 0; j < size; j++) {
183 pathMatrix[i][j] = new PathMatrixNode((i == j) ? 0.0f
184 : Float.POSITIVE_INFINITY);
185 }
186 }
187
188
189 for (int i = 0; i < size; i++) {
190 Point3d location = navPoints.get(i).getLocation().getPoint3d();
191 for (NavPointNeighbourLink link : navPoints.get(i)
192 .getOutgoingEdges().values()) {
193 if (checkLink(link)) {
194 pathMatrix[i][navPointIndices.get(link.getToNavPoint()
195 .getId())].setDistance((float) location
196 .distance(link.getToNavPoint().getLocation()
197 .getPoint3d()));
198 }
199 }
200 }
201
202
203 for (int k = 0; k < size; k++) {
204 for (int i = 0; i < size; i++) {
205 for (int j = 0; j < size; j++) {
206 float newLen = pathMatrix[i][k].getDistance()
207 + pathMatrix[k][j].getDistance();
208 if (pathMatrix[i][j].getDistance() > newLen) {
209 pathMatrix[i][j].setDistance(newLen);
210 pathMatrix[i][j].setViaNode(k);
211 }
212 }
213 }
214 }
215
216
217 int count = 0;
218 for (int i = 0; i < size; i++) {
219 for (int j = 0; j < size; j++) {
220 if (pathMatrix[i][j].getDistance() == Float.POSITIVE_INFINITY) {
221 if (log.isLoggable(Level.FINER)) log.finer("Unreachable path from " + navPoints.get(i).getId().getStringId()
222 + " -> " + navPoints.get(j).getId().getStringId());
223 count++;
224 } else {
225
226 pathMatrix[i][j].setPath(retrievePath(i, j));
227 }
228 }
229 }
230
231 if (count > 0) {
232 if (log.isLoggable(Level.WARNING)) log.warning(this + ": There are " + count + " unreachable nav point pairs (if you wish to see more, set logging to Level.FINER).");
233 }
234
235 if (log.isLoggable(Level.INFO)) log.info(this + ": computation for " + size + " navpoints took " + (System.currentTimeMillis() - start) + " millis");
236
237
238 indicesNavPoints = null;
239 }
240
241
242
243
244
245
246
247
248
249
250 public boolean checkLink(NavPointNeighbourLink edge) {
251
252 if ((edge.getFlags() & badEdgeFlag) != 0)
253 return false;
254
255
256 if ((edge.getFlags() & LinkFlag.SPECIAL.get()) != 0)
257 return true;
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279 if (edge.getNeededJump() != null && edge.getNeededJump().z > 680) {
280 return false;
281 }
282
283
284 if (edge.getToNavPoint().isLiftJumpExit()) {
285 return false;
286 }
287
288 return true;
289 }
290
291
292
293
294
295
296
297
298
299
300
301
302 private List<NavPoint> retrievePathInner(Integer from, Integer to) {
303 PathMatrixNode node = pathMatrix[from][to];
304 if (node.getDistance() == Float.POSITIVE_INFINITY)
305 return null;
306 if (node.getViaNode() == null) {
307 return new ArrayList<NavPoint>(0);
308 }
309 if (node.getViaNode() == null)
310 return new ArrayList<NavPoint>(0);
311
312 List<NavPoint> path = new ArrayList<NavPoint>();
313 path.addAll(retrievePathInner(from, node.getViaNode()));
314 path.add(indicesNavPoints.get(node.getViaNode()));
315 path.addAll(retrievePathInner(node.getViaNode(), to));
316
317 return path;
318 }
319
320
321
322
323
324
325
326
327
328
329
330
331 private List<NavPoint> retrievePath(Integer from, Integer to) {
332 List<NavPoint> path = new ArrayList<NavPoint>();
333 path.add(indicesNavPoints.get(from));
334 path.addAll(retrievePathInner(from, to));
335 path.add(indicesNavPoints.get(to));
336 return path;
337 }
338
339 protected PathMatrixNode getPathMatrixNode(NavPoint np1, NavPoint np2) {
340 return pathMatrix[navPointIndices.get(np1.getId())][navPointIndices
341 .get(np2.getId())];
342 }
343
344
345
346
347
348
349
350
351
352
353
354 public boolean reachable(NavPoint from, NavPoint to) {
355 if ((from == null) || (to == null))
356 return false;
357 return getPathMatrixNode(from, to).getDistance() != Float.POSITIVE_INFINITY;
358 }
359
360
361
362
363
364
365
366
367
368 public float getDistance(NavPoint from, NavPoint to) {
369 if ((from == null) || (to == null))
370 return Float.POSITIVE_INFINITY;
371 return getPathMatrixNode(from, to).getDistance();
372 }
373
374
375
376
377
378
379
380
381
382
383
384
385 public List<NavPoint> getPath(NavPoint from, NavPoint to) {
386 synchronized(mutex) {
387 if ((from == null) || (to == null))
388 return null;
389 if (log.isLoggable(Level.FINE)) log.fine("Retrieving path: " + from.getId().getStringId() + "[" + from.getLocation() + "] -> " + to.getId().getStringId() + "[" + to.getLocation() + "]");
390 List<NavPoint> path = getPathMatrixNode(from, to).getPath();
391 if (path == null) {
392 if (log.isLoggable(Level.WARNING)) log.warning("PATH NOT EXIST: " + from.getId().getStringId() + "[" + from.getLocation() + "] -> " + to.getId().getStringId() + "[" + to.getLocation() + "]");
393 } else {
394 if (log.isLoggable(Level.FINE)) log.fine("Path exists - " + path.size() + " navpoints.");
395 }
396 return path;
397 }
398 }
399
400 protected void cleanUp() {
401 pathMatrix = null;
402 navPointIndices = null;
403 }
404
405 @Override
406 public String toString() {
407 return "FloydWarshallMap";
408 }
409
410
411
412
413
414
415
416
417
418
419
420
421 @Override
422 public IPathFuture<NavPoint> computePath(NavPoint from, NavPoint to) {
423 return new PrecomputedPathFuture<NavPoint>(from, to, getPath(from, to));
424 }
425
426
427 }