View Javadoc

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