ILS in HUD

From FlightGear wiki
Jump to navigation Jump to search


Adding ILS to the HUD of an SU-37

ILS is superimposed over the standard HUD, in red

This is just one way of implementing this on a particular aircraft. Even on this aircraft there are many ways of achieving this. Apart from the SU-37-set.xml file that will need to be amended manually, the other files are available in this dropbox folder.

A piece of glass to draw on

First of all a surface is required to draw on using Canvas. The needs to be a 3d-model in AC3d format. For this SU-37 example, the file hudGlass.ac was used. These file types are saved as text files, this one being:

AC3Db
MATERIAL "ac3dmat4" rgb 1 0.5 0  amb 0.2 0.2 0.2  emis 1 0.8 0.6  spec 0.2 0.2 0.2  shi 128  trans 0.5
OBJECT world
kids 1
OBJECT poly
name "PFD-Screen"
loc -1.81012e-05 9.69689e-06 0.138677
texture "Aircraft/SU-37/Hud/screen-test.png"
texoff -0.036 -0.073
crease 45.000000
numvert 4
0 0.106446 -0.052729
0 0.106446 -0.224199
0 -0.106446 -0.224199
0 -0.106446 -0.052729
numsurf 1
SURF 0x30
mat 0
refs 4
3 0 0
2 1 0
1 1 1
0 0 1
kids 0
Note  For this to work, the surface (known as PFD-Screen in this example MUST be textured. Pretty much anything will do because Canvas replaces this texture with its own creation. Here the file specifies Aircraft/SU-37/Hud/screen-test.png as the texture file. Obviously, this file must exist, must be a graphics file (JPEG, PNG, etc.) and must be where is says it is. Here, it would need to be in the Aircraft/SU-37/Hud folder. See also AC files: Basic changes to textures and colors.

Placing the glass in the cockpit

This example used an extra model by adding some extra lines in the SU-37-set.xml file, following the main model:

<?xml version="1.0"?>

<PropertyList>

<!-- ... -->

<!-- New lines -->
<model>
  <path>Aircraft/SU-37/Hud/canvas-ILS.xml</path>
</model>

<!-- ... -->

</PropertyList>

The file canvas-ILS.xml contains the following:

<?xml version="1.0"?>

<PropertyList>
 <path>Aircraft/SU-37/Hud/hudGlass.ac</path>
 <offsets>
   <heading-deg>0</heading-deg>
   <roll-deg>0</roll-deg>
   <pitch-deg>40</pitch-deg>
   <x-m>4.55</x-m>
   <y-m>-0.005 </y-m>
   <z-m>1.415</z-m>
 </offsets>
</PropertyList>

This defines the piece of glass to be used (Aircraft/SU-37/Hud/hudGlass.ac) and positions it in a convenient place.

ILS properies

The properties required to place ILS "needles" in a HUD are:

  • /instrumentation/nav/heading-needle-deflection
  • /instrumentation/nav/gs-needle-deflection
  • /instrumentation/nav/gs-in-range
  • /instrumentation/nav/in-range

To be certain of these being recognised properly (i.e., as the correct types) it might be advisable to declare them in the aircraft-set.xml file between the <instrumentation> and the </instrumentation> tags:

<?xml version="1.0"?>

<PropertyList>

<!-- ... -->

<instrumentation>

<!-- ... -->

  <nav>
    <heading-needle-deflection type="double">10.0</heading-needle-deflection>
    <in-range type="bool">0</in-range>
    <gs-needle-deflection type="double">10.0</gs-needle-deflection>
    <gs-in-range type="bool">0</gs-in-range>
  </nav>

<!-- ... -->

</instrumentation>

<!-- ... -->

</PropertyList>

Drawing the ILS needles on the glass

This ILS example uses a derivative of the code at Canvas HUD

# ==============================================================================
# Head up display ILS extras for SU-37
# ==============================================================================
var HUD = {
  canvas_settings: {
    "name": "HUD",
    "size": [1024, 1024],
    "view": [640, 640],
    "mipmapping": 1
  },
  new: func(placement) {
    var m = {
      parents: [HUD],
      canvas: canvas.new(HUD.canvas_settings)
    };
    m.canvas.addPlacement(placement);
    m.canvas.setColorBackground(1, 0, 0, 0.02);
    m.root =
      m.canvas.createGroup()
              .setScale(1, 2)
              .setTranslation(320, 320)
              .set("font", "LiberationFonts/LiberationMono-Regular.ttf")
              .setDouble("character-size", 9)
              .setDouble("character-aspect-ration", 0.45)
              .set("stroke", "rgba(255,0,0,0.9)");
    m.text =
      m.root.createChild("group")
            .set("fill", "rgba(255,0,0,0.9)");
# ------------------------------------------------------------------------ ILS deflections
	# horizontal needle deflection text box (left/right)  
    m.hnd =
      m.text.createChild("text")
            .setDrawMode(3)
            .setPadding(2)
            .setAlignment("center-top")
            .setTranslation(0, -135); 
            
      # vertical needle deflection text box (up/down)      
      m.vnd =
      m.text.createChild("text")
            .setDrawMode(3)
            .setPadding(2)
            .setAlignment("center-top")
            .setTranslation(200, 0);
                       
    # Radar altitude (for below 1,000 ft AGL)
    m.rad_alt =
      m.text.createChild("text")
      .setFontSize(18, 0.9)
            .setAlignment("center-top")
            .setTranslation(0, 120);
 
    # Waterline / Pitch indicator (used for alignment with main HUD)
      m.root.createChild("path")
            .moveTo(-24, 0)
            .horizTo(-8)
            .lineTo(-4, 6)
            .lineTo(0, 0)
            .lineTo(4, 6)
            .lineTo(8, 0)
            .horizTo(24)
            .setStrokeLineWidth(0.9);
 
# ------------------------------------------------- ILS glide slope/localiser beam needles
	# glide slope indicator
    m.gsi = m.root.createChild("group", "GSI");
    m.gsi.createChild("path")
         .moveTo(8, 0)
         .arcSmallCCW(8, 8, 0, -16, 0)
         .arcSmallCCW(8, 8, 0,  16, 0)
         .moveTo(-4, 0)
         .horiz(-150)
         .moveTo(4, 0)
         .horiz(150)
         .setStrokeLineWidth(2.0);
         
    # localiser beam indicator    
    m.lbi = m.root.createChild("group", "GSI");
    m.lbi.createChild("path")
         .moveTo(8, 0)
         .arcSmallCCW(8, 8, 0, -16, 0)
         .arcSmallCCW(8, 8, 0,  16, 0)
         .moveTo(0, -4)
         .vert(-100)
         .moveTo(0, 4)
         .vert(200)
         .setStrokeLineWidth(2.0);
 # ---------------------------------------------------------------------------------------
    m.input = {
      hnd:		  "/instrumentation/nav/heading-needle-deflection",
      snd:		  "/instrumentation/nav/gs-needle-deflection",
      gsir:		  "/instrumentation/nav/gs-in-range",
      hir:		  "/instrumentation/nav/in-range",
      rad_alt:    "/position/altitude-agl-ft",
      wow_nlg:    "/gear/gear[4]/wow"
    };
    foreach(var name; keys(m.input)){
    	m.input[name] = props.globals.getNode(m.input[name], 1);
    }
    return m;
  },
  # ------------------------------------------------------------------------------- update
  update: func() {
    var rad_alt = me.input.rad_alt.getValue(); # Only show below 1000 ft AGL
    if(rad_alt and rad_alt < 1000){
        rad_alt = sprintf("%4d AGL", rad_alt);
    } else {
        rad_alt = nil;
    }
    me.rad_alt.setText(rad_alt);
    
    # the Left/right needle
    gslr = me.input.hnd.getValue();
    hir = me.input.hir.getValue();
    me.hnd.setText(sprintf("%1.3f", gslr));
    if(hir == 0) gslr = 10.8;
    me.lbi.setTranslation(20 * gslr, 0);     

    # The Glide Slope Up/Down needle
    gsud = me.input.snd.getValue();
    gsir = me.input.gsir.getValue();
    me.vnd.setText(sprintf("%1.3f", gsud));
    if(gsir == 0) gsud =  7.2;
    me.gsi.setTranslation(0, -20 * gsud);
 
    settimer(func(){ me.update(); }, 0);
  } # ---------------------------------------------------------------------- end of update
}; # end of HUD
 
var init = setlistener("/sim/signals/fdm-initialized", func(){
  removelistener(init); # only call once
  var hud_pilot = HUD.new({"node": "PFD-Screen"}); 
  hud_pilot.update();
});

It was saved as hudCanvasILS.nas in the Aircraft/SU-37/Hud folder

Getting the Nasal to run

Adding this line in the nasal section at the bottom of the SU-37-set.xml file will make the ILS script load and run with the aircraft

<?xml version="1.0"?>

<PropertyList>

<!-- ... -->

<nasal>

  <canvas_test>
    <file>Aircraft/SU-37/Hud/hudCanvasILS.nas</file>
  </canvas_test>

  <!-- ... -->

</nasal>

</PropertyList>

What to expect

ILS in HUD.

Tutorial written by Warty

Related content

External links

Forum topics