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