Revert "Revert "add icing from Seneca (unedited Nasal) and adjust it for the A320. Pitot heat and window probe button now working!""

This reverts commit 391a5620c1.
This commit is contained in:
Jonathan Redpath 2017-06-20 18:58:07 +01:00
parent 391a5620c1
commit b63c501659
14 changed files with 790 additions and 125 deletions

View file

@ -3,7 +3,6 @@
<PropertyList include="Aircraft/Generic/Human/Include/walker-include.xml">
<sim>
<author>Joshua Davidson (it0uchpods) and Jonathan Redpath (legoboyvdlp)</author>
<status>Pre V1.0</status>
@ -22,6 +21,44 @@
<kd type="double">0</kd>
<position-norm type="double">0</position-norm>
</pushback>
<icing>
<iceable>
<name>Wing</name>
<salvage-control>/controls/deice/wing</salvage-control>
<sensitivity type="double">0.8</sensitivity>
<output-property>/fdm/jsbsim/ice/wing</output-property>
</iceable>
<iceable>
<name>LeftEngine</name>
<salvage-control>/controls/deice/lengine</salvage-control>
<sensitivity type="double">0.5</sensitivity>
<output-property>/fdm/jsbsim/ice/lengine</output-property>
</iceable>
<iceable>
<name>RightEngine</name>
<salvage-control>/controls/deice/rengine</salvage-control>
<sensitivity type="double">0.5</sensitivity>
<output-property>/fdm/jsbsim/ice/rengine</output-property>
</iceable>
<iceable>
<name>Windshield</name>
<salvage-control>/controls/deice/windowprobeheat</salvage-control>
<sensitivity type="double">0.5</sensitivity>
<!-- not relevant for fdm, ignore output-property -->
</iceable>
<iceable>
<name>Fuselage</name>
<!-- no salvage control, no deicing of the fuselage -->
<sensitivity type="double">0.3</sensitivity>
<output-property>/fdm/jsbsim/ice/fuselage</output-property>
</iceable>
<iceable>
<name>Pitot tube</name>
<sensitivity type="double">1</sensitivity>
<salvage-control>/controls/deice/windowprobeheat</salvage-control>
<output-property>/systems/pitot/icing</output-property>
</iceable>
</icing>
</model>
<startup>
@ -229,7 +266,6 @@
</fuel>
</consumables>
<payload>
<weight n="0">
<name>Cockpit Crew</name>
@ -287,45 +323,45 @@
</weight>
</payload>
<it-autoflight>
<config>
<altitude-dial-mode>0</altitude-dial-mode>
<roll>
<umin>-0.45</umin>
<umax>0.45</umax>
<kp>0.045</kp>
<kp-vloc>0.07</kp-vloc>
<ti>10.0</ti>
<td>0.00001</td>
</roll>
<pitch>
<umin>-0.20</umin>
<umax>0.20</umax>
<kp>-0.06</kp>
<ti>10.0</ti>
<td>0.00001</td>
</pitch>
<cmd>
<roll-kp>-0.9</roll-kp>
<roll-scale>1.6</roll-scale>
<vorloc>-4.0</vorloc>
<vs>0.01</vs>
<fpa>0.30</fpa>
</cmd>
<autoland>
<kp-pitch>0.035</kp-pitch>
<kp-rudder>-0.05</kp-rudder>
</autoland>
</config>
<output>
<ap1>0</ap1>
<ap2>0</ap2>
</output>
<custom>
<hdg-input>0</hdg-input>
<trk-fpa>0</trk-fpa>
</custom>
</it-autoflight>
<it-autoflight>
<config>
<altitude-dial-mode>0</altitude-dial-mode>
<roll>
<umin>-0.45</umin>
<umax>0.45</umax>
<kp>0.045</kp>
<kp-vloc>0.07</kp-vloc>
<ti>10.0</ti>
<td>0.00001</td>
</roll>
<pitch>
<umin>-0.20</umin>
<umax>0.20</umax>
<kp>-0.06</kp>
<ti>10.0</ti>
<td>0.00001</td>
</pitch>
<cmd>
<roll-kp>-0.9</roll-kp>
<roll-scale>1.6</roll-scale>
<vorloc>-4.0</vorloc>
<vs>0.01</vs>
<fpa>0.30</fpa>
</cmd>
<autoland>
<kp-pitch>0.035</kp-pitch>
<kp-rudder>-0.05</kp-rudder>
</autoland>
</config>
<output>
<ap1>0</ap1>
<ap2>0</ap2>
</output>
<custom>
<hdg-input>0</hdg-input>
<trk-fpa>0</trk-fpa>
</custom>
</it-autoflight>
<it-fbw n="0">
<alpha-hld type="bool">0</alpha-hld>
@ -788,6 +824,10 @@
<canvas_nd>
<file>Aircraft/A320Family/Models/Instruments/ND/canvas/ND.nas</file>
</canvas_nd>
<icing> <!-- leave icing in this -->
<file>Aircraft/A320Family/Nasal/icing.nas</file>
<file>Aircraft/A320Family/Nasal/PitotIcing.nas</file>
</icing>
</nasal>
</PropertyList>

