View Javadoc

1   package SteeringStuff;
2   
3   import SocialSteeringsBeta.TriangleSteer;
4   import java.util.HashMap;
5   import java.util.Random;
6   
7   import javax.vecmath.Vector3d;
8   
9   import cz.cuni.amis.pogamut.base.communication.worldview.event.IWorldEventListener;
10  import cz.cuni.amis.pogamut.base3d.worldview.object.Location;
11  import cz.cuni.amis.pogamut.base3d.worldview.object.Rotation;
12  import cz.cuni.amis.pogamut.ut2004.agent.module.sensomotoric.Raycasting;
13  import cz.cuni.amis.pogamut.ut2004.bot.command.AdvancedLocomotion;
14  import cz.cuni.amis.pogamut.ut2004.bot.impl.UT2004Bot;
15  import cz.cuni.amis.pogamut.ut2004.communication.messages.gbcommands.Configuration;
16  import cz.cuni.amis.pogamut.ut2004.communication.messages.gbcommands.PlayAnimation;
17  import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.EndMessage;
18  import javax.vecmath.Tuple3d;
19  
20  import SteeringProperties.*;
21  import Steerings.*;
22  /**
23   * This class manages the whole navigation layer of the steered bot. The manager calls steerings to compute the force, combines all forces and sends the computed next velocity to the locomotion layer (modul locomotion).
24   * @author Marki
25   */
26  public class SteeringManager {
27  
28      /** Enables/disables all debugging println.*/
29      public static final boolean DEBUG = false;
30  
31      /** This manager needs botself, raycasting and AdvancedLocomotion. */
32      protected UT2004Bot botself;
33      //private Raycasting raycasting;
34      protected AdvancedLocomotion locomotion;
35      protected RaycastingManager rayManager;
36      private HashMap<SteeringType,ISteering> mySteerings;
37      public HashMap<SteeringType,Double> steeringWeights;
38      private HashMap<SteeringType,Vector3d> steeringForces;
39      private Vector3d myActualVelocity;
40      protected Vector3d myNextVelocity;
41      protected double multiplier;
42      private double lastVeloWeight = 2;
43      private boolean useLastVeloWeight = false;
44  
45      public static final double MAX_FORCE = 2000;
46      /** How long is the vector of walking velocity. Used for rescaling normal vector, when hitting an obstacle with a ray. */
47      protected static final double WALK_VELOCITY_LENGTH=220;
48      /** How long is the vector of running velocity. Used for rescaling normal vector, when hitting an obstacle with a ray. */
49      //protected static final double RUN_VELOCITY_LENGTH=440;
50      private static final double MIN_VALUE_TO_SUM = 0.3*WALK_VELOCITY_LENGTH;
51      public static final Location BASIC_LOCATION=new Location(800,-1500,-3446.65);//Mezi stromy (vice v ulici).
52      //public static final Location BASIC_LOCATION=new Location(9440,-9500,-3446.65); //Na rohu více na ulici.
53      //public static final Location BASIC_LOCATION=new Location(15000,-9500,-3446.65); //Na rohu - dále.
54      //public static final Location BASIC_LOCATION=new Location(5200,-2000,-3446.65); //Take nejak u koule.
55      //public static final Location BASIC_LOCATION=new Location(4500,-850,-3446.65); //U koule ve stredu mesta.
56  
57      /**Whether the rays should be drawned (this value will be the parameter of setDrawTraceLines()).*/
58      protected boolean drawRaycasting;
59      
60      /**If true, the velocity can be enlarged when every active steering agrees.*/
61      private boolean canEnlargeVelocity;
62  
63      private boolean WAPath = true;
64      public static boolean Thomas = false;
65      private boolean turning = true;
66      private boolean WA_debugg = true;
67  
68      /**
69       * When we register this listener, we activate our {@link SteeringManager } to steer the bot.
70       * This listener will call {@link SteeringManager#run() } on this object.
71       */
72      private IWorldEventListener<EndMessage> endMessageListener = new IWorldEventListener<EndMessage>() {
73          @Override
74          public void notify(EndMessage event) {
75              //Each time we receive end message run steering method will be called.
76              run();
77          }
78      };
79  
80      
81      /**
82       * Creates the new SteeringManager. This class manages the whole navigation layer of the steered bot. The manager calls steerings to compute the force, combines all forces and sends the computed next velocity to the locomotion layer (modul locomotion).
83       * @param bot The bot, who should be steered be these steerings.
84       * @param raycasting The instance of the class Raycasting.
85       * @param locomotion The AdvancedLocomotion of the bot.
86       */
87      public SteeringManager(UT2004Bot bot, Raycasting raycasting, AdvancedLocomotion locomotion) {
88          this.botself = bot;
89          //this.raycasting = raycasting;
90          this.locomotion = locomotion;
91          this.multiplier = 1;
92          rayManager = new RaycastingManager(botself, raycasting);
93          mySteerings = new HashMap<SteeringType,ISteering>();
94          steeringWeights = new HashMap<SteeringType, Double>();
95          steeringForces = new HashMap<SteeringType, Vector3d>();
96          steeringManagerInitialized();
97          myActualVelocity = new Vector3d();
98          myNextVelocity = new Vector3d();
99          drawRaycasting = false;
100         canEnlargeVelocity = true;
101     }
102 
103     /**
104      *
105      * @param bot The bot, who should be steered be these steerings. This class manages the whole navigation layer of the steered bot. The manager calls steerings to compute the force, combines all forces and sends the computed next velocity to the locomotion layer (modul locomotion).
106      * @param raycasting The instance of the class Raycasting.
107      * @param locomotion The AdvancedLocomotion of the bot.
108      * @param multiplier Default value is 1. The multiplier of the velocity. E.g, if you want to make this bot run nearly all the time, set the multiplier 2. But remember, that steerings could work worse.
109      */
110     public SteeringManager(UT2004Bot bot, Raycasting raycasting, AdvancedLocomotion locomotion, double multiplier) {
111         this.botself = bot;
112         //this.raycasting = raycasting;
113         this.locomotion = locomotion;
114         this.multiplier = multiplier;
115         rayManager = new RaycastingManager(botself, raycasting);
116         mySteerings = new HashMap<SteeringType,ISteering>();
117         steeringWeights = new HashMap<SteeringType, Double>();
118         steeringForces = new HashMap<SteeringType, Vector3d>();
119         steeringManagerInitialized();
120         myActualVelocity = new Vector3d();
121         myNextVelocity = new Vector3d();
122         drawRaycasting = false;
123         canEnlargeVelocity = true;
124     }
125 
126     private void steeringManagerInitialized() {
127         locomotion.setWalk();   //The bot is set to walk at normal speed.
128         if (Thomas) {
129             botself.getAct().act(new PlayAnimation().setName("walk_loop").setLoop(true));
130         }
131         botself.getAct().act(new Configuration().setDrawTraceLines(drawRaycasting).setAutoTrace(true).setSpeedMultiplier((double)1));
132     }
133 
134     /**Adds the steering of the steering type from the argument. The weight of this steering wil be 1.*/
135     public void addSteering(SteeringType type) {
136         addSteering(type, 1);
137     }
138 
139     /**Adds the steering of the steering type from the argument with the weight from the argument.*/
140     public void addSteering(SteeringType type, double weight) {
141         switch (type) {
142             case OBSTACLE_AVOIDANCE:
143                 mySteerings.put(type, new ObstacleAvoidanceSteer(botself, rayManager));
144                 break;
145             case TARGET_APPROACHING:
146                 mySteerings.put(type, new TargetApproachingSteer(botself));
147                 break;
148             case LEADER_FOLLOWING:
149                 mySteerings.put(type, new LeaderFollowingSteer(botself));
150                 break;
151             case PATH_FOLLOWING:
152                 if (WAPath && mySteerings.containsKey(SteeringType.WALK_ALONG)) {   //Když by měl mít WA i PF, tak se budou brát vrcholy z PF a sázet se mu jako cíle WA.
153                     
154                 } else {
155                     mySteerings.put(type, new PathFollowingSteer(botself));
156                 }
157                 break;
158             case PEOPLE_AVOIDANCE:
159                 mySteerings.put(type, new PeopleAvoidanceSteer(botself));
160                 break;
161             case WALK_ALONG:
162                 mySteerings.put(type, new WalkAlongSteer(botself));
163                 break;
164             case WALL_FOLLOWING:
165                 mySteerings.put(type, new WallFollowingSteer(botself, rayManager));
166                 break;
167             case TRIANGLE:
168                mySteerings.put(type, new TriangleSteer(botself));
169                 break;
170         }
171         steeringWeights.put(type, new Double(weight));
172     }
173 
174     /**Returns true, if the manager has this steering type in the list of used steerings.*/
175     public boolean hasSteering(SteeringType type) {
176         return mySteerings.containsKey(type);
177     }
178 
179     /**Removes the steering of the steering type from the argument.*/
180     public void removeSteering(SteeringType type) {
181         if ((type == SteeringType.OBSTACLE_AVOIDANCE) || (type == SteeringType.WALL_FOLLOWING)) {
182             rayManager.removeRays(type);
183         }
184         mySteerings.remove(type);
185         steeringWeights.remove(type);
186     }
187 
188     /**Sets the steering properties of the steering type from the argument.*/
189     public void setSteeringProperties(SteeringType type, SteeringProperties newProperties) {
190         ISteering steer = mySteerings.get(type);
191         if (steer!=null) steer.setProperties(newProperties);
192     }
193     
194     /**
195      * The main method. This method must be called in each tick (logic), if we want the navigation layer to compute the next velocity and send it to the locomotion layer.
196      * Note: Should not be called anymore. Use start() and stop() methods.
197      */
198     public void run() {
199         steeringForces.clear();
200 
201         Vector3d velocity = botself.getVelocity().getVector3d();
202 
203         if (SteeringManager.DEBUG) System.out.println("Velocity "+velocity+" length "+velocity.length());
204                 
205         // Supposed velocity in the next tick of logic, after applying various steering forces to the bot.
206         Vector3d nextVelocity = new Vector3d(velocity.x, velocity.y, velocity.z);
207 
208         double actualWeight;
209 
210         if (useLastVeloWeight) {
211             actualWeight = lastVeloWeight;
212         } else {
213             actualWeight = 3 - velocity.length()/WALK_VELOCITY_LENGTH;  //This causes that <= WALK_VEOCITY_LENGTH will have actualWeight 2, sth. >= 2*WALK_VELOCITY_LENGTH 1, and other values wil be between 1 and 2.
214             if (actualWeight <1)
215                 actualWeight = 1;
216             else if (actualWeight > 2)
217                 actualWeight = 2;
218             if (velocity.length() == 0)
219                 actualWeight = 0;
220         }
221 
222         //The actual velocity has bigger weigh ==> the behavior will be smoother.   //5389.0,-6203.0,-3446.65
223         nextVelocity.scale(actualWeight);
224 
225         myActualVelocity = new Vector3d(nextVelocity.x, nextVelocity.y, nextVelocity.z);
226         Vector3d myStopVelocity = new Vector3d(nextVelocity.x, nextVelocity.y, nextVelocity.z);
227         
228         double totalWeight = actualWeight;
229         
230         boolean everyoneWantsToGoFaster = canEnlargeVelocity;
231         RefBoolean wantsToGoFaster = new RefBoolean(false);
232         RefBoolean wantsToStop = new RefBoolean(false);
233         Location focusLoc = new Location(0,0,0);
234         
235         for(SteeringType stType : mySteerings.keySet()) {
236             ISteering steering = mySteerings.get(stType);
237             Location newFocus = new Location(0, 0, 0);
238             Vector3d newVelocity = setVelocitySpecific(steering, wantsToGoFaster, wantsToStop, newFocus);
239             focusLoc = setFocusSpecific(stType,wantsToStop.getValue(),newFocus,focusLoc);
240             if (wantsToStop.getValue()) {   //Wants to stop causes, tak bot stops, if this steering is the only one. Otherwise the other steerings can cause that bot will again move.
241                 newVelocity.x = -myStopVelocity.x;
242                 newVelocity.y = -myStopVelocity.y;
243                 newVelocity.z = -myStopVelocity.z;
244                 myStopVelocity.sub(newVelocity);
245                 everyoneWantsToGoFaster = false;
246                 if (SteeringManager.DEBUG) System.out.println("We stop.");
247                 wantsToStop.setValue(false);
248             } else {
249                 if (newVelocity.length() > MAX_FORCE) newVelocity.scale(MAX_FORCE/newVelocity.length());
250                 newVelocity.scale(steeringWeights.get(stType)); //Each steering has its own weight.
251                 everyoneWantsToGoFaster = everyoneWantsToGoFaster && wantsToGoFaster.getValue();
252             }
253             if (newVelocity.length()>0) {
254                 //TODO: WARNING hack to use different type of steering return values
255                 //it should be redone, more cleaner and robust way... Petr B.
256                 newVelocity.add((Tuple3d)nextVelocity);
257                 nextVelocity = newVelocity;
258                 if (newVelocity.length() > MIN_VALUE_TO_SUM)    //Only significant steerings are counted into totalWeight.
259                     totalWeight += steeringWeights.get(stType);
260             }
261             if (SteeringManager.DEBUG) System.out.println(steering.toString()+"| length "+newVelocity.length()+" | weight: "+steeringWeights.get(stType));
262             steeringForces.put(stType, newVelocity);
263         }
264         if (SteeringManager.DEBUG) System.out.print("Sum "+nextVelocity.length()+" TotalWeight: "+totalWeight);
265         if (totalWeight > 0) {
266             nextVelocity.scale(1/totalWeight);
267         }
268         if (SteeringManager.DEBUG) System.out.println(" Result "+nextVelocity.length());
269 
270         moveTheBot(nextVelocity, everyoneWantsToGoFaster, focusLoc);
271     }
272 
273     /**This method is used mainly in SteeringManager.run(). 
274      * But if we want to stop the bot - and after a while make him again to walk,
275      * we can remember his velocity befor stopping and use this methode.*/
276     public void moveTheBot(Vector3d nextVelocity, boolean everyoneWantsToGoFaster, Location focusLocation) {
277 
278         double nextVelocityLength = nextVelocity.length() * multiplier; //The multiplier enables to enlarge or decrease the velocity. E.g. to make the bot to run.
279 
280         if (SteeringManager.DEBUG) System.out.println("next velocity before scaling "+nextVelocityLength+" : "+(nextVelocityLength/WALK_VELOCITY_LENGTH));
281 
282         if (nextVelocityLength == 0) {     //If the velocity is too small, we could turn round. Maybe the better solution would be to count the next location just more far away from the actual location.
283             if (!focusLocation.equals(new Location(0,0,0))) {
284                 if (turning) {
285                     locomotion.turnTo(focusLocation);
286                     if (SteeringManager.DEBUG) System.out.println("We stop and turn to the location "+focusLocation);
287                 }
288             } else {
289                 if (SteeringManager.DEBUG) System.out.println("We stop but don't turn to the location "+focusLocation);
290             }
291             locomotion.stopMovement();
292             if (Thomas) botself.getAct().act(new PlayAnimation().setName("idleanim").setLoop(true));
293             
294             myNextVelocity = new Vector3d(0,0,0);
295             return;
296         }
297 
298         if (nextVelocityLength < 0.8*WALK_VELOCITY_LENGTH && everyoneWantsToGoFaster) {
299             if (SteeringManager.DEBUG) System.out.println("we enlarge the velocity");
300             nextVelocityLength = 0.8 * WALK_VELOCITY_LENGTH;
301         }
302 
303         double nextVelMult = nextVelocityLength / WALK_VELOCITY_LENGTH;
304 
305         /* According to the velocity magnitude we decide, if the bot wil run or walk. The treshold is 2.5*WALK_VELOCITY_LENGTH.
306          * Ideal are the values between 0.8 and 1.2. The bigger values (up to 2.5) can cause, that the bot looks like "skying".
307          * 0.8*WALK_VELOCITY_LENGTH means the velocity magnitude 176, 1.2*WALK_VELOCITY_LENGTH --> 264, 2.5*WALK_VELOCITY_LENGTH --> 550, 20.5*WALK_VELOCITY_LENGTH --> 4510.*/
308         if (nextVelMult > 2.5) {
309             locomotion.setRun();
310             if (Thomas) botself.getAct().act(new PlayAnimation().setName("run_normal01").setLoop(true));
311             if (SteeringManager.DEBUG) System.out.println("run");
312             if (nextVelMult > 20.5) {
313                 nextVelMult = 20.5;
314             }
315             nextVelMult -= 2.5;
316             nextVelMult = nextVelMult/18;
317             nextVelMult = (0.8+nextVelMult);
318         } else {
319             locomotion.setWalk();
320             if (Thomas) botself.getAct().act(new PlayAnimation().setName("walk_loop").setLoop(true));
321             if (SteeringManager.DEBUG) System.out.println("walk");
322             if (nextVelMult > 0.8) {
323                 nextVelMult = 0.85 + 0.1*Math.sqrt(10*(nextVelMult - 0.8));
324             } else {
325                 nextVelMult = nextVelMult*0.75 + 0.25;
326             }
327         }
328         nextVelocityLength = nextVelMult * WALK_VELOCITY_LENGTH;
329         nextVelocity.normalize();
330         nextVelocity.scale(nextVelocityLength);
331 
332         myNextVelocity = new Vector3d(nextVelocity.x, nextVelocity.y, nextVelocity.z);
333         
334         if (SteeringManager.DEBUG) System.out.println("next velocity "+nextVelocity.length()+" : "+(nextVelocity.length()/WALK_VELOCITY_LENGTH));
335         
336         //we change the bot's speed and turn him.
337         botself.getAct().act(new Configuration().setSpeedMultiplier(nextVelocityLength / WALK_VELOCITY_LENGTH).setAutoTrace(true).setDrawTraceLines(drawRaycasting));
338 
339         locomotion.moveTo(new Location(botself.getLocation().x + nextVelocity.x, botself.getLocation().y + nextVelocity.y, botself.getLocation().z));
340 
341         if (WA_debugg && mySteerings.containsKey(SteeringType.WALK_ALONG)) {
342             WalkAlongSteer WAsteering = (WalkAlongSteer)mySteerings.get(SteeringType.WALK_ALONG);
343             myActualVelocity = WAsteering.getForceToPartner();
344             if (myActualVelocity == null) {
345                 myActualVelocity = new Vector3d(0,0,0);
346             }
347             myNextVelocity = WAsteering.getForceToTarget();
348             if (myNextVelocity == null) {
349                 myNextVelocity = new Vector3d(0,0,0);
350             }
351         }
352     }
353 
354     /**Returns the sum of two loactions.*/
355     private Location addLocations(Location focusLoc, Location newFocus) {
356         if (focusLoc.equals(new Location(0,0,0))) return newFocus;
357         if (newFocus.equals(new Location(0,0,0))) return focusLoc;
358         Location result = new Location((focusLoc.x + newFocus.x) / 2, (focusLoc.y + newFocus.y) / 2, (focusLoc.z + newFocus.z) / 2);
359         return result;
360     }
361 
362     /**Returns the random location near to the BASIC_LOCATION.*/
363     public static Location getRandomStartLocation() {
364         Random random = new Random();
365         int znam = 1;
366         if (random.nextBoolean()) znam = -1;
367         return new Location(BASIC_LOCATION.x - random.nextInt(500)*znam, BASIC_LOCATION.y - random.nextInt(500)*znam, BASIC_LOCATION.z);
368     }
369 
370     /**Returns the random rotation.*/
371     public static Rotation getRandomStartRotation() {
372         Random random = new Random();
373         return new Rotation(0,angleToUTUnits(random.nextInt(360)-180),0);
374     }
375 
376     /**
377      * convert angle to UT rotation units
378      * @param angle
379      * @return
380      */
381     private static int angleToUTUnits(double angle){
382         return (int) Math.round((angle*65535)/360);
383     }
384 
385     /**Returns the hasp map of used steering forces.*/
386     public HashMap<SteeringType, Vector3d> getSteeringForces() {
387         return steeringForces;
388     }
389 
390     /**Returns the scaled actual velocity.*/
391     public Vector3d getMyActualVelocity() {
392         return myActualVelocity;
393     }
394 
395     /**Returns the computed next velocity.*/
396     public Vector3d getMyNextVelocity() {
397         return myNextVelocity;
398     }
399 
400     /**Returns whether the rays are drawn in the UE2.*/
401     public boolean isDrawRaycasting() {
402         return drawRaycasting;
403     }
404 
405     /**Sets whether the rays in UE2 should be drawned.*/
406     public void setDrawRaycasting(boolean drawRaycasting) {
407         this.drawRaycasting = drawRaycasting;
408     }
409 
410     /**If true, the velocity can be enlarged when every active steering agrees.*/
411     public void setCanEnlargeVelocity(boolean canEnlargeVelocity) {
412         this.canEnlargeVelocity = canEnlargeVelocity;
413     }
414 
415     /**Returns whether the velocity can be enlarged when every active steering agrees.*/
416     public boolean isCanEnlargeVelocity() {
417         return canEnlargeVelocity;
418     }
419     
420     /**Sets the multiplier of the velocity. The computed velocity vektor will be multiplied by this value.
421      * E.g, if you want to make this bot run nearly all the time, set the multiplier 2 (or 3).
422      * But remember, that steerings could work worse.*/
423     public void setMultiplier(double multiplier) {
424         this.multiplier = multiplier;
425     }
426 
427     public void setLastVeloWeight(double lastVeloWeight) {
428         this.lastVeloWeight = lastVeloWeight;
429     }
430 
431     public void setUseLastVeloWeight(boolean useLastVeloWeight) {
432         this.useLastVeloWeight = useLastVeloWeight;
433     }
434 
435     /**
436      * Registers {@link SteeringManager#endMessageListener } and by this activates
437      * steering navigation.
438      */
439     public void start() {
440         if (!botself.getWorldView().isListening(EndMessage.class, endMessageListener))
441             botself.getWorldView().addEventListener(EndMessage.class, endMessageListener);
442     }
443 
444     /**
445      * Unregisters {@link SteeringManager#endMessageListener } - steering manager
446      * will cease to navigate the bot (the bot will stop, but steering settings
447      * will be preserved).
448      */
449     public void stop() {
450         if (botself.getWorldView().isListening(EndMessage.class, endMessageListener))
451             botself.getWorldView().removeEventListener(EndMessage.class, endMessageListener);
452     }
453 
454     /**
455      * Returns whether we are currently using {@link SteeringManager }
456      * for navigation.
457      * @return
458      */
459     public boolean isNavigating() {
460         return botself.getWorldView().isListening(EndMessage.class, endMessageListener);
461     }
462 
463     /**
464      * Removes all currently active steerings.
465      */
466     public void clearSteerings() {
467         for (SteeringType type : mySteerings.keySet()) {
468             removeSteering(type);
469         }
470     }
471     
472     /**
473      * Returns path following properites if this steering is set or null otherwise.
474      * @return
475      */
476     public LeaderFollowingProperties getLeaderFollowingProperties() {
477         ISteering steering = mySteerings.get(SteeringType.LEADER_FOLLOWING);
478         if (steering != null)
479             return ((LeaderFollowingSteer) steering).getProperties();
480 
481         return null;
482     }
483 
484     /**
485      * Returns path following properites if this steering is set or null otherwise.
486      * @return
487      */
488     public ObstacleAvoidanceProperties getObstacleAvoidanceProperties() {
489         ISteering steering = mySteerings.get(SteeringType.OBSTACLE_AVOIDANCE);
490         if (steering != null)
491             return ((ObstacleAvoidanceSteer) steering).getProperties();
492 
493         return null;
494     }
495 
496     /**
497      * Returns path following properites if this steering is set or null otherwise.
498      * @return
499      */
500     public PathFollowingProperties getPathFollowingProperties() {
501         ISteering steering = mySteerings.get(SteeringType.PATH_FOLLOWING);
502         if (steering != null)
503             return ((PathFollowingSteer) steering).getProperties();
504 
505         return null;
506     }
507 
508     /**
509      * Returns people avoidance properites if this steering is set or null otherwise.
510      * @return
511      */
512     public PeopleAvoidanceProperties getPeopleAvoidanceProperties() {
513         ISteering steering = mySteerings.get(SteeringType.PEOPLE_AVOIDANCE);
514         if (steering != null)
515             return ((PeopleAvoidanceSteer) steering).getProperties();
516 
517         return null;
518     }
519 
520     /**
521      * Returns target approaching properites if this steering is set or null otherwise.
522      * @return
523      */
524     public TargetApproachingProperties getTargetApproachingProperties() {
525         ISteering steering = mySteerings.get(SteeringType.TARGET_APPROACHING);
526         if (steering != null)
527             return ((TargetApproachingSteer) steering).getProperties();
528 
529         return null;
530     }
531 
532     /**
533      * Returns walk along properites if this steering is set or null otherwise.
534      * @return
535      */
536     public WalkAlongProperties getWalkAlongProperties() {
537         ISteering steering = mySteerings.get(SteeringType.WALK_ALONG);
538         if (steering != null)
539             return ((WalkAlongSteer) steering).getProperties();
540 
541         return null;
542     }
543 
544     /**
545      * Returns wall following properites if this steering is set or null otherwise.
546      * @return
547      */
548     public WallFollowingProperties getWallFollowingProperties() {
549         ISteering steering = mySteerings.get(SteeringType.WALL_FOLLOWING);
550         if (steering != null)
551             return ((WallFollowingSteer) steering).getProperties();
552         
553         return null;
554     }
555 
556     public void addLeaderFollowingSteering(LeaderFollowingProperties properties) {
557         addSteering(SteeringType.LEADER_FOLLOWING);
558         setSteeringProperties(SteeringType.LEADER_FOLLOWING, properties);
559     }
560 
561     public void removeLeaderFollowingSteering() {
562         removeSteering(SteeringType.LEADER_FOLLOWING);
563     }
564 
565     public void setLeaderFollowingSteering(LeaderFollowingProperties properties) {
566         setSteeringProperties(SteeringType.LEADER_FOLLOWING, properties);
567     }
568 
569     public boolean isLeaderFollowingActive() {
570         return hasSteering(SteeringType.LEADER_FOLLOWING);
571     }
572 
573     public void addObstacleAvoidanceSteering(ObstacleAvoidanceProperties properties) {
574         addSteering(SteeringType.OBSTACLE_AVOIDANCE);
575         setSteeringProperties(SteeringType.OBSTACLE_AVOIDANCE, properties);
576     }
577 
578     public void removeObstacleAvoidanceSteering() {
579         removeSteering(SteeringType.OBSTACLE_AVOIDANCE);
580     }
581 
582     public void setObstacleAvoidanceSteering(ObstacleAvoidanceProperties properties) {
583         setSteeringProperties(SteeringType.OBSTACLE_AVOIDANCE, properties);
584     }
585 
586     public boolean isObstacleAvoidanceActive() {
587         return hasSteering(SteeringType.OBSTACLE_AVOIDANCE);
588     }
589 
590     public void addPathFollowingSteering(PathFollowingProperties properties) {
591         addSteering(SteeringType.PATH_FOLLOWING);
592         setSteeringProperties(SteeringType.PATH_FOLLOWING, properties);
593     }
594 
595     public void removePathFollowingSteering() {
596         removeSteering(SteeringType.PATH_FOLLOWING);
597     }
598 
599     public void setPathFollowingSteering(PathFollowingProperties properties) {
600         setSteeringProperties(SteeringType.PATH_FOLLOWING, properties);
601     }
602 
603     public boolean isPathFollowingActive() {
604         return hasSteering(SteeringType.PATH_FOLLOWING);
605     }
606 
607     public void addPeopleAvoidanceSteering(PeopleAvoidanceProperties properties) {
608         addSteering(SteeringType.PEOPLE_AVOIDANCE);
609         setSteeringProperties(SteeringType.OBSTACLE_AVOIDANCE, properties);
610     }
611 
612     public void removePeopleAvoidanceSteering() {
613         removeSteering(SteeringType.PEOPLE_AVOIDANCE);
614     }
615 
616     public void setPeopleAvoidanceSteering(PeopleAvoidanceProperties properties) {
617         setSteeringProperties(SteeringType.PEOPLE_AVOIDANCE, properties);
618     }
619 
620     public boolean isPeopleAvoidanceActive() {
621         return hasSteering(SteeringType.PEOPLE_AVOIDANCE);
622     }
623 
624     public void addTargetApproachingSteering(TargetApproachingProperties properties) {
625         addSteering(SteeringType.TARGET_APPROACHING);
626         setSteeringProperties(SteeringType.TARGET_APPROACHING, properties);
627     }
628 
629     public void removeTargetApproachingSteering() {
630         removeSteering(SteeringType.TARGET_APPROACHING);
631     }
632 
633     public void setTargetApproachingSteering(TargetApproachingProperties properties) {
634         setSteeringProperties(SteeringType.TARGET_APPROACHING, properties);
635     }
636 
637     public boolean isTargetApproachingActive() {
638         return hasSteering(SteeringType.TARGET_APPROACHING);
639     }
640 
641     public void addWalkAlongSteering(WalkAlongProperties properties) {
642         addSteering(SteeringType.WALK_ALONG);
643         setSteeringProperties(SteeringType.WALK_ALONG, properties);
644     }
645 
646     public void removeWalkAlongSteering() {
647         removeSteering(SteeringType.WALK_ALONG);
648     }
649 
650     public void setWalkAlongSteering(WalkAlongProperties properties) {
651         setSteeringProperties(SteeringType.WALK_ALONG, properties);
652     }
653 
654     public boolean isWalkAlongActive() {
655         return hasSteering(SteeringType.WALK_ALONG);
656     }
657 
658     public void addWallFollowingSteering(WallFollowingProperties properties) {
659         addSteering(SteeringType.WALL_FOLLOWING);        
660         setSteeringProperties(SteeringType.WALL_FOLLOWING, properties);
661     }
662 
663     public void removeWallFollowingSteering() {
664         removeSteering(SteeringType.WALL_FOLLOWING);
665     }
666 
667     public void setWallFollowingSteering(WallFollowingProperties properties) {
668         setSteeringProperties(SteeringType.WALL_FOLLOWING, properties);
669     }
670 
671     public boolean isWallFollowingActive() {
672         return hasSteering(SteeringType.WALL_FOLLOWING);
673     }
674 
675     // <editor-fold defaultstate="collapsed" desc="new methods">
676     protected Location setFocusSpecific(SteeringType steeringType, boolean wantsToStop, Location newFocus, Location focusLoc) {
677         if(wantsToStop)
678         {
679             return addLocations(focusLoc, newFocus);
680         }
681         else
682         {
683             return focusLoc;
684         }
685         
686     }
687     
688     /**
689      When owerriden can provide different behaviour of steering computation 
690      * i.e. can tunnel some other information like true distance to target place
691      * it is used for the social steerings...
692      */
693     protected Vector3d setVelocitySpecific(ISteering steering, RefBoolean wantsToGoFaster, RefBoolean wantsToStop, Location newFocus) {
694         Vector3d newVelocity = steering.run(myActualVelocity, wantsToGoFaster, wantsToStop, newFocus);
695         return newVelocity;
696     }
697     
698     // </editor-fold>
699     
700 }