1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package nl.tudelft.goal.unreal.environment;
21
22 import java.net.URI;
23 import java.util.ArrayList;
24 import java.util.HashMap;
25 import java.util.List;
26 import java.util.Map;
27
28 import nl.tudelft.goal.unreal.messages.BotParameters;
29 import nl.tudelft.goal.unreal.messages.EnvironmentParameters;
30 import nl.tudelft.goal.unreal.messages.Parameters;
31 import nl.tudelft.goal.unreal.translators.AgentIdTranslator;
32 import nl.tudelft.goal.unreal.translators.LevelTranslator;
33 import nl.tudelft.goal.unreal.translators.LocationTranslator;
34 import nl.tudelft.goal.unreal.translators.RotationTranslator;
35 import nl.tudelft.goal.unreal.translators.SkinTranslator;
36 import nl.tudelft.goal.unreal.translators.StringListTranslator;
37 import nl.tudelft.goal.unreal.translators.TeamTranslator;
38 import nl.tudelft.goal.unreal.translators.URITranslator;
39 import nl.tudelft.pogamut.base.server.ReconnectingServerDefinition;
40 import nl.tudelft.pogamut.ut2004.server.UTServerDefinition;
41 import cz.cuni.amis.pogamut.base.agent.IAgentId;
42 import cz.cuni.amis.pogamut.base.agent.exceptions.AgentException;
43 import cz.cuni.amis.pogamut.base.agent.impl.AgentId;
44 import cz.cuni.amis.pogamut.base.agent.state.level0.IAgentState;
45 import cz.cuni.amis.pogamut.base.agent.state.level1.IAgentStateDown;
46 import cz.cuni.amis.pogamut.base.communication.command.IAct;
47 import cz.cuni.amis.pogamut.base.component.IComponent;
48 import cz.cuni.amis.pogamut.base.utils.Pogamut;
49 import cz.cuni.amis.pogamut.base.utils.logging.AgentLogger;
50 import cz.cuni.amis.pogamut.base.utils.logging.IAgentLogger;
51 import cz.cuni.amis.pogamut.base.utils.logging.LogCategory;
52 import cz.cuni.amis.pogamut.base3d.worldview.IVisionWorldView;
53 import cz.cuni.amis.pogamut.ut2004.bot.impl.UT2004Bot;
54 import cz.cuni.amis.pogamut.ut2004.bot.impl.UT2004BotController;
55 import cz.cuni.amis.pogamut.ut2004.bot.params.UT2004BotParameters;
56 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbcommands.Pause;
57 import cz.cuni.amis.pogamut.ut2004.server.IUT2004Server;
58 import cz.cuni.amis.pogamut.ut2004.utils.UT2004BotRunner;
59 import cz.cuni.amis.utils.exception.PogamutException;
60 import cz.cuni.amis.utils.flag.FlagListener;
61 import eis.eis2java.environment.AbstractEnvironment;
62 import eis.eis2java.handlers.ActionHandler;
63 import eis.eis2java.handlers.PerceptHandler;
64 import eis.eis2java.translation.Translator;
65 import eis.exceptions.EntityException;
66 import eis.exceptions.ManagementException;
67 import eis.exceptions.RelationException;
68 import eis.iilang.Action;
69 import eis.iilang.EnvironmentState;
70 import eis.iilang.Parameter;
71
72 @SuppressWarnings("rawtypes")
73 public abstract class AbstractUnrealEnvironment extends SimpleTransitioningEnvironment implements IComponent {
74
75
76
77
78 private static final long serialVersionUID = 6786623950045095814L;
79 protected final IAgentId id;
80
81
82 protected final IAgentLogger environmentLogger;
83
84 protected final LogCategory log;
85
86
87 private final Map<String, AgentDownListener> agentDownListeners;
88
89
90 protected BotParameters botParameters;
91 protected EnvironmentParameters environmentParameters;
92
93
94 private ReconnectingServerDefinition<IUT2004Server> utServerConnection;
95
96
97
98
99
100
101 public AbstractUnrealEnvironment() {
102 id = new AgentId(getName());
103 agentDownListeners = new HashMap<String, AgentDownListener>();
104 environmentLogger = new AgentLogger(id);
105 environmentLogger.addDefaultConsoleHandler();
106 log = environmentLogger.getCategory(this);
107 log.info("Environment has been created.");
108 log.addConsoleHandler();
109
110
111 Translator translator = Translator.getInstance();
112 translator.registerParameter2JavaTranslator(new AgentIdTranslator());
113 translator.registerParameter2JavaTranslator(new LevelTranslator());
114 translator.registerParameter2JavaTranslator(new SkinTranslator());
115 translator.registerParameter2JavaTranslator(new StringListTranslator());
116 translator.registerParameter2JavaTranslator(new TeamTranslator());
117 translator.registerParameter2JavaTranslator(new URITranslator());
118 translator.registerParameter2JavaTranslator(new LocationTranslator());
119 translator.registerParameter2JavaTranslator(new RotationTranslator());
120
121
122 registerTranslators();
123 }
124
125 protected abstract void registerTranslators();
126
127
128
129
130
131 @Override
132 public IAgentId getComponentId() {
133 return id;
134 }
135
136
137
138
139
140
141
142 @Override
143 public String toString() {
144 return simplefyID(getComponentId());
145 }
146
147 public String getName() {
148 return "UnrealGoal Environment for EIS" + requiredVersion();
149 }
150
151 protected synchronized void initializeEnvironment(Map<String, Parameter> parameters) throws ManagementException {
152 assert botParameters == null;
153 assert environmentParameters == null;
154
155 try {
156 botParameters = new BotParameters(parameters, environmentLogger);
157 environmentParameters = new EnvironmentParameters(parameters, environmentLogger);
158 } catch (UnrealEnvironmentException e) {
159
160 botParameters = null;
161 environmentParameters = null;
162
163 log.severe("Invalid parameters: " + e);
164 throw new ManagementException("Invalid parameters.", e);
165 }
166
167
168 environmentParameters.assignDefaults(EnvironmentParameters.getDefaults(environmentLogger));
169 botParameters.assignDefaults(BotParameters.getDefaults(environmentLogger));
170
171
172
173 log.setLevel(environmentParameters.getLogLevel());
174
175
176 utServerConnection = new ReconnectingServerDefinition<IUT2004Server>(new UTServerDefinition());
177 }
178
179
180 protected synchronized void connectEnvironment() throws ManagementException {
181 assert botParameters != null;
182 assert environmentParameters != null;
183
184
185 URI utServerURI = environmentParameters.getUTServer();
186 if (utServerURI != null) {
187 log.info("Connecting to the control server at " + utServerURI + " .");
188 utServerConnection.setUri(utServerURI);
189 } else {
190 log.info("No address for the ut control server was provided. The environment will not try to connect to the control server.");
191 }
192
193
194 List<BotParameters> agentParameters = new ArrayList<BotParameters>();
195 for (String name : environmentParameters.getBotNames()) {
196 BotParameters parameter = new BotParameters(botParameters, environmentLogger);
197 parameter.setAgentId(name);
198 agentParameters.add(parameter);
199 }
200
201
202 BotParameters[] agentParameterArray = new BotParameters[agentParameters.size()];
203 agentParameterArray = agentParameters.toArray(agentParameterArray);
204 startAgents(agentParameterArray);
205
206 }
207
208 protected abstract Class<? extends UT2004BotController> getControlerClass();
209
210 protected synchronized void startAgents(BotParameters... parameters) throws ManagementException {
211
212
213 if (getState() == EnvironmentState.KILLED) {
214 return;
215 }
216
217
218 IUT2004Server server = utServerConnection.getServerFlag().getFlag();
219 if (server != null) {
220 Pause resume = new Pause(false, false);
221 server.getAct().act(resume);
222
223 try {
224 Thread.sleep(1000);
225 } catch (InterruptedException e) {
226 throw new ManagementException("Interupted while waiting for server to unpause",e );
227
228 }
229
230 log.info("The server has been unpaused. Required to allow adding bots.");
231 } else {
232 log.warning("We are not connected to ut server and could not unpause the environment.");
233 }
234
235
236
237 for (BotParameters botParameters : parameters) {
238 botParameters.assignDefaults(this.botParameters);
239 }
240
241
242
243 UT2004BotRunner<UT2004Bot<IVisionWorldView, IAct, UT2004BotController>, UT2004BotParameters> runner = new UT2004BotRunner<UT2004Bot<IVisionWorldView, IAct, UT2004BotController>, UT2004BotParameters>(
244 getControlerClass(), Parameters.DEFAULT_NAME, Parameters.LOCAL_HOST, Parameters.BOT_SERVER_PORT);
245 runner.setLogLevel(environmentParameters.getLogLevel());
246
247
248
249 List<UT2004Bot<IVisionWorldView, IAct, UT2004BotController>> agents;
250 try {
251 agents = runner.startAgents(parameters);
252 } catch (PogamutException e) {
253 throw new ManagementException(
254
255
256 "Pogmut was unable to start all agents. Cause: " + e.toString());
257 }
258
259
260 try {
261 for (UT2004Bot<IVisionWorldView, IAct, UT2004BotController> agent : agents) {
262 String simpleID = simplefyID(agent.getComponentId());
263 UT2004BotController controller = agent.getController();
264 registerEntity(simpleID, "bot", controller, createActionHandler(controller), createPerceptHandler(controller));
265 }
266 } catch (EntityException e) {
267
268
269 for (UT2004Bot<IVisionWorldView, IAct, UT2004BotController> agent : agents) {
270 agent.stop();
271 }
272
273 throw new ManagementException("Unable to register entity", e);
274 }
275
276
277 for (UT2004Bot<IVisionWorldView, IAct, UT2004BotController> agent : agents) {
278 String simpleID = simplefyID(agent.getComponentId());
279 agentDownListeners.put(simpleID, new AgentDownListener(simpleID, agent));
280 }
281
282
283 for (UT2004Bot<IVisionWorldView, IAct, UT2004BotController> agent : agents) {
284 if (agent.inState(IAgentStateDown.class)) {
285 String simpleID = simplefyID(agent.getComponentId());
286 agentDownListeners.get(simpleID).removeListener();
287 synchronizedDeleteEntity(simpleID);
288 }
289 }
290
291
292
293 }
294
295 protected abstract PerceptHandler createPerceptHandler(UT2004BotController controller ) throws EntityException;
296
297 protected abstract ActionHandler createActionHandler(UT2004BotController controller) throws EntityException;
298
299
300
301
302
303
304
305
306
307
308
309 private String simplefyID(IAgentId agentID) {
310 String token = agentID.getToken();
311 int index = token.lastIndexOf('/');
312
313 if (index < 0) {
314 log.severe("Could not find UUID seperator in Agent ID: " + token);
315 return token;
316
317 }
318
319 return token.substring(0, index);
320 }
321
322 protected void startEnvironment() throws ManagementException {
323
324 IUT2004Server server = utServerConnection.getServerFlag().getFlag();
325
326 if (server != null) {
327 Pause resume = new Pause(false, false);
328 server.getAct().act(resume);
329
330 log.info("The environment has been started.");
331 } else {
332 log.warning("We are not connected to ut server and could not start the environment.");
333 }
334 }
335
336 protected void pauseEvironment() {
337
338 IUT2004Server server = utServerConnection.getServerFlag().getFlag();
339
340 if (server != null) {
341 Pause pause = new Pause(true, false);
342 server.getAct().act(pause);
343 log.info("The environment has been paused.");
344 } else {
345 log.warning("We are not connected to ut server and could not pause the environment.");
346 }
347 }
348
349 protected synchronized void killEnvironment() {
350
351 IUT2004Server server = utServerConnection.getServerFlag().getFlag();
352 if (server != null) {
353 Pause resume = new Pause(false, false);
354 server.getAct().act(resume);
355
356 log.info("The environment has been unpaused.");
357 } else {
358 log.warning("We are not connected to ut server and could not unpause the environment.");
359 }
360
361
362 for (String id : getEntities()) {
363 @SuppressWarnings("unchecked")
364 UT2004BotController<UT2004Bot> controller = ((UT2004BotController<UT2004Bot>) getEntity(id));
365 UT2004Bot bot = controller.getBot();
366
367 try {
368 agentDownListeners.get(id).removeListener();
369 bot.stop();
370 log.info(bot.getName() + " has been stopped");
371 } catch (AgentException e) {
372
373 log.info(bot.getName() + " has been killed", e);
374 }
375 }
376
377
378 utServerConnection.stopServer();
379
380
381 botParameters = null;
382 environmentParameters = null;
383
384
385 Pogamut.getPlatform().close();
386 }
387
388
389
390
391
392
393
394
395 protected synchronized void synchronizedDeleteEntity(String name) {
396 try {
397 deleteEntity(name);
398 } catch (RelationException e) {
399
400 log.severe("Could not delete entity " + name);
401 } catch (EntityException e) {
402
403
404 log.severe("Could not delete entity " + name + ", it was already deleted.");
405 }
406 }
407
408
409
410
411
412
413
414
415 private class AgentDownListener implements FlagListener<IAgentState> {
416
417 private final String key;
418 private final UT2004Bot agent;
419
420 public AgentDownListener(String key, UT2004Bot agent) {
421 this.key = key;
422 this.agent = agent;
423 this.agent.getState().addStrongListener(this);
424 }
425
426 @Override
427 public void flagChanged(IAgentState state) {
428 if (state instanceof IAgentStateDown) {
429 removeListener();
430 synchronizedDeleteEntity(key);
431 }
432 }
433
434 public void removeListener() {
435 agent.getState().removeListener(this);
436 agentDownListeners.remove(key);
437 }
438 }
439
440 @Override
441 protected boolean isSupportedByEnvironment(Action arg0) {
442 return true;
443 }
444
445 @Override
446 protected boolean isSupportedByType(Action arg0, String arg1) {
447 return true;
448 }
449
450 }