View Javadoc

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  	 * Current focus of the bot.
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 	 * Returns current link the bot is following (if such link exist... may return null).
108 	 * @return
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 	 * If the path is not zero-length, recalls {@link IUT2004PathNavigator#newPath(List)}
124 	 * and set the path into the GB2004 via {@link SetRoute}.
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 	 * Sets the path into the GB2004 via {@link SetRoute} whenever switch occurs and the rest of the path is greater than
146 	 * 32 path elements.
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 	 * Returns how far is our target (path-distance).
201 	 * @return
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 }