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