1
0
Fork 0

- 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:
mfranz 2007-01-31 15:53:01 +00:00
parent 80b188706f
commit 221c23e18b

View file

@ -1,130 +1,144 @@
# 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
# #
# Properties under /engines/engine[n]: # Properties under /engines/engine[n]:
# + 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; }
total = total + consumed;
fuel.setDoubleValue(0);
}
# Unfortunately, FDM initialization hasn't happened when we start var consumed_fuel = 0;
# running. Wait for the FDM to start running before we set any output foreach (var e; engines) {
# properties. This also prevents us from mucking with FDMs that var fuel = e.getNode("fuel-consumed-lbs");
# don't support this fuel scheme. consumed_fuel += fuel.getValue();
if(total == 0) { return registerTimer(); } fuel.setDoubleValue(0);
if(!initialized) { initialize(); } }
AllTanks = props.globals.getNode("consumables/fuel").getChildren("tank"); if (!consumed_fuel) {
return;
}
# Build a list of selected tanks. Note the filtering for var selected_tanks = [];
# "zero-capacity" tanks. The FlightGear code likes to define foreach (var t; tanks) {
# zombie tanks that have no meaning to the FDM, so we have to take var cap = t.getNode("capacity-gal_us").getValue();
# measures to ignore them here. if (cap > 0.01 and t.getNode("selected").getBoolValue()) {
selectedTanks = []; append(selected_tanks, t);
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);
}
}
}
# 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 {
gals = lbs / ppg; t.getNode("selected").setBoolValue(0);
t.getNode("level-gal_us").setDoubleValue(gals); }
t.getNode("level-lbs").setDoubleValue(lbs); }
} var gals = lbs / ppg;
} t.getNode("level-gal_us").setDoubleValue(gals);
t.getNode("level-lbs").setDoubleValue(lbs);
# Total fuel properties }
gals = lbs = cap = 0; }
foreach(t; AllTanks) {
cap = cap + t.getNode("capacity-gal_us").getValue();
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) { # Total fuel properties
e.getNode("out-of-fuel").setBoolValue(outOfFuel); var lbs = 0;
} var gals = 0;
var cap = 0;
registerTimer(); foreach (var t; tanks) {
lbs += t.getNode("level-lbs").getValue();
gals += t.getNode("level-gal_us").getValue();
cap += t.getNode("capacity-gal_us").getValue();
}
total_lbs.setDoubleValue(lbs);
total_gals.setDoubleValue(gals);
total_norm.setDoubleValue(gals / cap);
foreach (var e; engines) {
e.getNode("out-of-fuel").setBoolValue(out_of_fuel);
}
} }
# Initalize: Make sure all needed properties are present and accounted
# for, and that they have sane default values.
initialized = 0;
initialize = func {
AllEngines = props.globals.getNode("engines").getChildren("engine");
AllTanks = props.globals.getNode("consumables/fuel").getChildren("tank");
foreach(e; AllEngines) { loop = func {
e.getNode("fuel-consumed-lbs", 1).setDoubleValue(0); update();
e.getNode("out-of-fuel", 1).setBoolValue(0); settimer(loop, UPDATE_PERIOD);
}
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;
} }
initDoubleProp = func(node, prop, val) {
if(node.getNode(prop) != nil) { init_double_prop = func(node, prop, val) {
val = num(node.getNode(prop).getValue()); if (node.getNode(prop) != nil) {
} 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 = [];
registerTimer(); 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);
}
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();
});