X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FAutopilot%2Fautobrake.cxx;h=ec1fcfc0e1aa67e55ddbf8caddbb3df0328d3784;hb=be13f1f3aced11ce844204b6a0c97365a3e069ca;hp=a43841ee74d59191af27974143b9b1fa883355d2;hpb=4d67c69462c457938562d8769931678688aeaa5d;p=flightgear.git diff --git a/src/Autopilot/autobrake.cxx b/src/Autopilot/autobrake.cxx index a43841ee7..ec1fcfc0e 100644 --- a/src/Autopilot/autobrake.cxx +++ b/src/Autopilot/autobrake.cxx @@ -39,6 +39,7 @@ FGAutoBrake::FGAutoBrake() : // default config, close to Boeing 747-400 / 777 values _configNumSteps = 4; _configRTOStep = -1; + _configDisengageStep = 0; _configMaxDecel = 11; // ft-sec-sec _configRTODecel = 11; // ft-sec-sec _configRTOSpeed = 85; // kts @@ -62,7 +63,6 @@ void FGAutoBrake::init() (*this, &FGAutoBrake::getRTO, &FGAutoBrake::setRTO)); _engineControlsNode = fgGetNode("/controls/engines"); - _groundspeedNode = fgGetNode("/velocities/groundspeed-kt"); // brake position nodes _brakeInputs[0] = fgGetNode("/controls/gear/brake-left"); @@ -74,10 +74,12 @@ void FGAutoBrake::init() SGPropertyNode_ptr config = _root->getChild("config", 0, true); config->tie("num-steps", SGRawValuePointer(&_configNumSteps)); config->tie("rto-step", SGRawValuePointer(&_configRTOStep)); + config->tie("disengage-step", SGRawValuePointer(&_configDisengageStep)); config->tie("rto-decel-fts-sec", SGRawValuePointer(&_configRTODecel)); config->tie("max-decel-fts-sec", SGRawValuePointer(&_configMaxDecel)); config->tie("rto-engage-kts", SGRawValuePointer(&_configRTOSpeed)); + // outputs _root->tie("target-decel-fts-sec", SGRawValueMethods(*this, &FGAutoBrake::getTargetDecel)); @@ -93,6 +95,11 @@ void FGAutoBrake::init() void FGAutoBrake::postinit() { _weightOnWheelsNode = fgGetNode("/gear/gear/wow"); + _groundspeedNode = fgGetNode("/velocities/groundspeed-kt"); + if (!_weightOnWheelsNode) { + return; // don't crash if we're using an acft (UFO, ATC, with no WoW flag) + } + _lastWoW = _weightOnWheelsNode->getBoolValue(); } @@ -107,6 +114,20 @@ void FGAutoBrake::unbind() void FGAutoBrake::update(double dt) { + _leftBrakeInput = SGMiscd::max(_brakeInputs[0]->getDoubleValue(), + _brakeInputs[2]->getDoubleValue()); + _rightBrakeInput = SGMiscd::max(_brakeInputs[1]->getDoubleValue(), + _brakeInputs[3]->getDoubleValue()); + + // various FDMs don't supply sufficent information for us to work, + // so just be passive in those cases. + if (!_weightOnWheelsNode || !_groundspeedNode || !_engineControlsNode) { + // pass the values straight through + _leftBrakeOutput = _leftBrakeInput; + _rightBrakeOutput = _rightBrakeInput; + return; + } + if (dt <= 0.0) { return; // paused } @@ -115,11 +136,6 @@ void FGAutoBrake::update(double dt) _actualDecel = (_lastGroundspeedKts - gs) / dt; _lastGroundspeedKts = gs; - _leftBrakeInput = SGMiscd::max(_brakeInputs[0]->getDoubleValue(), - _brakeInputs[2]->getDoubleValue()); - _rightBrakeInput = SGMiscd::max(_brakeInputs[1]->getDoubleValue(), - _brakeInputs[3]->getDoubleValue()); - if (!_armed || (_step == 0)) { // even if we're off or disarmed, the physical valve system must pass // pilot control values through. @@ -161,6 +177,12 @@ void FGAutoBrake::updateEngaged(double dt) return; } + if (!throttlesAtIdle()) { + SG_LOG(SG_AUTOPILOT, SG_INFO, "auto-brake, throttles not at idle, disengaing"); + disengage(); + return; + } + // update the target deceleration; note step can be changed while engaged if (_rto) { _targetDecel = _configRTODecel; @@ -180,6 +202,11 @@ bool FGAutoBrake::shouldEngage() return false; } + + if (!throttlesAtIdle()) { + return false; + } + SG_LOG(SG_AUTOPILOT, SG_INFO, "Autobrake, should enage"); return true; } @@ -196,10 +223,22 @@ bool FGAutoBrake::shouldEngageRTO() } if (!_weightOnWheelsNode->getBoolValue()) { + if (airborne()) { + SG_LOG(SG_AUTOPILOT, SG_INFO, "FGAutoBrake: RTO, airbone, disengaging"); + _rtoArmed = false; + _armed = false; + _step = _configDisengageStep; + } + return false; } - return throttlesAtIdle(); + if (throttlesAtIdle()) { + SG_LOG(SG_AUTOPILOT, SG_INFO, "FGAutoBrake: RTO, throttles at idle, will engage"); + return true; + } else { + return false; + } } else { // RTO arming case if (speed > _configRTOSpeed) { @@ -219,12 +258,19 @@ void FGAutoBrake::disengage() SG_LOG(SG_AUTOPILOT, SG_INFO, "FGAutoBrake: disengage"); _engaged = false; + _fcsBrakeControl = 0.0; _armed = false; _rtoArmed = false; _targetDecel = 0.0; + _step = _configDisengageStep; } -bool FGAutoBrake::throttlesAtIdle() +bool FGAutoBrake::airborne() const +{ + return !_weightOnWheelsNode->getBoolValue(); +} + +bool FGAutoBrake::throttlesAtIdle() const { SGPropertyNode_ptr e; const double IDLE_THROTTLE = 0.05; // 5% margin for idle setting @@ -235,7 +281,6 @@ bool FGAutoBrake::throttlesAtIdle() } } // of engines iteration - SG_LOG(SG_AUTOPILOT, SG_INFO, "FGAutoBrake: throttles at idle"); return true; } @@ -254,7 +299,16 @@ void FGAutoBrake::setRTO(bool aRTO) if (aRTO) { // ensure we meet RTO selection criteria: if (!_weightOnWheelsNode->getBoolValue()) { - SG_LOG(SG_AUTOPILOT, SG_WARN, "auto-brake: cannot select RTO mode, no weight on wheels"); + // some systems combine RTO with a standard step, selecting RTO if on + // the ground. Handle that case by setting _rto = false, and letting + // setStep() do the rest of the work as normal. + if ((_configRTOStep > 0) && (_configRTOStep <= _configNumSteps)) { + // RTO is combined with a normal step, select that + } else { + SG_LOG(SG_AUTOPILOT, SG_WARN, "auto-brake: cannot select RTO mode, no weight on wheels"); + } + + _rto = false; return; }