View file

@ -44,7 +44,7 @@
<binding>
<command>nasal</command>
<script>
systems.triggerDoor(systems.doorl1, "doorl1", "PAX left-front (main)");
libraries.triggerDoor(systems.doorl1, "doorl1", "PAX left-front (main)");
</script>
</binding>
</action>
@ -92,7 +92,7 @@
<binding>
<command>nasal</command>
<script>
systems.triggerDoor(systems.doorr1, "doorr1", "PAX right-front");
libraries.triggerDoor(systems.doorr1, "doorr1", "PAX right-front");
</script>
</binding>
</action>
@ -140,7 +140,7 @@
<binding>
<command>nasal</command>
<script>
systems.triggerDoor(systems.doorl3, "doorl3", "PAX left");
libraries.triggerDoor(systems.doorl3, "doorl3", "PAX left");
</script>
</binding>
</action>
@ -188,7 +188,7 @@
<binding>
<command>nasal</command>
<script>
systems.triggerDoor(systems.doorr3, "doorr3", "PAX right");
libraries.triggerDoor(systems.doorr3, "doorr3", "PAX right");
</script>
</binding>
</action>
@ -238,7 +238,7 @@
<binding>
<command>nasal</command>
<script>
systems.triggerDoor(systems.cargofwd, "cargofwd", "forward cargo");
libraries.triggerDoor(systems.cargofwd, "cargofwd", "forward cargo");
</script>
</binding>
</action>
@ -273,7 +273,7 @@
<binding>
<command>nasal</command>
<script>
systems.triggerDoor(systems.cargoaft, "cargoaft", "aft cargo");
libraries.triggerDoor(systems.cargoaft, "cargoaft", "aft cargo");
</script>
</binding>
</action>

View file

@ -44,7 +44,7 @@
<binding>
<command>nasal</command>
<script>
systems.triggerDoor(systems.doorl1, "doorl1", "PAX left-front (main)");
libraries.triggerDoor(systems.doorl1, "doorl1", "PAX left-front (main)");
</script>
</binding>
</action>
@ -92,7 +92,7 @@
<binding>
<command>nasal</command>
<script>
systems.triggerDoor(systems.doorr1, "doorr1", "PAX right-front");
libraries.triggerDoor(systems.doorr1, "doorr1", "PAX right-front");
</script>
</binding>
</action>
@ -140,7 +140,7 @@
<binding>
<command>nasal</command>
<script>
systems.triggerDoor(systems.doorl4, "doorl4", "PAX left-back");
libraries.triggerDoor(systems.doorl4, "doorl4", "PAX left-back");
</script>
</binding>
</action>
@ -188,7 +188,7 @@
<binding>
<command>nasal</command>
<script>
systems.triggerDoor(systems.doorr4, "doorr4", "PAX right-back");
libraries.triggerDoor(systems.doorr4, "doorr4", "PAX right-back");
</script>
</binding>
</action>

View file

@ -44,7 +44,7 @@
<binding>
<command>nasal</command>
<script>
systems.triggerDoor(systems.doorl1, "doorl1", "PAX left-front (main)");
libraries.triggerDoor(systems.doorl1, "doorl1", "PAX left-front (main)");
</script>
</binding>
</action>
@ -92,7 +92,7 @@
<binding>
<command>nasal</command>
<script>
systems.triggerDoor(systems.doorr1, "doorr1", "PAX right-front");
libraries.triggerDoor(systems.doorr1, "doorr1", "PAX right-front");
</script>
</binding>
</action>
@ -140,7 +140,7 @@
<binding>
<command>nasal</command>
<script>
systems.triggerDoor(systems.doorl4, "doorl4", "PAX left-back");
libraries.triggerDoor(systems.doorl4, "doorl4", "PAX left-back");
</script>
</binding>
</action>
@ -188,7 +188,7 @@
<binding>
<command>nasal</command>
<script>
systems.triggerDoor(systems.doorr4, "doorr4", "PAX right-back");
libraries.triggerDoor(systems.doorr4, "doorr4", "PAX right-back");
</script>
</binding>
</action>

View file

