Added crossfeed valve class to aircraft.nas, extended math.nas with min(), max(), and avg()
This commit is contained in:
parent
af24ff2c65
commit
36c48caaf2
2 changed files with 112 additions and 0 deletions
|
@ -1047,6 +1047,93 @@ var HUD = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# crossfeed_valve
|
||||||
|
# =============================================================================
|
||||||
|
# class that creates a fuel tank cross-feed valve. Designed for YASim aircraft;
|
||||||
|
# JSBSim aircraft can simply use systems code within the FDM (see 747-400 for
|
||||||
|
# an example).
|
||||||
|
#
|
||||||
|
# WARNING: this class requires the tank properties to be ready, so call new()
|
||||||
|
# after the FDM is initialized.
|
||||||
|
#
|
||||||
|
# SYNOPSIS:
|
||||||
|
# crossfeed_valve.new(<max_flow_rate>, <property>, <tank>, <tank>, ... );
|
||||||
|
# crossfeed_valve.open(<update>);
|
||||||
|
# crossfeed_valve.close(<update>);
|
||||||
|
#
|
||||||
|
# <max_flow_rate> ... maximum transfer rate between the tanks in lbs/sec
|
||||||
|
# <property> ... property path to use as switch - pass nil to use no such switch
|
||||||
|
# <tank> ... number of a tank to connect - can have unlimited number of tanks connected
|
||||||
|
# <update> ... update switch property when opening/closing valve via Nasal - 0 or 1; by default, 1
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# EXAMPLES:
|
||||||
|
# aircraft.crossfeed_valve.new(0.5, "/controls/fuel/x-feed", 0, 1, 2);
|
||||||
|
#-------
|
||||||
|
# var xfeed = aircraft.crossfeed_valve.new(1, nil, 0, 1);
|
||||||
|
# xfeed.open();
|
||||||
|
#
|
||||||
|
var crossfeed_valve = {
|
||||||
|
new: func(flow_rate, path) {
|
||||||
|
var m = { parents: [crossfeed_valve] };
|
||||||
|
m.valve_open = 0;
|
||||||
|
m.interval = 0.5;
|
||||||
|
m.loopid = -1;
|
||||||
|
m.flow_rate = flow_rate;
|
||||||
|
if (path != nil) {
|
||||||
|
m.switch_node = props.globals.initNode(path, 0, "BOOL");
|
||||||
|
setlistener(path, func(node) {
|
||||||
|
if (node.getBoolValue()) m.open(0);
|
||||||
|
else m.close(0);
|
||||||
|
}, 1, 0);
|
||||||
|
}
|
||||||
|
m.tanks = [];
|
||||||
|
for (var i = 0; i < size(arg); i += 1) {
|
||||||
|
var tank = props.globals.getNode("consumables/fuel/tank[" ~ arg[i] ~ "]");
|
||||||
|
if (tank.getChild("level-lbs") != nil) append(m.tanks, tank);
|
||||||
|
}
|
||||||
|
return m;
|
||||||
|
},
|
||||||
|
open: func(update_prop = 1) {
|
||||||
|
if (me.valve_open == 1) return;
|
||||||
|
if (update_prop and contains(me, "switch_node")) me.switch_node.setBoolValue(1);
|
||||||
|
me.valve_open = 1;
|
||||||
|
me.loopid += 1;
|
||||||
|
settimer(func me._loop_(me.loopid), me.interval);
|
||||||
|
},
|
||||||
|
close: func(update_prop = 1) {
|
||||||
|
if (update_prop and contains(me, "switch_node")) me.switch_node.setBoolValue(0);
|
||||||
|
me.valve_open = 0;
|
||||||
|
},
|
||||||
|
_loop_: func(id) {
|
||||||
|
if (id != me.loopid) return;
|
||||||
|
var average_level = 0;
|
||||||
|
var count = size(me.tanks);
|
||||||
|
for (var i = 0; i < count; i += 1) {
|
||||||
|
var level_node = me.tanks[i].getChild("level-lbs");
|
||||||
|
average_level += level_node.getValue();
|
||||||
|
}
|
||||||
|
average_level /= size(me.tanks);
|
||||||
|
var highest_diff = 0;
|
||||||
|
for (var i = 0; i < count; i += 1) {
|
||||||
|
var level = me.tanks[i].getChild("level-lbs").getValue();
|
||||||
|
var diff = math.abs(average_level - level);
|
||||||
|
if (diff > highest_diff) highest_diff = diff;
|
||||||
|
}
|
||||||
|
for (var i = 0; i < count; i += 1) {
|
||||||
|
var level_node = me.tanks[i].getChild("level-lbs");
|
||||||
|
var capacity = me.tanks[i].getChild("capacity-gal_us").getValue() * me.tanks[i].getChild("density-ppg").getValue();
|
||||||
|
var diff = math.abs(average_level - level_node.getValue());
|
||||||
|
var min_level = math.max(0, level_node.getValue() - me.flow_rate * diff / highest_diff);
|
||||||
|
var max_level = math.min(capacity, level_node.getValue() + me.flow_rate * diff / highest_diff);
|
||||||
|
var level = level_node.getValue() > average_level ? math.max(min_level, average_level) : math.min(max_level, average_level);
|
||||||
|
level_node.setValue(level);
|
||||||
|
}
|
||||||
|
if (me.valve_open) settimer(func me._loop_(id), me.interval);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# module initialization
|
# module initialization
|
||||||
|
|
|
@ -2,6 +2,31 @@ var abs = func(n) { n < 0 ? -n : n }
|
||||||
|
|
||||||
var sgn = func(x) { x < 0 ? -1 : x > 0 }
|
var sgn = func(x) { x < 0 ? -1 : x > 0 }
|
||||||
|
|
||||||
|
var max = func(x) {
|
||||||
|
var n = x;
|
||||||
|
for (var i = 0; i < size(arg); i += 1) {
|
||||||
|
if (arg[i] > n) n = arg[i];
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
var min = func(x) {
|
||||||
|
var n = x;
|
||||||
|
for (var i = 0; i < size(arg); i += 1) {
|
||||||
|
if (arg[i] < n) n = arg[i];
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
var avg = func {
|
||||||
|
var x = 0;
|
||||||
|
for (var i = 0; i < size(arg); i += 1) {
|
||||||
|
x += arg[i];
|
||||||
|
}
|
||||||
|
x /= size(arg);
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
var pow = func(x, y) { exp(y * ln(x)) }
|
var pow = func(x, y) { exp(y * ln(x)) }
|
||||||
|
|
||||||
var mod = func(n, m) {
|
var mod = func(n, m) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue