]> git.mxchange.org Git - flightgear.git/blob - src/Instrumentation/gps.hxx
Support for multiple data dirs.
[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 overflightArmDistanceM();
83
84 private:
85     friend class SearchFilter;
86
87     /**
88      * Configuration manager, track data relating to aircraft installation
89      */
90     class Config
91     {
92     public:
93       Config();
94
95       void bind(GPS* aOwner, SGPropertyNode* aCfg);
96
97       bool turnAnticipationEnabled() const { return _enableTurnAnticipation; }
98
99       /**
100        * Desired turn rate in degrees/second. From this we derive the turn
101        * radius and hence how early we need to anticipate it.
102        */
103       double turnRateDegSec() const        { return _turnRate; }
104
105       /**
106        * Distance at which we arm overflight sequencing. Once inside this
107        * distance, a change of the wp1 'TO' flag to false will be considered
108        * overlight of the wp.
109        */
110       double overflightArmDistanceNm() const { return _overflightArmDistance; }
111
112       /**
113        * Time before the next WP to activate an external annunciator
114        */
115       double waypointAlertTime() const     { return _waypointAlertTime; }
116
117       bool requireHardSurface() const      { return _requireHardSurface; }
118
119       bool cdiDeflectionIsAngular() const  { return (_cdiMaxDeflectionNm <= 0.0); }
120
121       double cdiDeflectionLinearPeg() const
122       {
123         assert(_cdiMaxDeflectionNm > 0.0);
124         return _cdiMaxDeflectionNm;
125       }
126
127       bool driveAutopilot() const          { return _driveAutopilot; }
128
129       bool courseSelectable() const        { return _courseSelectable; }
130
131     private:
132       bool _enableTurnAnticipation;
133
134       // desired turn rate in degrees per second
135       double _turnRate;
136
137       // distance from waypoint to arm overflight sequencing (in nm)
138       double _overflightArmDistance;
139
140       // time before reaching a waypoint to trigger annunciator light/sound
141       // (in seconds)
142       double _waypointAlertTime;
143
144       // should we require a hard-surfaced runway when filtering?
145       bool _requireHardSurface;
146
147       double _cdiMaxDeflectionNm;
148
149       // should we drive the autopilot directly or not?
150       bool _driveAutopilot;
151
152       // is selected-course-deg read to set desired-course or not?
153       bool _courseSelectable;
154     };
155
156     class SearchFilter : public FGPositioned::Filter
157     {
158     public:
159       virtual bool pass(FGPositioned* aPos) const;
160
161       virtual FGPositioned::Type minType() const;
162       virtual FGPositioned::Type maxType() const;
163     };
164
165     /** reset all output properties to default / non-service values */
166     void clearOutput();
167
168     void updateBasicData(double dt);
169
170     void updateTrackingBug();
171     void updateRouteData();
172     void driveAutopilot();
173
174     void updateTurn();
175     void updateOverflight();
176     void beginTurn();
177     void endTurn();
178
179     double computeTurnProgress(double aBearing) const;
180     void computeTurnData();
181     void updateTurnData();
182     double computeTurnRadiusNm(double aGroundSpeedKts) const;
183
184     /** Update one-shot things when WP1 / leg data change */
185     void wp1Changed();
186
187     void clearScratch();
188
189     /** Predicate, determine if the lon/lat position in the scratch is
190      * valid or not. */
191     bool isScratchPositionValid() const;
192
193 #if FG_210_COMPAT
194     void setScratchFromPositioned(FGPositioned* aPos, int aIndex);
195     void setScratchFromCachedSearchResult();
196     void setScratchFromRouteWaypoint(int aIndex);
197     
198     /** Add airport-specific information to a scratch result */
199     void addAirportToScratch(FGAirport* aAirport);
200     
201     FGPositioned::Filter* createFilter(FGPositioned::Type aTy);
202     
203     /** Search kernel - called each time we step through a result */
204     void performSearch();
205     
206     // command handlers
207     void loadRouteWaypoint();
208     void loadNearest();
209     void search();
210     void nextResult();
211     void previousResult();
212     void defineWaypoint();
213     void insertWaypointAtIndex(int aIndex);
214     void removeWaypointAtIndex(int aIndex);
215     
216     // tied-property getter/setters
217     double getScratchDistance() const;
218     double getScratchMagBearing() const;
219     double getScratchTrueBearing() const;
220     bool getScratchHasNext() const;
221
222 #endif
223     
224 // command handlers
225     void selectLegMode();
226     void selectOBSMode(flightgear::Waypt* waypt);
227     void directTo();
228
229 // tied-property getter/setters
230     void setCommand(const char* aCmd);
231     const char* getCommand() const { return ""; }
232
233     const char* getMode() const { return _mode.c_str(); }
234     bool getScratchValid() const { return _scratchValid; }
235
236     double getSelectedCourse() const { return _selectedCourse; }
237     void setSelectedCourse(double crs);
238     double getDesiredCourse() const { return _desiredCourse; }
239
240     double getCDIDeflection() const;
241
242     double getLegDistance() const;
243     double getLegCourse() const;
244     double getLegMagCourse() const;
245
246     double getTrueTrack() const { return _last_true_track; }
247     double getMagTrack() const;
248     double getGroundspeedKts() const { return _last_speed_kts; }
249     double getVerticalSpeed() const { return _last_vertical_speed; }
250
251     const char* getWP0Ident() const;
252     const char* getWP0Name() const;
253
254     const char* getWP1Ident() const;
255     const char* getWP1Name() const;
256
257     double getWP1Distance() const;
258     double getWP1TTW() const;
259     const char* getWP1TTWString() const;
260     double getWP1Bearing() const;
261     double getWP1MagBearing() const;
262     double getWP1CourseDeviation() const;
263     double getWP1CourseErrorNm() const;
264     bool getWP1ToFlag() const;
265     bool getWP1FromFlag() const;
266
267     // true-bearing-error and mag-bearing-error
268
269
270     /**
271      * Tied-properties helper, record nodes which are tied for easy un-tie-ing
272      */
273     template <typename T>
274     void tie(SGPropertyNode* aNode, const char* aRelPath, const SGRawValue<T>& aRawValue)
275     {
276         _tiedProperties.Tie(aNode->getNode(aRelPath, true), aRawValue);
277     }
278
279     /** helper, tie the lat/lon/elev of a SGGeod to the named children of aNode */
280     void tieSGGeod(SGPropertyNode* aNode, SGGeod& aRef,
281                    const char* lonStr, const char* latStr, const char* altStr);
282   
283     /** helper, tie a SGGeod to proeprties, but read-only */
284     void tieSGGeodReadOnly(SGPropertyNode* aNode, SGGeod& aRef,
285                            const char* lonStr, const char* latStr, const char* altStr);
286
287 // FlightPlan::Delegate
288     virtual void currentWaypointChanged();
289     virtual void waypointsChanged();
290     virtual void cleared();
291     virtual void endOfFlightPlan();
292     
293     void sequence();
294     void routeManagerFlightPlanChanged(SGPropertyNode*);
295     void routeActivated(SGPropertyNode*);
296     
297 // members
298     SGPropertyNode_ptr _gpsNode;
299     SGPropertyNode_ptr _currentWayptNode;
300     SGPropertyNode_ptr _magvar_node;
301     SGPropertyNode_ptr _serviceable_node;
302     SGPropertyNode_ptr _electrical_node;
303     SGPropertyNode_ptr _tracking_bug_node;
304     SGPropertyNode_ptr _raim_node;
305
306     SGPropertyNode_ptr _odometer_node;
307     SGPropertyNode_ptr _trip_odometer_node;
308     SGPropertyNode_ptr _true_bug_error_node;
309     SGPropertyNode_ptr _magnetic_bug_error_node;
310     SGPropertyNode_ptr _eastWestVelocity;
311     SGPropertyNode_ptr _northSouthVelocity;
312     
313   //  SGPropertyNode_ptr _route_active_node;
314     SGPropertyNode_ptr _route_current_wp_node;
315     SGPropertyNode_ptr _routeDistanceNm;
316     SGPropertyNode_ptr _routeETE;
317     SGPropertyNode_ptr _desiredCourseNode;
318     
319     double _selectedCourse;
320     double _desiredCourse;
321
322     bool _dataValid;
323     SGGeod _last_pos;
324     bool _lastPosValid;
325     double _last_speed_kts;
326     double _last_true_track;
327     double _last_vertical_speed;
328     double _lastEWVelocity;
329     double _lastNSVelocity;
330
331     /**
332      * the instrument manager creates a default instance of us,
333      * if no explicit GPS is specific in the aircraft's instruments.xml file.
334      * This allows default route-following to work with the generic autopilot.
335      * This flat is set in that case, to inform us we're a 'fake' installation,
336      * and not to worry about electrical power or similar.
337      */
338     bool _defaultGPSMode;
339     
340     std::string _mode;
341     Config _config;
342     std::string _name;
343     int _num;
344
345     SGGeod _wp0_position;
346     SGGeod _indicated_pos;
347     double _legDistanceNm;
348
349 // scratch data
350     SGGeod _scratchPos;
351     SGPropertyNode_ptr _scratchNode;
352     bool _scratchValid;
353 #if FG_210_COMPAT
354 // search data
355     int _searchResultIndex;
356     std::string _searchQuery;
357     FGPositioned::Type _searchType;
358     bool _searchExact;
359     FGPositionedList _searchResults;
360     bool _searchIsRoute; ///< set if 'search' is actually the current route
361     bool _searchHasNext; ///< is there a result after this one?
362     bool _searchNames; ///< set if we're searching names instead of idents
363 #endif
364     
365 // turn data
366     bool _computeTurnData; ///< do we need to update the turn data?
367     bool _anticipateTurn; ///< are we anticipating the next turn or not?
368     bool _inTurn; // is a turn in progress?
369     bool _turnSequenced; // have we sequenced the new leg?
370     double _turnAngle; // angle to turn through, in degrees
371     double _turnStartBearing; // bearing of inbound leg
372     double _turnRadius; // radius of turn in nm
373     SGGeod _turnPt;
374     SGGeod _turnCentre;
375
376     std::auto_ptr<flightgear::WayptController> _wayptController;
377
378     flightgear::WayptRef _prevWaypt;
379     flightgear::WayptRef _currentWaypt;
380
381 // autopilot drive properties
382     SGPropertyNode_ptr _apDrivingFlag;
383     SGPropertyNode_ptr _apTrueHeading;
384     
385     simgear::TiedPropertyList _tiedProperties;
386
387     flightgear::FlightPlanRef _route;
388     
389     SGPropertyChangeCallback<GPS> _callbackFlightPlanChanged;
390     SGPropertyChangeCallback<GPS> _callbackRouteActivated;
391 };
392
393 #endif // __INSTRUMENTS_GPS_HXX