@ -44,7 +44,7 @@
<binding>
<command>nasal</command>
<script>
systems.triggerDoor(systems.doorl1, "doorl1", "PAX left-front (main)");
libraries.triggerDoor(systems.doorl1, "doorl1", "PAX left-front (main)");
</script>
</binding>
</action>
@ -92,7 +92,7 @@
<binding>
<command>nasal</command>
<script>
systems.triggerDoor(systems.doorr1, "doorr1", "PAX right-front");
libraries.triggerDoor(systems.doorr1, "doorr1", "PAX right-front");
</script>
</binding>
</action>
@ -140,7 +140,7 @@
<binding>
<command>nasal</command>
<script>
systems.triggerDoor(systems.doorl2, "doorl2", "PAX left (main)");
libraries.triggerDoor(systems.doorl2, "doorl2", "PAX left (main)");
</script>
</binding>
</action>
@ -188,7 +188,7 @@
<binding>
<command>nasal</command>
<script>
systems.triggerDoor(systems.doorr2, "doorr2", "PAX right");
libraries.triggerDoor(systems.doorr2, "doorr2", "PAX right");
</script>
</binding>
</action>
@ -236,7 +236,7 @@
<binding>
<command>nasal</command>
<script>
systems.triggerDoor(systems.doorl3, "doorl3", "PAX left");
libraries.triggerDoor(systems.doorl3, "doorl3", "PAX left");
</script>
</binding>
</action>
@ -284,7 +284,7 @@
<binding>
<command>nasal</command>
<script>
systems.triggerDoor(systems.doorr3, "doorr3", "PAX right");
libraries.triggerDoor(systems.doorr3, "doorr3", "PAX right");
</script>
</binding>
</action>
@ -332,7 +332,7 @@
<binding>
<command>nasal</command>
<script>
systems.triggerDoor(systems.doorl4, "doorl4", "PAX left-back");
libraries.triggerDoor(systems.doorl4, "doorl4", "PAX left-back");
</script>
</binding>
</action>
@ -380,7 +380,7 @@
<binding>
<command>nasal</command>
<script>
systems.triggerDoor(systems.doorr4, "doorr4", "PAX right-back");
libraries.triggerDoor(systems.doorr4, "doorr4", "PAX right-back");
</script>
</binding>
</action>
@ -430,7 +430,7 @@
<binding>
<command>nasal</command>
<script>
systems.triggerDoor(systems.cargofwd, "cargofwd", "forward cargo");
libraries.triggerDoor(systems.cargofwd, "cargofwd", "forward cargo");
</script>
</binding>
</action>
@ -465,7 +465,7 @@
<binding>
<command>nasal</command>
<script>
systems.triggerDoor(systems.cargoaft, "cargoaft", "aft cargo");
libraries.triggerDoor(systems.cargoaft, "cargoaft", "aft cargo");
</script>
</binding>
</action>
@ -498,7 +498,7 @@
<binding>
<command>nasal</command>
<script>
systems.triggerDoor(systems.cargobulk, "cargobulk", "bulk cargo");
libraries.triggerDoor(systems.cargobulk, "cargobulk", "bulk cargo");
</script>
</binding>
</action>

View file

@ -44,7 +44,7 @@
<binding>
<command>nasal</command>
<script>
systems.triggerDoor(systems.doorl1, "doorl1", "PAX left-front (main)");
libraries.triggerDoor(systems.doorl1, "doorl1", "PAX left-front (main)");
</script>
</binding>
</action>
@ -92,7 +92,7 @@
<binding>
<command>nasal</command>
<script>
systems.triggerDoor(systems.doorr1, "doorr1", "PAX right-front");
libraries.triggerDoor(systems.doorr1, "doorr1", "PAX right-front");
</script>
</binding>
</action>
@ -140,7 +140,7 @@
<binding>
<command>nasal</command>
<script>
systems.triggerDoor(systems.doorl2, "doorl2", "PAX left (main)");
libraries.triggerDoor(systems.doorl2, "doorl2", "PAX left (main)");
</script>
</binding>
</action>
@ -188,7 +188,7 @@
<binding>
<command>nasal</command>
<script>
systems.triggerDoor(systems.doorr2, "doorr2", "PAX right");
libraries.triggerDoor(systems.doorr2, "doorr2", "PAX right");
</script>
</binding>
</action>
@ -236,7 +236,7 @@
<binding>
<command>nasal</command>
<script>
systems.triggerDoor(systems.doorl3, "doorl3", "PAX left");
libraries.triggerDoor(systems.doorl3, "doorl3", "PAX left");
</script>
</binding>
</action>
@ -284,7 +284,7 @@
<binding>
<command>nasal</command>
<script>
systems.triggerDoor(systems.doorr3, "doorr3", "PAX right");
libraries.triggerDoor(systems.doorr3, "doorr3", "PAX right");
</script>
</binding>
</action>
@ -332,7 +332,7 @@
<binding>
<command>nasal</command>
<script>
systems.triggerDoor(systems.doorl4, "doorl4", "PAX left-back");
libraries.triggerDoor(systems.doorl4, "doorl4", "PAX left-back");
</script>
</binding>
</action>
@ -380,7 +380,7 @@
<binding>
<command>nasal</command>
<script>
systems.triggerDoor(systems.doorr4, "doorr4", "PAX right-back");
libraries.triggerDoor(systems.doorr4, "doorr4", "PAX right-back");
</script>
</binding>
</action>
@ -430,7 +430,7 @@
<binding>
<command>nasal</command>
<script>
systems.triggerDoor(systems.cargofwd, "cargofwd", "forward cargo");
libraries.triggerDoor(systems.cargofwd, "cargofwd", "forward cargo");
</script>
</binding>
</action>
@ -465,7 +465,7 @@
<binding>
<command>nasal</command>
<script>
systems.triggerDoor(systems.cargoaft, "cargoaft", "aft cargo");
libraries.triggerDoor(systems.cargoaft, "cargoaft", "aft cargo");
</script>
</binding>
</action>
@ -498,7 +498,7 @@
<binding>
<command>nasal</command>
<script>
systems.triggerDoor(systems.cargobulk, "cargobulk", "bulk cargo");
libraries.triggerDoor(systems.cargobulk, "cargobulk", "bulk cargo");
</script>
</binding>
</action>

