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 import java.util.logging.Logger;
7
8 import cz.cuni.amis.pogamut.base.agent.navigation.IPathExecutionEstimator;
9 import cz.cuni.amis.pogamut.base.agent.navigation.IStuckDetector;
10 import cz.cuni.amis.pogamut.base.agent.navigation.PathExecutorState;
11 import cz.cuni.amis.pogamut.base.agent.navigation.impl.BasePathExecutor;
12 import cz.cuni.amis.pogamut.base.communication.worldview.event.IWorldEventListener;
13 import cz.cuni.amis.pogamut.base.communication.worldview.object.IWorldObjectEventListener;
14 import cz.cuni.amis.pogamut.base.communication.worldview.object.event.WorldObjectFirstEncounteredEvent;
15 import cz.cuni.amis.pogamut.base.utils.DefaultPogamutPlatform;
16 import cz.cuni.amis.pogamut.base.utils.Pogamut;
17 import cz.cuni.amis.pogamut.base3d.worldview.object.ILocated;
18 import cz.cuni.amis.pogamut.unreal.agent.navigation.IUnrealPathExecutor;
19 import cz.cuni.amis.pogamut.ut2004.agent.navigation.loquenavigator.LoqueNavigator;
20 import cz.cuni.amis.pogamut.ut2004.agent.navigation.timeoutestimator.UT2004BasicTimeoutEstimator;
21 import cz.cuni.amis.pogamut.ut2004.bot.impl.UT2004Bot;
22 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbcommands.SetRoute;
23 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbcommands.Stop;
24 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.BotKilled;
25 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.EndMessage;
26 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.NavPointNeighbourLink;
27 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.Self;
28 import cz.cuni.amis.pogamut.ut2004.utils.PogamutUT2004Property;
29 import cz.cuni.amis.utils.NullCheck;
30
31 public class UT2004PathExecutor<PATH_ELEMENT extends ILocated> extends BasePathExecutor<PATH_ELEMENT> implements IUnrealPathExecutor<PATH_ELEMENT>, IUT2004PathExecutorHelper<PATH_ELEMENT> {
32
33 private IUT2004PathNavigator<PATH_ELEMENT> navigator;
34
35 private UT2004Bot bot;
36
37 private Self self;
38
39 private long pathExecutionStart = Long.MIN_VALUE;
40
41 private double pathExecutionTimeout = Double.POSITIVE_INFINITY;
42
43 private IWorldObjectEventListener<Self, WorldObjectFirstEncounteredEvent<Self>> selfListener = new IWorldObjectEventListener<Self, WorldObjectFirstEncounteredEvent<Self>>() {
44 @Override
45 public void notify(WorldObjectFirstEncounteredEvent<Self> event) {
46 self = event.getObject();
47 }
48 };
49
50 private IWorldEventListener<EndMessage> endMessageListener = new IWorldEventListener<EndMessage>() {
51 @Override
52 public void notify(EndMessage event) {
53 eventEndMessage();
54 }
55 };
56
57 private IWorldEventListener<BotKilled> botKilledListener = new IWorldEventListener<BotKilled>() {
58 @Override
59 public void notify(BotKilled event) {
60 stop();
61 }
62 };
63
64 private IPathExecutionEstimator<PATH_ELEMENT> timeoutEstimator;
65
66
67
68
69 private ILocated focus;
70
71 private Boolean sendingSetRoute = Pogamut.getPlatform().getBooleanProperty(PogamutUT2004Property.POGAMUT_UT2004_PATH_EXECUTOR_SEND_SET_ROUTE.getKey());
72
73 public UT2004PathExecutor(UT2004Bot bot) {
74 this(bot, null, null);
75 }
76
77 public UT2004PathExecutor(UT2004Bot bot, IUT2004PathNavigator<PATH_ELEMENT> navigator) {
78 this(bot, navigator, null);
79 }
80
81 public UT2004PathExecutor(UT2004Bot bot, IUT2004PathNavigator<PATH_ELEMENT> navigator, Logger log) {
82 super(log);
83 if (getLog() == null) {
84 setLog(bot.getLogger().getCategory(getClass().getSimpleName()));
85 }
86 NullCheck.check(bot, "bot");
87 if (sendingSetRoute == null) sendingSetRoute = false;
88 this.bot = bot;
89 this.navigator = navigator;
90 if (this.navigator == null) {
91 this.navigator = new LoqueNavigator<PATH_ELEMENT>(bot, getLog());
92 }
93 this.navigator.setBot(bot);
94 this.navigator.setExecutor(this);
95 bot.getWorldView().addObjectListener(Self.class, WorldObjectFirstEncounteredEvent.class, selfListener);
96 bot.getWorldView().addEventListener(EndMessage.class, endMessageListener);
97 bot.getWorldView().addEventListener(BotKilled.class, botKilledListener);
98 this.timeoutEstimator = new UT2004BasicTimeoutEstimator<PATH_ELEMENT>();
99 }
100
101 public UT2004PathExecutor<PATH_ELEMENT> setTimeoutEstimator(IPathExecutionEstimator<PATH_ELEMENT> timeoutEstimator) {
102 this.timeoutEstimator = timeoutEstimator;
103 return this;
104 }
105
106
107
108
109
110 public NavPointNeighbourLink getCurrentLink() {
111 return navigator.getCurrentLink();
112 }
113
114 @Override
115 protected void stopped() {
116 }
117
118 @Override
119 protected void followPathImpl() {
120 }
121
122
123
124
125
126 @Override
127 protected void pathComputedImpl() {
128 if (getPath().size() == 0) {
129 targetReached();
130 } else {
131 if (sendingSetRoute) {
132 bot.getAct().act(new SetRoute().setRoute(getPath()));
133 }
134 navigator.newPath(getPath());
135 pathExecutionStart = System.currentTimeMillis();
136 calculateTimeout();
137 }
138 }
139
140 @Override
141 protected void pathComputationFailedImpl() {
142 }
143
144
145
146
147
148 @Override
149 protected void switchToAnotherPathElementImpl() {
150 List<PATH_ELEMENT> path = getPath();
151 if (path == null) return;
152 if (path.size() > 31 + getPathElementIndex()) {
153 List<PATH_ELEMENT> pathPart = new ArrayList<PATH_ELEMENT>(32);
154 for (int i = getPathElementIndex(); i < path.size() && i < getPathElementIndex() + 31; ++i) {
155 pathPart.add(path.get(i));
156 }
157 bot.getAct().act(new SetRoute().setRoute(pathPart));
158 }
159
160 PATH_ELEMENT pathElement = getPathElement();
161 for (IStuckDetector detector : getStuckDetectors()) {
162 detector.setBotTarget(pathElement);
163 }
164 }
165
166 protected void calculateTimeout() {
167 IPathExecutionEstimator<PATH_ELEMENT> estimator = timeoutEstimator;
168 if (estimator != null) {
169 pathExecutionTimeout = estimator.getTimeout(getPath());
170 } else {
171 pathExecutionTimeout = Long.MAX_VALUE;
172 }
173
174 }
175
176 protected void eventEndMessage() {
177 if (inState(PathExecutorState.PATH_COMPUTED) || inState(PathExecutorState.SWITCHED_TO_ANOTHER_PATH_ELEMENT)) {
178 navigate();
179 }
180 }
181
182 protected void navigate() {
183 if (log != null && log.isLoggable(Level.FINER)) log.finer("navigating");
184 double timeDelta = System.currentTimeMillis() - pathExecutionStart;
185 if (timeDelta > pathExecutionTimeout) {
186 if (log != null && log.isLoggable(Level.WARNING)) log.finer("TIMEOUT! (" + pathExecutionTimeout + "ms)");
187 stuck();
188 return;
189 }
190 IStuckDetector detector = checkStuckDetectors();
191 if (detector != null) {
192 if (log != null && log.isLoggable(Level.WARNING)) log.warning(detector.getClass().getSimpleName() + " has reported that the bot has stuck");
193 stuck();
194 } else {
195 navigator.navigate(focus);
196 }
197 }
198
199
200
201
202
203 public double getRemainingDistance() {
204 double result = 0;
205
206 List<PATH_ELEMENT> path = getPath();
207
208 if (path == null) return 0;
209
210 int currPathIndex = getPathElementIndex();
211
212 if (currPathIndex >= path.size()) return 0;
213 if (currPathIndex < 0) currPathIndex = 0;
214
215 result += self.getLocation().getDistance(path.get(currPathIndex).getLocation());
216 ++currPathIndex;
217
218 for (int i = currPathIndex; i < path.size(); ++i) {
219 result += path.get(i-1).getLocation().getDistance(path.get(i).getLocation());
220 }
221
222 return result;
223 }
224
225 @Override
226 public ILocated getFocus() {
227 return this.focus;
228 }
229
230 @Override
231 public void setFocus(ILocated located) {
232 this.focus = located;
233 }
234
235 @Override
236 public List<IStuckDetector> getStuckDetectors() {
237 return stuckDetectors;
238 }
239
240 @Override
241 protected void preStuckImpl() {
242 super.preStuckImpl();
243 }
244
245 @Override
246 protected void stuckImpl() {
247 }
248
249 @Override
250 protected void stopImpl() {
251 super.stopImpl();
252 bot.getAct().act(new Stop());
253 }
254
255 @Override
256 protected void preTargetReachedImpl() {
257 super.preTargetReachedImpl();
258 }
259
260 @Override
261 protected void targetReachedImpl() {
262 }
263
264 }