1
0
Fork 0
A320-family/Nasal/Effects/icing.nas
2020-05-11 15:57:23 +01:00

215 lines
5.8 KiB
Text

# A3XX Icing System
# Jonathan Redpath (legoboyvdlp)
# Copyright (c) 2020 Josh Davidson (Octal450)
### Ice sensitive components definition.
var Iceable = {
new: func(node) {
var m = { parents: [Iceable] };
m.ice_inches = node.getNode("ice-inches", 1);
m.sensitivity = node.getNode("sensitivity", 1);
var deice_prop = node.getValue("salvage-control");
m.deice = deice_prop ? props.globals.getNode(deice_prop, 1) : nil;
var output_prop = node.getValue("output-property");
m.output = output_prop ? props.globals.getNode(output_prop, 1): nil;
return m;
},
update: func(factor, melt) {
var icing = me.ice_inches.getValue();
if(me.deice != nil and me.deice.getBoolValue()) {
icing += melt;
} else {
icing += factor * me.sensitivity.getValue();
}
if(icing < 0) icing = 0;
me.ice_inches.setValue(icing);
if(me.output != nil) me.output.setValue(icing);
},
};
### Icing parameters computation.
# Environmental parameters of the icing model.
var environment = {
dewpoint: props.globals.getNode("environment/dewpoint-degc"),
temperature: props.globals.getNode("environment/temperature-degc"),
visibility: props.globals.getNode("environment/effective-visibility-m"),
visibLclWx: props.globals.getNode("environment/visibility-m"),
};
var effects = {
frost_inch: props.globals.getNode("environment/aircraft-effects/frost-inch", 1),
frost_norm: props.globals.getNode("environment/aircraft-effects/frost-level"),
};
# Icing factor computation.
var maxSpread = 0;
var severity_factor_table = [
-0.00000166,
0.00000277,
0.00000277,
0.00000554,
0.00001108,
0.00002216,
];
var melt_factor = -0.00005;
var icing_factor = func() {
var temperature = environment.temperature.getValue();
var dewpoint = environment.dewpoint.getValue();
var visibility = environment.visibility.getValue();
var visibLclWx = environment.visibLclWx.getValue();
# Do we create ice?
var spread = temperature - dewpoint;
# freezing fog or low temp and below dp or in advanced wx cloud
var icingCond = ((spread < maxSpread or visibility < 1000 or visibLclWx < 5000)
and temperature < 0);
# todo: turn this into a table or something
var severity = 0;
if (icingCond) {
if (temperature >= -2) {
severity = 1;
} else if (temperature >= -12) {
severity = 3;
} else if (temperature >= -30) {
severity = 5;
} else if (temperature >= -40) {
severity = 3;
} else if (temperature >= -99) {
severity = 1;
}
}
return severity_factor_table[severity];
}
var speed = 0;
var pause = 0;
var windowprobe = 0;
var wingBtn = 0;
var wingFault = 0;
var PSI = 0;
var wowl = 0;
var wowr = 0;
var PitotIcing = 0;
var PitotFailed = 0;
var lengBtn = 0;
var lengFault = 0;
var rengBtn = 0;
var rengFault = 0;
var WingHasBeenTurnedOff = 0;
var GroundModeFinished = 0;
var windowprb = 0;
var stateL = 0;
var stateR = 0;
var iceables = [];
var icingInit = func {
setprop("/controls/ice-protection/windowprobeheat", 0);
setprop("/controls/ice-protection/wingfault", 0);
setprop("/controls/ice-protection/wing", 0);
setprop("/controls/ice-protection/leng", 0);
setprop("/controls/ice-protection/lengfault", 0);
setprop("/controls/ice-protection/reng", 0);
setprop("/controls/ice-protection/rengfault", 0);
setprop("/controls/deice/windowprobeheat", 0);
setprop("/systems/pitot/icing", 0.0);
setprop("/systems/pitot/failed", 1);
iceables = props.globals.getNode("sim/model/icing", 1).getChildren("iceable");
forindex(var i; iceables) {
iceables[i] = Iceable.new(iceables[i]);
}
icing_timer.start();
}
var icingModel = func {
speed = getprop("velocities/airspeed-kt");
pause = getprop("/sim/freeze/master");
windowprobe = getprop("/controls/deice/windowprobeheat");
wingBtn = getprop("/controls/ice-protection/wing");
wingFault = getprop("/controls/ice-protection/wingfault");
#PSI = getprop("/systems/pneumatic/total-psi");
wowl = getprop("gear/gear[1]/wow");
wowr = getprop("gear/gear[2]/wow");
PitotIcing = getprop("/systems/pitot/icing");
PitotFailed = getprop("/systems/pitot/failed");
lengBtn = getprop("/controls/ice-protection/leng");
lengFault = getprop("/controls/ice-protection/lengfault");
rengBtn = getprop("/controls/ice-protection/reng");
rengFault = getprop("/controls/ice-protection/rengfault");
var factor = icing_factor();
foreach(iceable; iceables) {
iceable.update(factor, melt_factor);
}
effects.frost_norm.setDoubleValue(effects.frost_inch.getValue() * 50);
if (PitotIcing > 0.03) {
if (!PitotFailed) {
setprop("/systems/pitot/failed", 1);
}
} else if (PitotIcing < 0.03) {
if (PitotFailed) {
setprop("/systems/pitot/failed", 0);
}
}
# if ((getprop("/systems/electrical/bus/dc-1") == 0 or getprop("/systems/electrical/bus/dc-2") == 0) and getprop("fdm/jsbsim/position/wow") == 0) {
# setprop("/controls/ice-protection/leng", 1);
# setprop("/controls/ice-protection/reng", 1);
# }
#if (getprop("/systems/electrical/bus/dc-ess-shed") == 0) {
# setprop("/controls/ice-protection/wing", 0);
#}
}
##################
# Probe Anti-Ice #
##################
setlistener("/controls/ice-protection/windowprobeheat", func {
windowprb = getprop("/controls/ice-protection/windowprobeheat");
if (windowprb == 0.5) { # if in auto
wowl = getprop("gear/gear[1]/wow");
wowr = getprop("gear/gear[2]/wow");
stateL = getprop("engines/engine[0]/state");
stateR = getprop("engines/engine[1]/state");
if (!wowl or !wowr) {
setprop("/controls/deice/windowprobeheat", 1);
} else if (stateL == 3 or stateR == 3) {
setprop("/controls/deice/windowprobeheat", 1);
}
} else if (windowprb == 1) { # if in ON
setprop("/controls/deice/windowprobeheat", 1);
} else {
setprop("/controls/deice/windowprobeheat", 0);
}
});
###################
# Update Function #
###################
var update_Icing = func {
icingModel();
}
var icing_timer = maketimer(0.2, update_Icing);
icing_timer.simulatedTime = 1;