- don't create tanks in empty tank nodes (that nasty native_fdm.cxx causes)
- use Nasal features that were introduced after this code was first written: * var for local variables (and to make clear when a variable is first used) * += operator * listeners to import seldom changing variables and to avoid waiting for the FDM in a loop This new code started as empty file where I added my stuff and then copied parts from the old code, piece by piece. This is why the coding & indentation style has changed. Functionally the code should basically be equivalent.
This commit is contained in:
parent
80b188706f
commit
221c23e18b
1 changed files with 120 additions and 106 deletions
178
Nasal/fuel.nas
178
Nasal/fuel.nas
|
@ -1,6 +1,6 @@
|
||||||
# Properties under /consumables/fuel/tank[n]:
|
# Properties under /consumables/fuel/tank[n]:
|
||||||
# + level-gal_us - OUTPUT ONLY property, do not try to set
|
# + level-gal_us - Current fuel load. Can be set by user code.
|
||||||
# + level-lbs - Current fuel load. Can be set by user code.
|
# + level-lbs - OUTPUT ONLY property, do not try to set
|
||||||
# + selected - boolean indicating tank selection.
|
# + selected - boolean indicating tank selection.
|
||||||
# + density-ppg - Fuel density, in lbs/gallon.
|
# + density-ppg - Fuel density, in lbs/gallon.
|
||||||
# + capacity-gal_us - Tank capacity
|
# + capacity-gal_us - Tank capacity
|
||||||
|
@ -9,122 +9,136 @@
|
||||||
# + fuel-consumed-lbs - Output from the FDM, zeroed by this script
|
# + fuel-consumed-lbs - Output from the FDM, zeroed by this script
|
||||||
# + out-of-fuel - boolean, set by this code.
|
# + out-of-fuel - boolean, set by this code.
|
||||||
|
|
||||||
UPDATE_PERIOD = 0.3;
|
|
||||||
|
|
||||||
fuelUpdate = func {
|
var UPDATE_PERIOD = 0.3;
|
||||||
if(getprop("/sim/freeze/fuel")) { return registerTimer(); }
|
|
||||||
|
|
||||||
AllEngines = props.globals.getNode("engines").getChildren("engine");
|
|
||||||
|
|
||||||
# Sum the consumed fuel
|
update = func {
|
||||||
total = 0;
|
if (fuel_freeze) {
|
||||||
foreach(e; AllEngines) {
|
return;
|
||||||
fuel = e.getNode("fuel-consumed-lbs", 1);
|
}
|
||||||
consumed = fuel.getValue();
|
|
||||||
if(consumed == nil) { consumed = 0; }
|
var consumed_fuel = 0;
|
||||||
total = total + consumed;
|
foreach (var e; engines) {
|
||||||
|
var fuel = e.getNode("fuel-consumed-lbs");
|
||||||
|
consumed_fuel += fuel.getValue();
|
||||||
fuel.setDoubleValue(0);
|
fuel.setDoubleValue(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
# Unfortunately, FDM initialization hasn't happened when we start
|
if (!consumed_fuel) {
|
||||||
# running. Wait for the FDM to start running before we set any output
|
return;
|
||||||
# properties. This also prevents us from mucking with FDMs that
|
|
||||||
# don't support this fuel scheme.
|
|
||||||
if(total == 0) { return registerTimer(); }
|
|
||||||
if(!initialized) { initialize(); }
|
|
||||||
|
|
||||||
AllTanks = props.globals.getNode("consumables/fuel").getChildren("tank");
|
|
||||||
|
|
||||||
# Build a list of selected tanks. Note the filtering for
|
|
||||||
# "zero-capacity" tanks. The FlightGear code likes to define
|
|
||||||
# zombie tanks that have no meaning to the FDM, so we have to take
|
|
||||||
# measures to ignore them here.
|
|
||||||
selectedTanks = [];
|
|
||||||
foreach(t; AllTanks) {
|
|
||||||
cap = t.getNode("capacity-gal_us", 1).getValue();
|
|
||||||
if(cap != nil and cap > 0.01) {
|
|
||||||
if(t.getNode("selected", 1).getBoolValue()) {
|
|
||||||
append(selectedTanks, t);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var selected_tanks = [];
|
||||||
|
foreach (var t; tanks) {
|
||||||
|
var cap = t.getNode("capacity-gal_us").getValue();
|
||||||
|
if (cap > 0.01 and t.getNode("selected").getBoolValue()) {
|
||||||
|
append(selected_tanks, t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Subtract fuel from tanks, set auxilliary properties. Set out-of-fuel
|
# Subtract fuel from tanks, set auxilliary properties. Set out-of-fuel
|
||||||
# when any one tank is dry.
|
# when any one tank is dry.
|
||||||
outOfFuel = 0;
|
var out_of_fuel = 0;
|
||||||
if(size(selectedTanks) == 0) {
|
if (size(selected_tanks) == 0) {
|
||||||
outOfFuel = 1;
|
out_of_fuel = 1;
|
||||||
} else {
|
} else {
|
||||||
fuelPerTank = total / size(selectedTanks);
|
var fuel_per_tank = consumed_fuel / size(selected_tanks);
|
||||||
foreach(t; selectedTanks) {
|
foreach (var t; selected_tanks) {
|
||||||
ppg = t.getNode("density-ppg").getValue();
|
var ppg = t.getNode("density-ppg").getValue();
|
||||||
lbs = t.getNode("level-gal_us").getValue() * ppg;
|
var lbs = t.getNode("level-gal_us").getValue() * ppg;
|
||||||
lbs = lbs - fuelPerTank;
|
lbs = lbs - fuel_per_tank;
|
||||||
if (lbs < 0) {
|
if (lbs < 0) {
|
||||||
lbs = 0;
|
lbs = 0;
|
||||||
# Kill the engines if we're told to, otherwise simply
|
# Kill the engines if we're told to, otherwise simply
|
||||||
# deselect the tank.
|
# deselect the tank.
|
||||||
if(t.getNode("kill-when-empty", 1).getBoolValue()) { outOfFuel = 1; }
|
if (t.getNode("kill-when-empty", 1).getBoolValue()) {
|
||||||
else { t.getNode("selected", 1).setBoolValue(0); }
|
out_of_fuel = 1;
|
||||||
|
} else {
|
||||||
|
t.getNode("selected").setBoolValue(0);
|
||||||
}
|
}
|
||||||
gals = lbs / ppg;
|
}
|
||||||
|
var gals = lbs / ppg;
|
||||||
t.getNode("level-gal_us").setDoubleValue(gals);
|
t.getNode("level-gal_us").setDoubleValue(gals);
|
||||||
t.getNode("level-lbs").setDoubleValue(lbs);
|
t.getNode("level-lbs").setDoubleValue(lbs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Total fuel properties
|
# Total fuel properties
|
||||||
gals = lbs = cap = 0;
|
var lbs = 0;
|
||||||
foreach(t; AllTanks) {
|
var gals = 0;
|
||||||
cap = cap + t.getNode("capacity-gal_us").getValue();
|
var cap = 0;
|
||||||
gals = gals + t.getNode("level-gal_us").getValue();
|
|
||||||
lbs = lbs + t.getNode("level-lbs").getValue();
|
|
||||||
}
|
|
||||||
setprop("/consumables/fuel/total-fuel-gals", gals);
|
|
||||||
setprop("/consumables/fuel/total-fuel-lbs", lbs);
|
|
||||||
setprop("/consumables/fuel/total-fuel-norm", gals/cap);
|
|
||||||
|
|
||||||
foreach(e; AllEngines) {
|
foreach (var t; tanks) {
|
||||||
e.getNode("out-of-fuel").setBoolValue(outOfFuel);
|
lbs += t.getNode("level-lbs").getValue();
|
||||||
|
gals += t.getNode("level-gal_us").getValue();
|
||||||
|
cap += t.getNode("capacity-gal_us").getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
registerTimer();
|
total_lbs.setDoubleValue(lbs);
|
||||||
}
|
total_gals.setDoubleValue(gals);
|
||||||
|
total_norm.setDoubleValue(gals / cap);
|
||||||
|
|
||||||
# Initalize: Make sure all needed properties are present and accounted
|
foreach (var e; engines) {
|
||||||
# for, and that they have sane default values.
|
e.getNode("out-of-fuel").setBoolValue(out_of_fuel);
|
||||||
initialized = 0;
|
|
||||||
initialize = func {
|
|
||||||
AllEngines = props.globals.getNode("engines").getChildren("engine");
|
|
||||||
AllTanks = props.globals.getNode("consumables/fuel").getChildren("tank");
|
|
||||||
|
|
||||||
foreach(e; AllEngines) {
|
|
||||||
e.getNode("fuel-consumed-lbs", 1).setDoubleValue(0);
|
|
||||||
e.getNode("out-of-fuel", 1).setBoolValue(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach(t; AllTanks) {
|
|
||||||
initDoubleProp(t, "level-gal_us", 0);
|
|
||||||
initDoubleProp(t, "level-lbs", 0);
|
|
||||||
initDoubleProp(t, "capacity-gal_us", 0.01); # Not zero (div/zero issue)
|
|
||||||
initDoubleProp(t, "density-ppg", 6.0); # gasoline
|
|
||||||
|
|
||||||
if(t.getNode("selected") == nil) {
|
|
||||||
t.getNode("selected", 1).setBoolValue(1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
initialized = 1;
|
|
||||||
|
|
||||||
|
loop = func {
|
||||||
|
update();
|
||||||
|
settimer(loop, UPDATE_PERIOD);
|
||||||
}
|
}
|
||||||
|
|
||||||
initDoubleProp = func(node, prop, val) {
|
|
||||||
|
init_double_prop = func(node, prop, val) {
|
||||||
if (node.getNode(prop) != nil) {
|
if (node.getNode(prop) != nil) {
|
||||||
val = num(node.getNode(prop).getValue());
|
val = num(node.getNode(prop).getValue());
|
||||||
}
|
}
|
||||||
node.getNode(prop, 1).setDoubleValue(val);
|
node.getNode(prop, 1).setDoubleValue(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
# Fire it up
|
|
||||||
registerTimer = func {
|
|
||||||
settimer(fuelUpdate, UPDATE_PERIOD);
|
var tanks = [];
|
||||||
|
var engines = [];
|
||||||
|
var fuel_freeze = nil;
|
||||||
|
var total_gals = nil;
|
||||||
|
var total_lbs = nil;
|
||||||
|
var total_norm = nil;
|
||||||
|
|
||||||
|
|
||||||
|
var L = _setlistener("/sim/signals/fdm-initialized", func {
|
||||||
|
removelistener(L);
|
||||||
|
|
||||||
|
setlistener("/sim/freeze/fuel", func { fuel_freeze = cmdarg().getBoolValue() }, 1);
|
||||||
|
|
||||||
|
total_gals = props.globals.getNode("/consumables/fuel/total-fuel-gals", 1);
|
||||||
|
total_lbs = props.globals.getNode("/consumables/fuel/total-fuel-lbs", 1);
|
||||||
|
total_norm = props.globals.getNode("/consumables/fuel/total-fuel-norm", 1);
|
||||||
|
|
||||||
|
engines = props.globals.getNode("engines", 1).getChildren("engine");
|
||||||
|
foreach (var e; engines) {
|
||||||
|
e.getNode("fuel-consumed-lbs", 1).setDoubleValue(0);
|
||||||
|
e.getNode("out-of-fuel", 1).setBoolValue(0);
|
||||||
}
|
}
|
||||||
registerTimer();
|
|
||||||
|
foreach (var t; props.globals.getNode("/consumables/fuel", 1).getChildren("tank")) {
|
||||||
|
if (!size(t.getChildren())) {
|
||||||
|
continue; # skip native_fdm.cxx generated zombie tanks
|
||||||
|
}
|
||||||
|
append(tanks, t);
|
||||||
|
init_double_prop(t, "level-gal_us", 0.0);
|
||||||
|
init_double_prop(t, "level-lbs", 0.0);
|
||||||
|
init_double_prop(t, "capacity-gal_us", 0.01); # not zero (div/zero issue)
|
||||||
|
init_double_prop(t, "density-ppg", 6.0); # gasoline
|
||||||
|
|
||||||
|
if (t.getNode("selected") == nil) {
|
||||||
|
t.getNode("selected", 1).setBoolValue(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
loop();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue