]> git.mxchange.org Git - flightgear.git/blobdiff - src/Instrumentation/gps.hxx
GPS: fix bad init when far from any airport
[flightgear.git] / src / Instrumentation / gps.hxx
index 76596773a7a5eb4e769e75c24c9be6d8f8da617d..a142330ce54742a9c062fe72fc2a5b1d7fc00354 100644 (file)
@@ -7,33 +7,18 @@
 #ifndef __INSTRUMENTS_GPS_HXX
 #define __INSTRUMENTS_GPS_HXX 1
 
+#include <cassert>
+#include <memory>
+
 #include <simgear/props/props.hxx>
 #include <simgear/structure/subsystem_mgr.hxx>
-#include <simgear/math/SGMath.hxx>
+#include <simgear/props/tiedpropertylist.hxx>
 
-#include "Navaids/positioned.hxx"
+#include <Navaids/positioned.hxx>
+#include <Navaids/FlightPlan.hxx>
+#include <Instrumentation/rnav_waypt_controller.hxx>
 
-// 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,293 @@ 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; }
+
     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;
     };
-    
+
     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;
+
+#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; }
 
-  /**
-   * Tied-properties helper, record nodes which are tied for easy un-tie-ing
-   */
-  template <typename T>
-  void tie(SGPropertyNode* aNode, const char* aRelPath, const SGRawValue<T>& 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);
+    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 <typename T>
+    void tie(SGPropertyNode* aNode, const char* aRelPath, const SGRawValue<T>& 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);
+    /** 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 flat 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 +390,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<flightgear::WayptController> _wayptController;
+
+    flightgear::WayptRef _prevWaypt;
+    flightgear::WayptRef _currentWaypt;
+
 // autopilot drive properties
-  SGPropertyNode_ptr _apTrueHeading;
-  SGPropertyNode_ptr _apTargetAltitudeFt;
-  SGPropertyNode_ptr _apAltitudeLock;
-  
-  std::vector<SGPropertyNode*> _tiedNodes;
-};
+    SGPropertyNode_ptr _apDrivingFlag;
+    SGPropertyNode_ptr _apTrueHeading;
+    
+    simgear::TiedPropertyList _tiedProperties;
 
+    flightgear::FlightPlanRef _route;
+    
+    SGPropertyChangeCallback<GPS> _callbackFlightPlanChanged;
+    SGPropertyChangeCallback<GPS> _callbackRouteActivated;
+};
 
 #endif // __INSTRUMENTS_GPS_HXX