1
0
Fork 0

Merge commit 'refs/merge-requests/265' of https://gitorious.org/fg/fgdata into merge-requests/265

This commit is contained in:
Torsten Dreyer 2015-02-22 21:44:41 +01:00
commit 53dfd54beb
3 changed files with 200 additions and 84 deletions

View file

@ -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,24 +28,35 @@
# - add wind correction to speed-to-fly
# - final glide computer
io.include("updateloop.nas");
var MPS2KPH = 3.6;
var sqr = func(x) {x * x}
var InstrumentComponent = {
parents: [Updatable],
output: 0,
init: func { me.output = 0 },
update: func(dt) { },
reset: func { me.output = 0 },
};
# update_prop(property)
# Helper generator for updating the given property on every element update
# This alias is for keeping backwards compatibility.
# TODO: Refactor aircrafts that use it and remove this.
var Instrument = UpdateLoop;
##
# 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) }
@ -141,7 +166,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 +240,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 +409,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;
}
};

View file

@ -0,0 +1,164 @@
# updateloop.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.
##
# The UpdateLoop accepts a vector of Updatable components that it will call
# at regular intervals. In order to define custom objects to be controlled by
# the loop, the Updatable interface must be implemented:
#
# var MyComponent = {
# parents: [Updatable],
#
# reset: func {
# ...
# },
# update: func(dt) {
# ...
# },
# ...
# };
var Updatable = {
##
# When reset() is called, the component shall clean all internal state and
# reinitialize itself as if starting from scratch.
#
# Reset will be called automatically after a teleport, and then on demand
# when UpdateLoop.reset() is explicitly called.
reset: func { },
##
# Called at regular intervals from the UdateLoop.
# dt: Elapsed time in seconds since the last call.
update: func(dt) { },
};
##
# Wraps a set of user provided Updatable objects and calls 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.
# enable: Enable the loop immediately after creation.
# ignore_fdm: Do not wait for the fdm to be ready for starting the loop.
new: func(components, update_period = 0, enable = 1, ignore_fdm = 0) {
var m = { parents: [UpdateLoop] };
m.initialized = 0;
m.enabled = enable;
m.ignore_fdm = ignore_fdm;
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(n) { m._on_teleport(n) }));
if (ignore_fdm or getprop("sim/signals/fdm-initialized")) {
m.reset();
enable and m.timer.start();
}
if (!ignore_fdm) {
append(m.lst, setlistener("sim/signals/fdm-initialized",
func(n) { m._on_teleport(n) }));
}
return m;
},
del: func {
me.disable();
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;
},
##
# The loop will start updating the components under its control.
enable: func {
if (me.initialized) me.timer.start();
me.enabled = 1;
},
##
# 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);
},
_on_teleport: func(n) {
var signal = n.getName();
if (signal == "reinit" and n.getValue()) {
me.timer.stop();
me.initialized = 0;
}
elsif (me.ignore_fdm or signal == "fdm-initialized") {
me.timer.isRunning and me.timer.stop();
me.reset();
me.enabled and me.timer.start();
}
}
};

View file

@ -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);