1 package cz.cuni.amis.pogamut.ut2004.agent.navigation;
2
3 import java.util.ArrayList;
4 import java.util.List;
5 import java.util.logging.Level;
6
7 import cz.cuni.amis.pogamut.base.agent.navigation.IPathExecutorState;
8 import cz.cuni.amis.pogamut.base.agent.navigation.IPathFuture;
9 import cz.cuni.amis.pogamut.base.agent.navigation.IStuckDetector;
10 import cz.cuni.amis.pogamut.base.communication.worldview.event.IWorldEventListener;
11 import cz.cuni.amis.pogamut.base.utils.logging.LogCategory;
12 import cz.cuni.amis.pogamut.base.utils.math.DistanceUtils;
13 import cz.cuni.amis.pogamut.base3d.worldview.object.ILocated;
14 import cz.cuni.amis.pogamut.base3d.worldview.object.Location;
15 import cz.cuni.amis.pogamut.ut2004.agent.module.sensor.AgentInfo;
16 import cz.cuni.amis.pogamut.ut2004.agent.navigation.floydwarshall.FloydWarshallMap;
17 import cz.cuni.amis.pogamut.ut2004.agent.navigation.loquenavigator.KefikRunner;
18 import cz.cuni.amis.pogamut.ut2004.agent.navigation.loquenavigator.LoqueNavigator;
19 import cz.cuni.amis.pogamut.ut2004.agent.navigation.stuckdetector.UT2004DistanceStuckDetector;
20 import cz.cuni.amis.pogamut.ut2004.agent.navigation.stuckdetector.UT2004PositionStuckDetector;
21 import cz.cuni.amis.pogamut.ut2004.agent.navigation.stuckdetector.UT2004TimeStuckDetector;
22 import cz.cuni.amis.pogamut.ut2004.bot.command.AdvancedLocomotion;
23 import cz.cuni.amis.pogamut.ut2004.bot.impl.UT2004Bot;
24 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.EndMessage;
25 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.Item;
26 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.NavPoint;
27 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.Player;
28 import cz.cuni.amis.utils.flag.FlagListener;
29
30
31
32
33
34
35 public class UT2004Navigation {
36
37
38 protected LogCategory log;
39
40 protected UT2004PathExecutor<ILocated> pathExecutor;
41
42 protected FloydWarshallMap fwMap;
43
44 protected UT2004Bot bot;
45
46 protected UT2004GetBackToNavGraph getBackToNavGraph;
47
48 protected UT2004RunStraight runStraight;
49
50 protected static final int NEW_PATH_DISTANCE_THRESHOLD = 40;
51
52 protected static final int ARRIVED_AT_LOCATION_XY_THRESHOLD = 50;
53
54 protected static final int ARRIVED_AT_LOCATION_Z_THRESHOLD = 100;
55
56 protected static final double PLAYER_DISTANCE_TRASHOLD = 600;
57
58 public static final double AT_PLAYER = 100;
59
60
61
62
63 FlagListener<IPathExecutorState> myUT2004PathExecutorStateListener = new FlagListener<IPathExecutorState>() {
64
65 @Override
66 public void flagChanged(IPathExecutorState changedValue) {
67 switch (changedValue.getState()) {
68 case TARGET_REACHED:
69 targetReached();
70 break;
71 case PATH_COMPUTATION_FAILED:
72 case STUCK:
73 stuck();
74 break;
75 }
76 }
77 };
78
79 protected IWorldEventListener<EndMessage> endMessageListener = new IWorldEventListener<EndMessage>() {
80 @Override
81 public void notify(EndMessage event) {
82 navigate();
83 }
84 };
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100 public UT2004Navigation(UT2004Bot bot, UT2004PathExecutor ut2004PathExecutor, FloydWarshallMap fwMap, UT2004GetBackToNavGraph getBackOnPath, UT2004RunStraight runStraight) {
101 this.log = bot.getLogger().getCategory(this.getClass().getSimpleName());
102 this.bot = bot;
103
104 this.fwMap = fwMap;
105 this.pathExecutor = ut2004PathExecutor;
106
107 this.getBackToNavGraph = getBackOnPath;
108 this.runStraight = runStraight;
109
110 initListeners();
111 }
112
113
114
115
116
117
118
119 public UT2004Navigation(UT2004Bot bot, AgentInfo info, AdvancedLocomotion move) {
120 this.log = bot.getLogger().getCategory(this.getClass().getSimpleName());
121 this.bot = bot;
122 this.fwMap = new FloydWarshallMap(bot);
123
124 this.pathExecutor =
125 new UT2004PathExecutor<ILocated>(
126 bot,
127 new LoqueNavigator<ILocated>(bot,
128 new KefikRunner(bot, info, move, bot.getLog()),
129 bot.getLog())
130 );
131
132
133
134
135 this.pathExecutor.addStuckDetector(new UT2004TimeStuckDetector(bot, 3000, 100000));
136 this.pathExecutor.addStuckDetector(new UT2004PositionStuckDetector(bot));
137 this.pathExecutor.addStuckDetector(new UT2004DistanceStuckDetector(bot));
138
139 this.getBackToNavGraph = new UT2004GetBackToNavGraph(bot, info, move);
140 this.runStraight = new UT2004RunStraight(bot, info, move);
141
142 initListeners();
143 }
144
145 private void initListeners() {
146 this.pathExecutor.getState().addListener(myUT2004PathExecutorStateListener);
147 bot.getWorldView().addEventListener(EndMessage.class, endMessageListener);
148 }
149
150
151
152
153
154
155
156
157
158 public boolean isNavigating() {
159 return pathExecutor.isExecuting();
160 }
161
162
163
164
165
166
167 public void setFocus(ILocated located) {
168 pathExecutor.setFocus(located);
169 getBackToNavGraph.setFocus(located);
170 runStraight.setFocus(located);
171 }
172
173
174
175
176
177
178 public void stopNavigation() {
179 reset(true);
180 }
181
182
183
184
185
186
187
188 public void navigate(ILocated target) {
189 if (target == null) {
190 if (log != null && log.isLoggable(Level.WARNING)) log.warning("Cannot navigate to NULL target!");
191 return;
192 }
193
194 if (target instanceof Player) {
195
196 navigate((Player)target);
197 return;
198 }
199
200 if (navigating) {
201 if (currentTarget == target || currentTarget.getLocation().equals(target.getLocation())) {
202
203 return;
204 }
205
206
207 reset(false);
208 }
209
210 if (log != null && log.isLoggable(Level.FINE)) log.fine("Start navigating to: " + target);
211
212 navigating = true;
213
214 currentTarget = target;
215
216 navigate();
217 }
218
219
220
221
222
223
224
225 public void navigate(Player player) {
226 if (player == null) {
227 if (log != null && log.isLoggable(Level.WARNING)) log.warning("Cannot navigate to NULL player!");
228 return;
229 }
230
231 if (navigating) {
232 if (currentTarget == player) {
233
234 return;
235 }
236
237
238 reset(false);
239 }
240
241 if (log != null && log.isLoggable(Level.FINE)) log.fine("Start pursuing: " + player);
242
243 navigating = true;
244
245 currentTarget = player.getLocation();
246
247 currentTargetPlayer = player;
248
249 navigate();
250 }
251
252
253
254
255
256
257
258 public NavPoint getNearestNavPoint(ILocated location) {
259 if (location instanceof NavPoint) return (NavPoint)location;
260 if (location instanceof Item) {
261 if (((Item)location).getNavPoint() != null) return ((Item)location).getNavPoint();
262 }
263 return DistanceUtils.getNearest(bot.getWorldView().getAll(NavPoint.class).values(), location);
264 }
265
266
267
268
269
270
271 public List<ILocated> getCurrentPathCopy() {
272 List<ILocated> result = new ArrayList();
273 if (currentFuturePath != null) {
274 result.addAll(currentFuturePath.get());
275 }
276 return result;
277 }
278
279
280
281
282
283
284
285
286 public List<ILocated> getCurrentPathDirect() {
287 if (currentFuturePath != null) {
288 return currentFuturePath.get();
289 }
290 return null;
291 }
292
293
294
295
296
297 public ILocated getCurrentTarget() {
298 return currentTarget;
299 }
300
301
302
303
304
305 public Player getCurrentTargetPlayer() {
306 return currentTargetPlayer;
307 }
308
309
310
311
312
313
314 public ILocated getLastTarget() {
315 return lastTarget;
316 }
317
318
319
320
321
322
323
324 public ILocated getLastTargetPlayer() {
325 return lastTarget;
326 }
327
328
329
330
331
332
333 protected ILocated lastTarget = null;
334
335 protected Player lastTargetPlayer = null;
336
337 protected ILocated currentTarget = null;
338
339 protected Player currentTargetPlayer = null;
340
341 protected NavPoint fromNavPoint;
342
343 protected NavPoint toNavPoint;
344
345 protected IPathFuture currentFuturePath;
346
347 protected boolean navigating = false;
348
349 protected boolean runningStraightToPlayer = false;
350
351 protected Location runningStraightToPlayerFailedAt = null;
352
353
354
355
356
357 protected void navigate() {
358 if (!navigating) return;
359
360 if (log != null && log.isLoggable(Level.FINE)) {
361 log.fine("NAVIGATING");
362 }
363 if (currentTargetPlayer != null) {
364 if (log != null && log.isLoggable(Level.FINE)) log.fine("Pursuing " + currentTargetPlayer);
365 navigatePlayer();
366 } else {
367 if (log != null && log.isLoggable(Level.FINE)) log.fine("Navigating to " + currentTarget);
368 navigateLocation();
369 }
370 }
371
372 private void navigateLocation() {
373 if (pathExecutor.isExecuting()) {
374
375 if (log != null && log.isLoggable(Level.FINE)) log.fine("Path executor running");
376 return;
377 }
378
379
380
381
382
383 if (!getBackToNavGraph.isOnNavGraph()) {
384
385
386 if (log != null && log.isLoggable(Level.FINE)) log.fine("Getting back to navigation graph");
387 getBackToNavGraph.execute();
388 return;
389 }
390
391
392
393 fromNavPoint = getNearestNavPoint(bot.getLocation());
394 toNavPoint = getNearestNavPoint(currentTarget);
395
396 if (log != null && log.isLoggable(Level.FINE)) log.fine("Running from " + fromNavPoint.getId().getStringId() + " to " + toNavPoint.getId().getStringId());
397
398 currentFuturePath = fwMap.computePath(fromNavPoint, toNavPoint);
399
400
401
402
403
404 processPathFuture(currentFuturePath);
405
406 pathExecutor.followPath(currentFuturePath);
407 }
408
409 private void navigatePlayer() {
410 double vDistance = bot.getLocation().getDistanceZ(currentTargetPlayer.getLocation());
411 double hDistance = bot.getLocation().getDistance2D(currentTargetPlayer.getLocation());
412
413 if (hDistance < AT_PLAYER && vDistance < 50) {
414
415 if (log != null && log.isLoggable(Level.FINE)) log.fine("Player reached");
416 if (pathExecutor.isExecuting()) {
417 pathExecutor.getPath().set(pathExecutor.getPath().size()-1, bot.getLocation());
418 } else {
419 targetReached();
420 }
421 return;
422 }
423
424 if (hDistance < 400 && Math.abs(vDistance) < 50) {
425
426 if (runningStraightToPlayer) {
427 if (runStraight.isFailed()) {
428 runningStraightToPlayer = false;
429 runningStraightToPlayerFailedAt = bot.getLocation();
430 }
431 } else {
432 if (runningStraightToPlayerFailedAt == null ||
433 bot.getLocation().getDistance(runningStraightToPlayerFailedAt) > 500
434 ){
435 if (getBackToNavGraph.isExecuting()) {
436 getBackToNavGraph.stop();
437 }
438 if (pathExecutor.isExecuting()) {
439 pathExecutor.stop();
440 }
441 runningStraightToPlayer = true;
442 runStraight.runStraight(currentTargetPlayer);
443 }
444 }
445 if (runningStraightToPlayer) {
446 if (log != null && log.isLoggable(Level.FINE)) log.fine("Running straight to player");
447 return;
448 }
449 } else {
450 if (runningStraightToPlayer) {
451 runningStraightToPlayer = false;
452 runStraight.stop();
453 }
454 }
455
456 if (pathExecutor.isExecuting()) {
457
458 if (log != null && log.isLoggable(Level.FINE)) log.fine("Path executor running");
459
460 double distance = currentTarget.getLocation().getDistance(currentTargetPlayer.getLocation());
461 if (distance > PLAYER_DISTANCE_TRASHOLD) {
462 if (log != null && log.isLoggable(Level.FINE)) log.fine("Player moved " + distance + " from its original location, checking path...");
463
464 NavPoint newToNavPoint = getNearestNavPoint(currentTargetPlayer);
465 if (newToNavPoint != toNavPoint) {
466
467 if (log != null && log.isLoggable(Level.FINE)) log.fine("Replanning path to get to " + currentTargetPlayer);
468
469 ILocated currentlyRunningTo = pathExecutor.getPathElement();
470 if (currentlyRunningTo == null) currentlyRunningTo = bot.getLocation();
471 fromNavPoint = getNearestNavPoint(currentlyRunningTo);
472 toNavPoint = newToNavPoint;
473 currentTarget = currentTargetPlayer.getLocation();
474
475 currentFuturePath = fwMap.computePath(fromNavPoint, toNavPoint);
476
477
478 processPathFuture(currentFuturePath);
479
480 pathExecutor.followPath(currentFuturePath);
481 } else {
482 if (log != null && log.isLoggable(Level.FINE)) log.fine("Path remains the same");
483 }
484 }
485
486 return;
487 }
488
489
490
491
492
493 if (!getBackToNavGraph.isOnNavGraph()) {
494
495
496 if (log != null && log.isLoggable(Level.FINE)) log.fine("Getting back to navigation graph");
497 getBackToNavGraph.execute();
498 return;
499 }
500
501
502
503 fromNavPoint = getNearestNavPoint(bot.getLocation());
504 toNavPoint = getNearestNavPoint(currentTarget);
505
506 if (log != null && log.isLoggable(Level.FINE)) log.fine("Running from " + fromNavPoint.getId().getStringId() + " to " + toNavPoint.getId().getStringId());
507
508 currentFuturePath = fwMap.computePath(fromNavPoint, toNavPoint);
509
510
511
512
513
514 processPathFuture(currentFuturePath);
515
516 pathExecutor.followPath(currentFuturePath);
517 }
518
519
520
521
522
523
524 protected void processPathFuture(IPathFuture futurePath) {
525 List<ILocated> pathList = futurePath.get();
526
527 if (pathList == null) {
528
529 return;
530 }
531
532 if (!pathList.isEmpty()) {
533 ILocated lastPathElement = pathList.get(pathList.size() - 1);
534 if (lastPathElement.getLocation().getDistance(currentTarget.getLocation()) > NEW_PATH_DISTANCE_THRESHOLD) {
535 currentFuturePath.get().add(currentTarget);
536 }
537 } else {
538 currentFuturePath.get().add(currentTarget);
539 }
540 }
541
542 protected void stuck() {
543
544 reset(true);
545 }
546
547 protected void targetReached() {
548
549 reset(true);
550 }
551
552 protected void reset(boolean stopGetBackToNavGraph) {
553 if (currentTarget != null) {
554 lastTarget = currentTarget;
555 lastTargetPlayer = currentTargetPlayer;
556 }
557
558 navigating = false;
559
560 currentTarget = null;
561 currentTargetPlayer = null;
562
563 fromNavPoint = null;
564 toNavPoint = null;
565
566 currentFuturePath = null;
567
568 runningStraightToPlayer = false;
569 runningStraightToPlayerFailedAt = null;
570
571
572 pathExecutor.stop();
573 runStraight.stop();
574 if (stopGetBackToNavGraph) getBackToNavGraph.stop();
575 }
576
577
578
579
580
581
582
583
584
585
586
587 public void addStrongNavigationListener(FlagListener<IPathExecutorState> listener) {
588 pathExecutor.getState().addStrongListener(listener);
589 }
590
591
592
593
594
595 public void removeStrongNavigationListener(FlagListener<IPathExecutorState> listener) {
596 pathExecutor.getState().removeListener(listener);
597 }
598
599
600
601
602
603 public List<IStuckDetector> getStuckDetectors() {
604 return pathExecutor.getStuckDetectors();
605 }
606
607
608
609
610
611 public void addStuckDetector(IStuckDetector stuckDetector) {
612 pathExecutor.addStuckDetector(stuckDetector);
613 }
614
615
616
617
618
619 public void removeStuckDetector(IStuckDetector stuckDetector) {
620 pathExecutor.removeStuckDetector(stuckDetector);
621 }
622
623 }