X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FInstrumentation%2Fgps.hxx;h=ada60638e282d728ea04ae7dffa0e7448247b49d;hb=de959a14f35ee4e74d405b418bb09689967ee22f;hp=d20c74e4814eeb6ec3012c531df2e735b874b9f0;hpb=13ec36af4218402eda39c680e8da6ca2c198733c;p=flightgear.git diff --git a/src/Instrumentation/gps.hxx b/src/Instrumentation/gps.hxx index d20c74e48..ada60638e 100644 --- a/src/Instrumentation/gps.hxx +++ b/src/Instrumentation/gps.hxx @@ -7,33 +7,18 @@ #ifndef __INSTRUMENTS_GPS_HXX #define __INSTRUMENTS_GPS_HXX 1 +#include +#include + #include #include -#include +#include -#include "Navaids/positioned.hxx" +#include +#include +#include -// forward decls -class SGRoute; -class FGRouteMgr; -class FGAirport; -class GPSListener; - -class SGGeodProperty -{ -public: - SGGeodProperty() - { - } - - void init(SGPropertyNode* base, const char* lonStr, const char* latStr, const char* altStr = NULL); - void init(const char* lonStr, const char* latStr, const char* altStr = NULL); - void clear(); - void operator=(const SGGeod& geod); - SGGeod get() const; -private: - SGPropertyNode_ptr _lon, _lat, _alt; -}; +#define FG_210_COMPAT 1 /** * Model a GPS radio. @@ -69,26 +54,39 @@ private: * /instrumentation/gps/trip-odometer * /instrumentation/gps/true-bug-error-deg * /instrumentation/gps/magnetic-bug-error-deg - */ -class GPS : public SGSubsystem +class GPS : public SGSubsystem, + public flightgear::RNAV, + public flightgear::FlightPlan::Delegate { - public: - - GPS (SGPropertyNode *node); + GPS (SGPropertyNode *node, bool defaultGPSMode = false); GPS (); virtual ~GPS (); + // SGSubsystem interface virtual void init (); + virtual void reinit (); virtual void update (double delta_time_sec); - + virtual void bind(); virtual void unbind(); + + // RNAV interface + virtual SGGeod position(); + virtual double trackDeg(); + virtual double groundSpeedKts(); + virtual double vspeedFPM(); + virtual double magvarDeg(); + virtual double selectedMagCourse(); + virtual double overflightDistanceM(); + virtual double overflightArmDistanceM(); + virtual double overflightArmAngleDeg(); + virtual SGGeod previousLegWaypointPosition(bool& isValid); + private: - friend class GPSListener; friend class SearchFilter; - + /** * Configuration manager, track data relating to aircraft installation */ @@ -96,312 +94,306 @@ private: { public: Config(); - + void bind(GPS* aOwner, SGPropertyNode* aCfg); - - bool turnAnticipationEnabled() const - { return _enableTurnAnticipation; } - + + bool turnAnticipationEnabled() const { return _enableTurnAnticipation; } + /** * Desired turn rate in degrees/second. From this we derive the turn * radius and hence how early we need to anticipate it. */ - double turnRateDegSec() const - { return _turnRate; } - + double turnRateDegSec() const { return _turnRate; } + + /** + * Distance at which we switch to next waypoint. + */ + double overflightDistanceNm() const { return _overflightDistance; } /** * Distance at which we arm overflight sequencing. Once inside this * distance, a change of the wp1 'TO' flag to false will be considered * overlight of the wp. */ - double overflightArmDistanceNm() const - { return _overflightArmDistance; } - + double overflightArmDistanceNm() const { return _overflightArmDistance; } + /** + * abs angle at which we arm overflight sequencing. + */ + double overflightArmAngleDeg() const { return _overflightArmAngle; } + /** * Time before the next WP to activate an external annunciator */ - double waypointAlertTime() const - { return _waypointAlertTime; } - - bool tuneNavRadioToRefVor() const - { return _tuneRadio1ToRefVor; } - - bool requireHardSurface() const - { return _requireHardSurface; } - - double minRunwayLengthFt() const - { return _minRunwayLengthFt; } - - double getExternalCourse() const; - - void setExternalCourse(double aCourseDeg); - - bool cdiDeflectionIsAngular() const - { return (_cdiMaxDeflectionNm <= 0.0); } - + double waypointAlertTime() const { return _waypointAlertTime; } + + bool requireHardSurface() const { return _requireHardSurface; } + + bool cdiDeflectionIsAngular() const { return (_cdiMaxDeflectionNm <= 0.0); } + double cdiDeflectionLinearPeg() const { assert(_cdiMaxDeflectionNm > 0.0); return _cdiMaxDeflectionNm; } - - bool driveAutopilot() const - { return _driveAutopilot; } + + bool driveAutopilot() const { return _driveAutopilot; } + + bool courseSelectable() const { return _courseSelectable; } + + /** + * Select whether we fly the leg track between waypoints, or + * use a direct course from the turn end. Since this is likely confusing, + * look at: http://fgfs.goneabitbursar.com//screenshots/FlyByType-LegType.svg + * For fly-by waypoints, there is no difference. For fly-over waypoints, + * this selects if we fly TF or DF mode. + */ + bool followLegTrackToFix() const { return _followLegTrackToFix; } + private: bool _enableTurnAnticipation; - + // desired turn rate in degrees per second double _turnRate; - + + // distance from waypoint to arm overflight sequencing (in nm) + double _overflightDistance; + // distance from waypoint to arm overflight sequencing (in nm) double _overflightArmDistance; - - // time before reaching a waypoint to trigger annunicator light/sound + + //abs angle from course to waypoint to arm overflight sequencing (in deg) + double _overflightArmAngle; + + // time before reaching a waypoint to trigger annunciator light/sound // (in seconds) double _waypointAlertTime; - - // should GPS automatically tune NAV1 to the reference VOR? - bool _tuneRadio1ToRefVor; - - // minimum runway length to require when filtering - double _minRunwayLengthFt; - + // should we require a hard-surfaced runway when filtering? bool _requireHardSurface; - - // helpers to tie course-source property - const char* getCourseSource() const; - void setCourseSource(const char* aPropPath); - - // property to retrieve the external course from - SGPropertyNode_ptr _extCourseSource; - + double _cdiMaxDeflectionNm; - + + // should we drive the autopilot directly or not? bool _driveAutopilot; + + // is selected-course-deg read to set desired-course or not? + bool _courseSelectable; + + // do we fly direct to fixes, or follow the leg track closely? + bool _followLegTrackToFix; }; - + class SearchFilter : public FGPositioned::Filter { - public: + public: virtual bool pass(FGPositioned* aPos) const; - + virtual FGPositioned::Type minType() const; virtual FGPositioned::Type maxType() const; }; - - /** - * reset all output properties to default / non-service values - */ + + /** reset all output properties to default / non-service values */ void clearOutput(); void updateBasicData(double dt); - void updateWaypoints(); void updateTrackingBug(); - void updateReferenceNavaid(double dt); - void referenceNavaidSet(const std::string& aNavaid); - void tuneNavRadios(); void updateRouteData(); void driveAutopilot(); - - void routeActivated(); - void routeManagerSequenced(); - void routeEdited(); - void routeFinished(); - - void updateTurn(); - void updateOverflight(); + + void updateTurn(); + void updateOverflight(); void beginTurn(); void endTurn(); - + double computeTurnProgress(double aBearing) const; void computeTurnData(); void updateTurnData(); double computeTurnRadiusNm(double aGroundSpeedKts) const; - - /** - * Update one-shot things when WP1 / leg data change - */ - void wp1Changed(); - -// scratch maintenence utilities - void setScratchFromPositioned(FGPositioned* aPos, int aIndex); - void setScratchFromCachedSearchResult(); - void setScratchFromRouteWaypoint(int aIndex); - - /** - * Add airport-specific information to a scratch result - */ - void addAirportToScratch(FGAirport* aAirport); - - void clearScratch(); - - /** - * Predicate, determine if the lon/lat position in the scratch is - * valid or not. - */ - bool isScratchPositionValid() const; - - FGPositioned::Filter* createFilter(FGPositioned::Type aTy); - - /** - * Search kernel - called each time we step through a result - */ - void performSearch(); - + + /** Update one-shot things when WP1 / leg data change */ + void wp1Changed(); + + void clearScratch(); + + /** Predicate, determine if the lon/lat position in the scratch is + * valid or not. */ + bool isScratchPositionValid() const; + FGPositionedRef positionedFromScratch() const; + +#if FG_210_COMPAT + void setScratchFromPositioned(FGPositioned* aPos, int aIndex); + void setScratchFromCachedSearchResult(); + void setScratchFromRouteWaypoint(int aIndex); + + /** Add airport-specific information to a scratch result */ + void addAirportToScratch(FGAirport* aAirport); + + FGPositioned::Filter* createFilter(FGPositioned::Type aTy); + + /** Search kernel - called each time we step through a result */ + void performSearch(); + + // command handlers + void loadRouteWaypoint(); + void loadNearest(); + void search(); + void nextResult(); + void previousResult(); + void defineWaypoint(); + void insertWaypointAtIndex(int aIndex); + void removeWaypointAtIndex(int aIndex); + + // tied-property getter/setters + double getScratchDistance() const; + double getScratchMagBearing() const; + double getScratchTrueBearing() const; + bool getScratchHasNext() const; + +#endif + // command handlers - void selectLegMode(); - void selectOBSMode(); - void directTo(); - void loadRouteWaypoint(); - void loadNearest(); - void search(); - void nextResult(); - void previousResult(); - void defineWaypoint(); - void insertWaypointAtIndex(int aIndex); - void removeWaypointAtIndex(int aIndex); - + void selectLegMode(); + void selectOBSMode(flightgear::Waypt* waypt); + void directTo(); + // tied-property getter/setters - void setCommand(const char* aCmd); - const char* getCommand() const { return ""; } - - const char* getMode() const { return _mode.c_str(); } - - bool getScratchValid() const { return _scratchValid; } - double getScratchDistance() const; - double getScratchMagBearing() const; - double getScratchTrueBearing() const; - bool getScratchHasNext() const { return _searchHasNext; } - - double getSelectedCourse() const { return _selectedCourse; } - double getCDIDeflection() const; - - double getLegDistance() const; - double getLegCourse() const; - double getLegMagCourse() const; - double getAltDistanceRatio() const; - - double getTrueTrack() const { return _last_true_track; } - double getMagTrack() const; - double getGroundspeedKts() const { return _last_speed_kts; } - double getVerticalSpeed() const { return _last_vertical_speed; } - - //bool getLegMode() const { return _mode == "leg"; } - //bool getObsMode() const { return _mode == "obs"; } - - const char* getWP0Ident() const; - const char* getWP0Name() const; - - const char* getWP1Ident() const; - const char* getWP1Name() const; - - double getWP1Distance() const; - double getWP1TTW() const; - const char* getWP1TTWString() const; - double getWP1Bearing() const; - double getWP1MagBearing() const; - double getWP1CourseDeviation() const; - double getWP1CourseErrorNm() const; - bool getWP1ToFlag() const; - bool getWP1FromFlag() const; - - // true-bearing-error and mag-bearing-error - + void setCommand(const char* aCmd); + const char* getCommand() const { return ""; } + + const char* getMode() const { return _mode.c_str(); } + bool getScratchValid() const { return _scratchValid; } + + double getSelectedCourse() const { return _selectedCourse; } + void setSelectedCourse(double crs); + double getDesiredCourse() const { return _desiredCourse; } + + double getCDIDeflection() const; + + double getLegDistance() const; + double getLegCourse() const; + double getLegMagCourse() const; + + double getTrueTrack() const { return _last_true_track; } + double getMagTrack() const; + double getGroundspeedKts() const { return _last_speed_kts; } + double getVerticalSpeed() const { return _last_vertical_speed; } + + const char* getWP0Ident() const; + const char* getWP0Name() const; + + bool getWP1IValid() const; + const char* getWP1Ident() const; + const char* getWP1Name() const; + + double getWP1Distance() const; + double getWP1TTW() const; + const char* getWP1TTWString() const; + double getWP1Bearing() const; + double getWP1MagBearing() const; + double getWP1CourseDeviation() const; + double getWP1CourseErrorNm() const; + bool getWP1ToFlag() const; + bool getWP1FromFlag() const; + + // true-bearing-error and mag-bearing-error + + + /** + * Tied-properties helper, record nodes which are tied for easy un-tie-ing + */ + template + void tie(SGPropertyNode* aNode, const char* aRelPath, const SGRawValue& aRawValue) + { + _tiedProperties.Tie(aNode->getNode(aRelPath, true), aRawValue); + } - /** - * Tied-properties helper, record nodes which are tied for easy un-tie-ing - */ - template - void tie(SGPropertyNode* aNode, const char* aRelPath, const SGRawValue& aRawValue) - { - SGPropertyNode* nd = aNode->getNode(aRelPath, true); - _tiedNodes.push_back(nd); - nd->tie(aRawValue); - } - - /// helper, tie the lat/lon/elev of a SGGeod to the named children of aNode - void tieSGGeod(SGPropertyNode* aNode, SGGeod& aRef, - const char* lonStr, const char* latStr, const char* altStr); + /** helper, tie the lat/lon/elev of a SGGeod to the named children of aNode */ + void tieSGGeod(SGPropertyNode* aNode, SGGeod& aRef, + const char* lonStr, const char* latStr, const char* altStr); - /// helper, tie a SGGeod to proeprties, but read-only - void tieSGGeodReadOnly(SGPropertyNode* aNode, SGGeod& aRef, - const char* lonStr, const char* latStr, const char* altStr); + /** helper, tie a SGGeod to proeprties, but read-only */ + void tieSGGeodReadOnly(SGPropertyNode* aNode, SGGeod& aRef, + const char* lonStr, const char* latStr, const char* altStr); +// FlightPlan::Delegate + virtual void currentWaypointChanged(); + virtual void waypointsChanged(); + virtual void cleared(); + virtual void endOfFlightPlan(); + + void sequence(); + void routeManagerFlightPlanChanged(SGPropertyNode*); + void routeActivated(SGPropertyNode*); + // members - SGPropertyNode_ptr _gpsNode; - SGPropertyNode_ptr _magvar_node; - SGPropertyNode_ptr _serviceable_node; - SGPropertyNode_ptr _electrical_node; - SGPropertyNode_ptr _tracking_bug_node; - SGPropertyNode_ptr _raim_node; - - SGPropertyNode_ptr _odometer_node; + SGPropertyNode_ptr _gpsNode; + SGPropertyNode_ptr _currentWayptNode; + SGPropertyNode_ptr _magvar_node; + SGPropertyNode_ptr _serviceable_node; + SGPropertyNode_ptr _electrical_node; + SGPropertyNode_ptr _tracking_bug_node; + SGPropertyNode_ptr _raim_node; + + SGPropertyNode_ptr _odometer_node; SGPropertyNode_ptr _trip_odometer_node; SGPropertyNode_ptr _true_bug_error_node; SGPropertyNode_ptr _magnetic_bug_error_node; + SGPropertyNode_ptr _eastWestVelocity; + SGPropertyNode_ptr _northSouthVelocity; - SGPropertyNode_ptr _ref_navaid_id_node; - SGPropertyNode_ptr _ref_navaid_bearing_node; - SGPropertyNode_ptr _ref_navaid_distance_node; - SGPropertyNode_ptr _ref_navaid_mag_bearing_node; - SGPropertyNode_ptr _ref_navaid_frequency_node; - SGPropertyNode_ptr _ref_navaid_name_node; - - SGPropertyNode_ptr _route_active_node; + // SGPropertyNode_ptr _route_active_node; SGPropertyNode_ptr _route_current_wp_node; SGPropertyNode_ptr _routeDistanceNm; SGPropertyNode_ptr _routeETE; - SGPropertyNode_ptr _routeEditedSignal; - SGPropertyNode_ptr _routeFinishedSignal; - - double _selectedCourse; + SGPropertyNode_ptr _desiredCourseNode; + double _selectedCourse; + double _desiredCourse; + bool _dataValid; SGGeod _last_pos; bool _lastPosValid; double _last_speed_kts; double _last_true_track; double _last_vertical_speed; + double _lastEWVelocity; + double _lastNSVelocity; + + /** + * the instrument manager creates a default instance of us, + * if no explicit GPS is specific in the aircraft's instruments.xml file. + * This allows default route-following to work with the generic autopilot. + * This flag is set in that case, to inform us we're a 'fake' installation, + * and not to worry about electrical power or similar. + */ + bool _defaultGPSMode; std::string _mode; - GPSListener* _listener; Config _config; - FGRouteMgr* _routeMgr; - - bool _ref_navaid_set; - double _ref_navaid_elapsed; - FGPositionedRef _ref_navaid; - std::string _name; int _num; - - SGGeodProperty _position; - SGGeod _wp0_position; - SGGeod _wp1_position; - SGGeod _indicated_pos; - std::string _wp0Ident, _wp0Name, _wp1Ident, _wp1Name; - double _wp1DistanceM, _wp1TrueBearing; - + + SGGeod _wp0_position; + SGGeod _indicated_pos; + double _legDistanceNm; + // scratch data - SGGeod _scratchPos; - SGPropertyNode_ptr _scratchNode; - bool _scratchValid; - + SGGeod _scratchPos; + SGPropertyNode_ptr _scratchNode; + bool _scratchValid; +#if FG_210_COMPAT // search data - int _searchResultIndex; - std::string _searchQuery; - FGPositioned::Type _searchType; - bool _searchExact; - bool _searchOrderByRange; - bool _searchResultsCached; - FGPositioned::List _searchResults; - bool _searchIsRoute; ///< set if 'search' is actually the current route - bool _searchHasNext; ///< is there a result after this one? - bool _searchNames; ///< set if we're searching names instead of idents - - // turn data + int _searchResultIndex; + std::string _searchQuery; + FGPositioned::Type _searchType; + bool _searchExact; + FGPositionedList _searchResults; + bool _searchIsRoute; ///< set if 'search' is actually the current route + bool _searchHasNext; ///< is there a result after this one? + bool _searchNames; ///< set if we're searching names instead of idents +#endif + +// turn data bool _computeTurnData; ///< do we need to update the turn data? bool _anticipateTurn; ///< are we anticipating the next turn or not? bool _inTurn; // is a turn in progress? @@ -411,16 +403,22 @@ private: double _turnRadius; // radius of turn in nm SGGeod _turnPt; SGGeod _turnCentre; - - SGPropertyNode_ptr _realismSimpleGps; ///< should the GPS be simple or realistic? - + + std::auto_ptr _wayptController; + + flightgear::WayptRef _prevWaypt; + flightgear::WayptRef _currentWaypt; + // autopilot drive properties - SGPropertyNode_ptr _apTrueHeading; - SGPropertyNode_ptr _apTargetAltitudeFt; - SGPropertyNode_ptr _apAltitudeLock; - - std::vector _tiedNodes; -}; + SGPropertyNode_ptr _apDrivingFlag; + SGPropertyNode_ptr _apTrueHeading; + + simgear::TiedPropertyList _tiedProperties; + flightgear::FlightPlanRef _route; + + SGPropertyChangeCallback _callbackFlightPlanChanged; + SGPropertyChangeCallback _callbackRouteActivated; +}; #endif // __INSTRUMENTS_GPS_HXX