]> git.mxchange.org Git - flightgear.git/blob - src/Instrumentation/dclgps.hxx
Fix the rendering of the KLN89 on the 2D panel that was broken during the move to...
[flightgear.git] / src / Instrumentation / dclgps.hxx
1 // dclgps.hxx - a class to extend the operation of FG's current GPS
2 // code, and provide support for a KLN89-specific instrument.  It
3 // is envisioned that eventually this file and class will be split
4 // up between current FG code and new KLN89-specific code and removed.
5 //
6 // Written by David Luff, started 2005.
7 //
8 // Copyright (C) 2005 - David C Luff:  daveluff --AT-- ntlworld --D0T-- com
9 //
10 // This program is free software; you can redistribute it and/or
11 // modify it under the terms of the GNU General Public License as
12 // published by the Free Software Foundation; either version 2 of the
13 // License, or (at your option) any later version.
14 //
15 // This program is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18 // General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with this program; if not, write to the Free Software
22 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
23 //
24 // $Id$
25
26 #ifndef _DCLGPS_HXX
27 #define _DCLGPS_HXX
28
29 #include "render_area_2d.hxx"
30 #include <string>
31 #include <list>
32 #include <vector>
33 #include <map>
34
35 #include <simgear/structure/subsystem_mgr.hxx>
36 #include <Navaids/positioned.hxx>
37
38 class SGTime;
39 class FGPositioned;
40
41 // XXX fix me
42 class FGNavRecord;
43 class FGAirport;
44 class FGFix;
45
46 enum GPSDistanceUnits {
47         GPS_DIST_UNITS_NM = 0,
48         GPS_DIST_UNITS_KM
49 };
50
51 enum GPSSpeedUnits {
52         GPS_VEL_UNITS_KT,
53         GPS_VEL_UNITS_KPH
54 };
55
56 enum GPSAltitudeUnits {
57         GPS_ALT_UNITS_FT,
58         GPS_ALT_UNITS_M
59 };
60
61 enum GPSPressureUnits {
62         GPS_PRES_UNITS_IN = 1,
63         GPS_PRES_UNITS_MB,
64         GPS_PRES_UNITS_HP
65 };
66
67 // --------------------- Waypoint / Flightplan stuff -----------------------------
68 // This should be merged with other similar stuff in FG at some point.
69
70 // NOTE - ORDERING IS IMPORTANT HERE - it matches the Bendix-King page ordering!
71 enum GPSWpType {
72         GPS_WP_APT = 0,
73         GPS_WP_VOR,
74         GPS_WP_NDB,
75         GPS_WP_INT,
76         GPS_WP_USR,
77         GPS_WP_VIRT             // Used for virtual waypoints, such as the start of DTO operation.
78 };
79
80 enum GPSAppWpType {
81         GPS_IAF,                // Initial approach fix
82         GPS_IAP,                // Waypoint on approach sequence that isn't any of the others.
83         GPS_FAF,                // Final approach fix
84         GPS_MAP,                // Missed approach point
85         GPS_MAHP,               // Initial missed approach holding point.
86     GPS_HDR,        // A virtual 'waypoint' to represent the approach header in the fpl page
87     GPS_FENCE,      // A virtual 'waypoint' to represent the NO WPT SEQ fence.
88     GPS_APP_NONE    // Not part of the approach sequence - the default.
89 };
90
91 ostream& operator << (ostream& os, GPSAppWpType type);
92
93 struct GPSWaypoint {
94     GPSWaypoint();
95   
96   GPSWaypoint(const std::string& aIdent, float lat, float lon, GPSWpType aType);
97   
98   static GPSWaypoint* createFromPositioned(const FGPositioned* aFix);
99   
100     ~GPSWaypoint();
101         string GetAprId();      // Returns the id with i, f, m or h added if appropriate. (Initial approach fix, final approach fix, etc)
102         string id;
103         float lat;      // Radians
104         float lon;      // Radians
105         GPSWpType type;
106         GPSAppWpType appType;   // only used for waypoints that are part of an approach sequence
107 };
108
109 typedef vector < GPSWaypoint* > gps_waypoint_array;
110 typedef gps_waypoint_array::iterator gps_waypoint_array_iterator;
111 typedef map < string, gps_waypoint_array > gps_waypoint_map;
112 typedef gps_waypoint_map::iterator gps_waypoint_map_iterator;
113 typedef gps_waypoint_map::const_iterator gps_waypoint_map_const_iterator;
114
115 class GPSFlightPlan {
116 public:
117         vector<GPSWaypoint*> waypoints;
118         inline bool IsEmpty() { return(waypoints.size() == 0); }
119 };
120
121 // TODO - probably de-public the internals of the next 2 classes and add some methods!
122 // Instrument approach procedure base class
123 class FGIAP {
124 public:
125         FGIAP();
126         virtual ~FGIAP() = 0;
127 //protected:
128
129         string _id;             // The ID of the airport this approach is for
130         string _name;   // The approach name, eg "VOR/DME OR GPS-B"
131         string _abbrev; // The abbreviation the GPS unit uses - eg "VOR/D" in this instance.  Possibly GPS model specific.
132         string _rwyStr; // The string used to specify the rwy - eg "B" in this instance.
133         bool _precision;        // True for precision approach, false for non-precision.
134 };
135
136 // Non-precision instrument approach procedure
137 class FGNPIAP : public FGIAP {
138 public:
139         FGNPIAP();
140         ~FGNPIAP();
141 //private:
142 public:
143         vector<GPSWaypoint*> _IAF;      // The initial approach fix(es)
144         vector<GPSWaypoint*> _IAP;      // The compulsory waypoints of the approach procedure (may duplicate one of the above).
145                                                                 // _IAP includes the FAF and MAF.
146         vector<GPSWaypoint*> _MAP;      // The missed approach procedure (doesn't include the MAF).
147 };
148
149 typedef vector < FGIAP* > iap_list_type;
150 typedef map < string, iap_list_type > iap_map_type;
151 typedef iap_map_type::iterator iap_map_iterator;
152
153 //      A class to encapsulate hr:min representation of time. 
154
155 class ClockTime {
156 public:
157     ClockTime();
158     ClockTime(int hr, int min);
159     ~ClockTime();
160     inline void set_hr(int hr) { _hr = hr; }
161     inline int hr() const { return(_hr); } 
162     inline void set_min(int min) { _min = min; }
163     inline int min() const { return(_min); }
164     
165     ClockTime operator+ (const ClockTime& t) {
166         int cumMin = _hr * 60 + _min + t.hr() * 60 + t.min();
167         ClockTime t2(cumMin / 60, cumMin % 60);
168         return(t2);
169     }
170     // Operator - has a max difference of 23:59,
171     // and assumes the day has wrapped if the second operand
172     // is larger that the first.
173     // eg. 2:59 - 3:00 = 23:59
174     ClockTime operator- (const ClockTime& t) {
175         int diff = (_hr * 60 + _min) - (t.hr() * 60 + t.min());
176         if(diff < 0) { diff += 24 * 60; }
177         ClockTime t2(diff / 60, diff % 60);
178         return(t2);
179     }
180     friend ostream& operator<< (ostream& out, const ClockTime& t);
181
182 private:
183     int _hr;
184     int _min;
185 };
186
187 // ------------------------------------------------------------------------------
188
189 class DCLGPS;
190
191 class GPSPage {
192         
193 public:
194         GPSPage(DCLGPS* parent);
195         virtual ~GPSPage() = 0;
196         virtual void Update(double dt);
197         virtual void Knob1Left1();
198         virtual void Knob1Right1();     
199         virtual void Knob2Left1();
200         virtual void Knob2Right1();     
201         virtual void CrsrPressed();
202         virtual void EntPressed();
203         virtual void ClrPressed();
204         virtual void DtoPressed();
205         virtual void NrstPressed();
206         virtual void AltPressed();
207         virtual void OBSPressed();
208         virtual void MsgPressed();
209         
210         // Sometimes a page needs to maintain state for some return paths,
211         // but change it for others.  The CleanUp function can be used for
212         // changing state for non-ENT return  paths in conjunction with
213         // GPS::_cleanUpPage
214         virtual void CleanUp();
215         
216         // The LooseFocus function is called when a page or subpage looses focus
217         // and allows pages to clean up state that is maintained whilst focus is
218         // retained, but lost on return.
219         virtual void LooseFocus();
220         
221         // Allows pages that display info for a given ID to have it set/get if they implement these functions.
222         virtual void SetId(const string& s);
223         virtual const string& GetId()=0;
224         
225         inline int GetSubPage() { return(_subPage); }
226         
227         inline int GetNSubPages() { return(_nSubPages); }
228         
229         inline const string& GetName() { return(_name); }
230         
231 protected:
232         DCLGPS* _parent;
233         string _name;   // eg. "APT", "NAV" etc
234         int _nSubPages;
235         // _subpage is zero based
236         int _subPage;   // The subpage gets remembered when other pages are displayed
237         string GPSitoa(int n);
238 };
239
240 /*-----------------------------------------------------------------------*/
241
242 typedef vector<GPSPage*> gps_page_list_type;
243 typedef gps_page_list_type::iterator gps_page_list_itr;
244
245 // TODO - merge generic GPS functions instead and split out KLN specific stuff.
246 class DCLGPS : public SGSubsystem {
247         
248         friend class GPSPage;
249         
250 public:
251         DCLGPS(RenderArea2D* instrument);
252         virtual ~DCLGPS() = 0;
253         
254         virtual void draw(osg::State& state);
255         
256         virtual void init();
257         virtual void bind();
258         virtual void unbind();
259         virtual void update(double dt);
260
261         // Render string s in display field field at position x, y
262         // WHERE POSITION IS IN CHARACTER UNITS!
263         // zero y at bottom?
264         virtual void DrawText(const string& s, int field, int px, int py, bool bold = false);
265         
266         // Render a char at a given position as above
267         virtual void DrawChar(char c, int field, int px, int py, bool bold = false);
268         
269         virtual void Knob1Right1();
270         virtual void Knob1Left1();
271         virtual void Knob2Right1();
272         virtual void Knob2Left1();
273         virtual void CrsrPressed();
274         virtual void EntPressed();
275         virtual void ClrPressed();
276         virtual void DtoPressed();
277         virtual void NrstPressed();
278         virtual void AltPressed();
279         virtual void OBSPressed();
280         virtual void MsgPressed();
281         
282         // Set the number of fields
283         inline void SetNumFields(int n) { _nFields = (n > _maxFields ? _maxFields : (n < 1 ? 1 : n)); }
284         
285         // Set Units
286         // m if true, ft if false
287         inline void SetAltUnitsSI(bool b) { _altUnits = (b ? GPS_ALT_UNITS_M : GPS_ALT_UNITS_FT); }
288         // Returns true if alt units are SI (m), false if ft
289         inline bool GetAltUnitsSI() { return(_altUnits == GPS_ALT_UNITS_M ? true : false); }
290         // km and k/h if true, nm and kt if false
291         inline void SetDistVelUnitsSI(bool b) { _distUnits = (b ? GPS_DIST_UNITS_KM : GPS_DIST_UNITS_NM); _velUnits = (b ? GPS_VEL_UNITS_KPH : GPS_VEL_UNITS_KT); }
292         // Returns true if dist/vel units are SI
293         inline bool GetDistVelUnitsSI() { return(_distUnits == GPS_DIST_UNITS_KM && _velUnits == GPS_VEL_UNITS_KPH ? true : false); }
294         // Set baro units - 1 = in, 2 = mB, 3 = hP   Wrapping if for the convienience of the GPS setter.
295         void SetBaroUnits(int n, bool wrap = false);
296         // Get baro units: 1 = in, 2 = mB, 3 = hP
297         inline int GetBaroUnits() { return((int)_baroUnits); }
298         
299         // It is expected that specific GPS units will override these functions.
300         // Increase the CDI full-scale deflection (ie. increase the nm per dot) one (GPS unit dependent) increment.  Wraps if necessary (GPS unit dependent).
301         virtual void CDIFSDIncrease();
302         // Ditto for decrease the distance per dot
303         virtual void CDIFSDDecrease();
304         
305         // Host specifc
306         ////inline void SetOverlays(Overlays* overlays) { _overlays = overlays; }
307         
308         virtual void CreateDefaultFlightPlans();
309         
310         void SetOBSFromWaypoint();
311         
312         inline GPSWaypoint* GetActiveWaypoint() { return &_activeWaypoint; }
313         // Get the (zero-based) position of the active waypoint in the active flightplan
314         // Returns -1 if no active waypoint.
315         int GetActiveWaypointIndex();
316         // Ditto for an arbitrary waypoint id
317         int GetWaypointIndex(const string& id);
318         
319         // Returns meters
320         inline float GetDistToActiveWaypoint() { return _dist2Act; }
321         // Returns degrees (magnetic)
322         float GetHeadingToActiveWaypoint();
323         // Returns degrees (magnetic)
324         float GetHeadingFromActiveWaypoint();
325         // Get the time to the active waypoint in seconds.
326         // Returns -1 if groundspeed < 30 kts
327         double GetTimeToActiveWaypoint();
328         // Get the time to the final waypoint in seconds.
329         // Returns -1 if groundspeed < 30 kts
330         double GetETE();
331         // Get the time to a given waypoint (spec'd by ID) in seconds.
332         // returns -1 if groundspeed is less than 30kts.
333         // If the waypoint is an unreached part of the active flight plan the time will be via each leg.
334         // otherwise it will be a direct-to time.
335         double GetTimeToWaypoint(const string& id);
336         
337         // Return true if waypoint alerting is occuring
338         inline bool GetWaypointAlert() const { return(_waypointAlert); }
339         // Return true if in OBS mode
340         inline bool GetOBSMode() const { return(_obsMode); }
341         // Return true if in Leg mode
342         inline bool GetLegMode() const { return(!_obsMode); }
343         
344         // Clear a flightplan
345         void ClearFlightPlan(int n);
346         void ClearFlightPlan(GPSFlightPlan* fp);
347         
348         // Returns true if an approach is loaded/armed/active in the active flight plan
349         inline bool ApproachLoaded() const { return(_approachLoaded); }
350         inline bool GetApproachArm() const { return(_approachArm); }
351         inline bool GetApproachActive() const { return(_approachActive); }
352         double GetCDIDeflection() const;
353         inline bool GetToFlag() const { return(_headingBugTo); }
354         
355         // Initiate Direct To operation to the supplied ID.
356         void DtoInitiate(const string& id);
357         // Cancel Direct To operation
358         void DtoCancel();
359         
360 protected:
361         // Maximum number of display fields for this device
362         int _maxFields;
363         // Current number of on-screen fields
364         int _nFields;
365         // Full x border
366         int _xBorder;
367         // Full y border
368         int _yBorder;
369         // Lower (y) border per field
370         int _yFieldBorder[4];
371         // Left (x) border per field
372         int _xFieldBorder[4];
373         // Field start in x dir (border is part of field since it is the normal char border - sometimes map mode etc draws in it)
374         int _xFieldStart[4];
375         // Field start in y dir (for completeness - KLN89 only has vertical divider.
376         int _yFieldStart[4];
377         
378         // The number of pages on the cyclic knob control
379         unsigned int _nPages;
380         // The current page we're on (Not sure how this ties in with extra pages such as direct or nearest).
381         unsigned int _curPage;
382         
383         // 2D rendering area
384         RenderArea2D* _instrument;
385         
386         // The actual pages
387         gps_page_list_type _pages;
388         
389         // The currently active page
390         GPSPage* _activePage;
391         // And a facility to save the immediately preceeding active page
392         GPSPage* _lastActivePage;
393         
394         // Units
395         GPSSpeedUnits _velUnits;
396         GPSDistanceUnits _distUnits;
397         GPSPressureUnits _baroUnits;
398         GPSAltitudeUnits _altUnits;
399         
400         // CDI full-scale deflection, specified either as an index into a vector of values (standard values) or as a double precision float (intermediate values).
401         // This will influence how an externally driven CDI will display as well as the NAV1 page.
402         // Hence the variables are located here, not in the nav page class.
403         vector<float> _cdiScales;
404         unsigned int _currentCdiScaleIndex;
405         bool _cdiScaleTransition;               // Set true when the floating CDI value is used during transitions
406         double _currentCdiScale;        // The floating value to use.
407         unsigned int _targetCdiScaleIndex;      // The target indexed value to attain during a transition.
408         unsigned int _sourceCdiScaleIndex;      // The source indexed value during a transition - so we know which way we're heading!
409         // Timers to handle the transitions - not sure if we need these.
410         double _apprArmTimer;
411         double _apprActvTimer;
412         double _cdiTransitionTime;      // Time for transition to occur in - normally 30sec but may be quicker if time to FAF < 30sec?
413         // 
414         
415         // Data and lookup functions
416
417
418 protected:
419         // Find first of any type of waypoint by id.  (TODO - Possibly we should return multiple waypoints here).
420   GPSWaypoint* FindFirstById(const string& id) const;
421   GPSWaypoint* FindFirstByExactId(const string& id) const;
422    
423         FGNavRecord* FindFirstVorById(const string& id, bool &multi, bool exact = false);
424         FGNavRecord* FindFirstNDBById(const string& id, bool &multi, bool exact = false);
425         const FGAirport* FindFirstAptById(const string& id, bool &multi, bool exact = false);
426         const FGFix* FindFirstIntById(const string& id, bool &multi, bool exact = false);
427         // Find the closest VOR to a position in RADIANS.
428         FGNavRecord* FindClosestVor(double lat_rad, double lon_rad);
429
430   // helper to implement the above FindFirstXXX methods
431   FGPositioned* FindTypedFirstById(const std::string& id, FGPositioned::Type ty, bool &multi, bool exact);
432
433         // Position, orientation and velocity.
434         // These should be read from FG's built-in GPS logic if possible.
435         // Use the property node pointers below to do this.
436     SGPropertyNode_ptr _lon_node;
437     SGPropertyNode_ptr _lat_node;
438     SGPropertyNode_ptr _alt_node;
439         SGPropertyNode_ptr _grnd_speed_node;
440         SGPropertyNode_ptr _true_track_node;
441         SGPropertyNode_ptr _mag_track_node;
442         // Present position. (Radians)
443         double _lat, _lon;
444         // Present altitude (ft). (Yuk! but it saves converting ft->m->ft every update).
445         double _alt;
446         // Reported position as measured by GPS.  For now this is the same
447         // as present position, but in the future we might want to model
448         // GPS lat and lon errors.
449         // Note - we can depriciate _gpsLat and _gpsLon if we implement error handling in FG
450         // gps code and not our own.
451         double _gpsLat, _gpsLon;  //(Radians)
452         // Hack - it seems that the GPS gets initialised before FG's initial position is properly set.
453         // By checking for abnormal slew in the position we can force a re-initialisation of active flight
454         // plan leg and anything else that might be affected.
455         // TODO - sort FlightGear's initialisation order properly!!!
456         double _checkLat, _checkLon;    // (Radians)
457         double _groundSpeed_ms; // filtered groundspeed (m/s)
458         double _groundSpeed_kts;        // ditto in knots
459         double _track;                  // filtered true track (degrees)
460         double _magTrackDeg;    // magnetic track in degrees calculated from true track above
461         
462         // _navFlagged is set true when GPS navigation is either not possible or not logical.
463         // This includes not receiving adequate signals, and not having an active flightplan entered.
464         bool _navFlagged;
465         
466         // Positional functions copied from ATCutils that might get replaced
467         // INPUT in RADIANS, returns DEGREES!
468         // Magnetic
469         double GetMagHeadingFromTo(double latA, double lonA, double latB, double lonB);
470         // True
471         //double GetHeadingFromTo(double latA, double lonA, double latB, double lonB);
472         
473         // Given two positions (lat & lon in RADIANS), get the HORIZONTAL separation (in meters)
474         //double GetHorizontalSeparation(double lat1, double lon1, double lat2, double lon2);
475         
476         // Proper great circle positional functions from The Aviation Formulary
477         // Returns distance in Nm, input in RADIANS.
478         double GetGreatCircleDistance(double lat1, double lon1, double lat2, double lon2) const;
479         
480         // Input in RADIANS, output in DEGREES.
481         // True
482         double GetGreatCircleCourse(double lat1, double lon1, double lat2, double lon2) const;
483         
484         // Return a position on a radial from wp1 given distance d (nm) and magnetic heading h (degrees)
485         // Note that d should be less that 1/4 Earth diameter!
486         GPSWaypoint GetPositionOnMagRadial(const GPSWaypoint& wp1, double d, double h);
487         
488         // Return a position on a radial from wp1 given distance d (nm) and TRUE heading h (degrees)
489         // Note that d should be less that 1/4 Earth diameter!
490         GPSWaypoint GetPositionOnRadial(const GPSWaypoint& wp1, double d, double h);
491         
492         // Calculate the current cross-track deviation in nm.
493         // Returns zero if a sensible value cannot be calculated.
494         double CalcCrossTrackDeviation() const;
495         
496         // Calculate the cross-track deviation between 2 arbitrary waypoints in nm.
497         // Returns zero if a sensible value cannot be calculated.
498         double CalcCrossTrackDeviation(const GPSWaypoint& wp1, const GPSWaypoint& wp2) const;
499         
500         // Flightplans
501         // GPS can have up to _maxFlightPlans flightplans stored, PLUS an active FP which may or my not be one of the stored ones.
502         // This is from KLN89, but is probably not far off the mark for most if not all GPS.
503         vector<GPSFlightPlan*> _flightPlans;
504         unsigned int _maxFlightPlans;
505         GPSFlightPlan* _activeFP;
506         
507         // Modes of operation.
508         // This is currently somewhat Bendix-King specific, but probably applies fundamentally to other units as well
509         // Mode defaults to leg, but is OBS if _obsMode is true.
510         bool _obsMode;
511         // _dto is set true for DTO operation
512         bool _dto;
513         // In leg mode, we need to know if we are displaying a from and to waypoint, or just the to waypoint (eg. when OBS mode is cancelled).
514         bool _fullLegMode;
515         // In OBS mode we need to know the set OBS heading
516         int _obsHeading;
517         
518         // Operational variables
519         GPSWaypoint _activeWaypoint;
520         GPSWaypoint _fromWaypoint;
521         float _dist2Act;
522         float _crosstrackDist;  // UNITS ??????????
523         double _eta;    // ETA in SECONDS to active waypoint.
524         // Desired track for active leg, true and magnetic, in degrees
525         double _dtkTrue, _dtkMag;
526         bool _headingBugTo;             // Set true when the heading bug is TO, false when FROM.
527         bool _waypointAlert;    // Set true when waypoint alerting is happening. (This is a variable NOT a user-setting).
528         bool _departed;         // Set when groundspeed first exceeds 30kts.
529         string _departureTimeString;    // Ditto.
530         double _elapsedTime;    // Elapsed time in seconds since departure
531         ClockTime _powerOnTime;         // Time (hr:min) of unit power-up.
532         bool _powerOnTimerSet;          // Indicates that we have set the above following power-up.
533         void SetPowerOnTimer();
534 public:
535         void ResetPowerOnTimer();
536         // Set the alarm to go off at a given time.
537         inline void SetAlarm(int hr, int min) {
538                 _alarmTime.set_hr(hr);
539                 _alarmTime.set_min(min);
540                 _alarmSet = true;
541         }
542 protected:
543         ClockTime _alarmTime;
544         bool _alarmSet;
545         
546         // Configuration that affects flightplan operation
547         bool _turnAnticipationEnabled;
548         
549         // Configuration that affects general operation
550         bool _suaAlertEnabled;          // Alert user to potential SUA entry
551         bool _altAlertEnabled;          // Alert user to min safe alt violation
552         
553         // Magvar stuff.  Might get some of this stuff (such as time) from FG in future.
554         SGTime* _time;
555         
556         list<string> _messageStack;
557         
558         virtual void CreateFlightPlan(GPSFlightPlan* fp, vector<string> ids, vector<GPSWpType> wps);
559         
560         // Orientate the GPS unit to a flightplan - ie. figure out from current position
561         // and possibly orientation which leg of the FP we are on.
562         virtual void OrientateToFlightPlan(GPSFlightPlan* fp);
563         
564         // Ditto for active fp.  Probably all we need really!
565         virtual void OrientateToActiveFlightPlan();
566         
567         int _cleanUpPage;       // -1 => no cleanup required.
568         
569         // IAP stuff
570         iap_map_type _np_iap;   // Non-precision approaches
571         iap_map_type _pr_iap;   // Precision approaches
572         bool _approachLoaded;   // Set true when an approach is loaded in the active flightplan
573         bool _approachArm;              // Set true when in approach-arm mode
574         bool _approachReallyArmed;      // Apparently, approach-arm mode can be set from an external GPS-APR switch outside 30nm from airport,
575                                                                 // but the CDI scale change doesn't happen until 30nm from airport.  Bizarre that it can be armed without
576                                                                 // the scale change, but it's in the manual...
577         bool _approachActive;   // Set true when in approach-active mode
578         GPSFlightPlan* _approachFP;     // Current approach - not necessarily loaded.
579         string _approachID;             // ID of the airport we have an approach loaded for - bit of a hack that can hopefully be removed in future.
580         // More hackery since we aren't actually storing an approach class... Doh!
581         string _approachAbbrev;
582         string _approachRwyStr;
583 };
584
585 #endif  // _DCLGPS_HXX