diff --git a/Aircraft/Generic/soaring-instrumentation-sdk.nas b/Aircraft/Generic/soaring-instrumentation-sdk.nas index de085bc6a..95b8cd77e 100644 --- a/Aircraft/Generic/soaring-instrumentation-sdk.nas +++ b/Aircraft/Generic/soaring-instrumentation-sdk.nas @@ -1,6 +1,20 @@ # Glider Instrumentation Toolkit -# Author: Anton Gomez Alvedro (galvedro) -# Licensed under GNU GPL +# +# Copyright (C) 2013-2014 Anton Gomez Alvedro +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # # Features: # + Total energy compensated variometer @@ -14,16 +28,22 @@ # - add wind correction to speed-to-fly # - final glide computer +io.include("update_loop.nas"); + var MPS2KPH = 3.6; var sqr = func(x) {x * x} var InstrumentComponent = { + parents: [Component], output: 0, - init: func { me.output = 0 }, - update: func(dt) { }, + reset: func { me.output = 0 }, }; +# This alias is for keeping backwards compatibility. +# TODO: Refactor aircrafts that use it and remove this. +var Instrument = UpdateLoop; + # update_prop(property) # Helper generator for updating the given property on every element update # @@ -141,7 +161,7 @@ var TotalEnergyProbe = { }; }, - init: func { + reset: func { me.airspeed = getprop("/velocities/airspeed-kt") * KT2MPS; me.altitude = getprop("/position/altitude-ft") * FT2M; me.output = 0; @@ -215,11 +235,11 @@ var Averager = { m.sum = m.wp = 0; m.buffer = setsize([], buffer_size); - m.init(); + m.reset(); return m; }, - init: func { + reset: func { me.sum = me.wp = me.output = 0; forindex (var i; me.buffer) me.buffer[i] = 0; @@ -384,76 +404,3 @@ var SpeedCmdVario = { if (me.on_update != nil) me.on_update(me.output); } }; - -# Instrument -# Wraps a set of components and updates them periodically. -# Takes care of critical sim signals (reinit, fdm-initialized, speed-up). -# -# var instrument = Instrument.new( -# components: List of components to update in the fast loop. -# update_period: (optional) Time in seconds between updates (fast components). -# enable: (optional) Enable instrument after creation. - -var Instrument = { - - new: func(components, update_period = 0, enable = 1) { - - var m = { parents: [me] }; - m.initialized = 0; - m.enabled = enable; - m.update_period = update_period; - m.time_last = 0; - m.sim_speed = 1; - m.components = (components != nil)? components : []; - - m.timer = maketimer(update_period, - func { call(me.update, [], m) }); - - setlistener("/sim/speed-up", - func(n) { m.sim_speed = n.getValue() }, 1, 0); - - setlistener("sim/signals/reinit", func { - m.timer.stop(); - m.initialized = 0; - }); - - setlistener("sim/signals/fdm-initialized", func { - if (m.timer.isRunning) m.timer.stop(); - call(me.init, [], m); - if (m.enabled) m.timer.start(); - }); - - return m; - }, - - init: func { - me.time_last = getprop("/sim/time/elapsed-sec"); - - foreach (var component; me.components) - component.init(); - - me.initialized = 1; - }, - - update: func { - var time_now = getprop("/sim/time/elapsed-sec"); - var dt = (time_now - me.time_last) * me.sim_speed; - if (dt == 0) return; - - me.time_last = time_now; - - foreach (var component; me.components) - component.update(dt); - }, - - enable: func { - if (me.initialized) me.timer.start(); - me.enabled = 1; - }, - - disable: func { - me.timer.stop(); - me.enabled = 0; - } -}; - diff --git a/Aircraft/Generic/update_loop.nas b/Aircraft/Generic/update_loop.nas new file mode 100644 index 000000000..b552f0df9 --- /dev/null +++ b/Aircraft/Generic/update_loop.nas @@ -0,0 +1,147 @@ +# update_loop.nas - Generic Nasal update loop for implementing sytems, +# instruments or physics simulation. +# +# Copyright (C) 2014 Anton Gomez Alvedro +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +# Component +# +# The update loop accepts a vector of Components that it will update at regular +# intervals. In order to make custom components, you should add Component to +# the parents vector of your object: +# +# var CustomComponent = { +# parents: [Component], +# ... +# }; +# +# Your component shall then implement an "update" and a "reset" methods that +# the UpdateLoop will call when needed. + +var Component = { + reset: func { }, + update: func(dt) { }, +}; + +## +# Helper generator for updating a property on every element update +# +# Example: +# +# var needle = Dampener.new( +# input: probe, +# dampening: 2.8, +# on_update: update_prop("/instrumentation/variometer/te-reading-mps")); +# +# See Aircraft/Instruments-3d/glider/vario/ilec-sc7.nas and +# Aircraft/Generic/soaring-instrumentation-sdk.nas for usage examples. +# You can also refer to the soaring sdk wiki page. + +var update_prop = func(property) { + func(value) { setprop(property, value) } +}; + +# UpdateLoop +# Wraps a set of components and updates them periodically. +# Takes care of critical sim signals (reinit, fdm-initialized, speed-up). + +var UpdateLoop = { + + # UpdateLoop.new(components, [update_period], [enable]) + # + # components: Vector of components to update on every iteration. + # update_period: Time in seconds between updates (optional). + # enable: Enable the loop immediately after creation (optional). + + new: func(components, update_period = 0, enable = 1) { + + var m = { parents: [UpdateLoop] }; + m.initialized = 0; + m.enabled = enable; + m.update_period = update_period; + m.time_last = 0; + m.sim_speed = 1; + m.components = (components != nil)? components : []; + + m.timer = maketimer(update_period, + func { call(me._update, [], m) }); + + m.lst = []; + + append(m.lst, setlistener("/sim/speed-up", + func(n) { m.sim_speed = n.getValue() }, 1, 0)); + + append(m.lst, setlistener("sim/signals/reinit", func { + m.timer.stop(); + m.initialized = 0; + })); + + append(m.lst, setlistener("sim/signals/fdm-initialized", func { + if (m.timer.isRunning) m.timer.stop(); + call(me.reset, [], m); + if (m.enabled) m.timer.start(); + })); + + return m; + }, + + del: func { + foreach (var l; me.lst) removelistener(l); + }, + + ## + # Resets internal state for all components controlled by the loop. + # It is of course responsibility of every component to clean their internal + # state appropriately. + + reset: func { + me.time_last = getprop("/sim/time/elapsed-sec"); + + foreach (var component; me.components) + component.reset(); + + me.initialized = 1; + }, + + ## + # Enables the loop if it was disabled, i.e. the loop will start updating + # the components under control + + enable: func { + if (me.initialized) me.timer.start(); + me.enabled = 1; + }, + + ## + # Disables the loop if it was enabled, i.e. the loop will freeze and its + # components will not get updates until enabled again + + disable: func { + me.timer.stop(); + me.enabled = 0; + }, + + _update: func { + var time_now = getprop("/sim/time/elapsed-sec"); + var dt = (time_now - me.time_last) * me.sim_speed; + if (dt == 0) return; + + me.time_last = time_now; + + foreach (var component; me.components) + component.update(dt); + }, +}; diff --git a/Aircraft/Instruments-3d/glider/vario/ilec-sc7/ilec-sc7.nas b/Aircraft/Instruments-3d/glider/vario/ilec-sc7/ilec-sc7.nas index 1c71b14f3..b9474f51b 100644 --- a/Aircraft/Instruments-3d/glider/vario/ilec-sc7/ilec-sc7.nas +++ b/Aircraft/Instruments-3d/glider/vario/ilec-sc7/ilec-sc7.nas @@ -62,12 +62,12 @@ setlistener("instrumentation/ilec-sc7/sensitivity", func(n) { sc7_needle.dampening = n.getValue() }, 0, 0); # Wrap everything together into an instrument -var fast_instruments = Instrument.new( +var fast_instruments = UpdateLoop.new( update_period: 0, components: [probe, sc7_needle, extra_needle], enable: 1); -var slow_instruments = Instrument.new( +var slow_instruments = UpdateLoop.new( update_period: 1, components: [averager, temperature, lcd_controller], enable: 1);