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>
16 #include <simgear/math/SGMath.hxx>
18 #include <Navaids/positioned.hxx>
19 #include <Instrumentation/rnav_waypt_controller.hxx>
34 void init(SGPropertyNode* base, const char* lonStr, const char* latStr, const char* altStr = NULL);
35 void init(const char* lonStr, const char* latStr, const char* altStr = NULL);
37 void operator=(const SGGeod& geod);
41 SGPropertyNode_ptr _lon, _lat, _alt;
49 * /position/longitude-deg
50 * /position/latitude-deg
51 * /position/altitude-ft
52 * /environment/magnetic-variation-deg
53 * /systems/electrical/outputs/gps
54 * /instrumentation/gps/serviceable
59 * /instrumentation/gps/indicated-longitude-deg
60 * /instrumentation/gps/indicated-latitude-deg
61 * /instrumentation/gps/indicated-altitude-ft
62 * /instrumentation/gps/indicated-vertical-speed-fpm
63 * /instrumentation/gps/indicated-track-true-deg
64 * /instrumentation/gps/indicated-track-magnetic-deg
65 * /instrumentation/gps/indicated-ground-speed-kt
67 * /instrumentation/gps/wp-distance-nm
68 * /instrumentation/gps/wp-bearing-deg
69 * /instrumentation/gps/wp-bearing-mag-deg
70 * /instrumentation/gps/TTW
71 * /instrumentation/gps/course-deviation-deg
72 * /instrumentation/gps/course-error-nm
73 * /instrumentation/gps/to-flag
74 * /instrumentation/gps/odometer
75 * /instrumentation/gps/trip-odometer
76 * /instrumentation/gps/true-bug-error-deg
77 * /instrumentation/gps/magnetic-bug-error-deg
79 class GPS : public SGSubsystem, public flightgear::RNAV
82 GPS (SGPropertyNode *node);
86 // SGSubsystem interface
88 virtual void update (double delta_time_sec);
91 virtual void unbind();
94 virtual SGGeod position();
95 virtual double trackDeg();
96 virtual double groundSpeedKts();
97 virtual double vspeedFPM();
98 virtual double magvarDeg();
99 virtual double selectedMagCourse();
100 virtual double overflightArmDistanceM();
103 friend class GPSListener;
104 friend class SearchFilter;
107 * Configuration manager, track data relating to aircraft installation
114 void bind(GPS* aOwner, SGPropertyNode* aCfg);
116 bool turnAnticipationEnabled() const { return _enableTurnAnticipation; }
119 * Desired turn rate in degrees/second. From this we derive the turn
120 * radius and hence how early we need to anticipate it.
122 double turnRateDegSec() const { return _turnRate; }
125 * Distance at which we arm overflight sequencing. Once inside this
126 * distance, a change of the wp1 'TO' flag to false will be considered
127 * overlight of the wp.
129 double overflightArmDistanceNm() const { return _overflightArmDistance; }
132 * Time before the next WP to activate an external annunciator
134 double waypointAlertTime() const { return _waypointAlertTime; }
136 bool requireHardSurface() const { return _requireHardSurface; }
138 double minRunwayLengthFt() const { return _minRunwayLengthFt; }
140 bool cdiDeflectionIsAngular() const { return (_cdiMaxDeflectionNm <= 0.0); }
142 double cdiDeflectionLinearPeg() const
144 assert(_cdiMaxDeflectionNm > 0.0);
145 return _cdiMaxDeflectionNm;
148 bool driveAutopilot() const { return _driveAutopilot; }
150 bool courseSelectable() const { return _courseSelectable; }
153 bool _enableTurnAnticipation;
155 // desired turn rate in degrees per second
158 // distance from waypoint to arm overflight sequencing (in nm)
159 double _overflightArmDistance;
161 // time before reaching a waypoint to trigger annunciator light/sound
163 double _waypointAlertTime;
165 // minimum runway length to require when filtering
166 double _minRunwayLengthFt;
168 // should we require a hard-surfaced runway when filtering?
169 bool _requireHardSurface;
171 double _cdiMaxDeflectionNm;
173 // should we drive the autopilot directly or not?
174 bool _driveAutopilot;
176 // is selected-course-deg read to set desired-course or not?
177 bool _courseSelectable;
180 class SearchFilter : public FGPositioned::Filter
183 virtual bool pass(FGPositioned* aPos) const;
185 virtual FGPositioned::Type minType() const;
186 virtual FGPositioned::Type maxType() const;
189 /** reset all output properties to default / non-service values */
192 void updateBasicData(double dt);
194 void updateTrackingBug();
195 void updateReferenceNavaid(double dt);
196 void referenceNavaidSet(const std::string& aNavaid);
197 void updateRouteData();
198 void driveAutopilot();
200 void routeActivated();
201 void routeManagerSequenced();
203 void routeFinished();
206 void updateOverflight();
210 double computeTurnProgress(double aBearing) const;
211 void computeTurnData();
212 void updateTurnData();
213 double computeTurnRadiusNm(double aGroundSpeedKts) const;
215 /** Update one-shot things when WP1 / leg data change */
218 // scratch maintenance utilities
219 void setScratchFromPositioned(FGPositioned* aPos, int aIndex);
220 void setScratchFromCachedSearchResult();
221 void setScratchFromRouteWaypoint(int aIndex);
223 /** Add airport-specific information to a scratch result */
224 void addAirportToScratch(FGAirport* aAirport);
228 /** Predicate, determine if the lon/lat position in the scratch is
230 bool isScratchPositionValid() const;
232 FGPositioned::Filter* createFilter(FGPositioned::Type aTy);
234 /** Search kernel - called each time we step through a result */
235 void performSearch();
238 void selectLegMode();
239 void selectOBSMode();
241 void loadRouteWaypoint();
245 void previousResult();
246 void defineWaypoint();
247 void insertWaypointAtIndex(int aIndex);
248 void removeWaypointAtIndex(int aIndex);
250 // tied-property getter/setters
251 void setCommand(const char* aCmd);
252 const char* getCommand() const { return ""; }
254 const char* getMode() const { return _mode.c_str(); }
256 bool getScratchValid() const { return _scratchValid; }
257 double getScratchDistance() const;
258 double getScratchMagBearing() const;
259 double getScratchTrueBearing() const;
260 bool getScratchHasNext() const;
262 double getSelectedCourse() const { return _selectedCourse; }
263 void setSelectedCourse(double crs);
264 double getDesiredCourse() const { return _desiredCourse; }
266 double getCDIDeflection() const;
268 double getLegDistance() const;
269 double getLegCourse() const;
270 double getLegMagCourse() const;
272 double getTrueTrack() const { return _last_true_track; }
273 double getMagTrack() const;
274 double getGroundspeedKts() const { return _last_speed_kts; }
275 double getVerticalSpeed() const { return _last_vertical_speed; }
277 //bool getLegMode() const { return _mode == "leg"; }
278 //bool getObsMode() const { return _mode == "obs"; }
280 const char* getWP0Ident() const;
281 const char* getWP0Name() const;
283 const char* getWP1Ident() const;
284 const char* getWP1Name() const;
286 double getWP1Distance() const;
287 double getWP1TTW() const;
288 const char* getWP1TTWString() const;
289 double getWP1Bearing() const;
290 double getWP1MagBearing() const;
291 double getWP1CourseDeviation() const;
292 double getWP1CourseErrorNm() const;
293 bool getWP1ToFlag() const;
294 bool getWP1FromFlag() const;
296 // true-bearing-error and mag-bearing-error
300 * Tied-properties helper, record nodes which are tied for easy un-tie-ing
302 template <typename T>
303 void tie(SGPropertyNode* aNode, const char* aRelPath, const SGRawValue<T>& aRawValue)
305 _tiedProperties.Tie(aNode->getNode(aRelPath, true), aRawValue);
308 /** helper, tie the lat/lon/elev of a SGGeod to the named children of aNode */
309 void tieSGGeod(SGPropertyNode* aNode, SGGeod& aRef,
310 const char* lonStr, const char* latStr, const char* altStr);
312 /** helper, tie a SGGeod to proeprties, but read-only */
313 void tieSGGeodReadOnly(SGPropertyNode* aNode, SGGeod& aRef,
314 const char* lonStr, const char* latStr, const char* altStr);
317 SGPropertyNode_ptr _gpsNode;
318 SGPropertyNode_ptr _currentWayptNode;
319 SGPropertyNode_ptr _magvar_node;
320 SGPropertyNode_ptr _serviceable_node;
321 SGPropertyNode_ptr _electrical_node;
322 SGPropertyNode_ptr _tracking_bug_node;
323 SGPropertyNode_ptr _raim_node;
325 SGPropertyNode_ptr _odometer_node;
326 SGPropertyNode_ptr _trip_odometer_node;
327 SGPropertyNode_ptr _true_bug_error_node;
328 SGPropertyNode_ptr _magnetic_bug_error_node;
329 SGPropertyNode_ptr _eastWestVelocity;
330 SGPropertyNode_ptr _northSouthVelocity;
332 SGPropertyNode_ptr _ref_navaid_id_node;
333 SGPropertyNode_ptr _ref_navaid_bearing_node;
334 SGPropertyNode_ptr _ref_navaid_distance_node;
335 SGPropertyNode_ptr _ref_navaid_mag_bearing_node;
336 SGPropertyNode_ptr _ref_navaid_frequency_node;
337 SGPropertyNode_ptr _ref_navaid_name_node;
339 SGPropertyNode_ptr _route_active_node;
340 SGPropertyNode_ptr _route_current_wp_node;
341 SGPropertyNode_ptr _routeDistanceNm;
342 SGPropertyNode_ptr _routeETE;
343 SGPropertyNode_ptr _routeEditedSignal;
344 SGPropertyNode_ptr _routeFinishedSignal;
345 SGPropertyNode_ptr _desiredCourseNode;
347 double _selectedCourse;
348 double _desiredCourse;
353 double _last_speed_kts;
354 double _last_true_track;
355 double _last_vertical_speed;
356 double _lastEWVelocity;
357 double _lastNSVelocity;
360 GPSListener* _listener;
362 FGRouteMgr* _routeMgr;
364 bool _ref_navaid_set;
365 double _ref_navaid_elapsed;
366 FGPositionedRef _ref_navaid;
371 SGGeodProperty _position;
372 SGGeod _wp0_position;
373 SGGeod _indicated_pos;
374 double _legDistanceNm;
378 SGPropertyNode_ptr _scratchNode;
382 int _searchResultIndex;
383 std::string _searchQuery;
384 FGPositioned::Type _searchType;
386 FGPositioned::List _searchResults;
387 bool _searchIsRoute; ///< set if 'search' is actually the current route
388 bool _searchHasNext; ///< is there a result after this one?
389 bool _searchNames; ///< set if we're searching names instead of idents
392 bool _computeTurnData; ///< do we need to update the turn data?
393 bool _anticipateTurn; ///< are we anticipating the next turn or not?
394 bool _inTurn; // is a turn in progress?
395 bool _turnSequenced; // have we sequenced the new leg?
396 double _turnAngle; // angle to turn through, in degrees
397 double _turnStartBearing; // bearing of inbound leg
398 double _turnRadius; // radius of turn in nm
402 std::auto_ptr<flightgear::WayptController> _wayptController;
404 SGPropertyNode_ptr _realismSimpleGps; ///< should the GPS be simple or realistic?
405 flightgear::WayptRef _prevWaypt;
406 flightgear::WayptRef _currentWaypt;
408 // autopilot drive properties
409 SGPropertyNode_ptr _apDrivingFlag;
410 SGPropertyNode_ptr _apTrueHeading;
411 SGPropertyNode_ptr _apTargetAltitudeFt;
412 SGPropertyNode_ptr _apAltitudeLock;
414 simgear::TiedPropertyList _tiedProperties;
418 #endif // __INSTRUMENTS_GPS_HXX