View Javadoc

1   package cz.cuni.amis.pogamut.ut2004.agent.module.sensomotoric;
2   
3   import java.util.UUID;
4   import java.util.concurrent.Future;
5   import java.util.logging.Logger;
6   
7   import javax.vecmath.Vector3d;
8   
9   import cz.cuni.amis.pogamut.base.agent.module.SensomotoricModule;
10  import cz.cuni.amis.pogamut.base.communication.translator.event.IWorldObjectUpdateResult;
11  import cz.cuni.amis.pogamut.base.communication.translator.event.IWorldObjectUpdateResult.Result;
12  import cz.cuni.amis.pogamut.base.communication.translator.event.IWorldObjectUpdateResult.WorldObjectUpdateResult;
13  import cz.cuni.amis.pogamut.base.communication.translator.event.IWorldObjectUpdatedEvent;
14  import cz.cuni.amis.pogamut.base.communication.worldview.object.IWorldObject;
15  import cz.cuni.amis.pogamut.base.communication.worldview.object.IWorldObjectEventListener;
16  import cz.cuni.amis.pogamut.base.communication.worldview.object.WorldObjectId;
17  import cz.cuni.amis.pogamut.base.communication.worldview.object.event.WorldObjectUpdatedEvent;
18  import cz.cuni.amis.pogamut.base3d.worldview.object.Location;
19  import cz.cuni.amis.pogamut.unreal.communication.messages.UnrealId;
20  import cz.cuni.amis.pogamut.ut2004.agent.navigation.navmesh.LevelGeometry;
21  import cz.cuni.amis.pogamut.ut2004.agent.navigation.navmesh.LevelGeometryModule;
22  import cz.cuni.amis.pogamut.ut2004.agent.navigation.navmesh.NavMeshModule;
23  import cz.cuni.amis.pogamut.ut2004.bot.impl.UT2004Bot;
24  import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.AutoTraceRay;
25  import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.AutoTraceRayMessage;
26  import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.Self;
27  import java.util.HashMap;
28  import java.util.Map;
29  import java.util.Map.Entry;
30  
31  public class RaycastingBSP extends SensomotoricModule<UT2004Bot> {
32  	
33  	private LevelGeometryModule levelGeometryModule;
34  	
35      Map<String, BSPRayInfoContainer> rayInfoContainers = new HashMap<String, BSPRayInfoContainer>();
36      int counter = 0;
37      private String idSuffix;
38  
39      private IWorldObjectEventListener<Self, WorldObjectUpdatedEvent<Self>> selfListener = new IWorldObjectEventListener<Self, WorldObjectUpdatedEvent<Self>>() {
40  
41              @Override
42              public void notify(WorldObjectUpdatedEvent<Self> event) {
43                      selfUpdate(event.getObject());
44              }
45  
46      };
47  
48      /**
49       * Alternative contructor
50       * @param bot 
51       */
52      public RaycastingBSP(UT2004Bot bot, LevelGeometryModule levelGeometryModule) {
53          this(bot, levelGeometryModule, null);        
54      }
55      
56      /**
57       * Object's contructor
58       * @param bot
59       * @param log 
60       */
61      public RaycastingBSP(UT2004Bot bot, LevelGeometryModule levelGeometryModule, Logger log) {
62          super(bot, log);
63          
64          this.levelGeometryModule = levelGeometryModule;
65          
66          idSuffix = "_" + bot.getName() + UUID.randomUUID().toString();
67          
68          // listener for updating rays
69          bot.getWorldView().addObjectListener(Self.class, WorldObjectUpdatedEvent.class, selfListener);
70      }
71      
72      /**
73       * Whether we have BSP data for raycasting.
74       * @return
75       */
76      public boolean isUsable() {
77      	return levelGeometryModule != null && levelGeometryModule.isInitialized();
78      }
79  
80      /**
81       * Deletes all previous rays and makes this instance ready for setting up
82       * new rays.
83       */
84      public void clear() {
85          for(BSPRayInfoContainer rayInfo : rayInfoContainers.values()) {
86              if(rayInfo==null) continue;
87              UnrealId unrealId = rayInfo.unrealId;
88              if(unrealId==null) continue;
89              final AutoTraceRay ray = agent.getWorldView().get(unrealId, AutoTraceRay.class);
90              // LET'S DESTROY THE RAY INSIDE WORLDVIEW - IT WON'T BE ACCESSIBLE AGAIN!
91              agent.getWorldView().notifyImmediately( 				
92                      new IWorldObjectUpdatedEvent() {
93                                      @Override
94                                      public WorldObjectId getId() {
95                                              return ray.getId();
96                                      }
97                                      @Override
98                                      public IWorldObjectUpdateResult<IWorldObject> update(IWorldObject obj) {
99                                              return new WorldObjectUpdateResult<IWorldObject>(Result.DESTROYED, obj);
100                                     }
101                                     @Override
102                                     public long getSimTime() {
103                                             return ray.getSimTime();
104                                     }
105                     }
106             );                    
107         }        
108         rayInfoContainers.clear();
109     }
110 
111     public Future<AutoTraceRay> createRay(Vector3d direction, int length, boolean floorCorrection) {
112             String id = counter++ + idSuffix;
113             return createRay(id, direction, length, floorCorrection);
114     }
115 
116     /**
117      * This method creates a ray and puts it into worldview
118      * @param id
119      * @param direction
120      * @param length
121      * @param floorCorrection
122      * @return 
123      */
124     public Future<AutoTraceRay> createRay(String id, Vector3d direction, int length, boolean floorCorrection) {
125             
126             UnrealId unrealId = UnrealId.get(id);
127             BSPRayInfoContainer rayInfo = new BSPRayInfoContainer(unrealId, direction, length, floorCorrection);
128             rayInfoContainers.put(id, rayInfo);
129             // that's all for now. the ray will be put in worldview in selfUpdate()
130             selfUpdate(agent.getSelf());           
131             return null;
132     }
133 
134     /**
135      * gets all the rays from the hashmap, recomputes them and sends them to world view
136      * @param self 
137      */
138     protected void selfUpdate(Self self) {
139     	if (!isUsable()) return;
140         // RECOMPUTE AutoTraceRay(s)      
141         for(BSPRayInfoContainer rayInfo : rayInfoContainers.values()) {
142             AutoTraceRay ray = levelGeometryModule.getLevelGeometry().getAutoTraceRayMessage(self, rayInfo);
143             agent.getWorldView().notifyImmediately(ray);
144         }
145     }
146 
147     /**
148      * Returns a ray of specified id. If the ray of the specified id does not exist
149      * or was not initialized yet then it returns null.
150      * <p><p>
151      * Note that the {@link AutoTraceRay} instance is self updating - once obtained you may use it every
152      * logic cycle to obtain current readings from the ray.
153      * 
154      * @param rayID
155      * @return
156      */    
157     AutoTraceRay getRay(String rayID) {
158         BSPRayInfoContainer rayInfo = rayInfoContainers.get(rayID);
159         if(rayInfo==null) return null;
160         UnrealId unrealId = rayInfo.unrealId;
161         if(unrealId==null) return null;
162         AutoTraceRay ray = agent.getWorldView().get(unrealId, AutoTraceRay.class);
163         return ray;
164     }
165 
166 }