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