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/math/SGMath.hxx>
17 #include <Navaids/positioned.hxx>
18 #include <Instrumentation/rnav_waypt_controller.hxx>
33 void init(SGPropertyNode* base, const char* lonStr, const char* latStr, const char* altStr = NULL);
34 void init(const char* lonStr, const char* latStr, const char* altStr = NULL);
36 void operator=(const SGGeod& geod);
39 SGPropertyNode_ptr _lon, _lat, _alt;
47 * /position/longitude-deg
48 * /position/latitude-deg
49 * /position/altitude-ft
50 * /environment/magnetic-variation-deg
51 * /systems/electrical/outputs/gps
52 * /instrumentation/gps/serviceable
57 * /instrumentation/gps/indicated-longitude-deg
58 * /instrumentation/gps/indicated-latitude-deg
59 * /instrumentation/gps/indicated-altitude-ft
60 * /instrumentation/gps/indicated-vertical-speed-fpm
61 * /instrumentation/gps/indicated-track-true-deg
62 * /instrumentation/gps/indicated-track-magnetic-deg
63 * /instrumentation/gps/indicated-ground-speed-kt
65 * /instrumentation/gps/wp-distance-nm
66 * /instrumentation/gps/wp-bearing-deg
67 * /instrumentation/gps/wp-bearing-mag-deg
68 * /instrumentation/gps/TTW
69 * /instrumentation/gps/course-deviation-deg
70 * /instrumentation/gps/course-error-nm
71 * /instrumentation/gps/to-flag
72 * /instrumentation/gps/odometer
73 * /instrumentation/gps/trip-odometer
74 * /instrumentation/gps/true-bug-error-deg
75 * /instrumentation/gps/magnetic-bug-error-deg
78 class GPS : public SGSubsystem, public flightgear::RNAV
81 GPS (SGPropertyNode *node);
85 // SGSubsystem interface
87 virtual void update (double delta_time_sec);
90 virtual void unbind();
93 virtual SGGeod position();
94 virtual double trackDeg();
95 virtual double groundSpeedKts();
96 virtual double vspeedFPM();
97 virtual double magvarDeg();
98 virtual double selectedMagCourse();
99 virtual double overflightArmDistanceM();
102 friend class GPSListener;
103 friend class SearchFilter;
106 * Configuration manager, track data relating to aircraft installation
113 void bind(GPS* aOwner, SGPropertyNode* aCfg);
115 bool turnAnticipationEnabled() const
116 { 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
123 { return _turnRate; }
126 * Distance at which we arm overflight sequencing. Once inside this
127 * distance, a change of the wp1 'TO' flag to false will be considered
128 * overlight of the wp.
130 double overflightArmDistanceNm() const
131 { return _overflightArmDistance; }
134 * Time before the next WP to activate an external annunciator
136 double waypointAlertTime() const
137 { return _waypointAlertTime; }
139 bool requireHardSurface() const
140 { return _requireHardSurface; }
142 double minRunwayLengthFt() const
143 { return _minRunwayLengthFt; }
145 bool cdiDeflectionIsAngular() const
146 { return (_cdiMaxDeflectionNm <= 0.0); }
148 double cdiDeflectionLinearPeg() const
150 assert(_cdiMaxDeflectionNm > 0.0);
151 return _cdiMaxDeflectionNm;
154 bool driveAutopilot() const
155 { return _driveAutopilot; }
157 bool courseSelectable() const
158 { return _courseSelectable; }
160 bool _enableTurnAnticipation;
162 // desired turn rate in degrees per second
165 // distance from waypoint to arm overflight sequencing (in nm)
166 double _overflightArmDistance;
168 // time before reaching a waypoint to trigger annunicator light/sound
170 double _waypointAlertTime;
172 // minimum runway length to require when filtering
173 double _minRunwayLengthFt;
175 // should we require a hard-surfaced runway when filtering?
176 bool _requireHardSurface;
178 double _cdiMaxDeflectionNm;
180 // should we drive the autopilot directly or not?
181 bool _driveAutopilot;
183 // is selected-course-deg read to set desired-course or not?
184 bool _courseSelectable;
187 class SearchFilter : public FGPositioned::Filter
190 virtual bool pass(FGPositioned* aPos) const;
192 virtual FGPositioned::Type minType() const;
193 virtual FGPositioned::Type maxType() const;
197 * reset all output properties to default / non-service values
201 void updateBasicData(double dt);
203 void updateTrackingBug();
204 void updateReferenceNavaid(double dt);
205 void referenceNavaidSet(const std::string& aNavaid);
206 void updateRouteData();
207 void driveAutopilot();
209 void routeActivated();
210 void routeManagerSequenced();
212 void routeFinished();
215 void updateOverflight();
219 double computeTurnProgress(double aBearing) const;
220 void computeTurnData();
221 void updateTurnData();
222 double computeTurnRadiusNm(double aGroundSpeedKts) const;
225 * Update one-shot things when WP1 / leg data change
229 // scratch maintenence utilities
230 void setScratchFromPositioned(FGPositioned* aPos, int aIndex);
231 void setScratchFromCachedSearchResult();
232 void setScratchFromRouteWaypoint(int aIndex);
235 * Add airport-specific information to a scratch result
237 void addAirportToScratch(FGAirport* aAirport);
242 * Predicate, determine if the lon/lat position in the scratch is
245 bool isScratchPositionValid() const;
247 FGPositioned::Filter* createFilter(FGPositioned::Type aTy);
250 * Search kernel - called each time we step through a result
252 void performSearch();
255 void selectLegMode();
256 void selectOBSMode();
258 void loadRouteWaypoint();
262 void previousResult();
263 void defineWaypoint();
264 void insertWaypointAtIndex(int aIndex);
265 void removeWaypointAtIndex(int aIndex);
267 // tied-property getter/setters
268 void setCommand(const char* aCmd);
269 const char* getCommand() const { return ""; }
271 const char* getMode() const { return _mode.c_str(); }
273 bool getScratchValid() const { return _scratchValid; }
274 double getScratchDistance() const;
275 double getScratchMagBearing() const;
276 double getScratchTrueBearing() const;
277 bool getScratchHasNext() const;
279 double getSelectedCourse() const { return _selectedCourse; }
280 void setSelectedCourse(double crs);
281 double getDesiredCourse() const { return _desiredCourse; }
283 double getCDIDeflection() const;
285 double getLegDistance() const;
286 double getLegCourse() const;
287 double getLegMagCourse() const;
289 double getTrueTrack() const { return _last_true_track; }
290 double getMagTrack() const;
291 double getGroundspeedKts() const { return _last_speed_kts; }
292 double getVerticalSpeed() const { return _last_vertical_speed; }
294 //bool getLegMode() const { return _mode == "leg"; }
295 //bool getObsMode() const { return _mode == "obs"; }
297 const char* getWP0Ident() const;
298 const char* getWP0Name() const;
300 const char* getWP1Ident() const;
301 const char* getWP1Name() const;
303 double getWP1Distance() const;
304 double getWP1TTW() const;
305 const char* getWP1TTWString() const;
306 double getWP1Bearing() const;
307 double getWP1MagBearing() const;
308 double getWP1CourseDeviation() const;
309 double getWP1CourseErrorNm() const;
310 bool getWP1ToFlag() const;
311 bool getWP1FromFlag() const;
313 // true-bearing-error and mag-bearing-error
317 * Tied-properties helper, record nodes which are tied for easy un-tie-ing
319 template <typename T>
320 void tie(SGPropertyNode* aNode, const char* aRelPath, const SGRawValue<T>& aRawValue)
322 SGPropertyNode* nd = aNode->getNode(aRelPath, true);
323 _tiedNodes.push_back(nd);
327 /// helper, tie the lat/lon/elev of a SGGeod to the named children of aNode
328 void tieSGGeod(SGPropertyNode* aNode, SGGeod& aRef,
329 const char* lonStr, const char* latStr, const char* altStr);
331 /// helper, tie a SGGeod to proeprties, but read-only
332 void tieSGGeodReadOnly(SGPropertyNode* aNode, SGGeod& aRef,
333 const char* lonStr, const char* latStr, const char* altStr);
336 SGPropertyNode_ptr _gpsNode;
337 SGPropertyNode_ptr _currentWayptNode;
338 SGPropertyNode_ptr _magvar_node;
339 SGPropertyNode_ptr _serviceable_node;
340 SGPropertyNode_ptr _electrical_node;
341 SGPropertyNode_ptr _tracking_bug_node;
342 SGPropertyNode_ptr _raim_node;
344 SGPropertyNode_ptr _odometer_node;
345 SGPropertyNode_ptr _trip_odometer_node;
346 SGPropertyNode_ptr _true_bug_error_node;
347 SGPropertyNode_ptr _magnetic_bug_error_node;
348 SGPropertyNode_ptr _eastWestVelocity;
349 SGPropertyNode_ptr _northSouthVelocity;
351 SGPropertyNode_ptr _ref_navaid_id_node;
352 SGPropertyNode_ptr _ref_navaid_bearing_node;
353 SGPropertyNode_ptr _ref_navaid_distance_node;
354 SGPropertyNode_ptr _ref_navaid_mag_bearing_node;
355 SGPropertyNode_ptr _ref_navaid_frequency_node;
356 SGPropertyNode_ptr _ref_navaid_name_node;
358 SGPropertyNode_ptr _route_active_node;
359 SGPropertyNode_ptr _route_current_wp_node;
360 SGPropertyNode_ptr _routeDistanceNm;
361 SGPropertyNode_ptr _routeETE;
362 SGPropertyNode_ptr _routeEditedSignal;
363 SGPropertyNode_ptr _routeFinishedSignal;
364 SGPropertyNode_ptr _desiredCourseNode;
366 double _selectedCourse;
367 double _desiredCourse;
372 double _last_speed_kts;
373 double _last_true_track;
374 double _last_vertical_speed;
375 double _lastEWVelocity;
376 double _lastNSVelocity;
379 GPSListener* _listener;
381 FGRouteMgr* _routeMgr;
383 bool _ref_navaid_set;
384 double _ref_navaid_elapsed;
385 FGPositionedRef _ref_navaid;
390 SGGeodProperty _position;
391 SGGeod _wp0_position;
392 SGGeod _indicated_pos;
393 double _legDistanceNm;
397 SGPropertyNode_ptr _scratchNode;
401 int _searchResultIndex;
402 std::string _searchQuery;
403 FGPositioned::Type _searchType;
405 FGPositioned::List _searchResults;
406 bool _searchIsRoute; ///< set if 'search' is actually the current route
407 bool _searchHasNext; ///< is there a result after this one?
408 bool _searchNames; ///< set if we're searching names instead of idents
411 bool _computeTurnData; ///< do we need to update the turn data?
412 bool _anticipateTurn; ///< are we anticipating the next turn or not?
413 bool _inTurn; // is a turn in progress?
414 bool _turnSequenced; // have we sequenced the new leg?
415 double _turnAngle; // angle to turn through, in degrees
416 double _turnStartBearing; // bearing of inbound leg
417 double _turnRadius; // radius of turn in nm
421 std::auto_ptr<flightgear::WayptController> _wayptController;
423 SGPropertyNode_ptr _realismSimpleGps; ///< should the GPS be simple or realistic?
424 flightgear::WayptRef _prevWaypt;
425 flightgear::WayptRef _currentWaypt;
427 // autopilot drive properties
428 SGPropertyNode_ptr _apDrivingFlag;
429 SGPropertyNode_ptr _apTrueHeading;
430 SGPropertyNode_ptr _apTargetAltitudeFt;
431 SGPropertyNode_ptr _apAltitudeLock;
433 std::vector<SGPropertyNode_ptr> _tiedNodes;
437 #endif // __INSTRUMENTS_GPS_HXX