1
0
Fork 0

ISFD has ILS bars now in APProach mode

This commit is contained in:
James Turner 2019-01-17 09:46:04 +00:00
parent 29ec71b3a6
commit efbd5cbb4f
3 changed files with 319 additions and 47 deletions

View file

@ -3,6 +3,7 @@
var nasal_dir = getprop("/sim/fg-root") ~ "/Aircraft/Instruments-3d/ISFD/";
io.load_nasal(nasal_dir ~ 'ISFD_gui.nas', "isfd");
io.load_nasal(nasal_dir ~ 'ISFDGenericController.nas', "isfd");
io.load_nasal(nasal_dir ~ 'PhysicalController.nas', "isfd");
# main wrapper object
var ISFD = {
@ -18,7 +19,10 @@ rollBaseRadius: 160,
roseRadius: 512,
boxHeight: 48,
new : func() {
needleBoxSize: 220,
needleBoxHeight: 20,
new : func(controller = nil) {
var obj = {
parents : [ISFD],
_mode : ''
@ -41,10 +45,12 @@ new : func() {
# centering transform
obj.root.setTranslation(ISFD.halfSize, ISFD.halfSize);
obj._controller = isfd.GenericController.new();
var controllerClass = (controller == nil) ? isfd.GenericController : controller;
obj._controller = controllerClass.new(obj);
obj.createContents();
obj._updateTimer = maketimer(0.05, func obj.update(); );
obj._updateTimer.start();
obj._appMode = nil; # set to nil to force update on first update() trigger
return obj;
},
@ -79,9 +85,8 @@ createContents : func()
# mach readout - not on the B737 model?
me.createModeText();
# if ILS is tuned!
# glideslope marker
# localizer marker
me.createLocalizer();
me.createGlideslope();
me.createAirplaneMarker();
@ -160,6 +165,15 @@ addHorizontalSymmetricLine : func(path, positiveLength, y)
return path;
},
addDiamond : func(path, radius)
{
path.move(-radius, 0);
path.line(radius, -radius); # top
path.line(radius, radius); # right
path.line(-radius, radius); # bottom
path.close();
},
createDigitTape : func(parent, name, suffix = nil)
{
var t = parent.createChild('text', name);
@ -587,16 +601,110 @@ createModeText : func()
me._modeText.setTranslation(ISFD.hsiLeft + 2, midTextY);
},
pressButtonAPP : func()
updateApproachMode: func
{
if (me._mode == 'app') {
me._mode = '';
me._modeText.setVisible(0);
} else {
me._mode = 'app';
me._modeText.setText('APP');
me._modeText.setVisible(1);
if (me._appMode != 0) {
me._modeText.setText('APP');
}
me._modeText.setVisible(me._appMode);
me._localizerGroup.setVisible(me._appMode);
me._glideslopeGroup.setVisible(me._appMode);
},
createLocalizer: func
{
var hw = ISFD.needleBoxSize * 0.5;
var g = me.root.createChild('group', 'localizer-group');
g.setTranslation(ISFD.hsiXCenter, 156);
me._localizerGroup = g;
var bkg = g.rect(-hw, 0, ISFD.needleBoxSize, ISFD.needleBoxHeight);
bkg.setColorFill('#000000');
# markers: white line and hollow dots
var m = g.createChild("path", "localizer-marker");
m.setStrokeLineWidth(2);
m.setColor(1, 1, 1);
m.moveTo(0, 0);
m.line(0, ISFD.needleBoxHeight);
m.close();
var r =( ISFD.needleBoxHeight - 8) * 0.5;
var hh = ISFD.needleBoxHeight * 0.5;
# four dots
for (var i = -2; i <= 2; i +=1) {
if (i == 0) continue;
var x = i * 50;
m.moveTo(x - r, hh);
m.arcSmallCW(r, r, 0, r * 2, 0);
m.arcSmallCW(r, r, 0, -r * 2, 0);
m.close();
}
me._localizerPointer = g.createChild("path", "localizer-pointer");
me._localizerPointer.moveTo(0, hh);
me.addDiamond(me._localizerPointer , hh);
me._localizerPointer.setColorFill('#ff00ff'); # magenta!
},
createGlideslope: func
{
var g = me.root.createChild('group', 'glideslope-bar');
me._glideslopeGroup = g;
var hh = ISFD.needleBoxSize * 0.5;
var hw = ISFD.needleBoxHeight * 0.5;
g.setTranslation(ISFD.hsiRight - 36, 0);
me._localizerGroup = g;
var bkg = g.rect(0, -hh, ISFD.needleBoxHeight, ISFD.needleBoxSize);
bkg.setColorFill('#000000');
# markers: white line and hollow dots
var m = g.createChild("path", "gs-marker");
m.setStrokeLineWidth(2);
m.setColor(1, 1, 1);
m.moveTo(0, 0);
m.line(ISFD.needleBoxHeight, 0);
m.close();
var r =( ISFD.needleBoxHeight - 8) * 0.5;
# four dots
for (var i = -2; i <= 2; i +=1) {
if (i == 0) continue;
var y = i * 50;
m.moveTo(hw, y - r);
m.arcSmallCW(r, r, 0, 0, r * 2);
m.arcSmallCW(r, r, 0, 0, -r * 2);
m.close();
}
me._gsPointer = g.createChild("path", "gs-pointer");
me._gsPointer.moveTo(hw, 0);
me.addDiamond(me._gsPointer , hw);
me._gsPointer.setColorFill('#ff00ff'); # magenta!
},
updateILS: func
{
var hsz = ISFD.needleBoxSize * 0.5;
me._localizerPointer.setVisible(me._controller.isLocalizerValid());
var locDev = me._controller.getLocalizerDeviationNorm() * hsz;
me._localizerPointer.setTranslation(locDev, 0);
me._gsPointer.setVisible(me._controller.isGSValid());
var gsDev = me._controller.getGSDeviationNorm() * hsz;
me._gsPointer.setTranslation(0, gsDev);
},
pressButtonAPP : func
{
me._controller.toggleApproachMode();
},
update : func()
@ -631,6 +739,25 @@ update : func()
me._altitudeDigits00.setTranslation(80, 16 + altDigits00 * 32);
var s = sprintf("%03i ", math.floor(alt / 100));
me._altitudeBoxText.setText(s);
# barometric
if (me._controller.isSTDBarometricPressure()) {
me._altimeterText.setText('STD');
} elsif (me._controller.isHPaBarometer()) {
me._altimeterText.setText(sprintf('%4d HPA', me._controller.getBarometricPressureSettingHPa()));
} else {
me._altimeterText.setText(sprintf('%4.2f IN', me._controller.getBarometricPressureSettingInHg()));
}
# APProach mode
if (me._appMode != me._controller.isApproachMode()) {
me._appMode = me._controller.isApproachMode;
me.updateApproachMode();
}
if (me._appMode != 0) {
me.updateILS();
}
}
};

View file

@ -3,68 +3,105 @@
var GenericController =
{
# COLORS : {
# green : [0, 1, 0],
# white : [1, 1, 1],
# black : [0, 0, 0],
# lightblue : [0, 1, 1],
# darkblue : [0, 0, 1],
# red : [1, 0, 0],
# magenta : [1, 0, 1],
# },
new : func ()
new : func (isfd)
{
var obj = {
parents : [GenericController],
_isfd: isfd,
_altimeterProp : "/instrumentation/altimeter/",
_airspeedProp : "/instrumentation/airspeed-indicator/",
_attitudeProp : "/instrumentation/attitude-indicator/",
_navRadio: "/instrumentation/nav[0]/",
_isSTDBaro : 0,
_approachMode : 0
};
# IFSD does its own barometric altititde independant of the acft ADIRUs
#me.altitudeProp = props.globals.getNode('/instruments/')
return obj;
return obj;
},
update : func()
update : func
{
},
getAltitudeFt : func()
getAltitudeFt : func
{
return getprop("/position/altitude-ft");
return getprop(me._altimeterProp ~ "indicated-altitude-ft");
},
getIndicatedAirspeedKnots : func()
getIndicatedAirspeedKnots : func
{
return getprop("/velocities/airspeed-kt");
return getprop(me._airspeedProp ~ "indicated-speed-kt");
},
getHeadingDeg : func()
getHeadingDeg : func
{
# compass / gyro source for this?
return getprop("/orientation/heading-deg");
},
getPitchDeg : func()
getPitchDeg : func
{
return getprop("/orientation/pitch-deg");
#return getprop("/instrumentation/attitude-indicator/indicated-pitch-deg");
# obj.addPropMap("ADCTurnRate", "/instrumentation/turn-indicator/indicated-turn-rate");
# obj.addPropMap("ADCSlipSkid", "/instrumentation/slip-skid-ball/indicated-slip-skid");
return getprop(me._attitudeProp ~ "indicated-pitch-deg");
},
getBankAngleDeg : func()
getBankAngleDeg : func
{
return getprop("/orientation/roll-deg");
# return getprop("/instrumentation/attitude-indicator/indicated-roll-deg");
return getprop(me._attitudeProp ~ "indicated-roll-deg");
},
getBarometricPressureSetting : func()
isSTDBarometricPressure : func
{
return me._isSTDBaro;
},
}
toggleSTDBarometricPressure : func
{
me._isSTDBaro = (me._isSTDBaro == 0);
},
# also a setter
# set inHg / hPA units
isHPaBarometer : func
{
return me._isHPa;
},
toggleHPaBarometer : func
{
me._isHPa = (me._isHPa == 0);
},
getBarometricPressureSettingInHg : func
{
if (me._isSTDBaro) return 29.92;
return getprop(me._altimeterProp ~ "setting-inhg");
},
getBarometricPressureSettingHPa : func
{
if (me._isSTDBaro) return 1013;
return getprop(me._altimeterProp ~ "setting-hpa");
},
setBarometricPressureSettingInHg : func (inHg)
{
setprop(me._altimeterProp ~ "setting-inhg", inHg);
},
setBarometricPressureSettingHPa : func (hpa)
{
setprop(me._altimeterProp ~ "setting-hpa", hpa);
},
isApproachMode: func { return me._approachMode; },
toggleApproachMode : func { me._approachMode = (me._approachMode == 0); },
isLocalizerValid: func { return getprop(me._navRadio ~ "in-range"); },
isGSValid: func { return getprop(me._navRadio ~ "gs-in-range");},
getLocalizerDeviationNorm: func {
return getprop(me._navRadio ~ "heading-needle-deflection-norm");
},
getGSDeviationNorm: func {
return getprop(me._navRadio ~ "gs-needle-deflection-norm");
},
}

View file

@ -0,0 +1,108 @@
# ISFD controller drive by physical properties rather
# than instruments. Useful for testing with the UFO
var PhysicalController =
{
new : func (isfd)
{
var obj = {
parents : [PhysicalController],
_isfd: isfd,
_navRadio: "/instrumentation/nav[0]/",
_isSTDBaro : 0,
_isHPa : 1,
_approachMode : 0
};
print("ISFD is using physical properties, not indicated");
return obj;
},
update : func
{
},
getAltitudeFt : func
{
return getprop("/position/altitude-ft");
},
getIndicatedAirspeedKnots : func
{
return getprop("/velocities/airspeed-kt");
},
getHeadingDeg : func
{
return getprop("/orientation/heading-deg");
},
getPitchDeg : func
{
return getprop("/orientation/pitch-deg");
},
getBankAngleDeg : func
{
return getprop("/orientation/roll-deg");
},
isSTDBarometricPressure : func
{
return me._isSTDBaro;
},
toggleSTDBarometricPressure : func
{
me._isSTDBaro = (me._isSTDBaro == 0);
},
isHPaBarometer : func
{
return me._isHPa;
},
toggleHPaBarometer : func
{
me._isHPa = (me._isHPa == 0);
},
getBarometricPressureSettingInHg : func
{
return 29.92;
},
getBarometricPressureSettingHPa : func
{
return 1013;
},
setBarometricPressureSettingInHg : func (inHg)
{
print('ISFD: no-op with PhysicalController, no altimeter')
},
setBarometricPressureSettingHPa : func (hpa)
{
print('ISFD: no-op with PhysicalController, no altimeter')
},
isApproachMode: func {
return me._approachMode;
},
toggleApproachMode : func { me._approachMode = (me._approachMode == 0); },
isLocalizerValid: func { return getprop(me._navRadio ~ "in-range"); },
isGSValid: func { return getprop(me._navRadio ~ "gs-in-range");},
getLocalizerDeviationNorm: func {
return getprop(me._navRadio ~ "heading-needle-deflection-norm");
},
getGSDeviationNorm: func {
return getprop(me._navRadio ~ "gs-needle-deflection-norm");
},
}