]> git.mxchange.org Git - flightgear.git/blob - src/Instrumentation/gps.hxx
Merge branch 'work4' into next
[flightgear.git] / src / Instrumentation / gps.hxx
1 // gps.hxx - distance-measuring equipment.
2 // Written by David Megginson, started 2003.
3 //
4 // This file is in the Public Domain and comes with no warranty.
5
6
7 #ifndef __INSTRUMENTS_GPS_HXX
8 #define __INSTRUMENTS_GPS_HXX 1
9
10 #include <cassert>
11
12 #include <simgear/props/props.hxx>
13 #include <simgear/structure/subsystem_mgr.hxx>
14 #include <simgear/math/SGMath.hxx>
15
16 #include "Navaids/positioned.hxx"
17
18 // forward decls
19 class SGRoute;
20 class FGRouteMgr;
21 class FGAirport;
22 class GPSListener;
23
24 class SGGeodProperty
25 {
26 public:
27     SGGeodProperty()
28     {
29     }
30         
31     void init(SGPropertyNode* base, const char* lonStr, const char* latStr, const char* altStr = NULL);    
32     void init(const char* lonStr, const char* latStr, const char* altStr = NULL);    
33     void clear();    
34     void operator=(const SGGeod& geod);    
35     SGGeod get() const;
36 private:
37     SGPropertyNode_ptr _lon, _lat, _alt;
38 };
39
40 /**
41  * Model a GPS radio.
42  *
43  * Input properties:
44  *
45  * /position/longitude-deg
46  * /position/latitude-deg
47  * /position/altitude-ft
48  * /environment/magnetic-variation-deg
49  * /systems/electrical/outputs/gps
50  * /instrumentation/gps/serviceable
51  * 
52  *
53  * Output properties:
54  *
55  * /instrumentation/gps/indicated-longitude-deg
56  * /instrumentation/gps/indicated-latitude-deg
57  * /instrumentation/gps/indicated-altitude-ft
58  * /instrumentation/gps/indicated-vertical-speed-fpm
59  * /instrumentation/gps/indicated-track-true-deg
60  * /instrumentation/gps/indicated-track-magnetic-deg
61  * /instrumentation/gps/indicated-ground-speed-kt
62  *
63  * /instrumentation/gps/wp-distance-nm
64  * /instrumentation/gps/wp-bearing-deg
65  * /instrumentation/gps/wp-bearing-mag-deg
66  * /instrumentation/gps/TTW
67  * /instrumentation/gps/course-deviation-deg
68  * /instrumentation/gps/course-error-nm
69  * /instrumentation/gps/to-flag
70  * /instrumentation/gps/odometer
71  * /instrumentation/gps/trip-odometer
72  * /instrumentation/gps/true-bug-error-deg
73  * /instrumentation/gps/magnetic-bug-error-deg
74
75  */
76 class GPS : public SGSubsystem
77 {
78
79 public:
80
81     GPS (SGPropertyNode *node);
82     GPS ();
83     virtual ~GPS ();
84
85     virtual void init ();
86     virtual void update (double delta_time_sec);
87     
88     virtual void bind();
89     virtual void unbind();
90 private:
91     friend class GPSListener;
92     friend class SearchFilter;
93     
94     /**
95      * Configuration manager, track data relating to aircraft installation
96      */
97     class Config
98     {
99     public:
100       Config();
101             
102       void bind(GPS* aOwner, SGPropertyNode* aCfg);
103       
104       bool turnAnticipationEnabled() const
105       { return _enableTurnAnticipation; }
106       
107       /**
108        * Desired turn rate in degrees/second. From this we derive the turn
109        * radius and hence how early we need to anticipate it.
110        */
111       double turnRateDegSec() const
112       { return _turnRate; }
113       
114       /**
115        * Distance at which we arm overflight sequencing. Once inside this
116        * distance, a change of the wp1 'TO' flag to false will be considered
117        * overlight of the wp.
118        */
119       double overflightArmDistanceNm() const
120       { return _overflightArmDistance; }
121       
122       /**
123        * Time before the next WP to activate an external annunciator
124        */
125       double waypointAlertTime() const
126       { return _waypointAlertTime; }
127             
128       bool requireHardSurface() const
129       { return _requireHardSurface; }
130       
131       double minRunwayLengthFt() const
132       { return _minRunwayLengthFt; }
133       
134       bool cdiDeflectionIsAngular() const
135       { return (_cdiMaxDeflectionNm <= 0.0); }
136       
137       double cdiDeflectionLinearPeg() const
138       {
139         assert(_cdiMaxDeflectionNm > 0.0);
140         return _cdiMaxDeflectionNm;
141       }
142       
143       bool driveAutopilot() const
144       { return _driveAutopilot; }
145       
146       bool courseSelectable() const
147       { return _courseSelectable; }
148     private:
149       bool _enableTurnAnticipation;
150       
151       // desired turn rate in degrees per second
152       double _turnRate;
153       
154       // distance from waypoint to arm overflight sequencing (in nm)
155       double _overflightArmDistance;
156       
157       // time before reaching a waypoint to trigger annunicator light/sound 
158       // (in seconds)
159       double _waypointAlertTime;
160       
161       // minimum runway length to require when filtering
162       double _minRunwayLengthFt;
163       
164       // should we require a hard-surfaced runway when filtering?
165       bool _requireHardSurface;
166       
167       double _cdiMaxDeflectionNm;
168       
169       // should we drive the autopilot directly or not?
170       bool _driveAutopilot;
171       
172       // is selected-course-deg read to set desired-course or not?
173       bool _courseSelectable;
174     };
175     
176     class SearchFilter : public FGPositioned::Filter
177     {
178     public:      
179       virtual bool pass(FGPositioned* aPos) const;
180           
181       virtual FGPositioned::Type minType() const;
182       virtual FGPositioned::Type maxType() const;
183     };
184     
185     /**
186      * reset all output properties to default / non-service values
187      */
188     void clearOutput();
189
190     void updateBasicData(double dt);
191     void updateWaypoints();
192
193     void updateTrackingBug();
194     void updateReferenceNavaid(double dt);
195     void referenceNavaidSet(const std::string& aNavaid);
196     void updateRouteData();
197     void driveAutopilot();
198     
199     void routeActivated();
200     void routeManagerSequenced();
201     void routeEdited();
202     void routeFinished();
203     
204     void updateTurn();  
205     void updateOverflight();    
206     void beginTurn();
207     void endTurn();
208     
209     double computeTurnProgress(double aBearing) const;
210     void computeTurnData();
211     void updateTurnData();
212     double computeTurnRadiusNm(double aGroundSpeedKts) const;
213   
214   /**
215    * Update one-shot things when WP1 / leg data change
216    */
217   void wp1Changed();
218   
219 // scratch maintenence utilities
220   void setScratchFromPositioned(FGPositioned* aPos, int aIndex);
221   void setScratchFromCachedSearchResult();
222   void setScratchFromRouteWaypoint(int aIndex);
223   
224   /**
225    * Add airport-specific information to a scratch result
226    */
227   void addAirportToScratch(FGAirport* aAirport);
228   
229   void clearScratch();
230   
231   /**
232    * Predicate, determine if the lon/lat position in the scratch is 
233    * valid or not.
234    */
235   bool isScratchPositionValid() const;
236   
237   FGPositioned::Filter* createFilter(FGPositioned::Type aTy);
238   
239   /**
240    * Search kernel - called each time we step through a result
241    */
242   void performSearch();
243   
244 // command handlers
245   void selectLegMode();
246   void selectOBSMode();
247   void directTo();
248   void loadRouteWaypoint();
249   void loadNearest();
250   void search();
251   void nextResult();
252   void previousResult();
253   void defineWaypoint();
254   void insertWaypointAtIndex(int aIndex);
255   void removeWaypointAtIndex(int aIndex);
256   
257 // tied-property getter/setters
258   void setCommand(const char* aCmd);
259   const char* getCommand() const { return ""; }
260   
261   const char* getMode() const { return _mode.c_str(); }
262   
263   bool getScratchValid() const { return _scratchValid; }
264   double getScratchDistance() const;
265   double getScratchMagBearing() const;
266   double getScratchTrueBearing() const;
267   bool getScratchHasNext() const { return _searchHasNext; }
268   
269   double getSelectedCourse() const { return _selectedCourse; }
270   void setSelectedCourse(double crs);
271   double getDesiredCourse() const { return _desiredCourse; }
272   
273   double getCDIDeflection() const;
274   
275   double getLegDistance() const;
276   double getLegCourse() const;
277   double getLegMagCourse() const;
278   double getAltDistanceRatio() const;
279   
280   double getTrueTrack() const { return _last_true_track; }
281   double getMagTrack() const;
282   double getGroundspeedKts() const { return _last_speed_kts; }
283   double getVerticalSpeed() const { return _last_vertical_speed; }
284   
285   //bool getLegMode() const { return _mode == "leg"; }
286   //bool getObsMode() const { return _mode == "obs"; }
287   
288   const char* getWP0Ident() const;
289   const char* getWP0Name() const;
290   
291   const char* getWP1Ident() const;
292   const char* getWP1Name() const;
293   
294   double getWP1Distance() const;
295   double getWP1TTW() const;
296   const char* getWP1TTWString() const;
297   double getWP1Bearing() const;
298   double getWP1MagBearing() const;
299   double getWP1CourseDeviation() const;
300   double getWP1CourseErrorNm() const;
301   bool getWP1ToFlag() const;
302   bool getWP1FromFlag() const;
303   
304   // true-bearing-error and mag-bearing-error
305   
306
307   /**
308    * Tied-properties helper, record nodes which are tied for easy un-tie-ing
309    */
310   template <typename T>
311   void tie(SGPropertyNode* aNode, const char* aRelPath, const SGRawValue<T>& aRawValue)
312   {
313     SGPropertyNode* nd = aNode->getNode(aRelPath, true);
314     _tiedNodes.push_back(nd);
315     nd->tie(aRawValue);
316   }
317
318   /// helper, tie the lat/lon/elev of a SGGeod to the named children of aNode
319   void tieSGGeod(SGPropertyNode* aNode, SGGeod& aRef, 
320     const char* lonStr, const char* latStr, const char* altStr);
321   
322   /// helper, tie a SGGeod to proeprties, but read-only
323   void tieSGGeodReadOnly(SGPropertyNode* aNode, SGGeod& aRef, 
324     const char* lonStr, const char* latStr, const char* altStr);
325
326 // members
327   SGPropertyNode_ptr _gpsNode;
328   SGPropertyNode_ptr _magvar_node;
329   SGPropertyNode_ptr _serviceable_node;
330   SGPropertyNode_ptr _electrical_node;
331   SGPropertyNode_ptr _tracking_bug_node;
332   SGPropertyNode_ptr _raim_node;
333
334       SGPropertyNode_ptr _odometer_node;
335     SGPropertyNode_ptr _trip_odometer_node;
336     SGPropertyNode_ptr _true_bug_error_node;
337     SGPropertyNode_ptr _magnetic_bug_error_node;
338     SGPropertyNode_ptr _eastWestVelocity;
339     SGPropertyNode_ptr _northSouthVelocity;
340     
341     SGPropertyNode_ptr _ref_navaid_id_node;
342     SGPropertyNode_ptr _ref_navaid_bearing_node;
343     SGPropertyNode_ptr _ref_navaid_distance_node;
344     SGPropertyNode_ptr _ref_navaid_mag_bearing_node;
345     SGPropertyNode_ptr _ref_navaid_frequency_node;
346     SGPropertyNode_ptr _ref_navaid_name_node;
347     
348     SGPropertyNode_ptr _route_active_node;
349     SGPropertyNode_ptr _route_current_wp_node;
350     SGPropertyNode_ptr _routeDistanceNm;
351     SGPropertyNode_ptr _routeETE;
352   SGPropertyNode_ptr _routeEditedSignal;
353   SGPropertyNode_ptr _routeFinishedSignal;
354   SGPropertyNode_ptr _desiredCourseNode;
355   
356     double _selectedCourse;
357     double _desiredCourse;
358     
359     bool _dataValid;
360     SGGeod _last_pos;
361     bool _lastPosValid;
362     double _last_speed_kts;
363     double _last_true_track;
364     double _last_vertical_speed;
365     double _lastEWVelocity;
366     double _lastNSVelocity;
367     
368     std::string _mode;
369     GPSListener* _listener;
370     Config _config;
371     FGRouteMgr* _routeMgr;
372     
373     bool _ref_navaid_set;
374     double _ref_navaid_elapsed;
375     FGPositionedRef _ref_navaid;
376     
377     std::string _name;
378     int _num;
379   
380   SGGeodProperty _position;
381   SGGeod _wp0_position;
382   SGGeod _wp1_position;
383   SGGeod _indicated_pos;
384   std::string _wp0Ident, _wp0Name, _wp1Ident, _wp1Name;
385   double _wp1DistanceM, _wp1TrueBearing;
386   
387 // scratch data
388   SGGeod _scratchPos;
389   SGPropertyNode_ptr _scratchNode;
390   bool _scratchValid;
391   
392 // search data
393   int _searchResultIndex;
394   std::string _searchQuery;
395   FGPositioned::Type _searchType;
396   bool _searchExact;
397   bool _searchOrderByRange;
398   bool _searchResultsCached;
399   FGPositioned::List _searchResults;
400   bool _searchIsRoute; ///< set if 'search' is actually the current route
401   bool _searchHasNext; ///< is there a result after this one?
402   bool _searchNames; ///< set if we're searching names instead of idents
403   
404   // turn data
405     bool _computeTurnData; ///< do we need to update the turn data?
406     bool _anticipateTurn; ///< are we anticipating the next turn or not?
407     bool _inTurn; // is a turn in progress?
408     bool _turnSequenced; // have we sequenced the new leg?
409     double _turnAngle; // angle to turn through, in degrees
410     double _turnStartBearing; // bearing of inbound leg
411     double _turnRadius; // radius of turn in nm
412     SGGeod _turnPt;
413     SGGeod _turnCentre;
414   
415   SGPropertyNode_ptr _realismSimpleGps; ///< should the GPS be simple or realistic?
416   
417 // autopilot drive properties
418   SGPropertyNode_ptr _apDrivingFlag;
419   SGPropertyNode_ptr _apTrueHeading;
420   SGPropertyNode_ptr _apTargetAltitudeFt;
421   SGPropertyNode_ptr _apAltitudeLock;
422   
423   std::vector<SGPropertyNode_ptr> _tiedNodes;
424 };
425
426
427 #endif // __INSTRUMENTS_GPS_HXX