Durk Talsma:
I've included the latest fixes to the Traffic Manager/AI flightplan generation code. Most of the code changes are in AIFllightplan.cxx. This is the code that runs without depending on predefined FlightPlans in #FG_ROOT/Data/AI/Flightplans.i As suggested by Dave, I've also added a new property in preferences.xml: /sim/traffic-manager/enabled, which is used to control whether or not the traffic manager is active. I'm still working on a few more 737 traffic patterns, those are going to take a little longer, so I didn't want to wait sending in this code. Finally, I haven't put much effort into ensuring "aeronautical correctness" in this version yet. The code works on my system, but what the AI plane do may actaully be quite rediculous. But I'd like to leave that for the next version.
This commit is contained in:
parent
9d972d86bf
commit
025a1e2491
3 changed files with 428 additions and 100 deletions
|
@ -17,10 +17,11 @@
|
||||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
|
||||||
|
|
||||||
#include "AIFlightPlan.hxx"
|
|
||||||
#include <simgear/misc/sg_path.hxx>
|
#include <simgear/misc/sg_path.hxx>
|
||||||
#include <simgear/debug/logstream.hxx>
|
#include <simgear/debug/logstream.hxx>
|
||||||
#include <simgear/route/waypoint.hxx>
|
#include <simgear/route/waypoint.hxx>
|
||||||
|
#include <simgear/math/sg_geodesy.hxx>
|
||||||
#include <simgear/structure/exception.hxx>
|
#include <simgear/structure/exception.hxx>
|
||||||
#include <simgear/constants.h>
|
#include <simgear/constants.h>
|
||||||
#ifdef __BORLANDC__
|
#ifdef __BORLANDC__
|
||||||
|
@ -29,6 +30,15 @@
|
||||||
#include <simgear/props/props.hxx>
|
#include <simgear/props/props.hxx>
|
||||||
#include <Main/globals.hxx>
|
#include <Main/globals.hxx>
|
||||||
#include <Main/fg_props.hxx>
|
#include <Main/fg_props.hxx>
|
||||||
|
#include <Main/fg_init.hxx>
|
||||||
|
#include <Airports/simple.hxx>
|
||||||
|
#include <Airports/runways.hxx>
|
||||||
|
|
||||||
|
|
||||||
|
#include <Environment/environment_mgr.hxx>
|
||||||
|
#include <Environment/environment.hxx>
|
||||||
|
|
||||||
|
#include "AIFlightPlan.hxx"
|
||||||
|
|
||||||
|
|
||||||
FGAIFlightPlan::FGAIFlightPlan(string filename)
|
FGAIFlightPlan::FGAIFlightPlan(string filename)
|
||||||
|
@ -84,26 +94,52 @@ FGAIFlightPlan::FGAIFlightPlan(string filename,
|
||||||
double lon,
|
double lon,
|
||||||
double alt,
|
double alt,
|
||||||
double speed,
|
double speed,
|
||||||
double course)
|
double course,
|
||||||
|
FGAirport *dep,
|
||||||
|
FGAirport *arr)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
bool useInitialWayPoint = true;
|
bool useInitialWayPoint = true;
|
||||||
|
bool useCurrentWayPoint = false;
|
||||||
SGPath path( globals->get_fg_root() );
|
SGPath path( globals->get_fg_root() );
|
||||||
path.append( ("/Data/AI/FlightPlans/" + filename).c_str() );
|
path.append( ("/Data/AI/FlightPlans/" + filename).c_str() );
|
||||||
SGPropertyNode root;
|
SGPropertyNode root;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
readProperties(path.str(), &root);
|
readProperties(path.str(), &root);
|
||||||
} catch (const sg_exception &e) {
|
|
||||||
SG_LOG(SG_GENERAL, SG_ALERT,
|
SGPropertyNode * node = root.getNode("flightplan");
|
||||||
"Error reading AI flight plan: ");
|
|
||||||
cout << path.str() << endl;
|
//waypoints.push_back( init_waypoint );
|
||||||
return;
|
for (int i = 0; i < node->nChildren(); i++) {
|
||||||
|
//cout << "Reading waypoint " << i << endl;
|
||||||
|
waypoint* wpt = new waypoint;
|
||||||
|
SGPropertyNode * wpt_node = node->getChild(i);
|
||||||
|
wpt->name = wpt_node->getStringValue("name", "END");
|
||||||
|
wpt->latitude = wpt_node->getDoubleValue("lat", 0);
|
||||||
|
wpt->longitude = wpt_node->getDoubleValue("lon", 0);
|
||||||
|
wpt->altitude = wpt_node->getDoubleValue("alt", 0);
|
||||||
|
wpt->speed = wpt_node->getDoubleValue("ktas", 0);
|
||||||
|
//wpt->speed = speed;
|
||||||
|
wpt->crossat = wpt_node->getDoubleValue("crossat", -10000);
|
||||||
|
wpt->gear_down = wpt_node->getBoolValue("gear-down", false);
|
||||||
|
wpt->flaps_down= wpt_node->getBoolValue("flaps-down", false);
|
||||||
|
|
||||||
|
if (wpt->name == "END") wpt->finished = true;
|
||||||
|
else wpt->finished = false;
|
||||||
|
waypoints.push_back(wpt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (const sg_exception &e) {
|
||||||
|
//SG_LOG(SG_GENERAL, SG_ALERT,
|
||||||
|
// "Error reading AI flight plan: ");
|
||||||
|
// cout << path.str() << endl;
|
||||||
|
// cout << "Trying to create this plan dynamically" << endl;
|
||||||
|
// cout << "Route from " << dep->id << " to " << arr->id << endl;
|
||||||
|
create(dep,arr, alt, speed);
|
||||||
|
// Now that we have dynamically created a flight plan,
|
||||||
|
// we need to add some code that pops any waypoints already past.
|
||||||
|
//return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SGPropertyNode * node = root.getNode("flightplan");
|
|
||||||
// First waypoint is current position of the aircraft as
|
|
||||||
// dictated by the traffic manager.
|
|
||||||
waypoint* init_waypoint = new waypoint;
|
waypoint* init_waypoint = new waypoint;
|
||||||
init_waypoint->name = string("initial position");
|
init_waypoint->name = string("initial position");
|
||||||
init_waypoint->latitude = lat;
|
init_waypoint->latitude = lat;
|
||||||
|
@ -113,77 +149,74 @@ FGAIFlightPlan::FGAIFlightPlan(string filename,
|
||||||
init_waypoint->crossat = - 10000;
|
init_waypoint->crossat = - 10000;
|
||||||
init_waypoint->gear_down = false;
|
init_waypoint->gear_down = false;
|
||||||
init_waypoint->flaps_down = false;
|
init_waypoint->flaps_down = false;
|
||||||
waypoints.push_back( init_waypoint );
|
init_waypoint->finished = false;
|
||||||
for (i = 0; i < node->nChildren(); i++) {
|
|
||||||
//cout << "Reading waypoint " << i << endl;
|
|
||||||
waypoint* wpt = new waypoint;
|
|
||||||
SGPropertyNode * wpt_node = node->getChild(i);
|
|
||||||
wpt->name = wpt_node->getStringValue("name", "END");
|
|
||||||
wpt->latitude = wpt_node->getDoubleValue("lat", 0);
|
|
||||||
wpt->longitude = wpt_node->getDoubleValue("lon", 0);
|
|
||||||
wpt->altitude = wpt_node->getDoubleValue("alt", 0);
|
|
||||||
wpt->speed = wpt_node->getDoubleValue("ktas", 0);
|
|
||||||
//wpt->speed = speed;
|
|
||||||
wpt->crossat = wpt_node->getDoubleValue("crossat", -10000);
|
|
||||||
wpt->gear_down = wpt_node->getBoolValue("gear-down", false);
|
|
||||||
wpt->flaps_down= wpt_node->getBoolValue("flaps-down", false);
|
|
||||||
|
|
||||||
if (wpt->name == "END") wpt->finished = true;
|
wpt_vector_iterator i = waypoints.begin();
|
||||||
else wpt->finished = false;
|
while (i != waypoints.end())
|
||||||
// discard this waypoint if it's bearing differs more than
|
{
|
||||||
// 90 degrees from the course we should fly according to the
|
//cerr << "Checking status of each waypoint: " << (*i)->name << endl;
|
||||||
// Traffic manager. Those are considered "behind" us.
|
SGWayPoint first(init_waypoint->longitude,
|
||||||
SGWayPoint first(init_waypoint->longitude,
|
init_waypoint->latitude,
|
||||||
init_waypoint->latitude,
|
init_waypoint->altitude);
|
||||||
init_waypoint->altitude);
|
SGWayPoint curr ((*i)->longitude,
|
||||||
SGWayPoint curr (wpt->longitude,
|
(*i)->latitude,
|
||||||
wpt->latitude,
|
(*i)->altitude);
|
||||||
wpt->altitude);
|
double crse, crsDiff;
|
||||||
double crse, crsDiff;
|
double dist;
|
||||||
double dist;
|
first.CourseAndDistance(curr, &crse, &dist);
|
||||||
first.CourseAndDistance(curr, &crse, &dist);
|
|
||||||
|
dist *= SG_METER_TO_NM;
|
||||||
dist *= SG_METER_TO_NM;
|
|
||||||
|
// We're only interested in the absolute value of crsDiff
|
||||||
// We're only interested in the absolute value of crsDiff
|
// wich should fall in the 0-180 deg range.
|
||||||
// wich should fall in the 0-180 deg range.
|
crsDiff = fabs(crse-course);
|
||||||
crsDiff = fabs(crse-course);
|
if (crsDiff > 180)
|
||||||
if (crsDiff > 180)
|
crsDiff = 360-crsDiff;
|
||||||
crsDiff -= 180;
|
// These are the three conditions that we consider including
|
||||||
// These are the threee conditions that we consder including
|
// in our flight plan:
|
||||||
// in our flight plan:
|
// 1) current waypoint is less then 100 miles away OR
|
||||||
// 1) current waypoint is less then 100 miles away OR
|
// 2) curren waypoint is ahead of us, at any distance
|
||||||
// 2) curren waypoint is ahead of us, at any distance
|
|
||||||
bool useWpt = false;
|
|
||||||
if ((dist > 100.0) && (crsDiff > 90.0) && (wpt->name != string ("EOF")))
|
|
||||||
{
|
|
||||||
//useWpt = false;
|
|
||||||
// Once we start including waypoints, we have to continue, even though
|
|
||||||
// one of the following way point would suffice.
|
|
||||||
// so once is the useWpt flag is set to true, we cannot reset it to false.
|
|
||||||
// cerr << "Discarding waypoint: " << wpt->name
|
|
||||||
// << ": Course difference = " << crsDiff << endl;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
useWpt = true;
|
|
||||||
|
|
||||||
if (useWpt)
|
if ((dist > 20.0) && (crsDiff > 90.0) && ((*i)->name != string ("EOF")))
|
||||||
{
|
{
|
||||||
if ((dist > 100.0) && (useInitialWayPoint))
|
//useWpt = false;
|
||||||
{
|
// Once we start including waypoints, we have to continue, even though
|
||||||
waypoints.push_back(init_waypoint);
|
// one of the following way point would suffice.
|
||||||
//cerr << "Using waypoint : " << init_waypoint->name << endl;
|
// so once is the useWpt flag is set to true, we cannot reset it to false.
|
||||||
}
|
//cerr << "Discarding waypoint: " << (*i)->name
|
||||||
waypoints.push_back( wpt );
|
// << ": Course difference = " << crsDiff
|
||||||
//cerr << "Using waypoint : " << wpt->name
|
// << "Course = " << course
|
||||||
// << ": course diff : " << crsDiff
|
// << "crse = " << crse << endl;
|
||||||
// << "distance : " << dist << endl;
|
}
|
||||||
useInitialWayPoint = false;
|
else
|
||||||
}
|
useCurrentWayPoint = true;
|
||||||
else
|
|
||||||
delete wpt;
|
if (useCurrentWayPoint)
|
||||||
}
|
{
|
||||||
|
if ((dist > 100.0) && (useInitialWayPoint))
|
||||||
|
{
|
||||||
|
//waypoints.push_back(init_waypoint);
|
||||||
|
waypoints.insert(i, init_waypoint);
|
||||||
|
//cerr << "Using waypoint : " << init_waypoint->name << endl;
|
||||||
|
}
|
||||||
|
//waypoints.push_back( wpt );
|
||||||
|
//cerr << "Using waypoint : " << (*i)->name
|
||||||
|
// << ": course diff : " << crsDiff
|
||||||
|
// << "Course = " << course
|
||||||
|
// << "crse = " << crse << endl
|
||||||
|
// << "distance : " << dist << endl;
|
||||||
|
useInitialWayPoint = false;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//delete wpt;
|
||||||
|
delete *(i);
|
||||||
|
i = waypoints.erase(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//for (i = waypoints.begin(); i != waypoints.end(); i++)
|
||||||
|
// cerr << "Using waypoint : " << (*i)->name << endl;
|
||||||
wpt_iterator = waypoints.begin();
|
wpt_iterator = waypoints.begin();
|
||||||
//cout << waypoints.size() << " waypoints read." << endl;
|
//cout << waypoints.size() << " waypoints read." << endl;
|
||||||
}
|
}
|
||||||
|
@ -301,3 +334,292 @@ double FGAIFlightPlan::getBearing(double lat, double lon, waypoint* wp){
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* FGAIFlightPlan::create()
|
||||||
|
* dynamically create a flight plan for AI traffic, based on data provided by the
|
||||||
|
* Traffic Manager, when reading a filed flightplan failes. (DT, 2004/07/10)
|
||||||
|
*
|
||||||
|
* Probably need to split this into separate functions for different parts of the flight
|
||||||
|
|
||||||
|
* once the code matures a bit more.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void FGAIFlightPlan::create(FGAirport *dep, FGAirport *arr, double alt, double speed)
|
||||||
|
{
|
||||||
|
double wind_speed;
|
||||||
|
double wind_heading;
|
||||||
|
FGRunway rwy;
|
||||||
|
|
||||||
|
//waypoints.push_back(wpt);
|
||||||
|
// Create the outbound taxi leg, for now simplified as a
|
||||||
|
// Direct route from the airport center point to the start
|
||||||
|
// of the runway.
|
||||||
|
///////////////////////////////////////////////////////////
|
||||||
|
//cerr << "Cruise Alt << " << alt << endl;
|
||||||
|
waypoint *wpt = new waypoint;
|
||||||
|
wpt->name = dep->id; //wpt_node->getStringValue("name", "END");
|
||||||
|
wpt->latitude = dep->latitude;
|
||||||
|
wpt->longitude = dep->longitude;
|
||||||
|
wpt->altitude = dep->elevation + 19; // probably need to add some model height to it
|
||||||
|
wpt->speed = 15;
|
||||||
|
wpt->crossat = -10000;
|
||||||
|
wpt->gear_down = true;
|
||||||
|
wpt->flaps_down= true;
|
||||||
|
wpt->finished = false;
|
||||||
|
waypoints.push_back(wpt);
|
||||||
|
|
||||||
|
// Get the current active runway, based on code from David Luff
|
||||||
|
FGEnvironment
|
||||||
|
stationweather = ((FGEnvironmentMgr *) globals->get_subsystem("environment"))
|
||||||
|
->getEnvironment(dep->latitude, dep->longitude, dep->elevation);
|
||||||
|
|
||||||
|
wind_speed = stationweather.get_wind_speed_kt();
|
||||||
|
wind_heading = stationweather.get_wind_from_heading_deg();
|
||||||
|
if (wind_speed == 0) {
|
||||||
|
wind_heading = 270; // This forces West-facing rwys to be used in no-wind situations
|
||||||
|
// which is consistent with Flightgear's initial setup.
|
||||||
|
}
|
||||||
|
|
||||||
|
string rwy_no = globals->get_runways()->search(dep->id, int(wind_heading));
|
||||||
|
if (!(globals->get_runways()->search(dep->id, (int) wind_heading, &rwy )))
|
||||||
|
{
|
||||||
|
cout << "Failed to find runway for " << dep->id << endl;
|
||||||
|
// Hmm, how do we handle a potential error like this?
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
double lat, lon, az;
|
||||||
|
double lat2, lon2, az2;
|
||||||
|
double heading = rwy.heading;
|
||||||
|
double azimuth = heading + 180.0;
|
||||||
|
while ( azimuth >= 360.0 ) { azimuth -= 360.0; }
|
||||||
|
geo_direct_wgs_84 ( 0, rwy.lat, rwy.lon, azimuth,
|
||||||
|
rwy.length * SG_FEET_TO_METER * 0.5 - 5.0,
|
||||||
|
&lat2, &lon2, &az2 );
|
||||||
|
|
||||||
|
//Add the runway startpoint;
|
||||||
|
wpt = new waypoint;
|
||||||
|
wpt->name = rwy.id;
|
||||||
|
wpt->latitude = lat2;
|
||||||
|
wpt->longitude = lon2;
|
||||||
|
wpt->altitude = dep->elevation + 19;
|
||||||
|
wpt->speed = 15;
|
||||||
|
wpt->crossat = -10000;
|
||||||
|
wpt->gear_down = true;
|
||||||
|
wpt->flaps_down= true;
|
||||||
|
wpt->finished = false;
|
||||||
|
wpt->on_ground = true;
|
||||||
|
waypoints.push_back(wpt);
|
||||||
|
|
||||||
|
//Next: The point on the runway where we begin to accelerate to take-off speed
|
||||||
|
//100 meters down the runway seems to work. Shorter distances cause problems with
|
||||||
|
// the turn with larger aircraft
|
||||||
|
geo_direct_wgs_84 ( 0, rwy.lat, rwy.lon, azimuth,
|
||||||
|
rwy.length * SG_FEET_TO_METER * 0.5 - 105.0,
|
||||||
|
&lat2, &lon2, &az2 );
|
||||||
|
wpt = new waypoint;
|
||||||
|
wpt->name = "accel";
|
||||||
|
wpt->latitude = lat2;
|
||||||
|
wpt->longitude = lon2;
|
||||||
|
wpt->altitude = dep->elevation + 19;
|
||||||
|
wpt->speed = speed;
|
||||||
|
wpt->crossat = -10000;
|
||||||
|
wpt->gear_down = true;
|
||||||
|
wpt->flaps_down= true;
|
||||||
|
wpt->finished = false;
|
||||||
|
wpt->on_ground = true;
|
||||||
|
waypoints.push_back(wpt);
|
||||||
|
|
||||||
|
lat = lat2;
|
||||||
|
lon = lon2;
|
||||||
|
az = az2;
|
||||||
|
|
||||||
|
//Next: the Start of Climb
|
||||||
|
geo_direct_wgs_84 ( 0, lat, lon, heading,
|
||||||
|
2560 * SG_FEET_TO_METER,
|
||||||
|
&lat2, &lon2, &az2 );
|
||||||
|
|
||||||
|
wpt = new waypoint;
|
||||||
|
wpt->name = "SOC";
|
||||||
|
wpt->latitude = lat2;
|
||||||
|
wpt->longitude = lon2;
|
||||||
|
wpt->altitude = alt + 19;
|
||||||
|
wpt->speed = speed;
|
||||||
|
wpt->crossat = -10000;
|
||||||
|
wpt->gear_down = true;
|
||||||
|
wpt->flaps_down= true;
|
||||||
|
wpt->finished = false;
|
||||||
|
wpt->on_ground = false;
|
||||||
|
waypoints.push_back(wpt);
|
||||||
|
|
||||||
|
//Next: the Top of Climb
|
||||||
|
geo_direct_wgs_84 ( 0, lat, lon, heading,
|
||||||
|
20*SG_NM_TO_METER,
|
||||||
|
&lat2, &lon2, &az2 );
|
||||||
|
wpt = new waypoint;
|
||||||
|
wpt->name = "10000ft climb";
|
||||||
|
wpt->latitude = lat2;
|
||||||
|
wpt->longitude = lon2;
|
||||||
|
wpt->altitude = 10000;
|
||||||
|
wpt->speed = speed;
|
||||||
|
wpt->crossat = -10000;
|
||||||
|
wpt->gear_down = true;
|
||||||
|
wpt->flaps_down= true;
|
||||||
|
wpt->finished = false;
|
||||||
|
wpt->on_ground = false;
|
||||||
|
waypoints.push_back(wpt);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//Beginning of Decent
|
||||||
|
stationweather = ((FGEnvironmentMgr *)globals->get_subsystem("environment"))
|
||||||
|
->getEnvironment(arr->latitude, arr->longitude, arr->elevation);
|
||||||
|
|
||||||
|
wind_speed = stationweather.get_wind_speed_kt();
|
||||||
|
wind_heading = stationweather.get_wind_from_heading_deg();
|
||||||
|
|
||||||
|
if (wind_speed == 0) {
|
||||||
|
wind_heading = 270; // This forces West-facing rwys to be used in no-wind situations
|
||||||
|
// which is consistent with Flightgear's initial setup.
|
||||||
|
}
|
||||||
|
|
||||||
|
rwy_no = globals->get_runways()->search(arr->id, int(wind_heading));
|
||||||
|
//cout << "Using runway # " << rwy_no << " for departure at " << dep->id << endl;
|
||||||
|
|
||||||
|
if (!(globals->get_runways()->search(arr->id, (int) wind_heading, &rwy )))
|
||||||
|
{
|
||||||
|
cout << "Failed to find runway for " << arr->id << endl;
|
||||||
|
// Hmm, how do we handle a potential error like this?
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
//cerr << "Done" << endl;
|
||||||
|
heading = rwy.heading;
|
||||||
|
azimuth = heading + 180.0;
|
||||||
|
while ( azimuth >= 360.0 ) { azimuth -= 360.0; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
geo_direct_wgs_84 ( 0, rwy.lat, rwy.lon, azimuth,
|
||||||
|
100000,
|
||||||
|
&lat2, &lon2, &az2 );
|
||||||
|
wpt = new waypoint;
|
||||||
|
wpt->name = "BOD"; //wpt_node->getStringValue("name", "END");
|
||||||
|
wpt->latitude = lat2;
|
||||||
|
wpt->longitude = lon2;
|
||||||
|
wpt->altitude = 10000;
|
||||||
|
wpt->speed = speed;
|
||||||
|
wpt->crossat = alt +19;
|
||||||
|
wpt->gear_down = false;
|
||||||
|
wpt->flaps_down= false;
|
||||||
|
wpt->finished = false;
|
||||||
|
wpt->on_ground = false;
|
||||||
|
waypoints.push_back(wpt);
|
||||||
|
|
||||||
|
// Ten thousand ft. Slowing down to 240 kts
|
||||||
|
geo_direct_wgs_84 ( 0, rwy.lat, rwy.lon, azimuth,
|
||||||
|
20*SG_NM_TO_METER,
|
||||||
|
&lat2, &lon2, &az2 );
|
||||||
|
wpt = new waypoint;
|
||||||
|
wpt->name = "Dec 10000ft"; //wpt_node->getStringValue("name", "END");
|
||||||
|
wpt->latitude = lat2;
|
||||||
|
wpt->longitude = lon2;
|
||||||
|
wpt->altitude = arr->elevation + 19;
|
||||||
|
wpt->speed = 240;
|
||||||
|
wpt->crossat = 10000;
|
||||||
|
wpt->gear_down = false;
|
||||||
|
wpt->flaps_down= false;
|
||||||
|
wpt->finished = false;
|
||||||
|
wpt->on_ground = false;
|
||||||
|
waypoints.push_back(wpt);
|
||||||
|
|
||||||
|
// Three thousand ft. Slowing down to 160 kts
|
||||||
|
geo_direct_wgs_84 ( 0, rwy.lat, rwy.lon, azimuth,
|
||||||
|
8*SG_NM_TO_METER,
|
||||||
|
&lat2, &lon2, &az2 );
|
||||||
|
wpt = new waypoint;
|
||||||
|
wpt->name = "DEC 3000ft"; //wpt_node->getStringValue("name", "END");
|
||||||
|
wpt->latitude = lat2;
|
||||||
|
wpt->longitude = lon2;
|
||||||
|
wpt->altitude = arr->elevation + 19;
|
||||||
|
wpt->speed = 160;
|
||||||
|
wpt->crossat = 3000;
|
||||||
|
wpt->gear_down = true;
|
||||||
|
wpt->flaps_down= true;
|
||||||
|
wpt->finished = false;
|
||||||
|
wpt->on_ground = false;
|
||||||
|
waypoints.push_back(wpt);
|
||||||
|
//Runway Threshold
|
||||||
|
geo_direct_wgs_84 ( 0, rwy.lat, rwy.lon, azimuth,
|
||||||
|
rwy.length*0.45,
|
||||||
|
&lat2, &lon2, &az2 );
|
||||||
|
wpt = new waypoint;
|
||||||
|
wpt->name = "Threshold"; //wpt_node->getStringValue("name", "END");
|
||||||
|
wpt->latitude = lat2;
|
||||||
|
wpt->longitude = lon2;
|
||||||
|
wpt->altitude = arr->elevation + 19;
|
||||||
|
wpt->speed = 15;
|
||||||
|
wpt->crossat = arr->elevation + 19;
|
||||||
|
wpt->gear_down = true;
|
||||||
|
wpt->flaps_down= true;
|
||||||
|
wpt->finished = false;
|
||||||
|
wpt->on_ground = true;
|
||||||
|
waypoints.push_back(wpt);
|
||||||
|
|
||||||
|
//Full stop at the runway centerpoint
|
||||||
|
geo_direct_wgs_84 ( 0, rwy.lat, rwy.lon, azimuth,
|
||||||
|
rwy.length*0.45,
|
||||||
|
&lat2, &lon2, &az2 );
|
||||||
|
wpt = new waypoint;
|
||||||
|
wpt->name = "Center"; //wpt_node->getStringValue("name", "END");
|
||||||
|
wpt->latitude = rwy.lat;
|
||||||
|
wpt->longitude = rwy.lon;
|
||||||
|
wpt->altitude = arr->elevation + 19;
|
||||||
|
wpt->speed = 15;
|
||||||
|
wpt->crossat = -10000;
|
||||||
|
wpt->gear_down = true;
|
||||||
|
wpt->flaps_down= true;
|
||||||
|
wpt->finished = false;
|
||||||
|
wpt->on_ground = false;
|
||||||
|
waypoints.push_back(wpt);
|
||||||
|
|
||||||
|
// Add the final destination waypoint
|
||||||
|
wpt = new waypoint;
|
||||||
|
wpt->name = arr->id; //wpt_node->getStringValue("name", "END");
|
||||||
|
wpt->latitude = arr->latitude;
|
||||||
|
wpt->longitude = arr->longitude;
|
||||||
|
wpt->altitude = arr->elevation+19;
|
||||||
|
wpt->speed = 15;
|
||||||
|
wpt->crossat = -10000;
|
||||||
|
wpt->gear_down = true;
|
||||||
|
wpt->flaps_down= true;
|
||||||
|
wpt->finished = false;
|
||||||
|
wpt->on_ground = false;
|
||||||
|
waypoints.push_back(wpt);
|
||||||
|
|
||||||
|
// And finally one more named "END"
|
||||||
|
wpt = new waypoint;
|
||||||
|
wpt->name = "END"; //wpt_node->getStringValue("name", "END");
|
||||||
|
wpt->latitude = arr->latitude;
|
||||||
|
wpt->longitude = arr->longitude;
|
||||||
|
wpt->altitude = 19;
|
||||||
|
wpt->speed = 15;
|
||||||
|
wpt->crossat = -10000;
|
||||||
|
wpt->gear_down = true;
|
||||||
|
wpt->flaps_down= true;
|
||||||
|
wpt->finished = true;
|
||||||
|
wpt->on_ground = true;
|
||||||
|
waypoints.push_back(wpt);
|
||||||
|
|
||||||
|
// And finally one more named "EOF"
|
||||||
|
wpt = new waypoint;
|
||||||
|
wpt->name = "EOF"; //wpt_node->getStringValue("name", "END");
|
||||||
|
wpt->latitude = arr->latitude;
|
||||||
|
wpt->longitude = arr->longitude;
|
||||||
|
wpt->altitude = 19;
|
||||||
|
wpt->speed = 15;
|
||||||
|
wpt->crossat = -10000;
|
||||||
|
wpt->gear_down = true;
|
||||||
|
wpt->flaps_down= true;
|
||||||
|
wpt->finished = true;
|
||||||
|
wpt->finished = true;
|
||||||
|
waypoints.push_back(wpt);
|
||||||
|
}
|
||||||
|
|
|
@ -22,6 +22,9 @@
|
||||||
#include <simgear/compiler.h>
|
#include <simgear/compiler.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include <Airports/simple.hxx>
|
||||||
|
|
||||||
SG_USING_STD(vector);
|
SG_USING_STD(vector);
|
||||||
SG_USING_STD(string);
|
SG_USING_STD(string);
|
||||||
|
|
||||||
|
@ -46,10 +49,12 @@ public:
|
||||||
FGAIFlightPlan(string filename);
|
FGAIFlightPlan(string filename);
|
||||||
FGAIFlightPlan(string filename,
|
FGAIFlightPlan(string filename,
|
||||||
double lat,
|
double lat,
|
||||||
double lon,
|
double lon,
|
||||||
double alt,
|
double alt,
|
||||||
double speed,
|
double speed,
|
||||||
double course);
|
double course,
|
||||||
|
FGAirport *dep,
|
||||||
|
FGAirport *arr);
|
||||||
~FGAIFlightPlan();
|
~FGAIFlightPlan();
|
||||||
|
|
||||||
waypoint* getPreviousWaypoint( void );
|
waypoint* getPreviousWaypoint( void );
|
||||||
|
@ -64,6 +69,8 @@ public:
|
||||||
double getBearing(waypoint* previous, waypoint* next);
|
double getBearing(waypoint* previous, waypoint* next);
|
||||||
double getBearing(double lat, double lon, waypoint* next);
|
double getBearing(double lat, double lon, waypoint* next);
|
||||||
|
|
||||||
|
void create(FGAirport *dep, FGAirport *arr, double alt, double speed);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
typedef vector <waypoint*> wpt_vector_type;
|
typedef vector <waypoint*> wpt_vector_type;
|
||||||
|
|
|
@ -122,7 +122,7 @@ void FGAISchedule::update(time_t now)
|
||||||
userLatitude,
|
userLatitude,
|
||||||
userLongitude;
|
userLongitude;
|
||||||
|
|
||||||
if (fgGetBool("/sim/ai/enabled") == false)
|
if (fgGetBool("/sim/traffic-manager/enabled") == false)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
aimgr = (FGAIManager *) globals-> get_subsystem("ai_model");
|
aimgr = (FGAIManager *) globals-> get_subsystem("ai_model");
|
||||||
|
@ -251,25 +251,23 @@ void FGAISchedule::update(time_t now)
|
||||||
// one hour flight time, so that would be a good approximate point
|
// one hour flight time, so that would be a good approximate point
|
||||||
// to start a more detailed simulation of this aircraft.
|
// to start a more detailed simulation of this aircraft.
|
||||||
//cerr << registration << " is currently enroute from "
|
//cerr << registration << " is currently enroute from "
|
||||||
// << dep->id << " to " << arr->id << "distance : " << distanceToUser*SG_METER_TO_NM << endl;
|
// << dep->id << " to " << arr->id << "distance : "
|
||||||
|
// << distanceToUser*SG_METER_TO_NM << endl;
|
||||||
if ((distanceToUser*SG_METER_TO_NM) < 500.0)
|
if ((distanceToUser*SG_METER_TO_NM) < 500.0)
|
||||||
{
|
{
|
||||||
string flightPlanName = dep->id + string("-") + arr->id + string(".xml");
|
string flightPlanName = dep->id + string("-") + arr->id +
|
||||||
|
string(".xml");
|
||||||
|
|
||||||
FGAIFlightPlan* f;
|
FGAIFlightPlan* f;
|
||||||
// If we're less then 10 minutes behind schedule, do a normal
|
f = new FGAIFlightPlan(flightPlanName,
|
||||||
// full flight plan initialization, otherwise, do a modified
|
lat,
|
||||||
// in-air initializition, at the location where this flight is
|
lon,
|
||||||
// according to the Traffic Manager
|
i->getCruiseAlt() * 100, // convert from FL to feet
|
||||||
if (elapsedTimeEnroute < 600)
|
//speed,
|
||||||
f = new FGAIFlightPlan(flightPlanName);
|
450,
|
||||||
else
|
courseToDest,
|
||||||
f = new FGAIFlightPlan(flightPlanName,
|
dep,
|
||||||
lat,
|
arr);
|
||||||
lon,
|
|
||||||
i->getCruiseAlt() * 1000, // convert from FL to feet
|
|
||||||
speed,
|
|
||||||
courseToDest);
|
|
||||||
// Fixme: A non-existent model path results in an
|
// Fixme: A non-existent model path results in an
|
||||||
// abort, due to an unhandled exeption, in fg main loop.
|
// abort, due to an unhandled exeption, in fg main loop.
|
||||||
AIManagerRef = aimgr->createAircraft("jet_transport",
|
AIManagerRef = aimgr->createAircraft("jet_transport",
|
||||||
|
@ -278,6 +276,7 @@ void FGAISchedule::update(time_t now)
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Both departure and arrival time are in the future, so this
|
// Both departure and arrival time are in the future, so this
|
||||||
// the aircraft is parked at the departure airport.
|
// the aircraft is parked at the departure airport.
|
||||||
// Currently this status is mostly ignored, but in furture
|
// Currently this status is mostly ignored, but in furture
|
||||||
|
|
Loading…
Reference in a new issue