1
0
Fork 0

Fix: Systems that have mcbf triggers by default (flaps, gear & speedbrake) fail when first operated. from galvedros

This commit is contained in:
Hyde Yamakawa 2015-02-28 18:15:04 -05:00
parent 3fbb25cde6
commit 15c6160c05

View file

@ -31,16 +31,16 @@
var set_unserviceable = func(path) { var set_unserviceable = func(path) {
var prop = path ~ "/serviceable"; var prop = path ~ "/serviceable";
if (props.globals.getNode(prop) == nil) if (props.globals.getNode(prop) == nil)
props.globals.initNode(prop, 1, "BOOL"); props.globals.initNode(prop, 1, "BOOL");
return { return {
parents: [FailureMgr.FailureActuator], parents: [FailureMgr.FailureActuator],
set_failure_level: func(level) setprop(prop, level > 0 ? 0 : 1), set_failure_level: func(level) setprop(prop, level > 0 ? 0 : 1),
get_failure_level: func { getprop(prop) ? 0 : 1 } get_failure_level: func { getprop(prop) ? 0 : 1 }
} }
} }
## ##
@ -49,19 +49,19 @@ var set_unserviceable = func(path) {
# whatever it is that is controlling. # whatever it is that is controlling.
var set_readonly = func(property) { var set_readonly = func(property) {
return { return {
parents: [FailureMgr.FailureActuator], parents: [FailureMgr.FailureActuator],
set_failure_level: func(level) { set_failure_level: func(level) {
var pnode = props.globals.getNode(property); var pnode = props.globals.getNode(property);
pnode.setAttribute("writable", level > 0 ? 0 : 1); pnode.setAttribute("writable", level > 0 ? 0 : 1);
}, },
get_failure_level: func { get_failure_level: func {
var pnode = props.globals.getNode(property); var pnode = props.globals.getNode(property);
pnode.getAttribute("writable") ? 0 : 1; pnode.getAttribute("writable") ? 0 : 1;
} }
} }
} }
## ##
@ -70,32 +70,32 @@ var set_readonly = func(property) {
# while the system is failed. # while the system is failed.
var fail_engine = func(engine) { var fail_engine = func(engine) {
return { return {
parents: [FailureMgr.FailureActuator], parents: [FailureMgr.FailureActuator],
level: 0, level: 0,
magnetos: props.globals.getNode("/controls/engines/" ~ engine ~ "/magnetos", 1), magnetos: props.globals.getNode("/controls/engines/" ~ engine ~ "/magnetos", 1),
cutoff: props.globals.getNode("/controls/engines/" ~ engine ~ "/cutoff", 1), cutoff: props.globals.getNode("/controls/engines/" ~ engine ~ "/cutoff", 1),
get_failure_level: func me.level, get_failure_level: func me.level,
set_failure_level: func(level) { set_failure_level: func(level) {
if (level) { if (level) {
# Switch off the engine, and disable writing to it. # Switch off the engine, and disable writing to it.
me.magnetos.setValue(0); me.magnetos.setValue(0);
me.magnetos.setAttribute("writable", 0); me.magnetos.setAttribute("writable", 0);
me.cutoff.setValue(1); me.cutoff.setValue(1);
me.cutoff.setAttribute("writable", 0); me.cutoff.setAttribute("writable", 0);
} }
else { else {
# Enable the properties, but don't set the magnetos, as they may # Enable the properties, but don't set the magnetos, as they may
# be off for a reason. # be off for a reason.
me.magnetos.setAttribute("writable", 1); me.magnetos.setAttribute("writable", 1);
me.cutoff.setAttribute("writable", 1); me.cutoff.setAttribute("writable", 1);
me.cutoff.setValue(0); me.cutoff.setValue(0);
} }
me.level = level; me.level = level;
} }
} }
} }
@ -108,9 +108,9 @@ var fail_engine = func(engine) {
# standard deviation. # standard deviation.
var norm_rand = func(mean, std) { var norm_rand = func(mean, std) {
var r = -2 * math.ln(1 - rand()); var r = -2 * math.ln(1 - rand());
var a = 2 * math.pi * (1 - rand()); var a = 2 * math.pi * (1 - rand());
return mean + (math.sqrt(r) * math.sin(a) * std); return mean + (math.sqrt(r) * math.sin(a) * std);
}; };
## ##
@ -120,40 +120,40 @@ var norm_rand = func(mean, std) {
var AltitudeTrigger = { var AltitudeTrigger = {
parents: [FailureMgr.Trigger], parents: [FailureMgr.Trigger],
type: "altitude", type: "altitude",
requires_polling: 1, requires_polling: 1,
new: func(min, max) { new: func(min, max) {
min != nil or max != nil or min != nil or max != nil or
die("AltitudeTrigger.new: either min or max must be specified"); die("AltitudeTrigger.new: either min or max must be specified");
var m = FailureMgr.Trigger.new(); var m = FailureMgr.Trigger.new();
m.parents = [AltitudeTrigger]; m.parents = [AltitudeTrigger];
m.params["min-altitude-ft"] = min; m.params["min-altitude-ft"] = min;
m.params["max-altitude-ft"] = max; m.params["max-altitude-ft"] = max;
m._altitude_prop = "/position/altitude-ft"; m._altitude_prop = "/position/altitude-ft";
return m; return m;
}, },
to_str: func { to_str: func {
var min = me.params["min-altitude-ft"]; var min = me.params["min-altitude-ft"];
var max = me.params["max-altitude-ft"]; var max = me.params["max-altitude-ft"];
if (min == nil) sprintf("Altitude below %d ft", int(max)); if (min == nil) sprintf("Altitude below %d ft", int(max));
elsif (max == nil) sprintf("Altitude above %d ft", int(min)); elsif (max == nil) sprintf("Altitude above %d ft", int(min));
else sprintf("Altitude between %d and %d ft", int(min), int(max)); else sprintf("Altitude between %d and %d ft", int(min), int(max));
}, },
update: func { update: func {
var alt = getprop(me._altitude_prop); var alt = getprop(me._altitude_prop);
var min = me.params["min-altitude-ft"]; var min = me.params["min-altitude-ft"];
var max = me.params["max-altitude-ft"]; var max = me.params["max-altitude-ft"];
me.fired = min != nil ? min < alt : 1; me.fired = min != nil ? min < alt : 1;
me.fired = max != nil ? me.fired and alt < max : me.fired; me.fired = max != nil ? me.fired and alt < max : me.fired;
} }
}; };
## ##
@ -162,38 +162,38 @@ var AltitudeTrigger = {
var WaypointTrigger = { var WaypointTrigger = {
parents: [FailureMgr.Trigger], parents: [FailureMgr.Trigger],
type: "waypoint", type: "waypoint",
requires_polling: 1, requires_polling: 1,
new: func(lat, lon, distance) { new: func(lat, lon, distance) {
var wp = geo.Coord.new(); var wp = geo.Coord.new();
wp.set_latlon(lat, lon); wp.set_latlon(lat, lon);
var m = FailureMgr.Trigger.new(); var m = FailureMgr.Trigger.new();
m.parents = [WaypointTrigger]; m.parents = [WaypointTrigger];
m.params["latitude-deg"] = lat; m.params["latitude-deg"] = lat;
m.params["longitude-deg"] = lon; m.params["longitude-deg"] = lon;
m.params["distance-nm"] = distance; m.params["distance-nm"] = distance;
m.waypoint = wp; m.waypoint = wp;
return m; return m;
}, },
arm: func { arm: func {
call(FailureMgr.Trigger.arm, [], me); call(FailureMgr.Trigger.arm, [], me);
me.waypoint.set_latlon(me.params["latitude-deg"], me.waypoint.set_latlon(me.params["latitude-deg"],
me.params["longitude-deg"]); me.params["longitude-deg"]);
}, },
to_str: func { to_str: func {
sprintf("Within %.2f miles of %s", me.params["distance-nm"], sprintf("Within %.2f miles of %s", me.params["distance-nm"],
geo.format(me.waypoint.lat(), me.waypoint.lon())); geo.format(me.waypoint.lat(), me.waypoint.lon()));
}, },
update: func { update: func {
var d = geo.aircraft_position().distance_to(me.waypoint) * M2NM; var d = geo.aircraft_position().distance_to(me.waypoint) * M2NM;
me.fired = d < me.params["distance-nm"]; me.fired = d < me.params["distance-nm"];
} }
}; };
## ##
@ -201,47 +201,47 @@ var WaypointTrigger = {
var MtbfTrigger = { var MtbfTrigger = {
parents: [FailureMgr.Trigger], parents: [FailureMgr.Trigger],
type: "mtbf", type: "mtbf",
requires_polling: 0, requires_polling: 0,
new: func(mtbf) { new: func(mtbf) {
var m = FailureMgr.Trigger.new(); var m = FailureMgr.Trigger.new();
m.parents = [MtbfTrigger]; m.parents = [MtbfTrigger];
m.params["mtbf"] = mtbf; m.params["mtbf"] = mtbf;
m.timer = maketimer(0, func m.on_fire()); m.timer = maketimer(0, func m.on_fire());
m.timer.singleShot = 1; m.timer.singleShot = 1;
return m; return m;
}, },
enable: func { enable: func {
me.armed and me.timer.start(); me.armed and me.timer.start();
me.enabled = 1; me.enabled = 1;
}, },
disable: func { disable: func {
me.timer.stop(); me.timer.stop();
me.enabled = 0; me.enabled = 0;
}, },
arm: func { arm: func {
call(FailureMgr.Trigger.arm, [], me); call(FailureMgr.Trigger.arm, [], me);
me.timer.restart(norm_rand(me.params["mtbf"], me.params["mtbf"] / 10)); me.timer.restart(norm_rand(me.params["mtbf"], me.params["mtbf"] / 10));
me.enabled and me.timer.start(); me.enabled and me.timer.start();
}, },
disarm: func { disarm: func {
call(FailureMgr.Trigger.disarm, [], me); call(FailureMgr.Trigger.disarm, [], me);
me.timer.stop(); me.timer.stop();
}, },
to_str: func { to_str: func {
sprintf("Mean time between failures: %.1f mins", me.params["mtbf"] / 60); sprintf("Mean time between failures: %.1f mins", me.params["mtbf"] / 60);
}, },
update: func { update: func {
me.fired = getprop(me._time_prop) > me.fire_time; me.fired = getprop(me._time_prop) > me.fire_time;
} }
}; };
## ##
@ -249,47 +249,47 @@ var MtbfTrigger = {
var TimeoutTrigger = { var TimeoutTrigger = {
parents: [FailureMgr.Trigger], parents: [FailureMgr.Trigger],
type: "timeout", type: "timeout",
requires_polling: 0, requires_polling: 0,
new: func(timeout) { new: func(timeout) {
var m = FailureMgr.Trigger.new(); var m = FailureMgr.Trigger.new();
m.parents = [TimeoutTrigger]; m.parents = [TimeoutTrigger];
m.params["timeout-sec"] = timeout; m.params["timeout-sec"] = timeout;
m.timer = maketimer(0, func m.on_fire()); m.timer = maketimer(0, func m.on_fire());
m.timer.singleShot = 1; m.timer.singleShot = 1;
return m; return m;
}, },
enable: func { enable: func {
me.armed and me.timer.start(); me.armed and me.timer.start();
me.enabled = 1; me.enabled = 1;
}, },
disable: func { disable: func {
me.timer.stop(); me.timer.stop();
me.enabled = 0; me.enabled = 0;
}, },
arm: func { arm: func {
call(FailureMgr.Trigger.arm, [], me); call(FailureMgr.Trigger.arm, [], me);
me.timer.restart(me.params["timeout-sec"]); me.timer.restart(me.params["timeout-sec"]);
me.enabled and me.timer.start(); me.enabled and me.timer.start();
}, },
disarm: func { disarm: func {
call(FailureMgr.Trigger.disarm, [], me); call(FailureMgr.Trigger.disarm, [], me);
me.timer.stop(); me.timer.stop();
}, },
to_str: func { to_str: func {
sprintf("Fixed delay: %d minutes", me.params["timeout-sec"] / 60); sprintf("Fixed delay: %d minutes", me.params["timeout-sec"] / 60);
}, },
update: func { update: func {
me.fired = getprop("/sim/time/elapsed-sec") > me.fire_time; me.fired = getprop("/sim/time/elapsed-sec") > me.fire_time;
} }
}; };
## ##
@ -300,53 +300,53 @@ var TimeoutTrigger = {
var CycleCounter = { var CycleCounter = {
new: func(property, on_update = nil) { new: func(property, on_update = nil) {
return { return {
parents: [CycleCounter], parents: [CycleCounter],
cycles: 0, cycles: 0,
_property: property, _property: property,
_on_update: on_update, _on_update: on_update,
_prev_value: getprop(property), _prev_value: getprop(property),
_prev_delta: 0, _prev_delta: 0,
_lsnr: nil _lsnr: nil
}; };
}, },
enable: func { enable: func {
if (me._lsnr == nil) if (me._lsnr == nil)
me._lsnr = setlistener(me._property, func (p) me._on_prop_change(p), 0, 0); me._lsnr = setlistener(me._property, func (p) me._on_prop_change(p), 0, 0);
}, },
disable: func { disable: func {
if (me._lsnr != nil) { if (me._lsnr != nil) {
removelistener(me._lsnr); removelistener(me._lsnr);
me._lsnr = nil; me._lsnr = nil;
} }
}, },
reset: func { reset: func {
me.cycles = 0; me.cycles = 0;
me._prev_value = getprop(me._property); me._prev_value = getprop(me._property);
me._prev_delta = 0; me._prev_delta = 0;
}, },
_on_prop_change: func(prop) { _on_prop_change: func(prop) {
# TODO: Implement a filter for avoiding spureous values. # TODO: Implement a filter for avoiding spureous values.
var value = prop.getValue(); var value = prop.getValue();
var delta = value - me._prev_value; var delta = value - me._prev_value;
if (delta == 0) return; if (delta == 0) return;
if (delta * me._prev_delta < 0) { if (delta * me._prev_delta < 0) {
# Property variation has changed direction # Property variation has changed direction
me.cycles += 0.5; me.cycles += 0.5;
if (me._on_update != nil) me._on_update(me.cycles); if (me._on_update != nil) me._on_update(me.cycles);
} }
me._prev_delta = delta; me._prev_delta = delta;
me._prev_value = value; me._prev_value = value;
} }
}; };
## ##
@ -355,51 +355,51 @@ var CycleCounter = {
var McbfTrigger = { var McbfTrigger = {
parents: [FailureMgr.Trigger], parents: [FailureMgr.Trigger],
type: "mcbf", type: "mcbf",
requires_polling: 0, requires_polling: 0,
new: func(property, mcbf) { new: func(property, mcbf) {
var m = FailureMgr.Trigger.new(); var m = FailureMgr.Trigger.new();
m.parents = [McbfTrigger]; m.parents = [McbfTrigger];
m.params["mcbf"] = mcbf; m.params["mcbf"] = mcbf;
m.counter = CycleCounter.new(property, func(c) call(m._on_cycle, [c], m)); m.counter = CycleCounter.new(property, func(c) call(m._on_cycle, [c], m));
m.activation_cycles = 0; m.activation_cycles = 0;
return m; return m;
}, },
enable: func { enable: func {
me.counter.enable(); me.armed and me.counter.enable();
me.enabled = 1; me.enabled = 1;
}, },
disable: func { disable: func {
me.counter.disable(); me.counter.disable();
me.enabled = 0; me.enabled = 0;
}, },
arm: func { arm: func {
call(FailureMgr.Trigger.arm, [], me); call(FailureMgr.Trigger.arm, [], me);
me.counter.reset(); me.counter.reset();
me.activation_cycles = me.activation_cycles =
norm_rand(me.params["mcbf"], me.params["mcbf"] / 10); norm_rand(me.params["mcbf"], me.params["mcbf"] / 10);
me.enabled and me.counter.enable(); me.enabled and me.counter.enable();
}, },
disarm: func { disarm: func {
call(FailureMgr.Trigger.disarm, [], me); call(FailureMgr.Trigger.disarm, [], me);
me.enabled and me.counter.disable(); me.counter.disable();
}, },
to_str: func { to_str: func {
sprintf("Mean cycles between failures: %.2f", me.params["mcbf"]); sprintf("Mean cycles between failures: %.2f", me.params["mcbf"]);
}, },
_on_cycle: func(cycles) { _on_cycle: func(cycles) {
if (!me.fired and cycles > me.activation_cycles) { if (!me.fired and cycles > me.activation_cycles) {
me.fired = 1; me.fired = 1;
me.on_fire(); me.on_fire();
} }
} }
}; };