edf4077402
See: https://sourceforge.net/p/flightgear/codetickets/2853/ Squashed commit of the following: commit 28d4891e613f0ec14e13da2db3a1dd294ef0d922 Author: hbeni <beni@hallinger.org> Date: Tue Jan 9 08:03:40 2024 +0100 Walker menu item label changed fix #2655 see: https://sourceforge.net/p/flightgear/codetickets/2655/ commit 61adecd3b7d706ef13462e855ba9c141a8d0995b Author: hbeni <beni@hallinger.org> Date: Mon Jan 8 08:43:36 2024 +0100 Walker flashlight moved to own XML file and renamed colour-attributes to color commit ef7c6119506368abc02d9ee0c239d6fa6b0ad6af Author: hbeni <beni@hallinger.org> Date: Sun Jan 7 16:53:11 2024 +0100 Walker/Flashlight: add CTRL+F as default keybind to toggle modes commit 55d62498e5a86aa83d0447cce99ff054c0596076 Author: hbeni <beni@hallinger.org> Date: Sun Jan 7 16:25:45 2024 +0100 Dimmed walker flashlight, so it better corresponds to the old c172 one commit 0c8bc8a6c1c6c07308ddfb4d73ca6cf92fe40cae Author: hbeni <beni@hallinger.org> Date: Sun Jan 7 14:46:47 2024 +0100 Walker: Add a flashlight This adds a compositor based flashlight to the walker model. The flashlight currently has three modes: off/white/red. It can be toggled using the walker menu entry.
865 lines
33 KiB
Text
865 lines
33 KiB
Text
# == walking functions v4.3 for FlightGear version 1.9-2.0 OSG ==
|
|
# == plus coordinates for Bluebird Explorer Hovercraft 10.4 ==
|
|
|
|
# aircraft specific section:
|
|
var hatch_specs = {
|
|
z_opening_ft: 6.0,
|
|
z_floor_ft: 0, # z-axis offset for walker exit from aircraft origin
|
|
# generally floor z-axis converted to ft.
|
|
rear_hatch_loc: 5,
|
|
out_locations: func (loc) {
|
|
if (loc == 0) { # exit but not by hatch
|
|
|
|
# get default exit coordinates from set file
|
|
|
|
var defx = getprop ("sim/model/map/default_exit/x-offset-m");
|
|
var defy = getprop ("sim/model/map/default_exit/y-offset-m");
|
|
|
|
# if no exit is specified in set file, start at 0,0
|
|
|
|
if (defx == nil ) {
|
|
defx =0;
|
|
}
|
|
if (defy == nil ) {
|
|
defy =0;
|
|
}
|
|
|
|
var new_coord = xy2LatLonZ(defx,defy);
|
|
} elsif (loc == 1) {
|
|
var new_coord = xy2LatLonZ(getprop("sim/model/bluebird/crew/walker/x-offset-m"),-4.9);
|
|
} elsif (loc == 2) {
|
|
var new_coord = xy2LatLonZ(getprop("sim/model/bluebird/crew/walker/x-offset-m"),4.9);
|
|
} elsif (loc == 5) {
|
|
var new_coord = xy2LatLonZ(11.0,getprop("sim/model/bluebird/crew/walker/y-offset-m"));
|
|
} else {
|
|
var new_coord = xy2LatLonZ(xViewNode.getValue(),yViewNode.getValue());
|
|
}
|
|
return new_coord;
|
|
}
|
|
};
|
|
# end aircraft specific
|
|
|
|
var sin = func(a) { math.sin(a * math.pi / 180.0) } # degrees
|
|
var cos = func(a) { math.cos(a * math.pi / 180.0) }
|
|
var asin = func(y) { math.atan2(y, math.sqrt(1-y*y)) } # radians
|
|
var ERAD = 6378138.12; # Earth radius (m)
|
|
var ERAD_deg = 180 / (ERAD * math.pi);
|
|
var DEG2RAD = math.pi / 180;
|
|
var xViewNode = props.globals.getNode("sim/current-view/z-offset-m", 1);
|
|
var yViewNode = props.globals.getNode("sim/current-view/x-offset-m", 1);
|
|
var zViewNode = props.globals.getNode("sim/current-view/y-offset-m", 1);
|
|
var fps_node = props.globals.getNode("sim/frame-rate", 1);
|
|
var falling = 0; # 0/1 = false/true
|
|
var last_altitude = 0; # remember last position to detect falling from ground
|
|
var exit_time_sec = 0.0;
|
|
var parachute_ft = 0.0;
|
|
var parachute_deployed_sec = 0.0;
|
|
var elapsed_chute_sec = 0.0;
|
|
var lat_vector = 0.0;
|
|
var lon_vector = 0.0;
|
|
var z_vector_mps = 0.0;
|
|
var time_to_top_sec = 0.0;
|
|
var starting_lat = 0.0;
|
|
var starting_lon = 0.0;
|
|
var walk_heading = 0;
|
|
var walk_watch = 0;
|
|
var walk_factor = 1.0;
|
|
|
|
# debug section
|
|
var measure_main_count = 0;
|
|
var measure_walk_count = 0; # momentum_walk loops
|
|
var measure_extmov_count = 0;
|
|
var measure_sec = 0;
|
|
var measure_alt = 0;
|
|
var last_elapsed_sec = 0;
|
|
|
|
# ===== functions ======
|
|
var normheading = func (a) {
|
|
while (a >= 360)
|
|
a -= 360;
|
|
while (a < 0)
|
|
a += 360;
|
|
return a;
|
|
}
|
|
|
|
var distFromCraft = func (lat,lon) {
|
|
var c_lat = getprop("position/latitude-deg");
|
|
var c_lon = getprop("position/longitude-deg");
|
|
var a = sin((lat - c_lat) * 0.5);
|
|
var b = sin((lon - c_lon) * 0.5);
|
|
return 2.0 * ERAD * asin(math.sqrt(a * a + cos(lat) * cos(c_lat) * b * b));
|
|
}
|
|
|
|
var xy2LatLonZ = func (x,y) {
|
|
# given the x,y offsets of the cockpit view when walking (in meters)
|
|
# or the hatch location upon exit
|
|
# translate into lat,lon,z-offset-m for transfer to outside walker
|
|
var c_head_rad = getprop("orientation/heading-deg") * DEG2RAD;
|
|
var c_lat = getprop("position/latitude-deg");
|
|
var c_lon = getprop("position/longitude-deg");
|
|
# var c_gnd_pitch = getprop("orientation/ground-pitch");
|
|
var c_pitch = getprop("orientation/pitch-deg");
|
|
var c_roll = getprop("orientation/roll-deg");
|
|
var xZ_factor = math.cos(c_pitch * DEG2RAD);
|
|
var x_Zadjust = x * xZ_factor; # adjusted for pitch
|
|
var y_Zadjust = y * math.cos(c_roll * DEG2RAD); # adjusted for roll
|
|
# print(sprintf("W.xy2 x= %10.6f xZ= %10.6f y= %10.6f yZ= %10.6f",x,x_Zadjust,y,y_Zadjust));
|
|
var xy_hyp = math.sqrt((x_Zadjust * x_Zadjust) + (y_Zadjust * y_Zadjust));
|
|
var a = (xy_hyp == 0 ? 0 : asin(y_Zadjust / xy_hyp));
|
|
if (x > 0) {
|
|
a = math.pi - a;
|
|
}
|
|
var xy_head_rad = c_head_rad + a;
|
|
# print(sprintf ("W.xy2 c_head= %6.2f a= %6.2f xy_head= %6.2f",(c_head_rad*180/math.pi),(a*180/math.pi),(xy_head_rad*180/math.pi)));
|
|
var xy_lat_m = xy_hyp * math.cos(xy_head_rad);
|
|
var xy_lon_m = xy_hyp * math.sin(xy_head_rad);
|
|
# print(sprintf ("W.xy2 x= %9.8f y= %9.8f xy_lat_m= %9.8f xy_lon_m= %9.8f",x_Zadjust,y_Zadjust,xy_lat_m,xy_lon_m));
|
|
var xy_lat = xy_lat_m * ERAD_deg;
|
|
var xy_lon = xy_lon_m * ERAD_deg / cos(c_lat);
|
|
# print(sprintf ("W.xy2 position/lat= %9.8f lon= %9.8f xy_lat= %9.8f xy_lon= %9.8f",c_lat,c_lon,xy_lat,xy_lon));
|
|
var zxZ_m = -(x * math.sin(c_pitch * DEG2RAD));
|
|
var zyZ_m = -(y * math.sin(c_roll * DEG2RAD) * xZ_factor); # goes to zero as pitch to 90
|
|
|
|
# MARK-pre-10.4: not Perfect yet: z of hatch and height of walker (1.67m) is not adjusted for at angle.
|
|
# print (sprintf ("W.xy2 zxZ= %10.6f zyZ= %10.6f z= %10.6f",zxZ_m,zyZ_m,(zxZ_m + zyZ_m)));
|
|
return [(c_lat + xy_lat) , (c_lon + xy_lon) , (zxZ_m + zyZ_m)];
|
|
}
|
|
|
|
var calc_heading = func {
|
|
var w_forward = getprop("sim/walker/key-triggers/forward");
|
|
var w_left = getprop("sim/walker/key-triggers/slide");
|
|
var new_head = -999;
|
|
var new_walking = 0;
|
|
if (w_forward > 0) {
|
|
new_walking = 1;
|
|
if (w_left < 0) {
|
|
new_head = 45;
|
|
} elsif (w_left > 0) {
|
|
new_head = -45;
|
|
} else {
|
|
new_head = 0;
|
|
}
|
|
} elsif (w_forward < 0) {
|
|
new_walking = -1;
|
|
if (w_left < 0) {
|
|
new_head = 135;
|
|
} elsif (w_left > 0) {
|
|
new_head = -135;
|
|
} else {
|
|
new_head = 180;
|
|
}
|
|
} else {
|
|
if (w_left < 0) {
|
|
new_walking = 4;
|
|
new_head = 90;
|
|
} elsif (w_left > 0) {
|
|
new_walking = 6;
|
|
new_head = -90;
|
|
} else {
|
|
setprop ("sim/walker/walking", 0);
|
|
return 0;
|
|
}
|
|
}
|
|
walk_heading = new_head;
|
|
setprop ("sim/walker/walking", new_walking);
|
|
}
|
|
|
|
var momentum_walk = func {
|
|
measure_walk_count += 1;
|
|
if (walk_watch >= 3) {
|
|
if (walk_factor < 2.0) { # speed up when holding down key
|
|
walk_factor += 0.025;
|
|
}
|
|
setprop ("sim/walker/walking-momentum", 1);
|
|
} elsif (walk_watch >= 2) {
|
|
setprop ("sim/walker/walking-momentum", 1);
|
|
walk_watch -= 1;
|
|
} else {
|
|
walk_factor = ((walk_factor - 1.0) * 0.5) + 1.0;
|
|
if (walk_factor < 1.1) {
|
|
walk_factor = 1.0;
|
|
walk_watch = 0;
|
|
} else {
|
|
setprop ("sim/walker/walking-momentum", 1);
|
|
}
|
|
}
|
|
if (walk_watch) {
|
|
settimer(momentum_walk,0.05);
|
|
} else {
|
|
setprop ("sim/walker/walking-momentum", 0);
|
|
}
|
|
}
|
|
|
|
var main_loop = func {
|
|
measure_main_count += 1;
|
|
var c_view = getprop ("sim/current-view/view-number");
|
|
var moved = 0;
|
|
if (c_view == 0 and getprop("sim/walker/walking-momentum")) {
|
|
# inside aircraft
|
|
# bluebird.walk_about_cabin(0.1, walk_heading);
|
|
moved = 1;
|
|
}
|
|
if (getprop("sim/walker/outside")) {
|
|
if (falling or getprop("sim/walker/walking-momentum")) {
|
|
ext_mov(moved);
|
|
}
|
|
# check for proximity to hatches for entry after 0.75 sec.
|
|
var elapsed_sec = getprop("sim/time/elapsed-sec");
|
|
var elapsed_fall_sec = elapsed_sec - exit_time_sec;
|
|
if (elapsed_fall_sec > 0.75) {
|
|
if (abs(getprop("sim/walker/altitude-ft") - getprop("position/altitude-ft") + hatch_specs.z_opening_ft) < 7) {
|
|
# must be within (opening) ft vertically to climb in
|
|
var posy = getprop("sim/walker/latitude-deg");
|
|
var posx = getprop("sim/walker/longitude-deg");
|
|
|
|
# the following section is aircraft specific for locations of entry hatches and doors
|
|
# if (getprop("sim/model/bluebird/doors/door[0]/position-norm") > 0.73) {
|
|
# var door0_ll = xy2LatLonZ(-2.6,-3.42);
|
|
# var a0 = sin((door0_ll[0] - posy) * 0.5);
|
|
# var b0 = sin((door0_ll[1] - posx) * 0.5);
|
|
# doesn't actually check z-axis, mis-alignments in rare orientations
|
|
# var d0 = 2.0 * ERAD * asin(math.sqrt(a0 * a0 + cos(door0_ll[0]) * cos(posy) * b0 * b0));
|
|
# if (d0 < 1.2) {
|
|
# get_in(1);
|
|
# }
|
|
# }
|
|
# if (getprop("sim/model/bluebird/doors/door[1]/position-norm") > 0.73) {
|
|
# var door1_ll = xy2LatLonZ(-2.6,3.42);
|
|
# var a1 = sin((door1_ll[0] - posy) * 0.5);
|
|
# var b1 = sin((door1_ll[1] - posx) * 0.5);
|
|
# var d1 = 2.0 * ERAD * asin(math.sqrt(a1 * a1 + cos(door1_ll[0]) * cos(posy) * b1 * b1));
|
|
# if (d1 < 1.2) {
|
|
# get_in(2);
|
|
# }
|
|
# }
|
|
# if (getprop("sim/model/bluebird/doors/door[5]/position-norm") > 0.78) {
|
|
# var door5_ll = xy2LatLonZ(9.0,0);
|
|
# var a5 = sin((door5_ll[0] - posy) * 0.5);
|
|
# var b5 = sin((door5_ll[1] - posx) * 0.5);
|
|
# var d5 = 2.0 * ERAD * asin(math.sqrt(a5 * a5 + cos(door5_ll[0]) * cos(posy) * b5 * b5));
|
|
# if (d5 < 1.9) {
|
|
# get_in(5);
|
|
# }
|
|
# }
|
|
# end aircraft specific
|
|
|
|
}
|
|
}
|
|
} elsif (!moved and getprop("sim/walker/walking-momentum")) {
|
|
# bluebird.walk_about_cabin(0.1, walk_heading);
|
|
}
|
|
|
|
if (getprop("logging/walker-debug") and getprop("sim/walker/outside")) {
|
|
var elapsed_sec = getprop("sim/time/elapsed-sec");
|
|
var t = elapsed_sec - measure_sec;
|
|
if (t >= 0.991) {
|
|
var posz1 = getprop("sim/walker/altitude-ft");
|
|
print(sprintf("========= at %6.2f : %3i %3i %3i : Z-axis %6.2f ft / %6.4f sec = %6.2f mps",elapsed_sec,measure_main_count,measure_walk_count,measure_extmov_count,(measure_alt-posz1),t,((measure_alt-posz1)*0.3028/t)));
|
|
measure_alt = posz1;
|
|
measure_sec = elapsed_sec;
|
|
measure_main_count = 0;
|
|
measure_walk_count = 0;
|
|
measure_extmov_count = 0;
|
|
}
|
|
}
|
|
|
|
settimer(main_loop, 0.01)
|
|
}
|
|
|
|
var walker_model = {
|
|
index: 0,
|
|
add: func {
|
|
if (getprop("sim/model/crew/walker/visible")) {
|
|
if (getprop("logging/walker-position")) {
|
|
print("walker_model.add");
|
|
}
|
|
var manager = props.globals.getNode("/models", 1);
|
|
var i = 0;
|
|
for (; 1; i += 1)
|
|
if (manager.getChild("model", i, 0) == nil)
|
|
break;
|
|
|
|
props.globals.getNode("models/model[" ~ i ~ "]/path", 1);
|
|
props.globals.getNode("models/model[" ~ i ~ "]/longitude-deg-prop", 1);
|
|
props.globals.getNode("models/model[" ~ i ~ "]/latitude-deg-prop", 1);
|
|
props.globals.getNode("models/model[" ~ i ~ "]/elevation-ft-prop", 1);
|
|
props.globals.getNode("models/model[" ~ i ~ "]/heading-deg-prop", 1);
|
|
|
|
setprop ("models/model[" ~ i ~ "]/path", "Aircraft/Generic/Human/Models/walker.xml");
|
|
setprop ("models/model[" ~ i ~ "]/longitude-deg-prop", "sim/walker/longitude-deg");
|
|
setprop ("models/model[" ~ i ~ "]/latitude-deg-prop", "sim/walker/latitude-deg");
|
|
setprop ("models/model[" ~ i ~ "]/elevation-ft-prop", "sim/walker/altitude-ft");
|
|
setprop ("models/model[" ~ i ~ "]/heading-deg-prop", "sim/walker/model-heading-deg");
|
|
props.globals.getNode("models/model[" ~ i ~ "]/load", 1);
|
|
me.index = i;
|
|
}
|
|
},
|
|
remove: func {
|
|
if (getprop("logging/walker-position")) {
|
|
print("walker_model.remove");
|
|
}
|
|
props.globals.getNode("/models", 1).removeChild("model", me.index);
|
|
walker_model.reset_fall();
|
|
},
|
|
|
|
reset_fall: func {
|
|
falling = 0;
|
|
walk_factor = 1.0;
|
|
setprop("sim/walker/airborne", 0);
|
|
setprop("sim/walker/parachute-opened-altitude-ft", 0);
|
|
parachute_deployed_sec = 0;
|
|
setprop("sim/walker/parachute-opened-sec", 0);
|
|
setprop("sim/walker/starting-trajectory-lat", 0.0);
|
|
setprop("sim/walker/starting-trajectory-lon", 0.0);
|
|
setprop("sim/walker/starting-trajectory-z-mps", 0.0);
|
|
setprop("sim/walker/time-to-zero-z-sec", 0.0);
|
|
},
|
|
land: func (lon,lat,alt) {
|
|
walker_model.reset_fall();
|
|
setprop("sim/walker/latitude-deg", lat);
|
|
setprop("sim/walker/longitude-deg", lon);
|
|
setprop("sim/walker/altitude-ft", alt);
|
|
last_altitude = alt;
|
|
},
|
|
};
|
|
|
|
var open_chute = func {
|
|
if (getprop("sim/walker/airborne") and exit_time_sec and !parachute_ft and getprop("sim/walker/parachute-equipped")) {
|
|
setprop("sim/walker/parachute-opened-altitude-ft", getprop("sim/walker/altitude-ft"));
|
|
parachute_deployed_sec = getprop("sim/time/elapsed-sec");
|
|
setprop("sim/walker/parachute-opened-sec", 0);
|
|
}
|
|
}
|
|
|
|
setlistener("sim/walker/walking", func(n) {
|
|
var wdir = n.getValue();
|
|
if (wdir) { # repetitive input or bug in mod-up keeps triggering
|
|
walk_dir = wdir; # remember current direction
|
|
if (walk_watch == 0) {
|
|
walk_watch = 3; # start or reset timer for countdown
|
|
momentum_walk(); # starting from rest, start new loop
|
|
} else {
|
|
walk_watch = 3; # reset watcher
|
|
}
|
|
} else {
|
|
# last heard was zero
|
|
walk_watch -= 1;
|
|
if (walk_watch < 0) {
|
|
walk_watch = 0;
|
|
}
|
|
}
|
|
});
|
|
|
|
setlistener("sim/walker/key-triggers/outside-toggle", func {
|
|
var c_view = getprop ("sim/current-view/view-number");
|
|
if (c_view == 0) {
|
|
if (getprop("sim/walker/outside")) {
|
|
setprop("sim/current-view/view-number", view.indexof("Walk View"));
|
|
|
|
} else {
|
|
get_out(0);
|
|
}
|
|
} elsif (c_view == view.indexof("Walk View")) {
|
|
get_in(0);
|
|
} else {
|
|
if (getprop("sim/walker/outside")) {
|
|
get_in(0);
|
|
} else {
|
|
get_out(0);
|
|
}
|
|
}
|
|
});
|
|
|
|
var ext_mov = func (moved) {
|
|
measure_extmov_count += 1;
|
|
var c_view = getprop("sim/current-view/view-number");
|
|
if (c_view == view.indexof("Walker Orbit View")) {
|
|
var head_v = 360 - getprop("sim/walker/model-heading-deg");
|
|
} else {
|
|
var head_v = getprop("sim/current-view/heading-offset-deg");
|
|
}
|
|
var c_head_deg = getprop("orientation/heading-deg");
|
|
var posy1 = getprop("sim/walker/latitude-deg");
|
|
var posx1 = getprop("sim/walker/longitude-deg");
|
|
var posz1 = getprop("sim/walker/altitude-ft");
|
|
var posx2 = posx1; # new after calculations
|
|
var posy2 = posy1;
|
|
var posz2 = posz1;
|
|
var check_movement = 1;
|
|
var fps = fps_node.getValue();
|
|
fps = (fps < 10 ? 10 : fps); # only realistic above 10fps. Slow down below that so that walker pauses instead of jumping.
|
|
var speed = getprop("sim/walker/key-triggers/speed") * walk_factor / fps;
|
|
if (c_view >= 1 and c_view <=3) {
|
|
head_v = normheading(360 - c_head_deg + head_v);
|
|
} elsif (c_view == 5) {
|
|
head_v = normheading(c_head_deg + head_v + 90);
|
|
}
|
|
var head_w = normheading(head_v + walk_heading);
|
|
if (!moved) {
|
|
setprop("sim/walker/model-heading-deg" , 360 - head_v);
|
|
}
|
|
var elapsed_sec = getprop("sim/time/elapsed-sec");
|
|
if (falling) {
|
|
var elapsed_fall_sec = elapsed_sec - exit_time_sec;
|
|
if (elapsed_fall_sec > 0.1) {
|
|
check_movement = 0;
|
|
}
|
|
}
|
|
if (check_movement and !moved) {
|
|
var lat_m = speed * cos(head_w);
|
|
var lon_m = speed * sin(head_w);
|
|
var lat3 = lat_m * ERAD_deg;
|
|
var lon3 = lon_m * ERAD_deg / cos(posy1);
|
|
posx2 = posx1 - lon3; # heading is offset or reversed west to east
|
|
# if (posy1 < 0 ) {
|
|
# posy2 = posy1 + lat3;
|
|
# print (" South");
|
|
# } else {
|
|
# posy2 = posy1 + lat3;
|
|
# print (" North");
|
|
# }
|
|
posy2 = posy1 + lat3;
|
|
# posy2 = (posy1 < 0 ? posy1 - lat3 : posy1 + lat3);
|
|
# southern or northern hemisphere
|
|
}
|
|
if (falling) { # add movement from aircraft upon jumping
|
|
var parabola = 0;
|
|
var parachute_drag = 0;
|
|
var zero_xy_sec = (elapsed_fall_sec < 10 ? elapsed_fall_sec : 10.0);
|
|
if (parachute_ft) { # chute open
|
|
setprop("sim/walker/parachute-opened-sec", (elapsed_sec - parachute_deployed_sec - 1.0));
|
|
# chute starts to add drag at 1 second, fully open at 3 sec. Slows to 17 ft/sec
|
|
if (elapsed_chute_sec >= 3.0) {
|
|
parachute_drag = 0.9;
|
|
} elsif (elapsed_chute_sec >= 0.0) { # 1 second delay for chute to deploy
|
|
parachute_drag = sin(elapsed_chute_sec * 30) * 0.9; # 0 to 0.9 in 3 sec.
|
|
}
|
|
}
|
|
if (parachute_drag) {
|
|
zero_xy_sec = parachute_deployed_sec - exit_time_sec + 1.0;
|
|
if (zero_xy_sec > 10.0) {
|
|
zero_xy_sec = 10.0;
|
|
}
|
|
}
|
|
parabola = sin(90 - zero_xy_sec ) * zero_xy_sec - (0.096 * zero_xy_sec * zero_xy_sec / 2);
|
|
if (parachute_drag and zero_xy_sec < 7) {
|
|
posy2 = starting_lat + (lat_vector * parabola) + (lat_vector * parachute_drag);
|
|
posx2 = starting_lon + (lon_vector * parabola) + (lon_vector * parachute_drag);
|
|
} else {
|
|
posy2 = starting_lat + (lat_vector * parabola);
|
|
posx2 = starting_lon + (lon_vector * parabola);
|
|
}
|
|
}
|
|
var posz_geo = geo.elevation(posy2, posx2, ((posz1 * 0.3048) + 2));
|
|
if (posz_geo == nil) {
|
|
posz_geo = geo.elevation(posy2, posx2); # underground? try without current walker altitude
|
|
if (posz_geo == nil) {
|
|
posz_geo = 0;
|
|
print(sprintf("Error. Attempting to move to latitude %13.8f longitude %13.8f",posy2,posx2));
|
|
}
|
|
}
|
|
posz_geo = posz_geo / 0.3048; # convert to ft
|
|
# if (getprop("logging/walker-debug")) {
|
|
# print(sprintf("walker_lat= , %9.8f , lon= , %9.8f , groundDistanceFromAircraft= , %6.3f , geo.elev= , %8.3f , altitude= , %8.3f",posy2,posx2,distFromCraft(posy2,posx2),posz_geo,posz2));
|
|
# }
|
|
if (falling) { # 13,000 to 12,000 ft = 10 sec. 12,000 - 4,000 = 44 sec.
|
|
# 5.5 sec to cover each 1000 ft at terminal velocity (ignoring altitude density and surface area)
|
|
var dist_traveled_z = 0; # feet
|
|
if (posz_geo < posz1) { # ground is below walker
|
|
dist_traveled_z = -32.185 * time_to_top_sec * time_to_top_sec / 2; # upward half of arc
|
|
var elapsed1 = elapsed_fall_sec - time_to_top_sec;
|
|
# excludes wind resistance and cross section of projectile. Assume negligible for now.
|
|
if (elapsed_fall_sec > time_to_top_sec) { # past zero_z and falling
|
|
# drag constant is actually 0.515 kg/s for spread eagle, and 0.067 for feet first.
|
|
# I am ignoring these distinctions for now, until a more complex formula can be made,
|
|
# to go along with the new walker model visibility.
|
|
# also needs to be improved is loss of acceleration due to drag forces
|
|
if (elapsed_fall_sec > (time_to_top_sec + 5.358)) { # time to reach terminal velocity
|
|
dist_traveled_z += 461.99 + ((elapsed1 - 5.358) * 172);
|
|
} else { # 9.81m/s/s up to terminal velocity 172ft/s 54m/s spread eagle
|
|
dist_traveled_z += 32.185 * elapsed1 * elapsed1 / 2;
|
|
}
|
|
} else { # started going up, arch to zero_z before falling
|
|
dist_traveled_z += 32.185 * elapsed1 * elapsed1 / 2;
|
|
if (getprop("logging/walker-debug")) {
|
|
print(sprintf("time_to_top_sec= %6.2f elapsed1= %6.2f dist_traveled_z_ft = %8.3f z_vector_mps= %6.2f exit_alt= %9.3f posz1= %9.3f posz2= %9.3f" , time_to_top_sec,elapsed1,dist_traveled_z,z_vector_mps,getprop("sim/walker/altitude-at-exit-ft"),posz1,(getprop("sim/walker/altitude-at-exit-ft")-posz1)));
|
|
}
|
|
}
|
|
if (parachute_ft) { # chute open
|
|
# need to better model deceleration due to opening of chute, change in surface area.
|
|
var subtract_z = 0;
|
|
if (elapsed_chute_sec >= 5.0) {
|
|
subtract_z = 363.14 + ((elapsed_chute_sec - 5.0) * 155);
|
|
} elsif (elapsed_chute_sec >= 2.0) {
|
|
subtract_z = 32.15 * parachute_drag * elapsed_chute_sec * elapsed_chute_sec / 2;
|
|
} elsif (elapsed_chute_sec >= 0.0) {
|
|
subtract_z = 32.15 * parachute_drag * elapsed_chute_sec * elapsed_chute_sec / 2;
|
|
}
|
|
dist_traveled_z -= subtract_z;
|
|
}
|
|
posz2 = getprop("sim/walker/altitude-at-exit-ft") - dist_traveled_z;
|
|
if (posz2 < posz_geo) { # below ground
|
|
if ((parachute_drag < 0.7) and (dist_traveled_z > 20)) {
|
|
print(sprintf("OUCH! You fell %9.2f ft from an exit at %10.2f ft. Parachute was Not deployed.",dist_traveled_z,getprop("sim/walker/altitude-at-exit-ft")));
|
|
if (getprop("sim/current-view/view-number") == view.indexof("Walk View")) {
|
|
setprop("sim/current-view/pitch-offset-deg", -80);
|
|
}
|
|
setprop("sim/model/bluebird/position/landing-wow", 1);
|
|
setprop("sim/walker/crashed", 1);
|
|
setprop("sim/walker/airborne", 0);
|
|
}
|
|
posz2 = posz_geo;
|
|
walker_model.land(posx2,posy2,posz_geo);
|
|
} else {
|
|
if (getprop("logging/walker-position")) {
|
|
print(sprintf("falling_lat= %11.8f lon= %13.8f altitude= %9.2f elapsed_fall_sec= %5.2f speed_ft/s= %7.2f chute_drag= %4.2f",posy2,posx2,posz1,elapsed_fall_sec,((measure_alt-posz2)/(elapsed_sec - last_elapsed_sec)),parachute_drag));
|
|
measure_alt = posz2;
|
|
last_elapsed_sec = elapsed_sec;
|
|
}
|
|
}
|
|
} else {
|
|
walker_model.land(posx2,posy2,posz_geo);
|
|
posz2 = posz_geo;
|
|
}
|
|
} else { # not falling
|
|
# check for sudden change in ground elevation
|
|
if ((abs(posz1 - last_altitude) > 1.6) or ((posz_geo + 1.6) < posz1)) {
|
|
setprop("sim/walker/time-of-exit-sec", getprop("sim/time/elapsed-sec"));
|
|
setprop("sim/walker/altitude-at-exit-ft", last_altitude);
|
|
# add "forward" momentum upon step out and down
|
|
var lat_m = getprop("sim/walker/key-triggers/speed") * walk_factor * cos(head_w);
|
|
var lon_m = getprop("sim/walker/key-triggers/speed") * walk_factor * (0 - sin(head_w));
|
|
var lat3 = lat_m * ERAD_deg;
|
|
var lon3 = lon_m * ERAD_deg / cos(posy1);
|
|
posy3 = posy1 + lat3;
|
|
posx3 = posx1 + lon3;
|
|
setprop("sim/walker/starting-trajectory-lat", lat3);
|
|
setprop("sim/walker/starting-trajectory-lon", lon3);
|
|
setprop("sim/walker/starting-lat", posy2);
|
|
setprop("sim/walker/starting-lon", posx2);
|
|
setprop("sim/walker/latitude-deg", posy3);
|
|
setprop("sim/walker/longitude-deg", posx3);
|
|
setprop("sim/walker/starting-trajectory-z-mps", 0.0);
|
|
falling = 1;
|
|
if ((posz1 - posz_geo) > 50) {
|
|
setprop("sim/walker/airborne", 1);
|
|
setprop("sim/walker/parachute-equipped", 0);
|
|
}
|
|
}
|
|
if (!falling) {
|
|
if (posz_geo < (posz1 + 5)) { # walking, ground within 10 ft below walker
|
|
var posz3_geo = geo.elevation(posy2, posx2, ((posz1 * 0.3048) + 2));
|
|
if (posz3_geo == nil) {
|
|
posz3_geo = 0;
|
|
}
|
|
posz3_geo = posz3_geo / 0.3048; # convert to ft
|
|
var posz_geodiff = abs(posz_geo - posz1);
|
|
if ((posz3_geo - posz_geo) > 1.5 and posz_geodiff < 7 and posz_geodiff > 1.5) { # under object and nearly hitting head
|
|
print(sprintf ("Stopped by overhead obstruction, has height %6.2f ft above your position.", posz_geodiff));
|
|
posx2 -= (5 * (posx2 - posx1));
|
|
posy2 -= (5 * (posy2 - posy1)); # fall backward and reload ground level
|
|
posz_geo = geo.elevation(posy2, posx2, ((posz1 * 0.3048) + 1));
|
|
if (posz_geo == nil) {
|
|
posz_geo = 0;
|
|
}
|
|
posz_geo = posz_geo / 0.3048; # convert to ft
|
|
}
|
|
if ((posz1+0.3) > posz_geo or (posz1-0.3) < posz_geo) { # smoothen stride
|
|
interpolate ("sim/walker/altitude-ft", posz_geo, 0.25, 0.3);
|
|
posz2 = getprop("sim/walker/altitude-ft");
|
|
}
|
|
if (getprop("logging/walker-position")) {
|
|
print(sprintf("walker_lat= %12.8f lon= %11.8f altitude= %9.2f heading= %6.2f speed= %4.2f walk_factor= %4.2f groundDistanceFromAircraft= %3.2f geo.elev= %8.3f",posy2,posx2,posz2,head_v,speed,walk_factor,distFromCraft(posy2,posx2),posz_geo));
|
|
}
|
|
} else {
|
|
print(sprintf ("Stopped by wall, has height %6.2f ft above your position.",(posz1-posz_geo)));
|
|
posx2 -= (5 * (posx2 - posx1));
|
|
posy2 -= (5 * (posy2 - posy1));
|
|
}
|
|
}
|
|
}
|
|
setprop("sim/walker/latitude-deg", posy2);
|
|
setprop("sim/walker/longitude-deg", posx2);
|
|
last_altitude = posz2;
|
|
setprop("sim/walker/altitude-ft", posz2);
|
|
}
|
|
|
|
setlistener("sim/current-view/heading-offset-deg", func(n) {
|
|
var c_view = getprop("sim/current-view/view-number");
|
|
if (c_view == 0) {
|
|
var head_v = n.getValue();
|
|
setprop("sim/model/bluebird/crew/walker/head-offset-deg" , head_v);
|
|
} elsif (c_view == view.indexof("Walk View")) {
|
|
var head_v = n.getValue();
|
|
setprop("sim/walker/model-heading-deg" , 360 - head_v);
|
|
# } elsif (c_view == view.indexof("Walker Orbit View")) {
|
|
# var head_v = getprop("sim/current-view/heading-offset-deg");
|
|
}
|
|
});
|
|
|
|
var get_out = func (loc) {
|
|
var c_view = getprop("sim/current-view/view-number");
|
|
var head_add = 0;
|
|
if (c_view == 0) { # remember point of exit
|
|
setprop("sim/walker/keep-inside-offset-x", getprop("sim/current-view/x-offset-m"));
|
|
setprop("sim/walker/keep-inside-offset-y", getprop("sim/current-view/y-offset-m"));
|
|
setprop("sim/walker/keep-inside-offset-z", getprop("sim/current-view/z-offset-m"));
|
|
setprop("sim/walker/keep-pitch-offset-deg", getprop("sim/current-view/pitch-offset-deg"));
|
|
setprop("sim/view[110]/enabled",1);
|
|
setprop("sim/view[111]/enabled",1);
|
|
head_add = getprop("sim/current-view/heading-offset-deg");
|
|
}
|
|
var c_airspeed_mps = getprop("velocities/airspeed-kt") * 0.51444444;
|
|
var walk_dir = getprop("sim/walker/walking");
|
|
if (walk_dir and loc == hatch_specs.rear_hatch_loc) {
|
|
if (c_airspeed_mps > 0) {
|
|
c_airspeed_mps -= 1; # add momentum toward rear
|
|
} else {
|
|
c_airspeed_mps += 1;
|
|
}
|
|
}
|
|
var c_head_deg = getprop("orientation/heading-deg");
|
|
var c_pitch = getprop("orientation/pitch-deg");
|
|
# for powered ejections, add to the next line the rocket thrust
|
|
var c_z_vector_mps = sin(c_pitch) * c_airspeed_mps;
|
|
# x and y are in meters, but z axis needs to be in feet once it enters altitude calculations
|
|
setprop("sim/walker/starting-trajectory-z-mps", c_z_vector_mps);
|
|
if (c_airspeed_mps < 0) {
|
|
c_airspeed_mps = abs(c_airspeed_mps);
|
|
c_head_deg = normheading(c_head_deg + 180);
|
|
}
|
|
var c_head_rad = c_head_deg * 0.01745329252;
|
|
var c_lat = getprop("position/latitude-deg");
|
|
var c_lon = getprop("position/longitude-deg");
|
|
var xy_Z_factor = math.cos(c_pitch * 0.01745329252); # factor to zero when pitch = +- 90
|
|
var xy_lat_m = c_airspeed_mps * math.cos(c_head_rad) * xy_Z_factor;
|
|
var xy_lon_m = c_airspeed_mps * math.sin(c_head_rad) * xy_Z_factor;
|
|
var xy_lat = xy_lat_m * ERAD_deg;
|
|
var xy_lon = xy_lon_m * ERAD_deg / cos(c_lat);
|
|
setprop("sim/walker/starting-trajectory-lat", xy_lat);
|
|
setprop("sim/walker/starting-trajectory-lon", xy_lon);
|
|
var c_time0z_sec = math.sqrt(c_z_vector_mps * c_z_vector_mps / 9.81 / 9.81); # time to top of arc
|
|
if (c_z_vector_mps < 0) { # going down
|
|
c_time0z_sec = 0 - c_time0z_sec;
|
|
}
|
|
setprop("sim/walker/time-to-zero-z-sec", c_time0z_sec);
|
|
if (getprop("logging/walker-debug")) {
|
|
print(sprintf("get_out: traj-lat= %12.8f traj-lon= %12.8f c_z_vector_mps= %12.8f",xy_lat,xy_lon,c_z_vector_mps));
|
|
}
|
|
var new_coord = hatch_specs.out_locations(loc);
|
|
var head = normheading(abs(getprop("orientation/heading-deg") -360.00) + head_add);
|
|
setprop("sim/walker/latitude-deg" , (getprop("position/latitude-deg")));
|
|
setprop("sim/walker/longitude-deg" , (getprop("position/longitude-deg")));
|
|
setprop("sim/walker/roll-deg" , (getprop("orientation/roll-deg")));
|
|
setprop("sim/walker/pitch-deg" , (getprop("orientation/pitch-deg")));
|
|
setprop("sim/walker/heading-deg" , (getprop("orientation/heading-deg")));
|
|
# setprop("sim/view[100]/enabled", 1);
|
|
# setprop("sim/view[101]/enabled", 1);
|
|
var posy = new_coord[0];
|
|
var posx = new_coord[1];
|
|
var posz_ft = new_coord[2] * globals.M2FT;
|
|
setprop("sim/walker/outside", 1);
|
|
if (c_view == 0) {
|
|
setprop("sim/current-view/view-number", view.indexof("Walk View"));
|
|
setprop("sim/current-view/pitch-offset-deg", getprop("sim/walker/keep-pitch-offset-deg"));
|
|
setprop("sim/current-view/roll-offset-deg", 0);
|
|
setprop("sim/current-view/heading-offset-deg", head);
|
|
}
|
|
setprop("sim/walker/heading-deg", 0);
|
|
setprop("sim/walker/roll-deg", 0);
|
|
setprop("sim/walker/pitch-deg", 0);
|
|
setprop("sim/walker/latitude-deg", new_coord[0]);
|
|
setprop("sim/walker/longitude-deg", new_coord[1]);
|
|
falling = 1;
|
|
setprop("sim/walker/time-of-exit-sec", getprop("sim/time/elapsed-sec"));
|
|
var alt1 = getprop("position/altitude-ft") + posz_ft + hatch_specs.z_floor_ft;
|
|
setprop("sim/walker/altitude-at-exit-ft", alt1);
|
|
setprop("sim/walker/altitude-ft" , alt1);
|
|
measure_alt = alt1;
|
|
if ((alt1 - getprop("position/ground-elev-ft")) > 20) {
|
|
setprop("sim/walker/airborne", 1);
|
|
setprop("sim/walker/parachute-equipped", 1);
|
|
}
|
|
setprop("sim/walker/starting-lat", new_coord[0]);
|
|
setprop("sim/walker/starting-lon", new_coord[1]);
|
|
walk_factor = 1.0;
|
|
walker_model.add();
|
|
}
|
|
|
|
var get_in = func (loc) {
|
|
walker_model.remove();
|
|
# var c_view = getprop("sim/current-view/view-number");
|
|
# the following section is aircraft specific for locations of entry hatches and doors
|
|
# var new_pos = 4;
|
|
# var c_pos = getprop("sim/model/bluebird/crew/cockpit-position");
|
|
# if (c_view > 0) {
|
|
# if (loc == 0) { # find open hatch
|
|
# loc = 1;
|
|
# setprop("sim/model/bluebird/crew/cockpit-position", 4);
|
|
# c_pos = 5;
|
|
# } elsif (getprop("sim/model/bluebird/doors/door[1]/position-norm") > 0.2) {
|
|
# loc = 2;
|
|
# setprop("sim/model/bluebird/crew/cockpit-position", 4);
|
|
# c_pos = 5;
|
|
# } elsif (getprop("sim/model/bluebird/doors/door[5]/position-norm") > 0.2) {
|
|
# loc = 5;
|
|
# setprop("sim/model/bluebird/crew/cockpit-position", 4);
|
|
# c_pos = 5;
|
|
# }
|
|
# }
|
|
# if (loc >= 1) {
|
|
# if (c_pos == 5) {
|
|
# var new_walker_x = (loc == 1 ? -2.55 : (loc == 2 ? -2.55 : 10.0));
|
|
# var new_walker_y = (loc == 1 ? -2.8 : (loc == 2 ? 2.8 : 0));
|
|
# } else {
|
|
# if (loc == 1) {
|
|
# var new_walker_x = -2.55;
|
|
# var new_walker_y = -1.9;
|
|
# } elsif (loc == 2) {
|
|
# var new_walker_x = -2.55;
|
|
# var new_walker_y = 1.9;
|
|
# } else {
|
|
# var new_walker_x = getprop("sim/model/bluebird/crew/walker/x-offset-m");
|
|
# var new_walker_y = getprop("sim/model/bluebird/crew/walker/y-offset-m");
|
|
# if (new_walker_x < 9) {
|
|
# new_walker_x = 10.4;
|
|
# }
|
|
# if (new_walker_y < -1.6) {
|
|
# new_walker_y = -1.6;
|
|
# } elsif (new_walker_y > 1.6) {
|
|
# new_walker_y = 1.6;
|
|
# }
|
|
# }
|
|
# }
|
|
# var c_head_deg = getprop("orientation/heading-deg");
|
|
# c_pos = 5;
|
|
# var new_walker_h = normheading(getprop("sim/current-view/heading-offset-deg") + c_head_deg);
|
|
# } else {
|
|
# var new_walker_x = bluebird.cockpit_locations[c_pos].x;
|
|
# var new_walker_y = bluebird.cockpit_locations[c_pos].y;
|
|
# var new_walker_h = bluebird.cockpit_locations[c_pos].h;
|
|
# }
|
|
# var new_walker_z = bluebird.cockpit_locations[c_pos].z[0];
|
|
# var new_walker_p = bluebird.cockpit_locations[c_pos].p;
|
|
# var new_walker_fov = bluebird.cockpit_locations[c_pos].fov;
|
|
# end aircraft specific
|
|
# if (c_view == view.indexof("Walk View")) {
|
|
# setprop("sim/current-view/view-number", 0);
|
|
# setprop("sim/current-view/z-offset-m", new_walker_x);
|
|
# setprop("sim/current-view/x-offset-m", new_walker_y);
|
|
# setprop("sim/current-view/y-offset-m", new_walker_z);
|
|
# setprop("sim/current-view/goal-heading-offset-deg", new_walker_h);
|
|
# setprop("sim/current-view/heading-offset-deg", new_walker_h);
|
|
# setprop("sim/current-view/goal-pitch-offset-deg", new_walker_p);
|
|
# setprop("sim/current-view/pitch-offset-deg", new_walker_p);
|
|
# setprop("sim/current-view/field-of-view", new_walker_fov);
|
|
# }
|
|
# setprop("sim/model/bluebird/crew/walker/x-offset-m", new_walker_x);
|
|
# setprop("sim/model/bluebird/crew/walker/y-offset-m", new_walker_y);
|
|
#}
|
|
setprop("sim/current-view/view-number", 0);
|
|
setprop("sim/walker/crashed", 0);
|
|
setprop("sim/walker/airborne", 0);
|
|
setprop("sim/walker/outside", 0);
|
|
setprop("sim/walker/parachute-opened-altitude-ft", 0);
|
|
parachute_deployed_sec = 0;
|
|
setprop("sim/walker/parachute-opened-sec", 0);
|
|
setprop("sim/view[110]/enabled", 0);
|
|
setprop("sim/view[111]/enabled", 0);
|
|
}
|
|
|
|
var reinit_walker = func {
|
|
setprop("sim/walker/outside", 0);
|
|
setprop("sim/view[100]/enabled",0);
|
|
setprop("sim/view[101]/enabled",0);
|
|
setprop("sim/walker/crashed", 0);
|
|
setprop("sim/walker/airborne", 0);
|
|
falling = 0;
|
|
walk_factor = 1.0;
|
|
setprop("sim/walker/parachute-opened-altitude-ft", 0);
|
|
parachute_deployed_sec = 0;
|
|
setprop("sim/walker/parachute-opened-sec", 0);
|
|
#setprop("sim/walker/key-triggers/outside-toggle",1);
|
|
walker_model.remove();
|
|
}
|
|
|
|
var init_common = func {
|
|
setlistener("sim/walker/time-of-exit-sec", func(n) exit_time_sec = n.getValue());
|
|
|
|
setlistener("sim/walker/parachute-opened-altitude-ft", func(n) parachute_ft = n.getValue());
|
|
|
|
setlistener("sim/walker/parachute-opened-sec", func(n) elapsed_chute_sec = n.getValue());
|
|
|
|
setlistener("sim/walker/starting-trajectory-lat", func(n) lat_vector = n.getValue());
|
|
|
|
setlistener("sim/walker/starting-trajectory-lon", func(n) lon_vector = n.getValue());
|
|
|
|
setlistener("sim/walker/starting-trajectory-z-mps", func(n) z_vector_mps = n.getValue());
|
|
|
|
setlistener("sim/walker/time-to-zero-z-sec", func(n) time_to_top_sec = n.getValue());
|
|
|
|
setlistener("sim/walker/starting-lat", func(n) starting_lat = n.getValue());
|
|
|
|
setlistener("sim/walker/starting-lon", func(n) starting_lon = n.getValue());
|
|
|
|
setlistener("sim/walker/key-triggers/forward", func {
|
|
calc_heading();
|
|
});
|
|
|
|
setlistener("sim/walker/key-triggers/slide", func {
|
|
calc_heading();
|
|
});
|
|
|
|
setlistener("sim/walker/flashlight/mode", func(n) {
|
|
var mode = n.getValue();
|
|
|
|
# flashlight on/off
|
|
if (mode == 0){
|
|
setprop("sim/walker/flashlight/dim-factor", 0.0);
|
|
} else {
|
|
setprop("sim/walker/flashlight/dim-factor", getprop("sim/walker/flashlight/brightness-norm"));
|
|
}
|
|
|
|
# flashlight color
|
|
if (mode == 2) {
|
|
setprop("sim/walker/flashlight/color-red-factor", 1.0);
|
|
setprop("sim/walker/flashlight/color-green-factor", 0.0);
|
|
setprop("sim/walker/flashlight/color-blue-factor", 0.0);
|
|
} else {
|
|
setprop("sim/walker/flashlight/color-red-factor", 1.0);
|
|
setprop("sim/walker/flashlight/color-green-factor", 1.0);
|
|
setprop("sim/walker/flashlight/color-blue-factor", 1.0);
|
|
}
|
|
}, 1);
|
|
|
|
setlistener("sim/model/bluebird/crew/walker/visible", func(n) {
|
|
if (n.getValue()) {
|
|
if (getprop("sim/walker/outside")) {
|
|
walker_model.add();
|
|
}
|
|
} else {
|
|
walker_model.remove();
|
|
}
|
|
});
|
|
|
|
setlistener("sim/current-view/view-number", func(n) {
|
|
if (n.getValue() == view.indexof("Walk View")) {
|
|
yViewNode.setValue(0);
|
|
zViewNode.setValue(1.67); # matches person height when inside due to aircraft offsets
|
|
xViewNode.setValue(0);
|
|
}
|
|
});
|
|
|
|
setlistener("sim/signals/reinit", func {
|
|
reinit_walker();
|
|
});
|
|
|
|
setlistener("sim/signals/fdm-initialized", func {
|
|
reinit_walker();
|
|
});
|
|
}
|
|
settimer(init_common,0);
|
|
|
|
var theme_dialog = gui.OverlaySelector.new("Select Theme", "Aircraft/Generic/Human/Models/Themes", "sim/walker/theme-name", nil, "sim/multiplay/generic/string[10]");
|
|
var equip_dialog = gui.OverlaySelector.new("Select Equipment", "Aircraft/Generic/Human/Models/equipment/Themes", "sim/walker/equipment-name", nil, "sim/multiplay/generic/string[11]");
|
|
|