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