1   package Steerings;
2   
3   import SocialSteeringsBeta.RefLocation;
4   import SteeringStuff.SteeringManager;
5   import SteeringStuff.SteeringTools;
6   import SteeringStuff.RefBoolean;
7   import SteeringStuff.ISteering;
8   
9   import java.util.List;
10  
11  import javax.vecmath.Tuple3d;
12  import javax.vecmath.Vector2d;
13  import javax.vecmath.Vector3d;
14  
15  import SteeringProperties.PathFollowingProperties;
16  import SteeringProperties.SteeringProperties;
17  import cz.cuni.amis.pogamut.base.agent.navigation.IPathFuture;
18  import cz.cuni.amis.pogamut.base3d.worldview.object.ILocated;
19  import cz.cuni.amis.pogamut.base3d.worldview.object.Location;
20  import cz.cuni.amis.pogamut.ut2004.bot.impl.UT2004Bot;
21  import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.ConfigChange;
22  import cz.cuni.amis.utils.future.FutureStatus;
23  
24  
25  
26  
27  
28  
29  public class PathFollowingSteer implements ISteering {
30  
31      
32      private UT2004Bot botself;
33  
34      
35  
36      private int repulsiveForce;
37      
38      int distanceFromThePath;
39      
40      IPathFuture<ILocated> pathFuture;
41      
42      List<ILocated> path;
43      
44      double regulatingForce;
45      
46      private int projection;
47  
48      private static int NEARLY_THERE_DISTANCE = 150;
49      
50      
51      Location previousLocation;
52      
53      Location nextLocation;
54      
55      int actualIndex;
56      
57      double lastDistanceFromNextLocation;
58      
59      boolean newPath;
60  
61      private static boolean ZERO_DISTANCE = false;
62      
63  
64      
65  
66  
67  
68      public PathFollowingSteer(UT2004Bot bot) {
69          botself = bot;
70          actualIndex = 0;
71      }
72  
73      
74  
75  
76      @Override
77      public Vector3d run(Vector3d scaledActualVelocity, RefBoolean wantsToGoFaster, RefBoolean wantsToStop, RefLocation focus) {
78          Vector3d nextVelocity;
79          Vector3d actualVelocity = botself.getVelocity().getVector3d();
80          Location pointHeading;
81          Vector3d pointHeadingToFoot;
82          double distanceFromNextLocation;
83  
84          nextVelocity = new Vector3d(0,0,0);
85  
86          if (pathFuture == null) {
87              if (SteeringManager.DEBUG) System.out.println("path null");
88              return new Vector3d(0,0,0);
89          } 
90  
91          if (!newPath && pathFuture.getStatus() != FutureStatus.FUTURE_IS_READY) {
92              if (SteeringManager.DEBUG) System.out.println("path not ready");
93              return new Vector3d(0,0,0);
94          }
95  
96          if (newPath && pathFuture.getStatus() == FutureStatus.FUTURE_IS_READY) {
97              if (!setComputedPath()) {
98                  if (SteeringManager.DEBUG) System.out.println("path null or zero length");
99                  return new Vector3d(0,0,0);
100             }
101         }
102 
103         if (path == null) {
104             if (!setComputedPath()) {
105                 if (SteeringManager.DEBUG) System.out.println("path null or zero length");
106                 botself.getLog().warning("Received path is null / 0-sized");
107                 return new Vector3d(0,0,0);
108             }
109         }
110 
111         
112         
113         boolean shifted = shiftNextLocation();
114         if (nextLocation == null) {
115             if (SteeringManager.DEBUG) System.out.println("null next location");
116             return new Vector3d(0, 0, 0);            
117         }
118         distanceFromNextLocation = botself.getLocation().getDistance(nextLocation);
119 
120         
121         if (ZERO_DISTANCE) {
122             if (shifted) {
123                 
124                 if (actualIndex + 1 >= path.size()) {
125                     
126                     if (distanceFromNextLocation <= NEARLY_THERE_DISTANCE) {
127                         wantsToStop.setValue(true);
128                         if (SteeringManager.DEBUG) System.out.println("We reached the target point of the path.");
129                     }
130                     return nextVelocity;
131                 }
132             }
133             Location botsLoc = botself.getLocation();
134             Vector3d toNextLoc = new Vector3d(nextLocation.x - botsLoc.x, nextLocation.y - botsLoc.y, nextLocation.z - botsLoc.z);
135             toNextLoc.normalize();
136             toNextLoc.scale(repulsiveForce);
137             nextVelocity.add(toNextLoc);
138             return nextVelocity;
139         }
140         
141 
142         if (!shifted) {
143             if (lastDistanceFromNextLocation < distanceFromNextLocation) {
144                 lastDistanceFromNextLocation = distanceFromNextLocation;
145                 if (SteeringManager.DEBUG) System.out.println("Jdeme na spatnou stranu!");
146                 
147 
148                 Vector3d rightDirectionForce = new Vector3d(nextLocation.x - previousLocation.x, nextLocation.y - previousLocation.y, 0);
149                 rightDirectionForce.normalize();
150                 if (SteeringManager.DEBUG) System.out.println("Od správného směru jsme se odchýlili o "+rightDirectionForce.angle(botself.getVelocity().getVector3d()));
151                 double scale = rightDirectionForce.angle(botself.getVelocity().getVector3d())/Math.PI;
152                 rightDirectionForce.scale(repulsiveForce*scale);
153                 nextVelocity.add((Tuple3d) rightDirectionForce);
154                 wantsToGoFaster.setValue(false);
155                 return nextVelocity;
156             } else {
157                 lastDistanceFromNextLocation = distanceFromNextLocation;
158             }
159         } else {
160             lastDistanceFromNextLocation = distanceFromNextLocation;
161             if (actualIndex + 1 >= path.size()) {
162                 
163                 if (distanceFromNextLocation <= NEARLY_THERE_DISTANCE) {
164                     wantsToStop.setValue(true);
165                     
166                     if (SteeringManager.DEBUG) System.out.println("We reached the target point of the path.");
167                 } else {
168                     Vector3d botToNextLocation = new Vector3d(nextLocation.x - botself.getLocation().x, nextLocation.y - botself.getLocation().y, nextLocation.z - botself.getLocation().z);
169                     botToNextLocation.scale(actualVelocity.length() / botToNextLocation.length());
170                     nextVelocity.add((Tuple3d) botToNextLocation);
171                     if (SteeringManager.DEBUG) System.out.println("We must go to the target point.");
172                 }
173                 return nextVelocity;
174             }
175         }
176 
177         
178         ConfigChange cc = botself.getWorldView().getSingle(ConfigChange.class);
179         double oneTick = cc.getVisionTime();    
180 
181         double projectionTime = projection * oneTick;
182 
183         
184         Vector3d shift = new Vector3d(projectionTime * actualVelocity.x, projectionTime * actualVelocity.y, projectionTime * actualVelocity.z);
185 
186         
187         pointHeading = new Location(botself.getLocation().x + shift.x, botself.getLocation().y + shift.y, botself.getLocation().z + shift.z);
188 
189         Vector2d start = new Vector2d(previousLocation.x, previousLocation.y);
190         Vector2d end = new Vector2d(nextLocation.x, nextLocation.y);
191         Vector2d pointP = new Vector2d(pointHeading.x, pointHeading.y);
192 
193         Vector2d foot = SteeringTools.getNearestPoint(start, end, pointP, false);
194         
195         
196         pointHeadingToFoot = new Vector3d(foot.x - pointHeading.getX(), foot.y - pointHeading.getY(), 0);
197 
198         
199         if (pointHeadingToFoot.length() > distanceFromThePath) {
200             double distOut = pointHeadingToFoot.length() - distanceFromThePath;
201             
202 
203             
204 
205 
206 
207 
208 
209 
210             
211             double koefA = distOut / distanceFromThePath;   
212             if (koefA > 2) {
213                 koefA = 2;
214             }
215             nextVelocity.add(pointHeadingToFoot);
216             nextVelocity.normalize();
217             nextVelocity.scale(koefA * repulsiveForce + 30);    
218             if (SteeringManager.DEBUG) System.out.println("STAY IN CORRIDOR!");
219             wantsToGoFaster.setValue(false);
220         } else { 
221             wantsToGoFaster.setValue(true);
222         }       
223 
224         Vector3d regulatingVector = new Vector3d(nextLocation.x - previousLocation.x,nextLocation.y - previousLocation.y,0);
225         regulatingVector.normalize();
226         regulatingVector.scale(regulatingForce);
227         nextVelocity.add((Tuple3d) regulatingVector);
228 
229         return nextVelocity;
230     }
231 
232     private boolean shiftNextLocation() {
233         if (path == null) return false;
234         if (SteeringManager.DEBUG) System.out.println("vzdalenost od nextLocation "+botself.getLocation().getDistance(nextLocation));
235         
236         if (botself.getLocation().getDistance(nextLocation) <= distanceFromThePath || getBehindBorder()) {  
237             if (actualIndex + 1 < path.size()) {
238                 if (SteeringManager.DEBUG) {
239                     System.out.println("Novy navpoint; size " + path.size() + " actual index " + actualIndex);
240                 }
241                 ILocated help = path.get(actualIndex + 1);
242                 if (help == null) {
243                     if (SteeringManager.DEBUG) {
244                         System.out.println("NULL!!! " + pathFuture.getStatus() + pathFuture.isDone());
245                     }
246                 } else {
247                     actualIndex++;
248                     previousLocation = nextLocation;
249                     nextLocation = help.getLocation();
250                 }
251             }
252             return true;
253         } else {
254             return false;
255         }
256     }
257 
258     
259     private boolean getBehindBorder() {
260         
261         Vector2d startA = new Vector2d(previousLocation.x, previousLocation.y);
262         Vector2d endA = new Vector2d(botself.getLocation().x, botself.getLocation().y);
263         Vector2d directionA = new Vector2d(endA.x - startA.x, endA.y - startA.y);
264         
265         
266 
267         Vector2d startB = new Vector2d(nextLocation.x, nextLocation.y);
268         Vector2d normalDirectionB = new Vector2d(nextLocation.x - previousLocation.x, nextLocation.y - previousLocation.y);
269         Vector2d directionB = new Vector2d(-normalDirectionB.y, normalDirectionB.x);
270         
271 
272         Vector2d intersection = SteeringTools.getIntersection(startA, directionA, startB, directionB, SteeringTools.LineType.ABSCISSA, SteeringTools.LineType.STRAIGHT_LINE);
273         
274         if (SteeringManager.DEBUG) System.out.println("Jsme za hranicí "+(intersection != null)+" průsečík: "+intersection);
275         return (intersection != null);
276     }
277 
278     
279     private boolean setComputedPath() {
280         List<ILocated> myNewPath = this.pathFuture.get();
281         if (myNewPath == null) {
282             if (SteeringManager.DEBUG) System.out.println("null cesta ");
283             return false;
284         } else if (myNewPath.size() < 1) {
285             if (SteeringManager.DEBUG) System.out.println("kratka cesta " + myNewPath.size());
286             return false;
287         }
288         if (SteeringManager.DEBUG) System.out.println("path received " + myNewPath.size());
289         if (differentNewPath(myNewPath)) {  
290             path = myNewPath;
291             actualIndex = getIndexOfNearestILocated();
292             nextLocation = path.get(actualIndex).getLocation();
293             previousLocation = botself.getLocation();
294             lastDistanceFromNextLocation = botself.getLocation().getDistance(nextLocation);
295         }
296         newPath = false;    
297         return true;
298     }
299 
300     private boolean differentNewPath(List<ILocated> myNewPath) {
301         if (path == null) {
302             return true;    
303         } else if (myNewPath == null) {
304             return false;   
305         } else if (path.size() != myNewPath.size()) {
306             return true;    
307         } else {
308             for(int i = 0; i < path.size(); i++) {
309                 ILocated a = path.get(i);
310                 ILocated b = myNewPath.get(i);
311                 if (!a.equals(b)) {
312                     return true;    
313                 }
314             }
315             return false;   
316         }
317     }
318 
319     
320     private int getIndexOfNearestILocated() {
321         int result = 0;
322         Location botsLocation = botself.getLocation();
323         double dist = botsLocation.getDistance(path.get(0).getLocation());
324         for(int index = 0; index < path.size(); index++) {
325             ILocated il = path.get(index);
326             if (botsLocation.getDistance(il.getLocation()) < dist) {
327                 result = index;
328                 dist = botsLocation.getDistance(il.getLocation());
329             }
330         }
331         return result;
332     }
333 
334     public void setProperties(SteeringProperties newProperties) {
335         this.repulsiveForce = ((PathFollowingProperties)newProperties).getRepulsiveForce();
336         this.distanceFromThePath = ((PathFollowingProperties)newProperties).getDistanceFromThePath();
337         this.pathFuture = ((PathFollowingProperties)newProperties).getPath();
338         this.regulatingForce = ((PathFollowingProperties)newProperties).getRegulatingForce();
339         this.projection = ((PathFollowingProperties)newProperties).getProjection();
340         if (path != null) { 
341             newPath = true;
342         } else {
343             newPath = false;
344         }
345     }
346 
347     public PathFollowingProperties getProperties() {
348         PathFollowingProperties properties = new PathFollowingProperties();
349         properties.setRepulsiveForce(repulsiveForce);
350         properties.setDistanceFromThePath(distanceFromThePath);
351         properties.setPath(pathFuture);
352         properties.setRegulatingForce(regulatingForce);
353         properties.setProjection(projection);
354         return properties;
355     }
356     
357 }
358         
359         
360 
361 
362 
363