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