1
0
Fork 0

Failure manager. Based on work by Erobo and John DENKER.

This commit is contained in:
stuart 2009-02-12 20:24:06 +00:00
parent 824cff9192
commit a0a493b8ce
5 changed files with 1358 additions and 230 deletions

250
Nasal/failures.nas Normal file
View file

@ -0,0 +1,250 @@
# failures.nas a manager for failing systems based on MTBF/MCBF
# Time between MTBF checks
var dt = 10;
# Root property for failure information
var failure_root = "/sim/failure-manager";
# Enumerations
var type = { MTBF : 1, MCBF: 2 };
var fail = { SERVICEABLE : 1, JAM : 2, ENGINE: 3};
# This hash contains a mapping from property entry to a failure object
# containing the following members:
# type: MTBF|MCBF Mean Time Between Failures/Mean Cycle Between Failures
# desc: <description> Description of property for screen output
# failure: SERVICEABLE Property has a "serviceable" child that can be set to false
# failure: JAM Property is failed by marking as Read-Only
# failure: ENGINE Special case for engines, where a variety of properties are set.
# failure: <prop> Property is failed by setting another property to false
var breakHash = {
"/instrumentation/adf" : { type: type.MTBF, failure: fail.SERVICEABLE, desc: "ADF" },
"/instrumentation/dme" : { type: type.MTBF, failure: fail.SERVICEABLE, desc: "DME" },
"/instrumentation/airspeed-indicator" : { type: type.MTBF, failure: fail.SERVICEABLE, desc: "ASI" },
"/instrumentation/altimeter" : { type: type.MTBF, failure: fail.SERVICEABLE, desc: "Altimeter" },
"/instrumentation/attitude-indicator" : { type: type.MTBF, failure: fail.SERVICEABLE, desc: "Attitude Indicator" },
"/instrumentation/heading-indicator" : { type: type.MTBF, failure: fail.SERVICEABLE, desc: "Heading Indicator" },
"/instrumentation/magnetic-compass" : { type: type.MTBF, failure: fail.SERVICEABLE, desc: "Magnetic Compass" },
"/instrumentation/nav[0]/gs" : { type: type.MTBF, failure: fail.SERVICEABLE, desc: "Nav 1 Glideslope" },
"/instrumentation/nav[0]/cdi" : { type: type.MTBF, failure: fail.SERVICEABLE, desc: "Nav 1 CDI" },
"/instrumentation/nav[1]/gs" : { type: type.MTBF, failure: fail.SERVICEABLE, desc: "Nav 2 Glideslope" },
"/instrumentation/nav[1]/cdi" : { type: type.MTBF, failure: fail.SERVICEABLE, desc: "Nav 2 CDI" },
"/instrumentation/slip-skid-ball" : { type: type.MTBF, failure: fail.SERVICEABLE, desc: "Slip/Skid Ball" },
"/instrumentation/turn-indicator" : { type: type.MTBF, failure: fail.SERVICEABLE, desc: "Turn Indicator" },
"/instrumentation/vertical-speed-indicator" : { type: type.MTBF, failure: fail.SERVICEABLE, desc: "VSI" },
"/systems/electrical" : { type: type.MTBF, failure: fail.SERVICEABLE, desc: "Electrical system" },
"/systems/pitot" : { type: type.MTBF, failure: fail.SERVICEABLE, desc: "Pitot system" },
"/systems/static" : { type: type.MTBF, failure: fail.SERVICEABLE, desc: "Static system" },
"/systems/vacuum" : { type: type.MTBF, failure: fail.SERVICEABLE, desc: "Vacuum system" },
"/controls/gear/gear-down" : { type: type.MCBF, failure: "/gear/serviceable", desc: "Gear" },
"/controls/flight/aileron" : { type: type.MTBF, failure: fail.JAM, desc: "Aileron" },
"/controls/flight/elevator" : { type: type.MTBF, failure: fail.JAM, desc: "Elevator" },
"/controls/flight/rudder" : { type: type.MTBF, failure: fail.JAM, desc: "Rudder" },
"/controls/flight/flaps" : { type: type.MCBF, failure: fail.JAM, desc: "Flaps" },
"/controls/flight/speedbrake" : { type: type.MCBF, failure: fail.JAM, desc: "Speed Brake" }
};
# Set a given serviceable property to 1.
var set1 = func(prop) {
n = props.globals.getNode(prop, 1);
if (n.getValue() == nil) {
n.setBoolValue(1);
}
if (n.getType() == "UNSPECIFIED") {
n.setBoolValue(n.getValue());
}
}
# Return the failure entry for a given property
var getFailure = func (prop) {
var o = breakHash[prop];
if (o.failure == fail.SERVICEABLE) {
return prop ~ "/serviceable";
} elsif (o.failure == fail.ENGINE) {
return failure_root ~ prop ~ "/serviceable";
} elsif (o.failure == fail.JAM) {
return failure_root ~ prop ~ "/serviceable";
} else {
return o.failure;
}
}
# Fail a given property, either using a serviceable flag, or by jamming the property
var failProp = func(prop) {
var o = breakHash[prop];
var p = getFailure(prop);
if (getprop(p) == 1) {
setprop(p, 0);
# We always print to the console
print(getprop("/sim/time/gmt-string") ~ " : " ~ o.desc ~ " failed");
if (getprop(failure_root ~ "/display-on-screen")) {
# Display message to the screen in red
screen.log.write(o.desc ~ " failed", 1.0, 0.0, 0.0);
}
}
}
# Unfail a given property, used for resetting a failure state.
var unfailProp = func(prop)
{
var p = getFailure(prop);
setprop(p, 1);
}
# Unfail all the failed properties
var unfail = func {
foreach(var prop; keys(breakHash)) {
unfailProp(prop);
}
}
# Listener to jam a property. Note that the property to jam is
# encoded within the property name
var jamListener = func(p) {
var jamprop = string.replace(p.getParent().getPath(), failure_root, "");
#jamprop = string.replace(jamprop, "/serviceable", "");
var prop = props.globals.getNode(jamprop);
if (p.getValue()) {
prop.setAttribute("writable", 1);
} else {
prop.setAttribute("writable", 0);
}
}
# Listener for an engine property. Note that the engine to set is
# encoded within the property name. We set both the magnetos and
# cutoff to handle different engine models.
var engineListener = func(p) {
var e = string.replace(p.getParent().getPath(), failure_root, "");
var prop = props.globals.getNode(e);
if (p.getValue()) {
# Enable the properties, but don't set the magnetos, as they may
# be off for a reason.
var magnetos = props.globals.getNode("/controls/" ~ e ~ "/magnetos", 1);
var cutoff = props.globals.getNode("/controls/" ~ e ~ "/cutoff", 1);
magnetos.setAttribute("writable", 1);
cutoff.setAttribute("writable", 1);
cutoff.setValue(0);
} else {
# Switch off the engine, and disable writing to it.
var magnetos = props.globals.getNode("/controls/" ~ e ~ "/magnetos", 1);
var cutoff = props.globals.getNode("/controls/" ~ e ~ "/cutoff", 1);
magnetos.setValue(0);
cutoff.setValue(1);
magnetos.setAttribute("writable", 0);
cutoff.setAttribute("writable", 0);
}
}
# Perform a MCBF check against a failure property.
var checkMCBF = func(prop) {
var mcbf = getprop(failure_root ~ prop.getPath() ~ "/mcbf");
# mcbf == mean cycles between failures
# hence 2*mcbf is the number of _half-cycles_ between failures,
# which is relevant because we do this check on each half-cycle:
if ((mcbf > 0) and !int(2 * mcbf * rand())) {
# Get the property information.
failProp(prop.getPath());
}
}
# Timer based loop to check MTBF properties
var checkMTBF = func {
foreach(var prop; keys(breakHash)) {
var o = breakHash[prop];
if (o.type == type.MTBF) {
var mtbf = getprop(failure_root ~ prop ~ "/mtbf");
if (mtbf and !int(rand() * mtbf / dt)) {
failProp(prop);
}
}
}
settimer(checkMTBF, dt);
}
# Function to set all MTBF failures to a give value. Mainly for testing.
var setAllMTBF = func(mtbf) {
foreach(var prop; keys(breakHash)) {
var o = breakHash[prop];
if (o.type == type.MTBF) {
setprop(failure_root ~ prop ~ "/mtbf", mtbf);
}
}
}
# Function to set all MCBF failures to a give value. Mainly for testing.
var setAllMCBF = func(mcbf) {
foreach(var prop; keys(breakHash)) {
var o = breakHash[prop];
if (o.type == type.MCBF) {
setprop(failure_root ~ prop ~ "/mcbf", mcbf);
}
}
}
# Initialization, called once Nasal and the FDM are loaded properly.
_setlistener("/sim/signals/fdm-initialized", func {
srand();
# Engines are added dynamically because there may be an arbritary number
var i = 1;
foreach (var e; props.globals.getNode("/engines").getChildren("engine")) {
breakHash[e.getPath()] = { type: type.MTBF, failure: fail.ENGINE, desc : "Engine " ~ i };
i = i+1;
}
# Set up serviceable, MCBF and MTBF properties.
foreach(var prop; keys(breakHash)) {
var o = breakHash[prop];
var t = "/mcbf";
if (o.type == type.MTBF) {
t = "/mtbf";
}
# Set up the MTBF/MCFB properties to 0. Note that they are in a separate
# subtree, as there's no guarantee that the property isn't a leaf.
var n = props.globals.getNode(failure_root ~ prop ~ t, 1);
if (n.getValue() == nil) {
n.setDoubleValue(0);
}
if (n.getType() == "UNSPECIFIED") {
n.setDoubleValue(n.getValue());
}
if (o.failure == fail.SERVICEABLE) {
# If the property has a serviceable property, set it if appropriate.
props.globals.initNode(prop ~ "/serviceable", 1, "BOOL");
} elsif (o.failure == fail.JAM) {
# In the JAM case, we actually have a dummy serviceable property for the GUI.
props.globals.initNode(failure_root ~ prop ~ "/serviceable", 1, "BOOL");
setlistener(failure_root ~ prop ~ "/serviceable", jamListener);
} elsif (o.failure == fail.ENGINE) {
# In the JAM case, we actually have a dummy serviceable property for the GUI.
props.globals.initNode(failure_root ~ prop ~ "/serviceable", 1, "BOOL");
setlistener(failure_root ~ prop ~ "/serviceable", engineListener);
} else {
# If the serviceable property is actually defined, check it is set.
props.globals.initNode(o.failure, 1, "BOOL");
}
if (o.type == type.MCBF) {
# Set up listener for MCBF properties, only when the value changes.
setlistener(prop, checkMCBF, 0, 0);
}
}
# Start checking for failures.
checkMTBF();
});

