Howto:Write a fuel system in JSBSim: Difference between revisions

From FlightGear wiki
Jump to navigation Jump to search
(→‎Examples: Spitfire)
Line 131: Line 131:
=== Spitfire: Carburetor engine ===
=== Spitfire: Carburetor engine ===


Spitfire II fuel system. Simulating the carburetor as a small tank to handle fuel starvation if negative Gs.
Spitfire II fuel system. This systems have properties for damage, leaks and simulates the carburetor as a small tank to handle fuel starvation at negative Gs.
The Spitfire has two interconnected tanks with fuel flowing from an upper tank to a lower and both connected to the engine through cocks. The layout of the system can be seen [http://616sqn.tidesofwar.net/gallery/spitfuelsm.jpg here].


<syntaxhighlight lang="xml">
<syntaxhighlight lang="xml">

Revision as of 08:55, 24 April 2013

As of FlightGear 2.4.0, JSBSim aircraft have a new tank-property: propulsion/tank[n]/external-flow-rate-pps. Setting this property will either draw fuel from (value < 0), or insert fuel into (value > 0) the respective tank. By using this property, one can simulate complex fuel systems.

A fuel system file

First we create a system file, in which we will write the actual system. It's advised to save this file as Aircraft/.../Systems/fuel.xml.

<?xml version="1.0"?>  

<system name="fuel"> 
	<!-- we will write the system here -->
</system>

We link the main FDM to this system by adding the following line, somewhere in your aircraft's FDM (I advise to put it below </propulsion>).

<system file="fuel"/>

Notice how "fuel" refers to Aircraft/.../Systems/fuel.xml.

Fuel handling in JSBSim

To make JSBSim handle the fuel system during simulation we create one or more channels in the system file. Within these we can use the different control components available in JSBSim.

When using propulsion/tank[n]/external-flow-rate-pps there is no automatic detection if the tank is full or empty. Fuel filling an already full tank will just disappear, creating a "leak". Fuel drawn from an empty tank will make new fuel magically appear in the system. In most cases we will have to make checks to avoid these problems.

Two control components that is useful in a fuel system are summers and switches.

Summers

To calculate the total fuel-flows to/from each tank, we need to sum up the independent flows. This must be done for each single tank, but the principle is the same every time and simple to understand. Every flow that transports fuel from a tank should get a minus sign.

This summer calculates the total flow to or from tank[0].

<summer>
	<input>-propulsion/tank[0]/external-flow-rate/jettison</input>		<!-- jettison -->
	<input>-propulsion/tank[0]/external-flow-rate/tank[1]</input>		<!-- to tank 1 -->
	<input>-propulsion/tank[0]/external-flow-rate/tank[2]</input>		<!-- to tank 2 -->
	<input>-propulsion/tank[0]/external-flow-rate/tank[3]</input>		<!-- to tank 3 -->
	<input>propulsion/tank[1]/external-flow-rate/tank[0]</input>		<!-- from tank 1 -->
	<input>propulsion/tank[2]/external-flow-rate/tank[0]</input>		<!-- from tank 2 -->
	<input>propulsion/tank[3]/external-flow-rate/tank[0]</input>		<!-- from tank 3 -->
	<output>propulsion/tank[0]/external-flow-rate-pps</output>
</summer>

Switches

To turn the flow on or off we need a switch.

This switch draws 5 lbs/s from tank[0] until its empty as long as the collector vale is open.

    <switch>
      <default value="-5"/>
      <test logic="OR" value="0">
        propulsion/tank[0]/collector-valve EQ 0
        propulsion/tank[0]/pct-full LE 0
      </test>
      <output>propulsion/tank[0]/external-flow-rate-pps</output>
    </switch>

Examples

Jettison switch

The /controls/fuel/fuel-to-remain property controls the amount of fuel (in lbs) that should be kept a board. When the total-fuel-level reaches that level, fuel dumping will auomatically stop. Fuel dumping can also be stopped by closing the jettison valves (disable /controls/fuel/dump-valve).

<switch>
	<default value="0"/>
	<test logic="AND" value="12.25">
		/controls/fuel/dump-valve == 1
		propulsion/total-fuel-lbs gt /controls/fuel/fuel-to-remain
	</test>
	<output>propulsion/tank[0]/external-flow-rate/jettison</output>
	<output>propulsion/tank[2]/external-flow-rate/jettison</output>
	<output>propulsion/tank[3]/external-flow-rate/jettison</output>
	<output>propulsion/tank[7]/external-flow-rate/jettison</output>
</switch>

The output properties should be added as inputs to the respective summers. Add a minus sign, as the fuel is taken from the tank.

Two tanks and a collector tank

A system with two tanks (tank[0] and tank[1]) feeding a collector tank (tank[2]). The engine is fed from the collector tank. There is valves between each of the tanks and the collector that can be set open or closed. Negative Gs cut the supply to the collector.

The system consists of two properties: propulsion/tank[0]/collector-valve and propulsion/tank[1]/collector-valve that represent the valves and a channel that handles the fuel transfer from the tanks to the collector and the necessary checks.

The fuel transfer using external-flow-rate-pps does not check against if tanks are empty or full. This can create fuel when "fuel" is drawn from an empty tank or a "leak" when fuel is pumped into a full tank. Making the check against collector tank level greater or equal to 99.5 % instead of against 100% is done to avoid the later kind of leak since the collector tank normally receives more fuel every time step than the engine uses. The 0.5% margin creates a buffer for this difference as the value oscillates around 99.5% as the switch turns on and off the flow.

Two tanks and a collector tank
<?xml version="1.0"?>

 
<system name="Fuel">
<!-- tank[2] collector tank connected to the engine fuel pump, tank[0] and tank[1] feeds the collector through valves.
Negative Gs (<-0.5g) cuts the supply to the collector tanks -->

   <property type="bool" value="1">propulsion/tank[0]/collector-valve</property>
   <property type="bool" value="1">propulsion/tank[1]/collector-valve</property>

  <channel name="Fuel pumping">    

    <switch>
      <default value="-5"/>
      <test logic="OR" value="0">
        propulsion/tank[0]/collector-valve EQ 0
        propulsion/tank[0]/pct-full LE 0
        propulsion/tank[2]/pct-full GE 99.5
        accelerations/Nz LE -0.5
      </test>
      <output>propulsion/tank[0]/external-flow-rate-pps</output>
    </switch>

    <switch>
      <default value="-5"/>
      <test logic="OR" value="0">
        propulsion/tank[1]/collector-valve EQ 0
        propulsion/tank[1]/pct-full LE 0
        propulsion/tank[2]/pct-full GE 99.5
        accelerations/Nz LE -0.5 
      </test>
      <output>propulsion/tank[1]/external-flow-rate-pps</output>
    </switch>

    <summer>
      <input>-propulsion/tank[0]/external-flow-rate-pps</input>
      <input>-propulsion/tank[1]/external-flow-rate-pps</input>
      <output>propulsion/tank[2]/external-flow-rate-pps</output>
    </summer>  

  </channel>      

</system>

Spitfire: Carburetor engine

Spitfire II fuel system. This systems have properties for damage, leaks and simulates the carburetor as a small tank to handle fuel starvation at negative Gs. The Spitfire has two interconnected tanks with fuel flowing from an upper tank to a lower and both connected to the engine through cocks. The layout of the system can be seen here.

    <?xml version="1.0"?>

     
    <system name="Fuel">

       <property type="bool" value="0"> /fdm/jsbsim/fuel/tank_top_cock</property>
       <property type="bool" value="0"> /fdm/jsbsim/fuel/tank_bottom_cock</property>
       <property type="double" value="1"> /fdm/jsbsim/fuel/damage</property>
       <property type="double" value="0"> /fdm/jsbsim/fuel/priming</property>
       <property type="double" value="0"> /fdm/jsbsim/fuel/leak_top_tank</property>
       <property type="double" value="0"> /fdm/jsbsim/fuel/leak_bottom_tank</property>
       
       <channel name="carburetor">

          <!-- Total Carburetor Flow Rate in pps -->         
          <summer name="fuel/float_chamber-pps">
             <input>fuel/pump_flow_to_float-pps</input>
             <input>/fdm/jsbsim/fuel/priming</input>         
             <input>-propulsion/engine/fuel-flow-rate-pps</input>
             <output>propulsion/tank[0]/external-flow-rate-pps</output>      
          </summer>      

       </channel>   

       <channel name="Fuel Pump">
       
          <!-- float throttle valve position -->         
          <aerosurface_scale name="fuel/float_throttle-valve-cmd">
             <input>propulsion/tank[0]/contents-lbs</input>
             <zero_centered>false</zero_centered>
             <domain>
                <min>0.0</min>
                <max>0.5</max>
             </domain>                  
             <range>
                <min>1.0</min>
                <max>0.0</max>
             </range>
          </aerosurface_scale >      
          
          
          <!-- Fuel Flow into Float Chamber in pps -->
          <switch name="fuel/flowing_from_tank">
             <default value="0"/>
             <test logic="AND" value="fuel/float_throttle-valve-cmd">
                accelerations/Nz GE -0.5
                <test logic="OR">
                   <test logic="AND">
                      fuel/tank_top_cock EQ 1               
                      propulsion/tank[1]/contents-lbs GT 0
                   </test>            
                   <test logic="AND">
                      fuel/tank_bottom_cock EQ 1
                      propulsion/tank[2]/contents-lbs GT 0
                   </test>      
                </test>
             </test>               
          </switch>

          <fcs_function name="fuel/pump_flow_to_float-pps">
             <function>
                   <product>
                      <property>fuel/flowing_from_tank</property>
                      <table>      <!-- Fuel pump in pps -->
                         <independentVar>propulsion/engine/engine-rpm</independentVar>
                         <tableData> <!-- Fuel pump curve -->               
                            0      0
                            100      1
                            3000   10                  
                         </tableData>
                      </table>
                      <property>fuel/damage</property>
                      <value>0.12</value> <!-- full throttle max fuel demand in pps  -->
                   </product>            
             </function>
             <output>fuel/pump_flow_to_float-pps</output>   
          </fcs_function>   
          
       </channel>      
          
          
       <channel name="Tanks">
             
          <!-- Fuel flow to be divided aross a number of tanks -->      
          <fcs_function name="fuel/flow_from_tank">
             <function>
                <quotient>
                   <property>fuel/pump_flow_to_float-pps</property>
                   <sum>
                      <property>fuel/tank_top_cock</property>
                      <property>fuel/tank_bottom_cock</property>
                   </sum>
                </quotient>               
             </function>
             <output>fuel/flow_from_tank</output>         
          </fcs_function>         

       </channel>   

          
       <channel name="Top Tank">
       
          <!-- top_bottom_transfer -->            
          <switch name="fuel/top_bottom_transfer">
             <default value="0"/>
             <test logic="AND" value="1">
                propulsion/tank[1]/contents-lbs GT 0
                propulsion/tank[2]/contents-lbs LT 322
                accelerations/Nz GE -0.5
             </test>         
          </switch>   
             
          <!-- Fuel tranfer rate in pps-->
          <fcs_function name="fuel/top_bottom_transfer-pps">
             <function>
                <product>
                   <property>fuel/top_bottom_transfer</property>            
                   <sum>
                      <property>fuel/from_bottom_tank</property>
                      <table>      <!-- Liquid finds it's own level -->
                         <independentVar>propulsion/tank[2]/contents-lbs</independentVar>
                         <tableData>
                            319      1
                            322      0       
                         </tableData>
                      </table>
                   </sum>
                </product>               
             </function>
             <output>fuel/top_bottom_transfer-pps</output>   
          </fcs_function>   

          <!-- Top Tank Fuel Flow Rate in pps -->         
          <switch name="fuel/from_top_tank">
             <default value="0"/>
             <test logic="AND" value="fuel/flow_from_tank">   
                fuel/tank_top_cock EQ 1
                accelerations/Nz GE -0.5   
             </test>      
          </switch>

          <!-- Total Top Tank Fuel Flow Rate in pps -->         
          <summer name="fuel/total_from_top_tank-pps">
             <input>-fuel/top_bottom_transfer-pps</input>
             <input>-fuel/from_top_tank</input>
             <input>-fuel/leak_top_tank</input>
             <output>propulsion/tank[1]/external-flow-rate-pps</output>            
          </summer>
          
       </channel>
       
       <channel name="Bottom Tank">         
                
          <!-- Bottom Tank Fuel Flow Rate in pps -->            
          <switch name="fuel/from_bottom_tank">
             <default value="0"/>
             <test logic="AND" value="fuel/flow_from_tank">
                fuel/tank_bottom_cock EQ 1
                accelerations/Nz GE -0.5         
             </test>
          </switch>

          <!-- Total Bottom Tank Fuel Flow Rate in pps -->         
          <summer name="fuel/total_from_bottom_tank-pps">
             <input>fuel/top_bottom_transfer-pps</input>
             <input>-/fdm/jsbsim/fuel/priming</input>
             <input>-fuel/from_bottom_tank</input>
             <input>-fuel/leak_bottom_tank</input>         
             <output>propulsion/tank[2]/external-flow-rate-pps</output>            
          </summer>
          
       </channel>      

    </system>