From 153a604dde2d5b74932fbb51da744be43c7c7094 Mon Sep 17 00:00:00 2001 From: Jonathan Redpath <legoboyvdlp@gmail.com> Date: Tue, 20 Jun 2017 17:52:39 +0100 Subject: [PATCH] add icing from Seneca (unedited Nasal) and adjust it for the A320. Pitot heat and window probe button now working! --- A320-main.xml | 122 ++++++---- Models/Fuselages/A319/fuselage.xml | 12 +- Models/Fuselages/A320/fuselage.xml | 8 +- Models/Fuselages/A320neo/fuselage.xml | 8 +- Models/Fuselages/A321/fuselage.xml | 22 +- Models/Fuselages/A321neo/fuselage.xml | 22 +- Models/Instruments/OHpanel/OHpanel.xml | 73 ++++++ Models/Instruments/OHpanel/res/ohpanel.ac | 140 +++++++---- Nasal/PitotIcing.nas | 80 +++++++ Nasal/icing.nas | 276 ++++++++++++++++++++++ Systems/a319-aerodynamics.xml | 34 +++ Systems/a320-aerodynamics.xml | 33 +++ Systems/a321-aerodynamics.xml | 35 ++- Systems/icing.xml | 50 ++++ 14 files changed, 790 insertions(+), 125 deletions(-) create mode 100644 Nasal/PitotIcing.nas create mode 100644 Nasal/icing.nas create mode 100644 Systems/icing.xml diff --git a/A320-main.xml b/A320-main.xml index 30f2db4f..b645ef0f 100644 --- a/A320-main.xml +++ b/A320-main.xml @@ -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> diff --git a/Models/Fuselages/A319/fuselage.xml b/Models/Fuselages/A319/fuselage.xml index 223c9e18..67a49d2e 100644 --- a/Models/Fuselages/A319/fuselage.xml +++ b/Models/Fuselages/A319/fuselage.xml @@ -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> diff --git a/Models/Fuselages/A320/fuselage.xml b/Models/Fuselages/A320/fuselage.xml index 1048cf90..ee16a147 100644 --- a/Models/Fuselages/A320/fuselage.xml +++ b/Models/Fuselages/A320/fuselage.xml @@ -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> diff --git a/Models/Fuselages/A320neo/fuselage.xml b/Models/Fuselages/A320neo/fuselage.xml index 1048cf90..ee16a147 100644 --- a/Models/Fuselages/A320neo/fuselage.xml +++ b/Models/Fuselages/A320neo/fuselage.xml @@ -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> diff --git a/Models/Fuselages/A321/fuselage.xml b/Models/Fuselages/A321/fuselage.xml index 10d67c1c..af2daea4 100644 --- a/Models/Fuselages/A321/fuselage.xml +++ b/Models/Fuselages/A321/fuselage.xml @@ -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> diff --git a/Models/Fuselages/A321neo/fuselage.xml b/Models/Fuselages/A321neo/fuselage.xml index 10d67c1c..af2daea4 100644 --- a/Models/Fuselages/A321neo/fuselage.xml +++ b/Models/Fuselages/A321neo/fuselage.xml @@ -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> diff --git a/Models/Instruments/OHpanel/OHpanel.xml b/Models/Instruments/OHpanel/OHpanel.xml index e966ab2b..89d30d06 100644 --- a/Models/Instruments/OHpanel/OHpanel.xml +++ b/Models/Instruments/OHpanel/OHpanel.xml @@ -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> diff --git a/Models/Instruments/OHpanel/res/ohpanel.ac b/Models/Instruments/OHpanel/res/ohpanel.ac index 93db398b..8e31332c 100644 --- a/Models/Instruments/OHpanel/res/ohpanel.ac +++ b/Models/Instruments/OHpanel/res/ohpanel.ac @@ -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 diff --git a/Nasal/PitotIcing.nas b/Nasal/PitotIcing.nas new file mode 100644 index 00000000..c4cc2e4a --- /dev/null +++ b/Nasal/PitotIcing.nas @@ -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 ); diff --git a/Nasal/icing.nas b/Nasal/icing.nas new file mode 100644 index 00000000..17dc0fc8 --- /dev/null +++ b/Nasal/icing.nas @@ -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); + } +}); +##################################################################### \ No newline at end of file diff --git a/Systems/a319-aerodynamics.xml b/Systems/a319-aerodynamics.xml index ebda9b4c..24831ba1 100644 --- a/Systems/a319-aerodynamics.xml +++ b/Systems/a319-aerodynamics.xml @@ -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> diff --git a/Systems/a320-aerodynamics.xml b/Systems/a320-aerodynamics.xml index ebda9b4c..7d59bfe3 100644 --- a/Systems/a320-aerodynamics.xml +++ b/Systems/a320-aerodynamics.xml @@ -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"> diff --git a/Systems/a321-aerodynamics.xml b/Systems/a321-aerodynamics.xml index ebda9b4c..47a3d268 100644 --- a/Systems/a321-aerodynamics.xml +++ b/Systems/a321-aerodynamics.xml @@ -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"> diff --git a/Systems/icing.xml b/Systems/icing.xml new file mode 100644 index 00000000..d6ccaa88 --- /dev/null +++ b/Systems/icing.xml @@ -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> \ No newline at end of file