Thank you very much for answering.
As you can see in my post following the one you quote, I refer to the refreshing frequency of the updateRNAV function as a possible solution for the problem. By changing that frequency I finally got the CDI needle animation to be smooth.
Also, the issue of the display digit flashing time was solved by separating the relevant part of the "update" function at the end of the KNS80.nas file and including it into a new one with its own "settimer". Appending this new function to the signal ("setlistener("/sim/signals/fdm-initialized" ...) at the end of the file solves de flashing digit issue.
Below I include the code of my first version of the KNS80.nas for testing purposes (copy it to a file and name it KNS80.nas, then place it in the kns80 folder in the tree of Patten's Aerostar). I have documented my modifications clearly, so they can be easily seen. I would apreciate if anyone test the file (if so, first make sure to set the "slaved-to-gps" to false in the kns80.xml as I mentioned in one of my previous posts).
As you can see from the comments in the included KNS80.nas code, for the moment the to-from flag is not usable in RNAV modes. I'm considering to solve the problem either by writing new code for the to-nav flag to work inside a condition executed only if modes 2 ans 3 are active, or by slaving the dme/indicated-distance-nm to that value passed from rnav. I'll see.
Again, thank you very much for your advice. I'll definitely take a look at the instrument filters of the Citation II.
Jogois
Below is the code for the new KNS80.nas (for testing functionality):
- Code: Select all
#### King KNS-80 Integrated Navigation System ####
#### Syd Adams ####
#### Ron Jensen ####
####
#### Must be included in the Set file to run the KNS80 radio
####
#### Nav Modes 0 = VOR ; 1 = VOR/PAR ; 2 = RNAV/ENR ; 3 = RNAV/APR ;
####
################################>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
################################>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#
#THIS VERSION OF THE ORIGINAL FILE HAS BEEN MODIFIED BY JOGOIS. THE AIM OF THIS VERSION IS TO
#MAKE THE KNS80 IN FLIGHTGEAR TO BE GPS INDEPENDENT. ALL REFERENCES TO THE GPS IN THE
#ORIGINAL FILE HAVE BEEN COMMENTED OUT (THEY ARE KEEPT AS COMMENTS JUST FOR TRACKING THE
#CHANGES MADE TO THE ORIGINAL FILE). CONSEQUENTLY THE "slaved-to-gps" PROPERTY IN kns80.xml
#MUST BE SET TO FALSE.
#
#THE FUNCTIONALITY OF THE KNS80 HAS BEEN GOT BY USING "alias" IN NASAL ("setlistener" WAS ALSO
#CONSIDERED AND TESTED, AND ALTHOUGH THIS OPTION WORKED AS WELL, WAS NOT FINALLY CHOSEN).
#THE MODIFICATIONS MADE ARE CONTAINED BETWEEN DOUBLE "####>>>>" LINES FOR CLARITY.
#
#THIS IS VERSION 1.1 OF THE FILE (SOME CORRECTIONS TO THE COMMENTS). THERE ARE STILL MODIFICATIONS TO BE DONE
# (i.e.: THE TO-FROM FLAG IS NOT RELIABLE YET IN RNAV MODES SINCE BEFORE IT DEPENDED ON THE GPS).
#USE ONLY FOR TESTING FUNCTIONALITY OF THE KNS80 WITHOUT DEPENDING ON THE GPS.
#
#IN CASE YOU WANT TO TEST IT MAKE SURE YOU BACK UP THE ORIGINAL KNS80.nas AND kns80.xml
#FILES SO YOU CAN UNDO THE CHANGES.
#
#SEPTEMBER 9, 2018 BY JOGOIS
#
#########################>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#########################>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
var KNS80 = {
new : func(prop){
var m = { parents : [KNS80]};
m.wpt_freq=[];
m.wpt_radial=[];
m.wpt_distance=[];
m.volume_adjust =0;
m.nav_selected = "instrumentation/nav/frequencies/selected-mhz";
m.dme_selected = "instrumentation/dme/frequencies/selected-mhz";
m.display_num = 0;
m.use_num = 0;
m.flasher = 0;
m.kns80 = props.globals.initNode(prop);
m.serviceable = m.kns80.initNode("serviceable",1,"BOOL");
m.data_mode = m.kns80.initNode("data-mode",0,"DOUBLE");
m.nav_mode = m.kns80.initNode("nav-mode",0,"DOUBLE");
m.dme_hold = m.kns80.initNode("dme-hold",0,"BOOL");
m.dsp_flash = m.kns80.initNode("flash",0,"BOOL");
m.display = m.kns80.initNode("display",0,"DOUBLE");
m.use = m.kns80.initNode("use",0,"DOUBLE");
append(m.wpt_freq,m.kns80.initNode("wpt[0]/frequency",115.80,"DOUBLE"));
append(m.wpt_freq,m.kns80.initNode("wpt[1]/frequency",111.70,"DOUBLE"));
append(m.wpt_freq,m.kns80.initNode("wpt[2]/frequency",116.80,"DOUBLE"));
append(m.wpt_freq,m.kns80.initNode("wpt[3]/frequency",113.90,"DOUBLE"));
append(m.wpt_radial,m.kns80.initNode("wpt[0]/radial",280.0,"DOUBLE"));
append(m.wpt_radial,m.kns80.initNode("wpt[1]/radial",280.0,"DOUBLE"));
append(m.wpt_radial,m.kns80.initNode("wpt[2]/radial",029.0,"DOUBLE"));
append(m.wpt_radial,m.kns80.initNode("wpt[3]/radial",029.0,"DOUBLE"));
append(m.wpt_distance,m.kns80.initNode("wpt[0]/distance",0,"DOUBLE"));
append(m.wpt_distance,m.kns80.initNode("wpt[1]/distance",0,"DOUBLE"));
append(m.wpt_distance,m.kns80.initNode("wpt[2]/distance",0,"DOUBLE"));
append(m.wpt_distance,m.kns80.initNode("wpt[3]/distance",0,"DOUBLE"));
m.displayed_distance = m.kns80.initNode("displayed-distance",m.wpt_distance[0].getValue(),"DOUBLE");
m.displayed_frequency = m.kns80.initNode("displayed-frequency",m.wpt_freq[0].getValue(),"DOUBLE");
m.displayed_radial = m.kns80.initNode("displayed-radial",m.wpt_radial[0].getValue(),"DOUBLE");
m.NAV=props.globals.initNode("instrumentation/nav");
m.NAV1 = m.NAV.initNode("frequencies/selected-mhz");
m.NAV1_RADIAL = m.NAV.initNode("radials/selected-deg");
m.NAV1_ACTUAL = m.NAV.initNode("radials/actual-deg");
m.NAV1_TO_FLAG = m.NAV.initNode("to-flag");
m.NAV1_FROM_FLAG = m.NAV.initNode("from-flag");
m.NAV1_HEADING_NEEDLE_DEFLECTION = m.NAV.initNode("heading-needle-deflection");
m.NAV1_IN_RANGE = m.NAV.initNode("in-range");
m.NAV1_distance = m.NAV.initNode("distance");
######################>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
######################>>>>>>>>>>>>>>>>>>>>>>>>>>THE LINE BELOW WAS ADDED SINCE IT IS NEEDED
m.NAV1_RECIPROCAL = m.NAV.initNode("radials/reciprocal-radial-deg");
######################>>>>>>>>>>>>>>>>>>>>>>>>>>>THE LINE ABOVE WAS ADDED SINCE IT IS NEEDED
######################>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
m.NAV_volume = m.NAV.initNode("volume",0.2,"DOUBLE");
########################>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
########################>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>LINES BELOW COMMENTED OUT
# m.CDI_NEEDLE = props.globals.initNode("/instrumentation/gps/cdi-deflection");
# m.TO_FLAG = props.globals.initNode("/instrumentation/gps/to-flag");
# m.FROM_FLAG = props.globals.initNode("/instrumentation/gps/from-flag");
########################>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>LINES ABOVE COMMENTED OUT
########################>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
m.RNAV = m.kns80.initNode("rnav");
m.RNAV_deflection = m.RNAV.initNode("heading-needle-deflection",0,"DOUBLE");
m.RNAV_distance = m.RNAV.initNode("indicated-distance-nm",0,"DOUBLE");
m.RNAV_reciprocal = m.RNAV.initNode("reciprocal-radial-deg",0,"DOUBLE");
m.RNAV_actual_deg = m.RNAV.initNode("actual-deg",0,"DOUBLE");
m.DME_mhz = props.globals.initNode("instrumentation/dme/frequencies/selected-mhz",0,"DOUBLE");
m.DME_src = props.globals.initNode("instrumentation/dme/frequencies/source",m.nav_selected,"STRING");
m.DME_dist = props.globals.initNode("instrumentation/dme/indicated-distance-nm",0,"DOUBLE");
return m;
},
#### volume adjust ####
volume : func(vlm){
var vol = me.NAV_volume.getValue();
vol += vlm;
if(vol > 1.0)vol = 1.0;
if(vol < 0.0){
vol = 0.0;
me.serviceable.setBoolValue(0);
setprop("/instrumentation/nav/serviceable",0);
setprop("/instrumentation/dme/serviceable",0);
}
if(vol > 0.0){
me.serviceable.setBoolValue(1);
setprop("/instrumentation/nav/serviceable",1);
setprop("/instrumentation/dme/serviceable",1);
}
me.NAV_volume.setValue(vol);
},
#### dme hold ####
DME_hold : func{
var hold = me.dme_hold.getValue();
hold= 1- hold;
me.dme_hold.setValue(hold);
if(hold==1){
me.DME_mhz.setValue(me.NAV1.getValue());
me.DME_src.setValue(me.dme_selected);
}else{
me.DME_mhz.setValue(0);
me.DME_src.setValue(me.nav_selected);
}
},
#### display button ####
display_btn : func{
me.display_num +=1;
if(me.display_num>3)me.display_num=0;
me.displayed_frequency.setValue(me.wpt_freq[me.display_num].getValue());
me.displayed_distance.setValue(me.wpt_distance[me.display_num].getValue());
me.displayed_radial.setValue(me.wpt_radial[me.display_num].getValue());
me.data_mode.setValue(0);
if(me.use_num == me.display_num){
me.flasher=0;
}else{
me.flasher=1;
}
me.display.setValue(me.display_num);
},
#### use button ####
use_btn : func{
me.use_num = me.display_num;
me.flasher=0;
me.data_mode.setValue(0);
me.use.setValue(me.use_num);
me.NAV1.setValue(me.wpt_freq[me.display_num].getValue());
},
#### data button ####
data_btn : func{
var data = me.data_mode.getValue();
data +=1;
if(data > 2) data = 0;
me.data_mode.setValue(data);
},
#### data adjust ####
data_adjust : func(dtadj){
var dmode = me.data_mode.getValue();
var num = dtadj;
dtadj=0;
if(dmode == 0){
if(num == -1 or num ==1){num = num *0.05;}else{num = num *0.10;}
var newfreq = me.displayed_frequency.getValue();
newfreq += num;
if(newfreq > 118.95){newfreq -= 11.00;}
if(newfreq < 108.00){newfreq += 11.00;}
me.displayed_frequency.setValue(newfreq);
me.wpt_freq[me.display_num].setValue(newfreq);
if(me.use_num == me.display_num)me.NAV1.setValue(newfreq);
}elsif(dmode == 1){
var newrad = me.displayed_radial.getValue();
newrad += num;
if(newrad > 359){newrad -= 360;}
if(newrad < 0){newrad += 360;}
me.displayed_radial.setValue(newrad);
me.wpt_radial[me.display_num].setValue(newrad);
}elsif(dmode == 2){
var newdist = me.displayed_distance.getValue();
if(num == -1 or num ==1 ){num = num *0.1;}
newdist += num;
if(newdist > 99){newdist -= 100;}
if(newdist < 0){newdist += 100;}
me.displayed_distance.setValue(newdist);
me.wpt_distance[me.display_num].setValue(newdist);
}
},
#### update RNAV ####
# Properties
# outputs
# distance, radial from VOR Station
# rho, theta: distance and radial for phantom station
# range, bearing: distance and radial from phantom station
#### Nav Modes 0 = VOR ; 1 = VOR/PAR ; 2 = RNAV/ENR ; 3 = RNAV/APR ;
updateRNAV : func{
if(!me.NAV1_IN_RANGE.getValue()) {
return;
}
var mode = me.nav_mode.getValue() or 0;
var distance=me.DME_dist.getValue() or 0;
var selected_radial = me.NAV1_RADIAL.getValue() or 0;
var radial = me.NAV1_ACTUAL.getValue() or 0;
var rho = me.wpt_distance[me.use_num].getValue();
var theta = me.wpt_radial[me.use_num].getValue();
var fangle = 0;
var needle_deflection = 0;
var from_flag=1;
var to_flag =0;
var x1 = distance * math.cos( radial*D2R );
var y1 = distance * math.sin( radial*D2R );
var x2 = rho * math.cos( theta*D2R );
var y2 = rho * math.sin( theta*D2R );
var range = math.sqrt( (x1-x2)*(x1-x2) + (y1-y2)*(y1-y2) );
var bearing = math.atan2 (( y1-y2), (x1-x2))*R2D;
if(bearing < 0) bearing += 360;
var abearing = bearing > 180 ? bearing - 180 : bearing + 180;
if( mode == 0){
needle_deflection = (me.NAV1_HEADING_NEEDLE_DEFLECTION.getValue());
range = distance;
}
if ( mode == 1){
fangle = math.abs(selected_radial - radial);
needle_deflection = math.sin((selected_radial - radial) * D2R) * distance * 2;
range = distance;
}
if ( mode == 2){
fangle = math.abs(selected_radial - bearing);
needle_deflection = math.sin((selected_radial - bearing) * D2R) * range * 2;
}
if ( mode == 3){
fangle = math.abs(selected_radial - bearing);
needle_deflection = math.sin((selected_radial - bearing) * D2R) * range * 8;
}
#####################>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
########################>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>NOTE BELOW:
#THE "alias" OPTION HAS BEEN USED TO PASS THE VALUES GENERATED IN KNS-80 RNAV MODES TO THE
#MAIN NAV SYSTEM. THIS WAY THE NAV GOVERNED DEVICES (HSI'S CDI NEEDLE IN THIS CASE) ARE
#"SLAVED" TO THE RNAV VALUES SO WE CAN MAKE USE OF THE CDI NEEDLE AS IN NAV MODE TO FLY TO
#THE WAYPOINTS WITHOUT GPS, WHICH IS CLOSER TO THE REAL THING. THE OPTION HAS BEEN INCLUDED
#INSIDE A CONDITION THAT IS EXECUTED ONLY IF RNAV MODES (MODES 2 and 3) ARE ACTIVE. ACCORDINGLY
#AN "unalias" HAS BEEN INCLUDED AND IT IS EXECUTED EVERYTIME THE VOR OR VOR/PAR MODES ARE
#ACTIVE (MODES 0 AND 1).
if (( mode == 2) or (mode == 3)) {
props.globals.getNode("/instrumentation/nav/radials/actual-deg").alias("/instrumentation/kns-80/rnav/actual-deg");
props.globals.getNode("/instrumentation/nav/radials/reciprocal-radial-deg").alias("/instrumentation/kns-80/rnav/reciprocal-radial-deg");
props.globals.getNode("/instrumentation/nav/heading-needle-deflection").alias("/instrumentation/kns-80/rnav/heading-needle-deflection");
}
if (( mode == 0) or (mode == 1)) {
props.globals.getNode("/instrumentation/nav/radials/actual-deg").unalias("/instrumentation/kns-80/rnav/actual-deg");
props.globals.getNode("/instrumentation/nav/radials/reciprocal-radial-deg").unalias("/instrumentation/kns-80/rnav/reciprocal-radial-deg");
props.globals.getNode("/instrumentation/nav/heading-needle-deflection").unalias("/instrumentation/kns-80/rnav/heading-needle-deflection");
}
########################>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>LINES ABOVE ADDED
#########################>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>
if ( needle_deflection > 10) needle_deflection = 10;
if ( needle_deflection < -10) needle_deflection =-10;
if (fangle < 90 or fangle >270){
from_flag=1;
to_flag =0;
} else {
from_flag=0;
to_flag =1;
}
#####################
me.RNAV_deflection.setValue(needle_deflection);
########################>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
########################>>>>>>>>>>>>>>>>>>LINES BELOW COMMENTED OUT SINCE THEY ARE GPS DEPENDANT.
# me.CDI_NEEDLE.setDoubleValue(needle_deflection);
# me.TO_FLAG.setDoubleValue(to_flag);
# me.FROM_FLAG.setDoubleValue(from_flag);
########################>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>LINES ABOVE COMMENTED OUT
########################>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
me.RNAV_distance.setValue(range);
me.RNAV_reciprocal.setValue(abearing);
me.RNAV_actual_deg.setValue(bearing);
}
};
###########################################
var kns80 = KNS80.new("instrumentation/kns-80");
setlistener("/sim/signals/fdm-initialized", func {
update();
#####################>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
########################>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>LINE BELOW ADDED TO INCLUDE
#THE "flashstatus" FUNCTION INTO THE SIGNAL ABOVE.
flashstatus();
########################>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>LINE ABOVE ADDED
#########################>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
});
var update = func {
kns80.updateRNAV();
##########################>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
##########################>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> NOTE:
#THE PART OF THE FUNCTION THAT CORRESPONDS TO THE FLASHING OF THE DISPLAY DIGIT HAS BEEN SEPARATED INTO
#ANOTHER FUNCTION ("flashstatus" - the chosen name is self explanatory) THAT HAS BEEN INCLUDED IN THE
#SIGNAL ("setlistener") ABOVE TO MAKE ITS REFRESHING FREQUENCY INDEPENDENT OF THE ONE AFFECTING THE
#FUNCTION "update". THE DEFINITION OF THE FUNCTION "flashstatus" AND ITS "settimer" ARE AT THE BOTTOM OF THIS FILE.
##########################>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
##########################>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>NOTE BELOW:
#THE VALUE CHOSEN FOR THE "update" settimer MAY BE SYSTEM DEPENDANT. IN MY PERSONAL CASE IT IS THE VALUE
#THAT BEST DISPLAYS THE CDI NEEDLE IN RNAV MODES. ITS VALUE CORRESPONDS ROUGHLY TO 60Hz THAT, AGAIN IN
#MY PERSONAL CASE, IS THE SAME AS THE REFRESHING FREQUENCY OF MY MONITOR. START WITH THIS VALUE AND THEN
#YOU CAN MODIFY IT IF YOU WISH.
settimer(update,0.015);
};
#####################################>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#####################################>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>LINE BELOW ADDED
var flashstatus = func {
########################>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>LINE ABOVE ADDED
#########################>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#NOTE: BELOW IS THE PORTION OF THE ORIGINAL "update" FUNCTION THAT HAS BEEN SEPARATED. SEE NOTE ABOVE.
var fl = kns80.dsp_flash.getValue();
if(kns80.flasher){
kns80.dsp_flash.setValue(1-fl);
}else{
kns80.dsp_flash.setValue(1);
};
#####################################>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#####################################>>>>>>>>>>>>>>>>>>>>>>>LINES BELOW ADDED. SEE NOTE ABOVE.
settimer(flashstatus, 0.5);
};
#####################################>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>LINES ABOVE ADDED
#####################################>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>