1
0
Fork 0

Merge branch 'master' of git://gitorious.org/fg/fgdata

This commit is contained in:
BARANGER Emmanuel 2011-09-28 23:23:42 +02:00
commit 5b47a02dcf
8 changed files with 11641 additions and 0 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,477 @@
###############################################################################
##
## RAF mk9 bubble sextant.
##
## Copyright (C) 2007 - 2010 Anders Gidenstam (anders(at)gidenstam.org)
## This file is licensed under the GPL license version 2 or later.
##
###############################################################################
## NOTE: This module MUST be loaded as RAFmk9sextant;
## You can override these parameters when loading this file.
# Field of view when looking through the sextant
var FOV = 25;
# Distance from the eye to the sextant when looking through the sextant.
var VIEW_DISTANCE = 0.15;
# The view in which the sextant will be used.
var VIEW_NAME = "Cockpit View";
# The storage location and orientation.
# The location is relative to the default center for the view.
var STOWED = { position : {x:-0.3, y: 0.0, z: -0.2},
orientation : {heading : 320.0,
pitch : -45.0,
roll : 0.0}
};
## Interface functions.
var pick_up = func {
if (handling.lookthrough) return;
handling.toggle();
if (handling.enabled) {
handling.view_angle.setValue(-90.0);
handling.view_distance.setValue(2.0*VIEW_DISTANCE);
}
}
var toggle_look_through = func {
handling.toggle_look_through();
}
###############################################################################
# Bindings for mouse X and Y movements. Install these to the appropriate
# mouse mode and axes, e.g. in the -set file.
var mouseX = func {
if (!handling.enabled) return;
if(__kbd.alt.getValue()) {
var delta = 3*cmdarg().getNode("offset").getValue();
if(__kbd.shift.getValue() and handling.enabled) {
# Roll adjustment
var orient = sextant.get_orientation();
var roll = orient[2] - delta;
if(roll < -180) roll = -180;
if(roll > 180) roll = 180;
sextant.set_orientation(orient[0], orient[1], roll);
} else {
var view = "/sim/current-view/heading-offset-deg";
var val = getprop(view) - delta;
if(val < 0) val = 0;
if(val > 360) val = 360;
setprop(view, val);
}
}
}
var mouseY = func {
if (!handling.enabled) return;
if(__kbd.alt.getValue()) {
var delta = 3*cmdarg().getNode("offset").getValue();
if(__kbd.shift.getValue() and handling.enabled) {
# Altitude adjustment
sextant.adjust_altitude_fine(delta);
} else {
var view = "/sim/current-view/pitch-offset-deg";
var val = getprop(view) - delta;
if(val < -90) val = -90;
if(val > 90) val = 90;
setprop(view, val);
}
}
}
var RAD = math.pi/180;
var DEG = 180/math.pi;
###############################################################################
# Class for managing one RAF mk9 bubble sextant instrument.
var sextant = {
##################################################
init : func (n=0) {
me.UPDATE_INTERVAL = 0.0;
me.loopid = 0;
me.base =
props.globals.getNode("instrumentation/sextant["~ n ~"]/", 1);
## Instrument properties
me.pitch_err = me.base.getNode("pitch-error-deg", 1);
me.pitch_err.setDoubleValue(0);
me.roll_err = me.base.getNode("roll-error-deg", 1);
me.roll_err.setDoubleValue(0);
me.setting_min = me.base.getNode("setting/min", 1);
me.setting_min.setDoubleValue(0);
me.setting_deg1 = me.base.getNode("setting/deg1", 1);
me.setting_deg1.setDoubleValue(0); # 0 - 10 deg fractional.
me.setting_deg10 = me.base.getNode("setting/deg10", 1);
me.setting_deg10.setDoubleValue(0);
me.bubble = me.base.getNode("bubble-norm", 1);
me.bubble.setDoubleValue(0);
me.serviceable = me.base.getNode("serviceable", 1);
me.serviceable.setBoolValue(1);
## The instrument's orientation in the aircraft frame
## and position offset relative its initial position.
me.position = [me.base.getNode("offsets/x-m", 1),
me.base.getNode("offsets/y-m", 1),
me.base.getNode("offsets/z-m", 1)];
me.heading = me.base.getNode("offsets/heading-deg", 1);
me.pitch = me.base.getNode("offsets/pitch-deg", 1);
me.roll = me.base.getNode("offsets/roll-deg", 1);
me.position[0].setValue(0);
me.position[1].setValue(0);
me.position[2].setValue(0);
me.heading.setValue(0);
me.pitch.setValue(0);
me.roll.setValue(0);
me.reset();
print("RAF Mk9 bubble sextant ... initialized");
},
##################################################
set_position : func (x, y ,z) {
me.position[0].setValue(x);
me.position[1].setValue(y);
me.position[2].setValue(z);
},
##################################################
get_position : func (x, y ,z) {
return [me.position[0].getValue(),
me.position[1].getValue(),
me.position[2].getValue()];
},
##################################################
set_orientation : func (heading, pitch, roll) {
me.heading.setValue(heading);
me.pitch.setValue(pitch);
me.roll.setValue(roll);
},
##################################################
get_orientation : func () {
return [me.heading.getValue(),
me.pitch.getValue(),
me.roll.getValue()];
},
##################################################
step_10deg_knob : func (d) {
var val = me.setting_deg10.getValue() + (d < 0 ? -1 : 1);
if(val < 0) val = 0;
if(val > 8) val = 8;
me.setting_deg10.setValue(val);
},
##################################################
step_5deg_knob : func (d) {
var val = me.setting_deg1.getValue();
var new = val;
if (d <= 0 and val >= 5.0) new -= 5.0;
if (d >= 0 and val < 5.0) new += 5.0;
if(new < 0.0) new = 0;
if(new > 10.0) new = 10;
me.setting_deg1.setValue(new);
},
##################################################
step_bubble_knob : func (d) {
var val = me.bubble.getValue() + d;
if(val < 0) val = 0;
if(val > 1) val = 1;
me.bubble.setValue(val);
},
##################################################
adjust_altitude_fine : func (d) {
var val = me.setting_deg1.getValue() - d;
if(val < 0) val = 0;
if(val > 10) val = 10;
me.setting_deg1.setValue(val);
me.setting_min.setValue(60.0*val - 60*int(val));
},
##################################################
get_altitude : func {
return 10.0 * me.setting_deg10.getValue() + me.setting_deg1.getValue();
},
##################################################
reset : func {
me.loopid += 1;
me._loop_(me.loopid);
},
##################################################
update : func {
## State data we need.
var heading_ac = getprop("/orientation/heading-deg") * RAD;
var pitch_ac = getprop("/orientation/pitch-deg") * RAD;
var roll_ac = getprop("/orientation/roll-deg") * RAD;
var yaw_v = me.heading.getValue() * RAD;
var pitch_v = me.pitch.getValue() * RAD;
var roll_v = me.roll.getValue() * RAD;
## Compute local aircraft axes vectors in the local frame
## Account for aircraft orientation. (x/y/z = front/left/up)
var T_ac = mulMM(mulMM(rotateZ(heading_ac), rotateY(pitch_ac)),
rotateX(roll_ac));
## Account for view orientation and sextant settings.
## The sextant frame is assumed to coincide with the view frame
## except that it is pitched down altitude deg around its local
## Y axis.
var T_bs = mulMM(mulMM(mulMM(mulMM(
T_ac,
rotateZ(yaw_v)),
rotateY(pitch_v)),
rotateX(roll_v)),
rotateY(-me.get_altitude() * RAD));
var X_bs = mulMv(T_bs, X);
var Y_bs = mulMv(T_bs, Y);
var Z_bs = mulMv(T_bs, Z);
## Transform up in the local frame to the sextant frame.
var Up = mulMv([X_bs, Y_bs, Z_bs], Z);
var Up_xz = [Up[0], 0, Up[2]];
var Up_yz = [0, Up[1], Up[2]];
## Compute interesting angles in the sextant frame.
var p_err = angleV(Z, Up_xz);
if (scalar(Up_xz, X) < 0.0) {
p_err *= -1;
}
me.pitch_err.setValue(p_err*DEG);
var r_err = angleV(Z, Up_yz);
if (scalar(Up_yz, Y) < 0.0) {
r_err *= -1;
}
me.roll_err.setValue(r_err*DEG);
},
##################################################
_loop_ : func(id) {
id == me.loopid or return;
me.update();
settimer(func { me._loop_(id); }, me.UPDATE_INTERVAL, 1);
}
};
###############################################################################
## Singleton class for handling (i.e. moving / rotating) a sextant.
var handling = {
enabled : 0,
##################################################
init : func (n=0) {
me.UPDATE_INTERVAL = 0.0;
me.loopid = 0;
me.lookthrough = 0;
me.base =
props.globals.getNode("instrumentation/sextant["~ n ~"]/", 1);
## Instrument properties
me.altitude_deg = me.base.getNode("altitude-deg", 1);
me.altitude_deg.setDoubleValue(0);
## 3d model position properties
me.source_view = view.views[view.indexof(VIEW_NAME)];
var src = me.source_view.getNode("config");
me.offset = {x: src.getNode("z-offset-m").getValue(),
y: src.getNode("x-offset-m").getValue(),
z: src.getNode("y-offset-m").getValue()};
me.view_distance = me.base.getNode("view-distance-m", 1);
me.view_distance.setDoubleValue(2.0*VIEW_DISTANCE);
me.view_angle = me.base.getNode("view-angle-deg", 1);
me.view_angle.setDoubleValue(0.0);
sextant.init();
sextant.set_position
(STOWED.position.x,
STOWED.position.y,
STOWED.position.z);
sextant.set_orientation
(STOWED.orientation.heading,
STOWED.orientation.pitch,
STOWED.orientation.roll);
## Instrument "display"
me.display = screen.display.new(20, 10);
me.display.add(me.altitude_deg,
props.globals.getNode("/sim/time/gmt"));
me.disable();
print("RAF Mk9 bubble sextant handling ... initialized");
},
##################################################
toggle : func {
if (me.enabled) {
me.disable();
} else {
me.enable();
}
},
##################################################
enable : func {
me.enabled = 1;
me.display.toggle();
me.loopid += 1;
me._loop_(me.loopid);
},
##################################################
toggle_look_through : func {
if (!me.enabled) return;
if (!me.lookthrough) {
me.lookthrough = 1;
me.view_distance.setDoubleValue(VIEW_DISTANCE);
me.view_angle.setValue(0.0);
me.old_view = view.point.save();
setprop("/sim/current-view/field-of-view", FOV);
} else {
me.lookthrough = 0;
setprop("/sim/current-view/field-of-view",
me.old_view.getChild("field-of-view").getValue());
# view.point.restore();
me.view_angle.setValue(-90.0);
me.view_distance.setValue(2.0*VIEW_DISTANCE);
}
},
##################################################
disable : func {
me.enabled = 0;
me.lookthrough = 0;
me.display.toggle();
sextant.set_position
(STOWED.position.x,
STOWED.position.y,
STOWED.position.z);
sextant.set_orientation
(STOWED.orientation.heading,
STOWED.orientation.pitch,
STOWED.orientation.roll);
me.view_distance.setDoubleValue(0.0);
me.view_angle.setValue(0.0);
if (me.lookthrough) {
me.toggle_look_through();
}
},
##################################################
update : func {
## Move the 3d model.
if (view.current == me.source_view) {
var src = props.globals.getNode("/sim/current-view");
sextant.set_position
(src.getNode("z-offset-m").getValue() - me.offset.x,
src.getNode("x-offset-m").getValue() - me.offset.y,
src.getNode("y-offset-m").getValue() - me.offset.z);
var old = sextant.get_orientation();
sextant.set_orientation
(getprop("/sim/current-view/heading-offset-deg"),
getprop("/sim/current-view/pitch-offset-deg"),
old[2]);
me.altitude_deg.setValue(sextant.get_altitude());
}
},
##################################################
_loop_ : func(id) {
id == me.loopid and me.enabled or return;
me.update();
settimer(func { me._loop_(id); }, me.UPDATE_INTERVAL, 1);
}
};
###############################################################################
setlistener("/sim/signals/fdm-initialized", func {
handling.init();
});
###############################################################################
## Ugly matrix math as needed.
## Probably horribly inefficient matrix representation:
## M[row][col] = [[row1], [row2], [row3]]
## v[row] = [x, y, z]
var X = [1, 0, 0];
var Y = [0, 1, 0];
var Z = [0, 0, 1];
var id = [X, Y, Z];
var mulMv = func(M, v) {
return [M[0][0]*v[0] + M[0][1]*v[1] + M[0][2]*v[2],
M[1][0]*v[0] + M[1][1]*v[1] + M[1][2]*v[2],
M[2][0]*v[0] + M[2][1]*v[1] + M[2][2]*v[2]];
}
var mulMM = func(A, B) {
return [[A[0][0]*B[0][0] + A[0][1]*B[1][0] + A[0][2]*B[2][0],
A[0][0]*B[0][1] + A[0][1]*B[1][1] + A[0][2]*B[2][1],
A[0][0]*B[0][2] + A[0][1]*B[1][2] + A[0][2]*B[2][2]],
[A[1][0]*B[0][0] + A[1][1]*B[1][0] + A[1][2]*B[2][0],
A[1][0]*B[0][1] + A[1][1]*B[1][1] + A[1][2]*B[2][1],
A[1][0]*B[0][2] + A[1][1]*B[1][2] + A[1][2]*B[2][2]],
[A[2][0]*B[0][0] + A[2][1]*B[1][0] + A[2][2]*B[2][0],
A[2][0]*B[0][1] + A[2][1]*B[1][1] + A[2][2]*B[2][1],
A[2][0]*B[0][2] + A[2][1]*B[1][2] + A[2][2]*B[2][2]]];
}
var scalar = func(a, b) {
return a[0]*b[0] + a[1]*b[1] + a[2]*b[2];
}
var absV = func(a) {
return math.sqrt(scalar(a, a));
}
var crossV = func(a, b) {
return [a[1]*b[2] - a[2]*b[1],
a[2]*b[0] - a[0]*b[2],
a[0]*b[1] - a[1]*b[0]];
}
var rotateX = func (r) {
return [[1, 0, 0],
[0, math.cos(-r), -math.sin(-r)],
[0, math.sin(-r), math.cos(-r)]];
}
var rotateY = func (r) {
return [[math.cos(-r), 0, math.sin(-r)],
[0, 1, 0],
[-math.sin(-r), 0, math.cos(-r)]];
}
var rotateZ = func (r) {
return [[math.cos(r), -math.sin(r), 0],
[math.sin(r), math.cos(r), 0],
[0, 0, 1]];
}
var printMat = func (m) {
foreach (var e; m) {
if (typeof(e) == "scalar") {
print(" " ~ e);
} else {
var line = "";
foreach (var ee; e) {
line = line ~ " " ~ ee;
}
print(line);
}
}
}
var angleV = func (a, b) {
return math.acos(math.abs(scalar(a,b)) / (absV(a) * absV(b)));
}
#print("id*id=");
#printMat(mulMM(id,id));
#print("X=");
#printMat(X);
#print("RotY(45)*X=");
#printMat(mulMv(rotateY(45*math.pi/180),X));
#print("Y*X= " ~scalar(Y,X));

View file

@ -0,0 +1,520 @@
<?xml version="1.0"?>
<!--
RAF Mk9 bubble sextant.
Copyright (C) 2008 - 2010 Anders Gidenstam (anders(at)gidenstam.org)
This file is licensed under the GPL license version 2 or later.
-->
<PropertyList>
<path>RAF_Mk9_bubble_sextant.ac</path>
<!-- x/y/z == back/right/up -->
<!-- =========================================================================
Instrument function animations.
===================================================================== -->
<!-- ===================================================================== -->
<!-- Bubble movement -->
<animation>
<type>translate</type>
<object-name>bubble</object-name>
<property>instrumentation/sextant/roll-error-deg</property>
<axis>
<x>0</x>
<y>1</y>
<z>0</z>
</axis>
<interpolation>
<entry>
<ind>-4</ind>
<dep>0.008</dep>
</entry>
<entry>
<ind>0</ind>
<dep>0</dep>
</entry>
<entry>
<ind>4</ind>
<dep>-0.008</dep>
</entry>
</interpolation>
</animation>
<animation>
<type>translate</type>
<object-name>bubble</object-name>
<property>instrumentation/sextant/pitch-error-deg</property>
<axis>
<x>0</x>
<y>0</y>
<z>1</z>
</axis>
<interpolation>
<entry>
<ind>-4</ind>
<dep>0.008</dep>
</entry>
<entry>
<ind>0</ind>
<dep>0</dep>
</entry>
<entry>
<ind>4</ind>
<dep>-0.008</dep>
</entry>
</interpolation>
</animation>
<animation>
<type>scale</type>
<object-name>bubble</object-name>
<property>instrumentation/sextant/bubble-norm</property>
<x-factor>0.0</x-factor>
<x-offset>1.0</x-offset>
<y-factor>1.0</y-factor>
<y-offset>0.0</y-offset>
<z-factor>1.0</z-factor>
<z-offset>0.0</z-offset>
<center>
<x-m> -0.060 </x-m>
<y-m> 0.000 </y-m>
<z-m> 0.000 </z-m>
</center>
</animation>
<!-- If the bubble is gone the instrument is unserviceable. -->
<animation>
<type>select</type>
<object-name>bubble</object-name>
<condition>
<property>instrumentation/sextant/serviceable</property>
</condition>
</animation>
<!-- ===================================================================== -->
<!-- 10 deg setting knob -->
<animation>
<type>rotate</type>
<object-name>10_setting_knob</object-name>
<property>instrumentation/sextant/setting/deg10</property>
<factor>5.0</factor>
<offset-deg>-15.0</offset-deg>
<center>
<x-m> -0.057 </x-m>
<y-m> 0.035 </y-m>
<z-m> 0.038 </z-m>
</center>
<axis>
<x> 0.0 </x>
<y> 1.0 </y>
<z> 0.0 </z>
</axis>
</animation>
<animation>
<type>rotate</type>
<object-name>10_setting_knob_scale</object-name>
<property>instrumentation/sextant/setting/deg10</property>
<factor>5.0</factor>
<offset-deg>-15.0</offset-deg>
<center>
<x-m> -0.057 </x-m>
<y-m> 0.035 </y-m>
<z-m> 0.038 </z-m>
</center>
<axis>
<x> 0.0 </x>
<y> 1.0 </y>
<z> 0.0 </z>
</axis>
</animation>
<!-- ===================================================================== -->
<!-- Degree drum -->
<animation>
<type>rotate</type>
<object-name>degree_drum</object-name>
<property>instrumentation/sextant/setting/deg1</property>
<factor>36.0</factor>
<offset-deg>18</offset-deg>
<center>
<x-m> -0.1110 </x-m>
<y-m> 0.0150 </y-m>
<z-m> -0.0450 </z-m>
</center>
<axis>
<x> 1.0 </x>
<y> 0.0 </y>
<z> 0.0 </z>
</axis>
</animation>
<!-- ===================================================================== -->
<!-- Minute drum -->
<animation>
<type>rotate</type>
<object-name>minute_drum</object-name>
<property>instrumentation/sextant/setting/min</property>
<factor>6.0</factor>
<offset-deg>30.0</offset-deg>
<center>
<x-m> -0.1270 </x-m>
<y-m> 0.0040 </y-m>
<z-m> -0.0315 </z-m>
</center>
<axis>
<x>-1.0 </x>
<y> 0.0 </y>
<z> 0.0 </z>
</axis>
</animation>
<!-- ===================================================================== -->
<animation>
<type>rotate</type>
<object-name>slow_motion_knob</object-name>
<property>instrumentation/sextant/setting/deg1</property>
<factor>120.0</factor>
<offset-deg>0</offset-deg>
<center>
<x-m> -0.0680 </x-m>
<y-m> 0.0230 </y-m>
<z-m> 0.0090 </z-m>
</center>
<axis>
<x> 0.0 </x>
<y> 1.0 </y>
<z> 0.0 </z>
</axis>
</animation>
<!-- ===================================================================== -->
<animation>
<type>rotate</type>
<object-name>bubble_knob</object-name>
<property>instrumentation/sextant/bubble-norm</property>
<factor>360.0</factor>
<offset-deg>0</offset-deg>
<center>
<x-m> -0.0350 </x-m>
<y-m> -0.0230 </y-m>
<z-m> 0.0390 </z-m>
</center>
<axis>
<x> 0.0 </x>
<y> 1.0 </y>
<z> 0.0 </z>
</axis>
</animation>
<!-- ===================================================================== -->
<!-- Instrument control pick animations. -->
<animation>
<type>pick</type>
<object-name>10_setting_knob</object-name>
<action>
<button>0</button>
<repeatable>false</repeatable>
<binding>
<command>nasal</command>
<script>
RAFmk9sextant.sextant.step_10deg_knob(1);
</script>
</binding>
</action>
<action>
<button>1</button>
<repeatable>false</repeatable>
<binding>
<command>nasal</command>
<script>
RAFmk9sextant.sextant.step_10deg_knob(-1);
</script>
</binding>
</action>
<action>
<button>3</button>
<repeatable>false</repeatable>
<binding>
<command>nasal</command>
<script>
RAFmk9sextant.sextant.step_10deg_knob(-1);
</script>
</binding>
</action>
<action>
<button>4</button>
<repeatable>false</repeatable>
<binding>
<command>nasal</command>
<script>
RAFmk9sextant.sextant.step_10deg_knob(1);
</script>
</binding>
</action>
</animation>
<animation>
<type>pick</type>
<object-name>slow_motion_knob</object-name>
<action>
<button>0</button>
<repeatable>true</repeatable>
<binding>
<command>nasal</command>
<script>
RAFmk9sextant.sextant.adjust_altitude_fine(0.01667);
</script>
</binding>
</action>
<action>
<button>1</button>
<repeatable>true</repeatable>
<binding>
<command>nasal</command>
<script>
RAFmk9sextant.sextant.adjust_altitude_fine(-0.01667);
</script>
</binding>
</action>
<action>
<button>3</button>
<repeatable>false</repeatable>
<binding>
<command>nasal</command>
<script>
RAFmk9sextant.sextant.adjust_altitude_fine(-0.01667);
</script>
</binding>
</action>
<action>
<button>4</button>
<repeatable>false</repeatable>
<binding>
<command>nasal</command>
<script>
RAFmk9sextant.sextant.adjust_altitude_fine(0.01667);
</script>
</binding>
</action>
</animation>
<animation>
<type>pick</type>
<object-name>5_deg_knob</object-name>
<action>
<button>0</button>
<repeatable>false</repeatable>
<binding>
<command>nasal</command>
<script>
RAFmk9sextant.sextant.step_5deg_knob(0);
</script>
</binding>
</action>
</animation>
<animation>
<type>pick</type>
<object-name>bubble_knob</object-name>
<action>
<button>0</button>
<repeatable>true</repeatable>
<binding>
<command>nasal</command>
<script>
RAFmk9sextant.sextant.step_bubble_knob(0.01);
</script>
</binding>
</action>
<action>
<button>1</button>
<repeatable>true</repeatable>
<binding>
<command>nasal</command>
<script>
RAFmk9sextant.sextant.step_bubble_knob(-0.01);
</script>
</binding>
</action>
<action>
<button>3</button>
<repeatable>false</repeatable>
<binding>
<command>nasal</command>
<script>
RAFmk9sextant.sextant.step_bubble_knob(-0.01);
</script>
</binding>
</action>
<action>
<button>4</button>
<repeatable>false</repeatable>
<binding>
<command>nasal</command>
<script>
RAFmk9sextant.sextant.step_bubble_knob(0.01);
</script>
</binding>
</action>
</animation>
<!-- =========================================================================
Instrument handling animations.
===================================================================== -->
<!-- ===================================================================== -->
<animation>
<type>rotate</type>
<property>instrumentation/sextant/view-angle-deg</property>
<factor>1.0</factor>
<center>
<x-m> -0.10 </x-m>
<y-m> 0.00 </y-m>
<z-m> 0.00 </z-m>
</center>
<axis>
<x> 0.0 </x>
<y> 0.3 </y>
<z> 1.0 </z>
</axis>
</animation>
<!-- ===================================================================== -->
<!-- Offset from eye position -->
<animation>
<type>translate</type>
<property>instrumentation/sextant/view-distance-m</property>
<axis>
<x>-1.0 </x>
<y> 0.0 </y>
<z> 0.0 </z>
</axis>
<factor>1.0</factor>
</animation>
<!-- ===================================================================== -->
<animation>
<type>rotate</type>
<property>instrumentation/sextant/offsets/roll-deg</property>
<factor>1.0</factor>
<center>
<x-m> 0.00 </x-m>
<y-m> 0.00 </y-m>
<z-m> 0.00 </z-m>
</center>
<axis>
<x> 1.0 </x>
<y> 0.0 </y>
<z> 0.0 </z>
</axis>
</animation>
<animation>
<type>rotate</type>
<property>instrumentation/sextant/offsets/pitch-deg</property>
<factor>1.0</factor>
<center>
<x-m> 0.00 </x-m>
<y-m> 0.00 </y-m>
<z-m> 0.00 </z-m>
</center>
<axis>
<x> 0.0 </x>
<y> 1.0 </y>
<z> 0.0 </z>
</axis>
</animation>
<animation>
<type>rotate</type>
<property>instrumentation/sextant/offsets/heading-deg</property>
<factor>1.0</factor>
<center>
<x-m> 0.00 </x-m>
<y-m> 0.00 </y-m>
<z-m> 0.00 </z-m>
</center>
<axis>
<x> 0.0 </x>
<y> 0.0 </y>
<z> 1.0 </z>
</axis>
</animation>
<!-- ===================================================================== -->
<!-- Translations for user's view. -->
<animation>
<type>translate</type>
<property>instrumentation/sextant/offsets/x-m</property>
<axis>
<x>1</x>
<y>0</y>
<z>0</z>
</axis>
<factor>1.0</factor>
</animation>
<animation>
<type>translate</type>
<property>instrumentation/sextant/offsets/y-m</property>
<axis>
<x>0</x>
<y>1</y>
<z>0</z>
</axis>
<factor>1.0</factor>
</animation>
<animation>
<type>translate</type>
<property>instrumentation/sextant/offsets/z-m</property>
<axis>
<x>0</x>
<y>0</y>
<z>1</z>
</axis>
<factor>1.0</factor>
</animation>
<!-- ===================================================================== -->
<animation>
<type>pick</type>
<object-name>eye_piece</object-name>
<action>
<button>0</button>
<repeatable>false</repeatable>
<binding>
<command>nasal</command>
<script>
RAFmk9sextant.toggle_look_through();
</script>
</binding>
</action>
</animation>
<animation>
<type>pick</type>
<object-name>left_handle</object-name>
<action>
<button>0</button>
<repeatable>false</repeatable>
<binding>
<command>nasal</command>
<script>
RAFmk9sextant.pick_up();
</script>
</binding>
</action>
</animation>
<animation>
<type>pick</type>
<object-name>right_handle</object-name>
<action>
<button>0</button>
<repeatable>false</repeatable>
<binding>
<command>nasal</command>
<script>
RAFmk9sextant.pick_up();
</script>
</binding>
</action>
</animation>
</PropertyList>

