1 // gps.hxx - distance-measuring equipment.
2 // Written by David Megginson, started 2003.
4 // This file is in the Public Domain and comes with no warranty.
7 #ifndef __INSTRUMENTS_GPS_HXX
8 #define __INSTRUMENTS_GPS_HXX 1
13 #include <simgear/props/props.hxx>
14 #include <simgear/structure/subsystem_mgr.hxx>
15 #include <simgear/props/tiedpropertylist.hxx>
17 #include <Navaids/positioned.hxx>
18 #include <Navaids/FlightPlan.hxx>
19 #include <Instrumentation/rnav_waypt_controller.hxx>
21 #define FG_210_COMPAT 1
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
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
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
58 class GPS : public SGSubsystem,
59 public flightgear::RNAV,
60 public flightgear::FlightPlan::Delegate
63 GPS (SGPropertyNode *node, bool defaultGPSMode = false);
67 // SGSubsystem interface
69 virtual void reinit ();
70 virtual void update (double delta_time_sec);
73 virtual void unbind();
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);
88 friend class SearchFilter;
91 * Configuration manager, track data relating to aircraft installation
98 void bind(GPS* aOwner, SGPropertyNode* aCfg);
100 bool turnAnticipationEnabled() const { return _enableTurnAnticipation; }
103 * Desired turn rate in degrees/second. From this we derive the turn
104 * radius and hence how early we need to anticipate it.
106 double turnRateDegSec() const { return _turnRate; }
109 * Distance at which we switch to next waypoint.
111 double overflightDistanceNm() const { return _overflightDistance; }
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.
117 double overflightArmDistanceNm() const { return _overflightArmDistance; }
119 * abs angle at which we arm overflight sequencing.
121 double overflightArmAngleDeg() const { return _overflightArmAngle; }
124 * Time before the next WP to activate an external annunciator
126 double waypointAlertTime() const { return _waypointAlertTime; }
128 bool requireHardSurface() const { return _requireHardSurface; }
130 bool cdiDeflectionIsAngular() const { return (_cdiMaxDeflectionNm <= 0.0); }
132 double cdiDeflectionLinearPeg() const
134 assert(_cdiMaxDeflectionNm > 0.0);
135 return _cdiMaxDeflectionNm;
138 bool driveAutopilot() const { return _driveAutopilot; }
140 bool courseSelectable() const { return _courseSelectable; }
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.
149 bool followLegTrackToFix() const { return _followLegTrackToFix; }
152 bool _enableTurnAnticipation;
154 // desired turn rate in degrees per second
157 // distance from waypoint to arm overflight sequencing (in nm)
158 double _overflightDistance;
160 // distance from waypoint to arm overflight sequencing (in nm)
161 double _overflightArmDistance;
163 //abs angle from course to waypoint to arm overflight sequencing (in deg)
164 double _overflightArmAngle;
166 // time before reaching a waypoint to trigger annunciator light/sound
168 double _waypointAlertTime;
170 // should we require a hard-surfaced runway when filtering?
171 bool _requireHardSurface;
173 double _cdiMaxDeflectionNm;
175 // should we drive the autopilot directly or not?
176 bool _driveAutopilot;
178 // is selected-course-deg read to set desired-course or not?
179 bool _courseSelectable;
181 // do we fly direct to fixes, or follow the leg track closely?
182 bool _followLegTrackToFix;
185 class SearchFilter : public FGPositioned::Filter
188 virtual bool pass(FGPositioned* aPos) const;
190 virtual FGPositioned::Type minType() const;
191 virtual FGPositioned::Type maxType() const;
194 /** reset all output properties to default / non-service values */
197 void updateBasicData(double dt);
199 void updateTrackingBug();
200 void updateRouteData();
201 void driveAutopilot();
204 void updateOverflight();
208 double computeTurnProgress(double aBearing) const;
209 void computeTurnData();
210 void updateTurnData();
211 double computeTurnRadiusNm(double aGroundSpeedKts) const;
213 /** Update one-shot things when WP1 / leg data change */
218 /** Predicate, determine if the lon/lat position in the scratch is
220 bool isScratchPositionValid() const;
221 FGPositionedRef positionedFromScratch() const;
224 void setScratchFromPositioned(FGPositioned* aPos, int aIndex);
225 void setScratchFromCachedSearchResult();
226 void setScratchFromRouteWaypoint(int aIndex);
228 /** Add airport-specific information to a scratch result */
229 void addAirportToScratch(FGAirport* aAirport);
231 FGPositioned::Filter* createFilter(FGPositioned::Type aTy);
233 /** Search kernel - called each time we step through a result */
234 void performSearch();
237 void loadRouteWaypoint();
241 void previousResult();
242 void defineWaypoint();
243 void insertWaypointAtIndex(int aIndex);
244 void removeWaypointAtIndex(int aIndex);
246 // tied-property getter/setters
247 double getScratchDistance() const;
248 double getScratchMagBearing() const;
249 double getScratchTrueBearing() const;
250 bool getScratchHasNext() const;
255 void selectLegMode();
256 void selectOBSMode(flightgear::Waypt* waypt);
259 // tied-property getter/setters
260 void setCommand(const char* aCmd);
261 const char* getCommand() const { return ""; }
263 const char* getMode() const { return _mode.c_str(); }
264 bool getScratchValid() const { return _scratchValid; }
266 double getSelectedCourse() const { return _selectedCourse; }
267 void setSelectedCourse(double crs);
268 double getDesiredCourse() const { return _desiredCourse; }
270 double getCDIDeflection() const;
272 double getLegDistance() const;
273 double getLegCourse() const;
274 double getLegMagCourse() const;
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; }
281 const char* getWP0Ident() const;
282 const char* getWP0Name() const;
284 bool getWP1IValid() const;
285 const char* getWP1Ident() const;
286 const char* getWP1Name() const;
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;
298 // true-bearing-error and mag-bearing-error
302 * Tied-properties helper, record nodes which are tied for easy un-tie-ing
304 template <typename T>
305 void tie(SGPropertyNode* aNode, const char* aRelPath, const SGRawValue<T>& aRawValue)
307 _tiedProperties.Tie(aNode->getNode(aRelPath, true), aRawValue);
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);
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);
318 // FlightPlan::Delegate
319 virtual void currentWaypointChanged();
320 virtual void waypointsChanged();
321 virtual void cleared();
322 virtual void endOfFlightPlan();
325 void routeManagerFlightPlanChanged(SGPropertyNode*);
326 void routeActivated(SGPropertyNode*);
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;
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;
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;
350 double _selectedCourse;
351 double _desiredCourse;
356 double _last_speed_kts;
357 double _last_true_track;
358 double _last_vertical_speed;
359 double _lastEWVelocity;
360 double _lastNSVelocity;
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.
369 bool _defaultGPSMode;
376 SGGeod _wp0_position;
377 SGGeod _indicated_pos;
378 double _legDistanceNm;
382 SGPropertyNode_ptr _scratchNode;
386 int _searchResultIndex;
387 std::string _searchQuery;
388 FGPositioned::Type _searchType;
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
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
407 std::auto_ptr<flightgear::WayptController> _wayptController;
409 flightgear::WayptRef _prevWaypt;
410 flightgear::WayptRef _currentWaypt;
412 // autopilot drive properties
413 SGPropertyNode_ptr _apDrivingFlag;
414 SGPropertyNode_ptr _apTrueHeading;
416 simgear::TiedPropertyList _tiedProperties;
418 flightgear::FlightPlanRef _route;
420 SGPropertyChangeCallback<GPS> _callbackFlightPlanChanged;
421 SGPropertyChangeCallback<GPS> _callbackRouteActivated;
424 #endif // __INSTRUMENTS_GPS_HXX