View file

@ -3587,6 +3587,79 @@
</center>
</animation>
<!-- Anti-ice -->
<!-- Window Heat and Probe Button -->
<!-- 0.5 is auto, 1 is on -->
<animation>
<type>select</type>
<object-name>PrbWinHeatBtn2O</object-name>
<condition>
<or>
<equals>
<property>/controls/switches/windowprobeheat</property>
<value>1</value>
</equals>
<equals>
<property>/controls/switches/annun-test</property>
<value>1</value>
</equals>
</or>
</condition>
</animation>
<animation>
<type>select</type>
<object-name>PrbWinHeatBtn2</object-name>
<condition>
<less-than-equals>
<property>/controls/switches/windowprobeheat</property>
<value>0.5</value>
</less-than-equals>
</condition>
</animation>
<animation>
<name>Window Probe Heat Toggle</name>
<type>pick</type>
<object-name>PrbWinHeatBtn2</object-name>
<object-name>PrbWinHeatBtn2O</object-name>
<object-name>PrbWinHeatBtn1</object-name>
<action>
<button>0</button>
<repeatable>false</repeatable>
<binding>
<condition>
<or>
<greater-than-equals>
<property>/systems/electrical/battery1-amps</property>
<value>120</value>
</greater-than-equals>
<greater-than-equals>
<property>/systems/electrical/battery2-amps</property>
<value>120</value>
</greater-than-equals>
<greater-than-equals>
<property>/systems/electrical/bus/dc1</property>
<value>25</value>
</greater-than-equals>
<greater-than-equals>
<property>/systems/electrical/bus/dc2</property>
<value>25</value>
</greater-than-equals>
</or>
</condition>
<command>property-cycle</command>
<property>/controls/switches/windowprobeheat</property>
<value>0.5</value>
<value>1</value>
</binding>
<binding>
<command>nasal</command>
<script>setprop("/sim/sounde/oh-btn", 1);</script>
</binding>
</action>
</animation>
<!-- APU -->
<animation>
<name>APU master switch pick</name>

View file