View file

@ -0,0 +1,210 @@
Bubble sextant for Celestial Navigation in FlightGear
-----------------------------------------------------
Copyright 2007 - 2010 Anders Gidenstam
* These programs are free software; you can redistribute them and/or modify
* them 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.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Yes, the stars on the night sky in FlightGear can be used for navigation.
This short text gives a hint to how it is done. The references explain it
much better, though, so have a look there both for introduction and more
advanced topics.
Part 0 - Installing the tools: 3d bubble sextant model for FlightGear
---------------------------------------------------------------------
- The bubble sextant 3d model RAF_Mk9_bubble_sextant.xml need to be
loaded from the aircraft 3d model file and placed at the center of
the view it is intended to be used from. For example for a view located
2.5 meter behind and 2.0 meter above the aircraft origin:
(Note that any offsets of the main 3d model needs to be accounted for
in translating the view position to a 3d model position and that the
axes order differs.)
<!-- Star observer's instruments -->
<model>
<name>Bubble_sextant</name>
<path>Aircraft/Short_Empire/Instruments/BubbleSextant/RAF_Mk9_bubble_sextant.xml</path>
<offsets>
<x-m> 2.50 </x-m>
<y-m> 0.50 </y-m>
<z-m> 2.00 </z-m>
</offsets>
</model>
- The Nasal module needs to be loaded from the main aircraft -set file.
The name of the view in which the sextant will be used and
the stowed (= inactive) location of the instrument needs to be set.
The stored location is specified in a frame axis parallel with the
aircraft frame but centered at the location given for the sextant
3d model in the 3d model file.
For example:
<nasal>
<RAFmk9sextant>
<file>Aircraft/Short_Empire/Instruments/BubbleSextant/RAF_Mk9_bubble_sextant.nas</file>
<script>
var VIEW_NAME = "Star Observation View";
var STOWED = { position : {x:-0.3, y: 0.0, z: -0.2},
orientation : {heading : 320.0,
pitch : -45.0,
roll : 0.0}
};
</script>
</RAFmk9sextant>
</nasal>
- To allow fine control of the sextant using the mouse add the following
XML snippet to the aircraft's -set file.
It binds moves movements in mode 0/pointer mode to the sextant.
alt + move mouse - precision movement of view direction.
alt + shift + move mouse - up/down changes the altitude setting of the
sextant.
- left/right tilts the sextant to align with
the horizon.
<input>
<!-- Install the sextant controls in mouse mode 0. -->
<mice n="0">
<mouse n="0">
<mode n="0">
<x-axis>
<binding>
<command>nasal</command>
<script>
RAFmk9sextant.mouseX();
</script>
</binding>
</x-axis>
<y-axis>
<binding>
<command>nasal</command>
<script>
RAFmk9sextant.mouseY();
</script>
</binding>
</y-axis>
</mode>
</mouse>
</mice>
</input>
To correctly measure the altitude of a heavenly body the instrument
must be level, i.e. the bubble must be centered.
The instrument is configured for an aim-then-level method, i.e.
one first center the view on the desired object then change the altitude
and tilt settings until the instrument is level. (I.e. changing altitude
behaves as if the user changes the setting and rotates the instrument so
that it remains aimed in the same direction).
NOTE: Tilting of the instrument might still be somewhat buggy.
Part 1 - Taking sextant sights in FlightGear
-------------------------------------
What is needed?
- The celestial altitude (~angle from the horizon) for some (at least 2)
stars and the precise time of observation.
How?
- Pick up the sextant by clicking on either of its handles.
- Enter the sextant view by clicking on the sextant eye piece.
- Obtain a bubble by turning the bubble knob on the left side of
the instrument. It is possible to reach the bubble knob while in
sextant view.
- Aim the center of the view on the star. Alt + move mouse in pointer mode
enables high precision view rotation.
- Level the instrument. This is done by changing the altitude setting,
first in 10 degree steps by the coarse motion knob on the right side
of the instrument (reachable also while in sextant view) and then
with the slow motion knob (or alt+shift+move mouse up/down).
Tilt the instrument (alt+shift+move mouse right/left) as needed to
center the bubble.
- Time + celestial altitude constitutes a sighting. Make sure that
the instrument is level and aimed at the star when you note the time
and altitude.
But where are those bl**dy stars?
- I use the star charts around page 256 in "The American Practical Navigator",
http://www.nga.mil/MSISiteContent/StaticFiles/NAV_PUBS/APN/pub9.zip
to find some. For me the ones in Ursa Major was easiest to find (though
one should use a wider spread).
Suggestion (northern hemisphere):
* Dubhe (Right upper corner star of the Ursa Major "wagon".)
* Alkaid (Third and last (leftmost) star in the Ursa Major "wagon" handle.)
* Arcturus (Brightest star found to the "left" of Alkaid just below the
extended line between Alkaid and the star immediately to the
right in the Ursa Major "wagon" handle.
See star chart in [Bowditch] page 256.)
Part 2 - Computing a position
-----------------------------
The Intercept method
- Assume a position. It should be close to ones actual position - usually one
has a dead reckoning position to start from. (The assumed position need
not be equal to the DR one - one can choose a more convenient one e.g.
when using tables.)
- Compute the expected locations of the observed stars for
that position.
Use a program/website, like http://www.tecepe.com.br/cgi-win/cgiasvis.exe ,
or a Nautical Almenac + tables.
- Compare the observed star locations with the computed ones.
This gives a position line for each star. Plot the position
lines to (hopefully) get a fix.
Further info and plotting sheets: http://www.efalk.org/Navigation/
References
----------
http://www.celestialnavigation.net/
Good place to start.
http://www.efalk.org/Navigation/
Intercept method tutorial and downloadable plot sheets.
http://www.ludd.luth.se/users/kavli/peck_celestial/space.html
Longer tutorial and description. Focuses on the use of tables for sight
reductions.
http://www.tecepe.com.br/cgi-win/cgiasvis.exe
Computes star locations. Use instead of tables.
[Bowditch]
"The American Practical Navigator",
http://www.nga.mil/MSISiteContent/StaticFiles/NAV_PUBS/APN/pub9.zip
For those that really really want to learn it all :)
RAF Mk9 bubble sextant manuals and more information
http://www.users.bigpond.com/bgrobler/sextant/RAF_Mk9_manual.pdf
http://www.users.bigpond.com/bgrobler/sextant/sextant.html
http://www.physics.uq.edu.au/physics_museum/bblsex.html

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB