#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 "Navaids/positioned.hxx"
+#include <Navaids/positioned.hxx>
+#include <Instrumentation/rnav_waypt_controller.hxx>
// forward decls
class SGRoute;
* /instrumentation/gps/magnetic-bug-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;
{
public:
Config();
-
- void init(SGPropertyNode*);
+
+ void bind(GPS* aOwner, SGPropertyNode* aCfg);
bool turnAnticipationEnabled() const
{ return _enableTurnAnticipation; }
double waypointAlertTime() const
{ return _waypointAlertTime; }
- bool tuneNavRadioToRefVor() const
- { return _tuneRadio1ToRefVor; }
-
bool requireHardSurface() const
{ return _requireHardSurface; }
double minRunwayLengthFt() const
{ return _minRunwayLengthFt; }
- double getOBSCourse() const;
-
bool cdiDeflectionIsAngular() const
{ return (_cdiMaxDeflectionNm <= 0.0); }
assert(_cdiMaxDeflectionNm > 0.0);
return _cdiMaxDeflectionNm;
}
+
+ bool driveAutopilot() const
+ { return _driveAutopilot; }
+
+ bool courseSelectable() const
+ { return _courseSelectable; }
private:
bool _enableTurnAnticipation;
// (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 obs-course-source property
- const char* getOBSCourseSource() const;
- void setOBSCourseSource(const char* aPropPath);
+ double _cdiMaxDeflectionNm;
- // property to retrieve the OBS course from
- SGPropertyNode_ptr _obsCourseSource;
+ // should we drive the autopilot directly or not?
+ bool _driveAutopilot;
- double _cdiMaxDeflectionNm;
+ // is selected-course-deg read to set desired-course or not?
+ bool _courseSelectable;
};
class SearchFilter : public FGPositioned::Filter
*/
void clearOutput();
- void updateWithValid(double dt);
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 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 nextResult();
void previousResult();
void defineWaypoint();
+ void insertWaypointAtIndex(int aIndex);
+ void removeWaypointAtIndex(int aIndex);
// tied-property getter/setters
void setCommand(const char* aCmd);
double getScratchDistance() const;
double getScratchMagBearing() const;
double getScratchTrueBearing() const;
- bool getScratchHasNext() const { return _searchHasNext; }
+ 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 getAltDistanceRatio() const;
double getTrueTrack() const { return _last_true_track; }
double getMagTrack() const;
double getWP1CourseDeviation() const;
double getWP1CourseErrorNm() const;
bool getWP1ToFlag() const;
- // true-bearing-error and mag-bearing-error
+ 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)
+ {
+ 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 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 _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 _route_current_wp_node;
SGPropertyNode_ptr _routeDistanceNm;
SGPropertyNode_ptr _routeETE;
-
- SGPropertyNode_ptr _fromFlagNode;
-
+ SGPropertyNode_ptr _routeEditedSignal;
+ SGPropertyNode_ptr _routeFinishedSignal;
+ SGPropertyNode_ptr _desiredCourseNode;
+
double _selectedCourse;
+ double _desiredCourse;
- bool _last_valid;
+ 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;
SGGeodProperty _position;
SGGeod _wp0_position;
- SGGeod _wp1_position;
SGGeod _indicated_pos;
- std::string _wp0Ident, _wp0Name, _wp1Ident, _wp1Name;
- double _wp1DistanceM, _wp1TrueBearing;
+ double _legDistanceNm;
// scratch data
SGGeod _scratchPos;
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?
double _turnRadius; // radius of turn in nm
SGGeod _turnPt;
SGGeod _turnCentre;
+
+ std::auto_ptr<flightgear::WayptController> _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;
+
+ std::vector<SGPropertyNode_ptr> _tiedNodes;
};