1
0
Fork 0

Durk Talsma:

I just heard from John Wojnaroski that you and he are going to work on getting
a flightgear demo machine up for the linux expo thursday and Friday. John
indicated that he would very much like to get a CVS version with the new
traffic code up and running before the expo.
This commit is contained in:
ehofman 2005-02-10 09:01:51 +00:00
parent 03f0ac8519
commit 5bc15d7a69
29 changed files with 3436 additions and 623 deletions

View file

@ -23,9 +23,13 @@
#endif
#include <simgear/math/point3d.hxx>
#include <simgear/route/waypoint.hxx>
#include <Main/fg_props.hxx>
#include <Main/globals.hxx>
#include <Main/viewer.hxx>
#include <Scenery/scenery.hxx>
#include <Scenery/tilemgr.hxx>
#include <string>
#include <math.h>
#include <time.h>
@ -33,7 +37,7 @@
SG_USING_STD(string);
#include "AIAircraft.hxx"
static string tempReg;
//
// accel, decel, climb_rate, descent_rate, takeoff_speed, climb_speed,
// cruise_speed, descent_speed, land_speed
@ -54,17 +58,24 @@ const FGAIAircraft::PERF_STRUCT FGAIAircraft::settings[] = {
FGAIAircraft::FGAIAircraft(FGAIManager* mgr, FGAISchedule *ref) {
trafficRef = ref;
if (trafficRef)
groundOffset = trafficRef->getGroundOffset();
else
groundOffset = 0;
manager = mgr;
_type_str = "aircraft";
_otype = otAircraft;
fp = 0;
dt_count = 0;
dt_elev_count = 0;
use_perf_vs = true;
isTanker = false;
// set heading and altitude locks
hdg_lock = false;
alt_lock = false;
roll = 0;
headingChangeRate = 0.0;
}
@ -118,11 +129,22 @@ void FGAIAircraft::Run(double dt) {
if (fp)
{
ProcessFlightPlan(dt);
time_t now = time(NULL) + fgGetLong("/sim/time/warp");
ProcessFlightPlan(dt, now);
if (now < fp->getStartTime())
return;
//ProcessFlightPlan(dt);
{
// Do execute Ground elev for inactive aircraft, so they
// Are repositioned to the correct ground altitude when the user flies within visibility range.
if (no_roll)
{
Transform(); // make sure aip is initialized.
getGroundElev(dt); // make sure it's exectuted first time around, so force a large dt value
//getGroundElev(dt); // Need to do this twice.
//cerr << trafficRef->getRegistration() << " Setting altitude to " << tgt_altitude << endl;
setAltitude(tgt_altitude);
}
return;
}
}
double turn_radius_ft;
@ -133,11 +155,19 @@ void FGAIAircraft::Run(double dt) {
double alpha;
// adjust speed
double speed_diff = tgt_speed - speed;
double speed_diff; //= tgt_speed - speed;
if (!no_roll)
{
speed_diff = tgt_speed - speed;
}
else
{
speed_diff = groundTargetSpeed - speed;
}
if (fabs(speed_diff) > 0.2) {
if (speed_diff > 0.0) speed += performance->accel * dt;
if (speed_diff < 0.0) {
if (!no_roll) {
if (no_roll) { // was (!no_roll) but seems more logical this way (ground brakes).
speed -= performance->decel * dt * 3;
} else {
speed -= performance->decel * dt;
@ -154,19 +184,98 @@ void FGAIAircraft::Run(double dt) {
// set new position
pos.setlat( pos.lat() + speed_north_deg_sec * dt);
pos.setlon( pos.lon() + speed_east_deg_sec * dt);
//if (!(finite(pos.lat()) && finite(pos.lon())))
// {
// cerr << "Position is not finite" << endl;
// cerr << "speed = " << speed << endl;
// cerr << "dt" << dt << endl;
// cerr << "heading " << hdg << endl;
// cerr << "speed east " << speed_east_deg_sec << endl;
// cerr << "speed nrth " << speed_north_deg_sec << endl;
// cerr << "deg_lat " << ft_per_deg_lat << endl;
// cerr << "deg_lon " << ft_per_deg_lon << endl;
// }
// adjust heading based on current bank angle
if (roll == 0.0)
roll = 0.01;
if (roll != 0.0) {
turn_radius_ft = 0.088362 * speed * speed
/ tan( fabs(roll) / SG_RADIANS_TO_DEGREES );
turn_circum_ft = SGD_2PI * turn_radius_ft;
dist_covered_ft = speed * 1.686 * dt;
alpha = dist_covered_ft / turn_circum_ft * 360.0;
hdg += alpha * sign( roll );
if ( hdg > 360.0 ) hdg -= 360.0;
if ( hdg < 0.0) hdg += 360.0;
// double turnConstant;
//if (no_roll)
// turnConstant = 0.0088362;
//else
// turnConstant = 0.088362;
// If on ground, calculate heading change directly
if (no_roll) {
double headingDiff = fabs(hdg-tgt_heading);
if (headingDiff > 180)
headingDiff = fabs(headingDiff - 360);
groundTargetSpeed = tgt_speed - (tgt_speed * (headingDiff/45));
if (sign(groundTargetSpeed) != sign(tgt_speed))
groundTargetSpeed = 0.21 * sign(tgt_speed); // to prevent speed getting stuck in 'negative' mode
if (headingDiff > 30.0)
{
headingChangeRate += dt * sign(roll); // invert if pushed backward
// Print some debug statements to find out why aircraft may get stuck
// forever turning
//if (trafficRef->getDepartureAirport()->getId() == string("EHAM"))
// {
//cerr << "Turning : " << trafficRef->getRegistration()
//cerr << " Speed = " << speed << " Heading " << hdg
//<< " Target Heading " << tgt_heading
// << " Lead Distance " << fp->getLeadDistance()
// << " Distance to go "
// << fp->getDistanceToGo(pos.lat(), pos.lon(), fp->getCurrentWaypoint())
// << "waypoint name " << fp->getCurrentWaypoint()->name
// << endl;
//}
if (headingChangeRate > 30)
{
headingChangeRate = 30;
}
else if (headingChangeRate < -30)
{
headingChangeRate = -30;
}
}
else
{
if (fabs(headingChangeRate) > headingDiff)
headingChangeRate = headingDiff*sign(roll);
else
headingChangeRate += dt * sign(roll);
}
hdg += headingChangeRate * dt;
//cerr << "On ground. Heading: " << hdg << ". Target Heading: " << tgt_heading << ". Target speed: " << groundTargetSpeed << ". heading change rate" << headingChangeRate << endl;
}
else {
if (fabs(speed) > 1.0) {
turn_radius_ft = 0.088362 * speed * speed
/ tan( fabs(roll) / SG_RADIANS_TO_DEGREES );
}
else
{
turn_radius_ft = 1.0; // Check if turn_radius_ft == 0; this might lead to a division by 0.
}
turn_circum_ft = SGD_2PI * turn_radius_ft;
dist_covered_ft = speed * 1.686 * dt;
alpha = dist_covered_ft / turn_circum_ft * 360.0;
hdg += alpha * sign(roll);
}
while ( hdg > 360.0 ) {
hdg -= 360.0;
spinCounter++;
}
while ( hdg < 0.0)
{
hdg += 360.0;
spinCounter--;
}
}
// adjust target bank angle if heading lock engaged
if (hdg_lock) {
double bank_sense = 0.0;
@ -184,6 +293,27 @@ void FGAIAircraft::Run(double dt) {
} else {
tgt_roll = 30.0 * bank_sense;
}
if ((fabs((double) spinCounter) > 1) && (diff > 30))
{
tgt_speed *= 0.999; // Ugly hack: If aircraft get stuck, they will continually spin around.
// The only way to resolve this is to make them slow down.
//if (tempReg.empty())
// tempReg = trafficRef->getRegistration();
//if (trafficRef->getRegistration() == tempReg)
// {
// cerr << trafficRef->getRegistration()
// << " appears to be spinning: " << spinCounter << endl
// << " speed " << speed << endl
// << " heading " << hdg << endl
// << " lead distance " << fp->getLeadDistance() << endl
// << " waypoint " << fp->getCurrentWaypoint()->name
// << " target heading " << tgt_heading << endl
// << " lead in angle " << fp->getLeadInAngle()<< endl
// << " roll " << roll << endl
// << " target_roll " << tgt_roll << endl;
// }
}
}
// adjust bank angle, use 9 degrees per second
@ -191,6 +321,8 @@ void FGAIAircraft::Run(double dt) {
if (fabs(bank_diff) > 0.2) {
if (bank_diff > 0.0) roll += 9.0 * dt;
if (bank_diff < 0.0) roll -= 9.0 * dt;
//while (roll > 180) roll -= 360;
//while (roll < 180) roll += 360;
}
// adjust altitude (meters) based on current vertical speed (fpm)
@ -198,6 +330,11 @@ void FGAIAircraft::Run(double dt) {
pos.setelev(altitude * SG_FEET_TO_METER);
double altitude_ft = altitude;
// adjust target Altitude, based on ground elevation when on ground
if (no_roll)
{
getGroundElev(dt);
}
// find target vertical speed if altitude lock engaged
if (alt_lock && use_perf_vs) {
if (altitude_ft < tgt_altitude) {
@ -303,9 +440,28 @@ void FGAIAircraft::SetFlightPlan(FGAIFlightPlan *f) {
fp = f;
}
void FGAIAircraft::ProcessFlightPlan( double dt ) {
void FGAIAircraft::ProcessFlightPlan( double dt, time_t now )
{
bool eraseWaypoints;
if (trafficRef)
{
// FGAirport *arr;
// FGAirport *dep;
eraseWaypoints = true;
// cerr << trafficRef->getRegistration();
// cerr << "Departure airport " << endl;
// dep = trafficRef->getDepartureAirport();
// if (dep)
// cerr << dep->getId() << endl;
// cerr << "Arrival airport " << endl;
// arr = trafficRef->getArrivalAirport();
// if (arr)
// cerr << arr->getId() <<endl << endl;;
}
else
eraseWaypoints = false;
//cerr << "Processing Flightplan" << endl;
FGAIFlightPlan::waypoint* prev = 0; // the one behind you
FGAIFlightPlan::waypoint* curr = 0; // the one ahead
FGAIFlightPlan::waypoint* next = 0; // the next plus 1
@ -315,116 +471,481 @@ void FGAIAircraft::ProcessFlightPlan( double dt ) {
dt_count += dt;
if (!prev) { //beginning of flightplan, do this initialization once
fp->IncrementWaypoint();
//setBank(0.0);
spinCounter = 0;
tempReg = "";
//prev_dist_to_go = HUGE;
//cerr << "Before increment " << curr-> name << endl;
fp->IncrementWaypoint(eraseWaypoints);
//prev = fp->getPreviousWaypoint(); //first waypoint
//curr = fp->getCurrentWaypoint(); //second waypoint
//next = fp->getNextWaypoint(); //third waypoint (might not exist!)
//cerr << "After increment " << prev-> name << endl;
if (!(fp->getNextWaypoint()) && trafficRef)
{
loadNextLeg();
}
//cerr << "After load " << prev-> name << endl;
prev = fp->getPreviousWaypoint(); //first waypoint
curr = fp->getCurrentWaypoint(); //second waypoint
next = fp->getNextWaypoint(); //third waypoint (might not exist!)
//cerr << "After load " << prev-> name << endl;
setLatitude(prev->latitude);
setLongitude(prev->longitude);
setSpeed(prev->speed);
setAltitude(prev->altitude);
setHeading(fp->getBearing(prev->latitude, prev->longitude, curr));
if (next) fp->setLeadDistance(speed, hdg, curr, next);
if (prev->speed > 0.0)
setHeading(fp->getBearing(prev->latitude, prev->longitude, curr));
else
{
setHeading(fp->getBearing(curr->latitude, curr->longitude, prev));
}
// If next doesn't exist, as in incrementally created flightplans for
// AI/Trafficmanager created plans,
// Make sure lead distance is initialized otherwise
if (next)
fp->setLeadDistance(speed, hdg, curr, next);
if (curr->crossat > -1000.0) { //use a calculated descent/climb rate
use_perf_vs = false;
tgt_vs = (curr->crossat - prev->altitude)/
(fp->getDistanceToGo(pos.lat(), pos.lon(), curr)/
6076.0/prev->speed*60.0);
use_perf_vs = false;
tgt_vs = (curr->crossat - prev->altitude)/
(fp->getDistanceToGo(pos.lat(), pos.lon(), curr)/
6076.0/prev->speed*60.0);
tgt_altitude = curr->crossat;
} else {
use_perf_vs = true;
tgt_altitude = prev->altitude;
use_perf_vs = true;
tgt_altitude = prev->altitude;
}
alt_lock = hdg_lock = true;
no_roll = prev->on_ground;
if (no_roll)
{
Transform(); // make sure aip is initialized.
getGroundElev(60.1); // make sure it's exectuted first time around, so force a large dt value
//getGroundElev(60.1); // Need to do this twice.
//cerr << trafficRef->getRegistration() << " Setting altitude to " << tgt_altitude << endl;
setAltitude(tgt_altitude);
}
prevSpeed = 0;
//cout << "First waypoint: " << prev->name << endl;
//cout << " Target speed: " << tgt_speed << endl;
//cout << " Target altitude: " << tgt_altitude << endl;
//cout << " Target heading: " << tgt_heading << endl << endl;
//cerr << "Done Flightplan init" << endl;
return;
} // end of initialization
// let's only process the flight plan every 100 ms.
if (dt_count < 0.1) {
return;
} else {
dt_count = 0;
// check to see if we've reached the lead point for our next turn
double dist_to_go = fp->getDistanceToGo(pos.lat(), pos.lon(), curr);
double lead_dist = fp->getLeadDistance();
if (lead_dist < (2*speed)) lead_dist = 2*speed; //don't skip over the waypoint
//cout << "dist_to_go: " << dist_to_go << ", lead_dist: " << lead_dist << endl;
if ( dist_to_go < lead_dist ) {
if (curr->finished) { //end of the flight plan, so terminate
if (trafficRef)
{
delete fp;
//time_t now = time(NULL) + fgGetLong("/sim/time/warp");
trafficRef->next();
FGAIModelEntity entity;
entity.m_class = "jet_transport";
//entity.path = modelPath.c_str();
entity.flightplan = "none";
entity.latitude = _getLatitude();
entity.longitude = _getLongitude();
entity.altitude = trafficRef->getCruiseAlt() * 100; // convert from FL to feet
entity.speed = 450;
//entity.fp = new FGAIFlightPlan(&entity, courseToDest, i->getDepartureTime(), dep, arr);
entity.fp = new FGAIFlightPlan(&entity,
999, // A hack
trafficRef->getDepartureTime(),
trafficRef->getDepartureAirport(),
trafficRef->getArrivalAirport());
SetFlightPlan(entity.fp);
}
else
{
setDie(true);
return;
}
}
// we've reached the lead-point for the waypoint ahead
if (next) tgt_heading = fp->getBearing(curr, next);
fp->IncrementWaypoint();
prev = fp->getPreviousWaypoint();
curr = fp->getCurrentWaypoint();
next = fp->getNextWaypoint();
if (next) fp->setLeadDistance(speed, tgt_heading, curr, next);
if (curr->crossat > -1000.0) {
use_perf_vs = false;
tgt_vs = (curr->crossat - altitude)/
(fp->getDistanceToGo(pos.lat(), pos.lon(), curr)/6076.0/speed*60.0);
tgt_altitude = curr->crossat;
} else {
use_perf_vs = true;
tgt_altitude = prev->altitude;
}
tgt_speed = prev->speed;
hdg_lock = alt_lock = true;
no_roll = prev->on_ground;
//cout << "Crossing waypoint: " << prev->name << endl;
//cout << " Target speed: " << tgt_speed << endl;
//cout << " Target altitude: " << tgt_altitude << endl;
//cout << " Target heading: " << tgt_heading << endl << endl;
if ((dt_count < 0.1) || (now < fp->getStartTime()))
{
//cerr << "done fp dt" << endl;
return;
} else {
double calc_bearing = fp->getBearing(pos.lat(), pos.lon(), curr);
double hdg_error = calc_bearing - tgt_heading;
if (fabs(hdg_error) > 1.0) {
TurnTo( calc_bearing );
}
dt_count = 0;
}
// check to see if we've reached the lead point for our next turn
double dist_to_go = fp->getDistanceToGo(pos.lat(), pos.lon(), curr);
//cerr << "2" << endl;
double lead_dist = fp->getLeadDistance();
//cerr << " Distance : " << dist_to_go << ": Lead distance " << lead_dist << endl;
// experimental: Use fabs, because speed can be negative (I hope) during push_back.
if (lead_dist < fabs(2*speed))
{
lead_dist = fabs(2*speed); //don't skip over the waypoint
//cerr << "Extending lead distance to " << lead_dist << endl;
}
// FGAirport * apt = trafficRef->getDepartureAirport();
// if ((dist_to_go > prev_dist_to_go) && trafficRef && apt)
// {
// if (apt->getId() == string("EHAM"))
// cerr << "Alert: " << trafficRef->getRegistration() << " is moving away from waypoint " << curr->name << endl
// << "Target heading : " << tgt_heading << "act heading " << hdg << " Tgt speed : " << tgt_speed << endl
// << "Lead distance : " << lead_dist << endl
// << "Distance to go: " << dist_to_go << endl;
// }
prev_dist_to_go = dist_to_go;
//cerr << "2" << endl;
//if (no_roll)
// lead_dist = 10.0;
//cout << "Leg : " << (fp->getLeg()-1) << ". dist_to_go: " << dist_to_go << ", lead_dist: " << lead_dist << ", tgt_speed " << tgt_speed << ", tgt_heading " << tgt_heading << " speed " << speed << " hdg " << hdg << ". Altitude " << altitude << " TAget alt :" << tgt_altitude << endl;
if ( dist_to_go < lead_dist ) {
//prev_dist_to_go = HUGE;
// For traffic manager generated aircraft:
// check if the aircraft flies of of user range. And adjust the
// Current waypoint's elevation according to Terrain Elevation
if (curr->finished) { //end of the flight plan
{
setDie(true);
//cerr << "Done die end of fp" << endl;
}
return;
}
}
// we've reached the lead-point for the waypoint ahead
//cerr << "4" << endl;
//cerr << "Situation after lead point" << endl;
//cerr << "Prviious: " << prev->name << endl;
//cerr << "Current : " << curr->name << endl;
//cerr << "Next : " << next->name << endl;
if (next)
{
tgt_heading = fp->getBearing(curr, next);
spinCounter = 0;
}
fp->IncrementWaypoint(eraseWaypoints);
if (!(fp->getNextWaypoint()) && trafficRef)
{
loadNextLeg();
}
prev = fp->getPreviousWaypoint();
curr = fp->getCurrentWaypoint();
next = fp->getNextWaypoint();
// Now that we have incremented the waypoints, excute some traffic manager specific code
// based on the name of the waypoint we just passed.
if (trafficRef)
{
double userLatitude = fgGetDouble("/position/latitude-deg");
double userLongitude = fgGetDouble("/position/longitude-deg");
double course, distance;
SGWayPoint current (pos.lon(),
pos.lat(),
0);
SGWayPoint user ( userLongitude,
userLatitude,
0);
user.CourseAndDistance(current, &course, &distance);
if ((distance * SG_METER_TO_NM) > TRAFFICTOAIDIST)
{
setDie(true);
//cerr << "done fp die out of range" << endl;
return;
}
FGAirport * dep = trafficRef->getDepartureAirport();
FGAirport * arr = trafficRef->getArrivalAirport();
// At parking the beginning of the airport
if (!( dep && arr))
{
setDie(true);
return;
}
//if ((dep->getId() == string("EHAM") || (arr->getId() == string("EHAM"))))
// {
// cerr << trafficRef->getRegistration()
// << " Enroute from " << dep->getId()
// << " to " << arr->getId()
// << " just crossed " << prev->name
// << " Assigned rwy " << fp->getRunwayId()
// << " " << fp->getRunway() << endl;
// }
//if ((dep->getId() == string("EHAM")) && (prev->name == "park2"))
// {
// cerr << "Schiphol ground "
// << trafficRef->getCallSign();
// if (trafficRef->getHeavy())
// cerr << "Heavy";
// cerr << ", is type "
// << trafficRef->getAircraft()
// << " ready to go. IFR to "
// << arr->getId() <<endl;
// }
if (prev->name == "park2")
dep->releaseParking(fp->getGate());
//if ((arr->getId() == string("EHAM")) && (prev->name == "Center"))
// {
//
// cerr << "Schiphol ground "
// << trafficRef->getCallSign();
// if (trafficRef->getHeavy())
// cerr << "Heavy";
// cerr << " landed runway "
// << fp->getRunway()
// << " request taxi to gate "
// << arr->getParkingName(fp->getGate())
// << endl;
// }
if (prev->name == "END")
fp->setTime(trafficRef->getDepartureTime());
//cerr << "5" << endl;
}
if (next)
{
//cerr << "Current waypoint" << curr->name << endl;
//cerr << "Next waypoint" << next->name << endl;
fp->setLeadDistance(speed, tgt_heading, curr, next);
}
//cerr << "5.1" << endl;
if (curr->crossat > -1000.0) {
//cerr << "5.1a" << endl;
use_perf_vs = false;
tgt_vs = (curr->crossat - altitude)/
(fp->getDistanceToGo(pos.lat(), pos.lon(), curr)/6076.0/speed*60.0);
//cerr << "5.1b" << endl;
tgt_altitude = curr->crossat;
} else {
//cerr << "5.1c" << endl;
use_perf_vs = true;
//cerr << "5.1d" << endl;
tgt_altitude = prev->altitude;
//cerr << "Setting target altitude : " <<tgt_altitude << endl;
}
//cerr << "6" << endl;
tgt_speed = prev->speed;
hdg_lock = alt_lock = true;
no_roll = prev->on_ground;
//cout << "Crossing waypoint: " << prev->name << endl;
//cout << " Target speed: " << tgt_speed << endl;
//cout << " Target altitude: " << tgt_altitude << endl;
//cout << " Target heading: " << tgt_heading << endl << endl;
} else {
double calc_bearing = fp->getBearing(pos.lat(), pos.lon(), curr);
//cerr << "Bearing = " << calc_bearing << endl;
if (speed < 0)
{
calc_bearing +=180;
if (calc_bearing > 360)
calc_bearing -= 360;
}
if (finite(calc_bearing))
{
double hdg_error = calc_bearing - tgt_heading;
if (fabs(hdg_error) > 1.0) {
TurnTo( calc_bearing );
}
}
else
{
cerr << "calc_bearing is not a finite number : "
<< "Speed " << speed
<< "pos : " << pos.lat() << ", " << pos.lon()
<< "waypoint " << curr->latitude << ", " << curr->longitude << endl;
cerr << "waypoint name " << curr->name;
exit(1);
}
double speed_diff = speed - prevSpeed;
// Update the lead distance calculation if speed has changed sufficiently
// to prevent spinning (hopefully);
if (fabs(speed_diff) > 10)
{
prevSpeed = speed;
fp->setLeadDistance(speed, tgt_heading, curr, next);
}
//cerr << "Done Processing FlightPlan"<< endl;
} // if (dt count) else
}
bool FGAIAircraft::_getGearDown() const {
bool FGAIAircraft::_getGearDown() const {
return ((props->getFloatValue("position/altitude-agl-ft") < 900.0)
&& (props->getFloatValue("velocities/airspeed-kt")
< performance->land_speed*1.25));
}
void FGAIAircraft::loadNextLeg()
{
//delete fp;
//time_t now = time(NULL) + fgGetLong("/sim/time/warp");
//FGAIModelEntity entity;
//entity.m_class = "jet_transport";
//entity.path = modelPath.c_str();
//entity.flightplan = "none";
//entity.latitude = _getLatitude();
//entity.longitude = _getLongitude();
//entity.altitude = trafficRef->getCruiseAlt() * 100; // convert from FL to feet
//entity.speed = 450; // HACK ALERT
//entity.fp = new FGAIFlightPlan(&entity, courseToDest, i->getDepartureTime(), dep, arr);
int leg;
if ((leg = fp->getLeg()) == 10)
{
trafficRef->next();
leg = 1;
fp->setLeg(leg);
//cerr << "Resetting leg : " << leg << endl;
}
//{
//leg++;
//fp->setLeg(leg);
//cerr << "Creating leg number : " << leg << endl;
FGAirport *dep = trafficRef->getDepartureAirport();
FGAirport *arr = trafficRef->getArrivalAirport();
if (!(dep && arr))
{
setDie(true);
//cerr << "Failed to get airport in AIAircraft::ProcessFlightplan()" << endl;
//if (dep)
// cerr << "Departure " << dep->getId() << endl;
//if (arr)
// cerr << "Arrival " << arr->getId() << endl;
}
else
{
double cruiseAlt = trafficRef->getCruiseAlt() * 100;
//cerr << "Creating new leg using " << cruiseAlt << " as cruise altitude."<< endl;
fp->create (dep,
arr,
leg,
cruiseAlt, //(trafficRef->getCruiseAlt() * 100), // convert from FL to feet
trafficRef->getSpeed(),
_getLatitude(),
_getLongitude(),
false,
trafficRef->getRadius(),
trafficRef->getFlightType(),
acType,
company);
//prev = fp->getPreviousWaypoint();
//curr = fp->getCurrentWaypoint();
//next = fp->getNextWaypoint();
//cerr << "25" << endl;
//if (next)
// {
// //cerr << "Next waypoint" << next->name << endl;
// fp->setLeadDistance(speed, tgt_heading, curr, next);
// }
//cerr << "25.1" << endl;
//if (curr->crossat > -1000.0) {
// //cerr << "25.1a" << endl;
// use_perf_vs = false;
//
// tgt_vs = (curr->crossat - altitude)/
// (fp->getDistanceToGo(pos.lat(), pos.lon(), curr)/6076.0/speed*60.0);
// //cerr << "25.1b" << endl;
// tgt_altitude = curr->crossat;
//} else {
// //cerr << "25.1c" << endl;
// use_perf_vs = true;
// //cerr << "25.1d" << endl;
// tgt_altitude = prev->altitude;
// //cerr << "Setting target altitude : " <<tgt_altitude << endl;
// }
//cerr << "26" << endl;
//tgt_speed = prev->speed;
//hdg_lock = alt_lock = true;
//no_roll = prev->on_ground;
}
//}
//else
//{
//delete entity.fp;
//entity.fp = new FGAIFlightPlan(&entity,
// 999, // A hack
// trafficRef->getDepartureTime(),
// trafficRef->getDepartureAirport(),
// trafficRef->getArrivalAirport(),
// false,
// acType,
// company);
//SetFlightPlan(entity.fp);
}
// Note: This code is copied from David Luff's AILocalTraffic
// Warning - ground elev determination is CPU intensive
// Either this function or the logic of how often it is called
// will almost certainly change.
void FGAIAircraft::getGroundElev(double dt) {
dt_elev_count += dt;
//return;
if (dt_elev_count < (10.0 + (rand() % 100))) // Update minimally every 10 secs, but add some randomness to prevent them all IA objects doing this synced
{
return;
}
else
{
dt_elev_count = 0;
}
// It would be nice if we could set the correct tile center here in order to get a correct
// answer with one call to the function, but what I tried in the two commented-out lines
// below only intermittently worked, and I haven't quite groked why yet.
//SGBucket buck(pos.lon(), pos.lat());
//aip.getSGLocation()->set_tile_center(Point3D(buck.get_center_lon(), buck.get_center_lat(), 0.0));
// Only do the proper hitlist stuff if we are within visible range of the viewer.
double visibility_meters = fgGetDouble("/environment/visibility-m");
FGViewer* vw = globals->get_current_view();
double
course,
distance;
//Point3D currView(vw->getLongitude_deg(),
// vw->getLatitude_deg(), 0.0);
SGWayPoint current (pos.lon(),
pos.lat(),
0);
SGWayPoint view ( vw->getLongitude_deg(),
vw->getLatitude_deg(),
0);
view.CourseAndDistance(current, &course, &distance);
if(distance > visibility_meters) {
//aip.getSGLocation()->set_cur_elev_m(aptElev);
return;
}
//globals->get_tile_mgr()->prep_ssg_nodes( acmodel_location,
globals->get_tile_mgr()->prep_ssg_nodes( aip.getSGLocation(), visibility_meters );
Point3D scenery_center = globals->get_scenery()->get_center();
globals->get_tile_mgr()->update( aip.getSGLocation(),
visibility_meters,
(aip.getSGLocation())->get_absolute_view_pos( scenery_center ) );
// save results of update in SGLocation for fdm...
//if ( globals->get_scenery()->get_cur_elev() > -9990 ) {
// acmodel_location->
// set_cur_elev_m( globals->get_scenery()->get_cur_elev() );
//}
// The need for this here means that at least 2 consecutive passes are needed :-(
aip.getSGLocation()->set_tile_center( globals->get_scenery()->get_next_center() );
globals->get_tile_mgr()->prep_ssg_nodes( aip.getSGLocation(), visibility_meters );
//Point3D scenery_center = globals->get_scenery()->get_center();
globals->get_tile_mgr()->update( aip.getSGLocation(),
visibility_meters,
(aip.getSGLocation())->get_absolute_view_pos( scenery_center ) );
// save results of update in SGLocation for fdm...
//if ( globals->get_scenery()->get_cur_elev() > -9990 ) {
// acmodel_location->
// set_cur_elev_m( globals->get_scenery()->get_cur_elev() );
//}
// The need for this here means that at least 2 consecutive passes are needed :-(
aip.getSGLocation()->set_tile_center( globals->get_scenery()->get_next_center() );
//cerr << "Transform Elev is " << globals->get_scenery()->get_cur_elev() << '\n';
tgt_altitude = (globals->get_scenery()->get_cur_elev() * SG_METER_TO_FEET) + groundOffset;
}
//globals->get_tile_mgr()->prep_ssg_nodes( _aip.getSGLocation(), visibility_meters );
//Point3D scenery_center = globals->get_scenery()->get_center();
//globals->get_tile_mgr()->update(_aip.getSGLocation(), visibility_meters, (_aip.getSGLocation())->get_absolute_view_pos( scenery_center ) );
// save results of update in SGLocation for fdm...
//if ( globals->get_scenery()->get_cur_elev() > -9990 ) {
// acmodel_location->
// set_cur_elev_m( globals->get_scenery()->get_cur_elev() );
//}
// The need for this here means that at least 2 consecutive passes are needed :-(
//_aip.getSGLocation()->set_tile_center( globals->get_scenery()->get_next_center() );
//cout << "Transform Elev is " << globals->get_scenery()->get_cur_elev() << '\n';
//_aip.getSGLocation()->set_cur_elev_m(globals->get_scenery()->get_cur_elev());
//return(globals->get_scenery()->get_cur_elev());
//}

View file

@ -48,7 +48,6 @@ private:
} PERF_STRUCT;
public:
enum aircraft_e {LIGHT=0, WW2_FIGHTER, JET_TRANSPORT, JET_FIGHTER, TANKER};
static const PERF_STRUCT settings[];
@ -68,7 +67,13 @@ public:
void YawTo(double angle);
void ClimbTo(double altitude);
void TurnTo(double heading);
void ProcessFlightPlan( double dt );
void ProcessFlightPlan( double dt, time_t now );
void getGroundElev(double dt);
void loadNextLeg ();
void setAcType(string ac) { acType = ac; };
void setCompany(string comp) { company = comp;};
//void setSchedule(FGAISchedule *ref) { trafficRef = ref;};
inline void SetTanker(bool setting) { isTanker = setting; };
@ -78,6 +83,10 @@ private:
bool hdg_lock;
bool alt_lock;
double dt_count;
double dt_elev_count;
double headingChangeRate;
double groundTargetSpeed;
double groundOffset;
double dt;
const PERF_STRUCT *performance;
@ -88,7 +97,14 @@ private:
void Run(double dt);
double sign(double x);
string acType;
string company;
int spinCounter;
double prevSpeed;
double prev_dist_to_go;
bool _getGearDown() const;
bool reachedWaypoint;
};

View file

@ -26,6 +26,7 @@
#include <simgear/constants.h>
#include <simgear/math/point3d.hxx>
#include <simgear/scene/model/placement.hxx>
#include <simgear/misc/sg_path.hxx>
#include <Main/fg_props.hxx>
@ -76,6 +77,8 @@ typedef struct {
double x_offset; // used by ship ojects, in meters
double y_offset; // used by ship ojects, in meters
double z_offset; // used by ship ojects, in meters
string acType; // used by aircraft objects
string company; // used by aircraft objects
} FGAIModelEntity;

View file

@ -45,6 +45,8 @@ FGAIFlightPlan::FGAIFlightPlan(string filename)
{
int i;
start_time = 0;
leg = 10;
gateId = 0;
SGPath path( globals->get_fg_root() );
path.append( ("/Data/AI/FlightPlans/" + filename).c_str() );
SGPropertyNode root;
@ -55,7 +57,7 @@ FGAIFlightPlan::FGAIFlightPlan(string filename)
SG_LOG(SG_GENERAL, SG_ALERT,
"Error reading AI flight plan: " << path.str());
// cout << path.str() << endl;
return;
return;
}
SGPropertyNode * node = root.getNode("flightplan");
@ -94,8 +96,15 @@ FGAIFlightPlan::FGAIFlightPlan(FGAIModelEntity *entity,
double course,
time_t start,
FGAirport *dep,
FGAirport *arr)
FGAirport *arr,
bool firstLeg,
double radius,
string fltType,
string acType,
string airline)
{
leg = 10;
gateId=0;
start_time = start;
bool useInitialWayPoint = true;
bool useCurrentWayPoint = false;
@ -116,55 +125,86 @@ FGAIFlightPlan::FGAIFlightPlan(FGAIModelEntity *entity,
useCurrentWayPoint = true;
}
try {
readProperties(path.str(), &root);
if (path.exists())
{
try
{
readProperties(path.str(), &root);
SGPropertyNode * node = root.getNode("flightplan");
SGPropertyNode * node = root.getNode("flightplan");
//waypoints.push_back( init_waypoint );
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);
//waypoints.push_back( init_waypoint );
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);
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: ");
cerr << "Errno = " << errno << endl;
if (errno == ENOENT)
{
cerr << "Reason: No such file or directory" << endl;
}
}
}
}
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, entity->altitude, entity->speed);
// Now that we have dynamically created a flight plan,
// we need to add some code that pops any waypoints already past.
//return;
}
waypoint* init_waypoint = new waypoint;
init_waypoint->name = string("initial position");
init_waypoint->latitude = entity->latitude;
init_waypoint->longitude = entity->longitude;
init_waypoint->altitude = entity->altitude;
init_waypoint->speed = entity->speed;
init_waypoint->crossat = - 10000;
init_waypoint->gear_down = false;
init_waypoint->flaps_down = false;
init_waypoint->finished = false;
else
{
// cout << path.str() << endl;
// cout << "Trying to create this plan dynamically" << endl;
// cout << "Route from " << dep->id << " to " << arr->id << endl;
time_t now = time(NULL) + fgGetLong("/sim/time/warp");
time_t timeDiff = now-start;
leg = 1;
if ((timeDiff > 300) && (timeDiff < 1200))
leg = 2;
else if ((timeDiff >= 1200) && (timeDiff < 1500))
leg = 3;
else if ((timeDiff >= 1500) && (timeDiff < 2000))
leg = 4;
else if (timeDiff >= 2000)
leg = 5;
wpt_vector_iterator i = waypoints.begin();
while (i != waypoints.end())
//cerr << "Set leg to : " << leg << endl;
wpt_iterator = waypoints.begin();
create(dep,arr, leg, entity->altitude, entity->speed, entity->latitude, entity->longitude,
firstLeg, radius, fltType, acType, airline);
wpt_iterator = waypoints.begin();
//cerr << "after create: " << (*wpt_iterator)->name << endl;
//leg++;
// Now that we have dynamically created a flight plan,
// we need to add some code that pops any waypoints already past.
//return;
}
/*
waypoint* init_waypoint = new waypoint;
init_waypoint->name = string("initial position");
init_waypoint->latitude = entity->latitude;
init_waypoint->longitude = entity->longitude;
init_waypoint->altitude = entity->altitude;
init_waypoint->speed = entity->speed;
init_waypoint->crossat = - 10000;
init_waypoint->gear_down = false;
init_waypoint->flaps_down = false;
init_waypoint->finished = false;
wpt_vector_iterator i = waypoints.begin();
while (i != waypoints.end())
{
//cerr << "Checking status of each waypoint: " << (*i)->name << endl;
SGWayPoint first(init_waypoint->longitude,
@ -229,11 +269,13 @@ FGAIFlightPlan::FGAIFlightPlan(FGAIModelEntity *entity,
//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;
}
@ -242,7 +284,13 @@ FGAIFlightPlan::FGAIFlightPlan(FGAIModelEntity *entity,
FGAIFlightPlan::~FGAIFlightPlan()
{
waypoints.clear();
deleteWaypoints();
//waypoints.clear();
//while (waypoints.begin() != waypoints.end())
// {
// delete *(waypoints.begin());
// waypoints.erase (waypoints.begin());
// }
}
@ -266,7 +314,9 @@ FGAIFlightPlan::getCurrentWaypoint( void )
FGAIFlightPlan::waypoint*
FGAIFlightPlan::getNextWaypoint( void )
{
if (wpt_iterator == waypoints.end()) {
wpt_vector_iterator i = waypoints.end();
i--; // end() points to one element after the last one.
if (wpt_iterator == i) {
return 0;
} else {
wpt_vector_iterator next = wpt_iterator;
@ -274,14 +324,27 @@ FGAIFlightPlan::getNextWaypoint( void )
}
}
void FGAIFlightPlan::IncrementWaypoint( void )
void FGAIFlightPlan::IncrementWaypoint(bool eraseWaypoints )
{
wpt_iterator++;
if (eraseWaypoints)
{
if (wpt_iterator == waypoints.begin())
wpt_iterator++;
else
{
delete *(waypoints.begin());
waypoints.erase(waypoints.begin());
wpt_iterator = waypoints.begin();
wpt_iterator++;
}
}
else
wpt_iterator++;
}
// gives distance in feet from a position to a waypoint
double FGAIFlightPlan::getDistanceToGo(double lat, double lon, waypoint* wp){
// get size of a degree at the present latitude
// get size of a degree2 at the present latitude
// this won't work over large distances
double ft_per_deg_lat = 366468.96 - 3717.12 * cos(lat / SG_RADIANS_TO_DEGREES);
double ft_per_deg_lon = 365228.16 * cos(lat / SG_RADIANS_TO_DEGREES);
@ -293,12 +356,28 @@ double FGAIFlightPlan::getDistanceToGo(double lat, double lon, waypoint* wp){
// sets distance in feet from a lead point to the current waypoint
void FGAIFlightPlan::setLeadDistance(double speed, double bearing,
waypoint* current, waypoint* next){
double turn_radius = 0.1911 * speed * speed; // an estimate for 25 degrees bank
double turn_radius;
if (fabs(speed) > 1)
turn_radius = 0.1911 * speed * speed; // an estimate for 25 degrees bank
else
turn_radius = 1.0;
double inbound = bearing;
double outbound = getBearing(current, next);
double diff = fabs(inbound - outbound);
if (diff > 180.0) diff = 360.0 - diff;
lead_distance = turn_radius * sin(diff * SG_DEGREES_TO_RADIANS);
leadInAngle = fabs(inbound - outbound);
if (leadInAngle > 180.0)
leadInAngle = 360.0 - leadInAngle;
if (leadInAngle < 1.0) // To prevent lead_dist from getting so small it is skipped
leadInAngle = 1.0;
lead_distance = turn_radius * sin(leadInAngle * SG_DEGREES_TO_RADIANS);
// if ((errno == EDOM) || (errno == ERANGE) || lead_distance < 1.0)
// {
// cerr << "Lead Distance = " << lead_distance
// << "Diff = " << diff
// << "Turn Radius = " << turn_radius
// << "Speed = " << speed << endl;
// }
}
void FGAIFlightPlan::setLeadDistance(double distance_ft){
@ -345,310 +424,51 @@ double FGAIFlightPlan::getBearing(double lat, double lon, waypoint* wp){
// if (!southerly && !easterly) return 270.0 + angle;
SGWayPoint sgWp(wp->longitude,wp->latitude, wp->altitude, SGWayPoint::WGS84, string("temp"));
sgWp.CourseAndDistance(lon, lat, wp->altitude, &course, &distance);
return course;
// Omit a compiler warning.
//if ((errno == EDOM) || (errno == ERANGE))
// {
// cerr << "Lon: " << wp->longitude
// << "Lat = " << wp->latitude
// << "Tgt Lon = " <<
// << "TgT Lat = " << speed << endl;
// }
}
/* 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)
void FGAIFlightPlan::deleteWaypoints()
{
double wind_speed;
double wind_heading;
FGRunway rwy;
double lat, lon, az;
double lat2, lon2, az2;
int direction;
//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;
// Temporary code to add some small random variation to aircraft parking positions;
direction = (rand() % 360);
geo_direct_wgs_84 ( 0, dep->_latitude, dep->_longitude, direction,
100,
&lat2, &lon2, &az2 );
waypoint *wpt = new waypoint;
wpt->name = dep->_id; //wpt_node->getStringValue("name", "END");
wpt->latitude = lat2;
wpt->longitude = lon2;
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;
wpt->on_ground = true;
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 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 * SG_FEET_TO_METER,
&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 = true;
waypoints.push_back(wpt);
direction = (rand() % 360);
geo_direct_wgs_84 ( 0, arr->_latitude, arr->_longitude, direction,
100,
&lat2, &lon2, &az2 );
// Add the final destination waypoint
wpt = new waypoint;
wpt->name = arr->_id; //wpt_node->getStringValue("name", "END");
wpt->latitude = lat2;
wpt->longitude = lon2;
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 = true;
waypoints.push_back(wpt);
// And finally one more named "END"
wpt = new waypoint;
wpt->name = "END"; //wpt_node->getStringValue("name", "END");
wpt->latitude = lat2;
wpt->longitude = lon2;
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 = lat2;
wpt->longitude = lon2;
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);
for (wpt_vector_iterator i = waypoints.begin(); i != waypoints.end();i++)
delete (*i);
waypoints.clear();
}
// Delete all waypoints except the last,
// which we will recycle as the first waypoint in the next leg;
void FGAIFlightPlan::resetWaypoints()
{
if (waypoints.begin() == waypoints.end())
return;
else
{
waypoint *wpt = new waypoint;
wpt_vector_iterator i = waypoints.end();
i--;
wpt->name = (*i)->name;
wpt->latitude = (*i)->latitude;
wpt->longitude = (*i)->longitude;
wpt->altitude = (*i)->altitude;
wpt->speed = (*i)->speed;
wpt->crossat = (*i)->crossat;
wpt->gear_down = (*i)->gear_down;
wpt->flaps_down= (*i)->flaps_down;
wpt->finished = false;
wpt->on_ground = (*i)->on_ground;
//cerr << "Recycling waypoint " << wpt->name << endl;
deleteWaypoints();
waypoints.push_back(wpt);
}
}

View file

@ -24,6 +24,7 @@
#include <string>
#include <Airports/simple.hxx>
#include <Airports/runways.hxx>
#include "AIBase.hxx"
@ -53,15 +54,21 @@ public:
double course,
time_t start,
FGAirport *dep,
FGAirport *arr);
FGAirport *arr,
bool firstLeg,
double radius,
string fltType,
string acType,
string airline);
~FGAIFlightPlan();
waypoint* getPreviousWaypoint( void );
waypoint* getCurrentWaypoint( void );
waypoint* getNextWaypoint( void );
void IncrementWaypoint( void );
void IncrementWaypoint( bool erase );
double getDistanceToGo(double lat, double lon, waypoint* wp);
int getLeg () { return leg;};
void setLeadDistance(double speed, double bearing, waypoint* current, waypoint* next);
void setLeadDistance(double distance_ft);
double getLeadDistance( void ) const {return lead_distance;}
@ -69,10 +76,17 @@ public:
double getBearing(double lat, double lon, waypoint* next);
time_t getStartTime() { return start_time; };
void create(FGAirport *dep, FGAirport *arr, double alt, double speed);
void create(FGAirport *dep, FGAirport *arr, int leg, double alt, double speed, double lat, double lon,
bool firstLeg, double radius, string fltType, string aircraftType, string airline);
void setLeg(int val) { leg = val;};
void setTime(time_t st) { start_time = st; };
int getGate() { return gateId; };
double getLeadInAngle() { return leadInAngle; };
string getRunway() { return rwy._rwy_no; };
string getRunwayId() { return rwy._id; };
private:
FGRunway rwy;
typedef vector <waypoint*> wpt_vector_type;
typedef wpt_vector_type::iterator wpt_vector_iterator;
@ -81,8 +95,21 @@ private:
double distance_to_go;
double lead_distance;
double leadInAngle;
time_t start_time;
int leg;
int gateId;
void createPushBack(bool, FGAirport*, double, double, double, string, string, string);
void createTaxi(bool, int, FGAirport *, double, string, string, string);
void createTakeOff(bool, FGAirport *, double);
void createClimb(bool, FGAirport *, double, double);
void createCruise(bool, FGAirport*, FGAirport*, double, double, double, double);
void createDecent(FGAirport *);
void createLanding(FGAirport *);
void createParking(FGAirport *);
void deleteWaypoints();
void resetWaypoints();
};

View file

@ -0,0 +1,822 @@
/******************************************************************************
* AIFlightPlanCreate.cxx
* Written by Durk Talsma, started May, 2004.
*
* This program is free software; you can redistribute it and/or
* modify it 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*
**************************************************************************/
#include <AIFlightPlan.hxx>
#include <simgear/math/sg_geodesy.hxx>
#include <Airports/runways.hxx>
#include <Environment/environment_mgr.hxx>
#include <Environment/environment.hxx>
/* 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)
*
* This is the top-level function, and the only one that publicly available.
*
*/
// Check lat/lon values during initialization;
void FGAIFlightPlan::create(FGAirport *dep, FGAirport *arr, int legNr, double alt, double speed,
double latitude, double longitude, bool firstFlight,
double radius, string fltType, string aircraftType, string airline)
{
int currWpt = wpt_iterator - waypoints.begin();
switch(legNr)
{
case 1:
//cerr << "Creating Push_Back" << endl;
createPushBack(firstFlight,dep, latitude, longitude, radius, fltType, aircraftType, airline);
//cerr << "Done" << endl;
break;
case 2:
//cerr << "Creating Taxi" << endl;
createTaxi(firstFlight, 1, dep, radius, fltType, aircraftType, airline);
break;
case 3:
//cerr << "Creating TAkeoff" << endl;
createTakeOff(firstFlight, dep, speed);
break;
case 4:
//cerr << "Creating Climb" << endl;
createClimb(firstFlight, dep, speed, alt);
break;
case 5:
//cerr << "Creating Cruise" << endl;
createCruise(firstFlight, dep,arr, latitude, longitude, speed, alt);
break;
case 6:
//cerr << "Creating Decent" << endl;
createDecent(arr);
break;
case 7:
//cerr << "Creating Landing" << endl;
createLanding(arr);
break;
case 8:
//cerr << "Creating Taxi 2" << endl;
createTaxi(false, 2, arr, radius, fltType, aircraftType, airline);
break;
case 9:
//cerr << "Creating Parking" << endl;
createParking(arr);
break;
default:
//exit(1);
cerr << "Unknown case: " << legNr << endl;
}
wpt_iterator = waypoints.begin()+currWpt;
leg++;
}
/*******************************************************************
* createPushBack
* initialize the Aircraft at the parking location
******************************************************************/
void FGAIFlightPlan::createPushBack(bool firstFlight, FGAirport *dep,
double latitude,
double longitude,
double radius,
string fltType,
string aircraftType,
string airline)
{
double heading;
double lat;
double lon;
double lat2;
double lon2;
double az2;
//int currWpt = wpt_iterator - waypoints.begin();
// Erase all existing waypoints.
//resetWaypoints();
// We only need to get a valid parking if this is the first leg.
// Otherwise use the current aircraft position.
if (firstFlight)
{
if (!(dep->getAvailableParking(&lat, &lon, &heading, &gateId, radius, fltType, aircraftType, airline)))
{
cerr << "Could not find parking " << endl;
}
}
else
{
dep->getParking(gateId, &lat, &lon, &heading);
//lat = latitude;
//lon = longitude;
//heading = getHeading();
}
heading += 180.0;
if (heading > 360)
heading -= 360;
waypoint *wpt = new waypoint;
wpt->name = "park";
wpt->latitude = lat;
wpt->longitude = lon;
wpt->altitude = dep->getElevation();
wpt->speed = -10;
wpt->crossat = -10000;
wpt->gear_down = true;
wpt->flaps_down= true;
wpt->finished = false;
wpt->on_ground = true;
waypoints.push_back(wpt);
// Add park twice, because it uses park once for initialization and once
// to trigger the departure ATC message
geo_direct_wgs_84 ( 0, lat, lon, heading,
10,
&lat2, &lon2, &az2 );
wpt = new waypoint;
wpt->name = "park2";
wpt->latitude = lat2;
wpt->longitude = lon2;
wpt->altitude = dep->getElevation();
wpt->speed = -10;
wpt->crossat = -10000;
wpt->gear_down = true;
wpt->flaps_down= true;
wpt->finished = false;
wpt->on_ground = true;
waypoints.push_back(wpt);
geo_direct_wgs_84 ( 0, lat, lon, heading,
100,
&lat2, &lon2, &az2 );
wpt = new waypoint;
wpt->name = "taxiStart";
wpt->latitude = lat2;
wpt->longitude = lon2;
wpt->altitude = dep->getElevation();
wpt->speed = 10;
wpt->crossat = -10000;
wpt->gear_down = true;
wpt->flaps_down= true;
wpt->finished = false;
wpt->on_ground = true;
waypoints.push_back(wpt);
//wpt = new waypoint;
//wpt->name = "END";
//wpt->finished = false;
//waypoints.push_back(wpt); // add one more to prevent a segfault.
//waypoints.push_back(wpt); // add one more to prevent a segfault.
//wpt_iterator = waypoints.begin();
//if (!firstFlight)
// wpt_iterator++;
//wpt_iterator = waypoints.begin()+currWpt;
}
/*******************************************************************
* createCreate Taxi.
* initialize the Aircraft at the parking location
******************************************************************/
void FGAIFlightPlan::createTaxi(bool firstFlight, int direction, FGAirport *apt, double radius, string fltType, string acType, string airline)
{
double wind_speed;
double wind_heading;
double heading;
//FGRunway rwy;
double lat, lon, az;
double lat2, lon2, az2;
//int direction;
waypoint *wpt;
// Erase all existing waypoints.
// wpt_vector_iterator i= waypoints.begin();
//resetWaypoints();
//int currWpt = wpt_iterator - waypoints.begin();
if (direction == 1)
{
// Get the current active runway, based on code from David Luff
// This should actually be unified and extended to include
// Preferential runway use schema's
//FGEnvironment
//stationweather = ((FGEnvironmentMgr *) globals->get_subsystem("environment"))
//->getEnvironment(apt->getLatitude(), apt->getLongitude(), apt->getElevation());
//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(apt->getId(), int(wind_heading));
string name;
apt->getActiveRunway("com", 1, &name);
if (!(globals->get_runways()->search(apt->getId(),
name,
&rwy)))
{
cout << "Failed to find runway for " << apt->getId() << endl;
// Hmm, how do we handle a potential error like this?
exit(1);
}
//string test;
//apt->getActiveRunway(string("com"), 1, &test);
//exit(1);
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 = "Airport Center";
wpt->latitude = apt->getLatitude();
wpt->longitude = apt->getLongitude();
wpt->altitude = apt->getElevation();
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);
//Add the runway startpoint;
wpt = new waypoint;
wpt->name = "Runway Takeoff";
wpt->latitude = lat2;
wpt->longitude = lon2;
wpt->altitude = apt->getElevation();
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);
//wpt = new waypoint;
//wpt->finished = false;
//waypoints.push_back(wpt); // add one more to prevent a segfault.
}
else
{
//direction = (rand() % 360);
//geo_direct_wgs_84 ( 0, arr->getLatitude(), arr->getLongitude(), direction,
//100,
//&lat2, &lon2, &az2 );
// This next statement really requires the flight plan to be
// split up into smaller sections, because
// gate assignments will typically not be known until minutes before
// landing, and certainly not at the start of a 10 hour flight.
apt->getAvailableParking(&lat, &lon, &heading, &gateId, radius, fltType, acType, airline);
heading += 180.0;
if (heading > 360)
heading -= 360;
geo_direct_wgs_84 ( 0, lat, lon, heading,
100,
&lat2, &lon2, &az2 );
//Add the runway center
wpt = new waypoint;
wpt->name = "Airport Center";
wpt->latitude = apt->getLatitude();
wpt->longitude = apt->getLongitude();
wpt->altitude = apt->getElevation();
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);
// Add the final destination waypoint
wpt = new waypoint;
wpt->name = "Begin Parkingg"; //apt->getId(); //wpt_node->getStringValue("name", "END");
wpt->latitude = lat2;
wpt->longitude = lon2;
wpt->altitude = apt->getElevation();
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);
}
// wpt_iterator = waypoints.begin();
//if (!firstFlight)
// wpt_iterator++;
//wpt_iterator = waypoints.begin()+currWpt;
}
/*******************************************************************
* CreateTakeOff
* initialize the Aircraft at the parking location
******************************************************************/
void FGAIFlightPlan::createTakeOff(bool firstFlight, FGAirport *apt, double speed)
{
double wind_speed;
double wind_heading;
double heading;
//FGRunway rwy;
double lat, lon, az;
double lat2, lon2, az2;
//int direction;
waypoint *wpt;
// Erase all existing waypoints.
// wpt_vector_iterator i= waypoints.begin();
//while(waypoints.begin() != waypoints.end())
// {
// delete *(i);
// waypoints.erase(i);
// }
//resetWaypoints();
// Get the current active runway, based on code from David Luff
// This should actually be unified and extended to include
// Preferential runway use schema's
if (firstFlight)
{
string name;
apt->getActiveRunway("com", 1, &name);
if (!(globals->get_runways()->search(apt->getId(),
name,
&rwy)))
{
cout << "Failed to find runway for " << apt->getId() << endl;
// Hmm, how do we handle a potential error like this?
exit(1);
}
//string test;
//apt->getActiveRunway(string("com"), 1, &test);
//exit(1);
}
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 - 105.0,
&lat2, &lon2, &az2 );
wpt = new waypoint;
wpt->name = "accel";
wpt->latitude = lat2;
wpt->longitude = lon2;
wpt->altitude = apt->getElevation();
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 = apt->getElevation()+3000;
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);
// waypoints.push_back(wpt);
//waypoints.push_back(wpt); // add one more to prevent a segfault.
// wpt_iterator = waypoints.begin();
//if (!firstFlight)
// wpt_iterator++;
}
/*******************************************************************
* CreateClimb
* initialize the Aircraft at the parking location
******************************************************************/
void FGAIFlightPlan::createClimb(bool firstFlight, FGAirport *apt, double speed, double alt)
{
double wind_speed;
double wind_heading;
double heading;
//FGRunway rwy;
double lat, lon, az;
double lat2, lon2, az2;
//int direction;
waypoint *wpt;
// Erase all existing waypoints.
// wpt_vector_iterator i= waypoints.begin();
//while(waypoints.begin() != waypoints.end())
// {
// delete *(i);
// waypoints.erase(i);
// }
//resetWaypoints();
// Get the current active runway, based on code from David Luff
// This should actually be unified and extended to include
// Preferential runway use schema's
if (firstFlight)
{
string name;
apt->getActiveRunway("com", 1, &name);
if (!(globals->get_runways()->search(apt->getId(),
name,
&rwy)))
{
cout << "Failed to find runway for " << apt->getId() << endl;
// Hmm, how do we handle a potential error like this?
exit(1);
}
//string test;
//apt->getActiveRunway(string("com"), 1, &test);
//exit(1);
}
heading = rwy._heading;
double azimuth = heading + 180.0;
while ( azimuth >= 360.0 ) { azimuth -= 360.0; }
geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, heading,
10*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);
geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, heading,
20*SG_NM_TO_METER,
&lat2, &lon2, &az2 );
wpt = new waypoint;
wpt->name = "18000ft climb";
wpt->latitude = lat2;
wpt->longitude = lon2;
wpt->altitude = 18000;
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);
//waypoints.push_back(wpt);
//waypoints.push_back(wpt); // add one more to prevent a segfault.
// wpt_iterator = waypoints.begin();
//if (!firstFlight)
// wpt_iterator++;
}
/*******************************************************************
* CreateCruise
* initialize the Aircraft at the parking location
******************************************************************/
void FGAIFlightPlan::createCruise(bool firstFlight, FGAirport *dep, FGAirport *arr, double latitude, double longitude, double speed, double alt)
{
double wind_speed;
double wind_heading;
double heading;
//FGRunway rwy;
double lat, lon, az;
double lat2, lon2, az2;
double azimuth;
//int direction;
waypoint *wpt;
// Erase all existing waypoints.
// wpt_vector_iterator i= waypoints.begin();
//while(waypoints.begin() != waypoints.end())
// {
// delete *(i);
// waypoints.erase(i);
// }
//resetWaypoints();
wpt = new waypoint;
wpt->name = "Cruise"; //wpt_node->getStringValue("name", "END");
wpt->latitude = latitude;
wpt->longitude = longitude;
wpt->altitude = alt;
wpt->speed = speed;
wpt->crossat = -10000;
wpt->gear_down = false;
wpt->flaps_down= false;
wpt->finished = false;
wpt->on_ground = false;
waypoints.push_back(wpt);
//Beginning of Decent
string name;
arr->getActiveRunway("com", 2, &name);
if (!(globals->get_runways()->search(arr->getId(),
name,
&rwy)))
{
cout << "Failed to find runway for " << arr->getId() << endl;
// Hmm, how do we handle a potential error like this?
exit(1);
}
//string test;
//arr->getActiveRunway(string("com"), 1, &test);
//exit(1);
//cerr << "Altitude = " << alt << endl;
//cerr << "Done" << endl;
//if (arr->getId() == "EHAM")
// {
// cerr << "Creating cruise to EHAM " << latitude << " " << longitude << endl;
// }
heading = rwy._heading;
azimuth = heading + 180.0;
while ( azimuth >= 360.0 ) { azimuth -= 360.0; }
// Note: This places us at the location of the active
// runway during initial cruise. This needs to be
// fixed later.
geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, azimuth,
110000,
&lat2, &lon2, &az2 );
wpt = new waypoint;
wpt->name = "BOD"; //wpt_node->getStringValue("name", "END");
wpt->latitude = lat2;
wpt->longitude = lon2;
wpt->altitude = alt;
wpt->speed = speed;
wpt->crossat = alt;
wpt->gear_down = false;
wpt->flaps_down= false;
wpt->finished = false;
wpt->on_ground = false;
waypoints.push_back(wpt);
//waypoints.push_back(wpt);
//waypoints.push_back(wpt); // add one more to prevent a segfault.
//wpt_iterator = waypoints.begin();
//if (!firstFlight)
// wpt_iterator++;
}
/*******************************************************************
* CreateDecent
* initialize the Aircraft at the parking location
******************************************************************/
void FGAIFlightPlan::createDecent(FGAirport *apt)
{
// Ten thousand ft. Slowing down to 240 kts
double wind_speed;
double wind_heading;
double heading;
//FGRunway rwy;
double lat, lon, az;
double lat2, lon2, az2;
double azimuth;
//int direction;
waypoint *wpt;
//// Erase all existing waypoints.
// wpt_vector_iterator i= waypoints.begin();
//while(waypoints.begin() != waypoints.end())
// {
// delete *(i);
// waypoints.erase(i);
// }
//resetWaypoints();
//Beginning of Decent
string name;
apt->getActiveRunway("com", 2, &name);
if (!(globals->get_runways()->search(apt->getId(),
name,
&rwy)))
{
cout << "Failed to find runway for " << apt->getId() << endl;
// Hmm, how do we handle a potential error like this?
exit(1);
}
//string test;
//apt->getActiveRunway(string("com"), 1, &test);
//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 = "Dec 10000ft"; //wpt_node->getStringValue("name", "END");
wpt->latitude = lat2;
wpt->longitude = lon2;
wpt->altitude = apt->getElevation();
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 = apt->getElevation();
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);
//waypoints.push_back(wpt);
//waypoints.push_back(wpt); // add one more to prevent a segfault.
//wpt_iterator = waypoints.begin();
//wpt_iterator++;
//if (apt->getId() == "EHAM")
// {
// cerr << "Created Decend to EHAM " << lat2 << " " << lon2 << ": Runway = " << rwy._rwy_no
// << "heading " << heading << endl;
// }
}
/*******************************************************************
* CreateLanding
* initialize the Aircraft at the parking location
******************************************************************/
void FGAIFlightPlan::createLanding(FGAirport *apt)
{
// Ten thousand ft. Slowing down to 240 kts
double wind_speed;
double wind_heading;
double heading;
//FGRunway rwy;
double lat, lon, az;
double lat2, lon2, az2;
double azimuth;
//int direction;
waypoint *wpt;
heading = rwy._heading;
azimuth = heading + 180.0;
while ( azimuth >= 360.0 ) { azimuth -= 360.0; }
//Runway Threshold
geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, azimuth,
rwy._length*0.45 * SG_FEET_TO_METER,
&lat2, &lon2, &az2 );
wpt = new waypoint;
wpt->name = "Threshold"; //wpt_node->getStringValue("name", "END");
wpt->latitude = lat2;
wpt->longitude = lon2;
wpt->altitude = apt->getElevation();
wpt->speed = 150;
wpt->crossat = apt->getElevation();
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 = apt->getElevation();
wpt->speed = 30;
wpt->crossat = -10000;
wpt->gear_down = true;
wpt->flaps_down= true;
wpt->finished = false;
wpt->on_ground = true;
waypoints.push_back(wpt);
geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, heading,
rwy._length*0.45 * SG_FEET_TO_METER,
&lat2, &lon2, &az2 );
wpt = new waypoint;
wpt->name = "Threshold"; //wpt_node->getStringValue("name", "END");
wpt->latitude = lat2;
wpt->longitude = lon2;
wpt->altitude = apt->getElevation();
wpt->speed = 15;
wpt->crossat = apt->getElevation();
wpt->gear_down = true;
wpt->flaps_down= true;
wpt->finished = false;
wpt->on_ground = true;
waypoints.push_back(wpt);
//waypoints.push_back(wpt);
//waypoints.push_back(wpt); // add one more to prevent a segfault.
//wpt_iterator = waypoints.begin();
//wpt_iterator++;
//if (apt->getId() == "EHAM")
//{
// cerr << "Created Landing to EHAM " << lat2 << " " << lon2 << ": Runway = " << rwy._rwy_no
// << "heading " << heading << endl;
//}
}
/*******************************************************************
* CreateParking
* initialize the Aircraft at the parking location
******************************************************************/
void FGAIFlightPlan::createParking(FGAirport *apt)
{
waypoint* wpt;
double lat;
double lon;
double heading;
apt->getParking(gateId, &lat, &lon, &heading);
heading += 180.0;
if (heading > 360)
heading -= 360;
// Erase all existing waypoints.
// wpt_vector_iterator i= waypoints.begin();
//while(waypoints.begin() != waypoints.end())
// {
// delete *(i);
// waypoints.erase(i);
// }
//resetWaypoints();
// And finally one more named "END"
wpt = new waypoint;
wpt->name = "END"; //wpt_node->getStringValue("name", "END");
wpt->latitude = lat;
wpt->longitude = lon;
wpt->altitude = 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);
//waypoints.push_back(wpt);
//waypoints.push_back(wpt); // add one more to prevent a segfault.
//wpt_iterator = waypoints.begin();
//wpt_iterator++;
}

