Terrain Detection

From FlightGear wiki
Jump to navigation Jump to search

In Flightgear 2017.2.1 a new Nasal method was introduced by Richard Harrison.

It works like geo.elevation but in a more general way such that one would define an arbitrary line and the method will return any terrain detection along that line.

Definition

get_cart_ground_intersection() returns where the given position in the specified direction will intersect with the ground. Returns whether or not a certain position and direction pair intersect with the ground, and if so the intersection point.

Useful for radars, terrain avoidance (GPWS), etc.

Input parameters: (geocentric coordinate system)

1. hash {"x","y","z"} position

2. hash {"x","y","z"} direction

Returns nil or geod hash {lat:deg,lon:deg,elevation:Meters} intersection

Time till impact with terrain

This example could be used in terrain detection systems that warn about impending collision with terrain.

if (getprop("velocities/speed-east-fps") != 0 or getprop("velocities/speed-north-fps") != 0) {
    var start = geo.aircraft_position();
    var speed_down_fps  = getprop("velocities/speed-down-fps");
    var speed_east_fps  = getprop("velocities/speed-east-fps");
    var speed_north_fps = getprop("velocities/speed-north-fps");
    var speed_horz_fps  = math.sqrt((speed_east_fps * speed_east_fps) + (speed_north_fps * speed_north_fps));
    var speed_fps       = math.sqrt((speed_horz_fps * speed_horz_fps) + (speed_down_fps * speed_down_fps));
    var heading = 0;

    if (speed_north_fps >= 0) {
        heading -= math.acos(speed_east_fps / speed_horz_fps) * R2D - 90;
    } else {
        heading -= -math.acos(speed_east_fps / speed_horz_fps) * R2D - 90;
    }

    heading = geo.normdeg(heading);

    var end = geo.Coord.new(start);
    end.apply_course_distance(heading, speed_horz_fps * FT2M);
    end.set_alt(end.alt() - speed_down_fps * FT2M);

    var dir_x = end.x() - start.x();
    var dir_y = end.y() - start.y();
    var dir_z = end.z() - start.z();

    var xyz = { "x": start.x(), "y": start.y(), "z": start.z() };
    var dir = { "x": dir_x,     "y": dir_y,     "z": dir_z };

    var geod = get_cart_ground_intersection(xyz, dir);
    if (geod != nil) {
        end.set_latlon(geod.lat, geod.lon, geod.elevation);
        var dist = start.direct_distance_to(end) * M2FT;
        var time = dist / speed_fps;
        setprop("/sim/model/radar/time-until-impact", time);
    } else {
        setprop("/sim/model/radar/time-until-impact", -1);
    }
}

Check for terrain between 2 aircraft

This example is typically for radar use.

var myPos = geo.aircraft_position();
var otherPos = geo.aircraft_position()
    .apply_course_distance(100, 20000); # another plane 20 Km out, bearing (true) 100

# Check for terrain between own aircraft and other:
var v = get_cart_ground_intersection(
    {
        "x": myPos.x(), 
        "y": myPos.y(), 
        "z": myPos.z(),
    },
    {
        "x": otherPos.x() - myPos.x(), 
        "y": otherPos.y() - myPos.y(), 
        "z": otherPos.z() - myPos.z(),
    },
);

if (v == nil) {
    print("No terrain, planes has clear view of each other");
} else {
    var terrain = geo.Coord.new();
    terrain.set_latlon(v.lat, v.lon, v.elevation);
    var maxDist = myPos.direct_distance_to(otherPos);
    var terrainDist = myPos.direct_distance_to(terrain);
    if (terrainDist < maxDist) {
        print("terrain found between the planes");
    } else {
        print("The planes has clear view of each other");
    }
}