View file

@ -2,173 +2,376 @@
<PropertyList>
<!-- Control the weather -->
<name>instrument-failures</name>
<width>500</width>
<height>240</height>
<modal>false</modal>
<text>
<x>10</x>
<y>210</y>
<label>Instrument Failures</label>
</text>
<group>
<y>180</y>
<name>instrument-failures</name>
<modal>false</modal>
<layout>vbox</layout>
<text>
<x>100</x>
<label>(Uncheck an instrument to fail it.)</label>
<label>Instrument Failures</label>
</text>
</group>
<hrule/>
<group>
<y>150</y>
<group>
<layout>hbox</layout>
<halign>left</halign>
<text>
<label>Uncheck an instrument to fail it, or set the Mean Time Between Failures.</label>
</text>
</group>
<checkbox>
<x>10</x>
<y>0</y>
<width>20</width>
<height>20</height>
<label>Airspeed Indicator</label>
<property>/instrumentation/airspeed-indicator/serviceable</property>
</checkbox>
<group>
<layout>table</layout>
<halign>center</halign>
<text>
<row>0</row>
<col>0</col>
<label>Instrument</label>
</text>
<text>
<row>0</row>
<col>2</col>
<label>MTBF (sec)</label>
</text>
<checkbox>
<x>240</x>
<y>0</y>
<width>20</width>
<height>20</height>
<label>Attitude Indicator</label>
<property>/instrumentation/attitude-indicator/serviceable</property>
</checkbox>
<text>
<row>0</row>
<col>3</col>
<label> </label>
</text>
<text>
<row>0</row>
<col>4</col>
<label>Instrument</label>
</text>
<text>
<row>0</row>
<col>6</col>
<label>MTBF (sec)</label>
</text>
</group>
<text>
<row>1</row>
<col>0</col>
<halign>right</halign>
<label>Nav 1 CDI</label>
</text>
<checkbox>
<row>1</row>
<col>1</col>
<property>/instrumentation/nav[0]/cdi/serviceable</property>
</checkbox>
<group>
<y>120</y>
<input>
<row>1</row>
<col>2</col>
<width>80</width>
<height>20</height>
<property>/sim/failure-manager/instrumentation/nav[0]/cdi/mtbf</property>
</input>
<checkbox>
<x>10</x>
<y>0</y>
<width>20</width>
<height>20</height>
<label>Altimeter</label>
<property>/instrumentation/altimeter/serviceable</property>
</checkbox>
<text>
<row>1</row>
<col>4</col>
<halign>right</halign>
<label>Nav 2 CDI</label>
</text>
<checkbox>
<x>240</x>
<y>0</y>
<width>20</width>
<height>20</height>
<label>Turn Indicator</label>
<property>/instrumentation/turn-indicator/serviceable</property>
</checkbox>
<checkbox>
<row>1</row>
<col>5</col>
<property>/instrumentation/nav[1]/cdi/serviceable</property>
</checkbox>
</group>
<input>
<row>1</row>
<col>6</col>
<width>80</width>
<height>20</height>
<property>/sim/failure-manager/instrumentation/nav[1]/cdi/mtbf</property>
</input>
<text>
<row>2</row>
<col>0</col>
<halign>right</halign>
<label>Nav 1 GS</label>
</text>
<checkbox>
<row>2</row>
<col>1</col>
<property>/instrumentation/nav[0]/gs/serviceable</property>
</checkbox>
<group>
<y>90</y>
<input>
<row>2</row>
<col>2</col>
<property>/sim/failure-manager/instrumentation/nav[0]/gs/mtbf</property>
</input>
<checkbox>
<x>10</x>
<y>0</y>
<width>20</width>
<height>20</height>
<label>Slip/Skid Ball</label>
<property>/instrumentation/slip-skid-ball/serviceable</property>
</checkbox>
<text>
<row>2</row>
<col>4</col>
<halign>right</halign>
<label>Nav 2 GS</label>
</text>
<checkbox>
<x>240</x>
<y>0</y>
<width>20</width>
<height>20</height>
<label>Heading Indicator</label>
<property>/instrumentation/heading-indicator/serviceable</property>
</checkbox>
<checkbox>
<row>2</row>
<col>5</col>
<property>/instrumentation/nav[1]/gs/serviceable</property>
</checkbox>
</group>
<input>
<row>2</row>
<col>6</col>
<property>/sim/failure-manager/instrumentation/nav[1]/gs/mtbf</property>
</input>
<text>
<row>3</row>
<col>0</col>
<halign>right</halign>
<label>DME</label>
</text>
<group>
<y>60</y>
<checkbox>
<row>3</row>
<col>1</col>
<property>/instrumentation/dme/serviceable</property>
</checkbox>
<checkbox>
<x>10</x>
<y>0</y>
<width>20</width>
<height>20</height>
<label>Vertical Speed Indicator</label>
<property>/instrumentation/vertical-speed-indicator/serviceable</property>
</checkbox>
<input>
<row>3</row>
<col>2</col>
<property>/sim/failure-manager/instrumentation/dme/mtbf</property>
</input>
<checkbox>
<x>240</x>
<y>0</y>
<width>20</width>
<height>20</height>
<label>Magnetic Compass</label>
<property>/instrumentation/magnetic-compass/serviceable</property>
</checkbox>
<text>
<row>3</row>
<col>4</col>
<halign>right</halign>
<label>ADF</label>
</text>
</group>
<checkbox>
<row>3</row>
<col>5</col>
<property>/instrumentation/adf/serviceable</property>
</checkbox>
<input>
<row>3</row>
<col>6</col>
<property>/sim/failure-manager/instrumentation/adf/mtbf</property>
</input>
<group>
<y>10</y>
<text>
<row>4</row>
<col>0</col>
<halign>right</halign>
<label>Airspeed Indicator</label>
</text>
<button>
<x>50</x>
<y>0</y>
<legend>OK</legend>
<default>true</default>
<equal>true</equal>
<binding>
<command>dialog-apply</command>
</binding>
<binding>
<command>dialog-close</command>
</binding>
</button>
<checkbox>
<row>4</row>
<col>1</col>
<property>/instrumentation/airspeed-indicator/serviceable</property>
</checkbox>
<button>
<x>150</x>
<y>0</y>
<legend>Apply</legend>
<equal>true</equal>
<binding>
<command>dialog-apply</command>
</binding>
</button>
<input>
<row>4</row>
<col>2</col>
<property>/sim/failure-manager/instrumentation/airspeed-indicator/mtbf</property>
</input>
<button>
<x>250</x>
<y>0</y>
<legend>Reset</legend>
<equal>true</equal>
<binding>
<command>dialog-update</command>
</binding>
</button>
<text>
<row>4</row>
<col>4</col>
<halign>right</halign>
<label>Attitude Indicator</label>
</text>
<button>
<x>350</x>
<y>0</y>
<legend>Cancel</legend>
<equal>true</equal>
<key>Esc</key>
<binding>
<command>dialog-close</command>
</binding>
</button>
<checkbox>
<row>4</row>
<col>5</col>
<property>/instrumentation/attitude-indicator/serviceable</property>
</checkbox>
</group>
<input>
<row>4</row>
<col>6</col>
<property>/sim/failure-manager/instrumentation/attitude-indicator/mtbf</property>
</input>
<text>
<row>5</row>
<col>0</col>
<halign>right</halign>
<label>Altimeter</label>
</text>
<checkbox>
<row>5</row>
<col>1</col>
<property>/instrumentation/altimeter/serviceable</property>
</checkbox>
<input>
<row>5</row>
<col>2</col>
<property>/sim/failure-manager/instrumentation/altimeter/mtbf</property>
</input>
<text>
<row>5</row>
<col>4</col>
<halign>right</halign>
<label>Turn Indicator</label>
</text>
<checkbox>
<row>5</row>
<col>5</col>
<property>/instrumentation/turn-indicator/serviceable</property>
</checkbox>
<input>
<row>5</row>
<col>6</col>
<property>/sim/failure-manager/instrumentation/turn-indicator/mtbf</property>
</input>
<text>
<row>6</row>
<col>0</col>
<halign>right</halign>
<label>Slip/Skid Ball</label>
</text>
<checkbox>
<row>6</row>
<col>1</col>
<property>/instrumentation/slip-skid-ball/serviceable</property>
</checkbox>
<input>
<row>6</row>
<col>2</col>
<property>/sim/failure-manager/instrumentation/slip-skid-ball/mtbf</property>
</input>
<text>
<row>6</row>
<col>4</col>
<halign>right</halign>
<label>Heading Indicator</label>
</text>
<checkbox>
<row>6</row>
<col>5</col>
<property>/instrumentation/heading-indicator/serviceable</property>
</checkbox>
<input>
<row>6</row>
<col>6</col>
<property>/sim/failure-manager/instrumentation/heading-indicator/mtbf</property>
</input>
<text>
<row>7</row>
<col>0</col>
<halign>right</halign>
<label>Vertical Speed Ind.</label>
</text>
<checkbox>
<row>7</row>
<col>1</col>
<property>/instrumentation/vertical-speed-indicator/serviceable</property>
</checkbox>
<input>
<row>7</row>
<col>2</col>
<property>/sim/failure-manager/instrumentation/vertical-speed-indicator/mtbf</property>
</input>
<text>
<row>7</row>
<col>4</col>
<halign>right</halign>
<label>Magnetic Compass</label>
</text>
<checkbox>
<row>7</row>
<col>5</col>
<property>/instrumentation/magnetic-compass/serviceable</property>
</checkbox>
<input>
<row>7</row>
<col>6</col>
<property>/sim/failure-manager/instrumentation/magnetic-compass/mtbf</property>
</input>
</group>
<group>
<layout>hbox</layout>
<button>
<legend>OK</legend>
<default>true</default>
<equal>true</equal>
<binding>
<command>dialog-apply</command>
</binding>
<binding>
<command>nasal</command>
<script>
setprop("/instrumentation/heading-indicator-fg/serviceable",
getprop("/instrumentation/heading-indicator/serviceable"));
</script>
</binding>
<binding>
<command>dialog-close</command>
</binding>
</button>
<button>
<legend>Apply</legend>
<equal>true</equal>
<binding>
<command>dialog-apply</command>
</binding>
<binding>
<command>nasal</command>
<script>
setprop("/instrumentation/heading-indicator-fg/serviceable",
getprop("/instrumentation/heading-indicator/serviceable"));
</script>
</binding>
</button>
<button>
<legend>Reset</legend>
<equal>true</equal>
<binding>
<command>dialog-update</command>
</binding>
</button>
<button>
<legend>Cancel</legend>
<equal>true</equal>
<key>Esc</key>
<binding>
<command>dialog-close</command>
</binding>
</button>
</group>
</PropertyList>