View file

@ -156,6 +156,8 @@ FGAIManager::createAircraft( FGAIModelEntity *entity, FGAISchedule *ref) {
} else {
ai_plane->SetPerformance(&FGAIAircraft::settings[FGAIAircraft::JET_TRANSPORT]);
}
ai_plane->setAcType(entity->acType);
ai_plane->setCompany(entity->company);
ai_plane->setHeading(entity->heading);
ai_plane->setSpeed(entity->speed);
ai_plane->setPath(entity->path.c_str());

View file

@ -9,7 +9,7 @@ libAIModel_a_SOURCES = \
AIBallistic.hxx AIBallistic.cxx \
AIStorm.hxx AIStorm.cxx \
AIThermal.hxx AIThermal.cxx \
AIFlightPlan.hxx AIFlightPlan.cxx \
AIFlightPlan.hxx AIFlightPlan.cxx AIFlightPlanCreate.cxx \
AIScenario.hxx AIScenario.cxx \
AICarrier.hxx AICarrier.cxx

View file

@ -133,7 +133,7 @@ void FGAIMgr::init() {
f_ident = file.substr(0, pos);
FGAirport a;
if(dclFindAirportID(f_ident, &a)) {
SGBucket sgb(a._longitude, a._latitude);
SGBucket sgb(a.getLongitude(), a.getLatitude());
int idx = sgb.gen_index();
if(facilities.find(idx) != facilities.end()) {
facilities[idx]->push_back(f_ident);

View file

@ -460,7 +460,7 @@ void FGATCDialog::FreqDisplay(string ident) {
FGAirport a;
if ( dclFindAirportID( ident, &a ) ) {
comm_list_type stations;
int found = current_commlist->FindByPos(a._longitude, a._latitude, a._elevation, 20.0, &stations);
int found = current_commlist->FindByPos(a.getLongitude(), a.getLatitude(), a.getElevation(), 20.0, &stations);
if(found) {
ostringstream ostr;
comm_list_iterator itr = stations.begin();

View file

@ -221,9 +221,9 @@ bool FGATCMgr::AIRegisterAirport(string ident) {
//cout << "ident = " << ident << '\n';
AirportATC *a = new AirportATC;
// I'm not entirely sure that this AirportATC structure business is actually needed - it just duplicates what we can find out anyway!
a->lon = ap._longitude;
a->lat = ap._latitude;
a->elev = ap._elevation;
a->lon = ap.getLongitude();
a->lat = ap.getLatitude();
a->elev = ap.getElevation();
a->atis_freq = GetFrequency(ident, ATIS);
//cout << "ATIS freq = " << a->atis_freq << '\n';
a->atis_active = false;
@ -270,9 +270,9 @@ bool FGATCMgr::CommRegisterAirport(string ident, int chan, atc_type tp) {
if(dclFindAirportID(ident, &ap)) {
AirportATC *a = new AirportATC;
// I'm not entirely sure that this AirportATC structure business is actually needed - it just duplicates what we can find out anyway!
a->lon = ap._longitude;
a->lat = ap._latitude;
a->elev = ap._elevation;
a->lon = ap.getLongitude();
a->lat = ap.getLatitude();
a->elev = ap.getElevation();
a->atis_freq = GetFrequency(ident, ATIS);
a->atis_active = false;
a->tower_freq = GetFrequency(ident, TOWER);

View file

@ -314,7 +314,7 @@ bool dclFindAirportID( const string& id, FGAirport *a ) {
SG_LOG( SG_GENERAL, SG_INFO, "Searching for airport code = " << id );
result = globals->get_airports()->search( id );
if ( result._id.empty() ) {
if ( result.getId().empty() ) {
SG_LOG( SG_GENERAL, SG_WARN,
"Failed to find " << id << " in basic.dat.gz" );
return false;
@ -327,8 +327,8 @@ bool dclFindAirportID( const string& id, FGAirport *a ) {
SG_LOG( SG_GENERAL, SG_INFO,
"Position for " << id << " is ("
<< a->_longitude << ", "
<< a->_latitude << ")" );
<< a->getLongitude() << ", "
<< a->getLatitude() << ")" );
return true;
}
@ -342,7 +342,7 @@ double dclGetAirportElev( const string& id ) {
"Finding elevation for airport: " << id );
if ( dclFindAirportID( id, &a ) ) {
return a._elevation * SG_FEET_TO_METER;
return a.getElevation() * SG_FEET_TO_METER;
} else {
return -9999.0;
}
@ -357,7 +357,7 @@ Point3D dclGetAirportPos( const string& id ) {
"Finding position for airport: " << id );
if ( dclFindAirportID( id, &a ) ) {
return Point3D(a._longitude, a._latitude, a._elevation);
return Point3D(a.getLongitude(), a.getLatitude(), a.getElevation());
} else {
return Point3D(0.0, 0.0, -9999.0);
}

View file

@ -276,7 +276,7 @@ bool FGCommList::FindByCode( string ICAO, ATCData& ad, atc_type tp ) {
FGAirport a;
if ( dclFindAirportID( ICAO, &a ) ) {
comm_list_type stations;
int found = FindByPos(a._longitude, a._latitude, a._elevation, 10.0, &stations, tp);
int found = FindByPos(a.getLongitude(), a.getLatitude(), a.getElevation(), 10.0, &stations, tp);
if(found) {
comm_list_iterator itr = stations.begin();
while(itr != stations.end()) {

View file

@ -232,8 +232,8 @@ bool fgAirportDBLoad( FGAirportList *airports, FGRunwayList *runways,
if ( ident == "#" || ident == "//" ) {
metar_in >> skipeol;
} else {
FGAirport a = airports->search( ident );
if ( a._id == ident ) {
const FGAirport &a = airports->search( ident );
if ( a.getId() == ident ) {
airports->has_metar( ident );
}
}

File diff suppressed because it is too large Load diff

View file

@ -3,6 +3,7 @@
// elevation in feet.
//
// Written by Curtis Olson, started April 1998.
// Updated by Durk Talsma, started December 2004.
//
// Copyright (C) 1998 Curtis L. Olson - http://www.flightgear.org/~curt
//
@ -37,6 +38,7 @@
#endif
#include <simgear/compiler.h>
#include <simgear/xml/easyxml.hxx>
#include STL_STRING
#include <map>
@ -46,17 +48,249 @@ SG_USING_STD(string);
SG_USING_STD(map);
SG_USING_STD(vector);
typedef vector<string> stringVec;
typedef vector<string>::iterator stringVecIterator;
typedef vector<string>::const_iterator stringVecConstIterator;
struct FGAirport {
string _id;
double _longitude;
double _latitude;
double _elevation;
string _code; // depricated and can be removed
string _name;
bool _has_metar;
typedef vector<time_t> timeVec;
typedef vector<time_t>::const_iterator timeVecConstIterator;
/***************************************************************************/
class ScheduleTime {
private:
timeVec start;
timeVec end;
stringVec scheduleNames;
double tailWind;
double crssWind;
public:
ScheduleTime() {};
ScheduleTime(const ScheduleTime &other);
ScheduleTime &operator= (const ScheduleTime &other);
string getName(time_t dayStart);
FGAirport() : _longitude(0), _latitude(0), _elevation(0) {}
void clear();
void addStartTime(time_t time) { start.push_back(time); };
void addEndTime (time_t time) { end. push_back(time); };
void addScheduleName(string sched) { scheduleNames.push_back(sched); };
void setTailWind(double wnd) { tailWind = wnd; };
void setCrossWind(double wnd) { tailWind = wnd; };
double getTailWind() { return tailWind; };
double getCrossWind() { return crssWind; };
};
//typedef vector<ScheduleTime> ScheduleTimes;
/*****************************************************************************/
class RunwayList
{
private:
string type;
stringVec preferredRunways;
public:
RunwayList() {};
RunwayList(const RunwayList &other);
RunwayList& operator= (const RunwayList &other);
void set(string, string);
void clear();
string getType() { return type; };
stringVec *getRwyList() { return &preferredRunways; };
string getRwyList(int j) { return preferredRunways[j]; };
};
typedef vector<RunwayList> RunwayListVec;
typedef vector<RunwayList>::iterator RunwayListVectorIterator;
typedef vector<RunwayList>::const_iterator RunwayListVecConstIterator;
/*****************************************************************************/
class RunwayGroup
{
private:
string name;
RunwayListVec rwyList;
int active;
//stringVec runwayNames;
int choice[2];
int nrActive;
public:
RunwayGroup() {};
RunwayGroup(const RunwayGroup &other);
RunwayGroup &operator= (const RunwayGroup &other);
void setName(string nm) { name = nm; };
void add(RunwayList list) { rwyList.push_back(list);};
void setActive(string aptId, double windSpeed, double windHeading, double maxTail, double maxCross);
int getNrActiveRunways() { return nrActive;};
void getActive(int i, string *name, string *type);
string getName() { return name; };
void clear() { rwyList.clear(); };
//void add(string, string);
};
typedef vector<RunwayGroup> PreferenceList;
typedef vector<RunwayGroup>::iterator PreferenceListIterator;
typedef vector<RunwayGroup>::const_iterator PreferenceListConstIterator;
/******************************************************************************/
class FGRunwayPreference : public XMLVisitor {
private:
string value;
string scheduleName;
ScheduleTime comTimes; // Commercial Traffic;
ScheduleTime genTimes; // General Aviation;
ScheduleTime milTimes; // Military Traffic;
ScheduleTime currTimes; // Needed for parsing;
RunwayList rwyList;
RunwayGroup rwyGroup;
PreferenceList preferences;
time_t processTime(string);
bool initialized;
public:
FGRunwayPreference();
FGRunwayPreference(const FGRunwayPreference &other);
FGRunwayPreference & operator= (const FGRunwayPreference &other);
ScheduleTime *getSchedule(const char *trafficType);
RunwayGroup *getGroup(const string groupName);
bool available() { return initialized; };
// Some overloaded virtual XMLVisitor members
virtual void startXML ();
virtual void endXML ();
virtual void startElement (const char * name, const XMLAttributes &atts);
virtual void endElement (const char * name);
virtual void data (const char * s, int len);
virtual void pi (const char * target, const char * data);
virtual void warning (const char * message, int line, int column);
virtual void error (const char * message, int line, int column);
};
class FGParking {
private:
double latitude;
double longitude;
double heading;
double radius;
int index;
string parkingName;
string type;
string airlineCodes;
bool available;
double processPosition(string pos);
public:
FGParking() { available = true;};
//FGParking(FGParking &other);
FGParking(double lat,
double lon,
double hdg,
double rad,
int idx,
string name,
string tpe,
string codes);
void setLatitude (string lat) { latitude = processPosition(lat); };
void setLongitude(string lon) { longitude = processPosition(lon); };
void setHeading (double hdg) { heading = hdg; };
void setRadius (double rad) { radius = rad; };
void setIndex (int idx) { index = idx; };
void setName (string name) { parkingName = name; };
void setType (string tpe) { type = tpe; };
void setCodes (string codes){ airlineCodes= codes;};
bool isAvailable () { return available;};
void setAvailable(bool val) { available = val; };
double getLatitude () { return latitude; };
double getLongitude() { return longitude; };
double getHeading () { return heading; };
double getRadius () { return radius; };
int getIndex () { return index; };
string getType () { return type; };
string getCodes () { return airlineCodes;};
string getName () { return parkingName; };
bool operator< (const FGParking &other) const {return radius < other.radius; };
};
typedef vector<FGParking> FGParkingVec;
typedef vector<FGParking>::iterator FGParkingVecIterator;
typedef vector<FGParking>::const_iterator FGParkingVecConstIterator;
class FGAirport : public XMLVisitor{
private:
string _id;
double _longitude;
double _latitude;
double _elevation;
string _code; // depricated and can be removed
string _name;
bool _has_metar;
FGParkingVec parkings;
FGRunwayPreference rwyPrefs;
time_t lastUpdate;
string prevTrafficType;
stringVec landing;
stringVec takeoff;
// Experimental keep a running average of wind dir and speed to prevent
// Erratic runway changes.
// Note: I should add these to the copy constructor and assigment operator to be
// constistent
double avWindHeading [10];
double avWindSpeed [10];
public:
FGAirport();
FGAirport(const FGAirport &other);
//operator= (FGAirport &other);
FGAirport(string id, double lon, double lat, double elev, string name, bool has_metar);
void getActiveRunway(string trafficType, int action, string *runway);
void chooseRunwayFallback(string *runway);
bool getAvailableParking(double *lat, double *lon, double *heading, int *gate, double rad, string fltype,
string acType, string airline);
void getParking (int id, double *lat, double* lon, double *heading);
FGParking *getParking(int i); // { if (i < parkings.size()) return parkings[i]; else return 0;};
void releaseParking(int id);
string getParkingName(int i);
const string getId() const { return _id;};
const string &getName() const { return _name;};
FGAirport *getAddress() { return this; };
double getLongitude() { return _longitude;};
double getLatitude() { return _latitude; };
double getElevation() { return _elevation;};
bool getMetar() { return _has_metar;};
void setId(string id) { _id = id;};
void setMetar(bool value) { _has_metar = value; };
void setRwyUse(FGRunwayPreference& ref);
// Some overloaded virtual XMLVisitor members
virtual void startXML ();
virtual void endXML ();
virtual void startElement (const char * name, const XMLAttributes &atts);
virtual void endElement (const char * name);
virtual void data (const char * s, int len);
virtual void pi (const char * target, const char * data);
virtual void warning (const char * message, int line, int column);
virtual void error (const char * message, int line, int column);
};
typedef map < string, FGAirport > airport_map;
@ -97,6 +331,8 @@ public:
// return station id's marked as having metar data.
FGAirport search( double lon_deg, double lat_deg, bool with_metar );
// search and return a pointer;
FGAirport* search( const string& id, FGAirport *result);
/**
* Return the number of airports in the list.

View file

@ -668,7 +668,7 @@ int NewWaypoint( string Tgt_Alt )
sprintf( NewTgtAirportId, "%s", TgtAptId.c_str() );
SGWayPoint wp( a._longitude, a._latitude, alt,
SGWayPoint wp( a.getLongitude(), a.getLatitude(), alt,
SGWayPoint::WGS84, TgtAptId );
rm->add_waypoint( wp );

View file

@ -399,11 +399,11 @@ FGMetarEnvironmentCtrl::init ()
->search( longitude->getDoubleValue(),
latitude->getDoubleValue(),
true );
FGMetarResult result = fetch_data( a._id );
FGMetarResult result = fetch_data( a.getId() );
if ( result.m != NULL ) {
SG_LOG( SG_GENERAL, SG_INFO, "closest station w/ metar = " << a._id);
SG_LOG( SG_GENERAL, SG_INFO, "closest station w/ metar = " << a.getId());
last_apt = a;
_icao = a._id;
_icao = a.getId();
search_elapsed = 0.0;
fetch_elapsed = 0.0;
update_metar_properties( result.m );
@ -413,8 +413,8 @@ FGMetarEnvironmentCtrl::init ()
} else {
// mark as no metar so it doesn't show up in subsequent
// searches.
SG_LOG( SG_GENERAL, SG_INFO, "no metar at metar = " << a._id );
globals->get_airports()->no_metar( a._id );
SG_LOG( SG_GENERAL, SG_INFO, "no metar at metar = " << a.getId() );
globals->get_airports()->no_metar( a.getId() );
}
}
}
@ -456,13 +456,13 @@ FGMetarEnvironmentCtrl::update(double delta_time_sec)
->search( longitude->getDoubleValue(),
latitude->getDoubleValue(),
true );
if ( last_apt._id != a._id
if ( last_apt.getId() != a.getId()
|| fetch_elapsed > same_station_interval_sec )
{
SG_LOG( SG_GENERAL, SG_INFO, "closest station w/ metar = " << a._id);
request_queue.push( a._id );
SG_LOG( SG_GENERAL, SG_INFO, "closest station w/ metar = " << a.getId());
request_queue.push( a.getId() );
last_apt = a;
_icao = a._id;
_icao = a.getId();
search_elapsed = 0.0;
fetch_elapsed = 0.0;
} else {
@ -534,7 +534,7 @@ FGMetarEnvironmentCtrl::fetch_data( const string &icao )
// fetch station elevation if exists
FGAirport a = globals->get_airports()->search( icao );
station_elevation_ft = a._elevation;
station_elevation_ft = a.getElevation();
// fetch current metar data
try {

View file

@ -18,8 +18,8 @@ AirportList::AirportList (int x, int y, int width, int height)
for (int i = 0; i < _nAirports; i++) {
const FGAirport *airport = _airports->getAirport(i);
snprintf(buf, 1023, "%s %s",
airport->_id.c_str(),
airport->_name.c_str());
airport->getId().c_str(),
airport->getName().c_str());
unsigned int buf_len = (strlen(buf) > 1023) ? 1023 : strlen(buf);
@ -43,7 +43,7 @@ AirportList::~AirportList ()
char *
AirportList::getListStringValue ()
{
return (char *)_airports->getAirport(getListIntegerValue())->_id.c_str();
return (char *)_airports->getAirport(getListIntegerValue())->getId().c_str();
}
// end of AirportList.cxx

View file

@ -325,12 +325,12 @@ GPS::update (double delta_time_sec)
FGAirport a;
//cout << "Airport found" << endl;
a = globals->get_airports()->search(longitude_deg, latitude_deg, false);
_wp1_ID_node->setStringValue(a._id.c_str());
wp1_longitude_deg = a._longitude;
wp1_latitude_deg = a._latitude;
_wp1_name_node->setStringValue(a._name.c_str());
_wp1_ID_node->setStringValue(a.getId().c_str());
wp1_longitude_deg = a.getLongitude();
wp1_latitude_deg = a.getLatitude();
_wp1_name_node->setStringValue(a.getName().c_str());
_get_nearest_airport_node->setBoolValue(false);
_last_wp1_ID = wp1_ID = a._id.c_str();
_last_wp1_ID = wp1_ID = a.getId().c_str();
}
// If the waypoint 0 ID has changed, try to find the new ID
@ -341,11 +341,11 @@ GPS::update (double delta_time_sec)
if (waypont_type == "airport") {
FGAirport a;
a = globals->get_airports()->search( wp0_ID );
if ( a._id == wp0_ID ) {
if ( a.getId() == wp0_ID ) {
//cout << "Airport found" << endl;
wp0_longitude_deg = a._longitude;
wp0_latitude_deg = a._latitude;
_wp0_name_node->setStringValue(a._name.c_str());
wp0_longitude_deg = a.getLongitude();
wp0_latitude_deg = a.getLatitude();
_wp0_name_node->setStringValue(a.getName().c_str());
}
}
else if (waypont_type == "nav") {
@ -380,11 +380,11 @@ GPS::update (double delta_time_sec)
if (waypont_type == "airport") {
FGAirport a;
a = globals->get_airports()->search( wp1_ID );
if ( a._id == wp1_ID ) {
if ( a.getId() == wp1_ID ) {
//cout << "Airport found" << endl;
wp1_longitude_deg = a._longitude;
wp1_latitude_deg = a._latitude;
_wp1_name_node->setStringValue(a._name.c_str());
wp1_longitude_deg = a.getLongitude();
wp1_latitude_deg = a.getLatitude();
_wp1_name_node->setStringValue(a.getName().c_str());
}
}
else if (waypont_type == "nav") {

View file

@ -636,7 +636,7 @@ bool fgFindAirportID( const string& id, FGAirport *a ) {
result = globals->get_airports()->search( id );
if ( result._id.empty() ) {
if ( result.getId().empty() ) {
SG_LOG( SG_GENERAL, SG_ALERT,
"Failed to find " << id << " in basic.dat.gz" );
return false;
@ -649,8 +649,8 @@ bool fgFindAirportID( const string& id, FGAirport *a ) {
SG_LOG( SG_GENERAL, SG_INFO,
"Position for " << id << " is ("
<< a->_longitude << ", "
<< a->_latitude << ")" );
<< a->getLongitude() << ", "
<< a->getLatitude() << ")" );
return true;
}
@ -665,7 +665,7 @@ static double fgGetAirportElev( const string& id ) {
"Finding elevation for airport: " << id );
if ( fgFindAirportID( id, &a ) ) {
return a._elevation;
return a.getElevation();
} else {
return -9999.0;
}
@ -718,9 +718,9 @@ static bool fgSetTowerPosFromAirportID( const string& id, double hdg ) {
float fudge_lat = .003f - fudge_lon;
if ( fgFindAirportID( id, &a ) ) {
fgSetDouble("/sim/tower/longitude-deg", a._longitude + fudge_lon);
fgSetDouble("/sim/tower/latitude-deg", a._latitude + fudge_lat);
fgSetDouble("/sim/tower/altitude-ft", a._elevation + towerheight);
fgSetDouble("/sim/tower/longitude-deg", a.getLongitude() + fudge_lon);
fgSetDouble("/sim/tower/latitude-deg", a.getLatitude() + fudge_lat);
fgSetDouble("/sim/tower/altitude-ft", a.getElevation() + towerheight);
return true;
} else {
return false;
@ -1715,11 +1715,11 @@ bool fgInitSubsystems() {
globals->add_subsystem("Traffic Manager", new FGTrafficManager);
FGTrafficManager *dispatcher =
(FGTrafficManager*) globals->get_subsystem("Traffic Manager");
SGPath path =globals->get_fg_root();
path.append("Traffic/fgtraffic.xml");
SGPath path = globals->get_fg_root();
path.append("/Traffic/fgtraffic.xml");
readXML(path.str(),
*dispatcher);
globals->get_subsystem("Traffic Manager")->init();
*dispatcher);
//globals->get_subsystem("Traffic Manager")->init();
globals->add_subsystem("instrumentation", new FGInstrumentMgr);
globals->add_subsystem("systems", new FGSystemMgr);

View file

@ -96,8 +96,8 @@ bool fgNavDBInit( FGAirportList *airports,
// cout << r->get_type() << " " << r->get_apt_id() << " zero elev"
// << endl;
FGAirport a = airports->search( r->get_apt_id() );
if ( a._id == r->get_apt_id() ) {
r->set_elev_ft( a._elevation );
if ( a.getId() == r->get_apt_id() ) {
r->set_elev_ft( a.getElevation() );
// cout << " setting to " << a.elevation << endl;
}
}

View file

@ -81,6 +81,8 @@ FGScheduledFlight::FGScheduledFlight(const FGScheduledFlight &other)
callsign = other.callsign;
fltRules = other.fltRules;
departurePort = other.departurePort;
depId = other.depId;
arrId = other.arrId;
departureTime = other.departureTime;
cruiseAltitude = other.cruiseAltitude;
arrivalPort = other.arrivalPort;
@ -100,8 +102,11 @@ FGScheduledFlight::FGScheduledFlight(string cs,
{
callsign = cs;
fltRules = fr;
departurePort._id = depPrt;
arrivalPort._id = arrPrt;
//departurePort.setId(depPrt);
//arrivalPort.setId(arrPrt);
depId = depPrt;
arrId = arrPrt;
//cerr << "Constructor: departure " << depId << ". arrival " << arrId << endl;
//departureTime = processTimeString(deptime);
//arrivalTime = processTimeString(arrtime);
cruiseAltitude = cruiseAlt;
@ -225,7 +230,10 @@ FGAirport *FGScheduledFlight::getDepartureAirport()
{
initializeAirports();
}
return &departurePort;
if (initialized)
return departurePort;
else
return 0;
}
FGAirport * FGScheduledFlight::getArrivalAirport ()
{
@ -233,7 +241,10 @@ FGAirport * FGScheduledFlight::getArrivalAirport ()
{
initializeAirports();
}
return &arrivalPort;
if (initialized)
return arrivalPort;
else
return 0;
}
// Upon the first time of requesting airport information
@ -243,15 +254,24 @@ FGAirport * FGScheduledFlight::getArrivalAirport ()
// but we should improve that. The best idea is probably to cancel
// this flight entirely by removing it from the schedule, if one
// of the airports cannot be found.
void FGScheduledFlight::initializeAirports()
bool FGScheduledFlight::initializeAirports()
{
if(!(fgFindAirportID(arrivalPort._id, &arrivalPort )))
//cerr << "Initializing using : " << depId << " " << arrId << endl;
departurePort = globals->get_airports()->search( depId, departurePort );
if(departurePort->getId().empty())
{
//cerr << ": Could not find " << arrivalPort.id << endl;
cerr << "Could not find " << depId << endl;
return false;
}
if(!(fgFindAirportID(departurePort._id, &departurePort)))
arrivalPort = globals->get_airports()->search(arrId, arrivalPort);
if(arrivalPort->getId().empty())
{
//cerr << ": Could not find " << departurePort.id << endl;
cerr << "Could not find " << arrId << endl;
return false;
}
//cerr << "Found : " << departurePort->getId() << endl;
//cerr << "Found : " << arrivalPort->getId() << endl;
initialized = true;
return true;
}

View file

@ -51,15 +51,17 @@ class FGScheduledFlight
private:
string callsign;
string fltRules;
FGAirport departurePort;
FGAirport arrivalPort;
FGAirport *departurePort;
FGAirport *arrivalPort;
string depId;
string arrId;
time_t departureTime;
time_t arrivalTime;
time_t repeatPeriod;
int cruiseAltitude;
bool initialized;
void initializeAirports();
public:
FGScheduledFlight();
@ -77,6 +79,7 @@ public:
~FGScheduledFlight();
void update();
bool initializeAirports();
void adjustTime(time_t now);
@ -94,7 +97,7 @@ public:
};
time_t processTimeString(string time);
string getCallSign() {return callsign; };
};
typedef vector<FGScheduledFlight> FGScheduledFlightVec;

View file

@ -65,11 +65,23 @@ FGAISchedule::FGAISchedule(string mdl,
string liv,
string reg,
bool hvy,
string act,
string arln,
string mclass,
string fltpe,
double rad,
double grnd,
FGScheduledFlightVec flt)
{
modelPath = mdl;
livery = liv;
registration = reg;
acType = act;
airline = arln;
m_class = mclass;
flightType = fltpe;
radius = rad;
groundOffset = grnd;
heavy = hvy;
for (FGScheduledFlightVecIterator i = flt.begin();
i != flt.end();
@ -89,15 +101,49 @@ FGAISchedule::FGAISchedule(const FGAISchedule &other)
lat = other.lat;
lon = other.lon;
AIManagerRef = other.AIManagerRef;
acType = other.acType;
airline = other.airline;
m_class = other.m_class;
firstRun = other.firstRun;
radius = other.radius;
groundOffset = other.groundOffset;
flightType = other.flightType;
distanceToUser = other.distanceToUser;
}
FGAISchedule::~FGAISchedule()
{
}
void FGAISchedule::update(time_t now)
bool FGAISchedule::init()
{
//tm targetTimeDate;
//SGTime* currTimeDate = globals->get_time_params();
//tm *temp = currTimeDate->getGmt();
//char buffer[512];
//sgTimeFormatTime(&targetTimeDate, buffer);
//cout << "Scheduled Time " << buffer << endl;
//cout << "Time :" << time(NULL) << " SGTime : " << sgTimeGetGMT(temp) << endl;
for (FGScheduledFlightVecIterator i = flights.begin();
i != flights.end();
i++)
{
//i->adjustTime(now);
if (!(i->initializeAirports()))
return false;
}
//sort(flights.begin(), flights.end());
// Since time isn't initialized yet when this function is called,
// Find the closest possible airport.
// This should give a reasonable initialization order.
setClosestDistanceToUser();
return true;
}
bool FGAISchedule::update(time_t now)
{
FGAirport *dep;
FGAirport *arr;
@ -110,7 +156,7 @@ void FGAISchedule::update(time_t now)
string airport;
double courseToUser, courseToDest;
double distanceToUser, distanceToDest;
double distanceToDest;
double speed;
Point3D temp;
@ -123,7 +169,7 @@ void FGAISchedule::update(time_t now)
userLongitude;
if (fgGetBool("/sim/traffic-manager/enabled") == false)
return;
return true;
aimgr = (FGAIManager *) globals-> get_subsystem("ai_model");
// Before the flight status of this traffic entity is updated
@ -142,11 +188,11 @@ void FGAISchedule::update(time_t now)
if (firstRun)
{
for (FGScheduledFlightVecIterator i = flights.begin();
i != flights.end();
i++)
{
i->adjustTime(now);
}
i != flights.end();
i++)
{
i->adjustTime(now);
}
firstRun = false;
}
@ -168,13 +214,13 @@ void FGAISchedule::update(time_t now)
userLatitude = fgGetDouble("/position/latitude-deg");
userLongitude = fgGetDouble("/position/longitude-deg");
//cerr << "Estimated minimum distance to user: " << distanceToUser << endl;
// This flight entry is entirely in the past, do we need to
// push it forward in time to the next scheduled departure.
if ((i->getDepartureTime() < now) && (i->getArrivalTime() < now))
{
i->update();
return;
return true;
}
// Departure time in the past and arrival time in the future.
@ -189,19 +235,21 @@ void FGAISchedule::update(time_t now)
{
dep = i->getDepartureAirport();
arr = i->getArrivalAirport ();
if (!(dep && arr))
return false;
temp = sgPolarToCart3d(Point3D(dep->_longitude *
temp = sgPolarToCart3d(Point3D(dep->getLongitude() *
SG_DEGREES_TO_RADIANS,
dep->_latitude *
dep->getLatitude() *
SG_DEGREES_TO_RADIANS,
1.0));
a[0] = temp.x();
a[1] = temp.y();
a[2] = temp.z();
temp = sgPolarToCart3d(Point3D(arr->_longitude *
temp = sgPolarToCart3d(Point3D(arr->getLongitude() *
SG_DEGREES_TO_RADIANS,
arr->_latitude *
arr->getLatitude() *
SG_DEGREES_TO_RADIANS,
1.0));
b[0] = temp.x();
@ -219,8 +267,20 @@ void FGAISchedule::update(time_t now)
// total time enroute and elapsed time enroute.
totalTimeEnroute = i->getArrivalTime() - i->getDepartureTime();
elapsedTimeEnroute = now - i->getDepartureTime();
remainingTimeEnroute = i->getArrivalTime() - now;
if (now > i->getDepartureTime())
{
//err << "Lat = " << lat << ", lon = " << lon << endl;
//cerr << "Time diff: " << now-i->getDepartureTime() << endl;
elapsedTimeEnroute = now - i->getDepartureTime();
remainingTimeEnroute = i->getArrivalTime() - now;
}
else
{
lat = dep->getLatitude();
lon = dep->getLongitude();
elapsedTimeEnroute = 0;
remainingTimeEnroute = totalTimeEnroute;
}
angle *= ( (double) elapsedTimeEnroute/ (double) totalTimeEnroute);
@ -238,30 +298,28 @@ void FGAISchedule::update(time_t now)
}
temp = sgCartToPolar3d(Point3D(newPos[0], newPos[1],newPos[2]));
if (now > i->getDepartureTime())
{
//cerr << "Lat = " << lat << ", lon = " << lon << endl;
//cerr << "Time diff: " << now-i->getDepartureTime() << endl;
lat = temp.lat() * SG_RADIANS_TO_DEGREES;
lon = temp.lon() * SG_RADIANS_TO_DEGREES;
//err << "Lat = " << lat << ", lon = " << lon << endl;
//cerr << "Time diff: " << now-i->getDepartureTime() << endl;
}
else
{
lat = dep->_latitude;
lon = dep->_longitude;
lat = dep->getLatitude();
lon = dep->getLongitude();
}
SGWayPoint current (lon,
lat,
i->getCruiseAlt());
SGWayPoint user ( userLongitude,
userLatitude,
i->getCruiseAlt());
SGWayPoint dest ( arr->_longitude,
arr->_latitude,
SGWayPoint dest ( arr->getLongitude(),
arr->getLatitude(),
i->getCruiseAlt());
// We really only need distance to user
// and course to destination
@ -278,9 +336,9 @@ void FGAISchedule::update(time_t now)
//cerr << registration << " is currently enroute from "
// << 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) < TRAFFICTOAIDIST)
{
string flightPlanName = dep->_id + string("-") + arr->_id +
string flightPlanName = dep->getId() + string("-") + arr->getId() +
string(".xml");
int alt;
//if ((i->getDepartureTime() < now))
@ -294,32 +352,43 @@ void FGAISchedule::update(time_t now)
FGAIModelEntity entity;
entity.m_class = "jet_transport";
entity.m_class = m_class; //"jet_transport";
entity.company = airline; //i->getAirline();
entity.acType = acType; //i->getAcType();
entity.path = modelPath.c_str();
entity.flightplan = flightPlanName.c_str();
entity.latitude = lat;
entity.longitude = lon;
entity.altitude = i->getCruiseAlt() *100; // convert from FL to feet
entity.speed = 450;
entity.fp = new FGAIFlightPlan(&entity, courseToDest, i->getDepartureTime(), dep, arr);
entity.speed = speed;
entity.roll = 0.0;
entity.fp = new FGAIFlightPlan(&entity, courseToDest, i->getDepartureTime(), dep,
arr,true, radius, flightType, acType, airline);
// Fixme: A non-existent model path results in an
// abort, due to an unhandled exeption, in fg main loop.
AIManagerRef = aimgr->createAircraft( &entity, this);
//cerr << "Created: " << AIManagerRef << endl;
//cerr << "Class: " << m_class << ". acType: " << acType << ". Airline: " << airline << ". Speed = " << speed << ". From " << dep->getId() << " to " << arr->getId() << ". Time Fraction = " << (remainingTimeEnroute/(double) totalTimeEnroute) << endl;
//cerr << "Latitude : " << lat << ". Longitude : " << lon << endl;
//cerr << "Dep : " << dep->getLatitude()<< ", "<< dep->getLongitude() << endl;
//cerr << "Arr : " << arr->getLatitude()<< ", "<< arr->getLongitude() << endl;
//cerr << "Time remaining = " << (remainingTimeEnroute/3600.0) << endl;
//cerr << "Total time = " << (totalTimeEnroute/3600.0) << endl;
//cerr << "Distance remaining = " << distanceToDest*SG_METER_TO_NM << endl;
}
return;
}
return true;
}
// Both departure and arrival time are in the future, so this
// the aircraft is parked at the departure airport.
// Currently this status is mostly ignored, but in future
// versions, code should go here that -if within user range-
// positions these aircraft at parking locations at the airport.
if ((i->getDepartureTime() > now) && (i->getArrivalTime() > now))
if ((i->getDepartureTime() > now) && (i->getArrivalTime() > now))
{
dep = i->getDepartureAirport();
return;
return true;
}
}
}
@ -331,3 +400,71 @@ void FGAISchedule::next()
sort(flights.begin(), flights.end());
}
double FGAISchedule::getSpeed()
{
double courseToUser, courseToDest;
double distanceToUser, distanceToDest;
double speed, remainingTimeEnroute;
FGAirport *dep, *arr;
FGScheduledFlightVecIterator i = flights.begin();
dep = i->getDepartureAirport();
arr = i->getArrivalAirport ();
if (!(dep && arr))
return 0;
SGWayPoint dest ( dep->getLongitude(),
dep->getLatitude(),
i->getCruiseAlt());
SGWayPoint curr ( arr->getLongitude(),
arr->getLatitude(),
i->getCruiseAlt());
remainingTimeEnroute = i->getArrivalTime() - i->getDepartureTime();
dest.CourseAndDistance(curr, &courseToDest, &distanceToDest);
speed = (distanceToDest*SG_METER_TO_NM) /
((double) remainingTimeEnroute/3600.0);
return speed;
}
void FGAISchedule::setClosestDistanceToUser()
{
double course;
double dist;
Point3D temp;
time_t
totalTimeEnroute,
elapsedTimeEnroute;
double userLatitude = fgGetDouble("/position/latitude-deg");
double userLongitude = fgGetDouble("/position/longitude-deg");
FGAirport *dep;
distanceToUser = HUGE;
FGScheduledFlightVecIterator i = flights.begin();
while (i != flights.end())
{
dep = i->getDepartureAirport();
//if (!(dep))
//return HUGE;
SGWayPoint user ( userLongitude,
userLatitude,
i->getCruiseAlt());
SGWayPoint current (dep->getLongitude(),
dep->getLatitude(),
0);
user.CourseAndDistance(current, &course, &dist);
if (dist < distanceToUser)
{
distanceToUser = dist;
//cerr << "Found closest distance to user for " << registration << " to be " << distanceToUser << " at airport " << dep->getId() << endl;
}
i++;
}
//return distToUser;
}

View file

@ -29,6 +29,7 @@
#ifndef _FGSCHEDULE_HXX_
#define _FGSCHEDULE_HXX_
#define TRAFFICTOAIDIST 150.0
class FGAISchedule
@ -37,34 +38,56 @@ class FGAISchedule
string modelPath;
string livery;
string registration;
string airline;
string acType;
string m_class;
string flightType;
bool heavy;
FGScheduledFlightVec flights;
float lat;
float lon;
double radius;
double groundOffset;
double distanceToUser;
void* AIManagerRef;
bool firstRun;
public:
FGAISchedule(); // constructor
FGAISchedule(string, string, string, bool, FGScheduledFlightVec); // construct & init
FGAISchedule(string, string, string, bool, string, string, string, string, double, double, FGScheduledFlightVec); // construct & init
FGAISchedule(const FGAISchedule &other); // copy constructor
~FGAISchedule(); //destructor
void update(time_t now);
bool update(time_t now);
bool init();
double getSpeed ();
void setClosestDistanceToUser();
void next(); // forces the schedule to move on to the next flight.
time_t getDepartureTime () { return flights.begin()->getDepartureTime (); };
FGAirport * getDepartureAirport () { return flights.begin()->getDepartureAirport(); };
FGAirport * getArrivalAirport () { return flights.begin()->getArrivalAirport (); };
int getCruiseAlt () { return flights.begin()->getCruiseAlt (); };
double getRadius () { return radius; };
double getGroundOffset () { return groundOffset;};
string getFlightType () { return flightType;};
string getAirline () { return airline; };
string getAircraft () { return acType; };
string getCallSign () { return flights.begin()->getCallSign (); };
string getRegistration () { return registration;};
bool getHeavy () { return heavy; };
bool operator< (const FGAISchedule &other) const { return (distanceToUser < other.distanceToUser); };
//void * getAiRef () { return AIManagerRef; };
//FGAISchedule* getAddress () { return this;};
// More member functions follow later
};
typedef vector<FGAISchedule> ScheduleVector;
typedef vector<FGAISchedule>::iterator ScheduleVectorIterator;
typedef vector<FGAISchedule > ScheduleVector;
typedef vector<FGAISchedule >::iterator ScheduleVectorIterator;
#endif

View file

@ -53,6 +53,7 @@
#include <simgear/structure/subsystem_mgr.hxx>
#include <simgear/xml/easyxml.hxx>
#include <AIModel/AIAircraft.hxx>
#include <AIModel/AIFlightPlan.hxx>
#include <AIModel/AIBase.hxx>
#include <Airports/simple.hxx>
@ -73,21 +74,44 @@ FGTrafficManager::FGTrafficManager()
void FGTrafficManager::init()
{
//cerr << "Initializing Schedules" << endl;
time_t now = time(NULL) + fgGetLong("/sim/time/warp");
currAircraft = scheduledAircraft.begin();
while (currAircraft != scheduledAircraft.end())
{
if (!(currAircraft->init()))
{
currAircraft=scheduledAircraft.erase(currAircraft);
//cerr << "Erasing " << currAircraft->getRegistration() << endl;
currAircraft--;
}
else
{
currAircraft++;
}
}
//cerr << "Sorting by distance " << endl;
sort(scheduledAircraft.begin(), scheduledAircraft.end());
currAircraft = scheduledAircraft.begin();
currAircraftClosest = scheduledAircraft.begin();
//cerr << "Done initializing schedules" << endl;
}
void FGTrafficManager::update(double something)
{
//static const SGPropertyNode *warp = globals->get_props()->getNode("/sim/time/warp");
//time_t now = time(NULL) + globals->get_warp();
time_t now = time(NULL) + fgGetLong("/sim/time/warp");
// cerr << "TrafficManager update" << globals->get_warp() << endl;
if(currAircraft == scheduledAircraft.end())
if(currAircraft == scheduledAircraft.end())
{
//cerr << "resetting schedule " << endl;
currAircraft = scheduledAircraft.begin();
currAircraft->update(now);
currAircraft++;
}
if (!(currAircraft->update(now)))
{
// after proper initialization, we shouldnt get here.
// But let's make sure
cerr << "Failed to update aircraft schedule in traffic manager" << endl;
}
currAircraft++;
}
void FGTrafficManager::release(void *id)
@ -146,6 +170,18 @@ void FGTrafficManager::endElement (const char * name) {
livery = value;
else if (element == string("registration"))
registration = value;
else if (element == string("airline"))
airline = value;
else if (element == string("actype"))
acType = value;
else if (element == string("flighttype"))
flighttype = value;
else if (element == string("radius"))
radius = atoi(value.c_str());
else if (element == string("offset"))
offset = atoi(value.c_str());
else if (element == string("performance-class"))
m_class = value;
else if (element == string("heavy"))
{
if(value == string("true"))
@ -195,10 +231,16 @@ void FGTrafficManager::endElement (const char * name) {
{
//cerr << "Pushing back aircraft " << registration << endl;
scheduledAircraft.push_back(FGAISchedule(mdl,
livery,
registration,
heavy,
flights));
livery,
registration,
heavy,
acType,
airline,
m_class,
flighttype,
radius,
offset,
flights));
while(flights.begin() != flights.end())
flights.pop_back();
}

View file

@ -42,13 +42,14 @@ class FGTrafficManager : public SGSubsystem, public XMLVisitor
{
private:
ScheduleVector scheduledAircraft;
ScheduleVectorIterator currAircraft;
ScheduleVectorIterator currAircraft, currAircraftClosest;
string value;
string mdl, livery, registration, callsign, fltrules,
port, timeString, departurePort, departureTime, arrivalPort, arrivalTime,
repeat;
repeat, acType, airline, m_class, flighttype;
int cruiseAlt;
double radius, offset;
bool heavy;
IdList releaseList;