Howto:Carrier Landing Assistant in HUD
This article is a stub. You can help the wiki by expanding it. |
The FlightGear forum has a subforum related to: Canvas |
This Howto Details modifications to the Canvas-based ILS_in_HUD Wiki. It deals specifically with modifying an SU-37, though the principle should be applicable to any carrier-capable aircraft. The properties used are:
- /ai/models/carrier[%d]/controls/flols/angle-degs
- /ai/models/carrier[%d]/orientation/true-heading-deg
- /instrumentation/tacan/indicated-bearing-true-deg
- /orientation/heading-deg
Although a carrier would not be based on this data, in real life, this method has the advantage of being "generic".
Warnings and Limitations
- This HowTo builds on the ILS_in_HUD Wiki. If you haven't fully read and understood that then you probably should not read any further. Just take the video as inspiration for what you may one day achieve and go back a stage.
- It is based on having a valid TACAN signal and a carrier in range and also that the carrier is "/ai/models/carrier[0]". It only does some basic error-checking to see if this is the case and so this would need to be verified as adequate for your own implementation on an aircraft.
- It was done as a quick fix, just to see if it was possible. Consequently it is not particularly elegant or well-commented. Hopefully it will be improved in time.
- The heading needle is really only there to get within the last few hundred metres as it points towards the centre of the carrier model rather than the arrester cables.
- It is based on an offset angle of 8 degrees for the landing deck from the ship's heading and a 3 degree glideslope. These may need to be changed.
Interpreting the Display
[1] is the bearing to the carrier (226) and so, with the current heading of 249, it is off to the left. Within about +/- 30 degrees of the aircraft centreline the carrier symbol will show up at the top of the HUD (see [6]).
[2] is the heading of the landing deck, which in this case is defined as 8 degrees to the left of the carrier's heading.
[3] is the down angle to the carrier. The "needle" is set to align with "Centre" at 3 degrees. This is showing that aircraft needs to go down to get onto the glide-slope.
[4] is the offset angle between [1] and [2]. The "needle" is set to align with "Centre" when they are equal. The idea is to give a steer to get on the approach centreline to the landing deck. This is showing that the aircraft needs to head to the right to intersect the approach line of the landing deck (even though the carrier is off to the left - see [1]).
[5] is the difference in headings between that of the aircraft and the landing deck. This angle is also shown graphically in [6]. It indicates how much of a turn is required once the centreline of [4] is acheived.
[6] is a graphical representation of the carrier location and orientation. In this example it is off to the left and the landing deck is even further to the left. This would imply a gentle sweep to the left is required for the approach, once the approach line of the landing deck has been intersected (see [4]).
Ideally (with a stationary carrier and no wind) the perfect approach would be where Heading == BrgTo == DeckHg (so RelHdg == 0). But with the carrier moving away and a wind it will be unlikely to be that simple. Basically, a lot is going on here and so a good deal of spacial awareness is required. Watch the video for an example.
The Canvas graphics elements
Additions to the new: func(placement)
# ----------------------------------------------------------------- Carrier Landing System
# UP/DOWN:
# glide slope indicator for CARRIER
m.gsiC = m.root.createChild("group", "GSI");
m.gsiC.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)
.setColor(1,1,0);
# Slope to CARRIER vertical needle deflection text box (up/down)
m.STC =
m.text.createChild("text")
.setFontSize(14, 0.9)
.setDrawMode(3)
.setPadding(2)
.setAlignment("center-top")
.setTranslation(180, -20)
.setColor(1,1,0);
# LEFT/RIGHT:
# localiser beam indicator for CARRIER
m.lbiC = m.root.createChild("group", "GSI");
m.lbiC.createChild("path")
.moveTo(8, 0)
.arcSmallCCW(8, 8, 0, -16, 0)
.arcSmallCCW(8, 8, 0, 16, 0)
.moveTo(0, -4)
.vert(-40)
.moveTo(0, 4)
.vert(95)
.setStrokeLineWidth(2.0)
.setColor(1,1,0);
# For Carrier LANDING DECK heading text box
m.carrierHdgTxt =
m.text.createChild("text")
.setFontSize(16, 0.9)
.setAlignment("right-top")
.setTranslation(240, 105)
.setColor(1,1,0);
# Bearing TO the carrier text box
m.carrierBrgTxt =
m.text.createChild("text")
.setFontSize(16, 0.9)
.setAlignment("right-top")
.setTranslation(240, 90)
.setColor(1,1,0);
# Carrier Offset text box
m.carrierOffTxt =
m.text.createChild("text")
.setFontSize(16, 0.9)
.setAlignment("center-top")
.setTranslation(0, 100)
.setColor(1,1,0);
# Carrier pointer text box
m.carrierDiagramTxt =
m.text.createChild("text")
.setFontSize(24, 0.9)
.setAlignment("center-top")
.setTranslation(0, -70)
.setColor(1,1,0)
.setText('=>');
# relativeDeckHeading text box
m.relativeDeckHeadingText =
m.text.createChild("text")
.setFontSize(12, 1.0)
.setAlignment("center-top")
.setTranslation(0, -55)
.setColor(1,1,0);
# ---------------------------------------------------------- end of Carrier Landing System
Drawing them on the HUD
Additions to the update: func()
# The CARRIER Glide Slope Up/Down needle
var closestCarrier = 0;
var slopeToCarrierProp = sprintf("/ai/models/carrier[%d]/controls/flols/angle-degs", closestCarrier);
var slopeToCarrier = getprop(slopeToCarrierProp);
# Check to see if a carrier is available
if(slopeToCarrier != nil){
me.STC.setText(sprintf("%1.2f", -slopeToCarrier));
me.STC.setTranslation(185, 20*(slopeToCarrier -3) -5 );
me.gsiC.setTranslation(0, 20*(slopeToCarrier -3) );
# The CARRIER approach heading Left/Right needle
var carrierHdgProp = sprintf("/ai/models/carrier[%d]/orientation/true-heading-deg", closestCarrier);
var carrierHdg = getprop(carrierHdgProp);
me.carrierHdgTxt.setText(sprintf("DeckHdg: %1.0f", carrierHdg-8)); # allow for landing deck offset
var carrierBrgTo = getprop("/instrumentation/tacan/indicated-bearing-true-deg");
me.carrierBrgTxt.setText(sprintf("BrgTo: %1.0f", carrierBrgTo)); # heading TO the carrier
var carrierOffset = carrierHdg - carrierBrgTo -8 ; # landing deck offset
me.carrierOffTxt.setText(sprintf("%1.1f", -carrierOffset));
me.carrierOffTxt.setTranslation(-10*(carrierOffset), 100 );
me.lbiC.setTranslation(-10*(carrierOffset), 0 );
var currentHeading = getprop("/orientation/heading-deg");
var relativeDeckHeading = -(currentHeading - carrierHdg +8) ;
me.relativeDeckHeadingText.setText(sprintf("RelHdg: %1.0f", relativeDeckHeading)); # landing deck offset
me.carrierDiagramTxt.setRotation( ((relativeDeckHeading -105 )* math.pi )/ 180);
var hdgOffsetToCarrier = currentHeading - carrierBrgTo;
me.carrierDiagramTxt.setTranslation(-10*(hdgOffsetToCarrier), -90 );
}
else{ # hide from view
me.STC.setTranslation(300,300);
me.gsiC.setTranslation(300,300);
me.carrierOffTxt.setTranslation(300,300);
me.lbiC.setTranslation(300,300);
me.carrierDiagramTxt.setTranslation(300,300);
});