diff --git a/Docs/README.gremlins b/Docs/README.gremlins new file mode 100644 index 0000000..a8f7eea --- /dev/null +++ b/Docs/README.gremlins @@ -0,0 +1,109 @@ +Gremlins cause things to go wrong at random times. + +As implemented in Nasal/gremlins.nas, there are three types of +gremlins: + +-- Most gremlins are based simply on time. There will be a MTBF + number (i.e. mean time between failures) associated with each + affected feature. A zero value for the MTBF property means the + gremlins will leave that feature alone; this is the default. + Otherwise the MTBF is measured in hours. A plausible for + practice flights is 5 hours. Note that if you have ten gremlins + with a 5-hour MTBF each, that means that on average /something/ + will go wrong every 30 minutes. + + There are about 20 eligible features including nav[0]/gs, + nav[0]/cdi, nav[1]/gs, nav[1]/cdi, attitude-indicator, + heading-indicator, dme, and adf; if you really want the complete + current list, look at the "features" array in gremlins.nas. + +-- Landing gear gremlins are based on MCBF i.e. mean cycles between + failures. They are not based on time, i.e. not on MTBF. + +-- If desired, the QNH changes every time you move to a new air mass. + More specifically, it changes every time you use the + location-in-air popup. This is mediated by a listenter attached to + the /position/attention property. The listener is in gremlins.nas; + the property is set by the location-in-air popup menu. This + happens on a per-relocation-event basis (not MTBF or MCBF). + + The instructional purpose here is to encourage you (the pilot) to + pay attention to the altimeter setting. Every time you use + location-in-air, you should listen to the AWOS and set your altimeter + before practicing landings and/or instrument approaches. + + The amount of change in the QNH is random, on a scale set by the + /environment/pressure-sea-level-inhg-step property. The default is + zero, and a reasonably instructive value is 0.2. + + Also BTW, going the other way, note that anybody who changes the + QNH should set the /environment/attention property, not to be + confused with the /position/attention property. The former has + listeners in atis.cxx and perhaps elsewhere. + +============================== +Notes and hints: + +Note that failing the vacuum system gives a more gradual -- and +therefore more realistic -- gyro failure (as compared to failing the +attitude indicator directly, which causes an unrealistically sudden +failure). Both failure modes are supported; take your choice when you +set the MTBF values. + +====== + +There are three ways to check and/or change the status of a particular +feature: + A) The Equipment::Instrument-failures popup or the + Equipment::System-failures popup. + + B) The web interface. This is simpler than it initially appears; + for details see below. + + C) The File::browse-internal-properties popup. This has the + advantage that it shows properties changing in real time, + whereas the web interface and the Equipment popups don't + show updated values unless/until you hit the reset or + reload button. + +Using the web interface is simpler than it looks, because you can use +hyperlinks and/or bookmarks to quickly get access to the features you +want. + +Here are some examples of checking properties: + + lynx -dump 'http://localhost:5400/instrumentation/dme' + lynx -dump 'http://localhost:5400/gear' + +On such a page, both the "serviceable" property and the "mtbf" (or +"mcbf") property may be of interest. + +You can also use the web page to restore functionality. For +example: + lynx -dump 'http://localhost:5400/instrumentation/dme/serviceable?value=1&submit=update' + lynx -dump 'http://localhost:5400/gear/serviceable?value=1&submit=update' + lynx -dump 'http://localhost:5400/instrumentation/nav/gs/serviceable?value=1&submit=update' + +====== + +In order to make the gremlins active, you have to set a nonzero MTBF +(or MCBF, as appropriate) for each item of interest. This is +typically done via the .fgfsrc file or the preferences.xml file. To +save you some typing, here is an example of the setup you could put in +your .fgfsrc file: + + --prop:/gear/mcbf=5 + --prop:/instrumentation/nav[0]/gs/mtbf=5 + --prop:/instrumentation/nav[0]/cdi/mtbf=5 + --prop:/instrumentation/nav[1]/gs/mtbf=5 + --prop:/instrumentation/nav[1]/cdi/mtbf=5 + ###--prop:/instrumentation/attitude-indicator/mtbf=5 + --prop:/systems/vacuum/mtbf=5 + --prop:/instrumentation/heading-indicator/mtbf=5 + --prop:/instrumentation/dme/mtbf=5 + --prop:/instrumentation/adf/mtbf=5 + + --prop:/environment/pressure-sea-level-inhg-step=0.2 + +Also don't forget to start the web interface if you want it: + --httpd=5400 diff --git a/Nasal/gremlins.nas b/Nasal/gremlins.nas new file mode 100644 index 0000000..a098329 --- /dev/null +++ b/Nasal/gremlins.nas @@ -0,0 +1,122 @@ +#! nasal + +# For design notes and usage instructions, see Docs/README.gremlins + +var last_gear = 0; +var dt = 10; ## time between updates + +# Each of the following has an MTBF property: +features = [ + "/instrumentation/nav[0]/gs", + "/instrumentation/nav[0]/cdi", + "/instrumentation/nav[1]/gs", + "/instrumentation/nav[1]/cdi", + "/instrumentation/attitude-indicator", ## unrealistically sudden + "/systems/vacuum", ## more realistically gradual + "/instrumentation/heading-indicator", + "/instrumentation/dme", + "/instrumentation/adf", + "/instrumentation/airspeed-indicator", + "/instrumentation/attitude-indicator", + "/instrumentation/altimeter", + "/instrumentation/turn-indicator", + "/instrumentation/slip-skid-ball", + "/instrumentation/vertical-speed-indicator", + "/instrumentation/magnetic-compass", + "/systems/vacuum", + "/systems/static", + "/systems/pitot", + "/systems/electrical" + ]; + +# For the given feature, +# assign types and default values to the two properties of interest +set1 = func(feat, interval) { + nnn = props.globals.getNode(feat ~ "/serviceable", 1); + if (nnn.getValue() == nil) { + nnn.setBoolValue(1); + } + if (nnn.getType() == "UNSPECIFIED") { + nnn.setBoolValue(nnn.getValue()); + } + + nnn = props.globals.getNode(feat ~ interval, 1); + if (nnn.getValue() == nil) { + nnn.setDoubleValue(0); + } + if (nnn.getType() == "UNSPECIFIED") { + nnn.setDoubleValue(nnn.getValue()); + } +} + +var gearcheck = func { + gear = getprop("/controls/gear/gear-down"); + + if (gear != last_gear) { + last_gear = gear; +# 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: + mcbf = getprop("/gear/mcbf"); + if (mcbf and !int(2 * mcbf * rand())) { + setprop("/gear/serviceable", 0); + } + } +} + +var gremulate = func{ + foreach (feat ; features) { + mtbf = getprop(feat, "mtbf"); + if (mtbf and !int(rand() * mtbf * 3600.0 / dt)) { + setprop(feat, "serviceable", 0); + } + } + settimer(gremulate, dt); +} + +########################## +# Listener; responds when we have moved to a new position +var newpos = func{ + Psl = getprop("/environment/pressure-sea-level-inhg"); + step = getprop("/environment/pressure-sea-level-inhg-step"); + delta = step * (2*rand() - 1); + Psl += delta; + lat = getprop("/position/latitude-deg"); + lon = getprop("/position/longitude-deg"); + # print("Gremlins.nas noticed new location: ", lon, " ", lat); + # print("... and sets Psl, delta: ", delta, " new: ", Psl); + for (ii = 0; ii < 5; ii+=1){ + fmt = "/environment/config/%s/entry[%d]/pressure-sea-level-inhg"; + setprop(sprintf(fmt, "boundary", ii), Psl); + setprop(sprintf(fmt, "aloft", ii), Psl); + } +# Propagate it from the aforementioned entry[] items +# to the internal variable of the FGenvironment class, +# from whence it will propagate to the +# /environment/pressure-sea-level-inhg property: + fgcommand("reinit", props.Node.new({"subsystem" : "environment"})); +# Notify the ATIS generator that things have changed: + setprop("/environment/attention", 1); +} + +# Initialization, called once Nasal loaded properly. +_setlistener("/sim/signals/nasal-dir-initialized", func { + srand(); + + foreach (feat ; features) { + set1(feat, "/mtbf"); + } + + # Do the same for the gear, + # which is a special case (mcbf instead of mtbf). + set1("/gear", "/mcbf"); + + last_gear = getprop("/controls/gear/gear-down"); + + ##################### + # Now the variables are set up; implement the listeners + setlistener("/controls/gear/gear-down", gearcheck); + setlistener("/position/attention", newpos); + + gremulate(); # start the chain +}); diff --git a/gui/dialogs/instrument-failures.xml b/gui/dialogs/instrument-failures.xml index a0214dc..3b0f130 100644 --- a/gui/dialogs/instrument-failures.xml +++ b/gui/dialogs/instrument-failures.xml @@ -2,173 +2,362 @@ - - - instrument-failures - 500 - 240 - false - - - 10 - 210 - - + instrument-failures + 620 + 420 + false + vbox + + + - - 180 + - 100 - + 10 + - - - - 150 - - - 10 - 0 - 20 - 20 - - /instrumentation/airspeed-indicator/serviceable - - - - 240 - 0 - 20 - 20 - - /instrumentation/attitude-indicator/serviceable - - - - - - - 120 - - - 10 - 0 - 20 - 20 - - /instrumentation/altimeter/serviceable - - - - 240 - 0 - 20 - 20 - - /instrumentation/turn-indicator/serviceable - - - - - - - 90 - - - 10 - 0 - 20 - 20 - - /instrumentation/slip-skid-ball/serviceable - - - - 240 - 0 - 20 - 20 - - /instrumentation/heading-indicator/serviceable - - - - - - - 60 - - - 10 - 0 - 20 - 20 - - /instrumentation/vertical-speed-indicator/serviceable - - - - 240 - 0 - 20 - 20 - - /instrumentation/magnetic-compass/serviceable - - - - - - - 10 - - - - - - - - - - + + table + center + + 0 + 0 + + + + 0 + 2 + + + + + 0 + 3 + + + + 0 + 4 + + + + 0 + 6 + + + + + 1 + 0 + right + + + + + 1 + 1 + /instrumentation/nav[0]/cdi/serviceable + + + + 1 + 2 + 80 + 20 + /instrumentation/nav[0]/cdi/mtbf + + + + 1 + 4 + right + + + + + 1 + 5 + /instrumentation/nav[1]/cdi/serviceable + + + + 1 + 6 + 80 + 20 + /instrumentation/nav[1]/cdi/mtbf + + + + 2 + 0 + right + + + + + 2 + 1 + /instrumentation/nav[0]/gs/serviceable + + + + 2 + 2 + /instrumentation/nav[0]/gs/mtbf + + + + 2 + 4 + right + + + + + 2 + 5 + /instrumentation/nav[1]/gs/serviceable + + + + 2 + 6 + /instrumentation/nav[1]/gs/mtbf + + + + 3 + 0 + right + + + + + 3 + 1 + /instrumentation/dme/serviceable + + + + 3 + 2 + /instrumentation/dme/mtbf + + + + 3 + 4 + right + + + + + 3 + 5 + /instrumentation/adf/serviceable + + + + 3 + 6 + /instrumentation/adf/mtbf + + + + 4 + 0 + right + + + + + 4 + 1 + /instrumentation/airspeed-indicator/serviceable + + + + 4 + 2 + /instrumentation/airspeed-indicator/mtbf + + + + 4 + 4 + right + + + + + 4 + 5 + /instrumentation/attitude-indicator/serviceable + + + + 4 + 6 + /instrumentation/attitude-indicator/mtbf + + + + 5 + 0 + right + + + + + 5 + 1 + /instrumentation/altimeter/serviceable + + + + 5 + 2 + /instrumentation/altimeter/mtbf + + + + 5 + 4 + right + + + + + 5 + 5 + /instrumentation/turn-indicator/serviceable + + + + 5 + 6 + /instrumentation/turn-indicator/mtbf + + + + 6 + 0 + right + + + + + 6 + 1 + /instrumentation/slip-skid-ball/serviceable + + + + 6 + 2 + /instrumentation/slip-skid-ball/mtbf + + + + 6 + 4 + right + + + + + 6 + 5 + /instrumentation/heading-indicator/serviceable + + + + 6 + 6 + /instrumentation/heading-indicator/mtbf + + + + 7 + 0 + right + + + + + 7 + 1 + /instrumentation/vertical-speed-indicator/serviceable + + + + 7 + 2 + /instrumentation/vertical-speed-indicator/mtbf + + + + 7 + 4 + right + + + + + 7 + 5 + /instrumentation/magnetic-compass/serviceable + + + + 7 + 6 + /instrumentation/magnetic-compass/mtbf + + + + + hbox + + + + + + + + + diff --git a/gui/dialogs/system-failures.xml b/gui/dialogs/system-failures.xml index 142b22f..003fe9a 100644 --- a/gui/dialogs/system-failures.xml +++ b/gui/dialogs/system-failures.xml @@ -2,109 +2,180 @@ - - - system-failures - 300 - 240 - false - - - 10 - 210 - - - - - 30 - 180 - - - - - 30 - 150 - 20 - 20 - - /systems/static/serviceable - - - - 30 - 120 - 20 - 20 - - /systems/pitot/serviceable - - - - 30 - 90 - 20 - 20 - - /systems/electrical/serviceable - - - - 30 - 60 - 20 - 20 - - /systems/vacuum/serviceable - - - - 10 - - - - - - - - - - + system-failures + 400 + 360 + false + vbox + + + + + + + + 10 + + + + + table + center + + 0 + 0 + + + + + 0 + 2 + + + + + 1 + 0 + right + + + + + 1 + 1 + /gear/serviceable + + + + 1 + 2 + /gear/mcbf + + + + 2 + 2 + + + + + 3 + 0 + right + + + + + 3 + 1 + /systems/vacuum/serviceable + + + + 3 + 2 + /systems/vacuum/mtbf + + + + 4 + 0 + right + + + + + 4 + 1 + /systems/static/serviceable + + + + 4 + 2 + /systems/static/mtbf + + + + 5 + 0 + right + + + + + 5 + 1 + /systems/pitot/serviceable + + + + 5 + 2 + /systems/pitot/mtbf + + + + 6 + 0 + right + + + + + 6 + 1 + /systems/electrical/serviceable + + + + 6 + 2 + /systems/electrical/mtbf + + + + + + hbox + + + + + + + + + +