@ -8,7 +8,53 @@ MATERIAL "OHPanelOnBat" rgb 0.8 0.8 0.8 amb 1 1 1 emis 1 1 1 spec 0.5 0.5 0.5
MATERIAL "Switch" rgb 0.678431 0.678431 0.678431 amb 0.678431 0.678431 0.678431 emis 0 0 0 spec 0 0 0 shi 32 trans 0.004
MATERIAL "ac3dmat1" rgb 1 1 1 amb 1 1 1 emis 0 0 0 spec 1 1 1 shi 128 trans 0
OBJECT world
kids 266
kids 267
OBJECT poly
name "PrbWinHeatBtn2O"
loc 0.000113685 -5.00064e-005 -4.99785e-005
data 8
Cube.032
texture "buttons2.png"
crease 30.000000
numvert 8
-0.01 -0.2182 -0.0109
-0.01 -0.2182 0.0091
-0.007 -0.2182 0.0091
-0.007 -0.2182 -0.0109
-0.01 -0.2282 -0.0109
-0.01 -0.2282 0.0091
-0.007 -0.2282 0.0091
-0.007 -0.2282 -0.0109
numsurf 4
SURF 0x0
mat 4
refs 4
3 0.5 0.75
7 0.5 0.5
4 0.5 0.5
0 0.5 0.75
SURF 0x0
mat 4
refs 4
6 0 0.5
2 9.31321e-008 0.75
1 9.31321e-008 0.75
5 0 0.5
SURF 0x0
mat 4
refs 4
7 0.5 0.5
3 0.5 0.75
2 9.31321e-008 0.75
6 0 0.5
SURF 0x0
mat 4
refs 4
7 0.5 0.5
6 0 0.5
5 0 0.5
4 0.5 0.5
kids 0
OBJECT poly
name "FuelXfeedBtn1A"
loc 0.000175806 0.13925 0.04185
@ -27946,52 +27992,6 @@ refs 4
2 9.31321e-008 1
kids 0
OBJECT poly
name "PrbWinHeatBtn2"
loc 0.000113685 -5.00064e-005 -4.99785e-005
data 8
Cube.032
texture "buttons.png"
crease 30.000000
numvert 8
-0.01 -0.2182 -0.0109
-0.01 -0.2182 0.0091
-0.007 -0.2182 0.0091
-0.007 -0.2182 -0.0109
-0.01 -0.2282 -0.0109
-0.01 -0.2282 0.0091
-0.007 -0.2282 0.0091
-0.007 -0.2282 -0.0109
numsurf 4
SURF 0x0
mat 4
refs 4
3 0.5 0.75
7 0.5 0.5
4 0.5 0.5
0 0.5 0.75
SURF 0x0
mat 4
refs 4
6 0 0.5
2 9.31321e-008 0.75
1 9.31321e-008 0.75
5 0 0.5
SURF 0x0
mat 4
refs 4
7 0.5 0.5
3 0.5 0.75
2 9.31321e-008 0.75
6 0 0.5
SURF 0x0
mat 4
refs 4
7 0.5 0.5
6 0 0.5
5 0 0.5
4 0.5 0.5
kids 0
OBJECT poly
name "RFuelTank1Btn1"
loc 0.000113685 -5.00064e-005 -4.99785e-005
data 8
@ -35059,3 +35059,49 @@ refs 3
12 0 0
0 0 0
kids 0
OBJECT poly
name "PrbWinHeatBtn2"
loc 0.000113685 -5.00064e-005 -4.99785e-005
data 8
Cube.032
texture "buttons.png"
crease 30.000000
numvert 8
-0.007 -0.2282 -0.0109
-0.007 -0.2282 0.0091
-0.01 -0.2282 0.0091
-0.01 -0.2282 -0.0109
-0.007 -0.2182 -0.0109
-0.007 -0.2182 0.0091
-0.01 -0.2182 0.0091
-0.01 -0.2182 -0.0109
numsurf 4
SURF 0x0
mat 4
refs 4
0 0.5 0.5
1 0 0.5
2 0 0.5
3 0.5 0.5
SURF 0x0
mat 4
refs 4
0 0.5 0.5
4 0.5 0.75
5 9.31321e-008 0.75
1 0 0.5
SURF 0x0
mat 4
refs 4
1 0 0.5
5 9.31321e-008 0.75
6 9.31321e-008 0.75
2 0 0.5
SURF 0x0
mat 4
refs 4
4 0.5 0.75
0 0.5 0.5
3 0.5 0.5
7 0.5 0.75
kids 0

80
Nasal/PitotIcing.nas Normal file
View file

@ -0,0 +1,80 @@
#############################################################################
# This file is part of FlightGear, the free flight simulator
# http://www.flightgear.org/
#
# Copyright (C) 2009 Torsten Dreyer, Torsten (at) t3r _dot_ de
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#############################################################################
#########################################################################################
# Fail the airspeed indicator due to icing of the pitot tube
# Maintainer: Torsten Dreyer (Torsten at t3r dot de)
#
# inputs
# /instrumentation/airspeed-indicator[n]/icing
#
# outputs
# /instrumentation/airspeed-indicator/serviceable
# /instrumentation/airspeed-indicator/indicated-speed-kt
#########################################################################################
var PitotIcingHandler = {};
PitotIcingHandler.new = func {
var m = {};
m.parents = [PitotIcingHandler];
m.failAtIcelevel = arg[1];
m.baseNodeName = "/systems/pitot[" ~ arg[0] ~ "]";
print( "creating PitotIcingHandler for " ~ m.baseNodeName );
m.baseN = props.globals.getNode( m.baseNodeName );
m.icingN = m.baseN.initNode( "icing", 0.0 );
m.serviceableN = m.baseN.initNode( "serviceable", 1, "BOOL" );
setlistener( m.icingN, func { m.listener() } );
return m;
};
#########################################################################################
# The handler. Check if ice is above threshold, then fail the device
#########################################################################################
PitotIcingHandler.listener = func {
if( me.icingN.getValue() < me.failAtIcelevel ) {
# everything is fine
if( me.serviceableN.getBoolValue() == 0 ) {
# if the inidcator failed before, re-enable it
print( me.baseNodeName ~ " is functional again" );
me.serviceableN.setBoolValue( 1 );
}
} else {
# pitot is iced
if( me.serviceableN.getBoolValue() != 0 ) {
# if the indicator was servicable before, fail it now
print( me.baseNodeName ~ " is failing" );
me.serviceableN.setBoolValue( 0 );
}
}
};
# Fail pitot at 0.03" of ice
PitotIcingHandler.new( 0, 0.03 );

276
Nasal/icing.nas Normal file
View file

