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.Logger;
6
7 import cz.cuni.amis.pogamut.base.agent.navigation.IPathFuture;
8 import cz.cuni.amis.pogamut.base.agent.navigation.impl.PathFuture;
9 import cz.cuni.amis.pogamut.base.communication.worldview.react.EventReact;
10 import cz.cuni.amis.pogamut.base.communication.worldview.react.EventReactOnce;
11 import cz.cuni.amis.pogamut.base.utils.math.DistanceUtils;
12 import cz.cuni.amis.pogamut.base3d.worldview.IVisionWorldView;
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.unreal.communication.messages.UnrealId;
16 import cz.cuni.amis.pogamut.ut2004.agent.navigation.floydwarshall.FloydWarshallMap;
17 import cz.cuni.amis.pogamut.ut2004.bot.impl.UT2004Bot;
18 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbcommands.GetPath;
19 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.EndMessage;
20 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.Item;
21 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.NavPoint;
22 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.NavPointNeighbourLink;
23 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.Self;
24 import cz.cuni.amis.pogamut.ut2004.communication.translator.shared.events.Path;
25 import cz.cuni.amis.utils.future.FutureStatus;
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40 public class UT2004AStarPathFuture extends PathFuture<ILocated> {
41
42 private static final int PATH_TIMEOUT = 10;
43
44 private static Object idMutex = new Object();
45
46 private static long lastId = 0;
47
48 private String pathId;
49
50 private EventReactOnce<Path> pathReaction;
51
52 private EventReact<EndMessage> endReaction;
53
54 private IVisionWorldView worldView;
55
56 private Logger log;
57
58 private Double startTime;
59
60 public UT2004AStarPathFuture(UT2004Bot bot, ILocated pathFrom, ILocated pathTo) {
61 super(pathFrom, pathTo, bot.getEventBus(), bot.getWorldView());
62 log = bot.getLogger().getCategory(this.getClass().getSimpleName());
63 synchronized(idMutex) {
64 pathId = "UT2004AStarPathFuture_" + (++lastId);
65 }
66 pathReaction = new EventReactOnce<Path>(Path.class, bot.getWorldView()){
67 @Override
68 protected void react(Path event) {
69 if (pathId.equals(event.getPathId())) {
70 eventPath(event);
71 }
72 }
73 };
74 endReaction = new EventReact<EndMessage>(EndMessage.class, bot.getWorldView()) {
75 @Override
76 protected void react(EndMessage event) {
77 eventEndMessage(event);
78 }
79 };
80 log.finer("Requesting path from '" + pathFrom + "' to '" + pathTo + "' under id '" + pathId + "'.");
81 bot.getAct().act(new GetPath().setLocation(pathTo.getLocation()).setId(pathId));
82 log.fine("Path requested, listening for the result (timeout " + PATH_TIMEOUT + "s)");
83 worldView = bot.getWorldView();
84 }
85
86 @Override
87 protected boolean cancelComputation(boolean mayInterruptIfRunning) {
88 pathReaction.disable();
89 endReaction.disable();
90 return getStatus() == FutureStatus.FUTURE_IS_BEING_COMPUTED;
91 }
92
93 protected void eventEndMessage(EndMessage event) {
94 if (startTime == null) startTime = event.getTime();
95 if (event.getTime() - startTime > PATH_TIMEOUT) {
96 pathReaction.disable();
97 endReaction.disable();
98 if (getStatus() == FutureStatus.FUTURE_IS_BEING_COMPUTED) {
99 computationException(new UT2004AStarPathTimeoutException("Path did not came from GB2004 in " + PATH_TIMEOUT + "s.", log, this));
100 }
101 }
102 }
103
104 protected void eventPath(Path event) {
105 endReaction.disable();
106 List<ILocated> result = new ArrayList<ILocated>(event.getPath().size());
107 ILocated last = null;
108 for (int i = 0; i < event.getPath().size(); ++i) {
109 UnrealId routeId = event.getPath().get(i).getRouteId();
110 NavPoint nav = (NavPoint) worldView.get(routeId);
111 if (nav == null) {
112 result.add(last = event.getPath().get(i).getLocation());
113 } else {
114 result.add(last = nav);
115 }
116 }
117
118 double distance;
119 if (last != null) {
120 distance = getPathTo().getLocation().getDistance(last.getLocation());
121 if (distance < 40) {
122
123 setResult(result);
124 return;
125 }
126 } else {
127 last = worldView.getSingle(Self.class).getLocation();
128 distance = getPathTo().getLocation().getDistance(last.getLocation());
129 }
130
131 double distance2D = getPathTo().getLocation().getDistance2D(last.getLocation());
132 double distanceZ = getPathTo().getLocation().getDistanceZ(last.getLocation());
133
134
135
136 ILocated pathTo = getPathTo();
137 NavPoint pathToNav =
138 pathTo instanceof NavPoint
139 ? (NavPoint)getPathTo()
140 : DistanceUtils.getNearest(worldView.getAll(NavPoint.class).values(), pathTo, 20);
141 if (pathToNav == null) {
142
143 Item pathToItem = DistanceUtils.getNearest(worldView.getAll(Item.class).values(), pathTo, 20);
144 if (pathToItem != null) {
145 pathToNav = pathToItem.getNavPoint();
146 }
147 }
148 NavPoint lastNav = last instanceof NavPoint ? (NavPoint) last : DistanceUtils.getNearest(worldView.getAll(NavPoint.class).values(), last, 20);
149
150 if (pathToNav != null) {
151
152 if (lastNav != null) {
153
154 NavPointNeighbourLink link = lastNav.getOutgoingEdges().get(pathToNav.getId());
155 if (link != null) {
156
157 if (FloydWarshallMap.isWalkable(link.getFlags())) {
158
159 result.add(pathTo);
160 setResult(result);
161 return;
162 } else {
163
164
165 setResult(result);
166
167 return;
168 }
169 } else {
170
171
172 setResult(result);
173 return;
174 }
175 }
176 }
177
178
179
180 if (distance2D < 100 &&
181 distanceZ < 200) {
182
183 result.add(pathTo);
184 setResult(result);
185 return;
186 }
187
188
189
190 setResult(result);
191 }
192
193 }