Difference between revisions of "Canvas EFIS Framework"

From FlightGear wiki
Jump to: navigation, search
m
Line 3: Line 3:
 
{{Template:Canvas Navigation}}
 
{{Template:Canvas Navigation}}
  
== Introduction ==
+
== Foreword ==
Canvas EFIS framework is work in progress. I (jsb) am working on this for the CRJ700 family.  
+
The '''canvas EFIS framework''' (created by jsb) is by-product of the EFIS development
For now, this page will contain design drafts and ideas.
+
done for the CRJ700 family, which uses Rockwell Collins Proline.  
 +
It is published as a separate framework in the hope that it is useful for other aircraft as well,  
 +
however some features may be rather specific.
 +
The biggest motivation and primary design goal was to support "near optimal"
 +
performance but that does not come automatically of course.
  
 
For the bigger picture see also [[Howto:Add an EFIS to your aircraft]].
 
For the bigger picture see also [[Howto:Add an EFIS to your aircraft]].
  
== Design draft ==
+
== Introduction and Overview ==
Some assumptions:
+
An EFIS usually comprises multiple display units (DU for short; CRT or LCD screens) to show all the information
* More than one display unit (DU), e.g. a common airliner config would be six DU: 2x PFD, 2x MFD, 2x EICAS
+
relevant to the pilot (e.g. 2x PFD, 2x MFD, 2x EICAS in the CRJ700).
* Transfer of display sources to different DU so the pilot can handle display faults
+
Some displays like an EICAS / ECAM may show different pages for the systems of the aircraft, they
* Multiple pages per display role, e.g. for EICAS
+
can be select by the pilot via a corresponding control panel.
* Allow EICAS pages to be shown on different / multiple DU (the Rockwell Collins used in the CRJ700 supports this)
+
Furthermore, displays can be swapped in case of a DU fault.
 +
In the CRJ700 the pilot can select display sources by turning the corresponding knobs.
 +
 
 +
'''The EFIS framework provides Nasal classes to handle the following:'''
  
The EFIS framework should provide nasal classes to handle the following:
 
 
=== Display unit ===
 
=== Display unit ===
 
* reference to a 3D object in the cockpit ("display unit") on which the canvas texture shall be displayed
 
* reference to a 3D object in the cockpit ("display unit") on which the canvas texture shall be displayed
 
* power switch property
 
* power switch property
* dim property
 
 
* image source (canvas reference)
 
* image source (canvas reference)
  
=== Image source ===
+
'''Note:''' Dimming of display can be done by defining an animation in the XML going with the 3D model of the DU.
 +
See example below.
 +
 
 +
=== Image source (EFISCanvas) ===
 
* base class for EFIS/EICAS pages handling some SVG stuff  
 
* base class for EFIS/EICAS pages handling some SVG stuff  
* Should be easy to configure, e.g. by providing some common listeners to show/hide or colorize elements
+
* can load a SVG file and create clipping from <name>_clip elements
 +
* allows to register multiple update functions with individual update intervals
 +
* update functions can be en-/disabled by a single property that should reflect the visibility of the canvas (e.g. do not waste CPU with updating pages that are not currently displayed)
 +
* several listener factories for common animations like show/hide, translation, rotation
  
 
=== Display selectors / routing ===
 
=== Display selectors / routing ===
Line 33: Line 44:
 
* Handle EICAS messages efficiently without eating up to much frame rate
 
* Handle EICAS messages efficiently without eating up to much frame rate
 
* Message queue: decouple canvas updates from message arrival
 
* Message queue: decouple canvas updates from message arrival
* semi-automatic listener setup
 
  
 
== Thoughts on implementation ==
 
== Thoughts on implementation ==
Claim: '''EFIS framework should support different update rates / methods for efficency.'''
+
Design goal: '''EFIS framework should support best performance by offering different update methods and update rates for efficency.'''
  
 
=== Update rates ===
 
=== Update rates ===
 
The EFIS/EICAS basically monitors the whole aircraft so it will have to read lots of properties.  
 
The EFIS/EICAS basically monitors the whole aircraft so it will have to read lots of properties.  
For efficency the properties must be grouped into classes already in the design phase, that is, the aircraft developer shall carefully think about how often a property '''changes'''. Some props are written to at frame rate by property rules but that does not mean the value changes every time. Furthermore, not every change has the same relevance, not everything needs to be displayed real time (real time = frame rate).
+
For efficiency the properties must be grouped into different classes already in the design phase, that is, the aircraft developer shall carefully think about how often a property '''changes'''.  
 +
