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