- aircraft.nas: add variable-interval EWMA lowpass filter class
- dynamic_view.nas: use aircraft.lowpass() class This makes the dynamic view independent of the frame rate. Currently, each filter instance reads out dt on its own, which is a bit inefficient. I'll change that to just one read for all instances later (when Nasal implemented predictable module loading order. :-)
This commit is contained in:
parent
0ff3f5da2b
commit
dabf3f300c
2 changed files with 48 additions and 37 deletions
|
@ -216,6 +216,46 @@ light = {
|
|||
|
||||
|
||||
|
||||
# lowpass
|
||||
# ==============================================================================
|
||||
# class that implements a variable-interval EWMA (Exponentially Weighted
|
||||
# Moving Average) lowpass filter with characteristics independent of the
|
||||
# frame rate.
|
||||
#
|
||||
# SYNOPSIS:
|
||||
# lowpass.new(<coefficient>);
|
||||
#
|
||||
# EXAMPLE:
|
||||
# var lp = lowpass(0.5);
|
||||
# print(lp.filter(10));
|
||||
# print(lp.filter(0));
|
||||
#
|
||||
lowpass = {
|
||||
new : func(coeff) {
|
||||
var m = { parents : [lowpass] };
|
||||
m.dtN = props.globals.getNode("/sim/time/delta-realtime-sec", 1);
|
||||
m.value = nil;
|
||||
m.coeff = abs(coeff);
|
||||
return m;
|
||||
},
|
||||
# filter(raw_value) -> push new value, returns filtered value
|
||||
filter : func(v) {
|
||||
me.filter = me._filter_;
|
||||
me.value = v;
|
||||
},
|
||||
# get() -> returns filtered value
|
||||
get : func {
|
||||
me.value;
|
||||
},
|
||||
_filter_ : func(v) {
|
||||
var dt = me.dtN.getValue();
|
||||
var c = dt / (me.coeff + dt);
|
||||
me.value = v * c + me.value * (1 - c);
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
|
||||
# HUD control class to handle both HUD implementations.
|
||||
#
|
||||
HUDControl = {
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
# acceleration.
|
||||
|
||||
|
||||
|
||||
sin = func(a) { math.sin(a * math.pi / 180.0) }
|
||||
cos = func(a) { math.cos(a * math.pi / 180.0) }
|
||||
sigmoid = func(x) { 1 / (1 + math.exp(-x)) }
|
||||
|
@ -25,34 +24,6 @@ normdeg = func(a) {
|
|||
|
||||
|
||||
|
||||
# Class that implements EWMA (Exponentially Weighted Moving Average)
|
||||
# lowpass filter. Initialize with coefficient, set new value when
|
||||
# you fetch one. filter() pushes new value and returns filtered value,
|
||||
# get() only returns filtered value. A filter coefficient of 0 means
|
||||
# no filtering, coeff = 1 generates a factor 0.1, coeff = 2 a facdtor
|
||||
# 0.01, coeff = 3 a factor 0.001, etc.
|
||||
#
|
||||
LowPass = {
|
||||
new : func(coeff) {
|
||||
var m = { parents : [LowPass] };
|
||||
m.value = nil;
|
||||
m.coeff = 1.0 / pow(10, abs(coeff));
|
||||
return m;
|
||||
},
|
||||
filter : func(v) {
|
||||
me.filter = me._filter_;
|
||||
me.value = v;
|
||||
},
|
||||
_filter_ : func(v) {
|
||||
me.value = v * me.coeff + me.value * (1 - me.coeff);
|
||||
},
|
||||
get : func {
|
||||
me.value;
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
|
||||
# Class that reads a property value, applies factor & offset, clamps to min & max,
|
||||
# and optionally lowpass filters.
|
||||
#
|
||||
|
@ -64,7 +35,7 @@ Input = {
|
|||
m.offset = offset;
|
||||
m.min = min;
|
||||
m.max = max;
|
||||
m.lowpass = filter ? LowPass.new(filter) : nil;
|
||||
m.lowpass = filter ? aircraft.lowpass.new(filter) : nil;
|
||||
return m;
|
||||
},
|
||||
get : func {
|
||||
|
@ -131,19 +102,19 @@ ViewManager = {
|
|||
m.roll_axis = ViewAxis.new("/sim/current-view/goal-roll-offset-deg");
|
||||
|
||||
# accerations are converted to G (one G is subtraced from z-accel)
|
||||
m.ax = Input.new("/accelerations/pilot/x-accel-fps_sec", 0.03108095, 0, 1.1, 0);
|
||||
m.ay = Input.new("/accelerations/pilot/y-accel-fps_sec", 0.03108095, 0, 1.3);
|
||||
m.az = Input.new("/accelerations/pilot/z-accel-fps_sec", -0.03108095, -1, 1.0073);
|
||||
m.ax = Input.new("/accelerations/pilot/x-accel-fps_sec", 0.03108095, 0, 0.58, 0);
|
||||
m.ay = Input.new("/accelerations/pilot/y-accel-fps_sec", 0.03108095, 0, 0.95);
|
||||
m.az = Input.new("/accelerations/pilot/z-accel-fps_sec", -0.03108095, -1, 0.46);
|
||||
|
||||
# velocities are converted to knots
|
||||
m.vx = Input.new("/velocities/uBody-fps", 0.5924838, 0, 1);
|
||||
m.vx = Input.new("/velocities/uBody-fps", 0.5924838, 0, 0.45);
|
||||
m.vy = Input.new("/velocities/vBody-fps", 0.5924838, 0);
|
||||
m.vz = Input.new("/velocities/wBody-fps", 0.5924838, 0);
|
||||
|
||||
# turn WoW bool into smooth values ranging from 0 to 1
|
||||
m.wow = Input.new("/gear/gear/wow", 1, 0, 1.2);
|
||||
m.hdg_change = LowPass.new(1.3);
|
||||
m.ubody = LowPass.new(1.3);
|
||||
m.wow = Input.new("/gear/gear/wow", 1, 0, 0.74);
|
||||
m.hdg_change = aircraft.lowpass.new(0.95);
|
||||
m.ubody = aircraft.lowpass.new(0.95);
|
||||
m.last_heading = m.headingN.getValue();
|
||||
m.size_factor = -getprop("/sim/chase-distance-m") / 25;
|
||||
m.reset();
|
||||
|
|
Loading…
Add table
Reference in a new issue