1
0
Fork 0

- merge YASim fuel management parts in (should still work with JSBSim as

far as this supports air refueling at all)
- make listeners keep variables up-to-date (for better performance)
- remove the ugly initialization stuff in the main loop, but wait in
  an extra loop for the FDM to come up

This script works now with the a4f, too. The vulcan2 is *supposed* to
work, but there's apparently a bug in it that prevents it.
/systems/refuel/contact is correcly set, and that should be enough for it.
This commit is contained in:
mfranz 2006-08-27 12:25:43 +00:00
parent 65d4a4ba0a
commit 8994a4df3f

View file

@ -3,118 +3,230 @@
# + 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.
# ==================================== timer stuff ===========================================
# set the update period
var UPDATE_PERIOD = 0.3;
UPDATE_PERIOD = 0.3;
# set the timer for the selected function
registerTimer = func {
settimer(arg[0], UPDATE_PERIOD);
} # end function
# =============================== end timer stuff ===========================================
var enabled = nil;
var fuel_freeze = nil;
var ai_enabled = nil;
var engines = nil;
var tanks = nil;
var refuelingN = nil;
var aimodelsN = nil;
initialized = 0;
enabled = 0;
#print ("running aar");
#print (" enabled " , enabled, " initialized ", initialized);
updateTanker = func {
#print ("tanker update running ");
#if (!initialized ) {
#print("calling initialize");
#initialize();}
Refueling = props.globals.getNode("/systems/refuel/contact");
AllAircraft = props.globals.getNode("ai/models").getChildren("aircraft");
AllMultiplayer = props.globals.getNode("ai/models").getChildren("multiplayer");
Aircraft = props.globals.getNode("ai/models/aircraft");
# select all tankers which are in contact. For now we assume that it must be in
# contact with us.
selectedTankers = [];
if ( enabled ) { # check that AI Models are enabled, otherwise don't bother
foreach(a; AllAircraft) {
contact_node = a.getNode("refuel/contact");
id_node = a.getNode("id");
tanker_node = a.getNode("tanker");
contact = contact_node.getValue();
id = id_node.getValue();
tanker = tanker_node.getValue();
#print ("contact ", contact , " tanker " , tanker );
if (tanker and contact) {
append(selectedTankers, a);
}
}
foreach(m; AllMultiplayer) {
contact_node = m.getNode("refuel/contact");
id_node = m.getNode("id");
tanker_node = m.getNode("tanker");
contact = contact_node.getValue();
id = id_node.getValue();
tanker = tanker_node.getValue();
# print (" mp contact ", contact , " tanker " , tanker );
if (tanker and contact) {
append(selectedTankers, m);
}
}
}
#print ("tankers ", size(selectedTankers) );
if ( size(selectedTankers) >= 1 ){
Refueling.setBoolValue(1);
} else {
Refueling.setBoolValue(0);
}
registerTimer(updateTanker);
# initialize property if it doesn't exist, and set node type otherwise
init_prop = func(node, prop, val, type = "double") {
if (node.getNode(prop) != nil) {
val = node.getNode(prop).getValue();
}
node = node.getNode(prop, 1);
if (type == "double") {
node.setDoubleValue(val);
} elsif (type == "bool") {
node.setBoolValue(val);
} elsif (type == "int") {
node.setIntValue(val);
}
}
# Initalize: Make sure all needed properties are present and accounted
# for, and that they have sane default values.
update_loop = func {
# check for contact with tanker aircraft
var tankers = [];
if (ai_enabled) {
foreach (a; aimodelsN.getChildren("aircraft")) {
var contact = a.getNode("refuel/contact").getBoolValue();
var tanker = a.getNode("tanker").getBoolValue();
#var id = a.getNode("id").getValue();
#print("ai '", id, "' contact=", contact, " tanker=", tanker);
if (tanker and contact) {
append(tankers, a);
}
}
foreach (m; aimodelsN.getChildren("multiplayer")) {
var contact = m.getNode("refuel/contact").getBoolValue();
var tanker = m.getNode("tanker").getBoolValue();
#var id = m.getNode("id").getValue();
#print("mp '", id, "' contact=", contact, " tanker=", tanker);
if (tanker and contact) {
append(tankers, m);
}
}
}
var refueling = size(tankers) >= 1;
refuelingN.setBoolValue(refueling);
if (fuel_freeze) {
return settimer(update_loop, UPDATE_PERIOD);
}
# sum up consumed fuel
var total = 0;
foreach (var e; engines) {
total += e.getNode("fuel-consumed-lbs").getValue();
}
# calculate fuel received
if (refueling) {
# assume max flow rate is 6000 lbs/min (for KC135)
var received = 100 * UPDATE_PERIOD;
total -= received;
}
var tanks = props.globals.getNode("consumables/fuel", 1).getChildren("tank");
# make list of selected tanks
var selected_tanks = [];
foreach (var t; tanks) {
var cap = t.getNode("capacity-gal_us", 1).getValue();
if (cap != nil and cap > 0.01 and t.getNode("selected", 1).getBoolValue()) {
append(selected_tanks, t);
}
}
var out_of_fuel = 0;
if (size(selected_tanks) == 0) {
out_of_fuel = 1;
} else {
if (total >= 0) {
var fuelPerTank = total / 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 -= 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()) {
out_of_fuel = 1;
} else {
t.getNode("selected", 1).setBoolValue(0);
}
}
var gals = lbs / ppg;
t.getNode("level-gal_us").setDoubleValue(gals);
t.getNode("level-lbs").setDoubleValue(lbs);
}
} elsif (total < 0) {
#find the number of tanks which can accept fuel
var available = 0;
foreach (var t; selected_tanks) {
var ppg = t.getNode("density-ppg").getValue();
var capacity = t.getNode("capacity-gal_us").getValue() * ppg;
var lbs = t.getNode("level-gal_us").getValue() * ppg;
if (lbs < capacity) {
available += 1;
}
}
if (available > 0) {
var fuelPerTank = total / available;
# add fuel to each available tank
foreach (var t; selected_tanks) {
var ppg = t.getNode("density-ppg").getValue();
var capacity = t.getNode("capacity-gal_us").getValue() * ppg;
var lbs = t.getNode("level-gal_us").getValue() * ppg;
if (capacity - lbs >= fuelPerTank) {
lbs -= fuelPerTank;
} elsif (capacity - lbs < fuelPerTank) {
lbs = capacity;
}
t.getNode("level-gal_us").setDoubleValue(lbs / ppg);
t.getNode("level-lbs").setDoubleValue(lbs);
}
# print ("available ", available , " fuelPerTank " , fuelPerTank);
}
}
}
var gals = 0;
var lbs = 0;
var cap = 0;
foreach (var t; tanks) {
gals += t.getNode("level-gal_us", 1).getValue();
lbs += t.getNode("level-lbs", 1).getValue();
cap += t.getNode("capacity-gal_us", 1).getValue();
}
setprop("/consumables/fuel/total-fuel-gals", gals);
setprop("/consumables/fuel/total-fuel-lbs", lbs);
setprop("/consumables/fuel/total-fuel-norm", gals / cap);
foreach (var e; engines) {
e.getNode("out-of-fuel", 1).setBoolValue(out_of_fuel);
}
settimer(update_loop, UPDATE_PERIOD);
}
initialize = func {
AI_Enabled = props.globals.getNode("sim/ai/enabled");
Refueling = props.globals.getNode("/systems/refuel/contact",1);
Refueling.setBoolValue(0);
enabled = AI_Enabled.getValue();
initialized = 1;
fuel.updateFuel = func {}
refuelingN = props.globals.getNode("/systems/refuel/contact", 1);
refuelingN.setBoolValue(0);
aimodelsN = props.globals.getNode("ai/models", 1);
engines = props.globals.getNode("engines", 1).getChildren("engine");
tanks = props.globals.getNode("consumables/fuel", 1).getChildren("tank");
foreach (var e; engines) {
e.getNode("fuel-consumed-lbs", 1).setDoubleValue(0);
e.getNode("out-of-fuel", 1).setBoolValue(0);
}
foreach (var t; tanks) {
init_prop(t, "level-gal_us", 0);
init_prop(t, "level-lbs", 0);
init_prop(t, "capacity-gal_us", 0.01); # Not zero (div/zero issue)
init_prop(t, "density-ppg", 6.0); # gasoline
init_prop(t, "selected", 1, "bool");
}
setlistener("sim/freeze/fuel", func { fuel_freeze = cmdarg().getBoolValue() }, 1);
setlistener("sim/ai/enabled", func { ai_enabled = cmdarg().getBoolValue() }, 1);
update_loop();
}
initDoubleProp = func {
node = arg[0]; prop = arg[1]; val = arg[2];
if(node.getNode(prop) != nil) {
val = num(node.getNode(prop).getValue());
}
node.getNode(prop, 1).setDoubleValue(val);
wait_for_fdm = func {
if (getprop("/position/altitude-agl-ft")) { # is there a better indicator?
initialize();
} else {
settimer(wait_for_fdm, 1);
}
}
# Fire it up
if (!initialized) {initialize();}
registerTimer(updateTanker);
settimer(wait_for_fdm, 0);