View file

@ -0,0 +1,347 @@
<?xml version="1.0"?>
<PropertyList>
<name>random-failures</name>
<modal>false</modal>
<layout>vbox</layout>
<nasal>
<open>
<![CDATA[
var groups = cmdarg().getChildren("group")[0].getChildren("group");
var mtbfNodes = groups[0].getChildren("radio");
var mcbfNodes = groups[1].getChildren("radio");
var set_mtbf = func(m) {
for (var i = 0; i < size(mtbfNodes); i +=1) {
var prop = mtbfNodes[i].getChild("property").getValue();
setprop(prop, (m == mtbfNodes[i].getChild("value").getValue()));
}
setprop("/sim/failure-manager/global-mtbf", m);
};
var set_mcbf = func(m) {
for (var i = 0; i < size(mcbfNodes); i +=1) {
var prop = mcbfNodes[i].getChild("property").getValue();
setprop(prop, (m == mcbfNodes[i].getChild("value").getValue()));
}
setprop("/sim/failure-manager/global-mcbf", m);
};
set_mtbf(getprop("/sim/failure-manager/global-mtbf"));
set_mcbf(getprop("/sim/failure-manager/global-mcbf"));
]]>
</open>
</nasal>
<text>
<label>Random Failures</label>
</text>
<hrule></hrule>
<text>
<label>Configure MTBF/MCBF for all systems and instruments.</label>
</text>
<hrule></hrule>
<group>
<layout>hbox</layout>
<halign>center</halign>
<valign>top</valign>
<stretch>true</stretch>
<group>
<stretch>true</stretch>
<layout>vbox</layout>
<halign>center</halign>
<valign>top</valign>
<text>
<label>Mean Time Between Failures</label>
</text>
<radio>
<halign>left</halign>
<property>/sim/failure-manager/global-mtbf-60</property>
<live>true</live>
<value>60</value>
<label>1 minute</label>
<binding>
<command>nasal</command>
<script>set_mtbf(60);</script>
</binding>
</radio>
<radio>
<halign>left</halign>
<property>/sim/failure-manager/global-mtbf-300</property>
<live>true</live>
<value>300</value>
<label>5 minutes</label>
<binding>
<command>nasal</command>
<script>set_mtbf(300);</script>
</binding>
</radio>
<radio>
<halign>left</halign>
<property>/sim/failure-manager/global-mtbf-600</property>
<live>true</live>
<value>600</value>
<label>10 minutes</label>
<binding>
<command>nasal</command>
<script>set_mtbf(600);</script>
</binding>
</radio>
<radio>
<halign>left</halign>
<property>/sim/failure-manager/global-mtbf-1800</property>
<live>true</live>
<value>1800</value>
<label>30 minutes</label>
<binding>
<command>nasal</command>
<script>set_mtbf(1800);</script>
</binding>
</radio>
<radio>
<halign>left</halign>
<property>/sim/failure-manager/global-mtbf-3600</property>
<live>true</live>
<value>3600</value>
<label>1 hour</label>
<binding>
<command>nasal</command>
<script>set_mtbf(3600);</script>
</binding>
</radio>
<radio>
<halign>left</halign>
<property>/sim/failure-manager/global-mtbf-21600</property>
<live>true</live>
<value>21600</value>
<label>6 hours</label>
<binding>
<command>nasal</command>
<script>set_mtbf(21600);</script>
</binding>
</radio>
<radio>
<halign>left</halign>
<property>/sim/failure-manager/global-mtbf-86400</property>
<live>true</live>
<value>86400</value>
<label>24 hours</label>
<binding>
<command>nasal</command>
<script>set_mtbf(86400);</script>
</binding>
</radio>
<radio>
<halign>left</halign>
<property>/sim/failure-manager/global-mtbf-0</property>
<value>0</value>
<label>0 (Disabled)</label>
<live>true</live>
<binding>
<command>nasal</command>
<script>set_mtbf(0);</script>
</binding>
</radio>
</group>
<empty><stretch>true</stretch></empty>
<vrule/>
<empty><stretch>true</stretch></empty>
<group>
<layout>vbox</layout>
<halign>left</halign>
<valign>top</valign>
<stretch>true</stretch>
<text>
<halign>center</halign>
<label>Mean Cycles Between Failures</label>
</text>
<radio>
<halign>left</halign>
<property>/sim/failure-manager/global-mcbf-5</property>
<value>5</value>
<label>5</label>
<live>true</live>
<binding>
<command>nasal</command>
<script>set_mcbf(5);</script>
</binding>
</radio>
<radio>
<halign>left</halign>
<property>/sim/failure-manager/global-mcbf-10</property>
<value>10</value>
<label>10</label>
<live>true</live>
<binding>
<command>nasal</command>
<script>set_mcbf(10);</script>
</binding>
</radio>
<radio>
<halign>left</halign>
<property>/sim/failure-manager/global-mcbf-20</property>
<value>20</value>
<label>20</label>
<live>true</live>
<binding>
<command>nasal</command>
<script>set_mcbf(20);</script>
</binding>
</radio>
<radio>
<halign>left</halign>
<property>/sim/failure-manager/global-mcbf-50</property>
<value>50</value>
<label>50</label>
<live>true</live>
<binding>
<command>nasal</command>
<script>set_mcbf(50);</script>
</binding>
</radio>
<radio>
<halign>left</halign>
<property>/sim/failure-manager/global-mcbf-100</property>
<value>100</value>
<label>100</label>
<live>true</live>
<binding>
<command>nasal</command>
<script>set_mcbf(100);</script>
</binding>
</radio>
<radio>
<halign>left</halign>
<property>/sim/failure-manager/global-mcbf-200</property>
<value>200</value>
<label>200</label>
<live>true</live>
<binding>
<command>nasal</command>
<script>set_mcbf(200);</script>
</binding>
</radio>
<radio>
<halign>left</halign>
<property>/sim/failure-manager/global-mcbf-500</property>
<value>500</value>
<label>500</label>
<live>true</live>
<binding>
<command>nasal</command>
<script>set_mcbf(500);</script>
</binding>
</radio>
<radio>
<halign>left</halign>
<property>/sim/failure-manager/global-mcbf-0</property>
<value>0</value>
<label>0 (Disabled)</label>
<live>true</live>
<binding>
<command>nasal</command>
<script>set_mcbf(0);</script>
</binding>
</radio>
</group>
</group>
<hrule></hrule>
<checkbox>
<valign>down</valign>
<name>onScreenMessages</name>
<label>Display failure messages on screen</label>
<width>10</width>
<height>10</height>
<property>/sim/failure-manager/display-on-screen</property>
</checkbox>
<hrule></hrule>
<group>
<layout>hbox</layout>
<button>
<legend>OK</legend>
<default>true</default>
<equal>true</equal>
<binding>
<command>dialog-apply</command>
</binding>
<binding>
<command>nasal</command>
<script>
failures.setAllMTBF(getprop("/sim/failure-manager/global-mtbf"));
failures.setAllMCBF(getprop("/sim/failure-manager/global-mcbf"));
</script>
</binding>
<binding>
<command>dialog-close</command>
</binding>
</button>
<button>
<legend>Apply</legend>
<equal>true</equal>
<binding>
<command>dialog-apply</command>
</binding>
<binding>
<command>nasal</command>
<script>
failures.setAllMTBF(getprop("/sim/failure-manager/global-mtbf"));
failures.setAllMCBF(getprop("/sim/failure-manager/global-mcbf"));
</script>
</binding>
</button>
<button>
<legend>Close</legend>
<equal>true</equal>
<key>Esc</key>
<binding>
<command>dialog-close</command>
</binding>
</button>
</group>
<empty>
<pref-height>1</pref-height>
</empty>
</PropertyList>

