#include <simgear/props/tiedpropertylist.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.
* /instrumentation/gps/true-bug-error-deg
* /instrumentation/gps/magnetic-bug-error-deg
*/
-class GPS : public SGSubsystem, public flightgear::RNAV
+class GPS : public SGSubsystem,
+ public flightgear::RNAV,
+ public flightgear::FlightPlan::Delegate
{
public:
- GPS (SGPropertyNode *node);
+ GPS (SGPropertyNode *node, bool defaultGPSMode = false);
GPS ();
virtual ~GPS ();
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;
/**
*/
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; }
+ /**
+ * abs angle at which we arm overflight sequencing.
+ */
+ double overflightArmAngleDeg() const { return _overflightArmAngle; }
/**
* Time before the next WP to activate an external annunciator
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;
+ //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;
- // minimum runway length to require when filtering
- double _minRunwayLengthFt;
-
// should we require a hard-surfaced runway when filtering?
bool _requireHardSurface;
// 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
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();
/** 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;
-
+ 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 */
+
+ /** Search kernel - called each time we step through a result */
void performSearch();
-
-// command handlers
- void selectLegMode();
- void selectOBSMode();
- void directTo();
+
+ // command handlers
void loadRouteWaypoint();
void loadNearest();
void search();
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(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;
double getSelectedCourse() const { return _selectedCourse; }
void setSelectedCourse(double crs);
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;
+ bool getWP1IValid() const;
const char* getWP1Ident() const;
const char* getWP1Name() const;
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 _currentWayptNode;
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;
SGPropertyNode_ptr _desiredCourseNode;
-
+
double _selectedCourse;
double _desiredCourse;
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 _indicated_pos;
double _legDistanceNm;
SGGeod _scratchPos;
SGPropertyNode_ptr _scratchNode;
bool _scratchValid;
-
+#if FG_210_COMPAT
// search data
int _searchResultIndex;
std::string _searchQuery;
FGPositioned::Type _searchType;
bool _searchExact;
- FGPositioned::List _searchResults;
+ 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?
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;
-
+
simgear::TiedPropertyList _tiedProperties;
+ flightgear::FlightPlanRef _route;
+
+ SGPropertyChangeCallback<GPS> _callbackFlightPlanChanged;
+ SGPropertyChangeCallback<GPS> _callbackRouteActivated;
};
#endif // __INSTRUMENTS_GPS_HXX