View Javadoc

1   package cz.cuni.amis.pogamut.udk.agent.module.sensomotoric;
2   
3   import java.util.HashMap;
4   import java.util.Map;
5   import java.util.UUID;
6   import java.util.concurrent.Future;
7   import java.util.logging.Logger;
8   
9   import javax.vecmath.Vector3d;
10  
11  import cz.cuni.amis.pogamut.base.agent.module.SensomotoricModule;
12  import cz.cuni.amis.pogamut.base.communication.exception.CommunicationException;
13  import cz.cuni.amis.pogamut.base.communication.worldview.object.WorldObjectFuture;
14  import cz.cuni.amis.pogamut.udk.bot.IUDKBotController;
15  import cz.cuni.amis.pogamut.udk.bot.impl.UDKBot;
16  import cz.cuni.amis.pogamut.udk.communication.messages.gbcommands.AddRay;
17  import cz.cuni.amis.pogamut.udk.communication.messages.gbcommands.RemoveRay;
18  import cz.cuni.amis.pogamut.udk.communication.messages.gbinfomessages.AutoTraceRay;
19  import cz.cuni.amis.utils.flag.Flag;
20  import java.util.logging.Level;
21  
22  /**
23   * Support for creating rays used for raycasting (see {@link AutoTraceRay} that is being utilized).
24   * <p><p>
25   * It is designed to be initialized inside {@link IUDKBotController#initializeController(UDKBot)} method call
26   * and may be used since {@link IUDKBotController#botInitialized(cz.cuni.amis.pogamut.udk.communication.messages.gbinfomessages.GameInfo, cz.cuni.amis.pogamut.udk.communication.messages.gbinfomessages.ConfigChange, cz.cuni.amis.pogamut.udk.communication.messages.gbinfomessages.InitedMessage)}
27   * is called.
28   * @author ik
29   */
30  public class Raycasting extends SensomotoricModule<UDKBot> {
31  
32      Map<String, WorldObjectFuture<AutoTraceRay>> rayFutures = new HashMap<String, WorldObjectFuture<AutoTraceRay>>();
33      String idSuffix = null;
34      int counter = 0;
35      int alreadyInitialized = 0;
36      Flag<Boolean> allRaysInitialized = new Flag<Boolean>(false);
37      boolean listening = false;
38  
39      public Flag<Boolean> getAllRaysInitialized() {
40          return allRaysInitialized.getImmutable();
41      }
42  
43      public Raycasting(UDKBot bot) {
44          this(bot, null);
45      }
46      
47      public Raycasting(UDKBot bot, Logger log) {
48          super(bot, log);
49          idSuffix = "_" + bot.getName() + UUID.randomUUID().toString();
50      }
51      
52      /**
53  	 * Provides initialization of the module (clearing internal data structures). Called automatically
54  	 * during the agent starting sequence.
55  	 */
56      @Override
57      protected void start(boolean startPaused) {
58      	super.start(startPaused);
59      	clearDataStructures();
60      }
61      
62      /**
63       * Called from {@link Raycasting#start()} and {@link Raycasting#clear()} to reinit internal datas
64       * such as {@link Raycasting#rayFutures} that needs to be canceled out to remove listeners from the world view.
65       * 
66       */
67      private void clearDataStructures() {
68      	for (WorldObjectFuture<AutoTraceRay> future : rayFutures.values()) {
69          	future.cancel(false);
70          }
71          rayFutures.clear();
72          allRaysInitialized.setFlag(false);
73          alreadyInitialized = 0;
74          listening = false;
75      }
76  
77      /**
78       * Deletes all previous rays and makes this instance ready for setting up
79       * new rays.
80       */
81      public void clear() throws CommunicationException {
82          act.act(new RemoveRay("All"));
83          clearDataStructures();
84      }
85  
86      /**
87       * Once all rays were initialized using createRay(...) methods, call this
88       * method to start listening for response from UT.
89       */
90      public void endRayInitSequence() {
91          listening = true;
92          checkIfAllInited();
93      }
94  
95      /**
96       * Initializes ray usind AddRay command and returns future that waits for
97       * the first AutoTraceRay message corresponding to this ray.
98       * @param Id
99       * User set Id of the ray, so the ray can be identified.
100      * 
101      * @param Direction
102      * Vector direction of the ray (it will be relative - added to
103      * the vector, where the bot is looking, also takes into
104      * account angle of the floor the bot is standing on).
105      * 
106      * @param Length
107      * Specifies the length of the ray (in UT units).
108      * 
109      * @param FastTrace
110      * True if we want to use FastTrace function instead of Trace
111      * function (a bit faster but less information provided - just
112      * information if we hit something or not).
113      * 
114      * @param FloorCorrection
115      * If we should correct ray directions accoring floor normal. Note: Has issue - we can't set set rays up or down when correction is active.
116 	 * 
117      * @param TraceActors
118      * If we want to trace also actors – bots, monsters, players,
119      * items. False if we want to trace just level geometry.
120 	 * 
121      * @return
122      */
123     public Future<AutoTraceRay> createRay(
124             String Id, Vector3d Direction, int Length, boolean FastTrace, boolean FloorCorrection, boolean TraceActors) throws CommunicationException {
125         AddRay addRay = new AddRay(Id, Direction, Length, FastTrace, FloorCorrection, TraceActors);
126 
127         // create pointer to object that will be created in the future
128         WorldObjectFuture future = new WorldObjectFuture<AutoTraceRay>(worldView, Id, AutoTraceRay.class) {
129 
130             @Override
131             protected void customObjectEncounteredHook(AutoTraceRay obj) {
132                 alreadyInitialized++;
133                 checkIfAllInited();
134             }
135         };
136         rayFutures.put(Id, future);
137 
138         // send ray configuration command
139         act.act(addRay);
140         return future;
141     }
142 
143     /**
144      * Creates ray with system generated id. Note that the ray is not initialized immediately - we have to wait for GB2004 to 
145      * confirm us. Therefore you will not receive actual instance of {@link AutoTraceRay} but its {@link Future}.
146      * Use method {@link Future#isDone()} to check whether the ray was initialized and method {@link Future#get()} to obtain the ray instance.
147      * 
148      * @param Direction
149      * Vector direction of the ray (it will be relative - added to
150      * the vector, where the bot is looking, also takes into
151      * account angle of the floor the bot is standing on).
152 	 * 
153      * @param Length
154      * Specifies the length of the ray (in UT units).
155      * 
156      * @param FastTrace
157      * True if we want to use FastTrace function instead of Trace
158      * function (a bit faster but less information provided - just
159      * information if we hit something or not).
160      * 
161      * @param FloorCorrection
162      * If we should correct ray directions according floor normal. Note: Has issue - we can't set set rays up or down when correction is active.
163      * 
164      * @param TraceActors
165      * If we want to trace also actors, bots, monsters, players,
166      * items. False if we want to trace just level geometry.
167 	 * 
168      * @return ray's future - use method {@link Future#isDone()} to check whether the ray was initialized and method {@link Future#get()} to obtain the ray instance
169      * @throws cz.cuni.amis.pogamut.base.communication.exceptions.CommunicationException
170      */
171     public Future<AutoTraceRay> createRay(
172             Vector3d Direction, int Length, boolean FastTrace, boolean FloorCorrection, boolean TraceActors) throws CommunicationException {
173         String id = counter++ + idSuffix;
174         return createRay(id, Direction, Length, FastTrace, FloorCorrection, TraceActors);
175     }
176 
177     /**
178      * Returns a ray of specified id. If the ray of the specified id does not exist
179      * or was not initialized yet then it returns null.
180      * <p><p>
181      * Note that the {@link AutoTraceRay} instance is self updating - once obtained you may use it every
182      * logic cycle to obtain current readings from the ray.
183      * 
184      * @param rayID
185      * @return
186      */
187     public AutoTraceRay getRay(String rayID) {
188         try {
189         	Future<AutoTraceRay> ray = rayFutures.get(rayID);
190         	if (ray == null) return null;
191         	if (ray.isDone()) return ray.get();
192         	else return null;
193         } catch (Exception ex) {
194             if (log.isLoggable(Level.SEVERE)) log.severe(ex.getMessage());
195             return null;
196         }
197     }
198 
199     /**
200      * Sets {@link Raycasting#allRaysInitialized} flag to true if all rays has been initialized.
201      */
202     protected void checkIfAllInited() {
203         if (listening && rayFutures.size() == alreadyInitialized) {
204             allRaysInitialized.setFlag(true);
205         }
206     }
207     
208     
209 }
210