Failure Manager
Note Whenever possible, please refrain from modeling complex systems, like an FDM, autopilot or Route Manager with Nasal. This is primarily to help reduce Nasal overhead (especially GC overhead). It will also help to unify duplicated code. The FlightGear/SimGear code base already contains fairly generic and efficient systems and helpers, implemented in C++, that merely need to be better generalized and exposed to Nasal so that they can be used elsewhere. For example, this would enable Scripted AI Objects to use full FDM implementations and/or built-in route manager systems.
Technically, this is also the correct approach, as it allows us to easily reuse existing code that is known to be stable and working correctly, . For details on exposing these C++ systems to Nasal, please refer to Nasal/CppBind. If in doubt, please get in touch via the mailing list or the forum first. |
Started in | 02/2014 |
---|---|
Description | Failure Management Framework |
Maintainer(s) | galvedro, Hooray |
Contributor(s) | User:galvedro |
Status | First milestone merged to fgdata on 06/2014 |
Folders | [2] |
Topic branches: | |
fgdata | [3] |
Objective
Design a framework to unify and simplify failure simulation, both from the system modeler and end user perspective.
Status (12/2014)
- A first stable version of the framework is available since 3.2. See the project sidebar for pointers to the code.
- Necolatis is working on a more capable Canvas based GUI to replace the old one.
- Galvedro is revising the architecture to support aircraft provided wear/damage/failure models.
Current Situation (3.1 and earlier)
All systems and most instruments implemented in the C++ core support basic failure simulation by means of a serviceable property. Generally, when this property is set to false, the system will stop updating itself. Some of these systems may support additional, more elaborate types of failures.
Other than this convention of using a serviceable property, there is no framework on the C++ side with regards to failure simulation. There is, however, a Nasal submodule that can generate random failures by taking user input from the GUI and controlling the relevant properties.
The approach is good, but the main problem is that the supported types of failures are hardcoded both in the Nasal module and the GUI.
Limitations
- The GUI presents a fixed set of failures that can be simulated, regardless of what systems are actually implemented in the aricraft.
- Aircraft can not add their own implemented failures to the set in a clean way.
- Failures are considered boolean by the framework, i.e. either serviceable or not serviceable. There is no way to express intermediate states of failure.
- Only random failures based on time or usage cycles are supported.
- In general, the framework is not extensible.
Proposed improvements
The proposal is to maintain the current schemma of having a Nasal submodule dedicated to failure simulation, but overhaul it to overcome the limitations stated above. In order to accomplish that, we will raise its status to a full fledged Failure Manager.
Here are some desirable traits for the new module:
- To start with, the failure manager should definitively _not_ implement any particular system failure by default, but provide the logic for managing random events or on demand failure mode activation.
- It should also provide a subscription interface so aircraft systems can register their own failure modes. After all, only the aircraft "object" is really aware of what systems are being modeled.
- It should not make any assumptions on how to trigger failure modes (i.e. do not assume a serviceable property). Instead, the Failure Manager should use an opaque interface for setting a "failure level" and leave the details of activation to user scripts.
- The Failure Manager should also support a flexible set of trigger conditions, so failure modes can be programmed to be fired in different ways, for example at a certain altitude.
- GUI dialogs should be generated procedurally, based on the set of supported failure modes that has been declared by the aircraft.
Implementation Details
The current prototype includes three components:
- A Nasal submodule that implements the core Failure Manager.
- A Nasal library of triggers and actuators for programming the Failure Manager.
- A compatibility script that programs the Failure Manager to emulate previous behavior. Currently loaded by default on startup.
The design revolves around the following concepts, all of them implemented as Nasal objects.
- FailureMode
- A failure mode represents one way things can go wrong, for example, a blown tire. A given system may implement more than one failure mode. They store a current failure level that is represented by a floating point number in the range [0, 1] so non boolean failure states can be supported.
- FailureActuator
- Actuators are attached to FailureModes and encapsulate a specific way to activate the failure simulation. They can be simple wrappers that change a property value, but they could also implement more complex operations. By encapsulating the way failure modes are activated, the Failure Manager does not depend on conventions like the serviceable property, and can be easily adapted to control systems designed in different ways.
- Trigger
- A Trigger represents a condition that makes a given FailureMode become active. The current prototype supports the following types: altitude, waytpoint proximity, timeout, MTBF (mean time between failures) and MCBF (mean cycles between failures). More can be easily implemented by extending the FailureMgr.Trigger Nasal interface.
- FailureMgr
- The Failure Manager itself. Keeps a list of supported failure modes that can be added or removed dynamically using a Nasal API. It also offers a Nasal interface for attaching triggers to failure modes (one trigger per failure mode). While enabled, the FailureMgr monitors trigger conditions, and fires the relevant failure modes through their actuators when their trigger becomes active. The FailureMgr can be enabled and disabled on command, both from Nasal and the property tree.
Examples
Here is a speed trigger and a value actuator:
|
##
# Trigger object that will fire when aircraft air-speed is over
# min, specified in knots. Probability of failing will
# be 0% at min speed and 100% at max speed and beyond.
# When the specified property is 0 there is zero chance of failing.
var RandSpeedTrigger = {
parents: [FailureMgr.Trigger],
requires_polling: 1,
new: func(min, max, prop) {
if(min == nil or max == nil)
die("RandSpeedTrigger.new: min and max must be specified");
if(min >= max)
die("RandSpeedTrigger.new: min must be less than max");
if(min < 0 or max <= 0)
die("RandSpeedTrigger.new: min must be positive or zero and max larger than zero");
if(prop == nil or prop == "")
die("RandSpeedTrigger.new: prop must be specified");
var m = FailureMgr.Trigger.new();
m.parents = [RandSpeedTrigger];
m.params["min-speed-kt"] = min;
m.params["max-speed-kt"] = max;
m.params["property"] = prop;
m._speed_prop = "/velocities/airspeed-kt";
return m;
},
to_str: func {
sprintf("Increasing probability of fails between %d and %d kt air-speed",
int(me.params["min-speed-kt"]), int(me.params["max-speed-kt"]))
},
update: func {
if(getprop(me.params["property"]) != 0) {
var speed = getprop(me._speed_prop);
var min = me.params["min-speed-kt"];
var max = me.params["max-speed-kt"];
var speed_d = 0;
if(speed > min) {
speed_d = speed-min;
var delta_factor = 1/(max - min);
var factor = speed <= max ? delta_factor*speed_d : 1;
if(rand() < factor) {
return 1;
}
}
}
return 0;
}
};
##
# Returns an actuator object that will set a property at
# a value when triggered.
var set_value = func(path, value) {
var default = getprop(path);
return {
parents: [FailureMgr.FailureActuator],
set_failure_level: func(level) setprop(path, level > 0 ? value : default),
get_failure_level: func { getprop(path) == default ? 0 : 1 }
}
}
And a jsbsim example of how to use it on individual gears:
|
#front gear locking mechanism might fail when deployed at too high speeds
var prop = "gear/gear[0]/position-norm";
var trigger_gear0 = RandSpeedTrigger.new(350, 500, prop);
var actuator_gear0 = set_value("fdm/jsbsim/gear/unit[0]/z-position", 0.001);
FailureMgr.add_failure_mode("controls/gear0", "Front gear locking mechanism", actuator_gear0);
FailureMgr.set_trigger("controls/gear0", trigger_gear0);
Roadmap
- Replace Nasal/failures.nas with a new module implementing the design proposed above. Wire it to the exising GUI dialogs and ensure backwards compatibility
- Help the Canvas team to develop a Nasal GUI API.
- Replace the hardcoded dialogs with dynamic ones using whatever comes out from the step above.
- Do not load the compatibility layer globally (i.e. by default), but rather load it explicitly from every aircraft (this is gonna be some seriously boring and tedious work).
- Aircraft authors can now start customizing the failure features for their crafts in a clean way.
- Extend the feature set as needs arise (instructor console, additional triggers, ground equipment failure simulation, etc).
Under consideration
- Generalize the trigger system and make it available as a global service. Might be useful for missions/adventures, AI agents, etc.
- Introduce the concept of Wear Models.
Related
Quotes from the forum
Regarding damage modeling WRT combat/bombable, I'd like to check flug's code at some point to see if/how certain parts of it could be generalized there - even just moving useful routines to a dedicated module in $FG_ROOT/Nasal or $FG_ROOT/Aircraft would be a good thing in my opinion. Flug has written some very clever Nasal code as part of the bombable addon, and we should really try to understand how to generalize and integrate the most useful parts so that people working on similar features can reuse his work. EDIT: bombable.nas: https://github.com/bhugh/Bombable/blob/ ... mbable.nas |
I have tested most of it. New failures: McbfTrigger, TimeoutTrigger, MtbfTrigger, AltitudeTrigger, set_unserviceable, set_readonly all works. Old failures: Engine, gear, flaps, electrical, aileron, rudder, elevator, asi, altimeter, attitude still works. I have yet to write a custom trigger or actuator, but I would say this system seems good designed, and very powerful. — Necolatis (Thu Jun 12). Re: How does serviceable and failures work?.
|
We will talk about this a bit later on when the FGUK guys have played with the module as well. But one thing that aircraft developers are demanding in one way or another, is to go one step further and do a more complex system damage/wearing, where failures influence each other, i.e. a structural failure here produces a system failure there and so on. This kind of modeling is likely to be fairly aircraft specific, but we will see. I have given some thinking to a next evolutionary step in this direction, and it is quite tricky to organize in a clean way actually. — galvedro (Fri Jun 13). Re: How does serviceable and failures work?.
|
A fired triggerd remains fired until removed, or rearmed by using trigger.reset() Custom triggers will not play well with the gui at the moment. For this first release I just squeezed the new engine underneath the existing gui, and the compatibility layer responds to it by emulating the former behavior (if it doesn't, it is a bug). That means that only Mtbf and Mcbf triggers are currently supported through the gui. — galvedro (Fri Jun 13). Re: How does serviceable and failures work?.
|