@ -0,0 +1,276 @@
#############################################################################
# This file is part of FlightGear, the free flight simulator
# http://www.flightgear.org/
#
# Copyright (C) 2009 Torsten Dreyer, Torsten (at) t3r _dot_ de
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#############################################################################
#########################################################################################
# this are the helper functions to model structural icing on airplanes
# Maintainer: Torsten Dreyer (Torsten at t3r dot de)
#
# Simple model: we listen to temperature and dewpoint. If the difference (spread)
# is near zero and temperature is below zero, icing may occour.
#
# inputs
# /environment/dewpoint-degc
# /environment/temperature-degc
# /environment/effective-visibility-m
# /velocities/airspeed-kt
# /environment/icing/max-spread-degc default: 0.1
#
# outputs
# /environment/icing/icing-severity numeric value of icing severity
# /environment/icing/icing-severity-name textual representation of icing severity one of
# none,trace,light,moderate,severe
# /environment/icing/icing-factor ammound of ice accumulation per NAM
#########################################################################
# implementation of the global icemachine
#########################################################################
var ICING_NONE = 0;
var ICING_TRACE = 1;
var ICING_LIGHT = 2;
var ICING_MODERATE = 3;
var ICING_SEVERE = 4;
# these are the names for the icing severities
var ICING_CATEGORY = [ "none", "trace", "light", "moderate", "severe" ];
# the ice accumulating factors. Inches per nautical air mile flown
var ICING_FACTOR = [
# none: sublimating 0.3" / 80NM
-0.3/80,
# traces: 0.5" / 80NM
0.5/80.0,
# light: 0.5" / 40NM
0.5/40.0,
# moderate: 0.5" / 20NM
0.5/20.0,
#severe: 0.5" / 10NM
0.5/10
];
# since we don't know the LWC of our clouds, just define some severities
# depending on temperature and a random offset
# format: upper temperatur, lower temperatur, minimum severity, maximum severity
var ICING_TEMPERATURE = [
[ 999, 0, ICING_NONE, ICING_NONE ],
[ 0, -2, ICING_NONE, ICING_MODERATE ],
[ -2, -12, ICING_LIGHT, ICING_SEVERE ],
[ -12, -20, ICING_LIGHT, ICING_MODERATE ],
[ -20, -30, ICING_TRACE, ICING_LIGHT ],
[ -30, -99, ICING_TRACE, ICING_NONE ]
];
var dewpointN = props.globals.getNode( "/environment/dewpoint-degc" );
var temperatureN = props.globals.getNode( "/environment/temperature-degc" );
var speedN = props.globals.getNode( "/velocities/airspeed-kt" );
var icingRootN = props.globals.getNode( "/environment/icing", 1 );
var visibilityN = props.globals.getNode( "/environment/effective-visibility-m" );
var severityN = icingRootN.initNode( "icing-severity", ICING_NONE, "INT" );
var severityNameN = icingRootN.initNode( "icing-severity-name", ICING_CATEGORY[severityN.getValue()] );
var icingFactorN = icingRootN.initNode( "icing-factor", 0.0 );
var maxSpreadN = icingRootN.initNode( "max-spread-degc", 0.1 );
var setSeverity = func {
var value = arg[0];
if( severityN.getValue() != value ) {
severityN.setValue( value );
severityNameN.setValue( ICING_CATEGORY[value] );
}
}
#########################################################################################
# These are objects that are subject to icing
# inputs under /sim/model/icing/iceable (multiple instances allowed)
# ./name # name of this object, more or less useless
# ./salvage-control # name of a boolean property that salvages from ice
# ./output-property # the name of the property where the ice amount is written to
# ./sensitivity # a multiplier for the ice accumulation
#
# outputs
# ./ice-inches # the amount of ice in inches OR
# [property named by output-property] # the amount of ice in inches
#########################################################################################
var IceSensitiveElement = {};
IceSensitiveElement.new = func {
var obj = {};
obj.parents = [IceSensitiveElement];
obj.node = arg[0];
obj.nameN = obj.node.initNode( "name", "noname" );
var n = obj.node.getNode( "salvage-control", 0 );
obj.controlN = nil;
if( n != nil ) {
n = n.getValue();
if( n != nil ) {
obj.controlN = props.globals.initNode( n, 0, "BOOL" );
}
}
obj.sensitivityN = obj.node.initNode( "sensitivity", 1.0 );
obj.iceAmountN = nil;
n = obj.node.getNode( "output-property", 0 );
if( n != nil ) {
n = n.getValue();
if( n != nil ) {
obj.iceAmountN = props.globals.initNode( n, 0.0 );
}
}
if( obj.iceAmountN == nil ) {
obj.iceAmountN = obj.node.initNode( "ice-inches", 0.0 );
}
return obj;
};
#####################################################################
# this gets called from the icemachine on each update cycle
# arg[0] is the time in seconds since last update
# arg[1] is the number of NAM traveled since last update
# arg[2] is the ice-accumulation-factor for the current severity
#####################################################################
IceSensitiveElement.update = func {
if( me.controlN != nil and me.controlN.getBoolValue() ) {
if( me.iceAmountN.getValue() != 0.0 ) {
me.iceAmountN.setDoubleValue( 0.0 );
}
return;
}
var deltat = arg[0];
var dist_nm = arg[1];
var factor = arg[2];
var v = me.iceAmountN.getValue() + dist_nm * factor * me.sensitivityN.getValue();
if( v < 0.0 ) {
v = 0.0;
}
if( me.iceAmountN.getValue() != v ) {
me.iceAmountN.setValue( v );
}
};
#####################################################################
# read the ice sensitive elements from the config file
#####################################################################
var iceSensitiveElements = nil;
var icingConfigN = props.globals.getNode( "/sim/model/icing", 0 );
if( icingConfigN != nil ) {
iceSensitiveElements = [];
var iceableNodes = icingConfigN.getChildren( "iceable" );
foreach( var iceable; iceableNodes ) {
append( iceSensitiveElements, IceSensitiveElement.new( iceable ) );
}
};
#####################################################################
# the time triggered loop
#####################################################################
var elapsedTimeNode = props.globals.getNode( "/sim/time/elapsed-sec" );
var lastUpdate = 0.0;
var icing = func {
var temperature = temperatureN.getValue();
var severity = ICING_NONE;
icingFactorN.setDoubleValue( ICING_FACTOR[severity] );
var visibility = 0;
if( visibilityN != nil ) {
visibility = visibilityN.getValue();
}
# check if we should create some ice
var spread = temperature - dewpointN.getValue();
if( spread < maxSpreadN.getValue() and visibility < 1000 ) {
for( var i = 0; i < size(ICING_TEMPERATURE); i = i + 1 ) {
if( ICING_TEMPERATURE[i][0] > temperature and
ICING_TEMPERATURE[i][1] <= temperature ) {
var s1 = ICING_TEMPERATURE[i][2];
var s2 = ICING_TEMPERATURE[i][3];
var ds = s2 - s1 + 1;
severity = s1 + int(rand()*ds);
icingFactorN.setDoubleValue( ICING_FACTOR[severity] );
break;
}
}
} else {
# clear air
# melt ice if above freezing temperature
# the warmer, the faster. Lets guess that at 10degc
# 0.5 inch goes in 10miles
if( temperature > 0.0 ) {
icingFactorN.setDoubleValue( factor = -0.05 * temperature / 10.0 );
}
# if temperature below zero, sublimating factor is initialized
}
setSeverity( severity );
# update all sensitive areas
var now = elapsedTimeNode.getValue();
var dt = now - lastUpdate;
foreach( var iceable; iceSensitiveElements ) {
iceable.update( dt, dt * speedN.getValue()/3600.0, icingFactorN.getValue() );
}
lastUpdate = now;
settimer( icing, 2 );
}
#####################################################################
# start our icemachine
# don't care if there is nothing to put ice on
#####################################################################
if( iceSensitiveElements != nil ) {
lastUpdate = elapsedTimeNode.getValue();
icing();
}
#####################################################################
# OHP button
#####################################################################
setprop("/controls/switches/windowprobeheat", 0);
setprop("/controls/switches/windowprobeheatfault", 0);
setlistener("/controls/switches/windowprobeheat", func {
var windowprb = getprop("/controls/switches/windowprobeheat");
var fault = getprop("/controls/switches/windowprobeheatfault");
if (windowprb == 0.5) { # if in auto
var wowl = getprop("/gear/gear[1]/wow");
var wowr = getprop("/gear/gear[2]/wow");
var stateL = getprop("/engines/engine[0]/state");
var stateR = getprop("/engines/engine[1]/state");
var fault = getprop("/controls/switches/windowprobeheatfault");
if (!wowl or !wowr and !fault) {
setprop("/controls/deice/windowprobeheat", 1);
} else if (stateL == 3 or stateR == 3 and !fault) {
setprop("/controls/deice/windowprobeheat", 1);
}
} else if (windowprb == 1 and !fault) { # if in ON
setprop("/controls/deice/windowprobeheat", 1);
} else if (fault) {
setprop("/controls/deice/windowprobeheat", 0);
} else {
setprop("/controls/deice/windowprobeheat", 0);
}
});
#####################################################################

