]> git.mxchange.org Git - flightgear.git/blob - src/Instrumentation/gps.hxx
ada60638e282d728ea04ae7dffa0e7448247b49d
[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 <Navaids/FlightPlan.hxx>
19 #include <Instrumentation/rnav_waypt_controller.hxx>
20
21 #define FG_210_COMPAT 1
22
23 /**
24  * Model a GPS radio.
25  *
26  * Input properties:
27  *
28  * /position/longitude-deg
29  * /position/latitude-deg
30  * /position/altitude-ft
31  * /environment/magnetic-variation-deg
32  * /systems/electrical/outputs/gps
33  * /instrumentation/gps/serviceable
34  * 
35  *
36  * Output properties:
37  *
38  * /instrumentation/gps/indicated-longitude-deg
39  * /instrumentation/gps/indicated-latitude-deg
40  * /instrumentation/gps/indicated-altitude-ft
41  * /instrumentation/gps/indicated-vertical-speed-fpm
42  * /instrumentation/gps/indicated-track-true-deg
43  * /instrumentation/gps/indicated-track-magnetic-deg
44  * /instrumentation/gps/indicated-ground-speed-kt
45  *
46  * /instrumentation/gps/wp-distance-nm
47  * /instrumentation/gps/wp-bearing-deg
48  * /instrumentation/gps/wp-bearing-mag-deg
49  * /instrumentation/gps/TTW
50  * /instrumentation/gps/course-deviation-deg
51  * /instrumentation/gps/course-error-nm
52  * /instrumentation/gps/to-flag
53  * /instrumentation/gps/odometer
54  * /instrumentation/gps/trip-odometer
55  * /instrumentation/gps/true-bug-error-deg
56  * /instrumentation/gps/magnetic-bug-error-deg
57  */
58 class GPS : public SGSubsystem,
59             public flightgear::RNAV,
60             public flightgear::FlightPlan::Delegate
61 {
62 public:
63     GPS (SGPropertyNode *node, bool defaultGPSMode = false);
64     GPS ();
65     virtual ~GPS ();
66
67   // SGSubsystem interface
68     virtual void init ();
69     virtual void reinit ();
70     virtual void update (double delta_time_sec);
71
72     virtual void bind();
73     virtual void unbind();
74
75   // RNAV interface
76     virtual SGGeod position();
77     virtual double trackDeg();
78     virtual double groundSpeedKts();
79     virtual double vspeedFPM();
80     virtual double magvarDeg();
81     virtual double selectedMagCourse();
82     virtual double overflightDistanceM();
83     virtual double overflightArmDistanceM();
84     virtual double overflightArmAngleDeg();
85     virtual SGGeod previousLegWaypointPosition(bool& isValid);
86
87 private:
88     friend class SearchFilter;
89
90     /**
91      * Configuration manager, track data relating to aircraft installation
92      */
93     class Config
94     {
95     public:
96       Config();
97
98       void bind(GPS* aOwner, SGPropertyNode* aCfg);
99
100       bool turnAnticipationEnabled() const { return _enableTurnAnticipation; }
101
102       /**
103        * Desired turn rate in degrees/second. From this we derive the turn
104        * radius and hence how early we need to anticipate it.
105        */
106       double turnRateDegSec() const        { return _turnRate; }
107
108       /**
109        * Distance at which we switch to next waypoint.
110        */
111       double overflightDistanceNm() const { return _overflightDistance; }
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 { return _overflightArmDistance; }
118       /**
119                  * abs angle at which we arm overflight sequencing.
120                  */
121       double overflightArmAngleDeg() const { return _overflightArmAngle; }
122
123       /**
124        * Time before the next WP to activate an external annunciator
125        */
126       double waypointAlertTime() const     { return _waypointAlertTime; }
127
128       bool requireHardSurface() const      { return _requireHardSurface; }
129
130       bool cdiDeflectionIsAngular() const  { return (_cdiMaxDeflectionNm <= 0.0); }
131
132       double cdiDeflectionLinearPeg() const
133       {
134         assert(_cdiMaxDeflectionNm > 0.0);
135         return _cdiMaxDeflectionNm;
136       }
137
138       bool driveAutopilot() const          { return _driveAutopilot; }
139
140       bool courseSelectable() const        { return _courseSelectable; }
141
142         /**
143          * Select whether we fly the leg track between waypoints, or
144          * use a direct course from the turn end. Since this is likely confusing,
145          * look at: http://fgfs.goneabitbursar.com//screenshots/FlyByType-LegType.svg
146          * For fly-by waypoints, there is no difference. For fly-over waypoints,
147          * this selects if we fly TF or DF mode.
148          */
149         bool followLegTrackToFix() const      { return _followLegTrackToFix; }
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 _overflightDistance;
159
160       // distance from waypoint to arm overflight sequencing (in nm)
161       double _overflightArmDistance;
162
163       //abs angle from course to waypoint to arm overflight sequencing (in deg)
164       double _overflightArmAngle;
165
166       // time before reaching a waypoint to trigger annunciator light/sound
167       // (in seconds)
168       double _waypointAlertTime;
169
170       // should we require a hard-surfaced runway when filtering?
171       bool _requireHardSurface;
172
173       double _cdiMaxDeflectionNm;
174
175       // should we drive the autopilot directly or not?
176       bool _driveAutopilot;
177
178       // is selected-course-deg read to set desired-course or not?
179       bool _courseSelectable;
180
181         // do we fly direct to fixes, or follow the leg track closely?
182         bool _followLegTrackToFix;
183     };
184
185     class SearchFilter : public FGPositioned::Filter
186     {
187     public:
188       virtual bool pass(FGPositioned* aPos) const;
189
190       virtual FGPositioned::Type minType() const;
191       virtual FGPositioned::Type maxType() const;
192     };
193
194     /** reset all output properties to default / non-service values */
195     void clearOutput();
196
197     void updateBasicData(double dt);
198
199     void updateTrackingBug();
200     void updateRouteData();
201     void driveAutopilot();
202
203     void updateTurn();
204     void updateOverflight();
205     void beginTurn();
206     void endTurn();
207
208     double computeTurnProgress(double aBearing) const;
209     void computeTurnData();
210     void updateTurnData();
211     double computeTurnRadiusNm(double aGroundSpeedKts) const;
212
213     /** Update one-shot things when WP1 / leg data change */
214     void wp1Changed();
215
216     void clearScratch();
217
218     /** Predicate, determine if the lon/lat position in the scratch is
219      * valid or not. */
220     bool isScratchPositionValid() const;
221     FGPositionedRef positionedFromScratch() const;
222     
223 #if FG_210_COMPAT
224     void setScratchFromPositioned(FGPositioned* aPos, int aIndex);
225     void setScratchFromCachedSearchResult();
226     void setScratchFromRouteWaypoint(int aIndex);
227     
228     /** Add airport-specific information to a scratch result */
229     void addAirportToScratch(FGAirport* aAirport);
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 loadRouteWaypoint();
238     void loadNearest();
239     void search();
240     void nextResult();
241     void previousResult();
242     void defineWaypoint();
243     void insertWaypointAtIndex(int aIndex);
244     void removeWaypointAtIndex(int aIndex);
245     
246     // tied-property getter/setters
247     double getScratchDistance() const;
248     double getScratchMagBearing() const;
249     double getScratchTrueBearing() const;
250     bool getScratchHasNext() const;
251
252 #endif
253     
254 // command handlers
255     void selectLegMode();
256     void selectOBSMode(flightgear::Waypt* waypt);
257     void directTo();
258
259 // tied-property getter/setters
260     void setCommand(const char* aCmd);
261     const char* getCommand() const { return ""; }
262
263     const char* getMode() const { return _mode.c_str(); }
264     bool getScratchValid() const { return _scratchValid; }
265
266     double getSelectedCourse() const { return _selectedCourse; }
267     void setSelectedCourse(double crs);
268     double getDesiredCourse() const { return _desiredCourse; }
269
270     double getCDIDeflection() const;
271
272     double getLegDistance() const;
273     double getLegCourse() const;
274     double getLegMagCourse() const;
275
276     double getTrueTrack() const { return _last_true_track; }
277     double getMagTrack() const;
278     double getGroundspeedKts() const { return _last_speed_kts; }
279     double getVerticalSpeed() const { return _last_vertical_speed; }
280
281     const char* getWP0Ident() const;
282     const char* getWP0Name() const;
283
284     bool getWP1IValid() const;
285     const char* getWP1Ident() const;
286     const char* getWP1Name() const;
287
288     double getWP1Distance() const;
289     double getWP1TTW() const;
290     const char* getWP1TTWString() const;
291     double getWP1Bearing() const;
292     double getWP1MagBearing() const;
293     double getWP1CourseDeviation() const;
294     double getWP1CourseErrorNm() const;
295     bool getWP1ToFlag() const;
296     bool getWP1FromFlag() const;
297
298     // true-bearing-error and mag-bearing-error
299
300
301     /**
302      * Tied-properties helper, record nodes which are tied for easy un-tie-ing
303      */
304     template <typename T>
305     void tie(SGPropertyNode* aNode, const char* aRelPath, const SGRawValue<T>& aRawValue)
306     {
307         _tiedProperties.Tie(aNode->getNode(aRelPath, true), aRawValue);
308     }
309
310     /** helper, tie the lat/lon/elev of a SGGeod to the named children of aNode */
311     void tieSGGeod(SGPropertyNode* aNode, SGGeod& aRef,
312                    const char* lonStr, const char* latStr, const char* altStr);
313   
314     /** helper, tie a SGGeod to proeprties, but read-only */
315     void tieSGGeodReadOnly(SGPropertyNode* aNode, SGGeod& aRef,
316                            const char* lonStr, const char* latStr, const char* altStr);
317
318 // FlightPlan::Delegate
319     virtual void currentWaypointChanged();
320     virtual void waypointsChanged();
321     virtual void cleared();
322     virtual void endOfFlightPlan();
323     
324     void sequence();
325     void routeManagerFlightPlanChanged(SGPropertyNode*);
326     void routeActivated(SGPropertyNode*);
327     
328 // members
329     SGPropertyNode_ptr _gpsNode;
330     SGPropertyNode_ptr _currentWayptNode;
331     SGPropertyNode_ptr _magvar_node;
332     SGPropertyNode_ptr _serviceable_node;
333     SGPropertyNode_ptr _electrical_node;
334     SGPropertyNode_ptr _tracking_bug_node;
335     SGPropertyNode_ptr _raim_node;
336
337     SGPropertyNode_ptr _odometer_node;
338     SGPropertyNode_ptr _trip_odometer_node;
339     SGPropertyNode_ptr _true_bug_error_node;
340     SGPropertyNode_ptr _magnetic_bug_error_node;
341     SGPropertyNode_ptr _eastWestVelocity;
342     SGPropertyNode_ptr _northSouthVelocity;
343     
344   //  SGPropertyNode_ptr _route_active_node;
345     SGPropertyNode_ptr _route_current_wp_node;
346     SGPropertyNode_ptr _routeDistanceNm;
347     SGPropertyNode_ptr _routeETE;
348     SGPropertyNode_ptr _desiredCourseNode;
349     
350     double _selectedCourse;
351     double _desiredCourse;
352
353     bool _dataValid;
354     SGGeod _last_pos;
355     bool _lastPosValid;
356     double _last_speed_kts;
357     double _last_true_track;
358     double _last_vertical_speed;
359     double _lastEWVelocity;
360     double _lastNSVelocity;
361
362     /**
363      * the instrument manager creates a default instance of us,
364      * if no explicit GPS is specific in the aircraft's instruments.xml file.
365      * This allows default route-following to work with the generic autopilot.
366      * This flag is set in that case, to inform us we're a 'fake' installation,
367      * and not to worry about electrical power or similar.
368      */
369     bool _defaultGPSMode;
370     
371     std::string _mode;
372     Config _config;
373     std::string _name;
374     int _num;
375
376     SGGeod _wp0_position;
377     SGGeod _indicated_pos;
378     double _legDistanceNm;
379
380 // scratch data
381     SGGeod _scratchPos;
382     SGPropertyNode_ptr _scratchNode;
383     bool _scratchValid;
384 #if FG_210_COMPAT
385 // search data
386     int _searchResultIndex;
387     std::string _searchQuery;
388     FGPositioned::Type _searchType;
389     bool _searchExact;
390     FGPositionedList _searchResults;
391     bool _searchIsRoute; ///< set if 'search' is actually the current route
392     bool _searchHasNext; ///< is there a result after this one?
393     bool _searchNames; ///< set if we're searching names instead of idents
394 #endif
395     
396 // turn data
397     bool _computeTurnData; ///< do we need to update the turn data?
398     bool _anticipateTurn; ///< are we anticipating the next turn or not?
399     bool _inTurn; // is a turn in progress?
400     bool _turnSequenced; // have we sequenced the new leg?
401     double _turnAngle; // angle to turn through, in degrees
402     double _turnStartBearing; // bearing of inbound leg
403     double _turnRadius; // radius of turn in nm
404     SGGeod _turnPt;
405     SGGeod _turnCentre;
406
407     std::auto_ptr<flightgear::WayptController> _wayptController;
408
409     flightgear::WayptRef _prevWaypt;
410     flightgear::WayptRef _currentWaypt;
411
412 // autopilot drive properties
413     SGPropertyNode_ptr _apDrivingFlag;
414     SGPropertyNode_ptr _apTrueHeading;
415     
416     simgear::TiedPropertyList _tiedProperties;
417
418     flightgear::FlightPlanRef _route;
419     
420     SGPropertyChangeCallback<GPS> _callbackFlightPlanChanged;
421     SGPropertyChangeCallback<GPS> _callbackRouteActivated;
422 };
423
424 #endif // __INSTRUMENTS_GPS_HXX