diff --git a/src/Instrumentation/gps.cxx b/src/Instrumentation/gps.cxx index 57b67b455..0343a19d2 100644 --- a/src/Instrumentation/gps.cxx +++ b/src/Instrumentation/gps.cxx @@ -74,28 +74,6 @@ SGGeod SGGeodProperty::get() const } } -static void tieSGGeod(SGPropertyNode* aNode, SGGeod& aRef, - const char* lonStr, const char* latStr, const char* altStr) -{ - aNode->tie(lonStr, SGRawValueMethods(aRef, &SGGeod::getLongitudeDeg, &SGGeod::setLongitudeDeg)); - aNode->tie(latStr, SGRawValueMethods(aRef, &SGGeod::getLatitudeDeg, &SGGeod::setLatitudeDeg)); - - if (altStr) { - aNode->tie(altStr, SGRawValueMethods(aRef, &SGGeod::getElevationFt, &SGGeod::setElevationFt)); - } -} - -static void tieSGGeodReadOnly(SGPropertyNode* aNode, SGGeod& aRef, - const char* lonStr, const char* latStr, const char* altStr) -{ - aNode->tie(lonStr, SGRawValueMethods(aRef, &SGGeod::getLongitudeDeg, NULL)); - aNode->tie(latStr, SGRawValueMethods(aRef, &SGGeod::getLatitudeDeg, NULL)); - - if (altStr) { - aNode->tie(altStr, SGRawValueMethods(aRef, &SGGeod::getElevationFt, NULL)); - } -} - static const char* makeTTWString(double TTW) { if ((TTW <= 0.0) || (TTW >= 356400.5)) { // 99 hours @@ -220,20 +198,21 @@ GPS::Config::Config() : _extCourseSource = fgGetNode("/instrumentation/nav[0]/radials/selected-deg", true); } -void GPS::Config::init(SGPropertyNode* aCfgNode) +void GPS::Config::bind(GPS* aOwner, SGPropertyNode* aCfg) { - aCfgNode->tie("turn-rate-deg-sec", SGRawValuePointer(&_turnRate)); - aCfgNode->tie("turn-anticipation", SGRawValuePointer(&_enableTurnAnticipation)); - aCfgNode->tie("wpt-alert-time", SGRawValuePointer(&_waypointAlertTime)); - aCfgNode->tie("tune-nav-radio-to-ref-vor", SGRawValuePointer(&_tuneRadio1ToRefVor)); - aCfgNode->tie("min-runway-length-ft", SGRawValuePointer(&_minRunwayLengthFt)); - aCfgNode->tie("hard-surface-runways-only", SGRawValuePointer(&_requireHardSurface)); + aOwner->tie(aCfg, "turn-rate-deg-sec", SGRawValuePointer(&_turnRate)); - aCfgNode->tie("course-source", SGRawValueMethods + aOwner->tie(aCfg, "turn-anticipation", SGRawValuePointer(&_enableTurnAnticipation)); + aOwner->tie(aCfg, "wpt-alert-time", SGRawValuePointer(&_waypointAlertTime)); + aOwner->tie(aCfg, "tune-nav-radio-to-ref-vor", SGRawValuePointer(&_tuneRadio1ToRefVor)); + aOwner->tie(aCfg, "min-runway-length-ft", SGRawValuePointer(&_minRunwayLengthFt)); + aOwner->tie(aCfg, "hard-surface-runways-only", SGRawValuePointer(&_requireHardSurface)); + + aOwner->tie(aCfg, "course-source", SGRawValueMethods (*this, &GPS::Config::getCourseSource, &GPS::Config::setCourseSource)); - aCfgNode->tie("cdi-max-deflection-nm", SGRawValuePointer(&_cdiMaxDeflectionNm)); - aCfgNode->tie("drive-autopilot", SGRawValuePointer(&_driveAutopilot)); + aOwner->tie(aCfg, "cdi-max-deflection-nm", SGRawValuePointer(&_cdiMaxDeflectionNm)); + aOwner->tie(aCfg, "drive-autopilot", SGRawValuePointer(&_driveAutopilot)); } const char* @@ -291,6 +270,9 @@ GPS::GPS ( SGPropertyNode *node) : _anticipateTurn(false), _inTurn(false) { + string branch = "/instrumentation/" + _name; + _gpsNode = fgGetNode(branch.c_str(), _num, true ); + _scratchNode = _gpsNode->getChild("scratch", 0, true); } GPS::~GPS () @@ -300,112 +282,39 @@ GPS::~GPS () void GPS::init () { - _routeMgr = (FGRouteMgr*) globals->get_subsystem("route-manager"); - assert(_routeMgr); + _routeMgr = (FGRouteMgr*) globals->get_subsystem("route-manager"); + assert(_routeMgr); - string branch; - branch = "/instrumentation/" + _name; - - SGPropertyNode *node = fgGetNode(branch.c_str(), _num, true ); - _config.init(node->getChild("config", 0, true)); - _position.init("/position/longitude-deg", "/position/latitude-deg", "/position/altitude-ft"); _magvar_node = fgGetNode("/environment/magnetic-variation-deg", true); - _serviceable_node = node->getChild("serviceable", 0, true); + _serviceable_node = _gpsNode->getChild("serviceable", 0, true); _serviceable_node->setBoolValue(true); _electrical_node = fgGetNode("/systems/electrical/outputs/gps", true); // basic GPS outputs - node->tie("selected-course-deg", SGRawValueMethods(*this, &GPS::getSelectedCourse, NULL)); + _raim_node = _gpsNode->getChild("raim", 0, true); + _odometer_node = _gpsNode->getChild("odometer", 0, true); + _trip_odometer_node = _gpsNode->getChild("trip-odometer", 0, true); + _true_bug_error_node = _gpsNode->getChild("true-bug-error-deg", 0, true); + _magnetic_bug_error_node = _gpsNode->getChild("magnetic-bug-error-deg", 0, true); - _raim_node = node->getChild("raim", 0, true); - - tieSGGeodReadOnly(node, _indicated_pos, "indicated-longitude-deg", - "indicated-latitude-deg", "indicated-altitude-ft"); - - node->tie("indicated-vertical-speed", SGRawValueMethods - (*this, &GPS::getVerticalSpeed, NULL)); - node->tie("indicated-track-true-deg", SGRawValueMethods - (*this, &GPS::getTrueTrack, NULL)); - node->tie("indicated-track-magnetic-deg", SGRawValueMethods - (*this, &GPS::getMagTrack, NULL)); - node->tie("indicated-ground-speed-kt", SGRawValueMethods - (*this, &GPS::getGroundspeedKts, NULL)); - - _odometer_node = node->getChild("odometer", 0, true); - _trip_odometer_node = node->getChild("trip-odometer", 0, true); - _true_bug_error_node = node->getChild("true-bug-error-deg", 0, true); - _magnetic_bug_error_node = node->getChild("magnetic-bug-error-deg", 0, true); - -// command system - node->tie("mode", SGRawValueMethods(*this, &GPS::getMode, NULL)); - node->tie("command", SGRawValueMethods(*this, &GPS::getCommand, &GPS::setCommand)); - - _scratchNode = node->getChild("scratch", 0, true); - tieSGGeod(_scratchNode, _scratchPos, "longitude-deg", "latitude-deg", "altitude-ft"); - _scratchNode->tie("valid", SGRawValueMethods(*this, &GPS::getScratchValid, NULL)); - _scratchNode->tie("distance-nm", SGRawValueMethods(*this, &GPS::getScratchDistance, NULL)); - _scratchNode->tie("true-bearing-deg", SGRawValueMethods(*this, &GPS::getScratchTrueBearing, NULL)); - _scratchNode->tie("mag-bearing-deg", SGRawValueMethods(*this, &GPS::getScratchMagBearing, NULL)); - _scratchNode->tie("has-next", SGRawValueMethods(*this, &GPS::getScratchHasNext, NULL)); - _scratchValid = false; - -// waypoint data (including various historical things) - SGPropertyNode *wp_node = node->getChild("wp", 0, true); - SGPropertyNode *wp0_node = wp_node->getChild("wp", 0, true); +// waypoints + SGPropertyNode *wp_node = _gpsNode->getChild("wp", 0, true); SGPropertyNode *wp1_node = wp_node->getChild("wp", 1, true); - tieSGGeodReadOnly(wp0_node, _wp0_position, "longitude-deg", "latitude-deg", "altitude-ft"); - wp0_node->tie("ID", SGRawValueMethods - (*this, &GPS::getWP0Ident, NULL)); - wp0_node->tie("name", SGRawValueMethods - (*this, &GPS::getWP0Name, NULL)); - - tieSGGeodReadOnly(wp1_node, _wp1_position, "longitude-deg", "latitude-deg", "altitude-ft"); - wp1_node->tie("ID", SGRawValueMethods - (*this, &GPS::getWP1Ident, NULL)); - wp1_node->tie("name", SGRawValueMethods - (*this, &GPS::getWP1Name, NULL)); - // for compatability, alias selected course down to wp/wp[1]/desired-course-deg SGPropertyNode* wp1Crs = wp1_node->getChild("desired-course-deg", 0, true); - wp1Crs->alias(node->getChild("selected-course-deg")); + wp1Crs->alias(_gpsNode->getChild("selected-course-deg")); // _true_wp1_bearing_error_node = // wp1_node->getChild("true-bearing-error-deg", 0, true); // _magnetic_wp1_bearing_error_node = // wp1_node->getChild("magnetic-bearing-error-deg", 0, true); - wp1_node->tie("distance-nm", SGRawValueMethods - (*this, &GPS::getWP1Distance, NULL)); - wp1_node->tie("bearing-true-deg", SGRawValueMethods - (*this, &GPS::getWP1Bearing, NULL)); - wp1_node->tie("bearing-mag-deg", SGRawValueMethods - (*this, &GPS::getWP1MagBearing, NULL)); - wp1_node->tie("TTW-sec", SGRawValueMethods - (*this, &GPS::getWP1TTW, NULL)); - wp1_node->tie("TTW", SGRawValueMethods - (*this, &GPS::getWP1TTWString, NULL)); - - wp1_node->tie("course-deviation-deg", SGRawValueMethods - (*this, &GPS::getWP1CourseDeviation, NULL)); - wp1_node->tie("course-error-nm", SGRawValueMethods - (*this, &GPS::getWP1CourseErrorNm, NULL)); - wp1_node->tie("to-flag", SGRawValueMethods - (*this, &GPS::getWP1ToFlag, NULL)); - wp1_node->tie("from-flag", SGRawValueMethods - (*this, &GPS::getWP1FromFlag, NULL)); - - _tracking_bug_node = node->getChild("tracking-bug", 0, true); + _tracking_bug_node = _gpsNode->getChild("tracking-bug", 0, true); -// leg properties (only valid in DTO/LEG modes, not OBS) - wp_node->tie("leg-distance-nm", SGRawValueMethods(*this, &GPS::getLegDistance, NULL)); - wp_node->tie("leg-true-course-deg", SGRawValueMethods(*this, &GPS::getLegCourse, NULL)); - wp_node->tie("leg-mag-course-deg", SGRawValueMethods(*this, &GPS::getLegMagCourse, NULL)); - wp_node->tie("alt-dist-ratio", SGRawValueMethods(*this, &GPS::getAltDistanceRatio, NULL)); - // reference navid - SGPropertyNode_ptr ref_navaid = node->getChild("ref-navaid", 0, true); + SGPropertyNode_ptr ref_navaid = _gpsNode->getChild("ref-navaid", 0, true); _ref_navaid_id_node = ref_navaid->getChild("id", 0, true); _ref_navaid_name_node = ref_navaid->getChild("name", 0, true); _ref_navaid_bearing_node = ref_navaid->getChild("bearing-deg", 0, true); @@ -417,8 +326,8 @@ GPS::init () // route properties // should these move to the route manager? - _routeDistanceNm = node->getChild("route-distance-nm", 0, true); - _routeETE = node->getChild("ETE", 0, true); + _routeDistanceNm = _gpsNode->getChild("route-distance-nm", 0, true); + _routeETE = _gpsNode->getChild("ETE", 0, true); _routeEditedSignal = fgGetNode("/autopilot/route-manager/signals/edited", true); _routeFinishedSignal = fgGetNode("/autopilot/route-manager/signals/finished", true); @@ -433,16 +342,12 @@ GPS::init () _routeFinishedSignal->addChangeListener(_listener); // navradio slaving properties - node->tie("cdi-deflection", SGRawValueMethods - (*this, &GPS::getCDIDeflection)); - - SGPropertyNode* toFlag = node->getChild("to-flag", 0, true); + SGPropertyNode* toFlag = _gpsNode->getChild("to-flag", 0, true); toFlag->alias(wp1_node->getChild("to-flag")); - SGPropertyNode* fromFlag = node->getChild("from-flag", 0, true); + SGPropertyNode* fromFlag = _gpsNode->getChild("from-flag", 0, true); fromFlag->alias(wp1_node->getChild("from-flag")); - // autopilot drive properties _apTrueHeading = fgGetNode("/autopilot/settings/true-heading-deg",true); _apTargetAltitudeFt = fgGetNode("/autopilot/settings/target-altitude-ft", true); @@ -455,11 +360,101 @@ GPS::init () } // last thing, add the deprecated prop watcher - new DeprecatedPropListener(node); + new DeprecatedPropListener(_gpsNode); clearOutput(); } +void +GPS::bind() +{ + _config.bind(this, _gpsNode->getChild("config", 0, true)); +// basic GPS outputs + tie(_gpsNode, "selected-course-deg", SGRawValueMethods + (*this, &GPS::getSelectedCourse, NULL)); + + + tieSGGeodReadOnly(_gpsNode, _indicated_pos, "indicated-longitude-deg", + "indicated-latitude-deg", "indicated-altitude-ft"); + + tie(_gpsNode, "indicated-vertical-speed", SGRawValueMethods + (*this, &GPS::getVerticalSpeed, NULL)); + tie(_gpsNode, "indicated-track-true-deg", SGRawValueMethods + (*this, &GPS::getTrueTrack, NULL)); + tie(_gpsNode, "indicated-track-magnetic-deg", SGRawValueMethods + (*this, &GPS::getMagTrack, NULL)); + tie(_gpsNode, "indicated-ground-speed-kt", SGRawValueMethods + (*this, &GPS::getGroundspeedKts, NULL)); + +// command system + tie(_gpsNode, "mode", SGRawValueMethods(*this, &GPS::getMode, NULL)); + tie(_gpsNode, "command", SGRawValueMethods(*this, &GPS::getCommand, &GPS::setCommand)); + + tieSGGeod(_scratchNode, _scratchPos, "longitude-deg", "latitude-deg", "altitude-ft"); + tie(_scratchNode, "valid", SGRawValueMethods(*this, &GPS::getScratchValid, NULL)); + tie(_scratchNode, "distance-nm", SGRawValueMethods(*this, &GPS::getScratchDistance, NULL)); + tie(_scratchNode, "true-bearing-deg", SGRawValueMethods(*this, &GPS::getScratchTrueBearing, NULL)); + tie(_scratchNode, "mag-bearing-deg", SGRawValueMethods(*this, &GPS::getScratchMagBearing, NULL)); + tie(_scratchNode, "has-next", SGRawValueMethods(*this, &GPS::getScratchHasNext, NULL)); + _scratchValid = false; + +// waypoint data (including various historical things) + SGPropertyNode *wp_node = _gpsNode->getChild("wp", 0, true); + SGPropertyNode *wp0_node = wp_node->getChild("wp", 0, true); + SGPropertyNode *wp1_node = wp_node->getChild("wp", 1, true); + + tieSGGeodReadOnly(wp0_node, _wp0_position, "longitude-deg", "latitude-deg", "altitude-ft"); + tie(wp0_node, "ID", SGRawValueMethods + (*this, &GPS::getWP0Ident, NULL)); + tie(wp0_node, "name", SGRawValueMethods + (*this, &GPS::getWP0Name, NULL)); + + tieSGGeodReadOnly(wp1_node, _wp1_position, "longitude-deg", "latitude-deg", "altitude-ft"); + tie(wp1_node, "ID", SGRawValueMethods + (*this, &GPS::getWP1Ident, NULL)); + tie(wp1_node, "name", SGRawValueMethods + (*this, &GPS::getWP1Name, NULL)); + + tie(wp1_node, "distance-nm", SGRawValueMethods + (*this, &GPS::getWP1Distance, NULL)); + tie(wp1_node, "bearing-true-deg", SGRawValueMethods + (*this, &GPS::getWP1Bearing, NULL)); + tie(wp1_node, "bearing-mag-deg", SGRawValueMethods + (*this, &GPS::getWP1MagBearing, NULL)); + tie(wp1_node, "TTW-sec", SGRawValueMethods + (*this, &GPS::getWP1TTW, NULL)); + tie(wp1_node, "TTW", SGRawValueMethods + (*this, &GPS::getWP1TTWString, NULL)); + + tie(wp1_node, "course-deviation-deg", SGRawValueMethods + (*this, &GPS::getWP1CourseDeviation, NULL)); + tie(wp1_node, "course-error-nm", SGRawValueMethods + (*this, &GPS::getWP1CourseErrorNm, NULL)); + tie(wp1_node, "to-flag", SGRawValueMethods + (*this, &GPS::getWP1ToFlag, NULL)); + tie(wp1_node, "from-flag", SGRawValueMethods + (*this, &GPS::getWP1FromFlag, NULL)); + +// leg properties (only valid in DTO/LEG modes, not OBS) + tie(wp_node, "leg-distance-nm", SGRawValueMethods(*this, &GPS::getLegDistance, NULL)); + tie(wp_node, "leg-true-course-deg", SGRawValueMethods(*this, &GPS::getLegCourse, NULL)); + tie(wp_node, "leg-mag-course-deg", SGRawValueMethods(*this, &GPS::getLegMagCourse, NULL)); + tie(wp_node, "alt-dist-ratio", SGRawValueMethods(*this, &GPS::getAltDistanceRatio, NULL)); + +// navradio slaving properties + tie(_gpsNode, "cdi-deflection", SGRawValueMethods + (*this, &GPS::getCDIDeflection)); +} + +void +GPS::unbind() +{ + for (unsigned int t=0; t<_tiedNodes.size(); ++t) { + _tiedNodes[t]->untie(); + } + _tiedNodes.clear(); +} + void GPS::clearOutput() { @@ -1768,4 +1763,26 @@ void GPS::removeWaypointAtIndex(int aIndex) _routeMgr->pop_waypoint(aIndex); } +void GPS::tieSGGeod(SGPropertyNode* aNode, SGGeod& aRef, + const char* lonStr, const char* latStr, const char* altStr) +{ + tie(aNode, lonStr, SGRawValueMethods(aRef, &SGGeod::getLongitudeDeg, &SGGeod::setLongitudeDeg)); + tie(aNode, latStr, SGRawValueMethods(aRef, &SGGeod::getLatitudeDeg, &SGGeod::setLatitudeDeg)); + + if (altStr) { + tie(aNode, altStr, SGRawValueMethods(aRef, &SGGeod::getElevationFt, &SGGeod::setElevationFt)); + } +} + +void GPS::tieSGGeodReadOnly(SGPropertyNode* aNode, SGGeod& aRef, + const char* lonStr, const char* latStr, const char* altStr) +{ + tie(aNode, lonStr, SGRawValueMethods(aRef, &SGGeod::getLongitudeDeg, NULL)); + tie(aNode, latStr, SGRawValueMethods(aRef, &SGGeod::getLatitudeDeg, NULL)); + + if (altStr) { + tie(aNode, altStr, SGRawValueMethods(aRef, &SGGeod::getElevationFt, NULL)); + } +} + // end of gps.cxx diff --git a/src/Instrumentation/gps.hxx b/src/Instrumentation/gps.hxx index e745418d6..76596773a 100644 --- a/src/Instrumentation/gps.hxx +++ b/src/Instrumentation/gps.hxx @@ -82,7 +82,9 @@ public: virtual void init (); virtual void update (double delta_time_sec); - + + virtual void bind(); + virtual void unbind(); private: friend class GPSListener; friend class SearchFilter; @@ -94,8 +96,8 @@ private: { public: Config(); - - void init(SGPropertyNode*); + + void bind(GPS* aOwner, SGPropertyNode* aCfg); bool turnAnticipationEnabled() const { return _enableTurnAnticipation; } @@ -307,9 +309,28 @@ private: // 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) + { + 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 _magvar_node; SGPropertyNode_ptr _serviceable_node; SGPropertyNode_ptr _electrical_node; @@ -397,6 +418,8 @@ private: SGPropertyNode_ptr _apTrueHeading; SGPropertyNode_ptr _apTargetAltitudeFt; SGPropertyNode_ptr _apAltitudeLock; + + std::vector _tiedNodes; };