View Javadoc

1   package cz.cuni.amis.pogamut.usar2004.communication.messages.usarinfomessages;
2   
3   import java.util.*;
4   import javax.vecmath.*;
5   import cz.cuni.amis.pogamut.base.communication.worldview.event.*;
6   import cz.cuni.amis.pogamut.base.communication.translator.event.*;
7   import cz.cuni.amis.pogamut.base3d.worldview.object.*;
8   import cz.cuni.amis.pogamut.usar2004.communication.messages.*;
9   import cz.cuni.amis.pogamut.usar2004.communication.messages.datatypes.CustomTypes.*;
10  import cz.cuni.amis.pogamut.usar2004.communication.messages.datatypes.*;
11  
12  /**
13   *
14   * Sensor messages contain the sensor data. Sensor message Every sensor message
15   * starts with “SEN”. After it is an optional Time segment, {Time float}, that
16   * reports the current time in seconds in the virtual world. Whether the Time
17   * segment will appear or not is decided by the sensor’s ‘bWithTimeStamp’
18   * variable. For details information, please read section 10 in USARSim manual
19   * v3.1.3. Please note that the Sensor message parameters depend on the type of
20   * sensor that the information is being reported.
21   *
22   * Corresponding GameBots message is SEN.
23   *
24   */
25  public class SensorMessage extends GBEvent implements IWorldEvent, IWorldChangeEvent
26  {
27      public SensorMessage(String Type, double Time, String Name, double Duration, double FOV, int Fix, double Loudness, double Prob, double Resolution, int Satellites, String Status, String Gas, double Density, boolean Visible, double Dist, double Radius, double Corona)
28      {
29          this.Type = Type;
30          this.Time = Time;
31          this.Name = Name;
32          this.Duration = Duration;
33          this.FOV = FOV;
34          this.Fix = Fix;
35          this.Loudness = Loudness;
36          this.Prob = Prob;
37          this.Resolution = Resolution;
38          this.Satellites = Satellites;
39          this.Status = Status;
40          this.Gas = Gas;
41          this.Density = Density;
42          this.Visible = Visible;
43          this.Radius = Radius;
44          this.Dist = Dist;
45          this.Corona = Corona;
46  
47          //range-type, name-range..,
48          //laser-type,name,resolution,fov,range(...)
49          //odometry-type,name,pose(x,y,theta)
50          //gps-type, name, latitude(int,double,char), longitude, fix, satelites
51          //ins-type, name location, orientation...(?)
52          //encoder-type, (name,tick)...
53          //touch-type, (name,touch)...
54          //rfid-type, TAG-from type, name, id, location...
55          //victiom-type, name, partname, location...
56          //humanmotion-type, name, prob
57          //sound-type, name, loudness, duration
58      }
59      /**
60       * Example how the message looks like - used during parser tests.
61       */
62      public static final String PROTOTYPE = "SEN {Type text} {Time 0} {Name text} {Duration 0} {FOV 0} {Fix 0} {Loudness 0} {Prob 0} {Resolution 0} {Satellites 0} {Status text}";
63      /////// Properties BEGIN
64      protected String Type = null;
65  
66      /**
67       * Type describes the sensor type. It will be one of the following values:
68       * "RFID”, “RangeScanner”, “IR”, "IRScanner", "Tachometer", "Helper",
69       * "Sonar", "Odometry", "GPS", "INS", "INU", "Encoder", "Touch",
70       * "VictSensor","HumanMotion", "Sound" or "GroundTruth".
71       *
72       * @return Type of the sensor.
73       */
74      public String getType()
75      {
76          return Type;
77      }
78      protected double Time = 0;
79  
80      /**
81       * Timestamp form the UT since server start in seconds. Note that time is
82       * optional parameter.
83       *
84       * @return Returns seconds elapsed from the start of the server.
85       */
86      public double getTime()
87      {
88          return Time;
89      }
90      protected String Name = null;
91  
92      /**
93       * Name of the sensor.
94       *
95       * @return Returns name of the sensor
96       */
97      public String getName()
98      {
99          return Name;
100     }
101     //Range Sensor - Type, Name/Range...
102     //Sensor name/Range in meters
103     protected Map<String, Double> RangeRanges = new HashMap<String, Double>();
104 
105     /**
106      * Map indexed by string is used to collect data of range sensor. ‘Dtring’
107      * is the sensor name, ‘Double’ is the range value in meters.
108      *
109      * @return Returns Map of ranges from range sensor(Sonar).
110      */
111     public Map<String, Double> getRangeRanges()
112     {
113         return RangeRanges;
114     }
115 
116     /**
117      * Used by Yylex to fill the RangeRanges Map.
118      *
119      * @param Name Name of the range sensor.
120      * @param Range Valued of the range sensor.
121      */
122     public void addRange(String Name, Double Range)
123     {
124         RangeRanges.put(Name, Range);
125     }
126     //Laser Sensor - Type, Name, Resolution, FOV, Range(...)
127     protected double Resolution = 0;
128 
129     /**
130      * It is the sensor’s resolution in radians. With FOV, we can calculate the
131      * number of the data in the Range segment.
132      *
133      * @return Returns resolution of the sensor.
134      */
135     public double getResolution()
136     {
137         return Resolution;
138     }
139     //Sensors field of view in radians
140     protected double FOV = 0;
141 
142     /**
143      * FOV is the sensor’s field of view in radians.
144      *
145      * @return Returns field of view in radians.
146      */
147     public double getFOV()
148     {
149         return FOV;
150     }
151     protected List<Double> LaserRanges = new ArrayList<Double>();
152 
153     /**
154      * LaserRanges is a series of range values in meters.
155      *
156      * @return Returns List of double values representing distance in meters.
157      */
158     public List<Double> getLaserRanges()
159     {
160         return LaserRanges;
161     }
162     //Odometry sensor - Type, Name, Pose(x,y,theta)
163     //estimated robots position relative to the start position in meters(first two components) and theta - the head angle in radians(relative to the start position)
164     protected OdometryPose OdoPose = new OdometryPose();
165 
166     /**
167      * OdoPose is the estimated robot position relative to the start point in
168      * meters. ‘theta’ is the head angle in radians relative to the start
169      * orientation.
170      *
171      * @return Returns OdometryPose value.
172      */
173     public OdometryPose getOdoPose()
174     {
175         return OdoPose;
176     }
177     //GPS sensor - Type, Name, Latitude(int,double,char), Longitude, Fix, Satellites
178     protected Latitude Latitude = new Latitude();
179 
180     /**
181      * ‘int’, ’double’, ’char’ provide the latitude degree, minute (as a
182      * decimal), and cardinal description (i.e. ‘N’ or ‘S’), respectively. There
183      * are only two possible values for the ‘char’ parameter: ‘N’ for North and
184      * ‘S’ for South.
185      *
186      * @return Returns Latitude value of the sensor.
187      */
188     public Latitude getLatitude()
189     {
190         return Latitude;
191     }
192     protected Longitude Longitude = new Longitude();
193 
194     /**
195      * ‘int’, ’float’, ’char’ provide the longitude degree, minute (as a
196      * decimal), and cardinal description (i.e. ‘E’ or ‘W’), respectively. There
197      * are only two possible values for the ‘char’ parameter: ‘E’ for East and
198      * ‘W’ for West.
199      *
200      * @return Returns Longitude value of the sensor.
201      */
202     public Longitude getLongitude()
203     {
204         return Longitude;
205     }
206     protected int Fix = 0;
207 
208     /**
209      * ‘int’ indicates whether or not a position was acquired. The fix is the
210      * same as the GGA format. Namely, a value of 0 means that the GPS sensor
211      * failed to acquire a position and a value of 1 means that a position was
212      * acquired.
213      *
214      * @return Returns 0 - failed to acquire a position or 1 - success.
215      */
216     public int getFix()
217     {
218         return Fix;
219     }
220     //Number of satellites availible
221     protected int Satellites = 0;
222 
223     /**
224      * ‘int’ gives the number of satellites tracked by the GPS sensor. This
225      * number is an inexplicit source of accuracy. The more satellites are
226      * tracked, the higher the position accuracy.
227      *
228      * @return Returns number of active GPS satellite connections.
229      */
230     public int getSatellites()
231     {
232         return Satellites;
233     }
234     //INS Sensor - Type, Name, Location..., Orientation...
235     //a.k.a. The Inertial Navigation Sensor is a sensor that provides estimated location and orientation of the vehicle,
236     //based on measurements of angular velocity and linear acceleration relative to the vehicle current pose
237     protected List<Location> Locations = new ArrayList<Location>();
238 
239     /**
240      * List of Locations used by RFID sensor to determine where are various RFID
241      * Tags or by Victiom sensor to determine locations of bodys. Also used by
242      * INS sensor to determine robots location
243      *
244      * @return Returns list of Locations.
245      */
246     public List<Location> getLocations()
247     {
248         return Locations;
249     }
250     protected List<Rotation> Orientations = new ArrayList<Rotation>();
251 
252     /**
253      * INS sensor entry in USARSim manual v3.1.3 suggests that it should need
254      * more than one record of Orienation, but the experience was different.
255      * Still we use list of Rotations to support multiple entry. Mainly used for
256      * determination of robots Orientation.
257      *
258      * @return Returns List of Rotations.
259      */
260     public List<Rotation> getOrientations()
261     {
262         return Orientations;
263     }
264     //Encoder sensor - Type, Name/Tick...
265     //Sensor name/tick count
266     protected Map<String, Integer> EncoderTicks = new HashMap<String, Integer>();
267 
268     /**
269      * String is the sensor name. Integer is the tick count. Example:
270      *
271      * SEN {Type Encoder} {Name ECLeft Tick -61} {Name ECRight Tick -282} {Name
272      * ECTilt Tick 0} {Name ECPan Tick 0}
273      *
274      * @return Returns Map of Encoder couples String-Integers.
275      */
276     public Map<String, Integer> getEncoderTicks()
277     {
278         return EncoderTicks;
279     }
280     //Touch sensor - Type, Name/Bool...
281     //Sensor name/touch count
282     protected Map<String, Boolean> Touches = new HashMap<String, Boolean>();
283 
284     /**
285      * String is the sensor name. Boolean indicates whether the sensor is
286      * touching something. Value ‘True’ means the sensor is touching something.
287      *
288      * @return Returns map of touch names and values.
289      */
290     public Map<String, Boolean> getTouches()
291     {
292         return Touches;
293     }
294     //RFID sensor - Type, Name, ID..., Location... //tag I would say, is the ID
295     //RFID tags are simulated by implementing the class USARBot.RFIDTag class in the Unreal Editor when editing a map.
296     //This class contains an integer id and a bool bSingleshot variable that determines whether the tag is a single shot
297     //tag or a multi shot tag. They are deployed by placing them in UnrealEd. If the tag's ID is set to -1(default),
298     //then the tag id will be set to a unique value automatically. Other values for the id will not be changed. If the
299     //tags are within the MaxRange of the RFID sensor mounted on the robot then the server sends the following message:
300     protected List<Integer> IDs = new ArrayList<Integer>();
301 
302     /**
303      * Used by RFID sensor. RFID tags are simulated by implementing the class
304      * USARBot.RFIDTag class in the Unreal Editor when editing a map. This class
305      * contains an integer id and a boolean bSingleshot variable that determines
306      * whether the tag is a single shot tag or a multi shot tag. They are
307      * deployed by placing them in UnrealEd. If the tag’s id is set to -1 (the
308      * default), then the tag id will be set to a unique value automatically.
309      * Other values for the id will not be changed. If the tags are within the
310      * MaxRange of the RFID sensor mounted on the robot then the server sends
311      * the following message to the client:
312      *
313      * @return Returns a list of RFID IDs.
314      */
315     public List<Integer> getIDs()
316     {
317         return IDs;
318     }
319     //Victim sensor - Type, Name, PartName..., Location...
320     protected List<String> PartNames = new ArrayList<String>();
321 
322     /**
323      * PartName is the name of the victim part that was discovered by the
324      * sensor. It can be one of 7 values: “Head”, “Arm”, “Hand”, “Chest”,
325      * “Pelvis”, “Leg”, and “Foot”. Please note that the sensor does not
326      * differentiate between real victim’s part and false alarms. It is up to
327      * the controller to perform this task.
328      *
329      * @return Returns a list of victim body part names.
330      */
331     public List<String> getPartNames()
332     {
333         return PartNames;
334 
335     }
336     //Added after testing - not in the documentation!
337     protected String Status = null;
338 
339     /**
340      * Status is not in USARSim manual v3.1.3. And was added to full support of
341      * Victim sensor.
342      *
343      * @return Returns the status of Victim sensor.
344      */
345     public String getStatus()
346     {
347         return Status;
348     }
349     //Human Motion Detector - Type, Name, Prob
350     //Probability that it is actual human motion detected
351     protected double Prob = 0;
352 
353     /**
354      * Prob is the probability of it’s human motion.
355      *
356      * @return Returns the probability of Human motion detector.
357      */
358     public double getProb()
359     {
360         return Prob;
361     }
362     //Sound sensor - Type, Name, Loudness, Duration
363     protected double Loudness = 0;
364 
365     /**
366      * Loudnes from the sound sensor.
367      *
368      * @return Returns loundness of a sound.
369      */
370     public double getLoudness()
371     {
372         return Loudness;
373     }
374     protected double Duration = 0;
375 
376     /**
377      * Duration of a sound from the sound sensor.
378      *
379      * @return Returns a drutaion of a sound.
380      */
381     public double getDuration()
382     {
383         return Duration;
384     }
385     //Tachometer - new type not documented - Type, Name, Velocity, Position
386     protected Point4d Velocity = null;
387 
388     /**
389      * Velocity of the robot measured by Tachometer. Not in the USARSim manual
390      * v3.1.3.
391      *
392      * @return Returns velocity from Tachometer.
393      */
394     public Point4d getVelocity()
395     {
396         return Velocity;
397     }
398     protected Point4d Position = null;
399 
400     /**
401      * Position of the robot measured by Tachometer. Not in the USARSim manual
402      * v3.1.3.
403      *
404      * @return Returns position from Tachometer.
405      */
406     public Point4d getPosition()
407     {
408         return Position;
409     }
410     //added after trying DogBot-
411     protected Velocity Acceleration = null;
412 
413     /**
414      * Acceleration from Acceleration Sensor. Not in USARSim manual v3.1.3.
415      *
416      * @return Returns acceleration from accel sensor.
417      */
418     public Velocity getAcceleration()
419     {
420         return Acceleration;
421     }
422     //added after trying StereoP2AT
423     protected String Gas = null;
424 
425     /**
426      * Gas sensor measures type and density. Default value is CO2. There is
427      * Resolution and Range information offered by GetConf. Not in USARSim
428      * manual v3.1.3.
429      *
430      * @return Returns type of a gas measured by Gas sensor.
431      */
432     public String getGas()
433     {
434         return Gas;
435     }
436     protected double Density = 0;
437 
438     /**
439      * Gas sensor measures type and density. There is Resolution and Range
440      * information offered by GetConf. Not in USARSim manual v3.1.3.
441      *
442      * @return Returns density of a gas measured by Gas sensor.
443      */
444     public double getDensity()
445     {
446         return Density;
447     }
448     //added along with implementing AIBO - ERS sample bot. this is new undocumented sensor for tracking soccer ball from aibo camera
449     protected boolean Visible = false;
450 
451     /**
452      * AIBO - ERS robot uses tracking ball sensor, that recognises a soccer ball
453      * from camera. Not in USARSim manual v3.1.3.
454      *
455      * @return Returns wether the soccer ball is visible or not.
456      */
457     public boolean isVisible()
458     {
459         return Visible;
460     }
461     protected Point2d Pos2D = null;
462 
463     /**
464      * AIBO - ERS robot uses tracking ball sensor, that recognises a soccer ball
465      * from camera. Not in USARSim manual v3.1.3.
466      *
467      * @return Returns position on the camera of the soccer ball.
468      */
469     public Point2d getPos2D()
470     {
471         return Pos2D;
472     }
473     protected Location Pos3D = null;
474 
475     /**
476      * AIBO - ERS robot uses tracking ball sensor, that recognises a soccer ball
477      * from camera. Not in USARSim manual v3.1.3.
478      *
479      * @return Returns location of the soccer ball in the environment.
480      */
481     public Location getPos3D()
482     {
483         return Pos3D;
484     }
485     protected double Radius = 0;
486 
487     /**
488      * AIBO - ERS robot uses tracking ball sensor, that recognises a soccer ball
489      * from camera. Not in USARSim manual v3.1.3.
490      *
491      * @return Returns radius of the soccer ball.
492      */
493     public double getRadius()
494     {
495         return Radius;
496     }
497     protected double Dist = 0;
498 
499     /**
500      * AIBO - ERS robot uses tracking ball sensor, that recognises a soccer ball
501      * from camera. Not in USARSim manual v3.1.3.
502      *
503      * @return Returns distance of the soccer ball from the robot.
504      */
505     public double getDistance()
506     {
507         return Dist;
508     }
509     protected double Corona = 0;
510 
511     /**
512      * AIBO - ERS robot uses tracking ball sensor, that recognises a soccer ball
513      * from camera. Not in USARSim manual v3.1.3.
514      *
515      * @return Returns corona of the soccer ball.
516      */
517     public double getCorona()
518     {
519         return Corona;
520     }
521 
522     /**
523      * Cloning constructor.
524      */
525     public SensorMessage(SensorMessage original)
526     {
527         this.EncoderTicks.putAll(original.EncoderTicks);
528         this.Type = original.Type;
529         this.Time = original.Time;
530         this.Name = original.Name;
531         this.Duration = original.Duration;
532         this.FOV = original.FOV;
533         this.Fix = original.Fix;
534         this.Loudness = original.Loudness;
535         this.Prob = original.Prob;
536         this.Resolution = original.Resolution;
537         this.Satellites = original.Satellites;
538         this.IDs.addAll(original.IDs);
539         this.LaserRanges.addAll(original.LaserRanges);
540         this.Locations.addAll(original.Locations);
541         this.Longitude = original.Longitude;
542         this.Latitude = original.Latitude;
543         this.OdoPose = original.OdoPose;
544         this.Orientations.addAll(original.Orientations);
545         this.PartNames.addAll(original.PartNames);
546         this.Position = original.Position;
547         this.RangeRanges.putAll(original.RangeRanges);
548         this.Touches.putAll(original.Touches);
549         this.Velocity = original.Velocity;
550         this.Acceleration = original.Acceleration;
551         this.Status = original.Status;
552         this.Density = original.Density;
553         this.Gas = original.Gas;
554         this.Visible = original.Visible;
555         this.Pos2D = original.Pos2D;
556         this.Pos3D = original.Pos3D;
557         this.Radius = original.Radius;
558         this.Dist = original.Dist;
559         this.Corona = original.Corona;
560     }
561 
562     /**
563      * Used by Yylex to create empty message then to fill it's protected fields
564      * (Yylex is in the same package).
565      */
566     public SensorMessage()
567     {
568     }
569 
570     @Override
571     public String toString()
572     {
573         StringBuilder buf = new StringBuilder();
574         //"SEN {Type text} {Name 0} {Duration 0} {FOV 0} {Fix 0} {Loudness 0} {Prob 0} {Resolution 0} {Satellites 0}";
575         buf.append(super.toString() + " | "
576                 + "Type = "
577                 + String.valueOf(Type) + " | "
578                 + "Time = "
579                 + String.valueOf(Time) + " | "
580                 + "Name = "
581                 + String.valueOf(Name) + " | "
582                 + "Duration = "
583                 + String.valueOf(Duration) + " | "
584                 + "FOV = "
585                 + String.valueOf(FOV) + " | "
586                 + "Fix = "
587                 + String.valueOf(Fix) + " | "
588                 + "Loudness = "
589                 + String.valueOf(Loudness) + " | "
590                 + "Prob = "
591                 + String.valueOf(Prob) + " | "
592                 + "Resolution = "
593                 + String.valueOf(Resolution) + " | "
594                 + "Satellites = "
595                 + String.valueOf(Satellites) + " | "
596                 + "Status = "
597                 + String.valueOf(Status) + " | "
598                 + "Gas = "
599                 + String.valueOf(Gas) + " | "
600                 + "Density = "
601                 + String.valueOf(Density) + " | "
602                 + "Radius = "
603                 + String.valueOf(Radius) + " | "
604                 + "Corona = "
605                 + String.valueOf(Corona) + " | "
606                 + "Visible = "
607                 + String.valueOf(Visible) + " | "
608                 + "Dist = "
609                 + String.valueOf(Dist) + " | ");
610 
611         if(!RangeRanges.isEmpty())
612         {
613             Iterator it = RangeRanges.entrySet().iterator();
614             while(it.hasNext())
615             {
616                 Map.Entry en = (Map.Entry) it.next();
617                 buf.append(" ").append(en.getKey()).append(" ").append(en.getValue()).append(",");
618             }
619             buf.append(" | ");
620         }
621 
622 
623         if(!Touches.isEmpty())
624         {
625             Iterator it = Touches.entrySet().iterator();
626             while(it.hasNext())
627             {
628                 Map.Entry en = (Map.Entry) it.next();
629                 buf.append(" ").append(en.getKey()).append(" = ").append(en.getValue()).append(" ");
630             }
631             buf.append(" | ");
632         }
633 
634 
635         if(Velocity != null)
636         {
637             buf.append("Velocity = ").append(String.valueOf(Velocity.w)).append(String.valueOf(Velocity.x)).append(String.valueOf(Velocity.y)).append(String.valueOf(Velocity.z)).append(" | ");
638         }
639 
640         if(Acceleration != null)
641         {
642             buf.append("Acceleration = ").append(String.valueOf(Acceleration.x)).append(String.valueOf(Acceleration.y)).append(String.valueOf(Acceleration.z)).append(" | ");
643         }
644 
645         if(!IDs.isEmpty())
646         {
647             for(Integer i : IDs)
648             {
649                 buf.append("ID = ").append(i.toString()).append(" ");
650             }
651             buf.append(" | ");
652         }
653 
654 
655         if(!LaserRanges.isEmpty())
656         {
657             buf.append("LaserRange = ");
658             for(Double i : LaserRanges)
659             {
660                 buf.append(i.toString()).append(" ");
661             }
662             buf.append(" | ");
663         }
664 
665 
666         if(!Locations.isEmpty())
667         {
668             for(Location i : Locations)
669             {
670                 buf.append("Location = ").append(i.x).append(" ").append(i.y).append(" ").append(i.z).append(" ");
671             }
672             buf.append(" | ");
673         }
674 
675 
676         if(!Orientations.isEmpty())
677         {
678             for(Rotation i : Orientations)
679             {
680                 buf.append("Orientation = ").append(i.yaw).append(" ").append(i.roll).append(" ").append(i.pitch).append(" ");
681             }
682             buf.append(" | ");
683         }
684 
685 
686         if(Longitude != null)
687         {
688             buf.append("Longitude = ").append(String.valueOf(Longitude.getDegree())).append(" ").append(String.valueOf(Longitude.getMinute())).append(" ").append(String.valueOf(Longitude.getCardinal() + " | "));
689         }
690 
691         if(Latitude != null)
692         {
693             buf.append("Latitude = ").append(String.valueOf(Latitude.getDegree())).append(" ").append(String.valueOf(Latitude.getMinute())).append(" ").append(String.valueOf(Latitude.getCardinal() + " | "));
694         }
695 
696         if(OdoPose != null)
697         {
698             buf.append("OdoPose = ").append(String.valueOf(OdoPose.getX())).append(" ").append(String.valueOf(OdoPose.getY())).append(" ").append(String.valueOf(OdoPose.getTheta() + " | "));
699         }
700 
701         if(!PartNames.isEmpty())
702         {
703             for(String i : PartNames)
704             {
705                 buf.append("PartNames = ").append(i).append(" ");
706             }
707             buf.append(" | ");
708         }
709 
710 
711         if(Position != null)
712         {
713             buf.append("Position = ").append(String.valueOf(Position.w)).append(String.valueOf(Position.x)).append(String.valueOf(Position.y)).append(String.valueOf(Position.z)).append(" | ");
714         }
715 
716         if(Pos3D != null)
717         {
718             buf.append("Pos3D = ").append(String.valueOf(Pos3D.x)).append(String.valueOf(Pos3D.y)).append(String.valueOf(Pos3D.z)).append(" | ");
719         }
720         if(Pos2D != null)
721         {
722             buf.append("Pos2D = ").append(String.valueOf(Pos2D.x)).append(String.valueOf(Pos2D.y)).append(" | ");
723         }
724 
725         return buf.toString();
726 
727     }
728 
729     /**
730      * Gets all properties and values to create a HTML formated string;
731      *
732      * @return Returns all properties in HTML format
733      */
734     public String toHtmlString()
735     {
736         StringBuilder buf = new StringBuilder();
737         buf.append(super.toString()
738                 + "<b>Type</b> : "
739                 + String.valueOf(Type)
740                 + " <br/> "
741                 + "<b>Time</b> : "
742                 + String.valueOf(Time)
743                 + " <br/> "
744                 + "<b>Name</b> : "
745                 + String.valueOf(Name)
746                 + " <br/> "
747                 + "<b>Duration</b> : "
748                 + String.valueOf(Duration)
749                 + " <br/> "
750                 + "<b>FOV</b> : "
751                 + String.valueOf(FOV)
752                 + " <br/> "
753                 + "<b>Fix</b> : "
754                 + String.valueOf(Fix)
755                 + " <br/> "
756                 + "<b>Loudness</b> : "
757                 + String.valueOf(Loudness)
758                 + " <br/> "
759                 + "<b>Prob</b> : "
760                 + String.valueOf(Prob)
761                 + " <br/> "
762                 + "<b>Resolution</b> : "
763                 + String.valueOf(Resolution)
764                 + " <br/> "
765                 + "<b>Satellites</b> : "
766                 + String.valueOf(Satellites)
767                 + " <br/> "
768                 + "<b>Status</b> : "
769                 + String.valueOf(Status)
770                 + " <br/> "
771                 + "<b>Gas</b> : "
772                 + String.valueOf(Gas)
773                 + " <br/> "
774                 + "<b>Density</b> : "
775                 + String.valueOf(Density)
776                 + " <br/> "
777                 + "<b>Dist</b> : "
778                 + String.valueOf(Dist)
779                 + " <br/> "
780                 + "<b>Radius</b> : "
781                 + String.valueOf(Radius)
782                 + " <br/> "
783                 + "<b>Corona</b> : "
784                 + String.valueOf(Corona)
785                 + " <br/> "
786                 + "<b>Visible</b> : "
787                 + String.valueOf(Visible)
788                 + " <br/> ");
789 
790         if(!RangeRanges.isEmpty())
791         {
792             Iterator it = RangeRanges.entrySet().iterator();
793             while(it.hasNext())
794             {
795                 Map.Entry en = (Map.Entry) it.next();
796                 buf.append(" ").append(en.getKey()).append(" ").append(en.getValue()).append(" <br/> ");
797             }
798         }
799 
800         if(!Touches.isEmpty())
801         {
802             Iterator it = Touches.entrySet().iterator();
803             while(it.hasNext())
804             {
805                 Map.Entry en = (Map.Entry) it.next();
806                 buf.append(" ").append(en.getKey()).append(" = ").append(en.getValue()).append(" <br/> ");
807             }
808         }
809 
810         if(Velocity != null)
811         {
812             buf.append("<b>Velocity</b> : ").append(String.valueOf(Velocity.w)).append(String.valueOf(Velocity.x)).append(String.valueOf(Velocity.y)).append(String.valueOf(Velocity.z)).append(" <br/> ");
813         }
814 
815         if(Acceleration != null)
816         {
817             buf.append("<b>Acceleration</b> : ").append(String.valueOf(Acceleration.x)).append(String.valueOf(Acceleration.y)).append(String.valueOf(Acceleration.z)).append(" <br/> ");
818         }
819 
820         if(!IDs.isEmpty())
821         {
822             for(Integer i : IDs)
823             {
824                 buf.append("<b>ID</b> : ").append(i.toString()).append(" <br/>  ");
825             }
826         }
827 
828         if(!LaserRanges.isEmpty())
829         {
830             buf.append("<b>LaserRange</b> : ");
831             for(Double i : LaserRanges)
832             {
833                 buf.append(i.toString()).append(" <br/>  ");
834             }
835         }
836 
837         if(!Locations.isEmpty())
838         {
839             for(Location i : Locations)
840             {
841                 buf.append("<b>Location</b> : ").append(i.x).append(" ").append(i.y).append(" ").append(i.z).append(" <br/>  ");
842             }
843         }
844 
845         if(!Orientations.isEmpty())
846         {
847             for(Rotation i : Orientations)
848             {
849                 buf.append("<b>Orientation</b> : ").append(i.yaw).append(" ").append(i.roll).append(" ").append(i.pitch).append(" <br/>  ");
850             }
851         }
852         if(Longitude != null)
853         {
854             buf.append("<b>Longitude</b> : ").append(String.valueOf(Longitude.getDegree())).append(" ").append(String.valueOf(Longitude.getMinute())).append(" ").append(String.valueOf(Longitude.getCardinal() + " <br/> "));
855         }
856 
857         if(Latitude != null)
858         {
859             buf.append("<b>Latitude</b> : ").append(String.valueOf(Latitude.getDegree())).append(" ").append(String.valueOf(Latitude.getMinute())).append(" ").append(String.valueOf(Latitude.getCardinal() + " <br/>  "));
860         }
861 
862         if(OdoPose != null)
863         {
864             buf.append("<b>OdoPose</b> : ").append(String.valueOf(OdoPose.getX())).append(" ").append(String.valueOf(OdoPose.getY())).append(" ").append(String.valueOf(OdoPose.getTheta() + " <br/> "));
865         }
866 
867         if(!PartNames.isEmpty())
868         {
869             for(String i : PartNames)
870             {
871                 buf.append("<b>PartNames</b> : ").append(i).append(" <br/> ");
872             }
873         }
874 
875         if(Position != null)
876         {
877             buf.append("<b>Position</b> : ").append(String.valueOf(Position.w)).append(String.valueOf(Position.x)).append(String.valueOf(Position.y)).append(String.valueOf(Position.z)).append(" <br/> ");
878         }
879         if(Pos3D != null)
880         {
881             buf.append("<b>Pos3D</b> : ").append(String.valueOf(Pos3D.x)).append(String.valueOf(Pos3D.y)).append(String.valueOf(Pos3D.z)).append(" <br/> ");
882         }
883         if(Pos2D != null)
884         {
885             buf.append("<b>Pos2D</b> : ").append(String.valueOf(Pos2D.x)).append(String.valueOf(Pos2D.y)).append(" <br/> ");
886         }
887 
888         return buf.toString();
889     }
890 }