Some props are written to at frame rate by property rules but that does not mean the value changes every time. Furthermore, not every change has the same relevance, not everything needs to be displayed real time (= frame rate).
  
 
{| class="wikitable"
 
{| class="wikitable"
Line 62: Line 73:
  
 
=== Update methods ===
 
=== Update methods ===
* Simple approach is to write an update loop that reads all relevant props, calculates the needed updates and updates the canvas elements (which in the end means writing properties).
+
* Simple approach is to write an update loop that reads all relevant props, calculates the needed updates and updates the canvas elements (which in the end means writing properties) -> tends to be inefficient.
* Property read/write is somehow "expensive" and can cost you a lot of framerate. So the next better idea could be to limit the rate at which the update function is called - usually by a timer with some sensible interval.
+
* Property read/write is somehow "expensive" and can cost you a lot of frame rate. So the next better idea could be to limit the rate at which the update function is called - usually by a timer with some sensible interval.
* If an animation is triggered only by one property and that property is unlikely to change often, remove the prop / animation from the update loop and use a listener instead. The listener may read other props as needed. I have no idea, how much overhead the listener creates so I cannot tell at which point the "does not change often" becomes invalid. I guess that every change interval > 0.5s should be considered ok to be handled by listeners. Please update this article if you have better figures.
+
* If an animation is triggered only by one property and that property is unlikely to change often, remove the prop / animation from the update loop and use a listener instead. The listener may read other props as needed. A listener does not consume any CPU unless the property it listens to has changed, in which case the listener function is run.
* I did not consider complex listeners that monitor a prop sub-tree yet. This could be interesting for animations that depend on more than one prop (still at slow change rates for all props) but this and only this props would have to be in one property sub-tree.
+
 
 +
== Framework documentation ==
 +
This section documents the framework classes and their methods.
 +
 
 +
=== Class EFIS ===
 +
This is the top level class which ties together the different parts like display units, sources and cockpit controls.  
 +
 
 +
==== new() ====
 +
{{Nasal doc
 +
|syntax = new(display_names, object_names, canvas_settings=nil);
 +
|text = Returns a new EFIS object
 +
|param1 = display_names
 +
|param1text = Vector of display names
 +
|param2 = object_names
 +
|param2text = Vector of 3D object names for canvas placement.
 +
|param3 = canvas_settings
 +
|param3text = Optional config hash for canvas that is merged with default settings of EFIS class
 +
}}
 +
 
 +
==== setPowerProp() ====
 +
{{Nasal doc
 +
|syntax = setPowerProp(path);
 +
|text = Creates listener for property path. Power on will start all display update functions, power of will stop them.
 +
|param1 = path
 +
|param1text = Property path to EFIS power property (bool).
 +
}}
 +
 
 +
==== setWindowSize() ====
 +
{{Nasal doc
 +
|syntax = setWindowSize(window_size);
 +
|text = Sets default size for canvas windows
 +
|param1 = window_size
 +
|param1text = Vector [size_x, size_y]
 +
}}
 +
 
 +
==== setDUPowerProps() ====
 +
{{Nasal doc
 +
|syntax = setDUPowerProps(power_props, minimum_power=0);
 +
|text = Sets default size for canvas windows
 +
|param1 = power_props
 +
|param1text = Vector of property paths, must be of same size as display_names given to new().
 +
|param2 = minimum_power
 +
|param2text = Passed to DisplayUnit.setPowerSource()
 +
}}
 +
 
 +
==== addSource() ====
 +
{{Nasal doc
 +
|syntax = addSource(efis_canvas);
 +
|text = Adds a EFISCanvas as display source, returns source ID to be used in mappings.
 +
|param1 = efis_canvas
 +
|param1text = A EFISCanvas instance created with EFISCanvas.new()
 +
}}
 +
 
 +
==== addDisplaySwapControl() ====
 +
{{Nasal doc
 +
|syntax = addDisplaySwapControl(ctrl, mappings, callback=nil);
 +
|text = Adds a listener for "ctrl", activates new source-display-mapping on change. Use this to implement a display swap knob in the cockpit.
 +
|param1 = ctrl
 +
|param1text =  property path to integer prop, e.g. some selector knob in the cockpit
 +
|param1 = mappings
 +
|param1text = vector of display mappings, one mapping per value of ctrl
 +
|param1 = callback
 +
|param1text = optional function that will be called with current ctrl value
 +
}}
 +
 
 +
==== addSourceSelector() ====
 +
{{Nasal doc
 +
|syntax = addSourceSelector(selected, target, sources=nil);
 +
|text = Adds a listener for "selected" which will read the target DU from "target" and sets its source according to "selected". Use this e.g. for a EICAS / ECAM page select panel.
 +
|param1 = selected
 +
|param1text = property (node or path); source number (index to sources vector)
 +
|param1 = target
 +
|param1text = property (node or path); DU number to which the source will be mapped
 +
|param1 = sources
 +
|param1text = optional vector; selected -> source ID (as returned by addSource), defaults to all registered sources
 +
}}
 +
 
 +
==== setDefaultMapping() ====
 +
{{Nasal doc
 +
|syntax = setDefaultMapping(mapping);
 +
|text = Sets and activates a default mapping of sources to display units.
 +
|param1 = mapping
 +
|param1text = Vector [source_id1, source_id2, ...] or hash {DisplayName: source_id}
 +
}}
 +
 
 +
==== displayWindow() ====
 +
{{Nasal doc
 +
|syntax = displayWindow(id);
 +
|text = Opens display unit as canvas window.
 +
|param1 = id
 +
|param1text = Index of display
 +
}}
 +
 
 +
 
 +
=== Class EFISCanvas ===
 +
EFISCanvas manages a single canvas for you.
 +
It offers a bunch of little helpers to make the live of an aircraft developer easier.
 +
These helpers mostly do animation and update stuff on canvas elements in an efficient way.
 +
 
 +
==== new() ====
 +
{{Nasal doc
 +
|syntax = new(name, svgfile);
 +
|text = Returns a new EFISCanvas
 +
|param1 = name
 +
|param1text = Used e.g. in window title (see below)
 +
|param2 = svgfile
 +
|param2text = Filename of a SVG to load. (see also: loadsvg)
 +
}}
 +
 
 +
==== getPath() ====
 +
returns path of canvas
 +
 
 +
==== getCanvas() ====
 +
returns canvas instance
 +
 
 +
==== getRoot() ====
 +
returns root group of the canvas
 +
 
 +
==== setUpdateN() ====
 +
{{Nasal doc
 +
|syntax = setUpdateN(node);
 +
|text = set a node that is checked in all registered update functions, they will only be run, if the value of this node is true
 +
|param1 = node
 +
|param1text = props.node object
 +
}}
 +
 
 +
==== loadsvg() ====
 +
{{Nasal doc
 +
|syntax = loadsvg(file);
 +
|text = Parses the given SVG file into the root group of the EFISCanvas. Clipping is setup for elements that have a corresponding element with the same name extended by "_clip".
 +
|param1 = file
 +
|param1text = filepath passed to canvas.parsesvg
 +
}}
 +
 
 +
==== addUpdateFunction() ====
 +
{{Nasal doc
 +
|syntax = addUpdateFunction(f, interval);
 +
|text = Creates a timer with given interval that runs the given function if the value of the update node is true.
 +
|param1 = f
 +
|param1text = Nasal function to run
 +
|param2 = interval
 +
|param2text = Interval in seconds
 +
}}
 +
 
 +
==== startUpdates() ====
 +
Start all update timers.
 +
 
 +
==== stopUpdates() ====
 +
Stop all update timers.
 +
 
 +
==== getInstr() ====
 +
When updating EFIS displays, there is a need to access properties under /instrumentation very often.
 +
To avoid the rather expensive append operator ("~") and property path lookups, you should use this little helper.
 +
It creates node objects (only once) to access properties like "/instrumentation/"~sys~"["~id~"]/"~prop,
 +
 
 +
{{Nasal doc
 +
|syntax = getInstr(sys, prop, default=0, id=nil);
 +
|text = Helper to quickly access instrumentation properties with this name schema: "/instrumentation/"~sys~"["~id~"]/"~prop
 +
|param1 = sys
 +
|param1text = the system name under /instrumentation
 +
|param2 = prop
 +
|param2text =
 +
|param3 = default
 +
|param3text = Optional default value to return, if getValue() returns nil
 +
|param4 = id
 +
|param4text = Optional override the id of the current EFISCanvas obj (me.id)
 +
}}
 +
 
 +
==== updateTextElement() ====
 +
{{Nasal doc
 +
|syntax = updateTextElement(svgkey, text, color=nil);
 +
|text = Updates a single text element and optionally sets its color.
 +
|param1 = svgkey
 +
|param1text = Name of the text element to update.
 +
|param2 = text
 +
|param2text = new text, passed to setText()
 +
|param3 = color
 +
|param3text = Vector [r,g,b] or valid color name from EFISCanvas.colors
 +
}}
 +
 
 +
==== _updateClip() ====
 +
private function that sets clipping for an element, if there is another element with the same name extended by "_clip".
 +
 
 +
==== Listener factories ====
 +
{{note|
 +
The following listener factories will return a function. The general usage is
 +
setlistener("/some/property/name", _makeListener_xxx(parameters), 1, 0);
 +
 
 +
As usual, the listened-to node is passed into the listener function as first argument and the function will getValue() and do something meaningful with the value.
 +
}}
 +
 
 +
The first argument to the listener factory functions is always svgkey which can
 +
be either a string naming one canvas element or a vector of such strings.
 +
 
 +
 
 +
===== _makeListener_showHide() =====
 +
{{Nasal doc
 +
|syntax = _makeListener_showHide(svgkey, value=nil);
 +
|text = Returns listener to show/hide element(s).
 +
|param1 = svgkey
 +
|param1text = String or vector; the element(s) to update.
 +
|param2 = value
 +
|param2text = optional value to trigger show(); otherwise node.value will be implicitly treated as bool.
 +
}}
 +
 
 +
===== _makeListener_rotate() =====
 +
{{Nasal doc
 +
|syntax = _makeListener_rotate(svgkey, factors=nil);
 +
|text = Returns listener to rotate one or more canvas element(s) by property value. If svgkey is a vector, factors must be a hash having each elemnent in svgkey as a key and the corresponding factor.
 +
|param1 = svgkey
 +
|param1text = String or vector; the element(s) to update.
 +
|param2 = factors=nil
 +
|param2text = Factor for setRotation(value * factor); defaults to 1 if not given
 +
}}
 +
 
 +
===== _makeListener_translate() =====
 +
{{Nasal doc
 +
|syntax = _makeListener_translate(svgkey, fx, fy);
 +
|text = Returns listener to translate one or more canvas element(s) by property value. If svgkey is a vector, fx and fy must be hashes having each elemnent in svgkey as a key and the corresponding factor for translation.
 +
|param1 = svgkey
 +
|param1text = String or vector; the element(s) to update.
 +
|param2 = fx
 +
|param2text = Factor for translation in x direction
 +
|param3 = fy
 +
|param3text = Factor for translation in y direction
 +
}}
 +
 
 +
===== _makeListener_setColor() =====
 +
{{Nasal doc
 +
|syntax = _makeListener_setColor(svgkey, color_true, color_false);
 +
|text = Returns generic listener to change element color. Both color arguments can be either a vector [r,g,b] or a valid name (hash key) for EFISCanvas.colors;
 +
|param1 = svgkey
 +
|param1text = String or vector; element(s) on which to call setColor().
 +
|param2 = color_true
 +
|param2text = Color to use, if getValue() is true.
 +
|param3 = color_false
 +
|param3text = Color to use, if getValue() is false.
 +
}}
 +
 
 +
===== _makeListener_updateText() =====
 +
{{Nasal doc
 +
|syntax = _makeListener_updateText(svgkey, format="%s", default="");
 +
|text = Returns listener to update a canvas text element from property value.
 +
|param1 = svgkey
 +
|param1text = The element to update.
 +
|param2 = format
 +
|param2text = A valid format string for printf()
 +
|param3 = default
 +
|param3text = Value to use, if getValue() returns nil or false.
 +
}}
 +
 
 +
 
 +
=== Methods of class DisplayUnit ===
 +
This class is used by the EFIS class. DisplayUnit creates and places a canvas to a 3D object specified in new().
 +
 
 +
==== new() ====
 +
{{Nasal doc
 +
|syntax = new(name, canvas_settings, screen_obj, parent_obj = nil);
 +
|text = Configure the nasal file to load.
 +
|param1 = name
 +
|param1text = Used e.g. in window title (see below)
 +
|param2 = canvas_settings
 +
|param2text = passed to canvas.new()
 +
|param3 = screen_obj
 +
|param3text = used for canvas placement
 +
|param4 = parent_obj
 +
|param4text = used for canvas placement
 +
}}
 +
 
 +
==== setSource() ====
 +
{{Nasal doc
 +
|syntax = display_unit.setSource(path);
 +
|text = Select a canvas to show on the display unit.
 +
|param1 = path
 +
|param1text = A valid canvas path as returned by the canvas.getPath() method.
 +
}}
 +
 
 +
==== setPowerSource() ====
 +
{{Nasal doc
 +
|syntax = display_unit.setPowerSource(prop, min);
 +
|text = Sets a listener to prop. Display will show only if property value >= min
 +
|param1 = prop
 +
|param1text = Path to property that represents display power supply.
 +
|param2 = min
 +
|param2text = Minimum value of property to show display.
 +
|example1 =
 +
var my_display_unit = DisplayUnit.new("PFD1");
 +
# display turns on when DC power is >= 24 volts
 +
my_display_unit.setPowerSource("/systems/DC/outputs/pfd1", 24);
 +
}}
 +
 
 +
==== asWindow() ====
 +
{{Nasal doc
 +
|syntax = display_unit.asWindow(window_size);
 +
|text = Opens the display in a canvas window.
 +
|param1 = window_size
 +
|param1text = Vector [size_x, size_y]; passed to canvas.Window.new().
 +
}}
 +
 
 +
 
 +
=== EICAS / ECAM message system ===
 +
to be written
 +
 
 +
==== Format for message definitions ====
 +
 
 +
==== Class Pager ====
 +
==== Class MessageClass ====
 +
==== Class MessageSystem ====
 +
 
 +
== HOWTO and Examples ==
 +
to be written

Revision as of 11:32, 8 February 2020

This article is a stub. You can help the wiki by expanding it.

Foreword

The canvas EFIS framework (created by jsb) is by-product of the EFIS development done for the CRJ700 family, which uses Rockwell Collins Proline. It is published as a separate framework in the hope that it is useful for other aircraft as well, however some features may be rather specific. The biggest motivation and primary design goal was to support "near optimal" performance but that does not come automatically of course.

For the bigger picture see also Howto:Add an EFIS to your aircraft.

Introduction and Overview

An EFIS usually comprises multiple display units (DU for short; CRT or LCD screens) to show all the information relevant to the pilot (e.g. 2x PFD, 2x MFD, 2x EICAS in the CRJ700). Some displays like an EICAS / ECAM may show different pages for the systems of the aircraft, they can be select by the pilot via a corresponding control panel. Furthermore, displays can be swapped in case of a DU fault. In the CRJ700 the pilot can select display sources by turning the corresponding knobs.

The EFIS framework provides Nasal classes to handle the following:

Display unit

  • reference to a 3D object in the cockpit ("display unit") on which the canvas texture shall be displayed
  • power switch property
  • image source (canvas reference)

Note: Dimming of display can be done by defining an animation in the XML going with the 3D model of the DU. See example below.

Image source (EFISCanvas)

  • base class for EFIS/EICAS pages handling some SVG stuff
  • can load a SVG file and create clipping from <name>_clip elements
  • allows to register multiple update functions with individual update intervals
  • update functions can be en-/disabled by a single property that should reflect the visibility of the canvas (e.g. do not waste CPU with updating pages that are not currently displayed)
  • several listener factories for common animations like show/hide, translation, rotation

Display selectors / routing

  • Handle input events from cockpit knobs to switch displays / pages

EICAS Message system

  • Handle EICAS messages efficiently without eating up to much frame rate
  • Message queue: decouple canvas updates from message arrival

Thoughts on implementation

Design goal: EFIS framework should support best performance by offering different update methods and update rates for efficency.

Update rates

The EFIS/EICAS basically monitors the whole aircraft so it will have to read lots of properties. For efficiency the properties must be grouped into different classes already in the design phase, that is, the aircraft developer shall carefully think about how often a property changes. Some props are written to at frame rate by property rules but that does not mean the value changes every time. Furthermore, not every change has the same relevance, not everything needs to be displayed real time (= frame rate).

update rate Interval comment
2 0.500s low performance needs
10 0.100s low to med. performance but no fluent animation
20 0.050s
30 0.033s smooth canvas animation but possibly high performance need
60 0.017s

Some examples:

  • PFD contains many "real-time" elements like attitude indicator, speed, altitude etc. They should be updated probably at frame rate (min. 25 Hz) Other elements like radio frequency may be ok to update after 100ms or even 0.5s
  • An EICAS page displaying the door status maybe just fine with one update per second as doors move slowly and you won't see the door from outside and EICAS display inside the cockpit at the same time so a delay of one second does not matter

Update methods

  • Simple approach is to write an update loop that reads all relevant props, calculates the needed updates and updates the canvas elements (which in the end means writing properties) -> tends to be inefficient.
  • Property read/write is somehow "expensive" and can cost you a lot of frame rate. So the next better idea could be to limit the rate at which the update function is called - usually by a timer with some sensible interval.
  • If an animation is triggered only by one property and that property is unlikely to change often, remove the prop / animation from the update loop and use a listener instead. The listener may read other props as needed. A listener does not consume any CPU unless the property it listens to has changed, in which case the listener function is run.

Framework documentation

This section documents the framework classes and their methods.

Class EFIS

This is the top level class which ties together the different parts like display units, sources and cockpit controls.

new()

new(display_names, object_names, canvas_settings=nil);

Returns a new EFIS object

display_names
Vector of display names
object_names
Vector of 3D object names for canvas placement.
canvas_settings
Optional config hash for canvas that is merged with default settings of EFIS class

setPowerProp()

setPowerProp(path);

Creates listener for property path. Power on will start all display update functions, power of will stop them.

path
Property path to EFIS power property (bool).

setWindowSize()

setWindowSize(window_size);

Sets default size for canvas windows

window_size
Vector [size_x, size_y]

setDUPowerProps()

setDUPowerProps(power_props, minimum_power=0);

Sets default size for canvas windows

power_props
Vector of property paths, must be of same size as display_names given to new().
minimum_power
Passed to DisplayUnit.setPowerSource()

addSource()

addSource(efis_canvas);

Adds a EFISCanvas as display source, returns source ID to be used in mappings.

efis_canvas
A EFISCanvas instance created with EFISCanvas.new()

addDisplaySwapControl()

addDisplaySwapControl(ctrl, mappings, callback=nil);

Adds a listener for "ctrl", activates new source-display-mapping on change. Use this to implement a display swap knob in the cockpit.

callback
optional function that will be called with current ctrl value

addSourceSelector()

addSourceSelector(selected, target, sources=nil);

Adds a listener for "selected" which will read the target DU from "target" and sets its source according to "selected". Use this e.g. for a EICAS / ECAM page select panel.

sources
optional vector; selected -> source ID (as returned by addSource), defaults to all registered sources

setDefaultMapping()

setDefaultMapping(mapping);

Sets and activates a default mapping of sources to display units.

mapping
Vector [source_id1, source_id2, ...] or hash {DisplayName: source_id}

displayWindow()

displayWindow(id);

Opens display unit as canvas window.

id
Index of display


Class EFISCanvas

EFISCanvas manages a single canvas for you. It offers a bunch of little helpers to make the live of an aircraft developer easier. These helpers mostly do animation and update stuff on canvas elements in an efficient way.

new()

new(name, svgfile);

Returns a new EFISCanvas

name
Used e.g. in window title (see below)
svgfile
Filename of a SVG to load. (see also: loadsvg)

getPath()

returns path of canvas

getCanvas()

returns canvas instance

getRoot()

returns root group of the canvas

setUpdateN()

setUpdateN(node);

set a node that is checked in all registered update functions, they will only be run, if the value of this node is true

node
props.node object

loadsvg()

loadsvg(file);

Parses the given SVG file into the root group of the EFISCanvas. Clipping is setup for elements that have a corresponding element with the same name extended by "_clip".

file
filepath passed to canvas.parsesvg

addUpdateFunction()

addUpdateFunction(f, interval);

Creates a timer with given interval that runs the given function if the value of the update node is true.

f
Nasal function to run
interval
Interval in seconds

startUpdates()

Start all update timers.

stopUpdates()

Stop all update timers.

getInstr()

When updating EFIS displays, there is a need to access properties under /instrumentation very often. To avoid the rather expensive append operator ("~") and property path lookups, you should use this little helper. It creates node objects (only once) to access properties like "/instrumentation/"~sys~"["~id~"]/"~prop,

getInstr(sys, prop, default=0, id=nil);

Helper to quickly access instrumentation properties with this name schema: "/instrumentation/"~sys~"["~id~"]/"~prop

sys
the system name under /instrumentation
prop
default
Optional default value to return, if getValue() returns nil
id
Optional override the id of the current EFISCanvas obj (me.id)

updateTextElement()

updateTextElement(svgkey, text, color=nil);

Updates a single text element and optionally sets its color.

svgkey
Name of the text element to update.
text
new text, passed to setText()
color
Vector [r,g,b] or valid color name from EFISCanvas.colors

_updateClip()

private function that sets clipping for an element, if there is another element with the same name extended by "_clip".

Listener factories

Note

The following listener factories will return a function. The general usage is setlistener("/some/property/name", _makeListener_xxx(parameters), 1, 0);

As usual, the listened-to node is passed into the listener function as first argument and the function will getValue() and do something meaningful with the value.

The first argument to the listener factory functions is always svgkey which can be either a string naming one canvas element or a vector of such strings.


_makeListener_showHide()
_makeListener_showHide(svgkey, value=nil);

Returns listener to show/hide element(s).

svgkey
String or vector; the element(s) to update.
value
optional value to trigger show(); otherwise node.value will be implicitly treated as bool.
_makeListener_rotate()
_makeListener_rotate(svgkey, factors=nil);

Returns listener to rotate one or more canvas element(s) by property value. If svgkey is a vector, factors must be a hash having each elemnent in svgkey as a key and the corresponding factor.

svgkey
String or vector; the element(s) to update.
factors=nil
Factor for setRotation(value * factor); defaults to 1 if not given
_makeListener_translate()
_makeListener_translate(svgkey, fx, fy);

Returns listener to translate one or more canvas element(s) by property value. If svgkey is a vector, fx and fy must be hashes having each elemnent in svgkey as a key and the corresponding factor for translation.

svgkey
String or vector; the element(s) to update.
fx
Factor for translation in x direction
fy
Factor for translation in y direction
_makeListener_setColor()
_makeListener_setColor(svgkey, color_true, color_false);

Returns generic listener to change element color. Both color arguments can be either a vector [r,g,b] or a valid name (hash key) for EFISCanvas.colors;

svgkey
String or vector; element(s) on which to call setColor().
color_true
Color to use, if getValue() is true.
color_false
Color to use, if getValue() is false.
_makeListener_updateText()
_makeListener_updateText(svgkey, format="%s", default="");

Returns listener to update a canvas text element from property value.

svgkey
The element to update.
format
A valid format string for printf()
default
Value to use, if getValue() returns nil or false.


Methods of class DisplayUnit

This class is used by the EFIS class. DisplayUnit creates and places a canvas to a 3D object specified in new().

new()

new(name, canvas_settings, screen_obj, parent_obj = nil);

Configure the nasal file to load.

name
Used e.g. in window title (see below)
canvas_settings
passed to canvas.new()
screen_obj
used for canvas placement
parent_obj
used for canvas placement

setSource()

display_unit.setSource(path);

Select a canvas to show on the display unit.

path
A valid canvas path as returned by the canvas.getPath() method.

setPowerSource()

display_unit.setPowerSource(prop, min);

Sets a listener to prop. Display will show only if property value >= min

prop
Path to property that represents display power supply.
min
Minimum value of property to show display.

Example

var my_display_unit = DisplayUnit.new("PFD1");
# display turns on when DC power is >= 24 volts
my_display_unit.setPowerSource("/systems/DC/outputs/pfd1", 24);

asWindow()

display_unit.asWindow(window_size);

Opens the display in a canvas window.

window_size
Vector [size_x, size_y]; passed to canvas.Window.new().


EICAS / ECAM message system

to be written

Format for message definitions

Class Pager

Class MessageClass

Class MessageSystem

HOWTO and Examples

to be written