X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FInstrumentation%2Fgps.hxx;h=21cd461662d4404e32b62146d40bcfbf812133b0;hb=0b9adf8854398461333eba43df18fa2f5c8231a1;hp=27948ecb47e7ffc259724ce28eff798243573f4c;hpb=b9e4775a7a4bbeac9e3af2bf617ddacfbc2d47bf;p=flightgear.git diff --git a/src/Instrumentation/gps.hxx b/src/Instrumentation/gps.hxx index 27948ecb4..21cd46166 100644 --- a/src/Instrumentation/gps.hxx +++ b/src/Instrumentation/gps.hxx @@ -7,14 +7,38 @@ #ifndef __INSTRUMENTS_GPS_HXX #define __INSTRUMENTS_GPS_HXX 1 -#ifndef __cplusplus -# error This library requires C++ -#endif +#include +#include #include -#include #include +#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; +}; /** * Model a GPS radio. @@ -28,15 +52,6 @@ * /systems/electrical/outputs/gps * /instrumentation/gps/serviceable * - * /instrumentation/gps/wp-longitude-deg - * /instrumentation/gps/wp-latitude-deg - * /instrumentation/gps/wp-altitude-ft - * /instrumentation/gps/wp-ID - * /instrumentation/gps/wp-name - * /instrumentation/gps/desired-course-deg - * /instrumentation/gps/get-nearest-airport - * /instrumentation/gps/waypoint-type - * /instrumentation/gps/tracking-bug * * Output properties: * @@ -59,123 +74,342 @@ * /instrumentation/gps/trip-odometer * /instrumentation/gps/true-bug-error-deg * /instrumentation/gps/magnetic-bug-error-deg - * /instrumentation/gps/true-bearing-error-deg - * /instrumentation/gps/magnetic-bearing-error-deg */ -class GPS : public SGSubsystem +class GPS : public SGSubsystem, public flightgear::RNAV { - public: - GPS (SGPropertyNode *node); GPS (); virtual ~GPS (); + // SGSubsystem interface virtual void init (); 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 overflightArmDistanceM(); + private: + friend class GPSListener; + friend class SearchFilter; + + /** + * Configuration manager, track data relating to aircraft installation + */ + class Config + { + public: + Config(); + + void bind(GPS* aOwner, SGPropertyNode* aCfg); + + 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; } + + /** + * 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; } + + /** + * Time before the next WP to activate an external annunciator + */ + 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 courseSelectable() const { return _courseSelectable; } + + private: + bool _enableTurnAnticipation; + + // desired turn rate in degrees per second + double _turnRate; + + // distance from waypoint to arm overflight sequencing (in nm) + double _overflightArmDistance; + + // time before reaching a waypoint to trigger annunciator light/sound + // (in seconds) + double _waypointAlertTime; + + // minimum runway length to require when filtering + double _minRunwayLengthFt; + + // should we require a hard-surfaced runway when filtering? + bool _requireHardSurface; + + 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; + }; + + class SearchFilter : public FGPositioned::Filter + { + 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 */ + void clearOutput(); + + void updateBasicData(double dt); + + void updateTrackingBug(); + void updateReferenceNavaid(double dt); + void referenceNavaidSet(const std::string& aNavaid); + void updateRouteData(); + void driveAutopilot(); + + void routeActivated(); + void routeManagerSequenced(); + void routeEdited(); + void routeFinished(); + + void updateTurn(); + void updateOverflight(); + void beginTurn(); + void endTurn(); - void search (double frequency, double longitude_rad, - double latitude_rad, double altitude_m); + double computeTurnProgress(double aBearing) const; + void computeTurnData(); + void updateTurnData(); + double computeTurnRadiusNm(double aGroundSpeedKts) const; - SGPropertyNode_ptr _longitude_node; - SGPropertyNode_ptr _latitude_node; - SGPropertyNode_ptr _altitude_node; + /** Update one-shot things when WP1 / leg data change */ + void wp1Changed(); + +// scratch maintenance 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(); + +// 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); + +// 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; + + 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; } + + //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 + + + /** + * 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); + } + + /** 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); + +// members + SGPropertyNode_ptr _gpsNode; + SGPropertyNode_ptr _currentWayptNode; SGPropertyNode_ptr _magvar_node; SGPropertyNode_ptr _serviceable_node; SGPropertyNode_ptr _electrical_node; - SGPropertyNode_ptr _wp0_longitude_node; - SGPropertyNode_ptr _wp0_latitude_node; - SGPropertyNode_ptr _wp0_altitude_node; - SGPropertyNode_ptr _wp0_ID_node; - SGPropertyNode_ptr _wp0_name_node; - SGPropertyNode_ptr _wp0_course_node; - SGPropertyNode_ptr _get_nearest_airport_node; - SGPropertyNode_ptr _wp0_waypoint_type_node; - SGPropertyNode_ptr _wp1_longitude_node; - SGPropertyNode_ptr _wp1_latitude_node; - SGPropertyNode_ptr _wp1_altitude_node; - SGPropertyNode_ptr _wp1_ID_node; - SGPropertyNode_ptr _wp1_name_node; - SGPropertyNode_ptr _wp1_course_node; - SGPropertyNode_ptr _wp1_waypoint_type_node; SGPropertyNode_ptr _tracking_bug_node; - SGPropertyNode_ptr _raim_node; - SGPropertyNode_ptr _indicated_longitude_node; - SGPropertyNode_ptr _indicated_latitude_node; - SGPropertyNode_ptr _indicated_altitude_node; - SGPropertyNode_ptr _indicated_vertical_speed_node; - SGPropertyNode_ptr _true_track_node; - SGPropertyNode_ptr _magnetic_track_node; - SGPropertyNode_ptr _speed_node; - SGPropertyNode_ptr _wp0_distance_node; - SGPropertyNode_ptr _wp0_ttw_node; - SGPropertyNode_ptr _wp0_bearing_node; - SGPropertyNode_ptr _wp0_mag_bearing_node; - SGPropertyNode_ptr _wp0_course_deviation_node; - SGPropertyNode_ptr _wp0_course_error_nm_node; - SGPropertyNode_ptr _wp0_to_flag_node; - SGPropertyNode_ptr _wp1_distance_node; - SGPropertyNode_ptr _wp1_ttw_node; - SGPropertyNode_ptr _wp1_bearing_node; - SGPropertyNode_ptr _wp1_mag_bearing_node; - SGPropertyNode_ptr _wp1_course_deviation_node; - SGPropertyNode_ptr _wp1_course_error_nm_node; - SGPropertyNode_ptr _wp1_to_flag_node; + SGPropertyNode_ptr _odometer_node; SGPropertyNode_ptr _trip_odometer_node; SGPropertyNode_ptr _true_bug_error_node; SGPropertyNode_ptr _magnetic_bug_error_node; - SGPropertyNode_ptr _true_wp0_bearing_error_node; - SGPropertyNode_ptr _magnetic_wp0_bearing_error_node; - SGPropertyNode_ptr _true_wp1_bearing_error_node; - SGPropertyNode_ptr _magnetic_wp1_bearing_error_node; - SGPropertyNode_ptr _leg_distance_node; - SGPropertyNode_ptr _leg_course_node; - SGPropertyNode_ptr _leg_magnetic_course_node; - SGPropertyNode_ptr _alt_dist_ratio_node; - SGPropertyNode_ptr _leg_course_deviation_node; - SGPropertyNode_ptr _leg_course_error_nm_node; - SGPropertyNode_ptr _leg_to_flag_node; - SGPropertyNode_ptr _alt_deviation_node; - - SGPropertyNode_ptr _route; - SGPropertyNode_ptr addWp; - SGPropertyNode_ptr popWp; - - SGRoute *route; - - bool _last_valid; - double _last_longitude_deg; - double _last_latitude_deg; - double _last_altitude_m; + 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_current_wp_node; + SGPropertyNode_ptr _routeDistanceNm; + SGPropertyNode_ptr _routeETE; + SGPropertyNode_ptr _routeEditedSignal; + SGPropertyNode_ptr _routeFinishedSignal; + 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; + + std::string _mode; + GPSListener* _listener; + Config _config; + FGRouteMgr* _routeMgr; + + bool _ref_navaid_set; + double _ref_navaid_elapsed; + FGPositionedRef _ref_navaid; - double _wp0_latitude_deg; - double _wp0_longitude_deg; - double _wp0_altitude_m; - double _wp1_latitude_deg; - double _wp1_longitude_deg; - double _wp1_altitude_m; - string _last_wp0_ID; - string _last_wp1_ID; - - double _alt_dist_ratio; - double _distance_m; - double _course_deg; - - double _bias_length; - double _bias_angle; - double _azimuth_error; - double _range_error; - double _elapsed_time; - - string _name; + std::string _name; int _num; -}; + SGGeodProperty _position; + SGGeod _wp0_position; + SGGeod _indicated_pos; + double _legDistanceNm; + +// scratch data + SGGeod _scratchPos; + SGPropertyNode_ptr _scratchNode; + bool _scratchValid; + +// search data + int _searchResultIndex; + std::string _searchQuery; + FGPositioned::Type _searchType; + bool _searchExact; + 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 + 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? + bool _turnSequenced; // have we sequenced the new leg? + double _turnAngle; // angle to turn through, in degrees + double _turnStartBearing; // bearing of inbound leg + double _turnRadius; // radius of turn in nm + SGGeod _turnPt; + SGGeod _turnCentre; + + std::auto_ptr _wayptController; + SGPropertyNode_ptr _realismSimpleGps; ///< should the GPS be simple or realistic? + flightgear::WayptRef _prevWaypt; + flightgear::WayptRef _currentWaypt; + +// autopilot drive properties + SGPropertyNode_ptr _apDrivingFlag; + SGPropertyNode_ptr _apTrueHeading; + SGPropertyNode_ptr _apTargetAltitudeFt; + SGPropertyNode_ptr _apAltitudeLock; + + simgear::TiedPropertyList _tiedProperties; + +}; #endif // __INSTRUMENTS_GPS_HXX