View file

@ -2,6 +2,7 @@
<!-- Joshua Davidson (it0uchpods) -->
<aerodynamics>
<property value="0.0">ice/wing</property>
<axis name="LIFT">
<function name="aero/force/Lift_alpha">
@ -70,6 +71,22 @@
</product>
</function>
<function name="aero/force/Lift_wingice">
<description>Lift_decrease_due_to_ice_on_wing</description>
<product>
<property>aero/qbar-psf</property>
<property>metrics/Sw-sqft</property>
<table>
<independentVar>ice/wing</independentVar>
<tableData>
0.0 0
0.5 -0.1
1.0 -0.3
2.0 -1.5
</tableData>
</table>
</product>
</function>
</axis>
<axis name="DRAG">
@ -185,6 +202,23 @@
<value>0.035</value>
</product>
</function>
<function name="aero/force/Drag_wingice">
<description>Drag_due_to_ice_on_wing</description>
<product>
<property>aero/qbar-psf</property>
<property>metrics/Sw-sqft</property>
<table>
<independentVar>ice/wing</independentVar>
<tableData>
0.0 0
0.5 0.004
1.0 0.010
2.0 0.100
</tableData>
</table>
</product>
</function>
</axis>

View file

@ -2,6 +2,7 @@
<!-- Joshua Davidson (it0uchpods) -->
<aerodynamics>
<property value="0.0">ice/wing</property>
<axis name="LIFT">
<function name="aero/force/Lift_alpha">
@ -70,6 +71,22 @@
</product>
</function>
<function name="aero/coefficient/CLicew">
<description>Lift_decrease_due_to_ice_on_wing</description>
<product>
<property>aero/qbar-psf</property>
<property>metrics/Sw-sqft</property>
<table>
<independentVar>ice/wing</independentVar>
<tableData>
0.0 0
0.5 -0.1
1.0 -0.3
2.0 -1.5
</tableData>
</table>
</product>
</function>
</axis>
<axis name="DRAG">
@ -200,6 +217,22 @@
</product>
</function>
<function name="aero/force/Drag_wingice">
<description>Drag_due_to_ice_on_wing</description>
<product>
<property>aero/qbar-psf</property>
<property>metrics/Sw-sqft</property>
<table>
<independentVar>ice/wing</independentVar>
<tableData>
0.0 0
0.5 0.004
1.0 0.010
2.0 0.100
</tableData>
</table>
</product>
</function>
</axis>
<axis name="ROLL">

