View Javadoc

1   package cz.cuni.amis.pogamut.udk.agent.navigation;
2   
3   import java.util.ArrayList;
4   import java.util.List;
5   import java.util.logging.Logger;
6   
7   import cz.cuni.amis.pogamut.base.agent.navigation.IPathFuture;
8   import cz.cuni.amis.pogamut.base.agent.navigation.impl.PathFuture;
9   import cz.cuni.amis.pogamut.base.communication.worldview.react.EventReact;
10  import cz.cuni.amis.pogamut.base.communication.worldview.react.EventReactOnce;
11  import cz.cuni.amis.pogamut.base3d.worldview.IVisionWorldView;
12  import cz.cuni.amis.pogamut.base3d.worldview.object.ILocated;
13  import cz.cuni.amis.pogamut.base3d.worldview.object.Location;
14  import cz.cuni.amis.pogamut.udk.bot.impl.UDKBot;
15  import cz.cuni.amis.pogamut.unreal.communication.messages.UnrealId;
16  import cz.cuni.amis.pogamut.udk.communication.messages.gbcommands.GetPath;
17  import cz.cuni.amis.pogamut.udk.communication.messages.gbinfomessages.EndMessage;
18  import cz.cuni.amis.pogamut.udk.communication.messages.gbinfomessages.NavPoint;
19  import cz.cuni.amis.pogamut.udk.communication.translator.shared.events.Path;
20  import cz.cuni.amis.utils.future.FutureStatus;
21  
22  /**
23   * {@link IPathFuture} implementation that is using UDK inner AStar algorithm for finding the path inside UDK
24   * environment. 
25   * <p><p>
26   * <b>WARNING:</b> UDK has a limition set on the path length. It will return only the first
27   * 16 navpoints that are leading to the path's target. Whenever path executor happens to tell you, that
28   * the target is reached, you should compare your bot current location with {@link UDKAStarPathFuture#getPathTo()}.
29   * <p><p>
30   * Note that the path that is produced by this future contains mix of {@link NavPoint} and {@link Location} objects.
31   * Usually {@link Location} objects are only the first and last elements of the path and the rest are {@link NavPoint}s.
32   * 
33   * @author Jimmy
34   */
35  public class UDKAStarPathFuture extends PathFuture<ILocated> {
36  
37  	private static final int PATH_TIMEOUT = 10;
38  
39  	private static Object idMutex = new Object();
40  	
41  	private static long lastId = 0;
42  	
43  	private String pathId;
44  	
45  	private EventReactOnce<Path> pathReaction;
46  	
47  	private EventReact<EndMessage> endReaction;
48  
49  	private IVisionWorldView worldView;
50  	
51  	private Logger log;
52  	
53  	private Double startTime;
54  
55  	public UDKAStarPathFuture(UDKBot bot, ILocated pathFrom, ILocated pathTo) {
56  		super(pathFrom, pathTo, bot.getEventBus(), bot.getWorldView());
57  		log = bot.getLogger().getCategory(this.getClass().getSimpleName());
58  		synchronized(idMutex) {
59  			pathId = "UDKAStarPathFuture_" + (++lastId);
60  		}
61  		pathReaction = new EventReactOnce<Path>(Path.class, bot.getWorldView()){
62  			@Override
63  			protected void react(Path event) {
64  				if (pathId.equals(event.getPathId())) {
65  					eventPath(event);
66  				}
67  			}			
68  		};
69  		endReaction = new EventReact<EndMessage>(EndMessage.class, bot.getWorldView()) {
70  			@Override
71  			protected void react(EndMessage event) {
72  				eventEndMessage(event);
73  			}		
74  		};
75  		log.finer("Requesting path from '" + pathFrom + "' to '" + pathTo + "' under id '" + pathId + "'.");
76  		bot.getAct().act(new GetPath().setLocation(pathTo.getLocation()).setId(pathId));
77  		log.fine("Path requested, listening for the result (timeout " + PATH_TIMEOUT + "s)");		
78  		worldView = bot.getWorldView();
79  	}
80  
81  	@Override
82  	protected boolean cancelComputation(boolean mayInterruptIfRunning) {
83  		pathReaction.disable();
84  		endReaction.disable();
85  		return getStatus() == FutureStatus.FUTURE_IS_BEING_COMPUTED;
86  	}
87  	
88  	protected void eventEndMessage(EndMessage event) {
89  		if (startTime == null) startTime = event.getTime();
90  		if (event.getTime() - startTime > PATH_TIMEOUT) {
91  			pathReaction.disable();
92  			endReaction.disable();
93  			if (getStatus() == FutureStatus.FUTURE_IS_BEING_COMPUTED) {
94  				computationException(new UDKAStarPathTimeoutException("Path did not came from GB2004 in " + PATH_TIMEOUT + "s.", log, this));
95  			}
96  		}
97  	}
98  
99  	protected void eventPath(Path event) {
100 		endReaction.disable();
101 		List<ILocated> result = new ArrayList<ILocated>(event.getPath().size());
102 		for (int i = 0; i < event.getPath().size(); ++i) {			
103 			UnrealId routeId = event.getPath().get(i).getRouteId();
104 			NavPoint nav = (NavPoint) worldView.get(routeId);
105 			if (nav == null) {
106 				result.add(event.getPath().get(i).getLocation());
107 			} else {
108 				result.add(nav);
109 			}
110 		}
111 		setResult(result);
112 	}
113 
114 }