- 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:
parent
65d4a4ba0a
commit
8994a4df3f
1 changed files with 209 additions and 97 deletions
|
@ -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);
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue