From 221c23e18bf5e2006fb55fd58b76d44642f0e519 Mon Sep 17 00:00:00 2001 From: mfranz Date: Wed, 31 Jan 2007 15:53:01 +0000 Subject: [PATCH] - 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. --- Nasal/fuel.nas | 226 ++++++++++++++++++++++++++----------------------- 1 file changed, 120 insertions(+), 106 deletions(-) diff --git a/Nasal/fuel.nas b/Nasal/fuel.nas index a09d77317..86654111d 100644 --- a/Nasal/fuel.nas +++ b/Nasal/fuel.nas @@ -1,130 +1,144 @@ # Properties under /consumables/fuel/tank[n]: -# + level-gal_us - OUTPUT ONLY property, do not try to set -# + level-lbs - Current fuel load. Can be set by user code. +# + level-gal_us - Current fuel load. Can be set by user code. +# + level-lbs - OUTPUT ONLY property, do not try to set # + selected - boolean indicating tank selection. # + density-ppg - Fuel density, in lbs/gallon. -# + capacity-gal_us - Tank capacity +# + capacity-gal_us - Tank capacity # # Properties under /engines/engine[n]: # + fuel-consumed-lbs - Output from the FDM, zeroed by this script # + out-of-fuel - boolean, set by this code. -UPDATE_PERIOD = 0.3; -fuelUpdate = func { - if(getprop("/sim/freeze/fuel")) { return registerTimer(); } +var UPDATE_PERIOD = 0.3; - AllEngines = props.globals.getNode("engines").getChildren("engine"); - # Sum the consumed fuel - total = 0; - foreach(e; AllEngines) { - fuel = e.getNode("fuel-consumed-lbs", 1); - consumed = fuel.getValue(); - if(consumed == nil) { consumed = 0; } - total = total + consumed; - fuel.setDoubleValue(0); - } +update = func { + if (fuel_freeze) { + return; + } - # Unfortunately, FDM initialization hasn't happened when we start - # running. Wait for the FDM to start running before we set any output - # properties. This also prevents us from mucking with FDMs that - # don't support this fuel scheme. - if(total == 0) { return registerTimer(); } - if(!initialized) { initialize(); } + var consumed_fuel = 0; + foreach (var e; engines) { + var fuel = e.getNode("fuel-consumed-lbs"); + consumed_fuel += fuel.getValue(); + fuel.setDoubleValue(0); + } - AllTanks = props.globals.getNode("consumables/fuel").getChildren("tank"); + if (!consumed_fuel) { + return; + } - # 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 - # when any one tank is dry. - outOfFuel = 0; - if(size(selectedTanks) == 0) { - outOfFuel = 1; - } else { - fuelPerTank = total / size(selectedTanks); - foreach(t; selectedTanks) { - ppg = t.getNode("density-ppg").getValue(); - lbs = t.getNode("level-gal_us").getValue() * ppg; - lbs = lbs - fuelPerTank; - if(lbs < 0) { - lbs = 0; - # Kill the engines if we're told to, otherwise simply - # deselect the tank. - if(t.getNode("kill-when-empty", 1).getBoolValue()) { outOfFuel = 1; } - else { t.getNode("selected", 1).setBoolValue(0); } - } - 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); + # Subtract fuel from tanks, set auxilliary properties. Set out-of-fuel + # when any one tank is dry. + var out_of_fuel = 0; + if (size(selected_tanks) == 0) { + out_of_fuel = 1; + } else { + var fuel_per_tank = consumed_fuel / size(selected_tanks); + foreach (var t; selected_tanks) { + var ppg = t.getNode("density-ppg").getValue(); + var lbs = t.getNode("level-gal_us").getValue() * ppg; + lbs = lbs - fuel_per_tank; + if (lbs < 0) { + lbs = 0; + # Kill the engines if we're told to, otherwise simply + # deselect the tank. + if (t.getNode("kill-when-empty", 1).getBoolValue()) { + out_of_fuel = 1; + } else { + t.getNode("selected").setBoolValue(0); + } + } + var gals = lbs / ppg; + t.getNode("level-gal_us").setDoubleValue(gals); + t.getNode("level-lbs").setDoubleValue(lbs); + } + } - foreach(e; AllEngines) { - e.getNode("out-of-fuel").setBoolValue(outOfFuel); - } + # Total fuel properties + 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) { - 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) { - if(node.getNode(prop) != nil) { - val = num(node.getNode(prop).getValue()); - } - node.getNode(prop, 1).setDoubleValue(val); + +init_double_prop = func(node, prop, val) { + if (node.getNode(prop) != nil) { + val = num(node.getNode(prop).getValue()); + } + node.getNode(prop, 1).setDoubleValue(val); } -# Fire it up -registerTimer = func { - settimer(fuelUpdate, UPDATE_PERIOD); -} -registerTimer(); + + +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); + } + + 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(); +}); + +