579
edits
 (→How to add to aircraft:  created section)  | 
				 (→How to add to aircraft:  Found the ins.nas file, added.)  | 
				||
| Line 60: | Line 60: | ||
=== How to add to aircraft ===  | === How to add to aircraft ===  | ||
Make a xml file like in the example below. Then   | Make a ins.xml file like in the example below. Then put it in your aircraft root folder.  | ||
Do not add it in the set file.  | |||
<syntaxhighlight lang="xml">  | <syntaxhighlight lang="xml">  | ||
| Line 156: | Line 157: | ||
    </right>  |     </right>  | ||
</PropertyList>  | </PropertyList>  | ||
</syntaxhighlight>  | |||
Add this nasal file ins.nas to the aircraft and set file:  | |||
<syntaxhighlight lang="Nasal">  | |||
var inses = [];  | |||
var limit = func (n,l,h) {  | |||
	if (n<l) n=l;  | |||
	if (n>h) n=h;  | |||
	return n;  | |||
}  | |||
var errmdl = {          # drift and radio update model  | |||
        node: nil,  | |||
        delete: nil,  | |||
};  | |||
errmdl.new = func (node="/ins/drift") {  | |||
        var m = { parents: [errmdl], };  | |||
        m.node = node;  | |||
        setprop(node~"/pitcherr", rand()-0.5);  | |||
        setprop(node~"/rollerr", rand()-0.5);  | |||
        settimer(func m.run(), 0);  | |||
        return m;  | |||
}  | |||
errmdl.del = func (funct = "true") {  | |||
        me.delete = funct;  | |||
}  | |||
errmdl.run = func {  | |||
        if (me.delete == nil) settimer(func me.run(), 1);  | |||
	else {  | |||
		if (me.delete != "true") call(me.delete, nil, var err = []);  | |||
	}  | |||
        interpolate(me.node~"/pitcherr", getprop(me.node~"/pitcherr")*(0.9+0.1*rand()), 1);  | |||
        interpolate(me.node~"/rollerr", getprop(me.node~"/rollerr")*(0.9+0.1*rand()), 1);  | |||
}  | |||
errmdl.reset = func {  | |||
	setprop(me.node~"/pitcherr", rand()-0.5);  | |||
        setprop(me.node~"/rollerr", rand()-0.5);  | |||
}  | |||
var ins = {  | |||
	dtime: .1,  | |||
	latfttodeg: 0,  | |||
	nvelfps: 0,  | |||
	evelfps: 0,  | |||
	track: 0,  | |||
	magtrack: 0,  | |||
	vspeed: 0,  | |||
	gndspd: 0,  | |||
	hdg: 0,  | |||
	maghdg: 0,  | |||
	dhdg: 0,  | |||
	pitch: 0,  | |||
	dpitch: 0,  | |||
	roll: 0,  | |||
	droll: 0,  | |||
	delete: nil,  | |||
	driftrate: 0,  | |||
	mode: "off",  | |||
	alignst: 0,  | |||
};  | |||
ins.new = func (name = "ins") {  | |||
	var m = { parents: [ins], };  | |||
	m.name = name;  | |||
	m.errmdl = errmdl.new("/ins/"~name~"/drift");  | |||
	m.lat = 0;  | |||
	m.long = 0;  | |||
	m.time = getprop("/sim/time/elapsed-sec");  | |||
	setprop("/ins/"~name~"/mode", "off");  | |||
	setprop("/ins/"~name~"/lat", getprop("/position/latitude-deg"));  | |||
	setprop("/ins/"~name~"/long", getprop("/position/longitude-deg"));  | |||
	settimer(func m.run(), 0);  | |||
	return m;  | |||
}  | |||
ins.del = func (funct = "true") {  | |||
	me.delete = funct;  | |||
}  | |||
ins.nav = func {  | |||
	# Integration  | |||
	me.nvelfps = getprop("/velocities/speed-north-fps");  | |||
	me.evelfps = getprop("/velocities/speed-east-fps");  | |||
	me.vspeed = 60*getprop("/velocities/vertical-speed-fps");  | |||
	me.gndspd = math.sqrt(me.nvelfps*me.nvelfps + me.evelfps*me.evelfps) * .592483801295896;  | |||
	me.track = math.atan2(me.evelfps,me.nvelfps) * 180 / math.pi;  | |||
	me.track = me.track < 0 ? me.track+360 : me.track;  | |||
	me.magtrack = me.track-getprop("/environment/magnetic-variation-deg");  | |||
	me.magtrack = me.magtrack < 0 ? me.magtrack + 360 : me.magtrack;  | |||
	me.magtrack = me.magtrack > 360 ? me.magtrack - 360 : me.magtrack;  | |||
	me.latfttodeg = 180/((getprop("/position/sea-level-radius-ft")+getprop("/position/altitude-ft"))*math.pi);  | |||
	me.lat += getprop("/velocities/speed-north-fps")*me.dtime*me.latfttodeg;  | |||
	me.long += getprop("/velocities/speed-east-fps")*me.dtime*me.latfttodeg/math.sin((90-me.lat)*math.pi/180);  | |||
	if (me.long > 180) me.long += -360;  | |||
	if (me.long < -180) me.long += 360;             # is this right?  | |||
	me.hdg = getprop("/orientation/heading-deg");  | |||
	me.maghdg = me.hdg - getprop("/environment/magnetic-variation-deg");  | |||
	me.dhdg = getprop("/orientation/yaw-rate-degps");  | |||
	me.pitch = getprop("/orientation/pitch-deg") + getprop("/ins/"~me.name~"/drift/pitcherr");  | |||
	me.dpitch = getprop("/orientation/pitch-rate-degps");  | |||
	me.roll = getprop("/orientation/roll-deg") + getprop("/ins/"~me.name~"/drift/rollerr");  | |||
	me.droll = getprop("/orientation/roll-rate-degps");  | |||
	setprop("/ins/"~me.name~"/lat", me.lat);  | |||
	setprop("/ins/"~me.name~"/long", me.long);  | |||
	setprop("/ins/"~me.name~"/trutrack", me.track);  | |||
	setprop("/ins/"~me.name~"/magtrack", me.magtrack);  | |||
	setprop("/ins/"~me.name~"/north-velocity-fps", me.nvelfps);  | |||
	setprop("/ins/"~me.name~"/east-velocity-fps", me.evelfps);  | |||
	setprop("/ins/"~me.name~"/ground-speed", me.gndspd);  | |||
	setprop("/ins/"~me.name~"/vspeed", me.vspeed);  | |||
	setprop("/ins/"~me.name~"/truheading", me.hdg);  | |||
	setprop("/ins/"~me.name~"/magheading", me.maghdg);  | |||
	setprop("/ins/"~me.name~"/heading-rate", me.dhdg);  | |||
	setprop("/ins/"~me.name~"/pitch", me.pitch);  | |||
	setprop("/ins/"~me.name~"/pitch-rate", me.dpitch);  | |||
	setprop("/ins/"~me.name~"/roll-angle", me.roll);  | |||
	setprop("/ins/"~me.name~"/roll-rate", me.droll);  | |||
}  | |||
ins.att = func {  | |||
	var elaptm = getprop("/sim/time/elapsed-sec") - me.alignst;  | |||
	me.dhdg = getprop("/orientation/yaw-rate-degps");  | |||
	me.pitch = getprop("/orientation/pitch-deg") + getprop("/ins/"~me.name~"/drift/pitcherr");  | |||
	me.dpitch = getprop("/orientation/pitch-rate-degps");  | |||
	me.roll = getprop("/orientation/roll-deg") + getprop("/ins/"~me.name~"/drift/rollerr");  | |||
	me.droll = getprop("/orientation/roll-rate-degps");  | |||
	setprop("/ins/"~me.name~"/heading-rate", me.dhdg);  | |||
	setprop("/ins/"~me.name~"/pitch", me.pitch);  | |||
	setprop("/ins/"~me.name~"/pitch-rate", me.dpitch);  | |||
	setprop("/ins/"~me.name~"/roll-angle", me.roll);  | |||
	setprop("/ins/"~me.name~"/roll-rate", me.droll);  | |||
}  | |||
ins.align = func {  | |||
	var alignt = me.time - me.alignst;	# time since alignment started  | |||
	if (getprop("/ins/"~me.name~"/nolatlonin") != "true") {	# TODO: make this only happen once, when data is entered.  | |||
		me.lat = getprop("/ins/"~me.name~"/lat");  | |||
		me.long = getprop("/ins/"~me.name~"/long");  | |||
	} else {  | |||
		me.lat = getprop("/position/latitude-deg");  | |||
		me.long = getprop("/position/longitude-deg");  | |||
	}  | |||
	me.nvelfps = 0;  | |||
	me.evelfps = 0;  | |||
	me.vspeed = 0;  | |||
	setprop("/ins/"~me.name~"/north-velocity-fps", 0);  | |||
	setprop("/ins/"~me.name~"/east-velocity-fps", 0);  | |||
	setprop("/ins/"~me.name~"/ground-speed", 0);  | |||
	setprop("/ins/"~me.name~"/vspeed", 0);  | |||
	if (alignt > 500) {	# you don't have navigation working until after 500 seconds  | |||
		setprop("/ins/"~me.name~"/navwork", "true");  | |||
		me.hdg = getprop("/orientation/heading-deg");  | |||
		me.maghdg = me.hdg - getprop("/environment/magnetic-variation-deg");  | |||
		setprop("/ins/"~me.name~"/truheading", me.hdg);  | |||
		setprop("/ins/"~me.name~"/magheading", me.maghdg);  | |||
		setprop("/ins/"~me.name~"/done-aligning", "true");  | |||
	} else {  | |||
		setprop("/ins/"~me.name~"/done-aligning", "false");  | |||
		setprop("/ins/"~me.name~"/navwork", "false");  | |||
	}  | |||
	if (alignt > 10) {	# you don't have attitude working until after 10 seconds  | |||
		setprop("/ins/"~me.name~"/attwork", "true");  | |||
		me.pitch = getprop("/orientation/pitch-deg") + getprop("/ins/"~me.name~"/drift/pitcherr");  | |||
		me.roll = getprop("/orientation/roll-deg") + getprop("/ins/"~me.name~"/drift/rollerr");  | |||
		setprop("/ins/"~me.name~"/pitch", me.pitch);  | |||
		setprop("/ins/"~me.name~"/roll-angle", me.roll);  | |||
	} else setprop("/ins/"~me.name~"/attwork", "false");  | |||
	setprop("/ins/"~me.name~"/heading-rate", me.dhdg);  | |||
	setprop("/ins/"~me.name~"/pitch-rate", me.dpitch);  | |||
	setprop("/ins/"~me.name~"/roll-rate", me.droll);  | |||
}  | |||
ins.run = func {  | |||
	if (me.delete == nil) settimer(func me.run(), 0);  | |||
	else {  | |||
		if (me.delete != "true") call(me.delete, nil, var err = []);  | |||
	}  | |||
	if (me.mode != getprop("/ins/"~me.name~"/mode")) {  | |||
		if (me.mode == "off") {  | |||
			me.errmdl.reset();  | |||
		}  | |||
		me.mode = getprop("/ins/"~me.name~"/mode");  | |||
		if (me.mode == "align" or me.mode == "align-then-nav") {  | |||
			me.alignst = me.time;	# you have just entered alignment  | |||
		}  | |||
		if (me.mode != "nav" and me.mode != "att" and me.mode != "align" and me.mode != "align-then-nav") {  | |||
			me.mode = "off";  | |||
			setprop("/ins/"~me.name~"/mode", "off");  | |||
		}  | |||
	}  | |||
	me.dtime = getprop("/sim/time/elapsed-sec") - me.time;  | |||
	me.time += me.dtime;  | |||
	if (getprop("/ins/"~me.name~"/mode") == "nav") me.nav();  | |||
	elsif (getprop("/ins/"~me.name~"/mode") == "att") me.att();  | |||
	elsif (getprop("/ins/"~me.name~"/mode") == "align") me.align();  | |||
	elsif (getprop("/ins/"~me.name~"/mode") == "align-then-nav") {  | |||
		if (getprop("/ins/"~me.name~"/done-aligning") == "true") me.nav();  | |||
		else me.align();  | |||
	}  | |||
}  | |||
var mix = {  | |||
#       lat: 0,     # waiting until quaternions are used  | |||
#       long: 0,  | |||
	nvelfps: 0,  | |||
	evelfps: 0,  | |||
	track: 0,  | |||
	magtrack: 0,  | |||
	vspeed: 0,  | |||
	gndspd: 0,  | |||
	hdg: 0,  | |||
	maghdg: 0,  | |||
	hdgx: 0,  | |||
	hdgy: 0,  | |||
	dhdg: 0,  | |||
	pitch: 0,  | |||
	dpitch: 0,  | |||
	roll: 0,  | |||
	rollx: 0,  | |||
	rolly: 0,  | |||
	droll: 0,  | |||
};  | |||
var run = func () {  | |||
	settimer(run, 0);  | |||
	mix.nvelfps = 0;  | |||
	mix.evelfps = 0;  | |||
	mix.vspeed = 0;  | |||
	mix.gndspd = 0;  | |||
	mix.hdgx = 0;  | |||
	mix.hdgy = 0;  | |||
	mix.dhdg = 0;  | |||
	mix.pitch = 0;  | |||
	mix.dpitch = 0;  | |||
	mix.roll = 0;  | |||
	mix.rollx = 0;  | |||
	mix.rolly = 0;  | |||
	mix.droll = 0;  | |||
	for(var i=0; i<size(inses); i+=1) {  | |||
		mix.nvelfps += inses[i].nvelfps;  | |||
		mix.evelfps += inses[i].evelfps;  | |||
		mix.vspeed += inses[i].vspeed;  | |||
		mix.gndspd += inses[i].gndspd;  | |||
		mix.hdgx += math.sin(inses[i].hdg*math.pi/180);  | |||
		mix.hdgy += math.cos(inses[i].hdg*math.pi/180);  | |||
		mix.dhdg += inses[i].dhdg;  | |||
		mix.pitch += inses[i].pitch;  | |||
		mix.dpitch += inses[i].dpitch;  | |||
		mix.rollx += math.sin(inses[i].roll*math.pi/180);  | |||
		mix.rolly += math.cos(inses[i].roll*math.pi/180);  | |||
		mix.droll += inses[i].droll;  | |||
	}  | |||
	mix.nvelfps *= 1/i;  | |||
	mix.evelfps *= 1/i;  | |||
	mix.track = math.atan2(mix.evelfps, mix.nvelfps)*180/math.pi;  | |||
	mix.track = mix.track < 0 ? mix.track+360 : mix.track;  | |||
	mix.magtrack = mix.track-getprop("/environment/magnetic-variation-deg");  | |||
	mix.magtrack = mix.magtrack < 0 ? mix.magtrack + 360 : mix.magtrack;  | |||
	mix.magtrack = mix.magtrack > 360 ? mix.magtrack - 360 : mix.magtrack;  | |||
	mix.vspeed *= 1/i;  | |||
	mix.gndspd *= 1/i;  | |||
	mix.hdg = math.atan2(mix.hdgx, mix.hdgy)*180/math.pi;  | |||
	mix.hdg = mix.hdg < 0 ? mix.hdg+360 : mix.hdg;  | |||
	mix.maghdg = mix.hdg-getprop("/environment/magnetic-variation-deg");  | |||
	mix.maghdg = mix.maghdg < 0 ? mix.maghdg + 360 : mix.maghdg;  | |||
	mix.maghdg = mix.maghdg > 360 ? mix.maghdg - 360 : mix.maghdg;  | |||
	mix.dhdg *= 1/i;  | |||
	mix.pitch *= 1/i;  | |||
	mix.dpitch *= 1/i;  | |||
	mix.roll = math.atan2(mix.rollx, mix.rolly)*180/math.pi;  | |||
	mix.droll *= 1/i;  | |||
#	setprop("/ins/lat", mix.lat);  | |||
#	setprop("/ins/long", mix.long);  | |||
	setprop("/ins/trutrack", mix.track);  | |||
	setprop("/ins/magtrack", mix.magtrack);  | |||
	setprop("/ins/north-velocity-fps", mix.nvelfps);  | |||
	setprop("/ins/east-velocity-fps", mix.evelfps);  | |||
	setprop("/ins/ground-speed", mix.gndspd);  | |||
	setprop("/ins/vspeed", mix.vspeed);  | |||
	setprop("/ins/truheading", mix.hdg);  | |||
	setprop("/ins/magheading", mix.maghdg);  | |||
	setprop("/ins/heading-rate", mix.dhdg);  | |||
	setprop("/ins/pitch", mix.pitch);  | |||
	setprop("/ins/pitch-rate", mix.dpitch);  | |||
	setprop("/ins/roll-angle", mix.roll);  | |||
	setprop("/ins/roll-rate", mix.droll);  | |||
}  | |||
var main = func () {  | |||
	var path = getprop("/sim/aircraft-dir") ~ "/ins.xml";  | |||
	io.read_properties(path, "/ins");  | |||
	var inschildren = props.globals.getChild("ins").getChildren();  | |||
	for(var i=0; i<size(inschildren); i+=1) {  | |||
		inses = append(inses, ins.new(inschildren[i].getName()));  | |||
	}  | |||
	settimer(run, 0);  | |||
}  | |||
setlistener("/sim/signals/fdm-initialized", main);  | |||
</syntaxhighlight>  | </syntaxhighlight>  | ||
edits