View Javadoc

1   package cz.cuni.amis.pogamut.usar2004.samples;
2   
3   import cz.cuni.amis.pogamut.base.utils.guice.AgentScoped;
4   import cz.cuni.amis.pogamut.base3d.worldview.object.*;
5   import cz.cuni.amis.pogamut.usar2004.agent.*;
6   import cz.cuni.amis.pogamut.usar2004.agent.module.configuration.*;
7   import cz.cuni.amis.pogamut.usar2004.agent.module.datatypes.*;
8   import cz.cuni.amis.pogamut.usar2004.agent.module.geometry.GeoSensorEffecter;
9   import cz.cuni.amis.pogamut.usar2004.agent.module.logic.USAR2004BotLogicController;
10  import cz.cuni.amis.pogamut.usar2004.agent.module.master.*;
11  import cz.cuni.amis.pogamut.usar2004.agent.module.sensor.SensorLaser;
12  import cz.cuni.amis.pogamut.usar2004.agent.module.response.ResponseSensorEffecter;
13  import cz.cuni.amis.pogamut.usar2004.agent.module.sensor.*;
14  import cz.cuni.amis.pogamut.usar2004.communication.messages.datatypes.SensorMount;
15  import cz.cuni.amis.pogamut.usar2004.communication.messages.usarcommands.*;
16  import cz.cuni.amis.pogamut.usar2004.communication.messages.usarinfomessages.NfoMessage;
17  import cz.cuni.amis.pogamut.usar2004.samples.AirScanner.Record;
18  import cz.cuni.amis.pogamut.usar2004.samples.AirScanner.RiskLevel;
19  import cz.cuni.amis.pogamut.usar2004.samples.AirScanner.ScanPreview;
20  import cz.cuni.amis.pogamut.usar2004.samples.AirScanner.State;
21  import cz.cuni.amis.pogamut.usar2004.samples.AirScanner.ToolBox;
22  import cz.cuni.amis.pogamut.usar2004.utils.*;
23  import cz.cuni.amis.utils.exception.PogamutException;
24  import java.awt.geom.Point2D;
25  import java.util.HashMap;
26  import java.util.LinkedList;
27  import java.util.List;
28  import java.util.Map;
29  import java.util.logging.Level;
30  import javax.swing.SwingUtilities;
31  
32  /**
33   * This robot is designed for the map DM-TallTestWorld_250 and is based on logic
34   * bot controller
35   *
36   * @author vejmanm
37   */
38  @AgentScoped
39  public class AerialVehicle extends USAR2004BotLogicController<USAR2004Bot>
40  {
41      /**
42       * Method triggered after Game is initialized and STARTPOSES obtained. Tt
43       * will spawn the robot into the environment.
44       *
45       * @param nfom NfoMessge containing STARTPOSES
46       */
47      @Override
48      public void robotInitialized(NfoMessage nfom)
49      {
50          super.robotInitialized(nfom);
51          //INIT {ClassName USARBot.AirRobot} {Name AirRObot sample robot} {Location 209.30999755859375,-651.47998046875,12.420000076293945}
52          //bot.getAct().act(new Initialize("USARBot.AirRobot", "AirRobot sample robot", new Location(209.30999755859375,-651.47998046875,12.420000076293945), null));
53          logicInitialize(logicModule);
54          getAct().act(new Initialize("USARBot.AirRobot", "AirRobot - aierial sample robot", nfom.getStartPoses().get(0).getName()));
55          //getAct().act(new Trace("ALL"));
56          System.out.println(logicModule.isRunning());
57      }
58  
59      @Override
60      public void initializeController(USAR2004Bot bot)
61      {
62          super.initializeController(bot);
63          //startPoses = new NfoStartPoses(bot);
64          //begin = new NfoBeginMapInfo(bot);
65      }
66      
67      
68      
69      //-------------------------------------------------
70      /*
71       * This is the place to change the scanning area
72       */
73      //-------------------------------------------------
74      private final Location destCenter = new Location(-49,-225);//(11, -50);//
75      private final double destWidth = 774;//174;//
76      private final double destHeight = 774;//174;//
77      private final double seaLevel = 3;//-5; must be less or equal t zero
78      
79      
80      private final Map<String, Point2D> highRiskAction = new HashMap<String, Point2D>()
81      {
82          
83          {//name, linear and lateral velocity coeficient
84              put("L4", new math.geom2d.Point2D(-0.95, 0.31));
85              put("R4", new math.geom2d.Point2D(-0.95, -0.31));
86              put("L3", new math.geom2d.Point2D(-0.81, 0.59));
87              put("R3", new math.geom2d.Point2D(-0.81, -0.59));
88              put("L2", new math.geom2d.Point2D(-0.59, 0.81));
89              put("R2", new math.geom2d.Point2D(-0.59, -0.81));
90              put("L1", new math.geom2d.Point2D(-0.31, 0.95));
91              put("R1", new math.geom2d.Point2D(-0.31, -0.95));
92              put("M0", new math.geom2d.Point2D(-1, 0));
93          }
94      };
95      private final Map<String, Double> highRisk = new HashMap<String, Double>()
96      {
97          
98          {
99              put("L4", 0.47d);
100             put("R4", 0.47d);
101             put("L3", 0.61d);
102             put("R3", 0.61d);
103             put("L2", 0.86d);
104             put("R2", 0.86d);
105             put("L1", 1.22d);
106             put("R1", 1.22d);
107             put("M0", 1.5d);
108         }
109     };
110     private final Map<String, Double> lowRisk = new HashMap<String, Double>()
111     {
112         
113         {
114             put("L4", 1.57d);
115             put("R4", 1.57d);
116             put("L3", 1.91d);
117             put("R3", 1.91d);
118             put("L2", 2.72d);
119             put("R2", 2.72d);
120             put("L1", 3.5d);
121             put("R1", 3.5d);
122             put("M0", 4.2d);
123         }
124     };
125     private final String[] sonarOrder = new String[]
126     {
127         "L4", "L3", "L2", "L1", "M0", "R1", "R2", "R3", "R4"
128     };
129     private final Location zeroPoint = new Location(0, 0, 0);//when robot is spawned his location is noted and than subtracted from every read from the senzor, so this is actually the spawnLocation
130     private final int numOfRays = 10;//number of rays used to measure the avg. altitude of the robot from the range scanner
131     private final double minDensity = 15;// how far will the next row be    
132     private final double scanAltitude = 6;
133     private final int dockWaitPenalty = 8;
134     //private final double rotationSpeed=0.2d;//rychlost otáčení při dokončení štráfku
135     private final double scanningSpeed = 0.2d;//0.18d;//0.3d;//
136     private final double flyingSpeed = 0.35d;
137     private final int jammedLimit = 35; //ment for flying speed
138     private boolean singleFlight = true;//když je single flight tak to udělá jednu žížalu, když true, tak to udělá 4 žížaly
139     private Location destination = destCenter; //(-100,40);//
140     private double dWidth = destWidth;
141     private double dHeight = destHeight;//80;
142     private Location longStep; //bude se muset vypočítat je to max(width,height) a směr se určí podle destination-(nejbližší z rohů obdélníka) samozřejmě se odečítají souřadnice podle max(width,height)
143     private Location shortStep; //je vypočítán z density a směr je podle nejbližšího z rohů obdélníka
144     private double altitude = scanAltitude;//MaxRange/2;
145     private double actAlt = 0;
146     private Location actLoc;
147     private Rotation actRot;
148     private Location nextLoc;// = new Location();
149     private State state = State.DEFAULT;
150     private double speed = 0;
151     private double rotSpeed = 0;
152     private double minDev = 0.9d;//longitude/latitude minimal margin
153 //    private final double latitudeDev = 0.007d;//grid spacing in degrees
154 //    private final double longitudeDev = 0.007d;//grid spacing in degrees
155     //properties needed for logic run:
156     private boolean parametersObtained = false;
157     private boolean scanning = false; //not scanning-no need for slow motion
158     private double maxLateralVelocity = 0;
159     private double maxLinearVelocity = 0;
160     private double maxRotationalVelocity = 0;
161     private double maxAltitudeVelocity = 0;
162     private boolean risen = false;
163     private int offset = 0;
164     private int cycle = 0;
165     private int cycleStop = 0;
166     private Location startLoc;// = new Location();
167     private String infoToShow = "";
168     private String infoToWrite = "";
169     //works till the battery is dead
170 
171     /**
172      * this method is triggered by receipt of STA message. This is where all
173      * behaviour is controlled
174      *
175      * @throws PogamutException
176      */
177     @Override
178     public void logic() throws PogamutException
179     {
180         System.out.println("logika");
181         try
182         {
183             super.logic();
184             if(lf == null)//wait for the form to initialize!
185             {
186                 return;
187             }
188             time = staModule.getStatesByVehilceType(VehicleType.AERIAL_VEHICLE).getTime();
189             issueInfos();
190             while(resModule.size() > 0)
191             {
192                 System.out.println(((ResponseSensorEffecter) resModule.pull()).getStatus());
193             }
194 
195             if(!parametersObtained)
196             {
197                 if(!acceptSensorMessage())
198                 {
199                     return;
200                 }
201                 getConfig();
202                 return;//lets gather information befor rising;
203             }
204             else
205             {
206                 acceptSensorMessages();
207                 checkBattery();
208             }
209             if(!risen)
210             {
211                 rise();
212             }
213             else
214             {
215                 move();
216                 //getAct().act(new DriveAerial(0, 100, 50, 25, true));
217             }
218             lf.setInfo(infoToShow);
219             lf.setPostInfo(infoToWrite);
220         }
221         catch(Exception e)
222         {
223             System.out.println("ERROR LOGIC. " + e.getMessage());
224         }
225 
226     }
227 
228     /**
229      * Gatheres data to send to the scan preview form to show at the left white
230      * panel.
231      */
232     private void issueInfos()
233     {
234         infoToShow = "";
235         infoToShow += "\nRobot State: " + state.toString();
236         infoToShow += "\nTime Elapsed: " + ToolBox.getTime(System.currentTimeMillis() - startTime);
237         infoToShow += "\n\nnoRiskCount: " + noriskCount;
238         infoToShow += "\nriskCount: " + riskCount;
239         infoToWrite = "";
240         infoToWrite += "Elapsed: " + ToolBox.getTime(System.currentTimeMillis() - startTime);
241         infoToWrite += "\nBattery Cycles: " + battFills;
242     }
243 
244     /**
245      * Carefully tries to obtain all sensor messages. It is sed at the
246      * beginning.
247      *
248      * @return Returns false if it was not able to obtain values. True
249      * otherwise.
250      */
251     private boolean acceptSensorMessage()
252     {
253 
254         if(!senModule.isSensorReady(SensorType.LASER_SENSOR)
255                 || !senModule.isSensorReady(SensorType.INS_SENSOR)
256                 || !senModule.isSensorReady(SensorType.GROUND_TRUTH)
257                 || !senModule.isSensorReady(SensorType.RANGE_SENSOR))
258         {
259             return false;
260         }
261         laser = (SensorLaser) senModule.getSensorsBySensorType(SensorType.LASER_SENSOR).get(0);
262         ins = (SensorINS) senModule.getSensorsBySensorType(SensorType.INS_SENSOR).get(0);
263         sonar = (SensorRange) senModule.getSensorsBySensorType(SensorType.RANGE_SENSOR).get(0);
264         truth = (SensorGroundTruth) senModule.getSensorsBySensorType(SensorType.GROUND_TRUTH).get(0);
265         return true;
266     }
267 
268     /**
269      * Gets all sensor messages queued from the last logic call.
270      */
271     private void acceptSensorMessages()
272     {
273         List<SuperSensor> lasers = senModule.getSensorsBySensorType(SensorType.LASER_SENSOR);
274         List<SuperSensor> inses = senModule.getSensorsBySensorType(SensorType.INS_SENSOR);
275         List<SuperSensor> sonars = senModule.getSensorsBySensorType(SensorType.RANGE_SENSOR);
276         List<SuperSensor> truths = senModule.getSensorsBySensorType(SensorType.GROUND_TRUTH);
277 
278         int minIndex = ToolBox.getMin(lasers.size(), inses.size(), sonars.size(), truths.size());
279 
280         for(int i = 0; i < minIndex; i++)
281         {
282             laser = (SensorLaser) lasers.get(i);
283             truth = (SensorGroundTruth) truths.get(i);
284             ins = (SensorINS) inses.get(i);
285             sonar = (SensorRange) sonars.get(i);
286             refreshScanProcedure();
287         }
288     }
289 
290     /**
291      * Sets actual rotation and orientation and sets important sensor data to
292      * the preview JForm.
293      */
294     private void refreshScanProcedure()
295     {
296         actLoc = Location.sub(startLoc, truth.getLocation());//Location.sub(startLoc, ins.getLocation());//
297         actRot = truth.getOrientation();//ins.getOrientation();//
298 
299         lf.setRecord(new Record(laser.getRanges(), null, laser.getFOV()));
300         lf.setLocation(actLoc);
301         lf.setOrientation(actRot);
302         lf.refreshGraphics();
303     }
304     private SensorLaser laser;
305     private SensorGroundTruth truth;
306     private SensorINS ins;
307     private SensorRange sonar;
308     private double timeStamp = -1;
309     private double time = 0;
310     private long startTime = 0;
311     private double trip = 0;
312     private Location prevLoc = null;
313     private int battFull = 0;
314     private final int battLife = 500;
315     private int battFills = 0; //initial charge
316     private State stallState = State.DEFAULT;
317     private Location stallActLoc = null;
318     private Location stallNextLoc = null;
319 
320     /**
321      * System to compute range, battery left and used takes place here. If the
322      * robot is low on battery it returns to the base. If it has not been able
323      * to recover from the last recharge it terminates the scanning procedure.
324      */
325     private void checkBattery()
326     {
327         trip += Location.getDistance2D(actLoc, prevLoc);
328         prevLoc = actLoc;
329         double battUsed = battFull - staModule.getStatesByVehilceType(VehicleType.AERIAL_VEHICLE).getBattery();
330         double range = (battLife - battUsed) * (trip / battUsed);
331         double distanceFromHome = Location.getDistance2D(actLoc, zeroPoint);
332         infoToShow += "\n\nBatteryLife: " + battLife;
333         infoToShow += "\nBatteryUsed: " + battUsed;
334         infoToShow += "\n\nDistance From Home: " + ToolBox.getTwoDecimalPlaces(distanceFromHome);
335         infoToShow += "\nDistance From Next: " + ToolBox.getTwoDecimalPlaces(Location.getDistance2D(actLoc, nextLoc));
336         infoToShow += "\nRange: " + ToolBox.getTwoDecimalPlaces(range);
337         if(state == State.CHARGE || state == State.CHARGING || state == State.TERMINATE || state == State.LAND || tempState == State.TERMINATE || tempState == State.CHARGE || trip < 5)//trip<5->nevěrohodný range
338         {
339             return;
340         }
341         if(distanceFromHome > range * 0.85)
342         {
343             if(state == State.CONTINUE)
344             {
345                 finishGoalToStart();
346                 return;
347             }
348             if(state == State.AVOIDING && tempState == State.CHARGE)
349             {
350                 return; //vyhýbá se překážce, ale už měl namířeno na nabití
351             }
352             if(state == State.AVOIDING)
353             {
354                 stallState = tempState;//vyhýbá se překážce, ale ještě neví, že musí na nabití
355                 stallNextLoc = tempNextLoc;
356                 tempNextLoc = null;
357                 stallActLoc = (Location.getDistance2D(actLoc, stallNextLoc) < 15)?stallNextLoc:actLoc;
358             }
359             else
360             {
361                 stallState = state; //musí na nabití
362                 stallNextLoc = nextLoc;
363                 //pokud už byl fakt blízko k další metě, tak je to jakoby tam byl - zbytečná ztráta času
364                 stallActLoc = (Location.getDistance2D(actLoc, nextLoc) < 15)?nextLoc:actLoc;
365             }
366             state = State.CHARGE;
367             nextLoc = zeroPoint;
368             minDev = 1.5d;
369             lf.setRechargeBreakPoint(actLoc);
370         }
371 
372     }
373 
374     /**
375      * Computes the closest corner based on input parameters of scanning area
376      * and actual location of the robot.
377      *
378      * @param center Center point of the rectangle.
379      * @param width Width of the rectangle.
380      * @param height Height of the rectangle.
381      * @param actual Actual location from which it gets the closest corner.
382      * @return Returns closest corner of scanning area from the actual location.
383      */
384     private Location getClosestCorner(Location center, double width, double height, Location actual)
385     {
386         Location closest = new Location(center.x - width / 2, center.y + height / 2);//LeftTop
387         Location rt = new Location(center.x + width / 2, center.y + height / 2);//RightTop
388         Location lb = new Location(center.x - width / 2, center.y - height / 2);//LeftBottom
389         Location rb = new Location(center.x + width / 2, center.y - height / 2);//RightBottom
390 
391         if(Location.getDistance2D(closest, actual) > Location.getDistance2D(rt, actual))
392         {
393             closest = rt;
394         }
395         if(Location.getDistance2D(closest, actual) > Location.getDistance2D(lb, actual))
396         {
397             closest = lb;
398         }
399         if(Location.getDistance2D(closest, actual) > Location.getDistance2D(rb, actual))
400         {
401             closest = rb;
402         }
403         return closest;
404     }
405 
406     /**
407      * It computes its path to cover the whole scanning area.
408      *
409      * @param center center of the scanning area
410      * @param corner first corner to beggin with.
411      */
412     private void setupSteps(Location center, Location corner)
413     {
414         //set direction towards the center and pick the longer side every time!
415         //the small step has the oposite coordinate and points to the center as well.
416         //finally set the Stop to number of rows made.
417 
418         if(this.dHeight > this.dWidth)
419         {
420             double density = this.dWidth / Math.ceil(this.dWidth / this.minDensity);
421             this.longStep = new Location(0, this.dHeight * Math.signum(center.y - corner.y));
422             this.shortStep = new Location(density * Math.signum(center.x - corner.x), 0);
423             this.cycleStop = (int) (this.dWidth / density);
424         }
425         else
426         {
427             double density = this.dHeight / Math.ceil(this.dHeight / this.minDensity);
428             this.longStep = new Location(this.dWidth * Math.signum(center.x - corner.x), 0);
429             this.shortStep = new Location(0, density * Math.signum(center.y - corner.y));
430             this.cycleStop = (int) (this.dHeight / density);
431         }
432     }
433 
434     /**
435      * This computes the avarage height from ten rays from Range scanner that
436      * aim directly below the robot.
437      */
438     private void checkAltitudeFromLaser()
439     {
440         //SensorLaser laser = (SensorLaser) (senModule.getSensorsBySensorType(SensorType.LASER_SENSOR).get(0));
441         //half of the FOV + actRotation to degrees + 90° gives us the angle of a ray that is aiming vertically
442         //máme v paměti, že jeden paprsek = 1°
443         //a taky že rotace je mezi 0 a 6.28, resp. že když se nakloní doprava tak se k nule přičítá a když doleva, tak se od 6.28 odečítá
444         offset = (int) ((actRot.roll >= Math.PI)?(360 - (actRot.roll * 180 / Math.PI)):(-actRot.roll * 180 / Math.PI));
445         actAlt = laser.getNMidAvg(numOfRays, offset);
446         lf.setOffset(offset);
447     }
448 
449     /**
450      * This method elevates robots altitude till the scanning altitude is
451      * reached.
452      */
453     private void rise()
454     {
455         if(altitude == 0)
456         {
457             return;
458         }
459         //TODO: actAlt se musí počítat ještě s náklonem dopředu, takže tam bude nějakej kosínus
460         actAlt = laser.getNMidAvg(10);//nemusíme počítat s odchylkou, když soupá kolmo
461         //musíme stoupat pomalu, aby se nezbláznila odchylka
462         bot.getAct().act(new DriveAerial(maxAltitudeVelocity / 4, 0, 0, 0, false));
463         if(altitude - actAlt < 0)
464         {
465             risen = true;
466             bot.getAct().act(new DriveAerial(0, 0, 0, 0, false));
467         }
468     }
469 
470     /**
471      * main control block that computes next direction based on altitude, risk
472      * level and computes next goal if needed. Also unjams the robot if
473      * necessary.
474      */
475     private void move()
476     {
477         checkAltitudeFromLaser();
478         if(state != State.CHARGING && state != State.LAND)
479         {
480             if(checkSonars() == RiskLevel.HIGHRISK)
481             {
482                 return;
483             }
484         }
485         approachNext();
486         scanning = (state == State.AVOIDING)?isScanning(tempState):isScanning(state);
487         if(state == State.CHARGING || state == State.LAND)
488         {
489             if(wait(dockWaitPenalty))
490             {
491                 if(state == State.CHARGING)
492                 {
493                     setResumeState();
494                 }
495                 else if(!singleFlight && wait(dockWaitPenalty))
496                 {
497                     setupMultiple();
498                 }
499             }
500             return;//no point in doing the next thing
501         }
502         if(hasReachedTarget(actLoc, nextLoc))//hasReachedTarget(latitude, latitudeNext) && hasReachedTarget(longitude, longitudeNext))
503         {
504             state = State.getNextState(state);
505             computeNext(state);
506         }
507         carryOnIfJammed();
508     }
509 
510     /**
511      * Method to establish if the robot is currently scanning important area or
512      * not, so it knows wether to speed up or not.
513      *
514      * @param state Can be actual state or temporary if avoiding obstacle
515      * @return Returns true if the robot is scanning important area based on its
516      * state.
517      */
518     private boolean isScanning(State state)
519     {
520         return (state == State.LONGFORTH || state == State.SHORTFORTH || state == State.LONGBACK || state == State.SHORTBACK);
521     }
522 
523     /**
524      * We use minimal deviation constant to allow robot to be just near its
525      * goal. The INS noise would cause the robot to spin around when the
526      * acceptable distance was too close.
527      *
528      * @param actual Actual position of the robot
529      * @param target Goal position.
530      * @return Returns true if the robot is within acceptable distance from its
531      * target.
532      */
533     private boolean hasReachedTarget(Location actual, Location target)
534     {
535         if(Location.getDistance2D(actual, target) > minDev)
536         {
537             return false;
538         }
539         return true;
540     }
541 
542     /**
543      * Helper method for terminating the scanning procedure and setting the last
544      * goal to its start position.
545      */
546     private void finishGoalToStart()
547     {
548         this.state = State.TERMINATE;
549         nextLoc = new Location(0, 0, 0);
550     }
551 
552     /**
553      * This comutes next goal or choses next action according to actual state of
554      * the robot.
555      *
556      * @param state current state of the robot.
557      */
558     private void computeNext(State state)
559     {
560         switch(state)
561         {
562             case DEFAULT:
563             case LONGFORTH:
564                 nextLoc = nextLoc.add(longStep);
565                 break;
566             case SHORTFORTH:
567             case SHORTBACK:
568                 nextLoc = nextLoc.add(shortStep);
569                 if(cycle >= cycleStop)
570                 {
571                     finishGoalToStart();
572                 }
573                 cycle++;
574                 break;
575             case LONGBACK:
576                 nextLoc = nextLoc.sub(longStep);
577                 break;
578             case TERMINATE:
579                 break;
580             case LAND:
581             case CHARGING:
582                 altitude = 0;
583                 break;
584             case CONTINUED:
585                 continueScanning();
586                 break;
587             case AVOIDED:
588                 tryReleaseDiversion();
589                 break;
590             default:
591                 System.out.println("Unexpected STATE");
592         }
593     }
594     private int multipleRunCount = 0;
595     private double multipleMargin = 10;
596 
597     /**
598      * If scanning area is too large it has to devide it into quadrants, this
599      * computes actual quadrant to scan. It narrows individual segments because
600      * the neighboring sides are covered even if the robot flies aside at some
601      * margin distance.
602      */
603     private void setupMultiple()
604     {
605         switch(multipleRunCount)
606         {
607             case 1:
608                 destination = new Location(destCenter.x - dWidth / 2 - multipleMargin, destCenter.y + dHeight / 2 + multipleMargin);
609                 break;
610             case 2:
611                 destination = new Location(destCenter.x - dWidth / 2 - multipleMargin, destCenter.y - dHeight / 2 - multipleMargin);
612                 break;
613             case 3:
614                 destination = new Location(destCenter.x + dWidth / 2 + multipleMargin, destCenter.y - dHeight / 2 - multipleMargin);
615                 break;
616             case 4:
617                 altitude = 0;
618                 break;
619         }
620         if(multipleRunCount < 4)
621         {
622             resetINS();
623             nextLoc = getClosestCorner(destination, dWidth, dHeight, new Location(0, 0, 0));
624             setupSteps(destination, nextLoc);
625             cycle = 0;
626             state = State.DEFAULT;
627             multipleRunCount++;
628             prepareForTakeof();
629         }
630     }
631 
632     /**
633      * Sets widths and heights of long and short streights if division into
634      * quadrant is needed.
635      */
636     private void initMultipleRun()
637     {
638         this.dWidth = destWidth / 2 - multipleMargin;// Math.abs(destination.x * 2);
639         this.dHeight = destHeight / 2 - multipleMargin; //Math.abs(destination.y * 2);
640         this.destination = new Location(destCenter.x + dWidth / 2 + multipleMargin, destCenter.y + dHeight / 2 + multipleMargin);
641     }
642 
643     /**
644      * Once the method is called it uses timeStamp variable to determine when it
645      * was called for the first time and every other call it checks if the time
646      * passed from the timeStamp is greater than the input variable timeSpan
647      *
648      * @param timeSpan - time interval that should pass from the first calling
649      * of this method to its last call
650      * @return returns false if the time passed is less than timeSpan and true
651      * if it is greater.
652      */
653     private boolean wait(int timeSpan)
654     {
655         if(timeStamp == -1)
656         {
657             timeStamp = time;
658         }
659         else if(time - timeStamp > timeSpan)
660         {
661             return true;
662         }
663         return false;
664     }
665 
666     /**
667      * If the robot is awoiding and is presumably jammed, this methods proceeds
668      * to next goal.
669      */
670     private void tryReleaseDiversion()
671     {
672         if(state == State.AVOIDING || state == State.AVOIDED)
673         {
674             nextLoc = tempNextLoc;
675             tempNextLoc = null;
676             state = tempState;
677         }
678     }
679 
680     /**
681      * This establishes previously interrupted scanning procedure for it had to
682      * recharge.
683      */
684     private void continueScanning()
685     {
686         this.state = stallState;
687         nextLoc = stallNextLoc;
688         stallNextLoc = null;
689         minDev = 0.9d;
690     }
691 
692     /**
693      * sets up necessary variables to resume scan procedure Resets INS position
694      * and rotation according to groundTruth - simulation of recharging and
695      * sensor reset.
696      *
697      */
698     private void setResumeState()
699     {
700         resetINS();
701         state = State.CONTINUE;
702         nextLoc = stallActLoc;
703         stallActLoc = null;
704         prepareForTakeof();
705     }
706 
707     /**
708      * Setting important variables, reseting battery and preparing for another
709      * take off.
710      */
711     private void prepareForTakeof()
712     {
713         risen = false;
714         battFills++;
715         double battUsed = battFull - staModule.getStatesByVehilceType(VehicleType.AERIAL_VEHICLE).getBattery();
716         double range = (battLife - battUsed) * (trip / battUsed);
717         System.out.println("range left: " + range + " trip odometer: " + trip + " battery used: " + battUsed);
718         battFull = staModule.getStatesByVehilceType(VehicleType.AERIAL_VEHICLE).getBattery();//reset batteryMeter
719         trip = 0; //reset odometer
720         timeStamp = -1;//reset of the wait method
721         altitude = scanAltitude;
722     }
723 
724     /**
725      * Gets sensor data from ground truth sensor and sets it into the INS sensor
726      * which results in erasing the drift it gained.
727      */
728     private void resetINS()
729     {
730         Location truthLoc = truth.getLocation();
731         Rotation truthRot = truth.getOrientation();
732         lf.setStartLocation(Location.sub(startLoc, truthLoc.getLocation()));
733         StringBuilder sb = new StringBuilder();
734         sb.append(truthLoc.x).append(',').append(truthLoc.y).append(',').append(truthLoc.z).append(',');
735         sb.append(truthRot.roll).append(',').append(truthRot.pitch).append(',').append(truthRot.yaw);
736         bot.getAct().act(new SetSensorEffecter("INS", "INS", "POSE", sb.toString()));
737     }
738 
739     /**
740      * Computes an angle of the robot in degrees.
741      *
742      * @param sx sinus
743      * @param cx cosinus
744      * @return returns angle in degrees.
745      */
746     private double getAngle(double sx, double cx)
747     {
748         if(sx > 0 && cx > 0)
749         {
750             return Math.acos(Math.abs(cx)) * 180 / Math.PI;
751         }
752         else if(sx > 0 && cx <= 0)
753         {
754             return 180 - Math.acos(Math.abs(cx)) * 180 / Math.PI;
755         }
756         else if(sx <= 0 && cx <= 0)
757         {
758             return 180 + Math.acos(Math.abs(cx)) * 180 / Math.PI;
759         }
760         else
761         {
762             return 360 - Math.acos(Math.abs(cx)) * 180 / Math.PI;
763         }
764     }
765 
766     /**
767      * System of setting lateral, linear, altitude and rotational speeds takes
768      * place here. If the robot is close to the base, it has to slow down not to
769      * descend out of desired location. Also when it is close to goal it stops
770      * the forward movement for better dexterity.
771      */
772     private void approachNext()
773     {
774         speed = (scanning)?scanningSpeed:flyingSpeed;
775         rotSpeed = (scanning)?scanningSpeed:flyingSpeed * 2 / 3;
776 
777         double rotVel;
778         double altVel;
779         double linVel = maxLinearVelocity * speed;
780 
781         double diff = getTargetAngle(false);
782         //směr zatáčení musí bejt ne podle dot, ale podle toho, jestli je úhel s osou menší než úhel s osou co svírá ten druhej vektor!!!            
783         rotVel = Math.signum(-diff) * Math.min(Math.abs((double) (maxRotationalVelocity * (-diff / 90))), rotSpeed);
784 
785         if(actLoc.z < seaLevel + 1 && actAlt > scanAltitude && (state != State.LAND && state != State.CHARGING))
786         {
787             altVel = (double) (maxAltitudeVelocity * (seaLevel - actLoc.z) / 6);
788         }
789         else
790         {
791             altVel = (double) (maxAltitudeVelocity * (altitude - actAlt) / 5);
792         }
793         //altVel = (double) ((actLoc.z < seaLevel)?(maxAltitudeVelocity * (seaLevel - actLoc.z) / 5):(maxAltitudeVelocity * (altitude - actAlt) / 5));//we don't want to go lower than some minimum value
794         //altVel = Math.min(altVel, maxAltitudeVelocity / 4);//make sure that it wont take off too quickly
795         if(state == State.AVOIDING || Location.getDistance2D(actLoc, nextLoc) < 2.7)
796         {
797             linVel = (Math.abs(rotVel) >= rotSpeed)?0:linVel;
798         }
799         else
800         {
801             linVel = (Math.abs(rotVel) >= rotSpeed)?linVel * 3 / 5:linVel;
802         }
803         shouldGoWithIt = true;
804         if(Math.abs(rotVel) >= rotSpeed)
805         {
806             noriskCount = Math.max(0, noriskCount - 1);
807             if(state == State.AVOIDING)
808             {
809                 shouldGoWithIt = false;
810             }
811         }
812         //landing - we have to slow down before falling
813         if(state == State.TERMINATE || state == State.CHARGE)
814         {
815             linVel *= Math.min((Location.getDistance2D(actLoc, nextLoc)) / 6, 1);
816         }
817         //landed - we don't need to correct the position while falling
818         if(state == State.LAND || state == State.CHARGING)
819         {
820             bot.getAct().act(new DriveAerial(altVel, 0, 0, 0, false));
821         }
822         else
823         {
824             altVel = (Math.abs(rotVel) >= rotSpeed)?0:altVel;
825             bot.getAct().act(new DriveAerial(altVel, linVel, 0, rotVel, false));
826         }
827     }
828     Location tempNextLoc;
829     State tempState;
830     List<SensorMount> sonarGeo;
831     Map.Entry<String, Double> greatestRiskSonar;//filled by getRiskLevel()
832     private final double sonarThreashold = 4.91d;//value beyond this threashold is eqal to infinity
833 
834     /**
835      * Triggered by robot being close to an obstacle. Computes the most
836      * advantageous direction based on sonar ring.
837      */
838     private void computeDiversion(Map<String, Double> sonars)
839     {
840         //kounknout kde všude jsou překážky a vypočítat bod, kterej je vedle překážky a kam se robot ještě vejde aniž by se dostal do HighRisk
841         //mám paprsek, kde je místa nejmíň, tak kouknu na ty od něj doleva a od něj doprava, sečtu všechny hodnoty a podělim je počtem senzorů a 
842         //vyberu potom bod, kde je první volenj, ale asi taky se skreslením-udělám váženej průměr totiž!
843         boolean leftSide = true;
844         double leftWM = 0;//left weighted mean
845         double rightWM = 0;//right weighted mean
846         double leftFittest = 0;
847         double rightFittest = 0;
848         int leftFindex = 0;
849         int rightFindex = 0;
850 
851         //int targetIndex=getSonarTargetIndex(); //computes the index of the sonar that is closest to target direction
852         //targetIndex ensures that the robot wont be influenced by minor disturbances
853 
854         int greatestRiskIndex = -1;
855         for(int i = 0; i < sonars.size(); i++)
856         {
857             Double entry = sonars.get(sonarOrder[i]);//order of entries does matter at this point
858             if(sonarOrder[i].equals(greatestRiskSonar.getKey()))
859             {
860                 greatestRiskIndex = i;
861                 leftSide = false;
862                 continue;
863             }
864 
865             //computes the odds left and right from the sonar with greatest risk
866             if(leftSide)
867             {
868                 leftWM += entry * entry;//lets get the mean from the second power - it will ensure, that one inf.(>4.8) ray is valued better than six finite.(<4.8)
869                 if(leftFittest < entry || entry > sonarThreashold)//we want the closest open direction to the occupied as possible
870                 {
871                     leftFittest = entry;
872                     leftFindex = i;
873                 }
874             }
875             else
876             {
877                 rightWM += entry * entry;
878                 //we want the first open direction or the best possible
879                 if(rightFittest < entry && rightFittest < sonarThreashold)
880                 {
881                     rightFittest = entry;
882                     rightFindex = i;
883                 }
884             }
885         }
886         if(leftWM < rightWM)
887         {
888             if(rightFindex < 7 && sonars.get(sonarOrder[rightFindex - 1]) < 2.5d)
889             {
890                 RiskLevel righterRisk = getRiskLevel(sonarOrder[rightFindex + 2], sonars.get(sonarOrder[rightFindex + 2]));
891                 if(righterRisk == RiskLevel.NORISK)
892                 {
893                     rightFindex += 2;
894                 }
895             }
896             //když to neni na kraji, tak to bere druhej nejlepší paprsek, ještě by se dal dát
897             else if(/*
898                      * rightFindex - greatestRiskIndex == 1 &&
899                      */rightFindex < 8)
900             {//ale musíme se ujistit, že tím dalším směrem nás nečeká žádná překážka
901                 RiskLevel righterRisk = getRiskLevel(sonarOrder[rightFindex + 1], sonars.get(sonarOrder[rightFindex + 1]));
902                 if(righterRisk == RiskLevel.NORISK)
903                 {
904                     rightFindex++;
905                 }
906             }
907             int targetIndex = getSonarTargetIndex();
908             if(targetIndex > rightFindex && targetIndex < 8)
909             {
910                 RiskLevel targetRiskLevel = getRiskLevel(sonarOrder[targetIndex], sonars.get(sonarOrder[targetIndex]));
911                 if(targetRiskLevel == RiskLevel.NORISK)
912                 {
913                     //vlastně nepotřebujem měnit směr
914                     rightFindex = targetIndex;
915                     tryReleaseDiversion();
916                     return;
917                 }
918             }
919             setDiversionPoint(rightFindex, rightFittest);
920         }
921         else
922         {
923             if(leftFindex > 1 && sonars.get(sonarOrder[leftFindex + 1]) < 1.5d)
924             {
925                 RiskLevel lefterRisk = getRiskLevel(sonarOrder[leftFindex - 2], sonars.get(sonarOrder[leftFindex - 2]));
926                 if(lefterRisk == RiskLevel.NORISK)
927                 {
928                     leftFindex -= 2;
929                 }
930             }
931             else if(/*
932                      * greatestRiskIndex - leftFindex == 1 &&
933                      */leftFindex > 0)
934             {
935                 RiskLevel lefterRisk = getRiskLevel(sonarOrder[leftFindex - 1], sonars.get(sonarOrder[leftFindex - 1]));
936                 if(lefterRisk == RiskLevel.NORISK)
937                 {
938                     leftFindex--;
939                 }
940             }
941             int targetIndex = getSonarTargetIndex();
942             if(targetIndex < leftFindex && targetIndex > 0)
943             {
944                 RiskLevel targetRiskLevel = getRiskLevel(sonarOrder[targetIndex], sonars.get(sonarOrder[targetIndex]));
945                 if(targetRiskLevel == RiskLevel.NORISK)
946                 {
947                     leftFindex = targetIndex;
948                     tryReleaseDiversion();
949                     return;
950                 }
951             }
952             setDiversionPoint(leftFindex, leftFittest);
953         }
954     }
955     private boolean shouldGoWithIt = true;
956 
957     /**
958      * Sets a diversion point in a direction of the fittest sonar based on its
959      * index.
960      *
961      * @param index index of the sonar sensor.
962      * @param fittest fittest value obtained from sonar sensor.
963      */
964     private void setDiversionPoint(int index, double fittest)
965     {
966         Rotation sonarRot = sonarGeo.get(index).getOrientation();
967         //if its left side sonar give it +0.3 rad to go further from an obstacle. if it is right lets give it -0.3 for the same reason
968         double angle = Math.PI / 2 - (sonarRot.yaw + actRot.yaw) + ((greatestRiskSonar.getKey().charAt(0) == 'L')?-0.3:(greatestRiskSonar.getKey().charAt(0) == 'R')?0.3:0);
969         Location actDiv = new Location(-Math.sin(angle) * fittest, -Math.cos(angle) * fittest);
970         Location diversion = actLoc.add(actDiv);
971         lf.setDivPoint(diversion);
972         if(state != State.AVOIDING)
973         {
974             tempState = state;
975             tempNextLoc = nextLoc;
976         }
977 
978         state = State.AVOIDING;
979         nextLoc = diversion;
980     }
981 
982     /**
983      * *
984      * Computes an angle in degrees of the aircraft relative to next Location
985      * that the robot is heading to.
986      *
987      * @param actual Tells the method whether it should be considering temporary
988      * next Location (true) or not (false). Temporary next Location is greater
989      * goal that the robot is not pursuing when avoiding an obstacle.
990      * @return Returns angle in degrees relative to next Location or temp. next
991      * Location based on <B>actual</B>
992      */
993     private double getTargetAngle(boolean actual)
994     {
995         //v1 is vector from actual location to next location
996         double v1x;
997         double v1y;
998         if(actual && state == State.AVOIDING && tempNextLoc != null)
999         {
1000             v1x = tempNextLoc.x - actLoc.x;
1001             v1y = tempNextLoc.y - actLoc.y;
1002         }
1003         else
1004         {
1005             v1x = nextLoc.x - actLoc.x;
1006             v1y = nextLoc.y - actLoc.y;
1007 
1008         }
1009         double v1l = Math.sqrt(v1x * v1x + v1y * v1y);
1010 
1011         double sinv1 = v1y / v1l;
1012         double cosv1 = v1x / v1l;
1013 
1014         double v1Theta = (getAngle(sinv1, cosv1) + 180) % 360;//requiered angle
1015         double v2Theta = actRot.yaw * 180 / Math.PI;//robot actual angle
1016         double diff = v2Theta - v1Theta;//(Math.abs(v2Theta - v1Theta) < Math.abs(v1Theta - v2Theta))?v2Theta - v1Theta:v1Theta - v2Theta;
1017         if(diff > 180)
1018         {
1019             diff = diff - 360;
1020         }
1021         else if(diff < -180)
1022         {
1023             diff = diff + 360;
1024         }
1025         return diff;
1026     }
1027 
1028     /**
1029      * If the robot faces the goal this gets the index of sonar that points
1030      * closest to this direction.
1031      *
1032      * @return returns a sonar index, that points to goal direction.
1033      */
1034     private int getSonarTargetIndex()
1035     {
1036         int sonarIndex = -1;
1037         int count = 0;
1038         double v1Theta = getTargetAngle(true) / 180 * Math.PI;
1039         double minDiv = 7;//2*PI
1040         for(SensorMount sensorMount : sonarGeo)
1041         {
1042             if(minDiv > Math.abs(v1Theta - sensorMount.getOrientation().yaw))
1043             {
1044                 minDiv = Math.abs(v1Theta - sensorMount.getOrientation().yaw);
1045                 sonarIndex = count;
1046             }
1047             count++;
1048         }
1049         return sonarIndex;
1050     }
1051 
1052     /**
1053      * Triggered by robot being too close to an obstacle. It dodges an obstacle
1054      * in a wince maner.
1055      */
1056     private void abortAim()
1057     {
1058         String key = greatestRiskSonar.getKey();
1059         Point2D velocity = highRiskAction.get(key);
1060         getAct().act(new DriveAerial(0, velocity.getX() * 40, velocity.getY() * 40, 0, true));//*40 na procenta
1061         //zastav-ozkoušet, kdy se to stane-> zastavit nebo dát DRIVE a opačný hodnoty než v předchozím a zastavit
1062         //otočit o 180 nebo 360 a vybrat nejlepší cestu ven, nebo zhasnout.
1063     }
1064     int noriskCount = 0;
1065     int riskCount = 0;
1066 
1067     /**
1068      * Checks the sonar ring for possible threat and also issues longterm stuff
1069      * such a jamm count represents.
1070      *
1071      * @return Returns LOW, HIGH or NO RISK based on Sonar sensor reading.
1072      */
1073     private RiskLevel checkSonars()
1074     {
1075         //Map<String, Double> sonars = ((SensorRange) senModule.getSensorsBySensorType(SensorType.RANGE_SENSOR).get(0)).getRanges();
1076         RiskLevel worstThread = getRiskLevel(sonar.getRanges());
1077 
1078         //když je od cíle blíž než je nejhorší risk level, tak to nevadí, že je robot v ohrožení
1079         if(worstThread != RiskLevel.NORISK && greatestRiskSonar.getValue() > Location.getDistance2D(actLoc, nextLoc))
1080         {
1081             return RiskLevel.NORISK;
1082         }
1083 
1084         switch(worstThread)
1085         {
1086             case NORISK:
1087                 noriskCount++;
1088                 if(noriskCount > 6)
1089                 {
1090                     tryReleaseDiversion();
1091                 }
1092                 if(noriskCount > 15)
1093                 {
1094                     riskCount = 0;
1095                 }
1096                 break;
1097             case LOWRISK:
1098                 //if(!delay)
1099                 if(shouldGoWithIt)
1100                 {
1101                     computeDiversion(sonar.getRanges());
1102                 }
1103                 noriskCount = 0;
1104                 riskCount++;
1105                 lf.setLowRiskPoint(actLoc);
1106                 break;
1107             case HIGHRISK:
1108                 abortAim();
1109                 noriskCount = 0;
1110                 lf.setHighRiskPoint(actLoc);
1111                 riskCount++;
1112                 break;
1113         }
1114         return worstThread;
1115     }
1116 
1117     /**
1118      * *
1119      * If the Robot is avoiding some obstacle for a long time(edge of the world,
1120      * target Location in the middle of a tree/house etc.), there is probably no
1121      * point trying any further. Next Location to go after the one currently
1122      * pursued is computed and given to the robot to chase. The robot simply
1123      * leaves out its original goal after some time trying to avoid an obstacle.
1124      */
1125     private void carryOnIfJammed()
1126     {
1127         if(riskCount > jammedLimit * (flyingSpeed / speed))
1128         {
1129             if(state == State.CHARGE || tempState == State.CHARGE || tempState == State.TERMINATE || state == State.TERMINATE)
1130             {
1131                 getAct().act(new DriveAerial(0, -maxLinearVelocity, 0, 0, false));
1132                 riskCount = 0;
1133                 return;
1134             }
1135             if(state == State.AVOIDING)
1136             {
1137                 tryReleaseDiversion();
1138             }
1139             else if(state == State.CONTINUE)
1140             {
1141                 continueScanning();
1142             }
1143             state = State.getNextState(state);
1144             computeNext(state);
1145             riskCount = 0;
1146         }
1147     }
1148 
1149     /**
1150      * Gets risk level from each sonar from the Map sonars and returns the
1151      * greatest risk. It also logs the location of the biggest thread.
1152      *
1153      * @param sonars Map acquired from the sensor module.
1154      * @return returns greates thread to robot.
1155      */
1156     private RiskLevel getRiskLevel(Map<String, Double> sonars)
1157     {
1158         List<Double> sonarValues = new LinkedList<Double>();
1159         for(int i = 0; i < sonars.size(); i++)
1160         {
1161             sonarValues.add(sonars.get(sonarOrder[i]));
1162         }
1163         lf.setSonars(sonarValues);
1164         RiskLevel globalRisk = RiskLevel.NORISK;
1165         double riskValue = sonarThreashold;
1166 
1167         //order of entrys does not matter at this point
1168         for(Map.Entry<String, Double> entry : sonars.entrySet())
1169         {
1170             RiskLevel risk = getRiskLevel(entry);
1171             //due to nonequal conditions for each sonar, we have to get the urgency first(greater urgency at one could be further than no urgency at other)
1172             //and than ask the distance. We want to determine the greatest risk and than the nearest sonar at this risk level
1173 
1174             if(risk.isGreaterRisk(globalRisk))
1175             {
1176                 globalRisk = risk;
1177                 riskValue = entry.getValue();
1178                 greatestRiskSonar = entry;
1179             }
1180             else if(risk == globalRisk)
1181             {
1182                 if(entry.getValue() < riskValue)
1183                 {
1184                     riskValue = entry.getValue();
1185                     greatestRiskSonar = entry;
1186                 }
1187             }
1188         }
1189 
1190         return globalRisk;
1191     }
1192 
1193     /**
1194      * Decides the risk individually based on the name of the sonar and static
1195      * arrays with Low Risk and High Risk Threasholds. (Side sonars have grater
1196      * tollerance than the front ones.)
1197      *
1198      * @param sonar Entry acquired from the sonar sensor Map.
1199      * @return Returns the risk based on the name of the sonar.
1200      */
1201     private RiskLevel getRiskLevel(Map.Entry<String, Double> sonar)
1202     {
1203         return (sonar.getValue() < lowRisk.get(sonar.getKey()))?(sonar.getValue() < highRisk.get(sonar.getKey()))?RiskLevel.HIGHRISK:RiskLevel.LOWRISK:RiskLevel.NORISK;
1204     }
1205 
1206     /**
1207      * Gets risk level from concrete sonar.
1208      *
1209      * @param sonar Name of the sonar
1210      * @param value value of the sonar sensor
1211      * @return Returns risk level of input sonar.
1212      */
1213     private RiskLevel getRiskLevel(String sonar, double value)
1214     {
1215         return (value < lowRisk.get(sonar))?(value < highRisk.get(sonar))?RiskLevel.HIGHRISK:RiskLevel.LOWRISK:RiskLevel.NORISK;
1216     }
1217 
1218     /**
1219      * If a scanning area has width or height greater than 150 meters it is
1220      * considered to be large space.
1221      *
1222      * @return Returns true if large ara is about to be scanned.
1223      */
1224     private boolean isLargeSpace()
1225     {
1226         return ((destHeight > 150) || (destWidth > 150));
1227     }
1228 
1229     
1230     //    /**
1231 //     * If the geometry or configuration modules are ready it issues a query
1232 //     * about the robots configuration and than a query about the sonar geometry.
1233 //     * Please note that this method works in cycles. First it issues a
1234 //     * configuration query, when recieved it issues a geometry query. When
1235 //     * obtained both it can proceed in filling and configurating variables.
1236 //     * complete config information. There is a reason why both queries are
1237 //     * issued at different calls. This method is considered to be called - once
1238 //     * at most - from the logic() which is in fact triggered every time the
1239 //     * state message from the server is recieved. Thus, each query in this
1240 //     * method is issued at different cycle. This fact gives the server necessary
1241 //     * time to process the queries. In other words: The experience with the
1242 //     * USARSim server so far was that it won't process more than one CONF/GEO
1243 //     * message at a time. Which is why we can't call more than one
1244 //     * GETCONF/GETGEO command message in one cycle. Note that there would be
1245 //     * another "else if" branch if we wanted to know any other conf./geo. data
1246 //     * about anything else. The if clause with anothre isReady() would not be
1247 //     * sufficient, we would have to ask for example about the number of messages
1248 //     * conf or geo module has in store.
1249 //     *
1250 //     */
1251     
1252     
1253     /**
1254      * Obtaining of configuration information in several steps. It is unable to
1255      * obtain all data in one logic cycle.
1256      */
1257     private void getConfig()
1258     {
1259         if(!confModule.isReady())
1260         {
1261             confModule.queryConfigurationByType("Robot");
1262         }
1263         else if(!geoModule.isReady())
1264         {
1265             geoModule.queryGeometryByType("Sonar");
1266         }
1267         else if(senModule.isReady())
1268         {
1269             ConfigAerial robotCfg = (ConfigAerial) confModule.getConfigurationsByConfigType(ConfigType.AERIAL_VEHICLE).get(0);
1270             //getParameters
1271             maxLateralVelocity = Double.parseDouble(robotCfg.getFeatureValueBy("MaxLateralVelocity"));
1272             maxLinearVelocity = Double.parseDouble(robotCfg.getFeatureValueBy("MaxLinearVelocity"));
1273             maxAltitudeVelocity = Double.parseDouble(robotCfg.getFeatureValueBy("MaxAltitudeVelocity"));
1274             maxRotationalVelocity = Double.parseDouble(robotCfg.getFeatureValueBy("MaxRotationalVelocity"));
1275             //set startLoc
1276             //SensorINS ins = (SensorINS) (senModule.getSensorsBySensorType(SensorType.INS_SENSOR).get(0));
1277             startLoc = ins.getLocation();//((SensorGroundTruth) senModule.getSensorsBySensorType(SensorType.GROUND_TRUTH).get(0)).getLocation();//
1278             //prepare variables for the flight.
1279             singleFlight = !isLargeSpace();
1280             //TODO: tohle se mi nějak nezdá, opravdu to dělá, co má? -> jestli v actLoc je správná hodnota? zeroPoint?
1281             actLoc = zeroPoint;
1282             prevLoc = zeroPoint;
1283             lf.setStartLocation(zeroPoint);
1284             if(singleFlight)
1285             {
1286                 nextLoc = getClosestCorner(destination, destWidth, destHeight, new Location(0, 0, 0));
1287                 setupSteps(destination, nextLoc);
1288             }
1289             else
1290             {
1291                 initMultipleRun();
1292                 setupMultiple();
1293             }
1294             battFull = staModule.getStatesByVehilceType(VehicleType.AERIAL_VEHICLE).getBattery();
1295             startTime = System.currentTimeMillis();//staModule.getStatesByVehilceType(VehicleType.AERIAL_VEHICLE).getTime();
1296             //saveGeometryOfSonars
1297             sonarGeo = ((GeoSensorEffecter) geoModule.getGeometriesByGeometryType(GeometryType.SENSOR_EFFECTER).get(0)).getSensorMountCollection();
1298 
1299             parametersObtained = true;         //setFlag
1300         }
1301     }
1302 
1303     /**
1304      * Initialization of modules used within this robot.
1305      *
1306      * @param bot Necessary parameter for hooking listeners and for sending
1307      * commands
1308      */
1309     @Override
1310     public void prepareBot(USAR2004Bot bot)
1311     {
1312         super.prepareBot(bot);
1313 
1314         senModule = SensorMasterModuleQueued.getModuleInstance(bot);
1315         geoModule = GeometryMasterModule.getModuleInstance(bot);
1316         confModule = ConfigMasterModule.getModuleInstance(bot);
1317         resModule = ResponseModule.getModuleInstance(bot);
1318         staModule = StateMasterModule.getModuleInstance(bot);
1319     }
1320     private SensorMasterModuleQueued senModule;
1321     private GeometryMasterModule geoModule;
1322     private ConfigMasterModule confModule;
1323     private ResponseModule resModule;
1324     private StateMasterModule staModule;
1325     static ScanPreview lf = null;
1326 
1327     public static void main(String[] args)
1328     {
1329         SwingUtilities.invokeLater(new Runnable()
1330         {
1331             @Override
1332             public void run()
1333             {
1334                 try
1335                 {
1336                     lf = new ScanPreview();
1337                     lf.runScanPreview(); // Calling Login Frame
1338                     lf.show();
1339 
1340                 }
1341                 catch(Exception e)
1342                 {
1343                     System.out.println("error");
1344                 }
1345             }
1346         });
1347 
1348         try
1349         {
1350             new USAR2004BotRunner(AerialVehicle.class, "PogamutBotBot", "127.0.0.1", 3000).setMain(true).setLogLevel(Level.OFF).startAgent();
1351 
1352         }
1353         catch(Exception e)
1354         {
1355             System.out.println(e.getCause());
1356         }
1357     }
1358 }