View file

@ -2,6 +2,7 @@
<!-- Joshua Davidson (it0uchpods) -->
<aerodynamics>
<property value="0.0">ice/wing</property>
<axis name="LIFT">
<function name="aero/force/Lift_alpha">
@ -69,7 +70,23 @@
<value>0.04</value>
</product>
</function>
<function name="aero/coefficient/CLicew">
<description>Lift_decrease_due_to_ice_on_wing</description>
<product>
<property>aero/qbar-psf</property>
<property>metrics/Sw-sqft</property>
<table>
<independentVar>ice/wing</independentVar>
<tableData>
0.0 0
0.5 -0.1
1.0 -0.3
2.0 -1.5
</tableData>
</table>
</product>
</function>
</axis>
<axis name="DRAG">
@ -186,6 +203,22 @@
</product>
</function>
<function name="aero/force/Drag_wingice">
<description>Drag_due_to_ice_on_wing</description>
<product>
<property>aero/qbar-psf</property>
<property>metrics/Sw-sqft</property>
<table>
<independentVar>ice/wing</independentVar>
<tableData>
0.0 0
0.5 0.004
1.0 0.010
2.0 0.100
</tableData>
</table>
</product>
</function>
</axis>
<axis name="SIDE">

50
Systems/icing.xml Normal file
View file

@ -0,0 +1,50 @@
<PropertyList>
<sim>
<model>
<icing>
<iceable>
<name>Wing</name>
<salvage-control>/controls/deice/surface-deice-wingtail-light</salvage-control>
<sensitivity type="double">0.8</sensitivity>
<output-property>/fdm/jsbsim/ice/wing</output-property>
</iceable>
<iceable>
<name>Stabilizer</name>
<salvage-control>/controls/deice/surface-deice-wingtail-light</salvage-control>
<sensitivity type="double">1.0</sensitivity>
<output-property>/fdm/jsbsim/ice/stabilizer</output-property>
</iceable>
<iceable>
<name>LeftEngine</name>
<salvage-control>/controls/deice/prop-deice</salvage-control>
<sensitivity type="double">0.5</sensitivity>
<output-property>/fdm/jsbsim/ice/propeller</output-property>
</iceable>
<iceable>
<name>Right</name>Engine</name>
<salvage-control>/controls/deice/prop-deice</salvage-control>
<sensitivity type="double">0.5</sensitivity>
<output-property>/fdm/jsbsim/ice/propeller</output-property>
</iceable>
<iceable>
<name>Windshield</name>
<salvage-control>/controls/deice/windshield-deice</salvage-control>
<sensitivity type="double">0.5</sensitivity>
<!-- not relevant for fdm, ignore output-property -->
</iceable>
<iceable>
<name>Fuselage</name>
<!-- no salvage control, no deicing of the fuselage -->
<sensitivity type="double">0.3</sensitivity>
<output-property>/fdm/jsbsim/ice/fuselage</output-property>
</iceable>
<iceable>
<name>Pitot tube</name>
<sensitivity type="double">1</sensitivity>
<salvage-control>/controls/anti-ice/pitot-heat</salvage-control>
<output-property>/systems/pitot/icing</output-property>
</iceable>
</icing>
</model>
</sim>
</PropertyList>