View file

@ -2,109 +2,408 @@
<PropertyList>
<!-- Control the weather -->
<name>system-failures</name>
<modal>false</modal>
<layout>vbox</layout>
<name>system-failures</name>
<width>300</width>
<height>240</height>
<modal>false</modal>
<nasal>
<open>
# Code to populate the engine entries.
var groups = cmdarg().getChildren("group");
var group = groups[3].getChildren("group")[2];
var engines = props.globals.getNode("/engines");
var row = 4;
var engine = 0;
var i = 0;
group.removeChildren("checkbox");
group.removeChildren("input");
group.removeChildren("text");
<text>
<x>10</x>
<y>210</y>
<label>System Failures</label>
</text>
# Copy in the labels.
var target = group.getNode("text[" ~ i ~ "]", 1);
props.copy(group.getNode("engine-label"), target);
i += 1;
<text>
<x>30</x>
<y>180</y>
<label>(Uncheck a system to fail it.)</label>
</text>
target = group.getNode("text[" ~ i ~ "]", 1);
props.copy(group.getNode("mtbf-label"), target);
i += 1;
foreach (var e; engines.getChildren("engine")) {
if ((e.getChild("starter") != nil) or (e.getChild("running") != nil)) {
row = row + 1;
# Set up the label
target = group.getNode("text[" ~ i ~ "]", 1);
props.copy(group.getNode("text-template"), target);
target.getNode("row").setValue(row);
if (size(engines.getChildren("engine")) == 1) {
target.getNode("label").setValue("Engine");
} else {
# Engines are indexed from 1 in the GUI.
target.getNode("label").setValue("Engine " ~ (engine + 1));
}
# Now the checkbox
target = group.getNode("checkbox[" ~ i ~ "]", 1);
props.copy(group.getChild("checkbox-template"), target);
target.getNode("row").setValue(row);
<checkbox>
<x>30</x>
<y>150</y>
<width>20</width>
<height>20</height>
<label>Static System</label>
<property>/systems/static/serviceable</property>
</checkbox>
var failure = "/sim/failure-manager/engines/engine[" ~ engine ~ "]/serviceable";
target.getNode("property").setValue(failure);
# Finally the MTBF
target = group.getNode("input[" ~ i ~ "]", 1);
props.copy(group.getChild("input-template"), target);
target.getNode("row").setValue(row);
i += 1;
var mtbf = "/sim/failure-manager/engines/engine[" ~ engine ~ "]/mtbf";
target.getNode("property").setValue(mtbf);
engine += 1;
}
}
</open>
</nasal>
<checkbox>
<x>30</x>
<y>120</y>
<width>20</width>
<height>20</height>
<label>Pitot System</label>
<property>/systems/pitot/serviceable</property>
</checkbox>
<group>
<layout>hbox</layout>
<text>
<label>System Failures</label>
</text>
</group>
<checkbox>
<x>30</x>
<y>90</y>
<width>20</width>
<height>20</height>
<label>Electrical System</label>
<property>/systems/electrical/serviceable</property>
</checkbox>
<group>
<layout>hbox</layout>
<hrule/>
</group>
<checkbox>
<x>30</x>
<y>60</y>
<width>20</width>
<height>20</height>
<label>Vacuum System</label>
<property>/systems/vacuum/serviceable</property>
</checkbox>
<group>
<layout>hbox</layout>
<halign>left</halign>
<text>
<label>Uncheck a system to fail it, or set the Mean Time/Cycles Between Failures.</label>
</text>
</group>
<group>
<y>10</y>
<group>
<layout>hbox</layout>
<halign>left</halign>
<button>
<x>10</x>
<y>0</y>
<legend>OK</legend>
<default>true</default>
<equal>true</equal>
<binding>
<command>dialog-apply</command>
</binding>
<binding>
<command>dialog-close</command>
</binding>
</button>
<group>
<layout>table</layout>
<halign>center</halign>
<valign>top</valign>
<button>
<x>60</x>
<y>0</y>
<legend>Apply</legend>
<equal>true</equal>
<binding>
<command>dialog-apply</command>
</binding>
</button>
<text>
<row>0</row>
<col>0</col>
<label>System</label>
</text>
<text>
<row>0</row>
<col>2</col>
<label>MTBF (sec)</label>
</text>
<button>
<x>140</x>
<y>0</y>
<legend>Reset</legend>
<equal>true</equal>
<binding>
<command>dialog-update</command>
</binding>
</button>
<text>
<row>1</row>
<col>0</col>
<halign>right</halign>
<label>Vacuum System</label>
</text>
<button>
<x>220</x>
<y>0</y>
<legend>Cancel</legend>
<equal>true</equal>
<key>Esc</key>
<binding>
<command>dialog-close</command>
</binding>
</button>
<checkbox>
<row>1</row>
<col>1</col>
<property>/systems/vacuum/serviceable</property>
</checkbox>
</group>
<input>
<row>1</row>
<col>2</col>
<property>/sim/failure-manager/systems/vacuum/mtbf</property>
</input>
<text>
<row>2</row>
<col>0</col>
<halign>right</halign>
<label>Static System</label>
</text>
<checkbox>
<row>2</row>
<col>1</col>
<property>/systems/static/serviceable</property>
</checkbox>
<input>
<row>2</row>
<col>2</col>
<property>/sim/failure-manager/systems/static/mtbf</property>
</input>
<text>
<row>3</row>
<col>0</col>
<halign>right</halign>
<label>Pitot System</label>
</text>
<checkbox>
<row>3</row>
<col>1</col>
<property>/systems/pitot/serviceable</property>
</checkbox>
<input>
<row>3</row>
<col>2</col>
<property>/sim/failure-manager/systems/pitot/mtbf</property>
</input>
<text>
<row>4</row>
<col>0</col>
<halign>right</halign>
<label>Electrical System</label>
</text>
<checkbox>
<row>4</row>
<col>1</col>
<property>/systems/electrical/serviceable</property>
</checkbox>
<input>
<row>4</row>
<col>2</col>
<property>/sim/failure-manager/systems/electrical/mtbf</property>
</input>
<text>
<row>5</row>
<col>0</col>
<halign>right</halign>
<label>Aileron</label>
</text>
<checkbox>
<row>5</row>
<col>1</col>
<property>/sim/failure-manager/controls/flight/aileron/serviceable</property>
</checkbox>
<input>
<row>5</row>
<col>2</col>
<property>/sim/failure-manager/controls/flight/aileron/mtbf</property>
</input>
<text>
<row>6</row>
<col>0</col>
<halign>right</halign>
<label>Elevator</label>
</text>
<checkbox>
<row>6</row>
<col>1</col>
<property>/sim/failure-manager/controls/flight/elevator/serviceable</property>
</checkbox>
<input>
<row>6</row>
<col>2</col>
<property>/sim/failure-manager/controls/flight/elevator/mtbf</property>
</input>
<text>
<row>7</row>
<col>0</col>
<halign>right</halign>
<label>Rudder</label>
</text>
<checkbox>
<row>7</row>
<col>1</col>
<property>/sim/failure-manager/controls/flight/rudder/serviceable</property>
</checkbox>
<input>
<row>7</row>
<col>2</col>
<property>/sim/failure-manager/controls/flight/rudder/mtbf</property>
</input>
</group>
<vrule/>
<group>
<layout>table</layout>
<halign>center</halign>
<valign>top</valign>
<text>
<row>0</row>
<col>0</col>
<label>System</label>
</text>
<text>
<row>0</row>
<col>2</col>
<label>MCBF</label>
</text>
<text>
<row>1</row>
<col>0</col>
<halign>right</halign>
<label>Landing Gear</label>
</text>
<checkbox>
<row>1</row>
<col>1</col>
<property>/gear/serviceable</property>
</checkbox>
<input>
<row>1</row>
<col>2</col>
<property>/sim/failure-manager/controls/gear/gear-down/mcbf</property>
</input>
<text>
<row>2</row>
<col>0</col>
<halign>right</halign>
<label>Flaps</label>
</text>
<checkbox>
<row>2</row>
<col>1</col>
<property>/sim/failure-manager/controls/flight/flaps/serviceable</property>
</checkbox>
<input>
<row>2</row>
<col>2</col>
<property>/sim/failure-manager/controls/flight/flaps/mcbf</property>
</input>
<text>
<row>3</row>
<col>0</col>
<halign>right</halign>
<label>Speedbrake</label>
</text>
<checkbox>
<row>3</row>
<col>1</col>
<property>/sim/failure-manager/controls/flight/speedbrake/serviceable</property>
</checkbox>
<input>
<row>3</row>
<col>2</col>
<property>/sim/failure-manager/controls/flight/speedbrake/mcbf</property>
</input>
</group>
<vrule/>
<group>
<layout>table</layout>
<halign>center</halign>
<valign>top</valign>
<engine-label>
<row>0</row>
<col>0</col>
<label>Engine</label>
</engine-label>
<mtbf-label>
<row>0</row>
<col>2</col>
<label>MTBF</label>
</mtbf-label>
<text-template>
<row><!-- template value--></row>
<col>0</col>
<halign>right</halign>
<label><!-- template value--></label>
</text-template>
<checkbox-template>
<row><!-- template value--></row>
<col>1</col>
<property><!-- template value--></property>
</checkbox-template>
<input-template>
<row><!-- template value--></row>
<col>2</col>
<property><!-- template value--></property>
</input-template>
</group>
</group>
<group>
<layout>hbox</layout>
<button>
<legend>OK</legend>
<default>true</default>
<equal>true</equal>
<binding>
<command>dialog-apply</command>
</binding>
<binding>
<command>dialog-close</command>
</binding>
</button>
<button>
<legend>Apply</legend>
<equal>true</equal>
<binding>
<command>dialog-apply</command>
</binding>
</button>
<button>
<legend>Reset</legend>
<equal>true</equal>
<binding>
<command>dialog-update</command>
</binding>
</button>
<button>
<legend>Cancel</legend>
<equal>true</equal>
<key>Esc</key>
<binding>
<command>dialog-close</command>
</binding>
</button>
</group>
</PropertyList>

View file

@ -357,6 +357,14 @@
</binding>
</item>
<item>
<label>Random Failures</label>
<binding>
<command>dialog-show</command>
<dialog-name>random-failures</dialog-name>
</binding>
</item>
<item>
<label>System Failures</label>
<binding>
@ -372,6 +380,7 @@
<dialog-name>instrument-failures</dialog-name>
</binding>
</item>
</menu>
<menu>
@ -487,6 +496,17 @@
<dialog-name>devel-extensions</dialog-name>
</binding>
</item>
<item>
<label>Display Marker</label>
<name>display-marker</name>
<binding>
<command>nasal</command>
<script>
tutorial.dialog();
</script>
</binding>
</item>
<item>
<label>Dump Scene Graph</label>
@ -572,6 +592,15 @@
<item>
<label>Start Tutorial</label>
<name>tutorial-start</name>
<binding>
<command>nasal</command>
<script>
props.globals.getNode("/sim/tutorials").remove();
io.read_properties(
"/home/stuart/FlightGear-0.9/data/Aircraft/c172p/Tutorials/c172-tutorials.xml",
"/sim/tutorials");
</script>
</binding>
<binding>
<command>dialog-show</command>
<dialog-name>tutorial</dialog-name>