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 protected synchronized void connectEnvironment() throws ManagementException {
180 assert botParameters != null;
181 assert environmentParameters != null;
182
183
184 URI utServerURI = environmentParameters.getUTServer();
185 if (utServerURI != null) {
186 log.info("Connecting to the control server at " + utServerURI + " .");
187 utServerConnection.setUri(utServerURI);
188 } else {
189 log.info("No address for the ut control server was provided. The environment will not try to connect to the control server.");
190 }
191
192
193 List<BotParameters> agentParameters = new ArrayList<BotParameters>();
194 for (String name : environmentParameters.getBotNames()) {
195 BotParameters parameter = new BotParameters(botParameters, environmentLogger);
196 parameter.setAgentId(name);
197 agentParameters.add(parameter);
198 }
199
200
201 BotParameters[] agentParameterArray = new BotParameters[agentParameters.size()];
202 agentParameterArray = agentParameters.toArray(agentParameterArray);
203 startAgents(agentParameterArray);
204
205 }
206
207 protected abstract Class<? extends UT2004BotController> getControlerClass();
208
209 protected synchronized void startAgents(BotParameters... parameters) throws ManagementException {
210
211
212 if (getState() == EnvironmentState.KILLED) {
213 return;
214 }
215
216
217 IUT2004Server server = utServerConnection.getServerFlag().getFlag();
218 if (server != null) {
219 Pause resume = new Pause(false, false);
220 server.getAct().act(resume);
221
222 log.info("The server has been unpaused. Required to allow adding bots.");
223 } else {
224 log.warning("We are not connected to ut server and could not unpause the environment.");
225 }
226
227
228
229 for (BotParameters botParameters : parameters) {
230 botParameters.assignDefaults(this.botParameters);
231 }
232
233
234
235 UT2004BotRunner<UT2004Bot<IVisionWorldView, IAct, UT2004BotController>, UT2004BotParameters> runner = new UT2004BotRunner<UT2004Bot<IVisionWorldView, IAct, UT2004BotController>, UT2004BotParameters>(
236 getControlerClass(), Parameters.DEFAULT_NAME, Parameters.LOCAL_HOST, Parameters.BOT_SERVER_PORT);
237
238
239 runner.setLog(log);
240 List<UT2004Bot<IVisionWorldView, IAct, UT2004BotController>> agents;
241 try {
242 agents = runner.startAgents(parameters);
243 } catch (PogamutException e) {
244 throw new ManagementException(
245
246
247 "Pogmut was unable to start all agents. Cause: " + e.toString());
248 }
249
250
251 try {
252 for (UT2004Bot<IVisionWorldView, IAct, UT2004BotController> agent : agents) {
253 String simpleID = simplefyID(agent.getComponentId());
254 UT2004BotController controller = agent.getController();
255 registerEntity(simpleID, "bot", controller, createActionHandler(controller), createPerceptHandler(controller));
256 }
257 } catch (EntityException e) {
258
259
260 for (UT2004Bot<IVisionWorldView, IAct, UT2004BotController> agent : agents) {
261 agent.stop();
262 }
263
264 throw new ManagementException("Unable to register entity", e);
265 }
266
267
268 for (UT2004Bot<IVisionWorldView, IAct, UT2004BotController> agent : agents) {
269 String simpleID = simplefyID(agent.getComponentId());
270 agentDownListeners.put(simpleID, new AgentDownListener(simpleID, agent));
271 }
272
273
274 for (UT2004Bot<IVisionWorldView, IAct, UT2004BotController> agent : agents) {
275 if (agent.inState(IAgentStateDown.class)) {
276 String simpleID = simplefyID(agent.getComponentId());
277 agentDownListeners.get(simpleID).removeListener();
278 synchronizedDeleteEntity(simpleID);
279 }
280 }
281
282
283
284 }
285
286 protected abstract PerceptHandler createPerceptHandler(UT2004BotController controller ) throws EntityException;
287
288 protected abstract ActionHandler createActionHandler(UT2004BotController controller) throws EntityException;
289
290
291
292
293
294
295
296
297
298
299
300 private String simplefyID(IAgentId agentID) {
301 String token = agentID.getToken();
302 int index = token.lastIndexOf('/');
303
304 if (index < 0) {
305 log.severe("Could not find UUID seperator in Agent ID: " + token);
306 return token;
307
308 }
309
310 return token.substring(0, index);
311 }
312
313 protected void startEnvironment() throws ManagementException {
314
315 IUT2004Server server = utServerConnection.getServerFlag().getFlag();
316
317 if (server != null) {
318 Pause resume = new Pause(false, false);
319 server.getAct().act(resume);
320
321 log.info("The environment has been started.");
322 } else {
323 log.warning("We are not connected to ut server and could not start the environment.");
324 }
325 }
326
327 protected void pauseEvironment() {
328
329 IUT2004Server server = utServerConnection.getServerFlag().getFlag();
330
331 if (server != null) {
332 Pause pause = new Pause(true, false);
333 server.getAct().act(pause);
334 log.info("The environment has been paused.");
335 } else {
336 log.warning("We are not connected to ut server and could not pause the environment.");
337 }
338 }
339
340 protected synchronized void killEnvironment() {
341
342 IUT2004Server server = utServerConnection.getServerFlag().getFlag();
343 if (server != null) {
344 Pause resume = new Pause(false, false);
345 server.getAct().act(resume);
346
347 log.info("The environment has been unpaused.");
348 } else {
349 log.warning("We are not connected to ut server and could not unpause the environment.");
350 }
351
352
353 for (String id : getEntities()) {
354 @SuppressWarnings("unchecked")
355 UT2004BotController<UT2004Bot> controller = ((UT2004BotController<UT2004Bot>) getEntity(id));
356 UT2004Bot bot = controller.getBot();
357
358 try {
359 agentDownListeners.get(id).removeListener();
360 bot.stop();
361 log.info(bot.getName() + " has been stopped");
362 } catch (AgentException e) {
363
364 log.info(bot.getName() + " has been killed", e);
365 }
366 }
367
368
369 utServerConnection.stopServer();
370
371
372 botParameters = null;
373 environmentParameters = null;
374
375
376 Pogamut.getPlatform().close();
377 }
378
379
380
381
382
383
384
385
386 protected synchronized void synchronizedDeleteEntity(String name) {
387 try {
388 deleteEntity(name);
389 } catch (RelationException e) {
390
391 log.severe("Could not delete entity " + name);
392 } catch (EntityException e) {
393
394
395 log.severe("Could not delete entity " + name + ", it was already deleted.");
396 }
397 }
398
399
400
401
402
403
404
405
406 private class AgentDownListener implements FlagListener<IAgentState> {
407
408 private final String key;
409 private final UT2004Bot agent;
410
411 public AgentDownListener(String key, UT2004Bot agent) {
412 this.key = key;
413 this.agent = agent;
414 this.agent.getState().addStrongListener(this);
415 }
416
417 @Override
418 public void flagChanged(IAgentState state) {
419 if (state instanceof IAgentStateDown) {
420 removeListener();
421 synchronizedDeleteEntity(key);
422 }
423 }
424
425 public void removeListener() {
426 agent.getState().removeListener(this);
427 agentDownListeners.remove(key);
428 }
429 }
430
431 @Override
432 protected boolean isSupportedByEnvironment(Action arg0) {
433 return true;
434 }
435
436 @Override
437 protected boolean isSupportedByType(Action arg0, String arg1) {
438 return true;
439 }
440
441 }