Add possibility to take off in the bush.

pull/2/head
PlayeRom 2 years ago
parent 8a0eaab753
commit 51fe8f095e

@ -24,6 +24,8 @@ Start FlightGear at any airport with your aircraft as a glider, such as ASK 21.
From the top menu, select `Aerotow Everywhere` -> `Call for Piper J3 Cub aircraft`, `Robin DR400` or `Cessna 182` (yes, you can choose from many aircrafts). The AI aircraft will appear to your right and align to the centreline of the runway in front of you. At this time you should hook up to the aircraft, most often by pressing the `Ctrl-o` key (check help of your glider). The AI aircraft will begin to accelerate and take off.
You can also take off in the bush. Then the tow plane will position itself in front of you (glider's course), so what heading you have is important. If you move away from the runway threshold further than 100 m, then the take-off of the tow plane will be as in the bush, i.e. according to the glider heading and not the runway.
## How does the AI tow aircraft fly by default?
The tow plane always takes off in front of your runway and flies along the runway for 5 km, then turns back and flies downwind for 6 km, then turns back again and flies another 6 km. During this flight it is constantly gaining altitude. Then when it has completed the entire set route it turns to unknown direction and flies at a constant altitude.

@ -44,34 +44,42 @@ var FlightPlan = {
},
#
# Get airport an runway hash where the glider is located.
# Get inital location of glider.
#
# Return hash with "airport" and "runway", otherwise nil.
# Return object with "lat", "lon" and 'heading".
#
getAirportAndRunway: func () {
getLocation: func () {
var icao = getprop("/sim/airport/closest-airport-id");
if (icao == nil) {
if (icao == nil or icao == "") {
me.message.error("Airport code cannot be obtained.");
return nil;
}
var runwayName = getprop("/sim/atc/runway");
if (runwayName == nil) {
me.message.error("Runway name cannot be obtained.");
# Find nearest runway threshold
var airport = airportinfo(icao);
if (airport == nil) {
me.message.error("An airport with the code " ~ icao ~ " cannot be found.");
return nil;
}
var airport = airportinfo(icao);
var gliderCoord = geo.aircraft_position();
if (!contains(airport.runways, runwayName)) {
me.message.error("The " ~ icao ~" airport does not have runway " ~ runwayName);
return nil;
var rwyResult = me.findRunway(airport, gliderCoord);
if (rwyResult.distance > 100) {
# The runway is too far away, we assume a bush start
return {
"type" : "bush",
"lat" : gliderCoord.lat(),
"lon" : gliderCoord.lon(),
"heading" : getprop("/orientation/heading-deg"),
};
}
var runway = airport.runways[runwayName];
# We have a runway
var minRwyLength = Aircraft.getSelected(me.addon).minRwyLength;
if (runway.length < minRwyLength) {
if (rwyResult.runway.length < minRwyLength) {
me.message.error(
"This runway is too short. Please choose a longer one than " ~ minRwyLength ~ " m "
~ "(" ~ math.round(minRwyLength * globals.M2FT) ~ " ft)."
@ -80,9 +88,36 @@ var FlightPlan = {
}
return {
"airport": airport,
"runway": runway,
"type" : "runway",
"lat" : rwyResult.runway.lat,
"lon" : rwyResult.runway.lon,
"heading" : rwyResult.runway.heading,
}
},
#
# Find nearest runway for given airport
#
# Return hash with distance to nearest runway threshold and runway object itself.
#
findRunway: func (airport, gliderCoord) {
var result = {
"runway" : nil,
"distance" : 999999999,
};
foreach (var runwayName; keys(airport.runways)) {
var runway = airport.runways[runwayName];
var rwyThreshold = geo.Coord.new().set_latlon(runway.lat, runway.lon);
var distanceToThreshold = rwyThreshold.distance_to(gliderCoord);
if (distanceToThreshold < result.distance) {
result.runway = runway;
result.distance = distanceToThreshold;
}
}
return result;
},
#
@ -91,14 +126,15 @@ var FlightPlan = {
# Return 1 on successful, otherwise 0.
#
initial: func () {
var location = me.getAirportAndRunway();
var location = me.getLocation();
if (location == nil) {
return 0;
}
var aircraft = Aircraft.getSelected(me.addon);
me.initAircraftVariable(location.airport, location.runway, 0);
var isGliderPos = 0;
me.initAircraftVariable(location, isGliderPos);
# inittial readonly waypoint
setprop(me.addonNodePath ~ "/addon-devel/route/init-wpt/heading-change", me.heading);
@ -162,7 +198,7 @@ var FlightPlan = {
generateXml: func () {
me.wptCount = 0;
var location = me.getAirportAndRunway();
var location = me.getLocation();
if (location == nil) {
return 0;
}
@ -171,16 +207,18 @@ var FlightPlan = {
var aircraft = Aircraft.getSelected(me.addon);
me.initAircraftVariable(location.airport, location.runway, 1);
var isGliderPos = 1;
me.initAircraftVariable(location, isGliderPos);
# Start at 2 o'clock from the glider...
# Inital ktas must be >= 1.0
me.addWptGround({"hdgChange": 60, "dist": 25}, {"altChange": 0, "ktas": 5});
# Reset coord and heading
me.initAircraftVariable(location.airport, location.runway, 0);
isGliderPos = 0;
me.initAircraftVariable(location, isGliderPos);
var gliderOffsetM = me.getGliderOffsetFromRunwayThreshold(location.runway);
var gliderOffsetM = me.getGliderOffsetFromRunwayThreshold(location);
# ... and line up with the runway
me.addWptGround({"hdgChange": 0, "dist": 30 + gliderOffsetM}, {"altChange": 0, "ktas": 2.5});
@ -200,7 +238,7 @@ var FlightPlan = {
me.addWptGround({"hdgChange": 0, "dist": 10 * aircraft.rolling}, {"altChange": 0, "ktas": aircraft.speed / 1.25});
me.addWptGround({"hdgChange": 0, "dist": 10 * aircraft.rolling}, {"altChange": 0, "ktas": aircraft.speed});
# Takeof
# Take-off
me.addWptAir({"hdgChange": 0, "dist": 100 * aircraft.rolling}, {"elevationPlus": 3, "ktas": aircraft.speed * 1.05});
me.addWptAir({"hdgChange": 0, "dist": 100}, {"altChange": aircraft.vs / 10, "ktas": aircraft.speed * 1.025});
@ -233,20 +271,19 @@ var FlightPlan = {
#
# Initialize AI aircraft variable
#
# airport - Object from airportinfo().
# runway - Object of runway from which the glider start.
# location - Object of location from which the glider start.
# isGliderPos - Pass 1 for set AI aircraft's coordinates as glider position, 0 set coordinates as runway threshold.
#
initAircraftVariable: func (airport, runway, isGliderPos = 1) {
initAircraftVariable: func (location, isGliderPos = 1) {
var gliderCoord = geo.aircraft_position();
# Set coordinates as glider position or runway threshold
me.coord = isGliderPos
? gliderCoord
: geo.Coord.new().set_latlon(runway.lat, runway.lon);
: geo.Coord.new().set_latlon(location.lat, location.lon);
# Set airplane heading as runway heading
me.heading = runway.heading;
# Set airplane heading as runway or glider heading
me.heading = location.heading;
# Set AI airplane altitude as glider altitude (assumed it's on the ground).
# It is more accurate than airport.elevation.
@ -256,14 +293,19 @@ var FlightPlan = {
#
# Get distance from glider to runway threshold e.g. in case that the user taxi from the runway threshold
#
# runway - Object of runway from which the glider start
# location - Object of location from which the glider start.
# Return the distance in metres, of the glider's displacement from the runway threshold.
#
getGliderOffsetFromRunwayThreshold: func (runway) {
getGliderOffsetFromRunwayThreshold: func (location) {
if (location.type == "runway") {
var gliderCoord = geo.aircraft_position();
var rwyThreshold = geo.Coord.new().set_latlon(runway.lat, runway.lon);
var rwyThreshold = geo.Coord.new().set_latlon(location.lat, location.lon);
return rwyThreshold.distance_to(gliderCoord);
}
# We are not on runway
return 0;
},
#

Loading…
Cancel
Save