User talk:Awexome/WCA
Named function arguments
#
## ##### BEGIN GPL LICENSE BLOCK #####
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of the
# License, or (at your option) any later version.
#
# More topping for your chocolate, you ask? READ below!
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details. <http://www.gnu.org/licenses/>
## ##### BEGIN GPL LICENSE BLOCK #####
# Useful References
# http://en.wikipedia.org/wiki/E6B
# http://en.wikipedia.org/wiki/Law_of_sines
# http://en.wikipedia.org/wiki/Inverse_trigonometric_functions
# Flightgear A380 project
#################################################
# Trigonometric Constants and functions #
#===============================================#
var acos = func(x) {
math.atan2(math.sqrt(1-x*x), x)
}
var asin = func(x) {
math.atan2(x,math.sqrt(math.pow(2,1-x)));
}
var degMin2rad = func(deg, min) {
var d1 = deg+(min/60);
return d1*(math.pi/180);
}
var nm2rad = func(d) {
return d*math.pi /
}
###############################################################################
# calculate WCA for course TCrs, speed of TAS, wind heading of wDir, and
# related speed of WS; and the desired unit of output [nil,0-deg; 1-rad]
#=============================================================================#
var getWCA = func {
# arguments: TCrs, TAS, WDir, WS [, optional - DEG[0|nil] | RAD[1]]
# output: WCA - Wind Correction Angle
var TCrs = arg[0] ? geo.normdeg(arg[0]) : getprop("/orientation/heading-deg");
var TAS = arg[1] or getprop("/velocities/airspeed-kt");
var WDir = arg[2] or geo.normdeg(getprop("/environment/wind-from-heading-deg") + 180);
var WS = arg[3] or getprop("/environment/wind-speed-kt");
# WCA = asin(WS90 / TAS) : WS90 - wind speed (90deg component); TAS - True Air Speed
# WS90 = WS * sin(AC - Wind)[direction in degrees];
var DEG2RAD = 0.01745329;
var WTAngle = (TCrs - WDir);
var WScoef = math.sin(WTAngle);
var WS90 = WS * WScoef;
var WCA = asin(WS90 / TAS);
return WCA * (arg[4] ? DEG2RAD : 1);
# example use for heading correction for course newCrs
# var hdg = newCrs + getWCA(newCrs);
} # getWCA
###############################################################################
# calculate distance between two GPS positions in degrees
#=============================================================================#
var calcGPSDistDeg = func (lat1, lon1, lat2, lon2) {
# arguments
var DEG2RAD = 0.01745329;
lat1 *= DEG2RAD;
lon1 *= DEG2RAD;
lat2 *= DEG2RAD;
lon2 *= DEG2RAD;
return me.calcGPSDist(lat1, lon1, lat2, lon2);
} # calcGPSDistDeg
###############################################################################
# calculate distance between two GPS positions in radians, returns NM
#=============================================================================#
var calcGPSDist = func (lat1, lon1, lat2, lon2) {
var d1 = math.sin((lat1-lat2)/2);
var p1 = math.pow(2, d1);
var dd2 = (math.sin((lon1-lon2)/2));
var d2 = math.cos(lat1)*math.cos(lat2)*dd2;
var p2 = math.pow(2, d2);
var d3 = math.sqrt(p1 + p2);
var as4 = asin(d3);
var das4rad = 2*as4;
var das4nm = das4rad*180*60/math.pi;
return das4nm;
} # calcGPSDist
###############################################################################
# calculate great circle true course using radians and distance in nm.
#=============================================================================#
var calcGPSTrueCourse = func (d, lat1, lon1, lat2, lon2) {
var tc1 = 0;
if(math.sin(lon2-lon1)<0) {
tc1=acos((math.sin(lat2)-math.sin(lat1)*math.cos(d))/(math.sin(d)*math.cos(lat1)));
}
else {
var d1 = (math.sin(lat2)-math.sin(lat1)*math.cos(d));
var d2 = (math.sin(d)*math.cos(lat1));
var dd1 = d1 / d2;
tc1=2*math.pi - math.acos(dd1);
}
return tc1;
} # calcGPSTrueCourse
###############################################################################
# calculate a coord as 'dest' that is d distance from a reference
# position(lat1,lon1) along a true course tc in radians
#=============================================================================#
var calcDistCoord = func (tc, d, lat1, lon1) {
var RAD2DEG = 57.29577951;
var lat = math.asin(math.sin(lat1)*math.cos(d)+math.cos(lat1)*math.sin(d)*math.cos(tc));
var dlon = math.atan2(math.sin(tc)*math.sin(d)*math.cos(lat1),math.cos(d)-math.sin(lat1)*math.sin(lat));
var lon = math.mod(lon1-dlon+math.pi,2*math.pi )-math.pi;
var latDeg = lat*RAD2DEG;
var lonDeg = lon*RAD2DEG;
var dest = geo.Coord.new();
dest.set_latlon(latDeg, lonDeg, 0);
return dest;
} # calcDistCoord
var calcDistCoordDeg = func(tc, d, lat1, lon1) {
var DEG2RAD = 0.01745329;
return calcDistCoord(tc*DEG2RAD, nm2rad(d), (lat1*DEG2RAD), (lon1*DEG2RAD));
} # calcDistCoordDeg
###############################################################################
# calc straight line course between two GPS coords
#=============================================================================#
var calcGPSCourse = func(lat1, lon1, lat2, lon2) {
var DEG2RAD = 0.01745329;
lat1 *= DEG2RAD;
lon1 *= DEG2RAD;
lat2 *= DEG2RAD;
lon2 *= DEG2RAD;
var sin_lat1 = math.sin(lat1);
var cos_lat1 = math.cos(lat1);
var sin_lat2 = math.sin(lat2);
var cos_lat2 = math.cos(lat2);
var dlon = lon2-lon1;
var Aorth = math.atan2(math.sin(dlon)*cos_lat2, cos_lat1*sin_lat2-sin_lat1*cos_lat2*math.cos(dlon));
var TWOPI=6.28318530;
var RAD2DEG = 57.29577951;
while ( Aorth >= TWOPI ) {Aorth -= TWOPI};
if(Aorth<0) Aorth+= TWOPI;
return (Aorth*RAD2DEG);
} # calcGPSCourse
var asin = func(x) {
math.atan2(x,math.sqrt(math.pow(2,1-x)));
}
Interesting insight. Lookign at the original GPL code, a similar comment can be made. Now to evolve this version - awexome
Question: DEG2RAD factor (and others)
Do you intentionally replicate the DEG2RAD in each function in order to prevent it from being mutated if it is a "global" DEG2RAD constant? What about turning the DEG2RAD factor into a function that simply returns the constant. What do you think? There's tons of Nasal code replicating all those constants... I do know that people do this to ensure that they are using the right constants (i.e. there are not static variables in Nasal, so things can be changed arbitrarily). I guess it would be "better" to eventually move such constants to a separate namespace and "protect" it from being mutated by using some "globals" magic, so that these symbols can no longer be overwritten.--Hooray 16:40, 10 April 2012 (EDT)