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 #endif
#include <simgear/math/point3d.hxx> #include <simgear/math/point3d.hxx>
#include <simgear/route/waypoint.hxx>
#include <Main/fg_props.hxx> #include <Main/fg_props.hxx>
#include <Main/globals.hxx> #include <Main/globals.hxx>
#include <Main/viewer.hxx>
#include <Scenery/scenery.hxx> #include <Scenery/scenery.hxx>
#include <Scenery/tilemgr.hxx>
#include <string> #include <string>
#include <math.h> #include <math.h>
#include <time.h> #include <time.h>
@ -33,7 +37,7 @@
SG_USING_STD(string); SG_USING_STD(string);
#include "AIAircraft.hxx" #include "AIAircraft.hxx"
static string tempReg;
// //
// accel, decel, climb_rate, descent_rate, takeoff_speed, climb_speed, // accel, decel, climb_rate, descent_rate, takeoff_speed, climb_speed,
// cruise_speed, descent_speed, land_speed // cruise_speed, descent_speed, land_speed
@ -54,17 +58,24 @@ const FGAIAircraft::PERF_STRUCT FGAIAircraft::settings[] = {
FGAIAircraft::FGAIAircraft(FGAIManager* mgr, FGAISchedule *ref) { FGAIAircraft::FGAIAircraft(FGAIManager* mgr, FGAISchedule *ref) {
trafficRef = ref; trafficRef = ref;
if (trafficRef)
groundOffset = trafficRef->getGroundOffset();
else
groundOffset = 0;
manager = mgr; manager = mgr;
_type_str = "aircraft"; _type_str = "aircraft";
_otype = otAircraft; _otype = otAircraft;
fp = 0; fp = 0;
dt_count = 0; dt_count = 0;
dt_elev_count = 0;
use_perf_vs = true; use_perf_vs = true;
isTanker = false; isTanker = false;
// set heading and altitude locks // set heading and altitude locks
hdg_lock = false; hdg_lock = false;
alt_lock = false; alt_lock = false;
roll = 0;
headingChangeRate = 0.0;
} }
@ -118,13 +129,24 @@ void FGAIAircraft::Run(double dt) {
if (fp) if (fp)
{ {
ProcessFlightPlan(dt);
time_t now = time(NULL) + fgGetLong("/sim/time/warp"); time_t now = time(NULL) + fgGetLong("/sim/time/warp");
ProcessFlightPlan(dt, now);
if (now < fp->getStartTime()) 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; double turn_radius_ft;
double turn_circum_ft; double turn_circum_ft;
double speed_north_deg_sec; double speed_north_deg_sec;
@ -133,11 +155,19 @@ void FGAIAircraft::Run(double dt) {
double alpha; double alpha;
// adjust speed // 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 (fabs(speed_diff) > 0.2) {
if (speed_diff > 0.0) speed += performance->accel * dt; if (speed_diff > 0.0) speed += performance->accel * dt;
if (speed_diff < 0.0) { 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; speed -= performance->decel * dt * 3;
} else { } else {
speed -= performance->decel * dt; speed -= performance->decel * dt;
@ -154,19 +184,98 @@ void FGAIAircraft::Run(double dt) {
// set new position // set new position
pos.setlat( pos.lat() + speed_north_deg_sec * dt); pos.setlat( pos.lat() + speed_north_deg_sec * dt);
pos.setlon( pos.lon() + speed_east_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 // adjust heading based on current bank angle
if (roll == 0.0)
roll = 0.01;
if (roll != 0.0) { if (roll != 0.0) {
turn_radius_ft = 0.088362 * speed * speed // double turnConstant;
/ tan( fabs(roll) / SG_RADIANS_TO_DEGREES ); //if (no_roll)
turn_circum_ft = SGD_2PI * turn_radius_ft; // turnConstant = 0.0088362;
dist_covered_ft = speed * 1.686 * dt; //else
alpha = dist_covered_ft / turn_circum_ft * 360.0; // turnConstant = 0.088362;
hdg += alpha * sign( roll ); // If on ground, calculate heading change directly
if ( hdg > 360.0 ) hdg -= 360.0; if (no_roll) {
if ( hdg < 0.0) hdg += 360.0; 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 // adjust target bank angle if heading lock engaged
if (hdg_lock) { if (hdg_lock) {
double bank_sense = 0.0; double bank_sense = 0.0;
@ -174,7 +283,7 @@ void FGAIAircraft::Run(double dt) {
if (diff > 180) diff = fabs(diff - 360); if (diff > 180) diff = fabs(diff - 360);
double sum = hdg + diff; double sum = hdg + diff;
if (sum > 360.0) sum -= 360.0; if (sum > 360.0) sum -= 360.0;
if (fabs(sum - tgt_heading) < 1.0) { if (fabs(sum - tgt_heading) < 1.0) {
bank_sense = 1.0; // right turn bank_sense = 1.0; // right turn
} else { } else {
bank_sense = -1.0; // left turn bank_sense = -1.0; // left turn
@ -184,6 +293,27 @@ void FGAIAircraft::Run(double dt) {
} else { } else {
tgt_roll = 30.0 * bank_sense; 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 // adjust bank angle, use 9 degrees per second
@ -191,6 +321,8 @@ void FGAIAircraft::Run(double dt) {
if (fabs(bank_diff) > 0.2) { if (fabs(bank_diff) > 0.2) {
if (bank_diff > 0.0) roll += 9.0 * dt; if (bank_diff > 0.0) roll += 9.0 * dt;
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) // 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); pos.setelev(altitude * SG_FEET_TO_METER);
double altitude_ft = altitude; 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 // find target vertical speed if altitude lock engaged
if (alt_lock && use_perf_vs) { if (alt_lock && use_perf_vs) {
if (altitude_ft < tgt_altitude) { if (altitude_ft < tgt_altitude) {
@ -303,9 +440,28 @@ void FGAIAircraft::SetFlightPlan(FGAIFlightPlan *f) {
fp = 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* prev = 0; // the one behind you
FGAIFlightPlan::waypoint* curr = 0; // the one ahead FGAIFlightPlan::waypoint* curr = 0; // the one ahead
FGAIFlightPlan::waypoint* next = 0; // the next plus 1 FGAIFlightPlan::waypoint* next = 0; // the next plus 1
@ -313,118 +469,483 @@ void FGAIAircraft::ProcessFlightPlan( double dt ) {
curr = fp->getCurrentWaypoint(); curr = fp->getCurrentWaypoint();
next = fp->getNextWaypoint(); next = fp->getNextWaypoint();
dt_count += dt; dt_count += dt;
if (!prev) { //beginning of flightplan, do this initialization once 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 prev = fp->getPreviousWaypoint(); //first waypoint
curr = fp->getCurrentWaypoint(); //second waypoint curr = fp->getCurrentWaypoint(); //second waypoint
next = fp->getNextWaypoint(); //third waypoint (might not exist!) next = fp->getNextWaypoint(); //third waypoint (might not exist!)
//cerr << "After load " << prev-> name << endl;
setLatitude(prev->latitude); setLatitude(prev->latitude);
setLongitude(prev->longitude); setLongitude(prev->longitude);
setSpeed(prev->speed); setSpeed(prev->speed);
setAltitude(prev->altitude); setAltitude(prev->altitude);
setHeading(fp->getBearing(prev->latitude, prev->longitude, curr)); if (prev->speed > 0.0)
if (next) fp->setLeadDistance(speed, hdg, curr, next); 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 if (curr->crossat > -1000.0) { //use a calculated descent/climb rate
use_perf_vs = false; use_perf_vs = false;
tgt_vs = (curr->crossat - prev->altitude)/ tgt_vs = (curr->crossat - prev->altitude)/
(fp->getDistanceToGo(pos.lat(), pos.lon(), curr)/ (fp->getDistanceToGo(pos.lat(), pos.lon(), curr)/
6076.0/prev->speed*60.0); 6076.0/prev->speed*60.0);
tgt_altitude = curr->crossat; tgt_altitude = curr->crossat;
} else { } else {
use_perf_vs = true; use_perf_vs = true;
tgt_altitude = prev->altitude; tgt_altitude = prev->altitude;
} }
alt_lock = hdg_lock = true; alt_lock = hdg_lock = true;
no_roll = prev->on_ground; 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 << "First waypoint: " << prev->name << endl;
//cout << " Target speed: " << tgt_speed << endl; //cout << " Target speed: " << tgt_speed << endl;
//cout << " Target altitude: " << tgt_altitude << endl; //cout << " Target altitude: " << tgt_altitude << endl;
//cout << " Target heading: " << tgt_heading << endl << endl; //cout << " Target heading: " << tgt_heading << endl << endl;
//cerr << "Done Flightplan init" << endl;
return; return;
} // end of initialization } // end of initialization
// let's only process the flight plan every 100 ms. // let's only process the flight plan every 100 ms.
if (dt_count < 0.1) { if ((dt_count < 0.1) || (now < fp->getStartTime()))
return; {
} else { //cerr << "done fp dt" << endl;
dt_count = 0; return;
// 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;
} else { } else {
double calc_bearing = fp->getBearing(pos.lat(), pos.lon(), curr); dt_count = 0;
double hdg_error = calc_bearing - tgt_heading;
if (fabs(hdg_error) > 1.0) {
TurnTo( calc_bearing );
}
} }
// 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) return ((props->getFloatValue("position/altitude-agl-ft") < 900.0)
&& (props->getFloatValue("velocities/airspeed-kt") && (props->getFloatValue("velocities/airspeed-kt")
< performance->land_speed*1.25)); < 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; } PERF_STRUCT;
public: public:
enum aircraft_e {LIGHT=0, WW2_FIGHTER, JET_TRANSPORT, JET_FIGHTER, TANKER}; enum aircraft_e {LIGHT=0, WW2_FIGHTER, JET_TRANSPORT, JET_FIGHTER, TANKER};
static const PERF_STRUCT settings[]; static const PERF_STRUCT settings[];
@ -68,7 +67,13 @@ public:
void YawTo(double angle); void YawTo(double angle);
void ClimbTo(double altitude); void ClimbTo(double altitude);
void TurnTo(double heading); 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; }; inline void SetTanker(bool setting) { isTanker = setting; };
@ -78,6 +83,10 @@ private:
bool hdg_lock; bool hdg_lock;
bool alt_lock; bool alt_lock;
double dt_count; double dt_count;
double dt_elev_count;
double headingChangeRate;
double groundTargetSpeed;
double groundOffset;
double dt; double dt;
const PERF_STRUCT *performance; const PERF_STRUCT *performance;
@ -87,8 +96,15 @@ private:
void Run(double dt); void Run(double dt);
double sign(double x); double sign(double x);
string acType;
string company;
int spinCounter;
double prevSpeed;
double prev_dist_to_go;
bool _getGearDown() const; bool _getGearDown() const;
bool reachedWaypoint;
}; };

View file

@ -26,6 +26,7 @@
#include <simgear/constants.h> #include <simgear/constants.h>
#include <simgear/math/point3d.hxx> #include <simgear/math/point3d.hxx>
#include <simgear/scene/model/placement.hxx> #include <simgear/scene/model/placement.hxx>
#include <simgear/misc/sg_path.hxx>
#include <Main/fg_props.hxx> #include <Main/fg_props.hxx>
@ -75,7 +76,9 @@ typedef struct {
double radius; // used by ship ojects, in feet double radius; // used by ship ojects, in feet
double x_offset; // used by ship ojects, in meters double x_offset; // used by ship ojects, in meters
double y_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 double z_offset; // used by ship ojects, in meters
string acType; // used by aircraft objects
string company; // used by aircraft objects
} FGAIModelEntity; } FGAIModelEntity;

View file

@ -45,6 +45,8 @@ FGAIFlightPlan::FGAIFlightPlan(string filename)
{ {
int i; int i;
start_time = 0; start_time = 0;
leg = 10;
gateId = 0;
SGPath path( globals->get_fg_root() ); SGPath path( globals->get_fg_root() );
path.append( ("/Data/AI/FlightPlans/" + filename).c_str() ); path.append( ("/Data/AI/FlightPlans/" + filename).c_str() );
SGPropertyNode root; SGPropertyNode root;
@ -55,7 +57,7 @@ FGAIFlightPlan::FGAIFlightPlan(string filename)
SG_LOG(SG_GENERAL, SG_ALERT, SG_LOG(SG_GENERAL, SG_ALERT,
"Error reading AI flight plan: " << path.str()); "Error reading AI flight plan: " << path.str());
// cout << path.str() << endl; // cout << path.str() << endl;
return; return;
} }
SGPropertyNode * node = root.getNode("flightplan"); SGPropertyNode * node = root.getNode("flightplan");
@ -94,8 +96,15 @@ FGAIFlightPlan::FGAIFlightPlan(FGAIModelEntity *entity,
double course, double course,
time_t start, time_t start,
FGAirport *dep, FGAirport *dep,
FGAirport *arr) FGAirport *arr,
bool firstLeg,
double radius,
string fltType,
string acType,
string airline)
{ {
leg = 10;
gateId=0;
start_time = start; start_time = start;
bool useInitialWayPoint = true; bool useInitialWayPoint = true;
bool useCurrentWayPoint = false; bool useCurrentWayPoint = false;
@ -116,55 +125,86 @@ FGAIFlightPlan::FGAIFlightPlan(FGAIModelEntity *entity,
useCurrentWayPoint = true; useCurrentWayPoint = true;
} }
try { if (path.exists())
readProperties(path.str(), &root); {
try
SGPropertyNode * node = root.getNode("flightplan"); {
readProperties(path.str(), &root);
//waypoints.push_back( init_waypoint );
for (int i = 0; i < node->nChildren(); i++) { SGPropertyNode * node = root.getNode("flightplan");
//cout << "Reading waypoint " << i << endl;
waypoint* wpt = new waypoint; //waypoints.push_back( init_waypoint );
SGPropertyNode * wpt_node = node->getChild(i); for (int i = 0; i < node->nChildren(); i++) {
wpt->name = wpt_node->getStringValue("name", "END"); //cout << "Reading waypoint " << i << endl;
wpt->latitude = wpt_node->getDoubleValue("lat", 0); waypoint* wpt = new waypoint;
wpt->longitude = wpt_node->getDoubleValue("lon", 0); SGPropertyNode * wpt_node = node->getChild(i);
wpt->altitude = wpt_node->getDoubleValue("alt", 0); wpt->name = wpt_node->getStringValue("name", "END");
wpt->speed = wpt_node->getDoubleValue("ktas", 0); wpt->latitude = wpt_node->getDoubleValue("lat", 0);
//wpt->speed = speed; wpt->longitude = wpt_node->getDoubleValue("lon", 0);
wpt->crossat = wpt_node->getDoubleValue("crossat", -10000); wpt->altitude = wpt_node->getDoubleValue("alt", 0);
wpt->gear_down = wpt_node->getBoolValue("gear-down", false); wpt->speed = wpt_node->getDoubleValue("ktas", 0);
wpt->flaps_down= wpt_node->getBoolValue("flaps-down", false); //wpt->speed = speed;
wpt->crossat = wpt_node->getDoubleValue("crossat", -10000);
if (wpt->name == "END") wpt->finished = true; wpt->gear_down = wpt_node->getBoolValue("gear-down", false);
else wpt->finished = false; wpt->flaps_down= wpt_node->getBoolValue("flaps-down", 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;
}
}
} }
} else
catch (const sg_exception &e) { {
//SG_LOG(SG_GENERAL, SG_ALERT, // cout << path.str() << endl;
// "Error reading AI flight plan: "); // cout << "Trying to create this plan dynamically" << endl;
// cout << path.str() << endl; // cout << "Route from " << dep->id << " to " << arr->id << endl;
// cout << "Trying to create this plan dynamically" << endl; time_t now = time(NULL) + fgGetLong("/sim/time/warp");
// cout << "Route from " << dep->id << " to " << arr->id << endl; time_t timeDiff = now-start;
create(dep,arr, entity->altitude, entity->speed); leg = 1;
// Now that we have dynamically created a flight plan, if ((timeDiff > 300) && (timeDiff < 1200))
// we need to add some code that pops any waypoints already past. leg = 2;
//return; else if ((timeDiff >= 1200) && (timeDiff < 1500))
} leg = 3;
waypoint* init_waypoint = new waypoint; else if ((timeDiff >= 1500) && (timeDiff < 2000))
init_waypoint->name = string("initial position"); leg = 4;
init_waypoint->latitude = entity->latitude; else if (timeDiff >= 2000)
init_waypoint->longitude = entity->longitude; leg = 5;
init_waypoint->altitude = entity->altitude;
init_waypoint->speed = entity->speed; //cerr << "Set leg to : " << leg << endl;
init_waypoint->crossat = - 10000; wpt_iterator = waypoints.begin();
init_waypoint->gear_down = false; create(dep,arr, leg, entity->altitude, entity->speed, entity->latitude, entity->longitude,
init_waypoint->flaps_down = false; firstLeg, radius, fltType, acType, airline);
init_waypoint->finished = false; wpt_iterator = waypoints.begin();
//cerr << "after create: " << (*wpt_iterator)->name << endl;
wpt_vector_iterator i = waypoints.begin(); //leg++;
while (i != waypoints.end()) // 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; //cerr << "Checking status of each waypoint: " << (*i)->name << endl;
SGWayPoint first(init_waypoint->longitude, SGWayPoint first(init_waypoint->longitude,
@ -229,11 +269,13 @@ FGAIFlightPlan::FGAIFlightPlan(FGAIModelEntity *entity,
//delete wpt; //delete wpt;
delete *(i); delete *(i);
i = waypoints.erase(i); i = waypoints.erase(i);
}
} }
} */
//for (i = waypoints.begin(); i != waypoints.end(); i++) //for (i = waypoints.begin(); i != waypoints.end(); i++)
// cerr << "Using waypoint : " << (*i)->name << endl; // cerr << "Using waypoint : " << (*i)->name << endl;
wpt_iterator = waypoints.begin(); //wpt_iterator = waypoints.begin();
//cout << waypoints.size() << " waypoints read." << endl; //cout << waypoints.size() << " waypoints read." << endl;
} }
@ -242,7 +284,13 @@ FGAIFlightPlan::FGAIFlightPlan(FGAIModelEntity *entity,
FGAIFlightPlan::~FGAIFlightPlan() 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::waypoint*
FGAIFlightPlan::getNextWaypoint( void ) 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; return 0;
} else { } else {
wpt_vector_iterator next = wpt_iterator; 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 // gives distance in feet from a position to a waypoint
double FGAIFlightPlan::getDistanceToGo(double lat, double lon, waypoint* wp){ 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 // 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_lat = 366468.96 - 3717.12 * cos(lat / SG_RADIANS_TO_DEGREES);
double ft_per_deg_lon = 365228.16 * 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 // sets distance in feet from a lead point to the current waypoint
void FGAIFlightPlan::setLeadDistance(double speed, double bearing, void FGAIFlightPlan::setLeadDistance(double speed, double bearing,
waypoint* current, waypoint* next){ 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 inbound = bearing;
double outbound = getBearing(current, next); double outbound = getBearing(current, next);
double diff = fabs(inbound - outbound); leadInAngle = fabs(inbound - outbound);
if (diff > 180.0) diff = 360.0 - diff; if (leadInAngle > 180.0)
lead_distance = turn_radius * sin(diff * SG_DEGREES_TO_RADIANS); 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){ 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; // if (!southerly && !easterly) return 270.0 + angle;
SGWayPoint sgWp(wp->longitude,wp->latitude, wp->altitude, SGWayPoint::WGS84, string("temp")); SGWayPoint sgWp(wp->longitude,wp->latitude, wp->altitude, SGWayPoint::WGS84, string("temp"));
sgWp.CourseAndDistance(lon, lat, wp->altitude, &course, &distance); sgWp.CourseAndDistance(lon, lat, wp->altitude, &course, &distance);
return course; return course;
// Omit a compiler warning. // 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::deleteWaypoints()
*/
void FGAIFlightPlan::create(FGAirport *dep, FGAirport *arr, double alt, double speed)
{ {
double wind_speed; for (wpt_vector_iterator i = waypoints.begin(); i != waypoints.end();i++)
double wind_heading; delete (*i);
FGRunway rwy; waypoints.clear();
double lat, lon, az; }
double lat2, lon2, az2;
int direction; // Delete all waypoints except the last,
// which we will recycle as the first waypoint in the next leg;
//waypoints.push_back(wpt); void FGAIFlightPlan::resetWaypoints()
// Create the outbound taxi leg, for now simplified as a {
// Direct route from the airport center point to the start if (waypoints.begin() == waypoints.end())
// of the runway. return;
/////////////////////////////////////////////////////////// else
//cerr << "Cruise Alt << " << alt << endl; {
// Temporary code to add some small random variation to aircraft parking positions; waypoint *wpt = new waypoint;
direction = (rand() % 360); wpt_vector_iterator i = waypoints.end();
geo_direct_wgs_84 ( 0, dep->_latitude, dep->_longitude, direction, i--;
100, wpt->name = (*i)->name;
&lat2, &lon2, &az2 ); wpt->latitude = (*i)->latitude;
waypoint *wpt = new waypoint; wpt->longitude = (*i)->longitude;
wpt->name = dep->_id; //wpt_node->getStringValue("name", "END"); wpt->altitude = (*i)->altitude;
wpt->latitude = lat2; wpt->speed = (*i)->speed;
wpt->longitude = lon2; wpt->crossat = (*i)->crossat;
wpt->altitude = dep->_elevation + 19; // probably need to add some model height to it wpt->gear_down = (*i)->gear_down;
wpt->speed = 15; wpt->flaps_down= (*i)->flaps_down;
wpt->crossat = -10000; wpt->finished = false;
wpt->gear_down = true; wpt->on_ground = (*i)->on_ground;
wpt->flaps_down= true; //cerr << "Recycling waypoint " << wpt->name << endl;
wpt->finished = false; deleteWaypoints();
wpt->on_ground = true; waypoints.push_back(wpt);
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);
} }

View file

@ -24,6 +24,7 @@
#include <string> #include <string>
#include <Airports/simple.hxx> #include <Airports/simple.hxx>
#include <Airports/runways.hxx>
#include "AIBase.hxx" #include "AIBase.hxx"
@ -53,15 +54,21 @@ public:
double course, double course,
time_t start, time_t start,
FGAirport *dep, FGAirport *dep,
FGAirport *arr); FGAirport *arr,
bool firstLeg,
double radius,
string fltType,
string acType,
string airline);
~FGAIFlightPlan(); ~FGAIFlightPlan();
waypoint* getPreviousWaypoint( void ); waypoint* getPreviousWaypoint( void );
waypoint* getCurrentWaypoint( void ); waypoint* getCurrentWaypoint( void );
waypoint* getNextWaypoint( void ); waypoint* getNextWaypoint( void );
void IncrementWaypoint( void ); void IncrementWaypoint( bool erase );
double getDistanceToGo(double lat, double lon, waypoint* wp); 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 speed, double bearing, waypoint* current, waypoint* next);
void setLeadDistance(double distance_ft); void setLeadDistance(double distance_ft);
double getLeadDistance( void ) const {return lead_distance;} double getLeadDistance( void ) const {return lead_distance;}
@ -69,10 +76,17 @@ public:
double getBearing(double lat, double lon, waypoint* next); double getBearing(double lat, double lon, waypoint* next);
time_t getStartTime() { return start_time; }; 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: private:
FGRunway rwy;
typedef vector <waypoint*> wpt_vector_type; typedef vector <waypoint*> wpt_vector_type;
typedef wpt_vector_type::iterator wpt_vector_iterator; typedef wpt_vector_type::iterator wpt_vector_iterator;
@ -81,8 +95,21 @@ private:
double distance_to_go; double distance_to_go;
double lead_distance; double lead_distance;
double leadInAngle;
time_t start_time; 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 { } else {
ai_plane->SetPerformance(&FGAIAircraft::settings[FGAIAircraft::JET_TRANSPORT]); 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->setHeading(entity->heading);
ai_plane->setSpeed(entity->speed); ai_plane->setSpeed(entity->speed);
ai_plane->setPath(entity->path.c_str()); ai_plane->setPath(entity->path.c_str());

View file

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

View file

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

View file

@ -460,7 +460,7 @@ void FGATCDialog::FreqDisplay(string ident) {
FGAirport a; FGAirport a;
if ( dclFindAirportID( ident, &a ) ) { if ( dclFindAirportID( ident, &a ) ) {
comm_list_type stations; 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) { if(found) {
ostringstream ostr; ostringstream ostr;
comm_list_iterator itr = stations.begin(); comm_list_iterator itr = stations.begin();

View file

@ -221,9 +221,9 @@ bool FGATCMgr::AIRegisterAirport(string ident) {
//cout << "ident = " << ident << '\n'; //cout << "ident = " << ident << '\n';
AirportATC *a = new AirportATC; 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! // 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->lon = ap.getLongitude();
a->lat = ap._latitude; a->lat = ap.getLatitude();
a->elev = ap._elevation; a->elev = ap.getElevation();
a->atis_freq = GetFrequency(ident, ATIS); a->atis_freq = GetFrequency(ident, ATIS);
//cout << "ATIS freq = " << a->atis_freq << '\n'; //cout << "ATIS freq = " << a->atis_freq << '\n';
a->atis_active = false; a->atis_active = false;
@ -270,9 +270,9 @@ bool FGATCMgr::CommRegisterAirport(string ident, int chan, atc_type tp) {
if(dclFindAirportID(ident, &ap)) { if(dclFindAirportID(ident, &ap)) {
AirportATC *a = new AirportATC; 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! // 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->lon = ap.getLongitude();
a->lat = ap._latitude; a->lat = ap.getLatitude();
a->elev = ap._elevation; a->elev = ap.getElevation();
a->atis_freq = GetFrequency(ident, ATIS); a->atis_freq = GetFrequency(ident, ATIS);
a->atis_active = false; a->atis_active = false;
a->tower_freq = GetFrequency(ident, TOWER); 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 ); SG_LOG( SG_GENERAL, SG_INFO, "Searching for airport code = " << id );
result = globals->get_airports()->search( id ); result = globals->get_airports()->search( id );
if ( result._id.empty() ) { if ( result.getId().empty() ) {
SG_LOG( SG_GENERAL, SG_WARN, SG_LOG( SG_GENERAL, SG_WARN,
"Failed to find " << id << " in basic.dat.gz" ); "Failed to find " << id << " in basic.dat.gz" );
return false; return false;
@ -327,8 +327,8 @@ bool dclFindAirportID( const string& id, FGAirport *a ) {
SG_LOG( SG_GENERAL, SG_INFO, SG_LOG( SG_GENERAL, SG_INFO,
"Position for " << id << " is (" "Position for " << id << " is ("
<< a->_longitude << ", " << a->getLongitude() << ", "
<< a->_latitude << ")" ); << a->getLatitude() << ")" );
return true; return true;
} }
@ -342,7 +342,7 @@ double dclGetAirportElev( const string& id ) {
"Finding elevation for airport: " << id ); "Finding elevation for airport: " << id );
if ( dclFindAirportID( id, &a ) ) { if ( dclFindAirportID( id, &a ) ) {
return a._elevation * SG_FEET_TO_METER; return a.getElevation() * SG_FEET_TO_METER;
} else { } else {
return -9999.0; return -9999.0;
} }
@ -357,7 +357,7 @@ Point3D dclGetAirportPos( const string& id ) {
"Finding position for airport: " << id ); "Finding position for airport: " << id );
if ( dclFindAirportID( id, &a ) ) { if ( dclFindAirportID( id, &a ) ) {
return Point3D(a._longitude, a._latitude, a._elevation); return Point3D(a.getLongitude(), a.getLatitude(), a.getElevation());
} else { } else {
return Point3D(0.0, 0.0, -9999.0); 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; FGAirport a;
if ( dclFindAirportID( ICAO, &a ) ) { if ( dclFindAirportID( ICAO, &a ) ) {
comm_list_type stations; 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) { if(found) {
comm_list_iterator itr = stations.begin(); comm_list_iterator itr = stations.begin();
while(itr != stations.end()) { while(itr != stations.end()) {

View file

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

File diff suppressed because it is too large Load diff

View file

@ -3,6 +3,7 @@
// elevation in feet. // elevation in feet.
// //
// Written by Curtis Olson, started April 1998. // 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 // Copyright (C) 1998 Curtis L. Olson - http://www.flightgear.org/~curt
// //
@ -37,6 +38,7 @@
#endif #endif
#include <simgear/compiler.h> #include <simgear/compiler.h>
#include <simgear/xml/easyxml.hxx>
#include STL_STRING #include STL_STRING
#include <map> #include <map>
@ -46,17 +48,249 @@ SG_USING_STD(string);
SG_USING_STD(map); SG_USING_STD(map);
SG_USING_STD(vector); SG_USING_STD(vector);
typedef vector<string> stringVec;
typedef vector<string>::iterator stringVecIterator;
typedef vector<string>::const_iterator stringVecConstIterator;
struct FGAirport { typedef vector<time_t> timeVec;
string _id; typedef vector<time_t>::const_iterator timeVecConstIterator;
double _longitude; /***************************************************************************/
double _latitude; class ScheduleTime {
double _elevation; private:
string _code; // depricated and can be removed timeVec start;
string _name; timeVec end;
bool _has_metar; 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; typedef map < string, FGAirport > airport_map;
@ -97,6 +331,8 @@ public:
// return station id's marked as having metar data. // return station id's marked as having metar data.
FGAirport search( double lon_deg, double lat_deg, bool with_metar ); 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. * 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() ); sprintf( NewTgtAirportId, "%s", TgtAptId.c_str() );
SGWayPoint wp( a._longitude, a._latitude, alt, SGWayPoint wp( a.getLongitude(), a.getLatitude(), alt,
SGWayPoint::WGS84, TgtAptId ); SGWayPoint::WGS84, TgtAptId );
rm->add_waypoint( wp ); rm->add_waypoint( wp );

View file

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

View file

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

View file

@ -22,4 +22,4 @@ layout_test_SOURCES = layout-test.cxx
layout_test_LDADD = libGUI.a \ layout_test_LDADD = libGUI.a \
-lsgprops -lsgdebug -lsgstructure -lsgmisc -lsgxml \ -lsgprops -lsgdebug -lsgstructure -lsgmisc -lsgxml \
-lplibpw -lplibpu -lplibfnt -lplibul $(opengl_LIBS) -lplibpw -lplibpu -lplibfnt -lplibul $(opengl_LIBS)

View file

@ -325,12 +325,12 @@ GPS::update (double delta_time_sec)
FGAirport a; FGAirport a;
//cout << "Airport found" << endl; //cout << "Airport found" << endl;
a = globals->get_airports()->search(longitude_deg, latitude_deg, false); a = globals->get_airports()->search(longitude_deg, latitude_deg, false);
_wp1_ID_node->setStringValue(a._id.c_str()); _wp1_ID_node->setStringValue(a.getId().c_str());
wp1_longitude_deg = a._longitude; wp1_longitude_deg = a.getLongitude();
wp1_latitude_deg = a._latitude; wp1_latitude_deg = a.getLatitude();
_wp1_name_node->setStringValue(a._name.c_str()); _wp1_name_node->setStringValue(a.getName().c_str());
_get_nearest_airport_node->setBoolValue(false); _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 // 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") { if (waypont_type == "airport") {
FGAirport a; FGAirport a;
a = globals->get_airports()->search( wp0_ID ); a = globals->get_airports()->search( wp0_ID );
if ( a._id == wp0_ID ) { if ( a.getId() == wp0_ID ) {
//cout << "Airport found" << endl; //cout << "Airport found" << endl;
wp0_longitude_deg = a._longitude; wp0_longitude_deg = a.getLongitude();
wp0_latitude_deg = a._latitude; wp0_latitude_deg = a.getLatitude();
_wp0_name_node->setStringValue(a._name.c_str()); _wp0_name_node->setStringValue(a.getName().c_str());
} }
} }
else if (waypont_type == "nav") { else if (waypont_type == "nav") {
@ -380,11 +380,11 @@ GPS::update (double delta_time_sec)
if (waypont_type == "airport") { if (waypont_type == "airport") {
FGAirport a; FGAirport a;
a = globals->get_airports()->search( wp1_ID ); a = globals->get_airports()->search( wp1_ID );
if ( a._id == wp1_ID ) { if ( a.getId() == wp1_ID ) {
//cout << "Airport found" << endl; //cout << "Airport found" << endl;
wp1_longitude_deg = a._longitude; wp1_longitude_deg = a.getLongitude();
wp1_latitude_deg = a._latitude; wp1_latitude_deg = a.getLatitude();
_wp1_name_node->setStringValue(a._name.c_str()); _wp1_name_node->setStringValue(a.getName().c_str());
} }
} }
else if (waypont_type == "nav") { else if (waypont_type == "nav") {

View file

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

View file

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

View file

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

View file

@ -65,11 +65,23 @@ FGAISchedule::FGAISchedule(string mdl,
string liv, string liv,
string reg, string reg,
bool hvy, bool hvy,
string act,
string arln,
string mclass,
string fltpe,
double rad,
double grnd,
FGScheduledFlightVec flt) FGScheduledFlightVec flt)
{ {
modelPath = mdl; modelPath = mdl;
livery = liv; livery = liv;
registration = reg; registration = reg;
acType = act;
airline = arln;
m_class = mclass;
flightType = fltpe;
radius = rad;
groundOffset = grnd;
heavy = hvy; heavy = hvy;
for (FGScheduledFlightVecIterator i = flt.begin(); for (FGScheduledFlightVecIterator i = flt.begin();
i != flt.end(); i != flt.end();
@ -89,15 +101,49 @@ FGAISchedule::FGAISchedule(const FGAISchedule &other)
lat = other.lat; lat = other.lat;
lon = other.lon; lon = other.lon;
AIManagerRef = other.AIManagerRef; AIManagerRef = other.AIManagerRef;
acType = other.acType;
airline = other.airline;
m_class = other.m_class;
firstRun = other.firstRun; firstRun = other.firstRun;
radius = other.radius;
groundOffset = other.groundOffset;
flightType = other.flightType;
distanceToUser = other.distanceToUser;
} }
FGAISchedule::~FGAISchedule() 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 *dep;
FGAirport *arr; FGAirport *arr;
@ -110,7 +156,7 @@ void FGAISchedule::update(time_t now)
string airport; string airport;
double courseToUser, courseToDest; double courseToUser, courseToDest;
double distanceToUser, distanceToDest; double distanceToDest;
double speed; double speed;
Point3D temp; Point3D temp;
@ -123,7 +169,7 @@ void FGAISchedule::update(time_t now)
userLongitude; userLongitude;
if (fgGetBool("/sim/traffic-manager/enabled") == false) if (fgGetBool("/sim/traffic-manager/enabled") == false)
return; return true;
aimgr = (FGAIManager *) globals-> get_subsystem("ai_model"); aimgr = (FGAIManager *) globals-> get_subsystem("ai_model");
// Before the flight status of this traffic entity is updated // Before the flight status of this traffic entity is updated
@ -142,11 +188,11 @@ void FGAISchedule::update(time_t now)
if (firstRun) if (firstRun)
{ {
for (FGScheduledFlightVecIterator i = flights.begin(); for (FGScheduledFlightVecIterator i = flights.begin();
i != flights.end(); i != flights.end();
i++) i++)
{ {
i->adjustTime(now); i->adjustTime(now);
} }
firstRun = false; firstRun = false;
} }
@ -168,13 +214,13 @@ void FGAISchedule::update(time_t now)
userLatitude = fgGetDouble("/position/latitude-deg"); userLatitude = fgGetDouble("/position/latitude-deg");
userLongitude = fgGetDouble("/position/longitude-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 // This flight entry is entirely in the past, do we need to
// push it forward in time to the next scheduled departure. // push it forward in time to the next scheduled departure.
if ((i->getDepartureTime() < now) && (i->getArrivalTime() < now)) if ((i->getDepartureTime() < now) && (i->getArrivalTime() < now))
{ {
i->update(); i->update();
return; return true;
} }
// Departure time in the past and arrival time in the future. // Departure time in the past and arrival time in the future.
@ -189,19 +235,21 @@ void FGAISchedule::update(time_t now)
{ {
dep = i->getDepartureAirport(); dep = i->getDepartureAirport();
arr = i->getArrivalAirport (); arr = i->getArrivalAirport ();
if (!(dep && arr))
return false;
temp = sgPolarToCart3d(Point3D(dep->_longitude * temp = sgPolarToCart3d(Point3D(dep->getLongitude() *
SG_DEGREES_TO_RADIANS, SG_DEGREES_TO_RADIANS,
dep->_latitude * dep->getLatitude() *
SG_DEGREES_TO_RADIANS, SG_DEGREES_TO_RADIANS,
1.0)); 1.0));
a[0] = temp.x(); a[0] = temp.x();
a[1] = temp.y(); a[1] = temp.y();
a[2] = temp.z(); a[2] = temp.z();
temp = sgPolarToCart3d(Point3D(arr->_longitude * temp = sgPolarToCart3d(Point3D(arr->getLongitude() *
SG_DEGREES_TO_RADIANS, SG_DEGREES_TO_RADIANS,
arr->_latitude * arr->getLatitude() *
SG_DEGREES_TO_RADIANS, SG_DEGREES_TO_RADIANS,
1.0)); 1.0));
b[0] = temp.x(); b[0] = temp.x();
@ -219,9 +267,21 @@ void FGAISchedule::update(time_t now)
// total time enroute and elapsed time enroute. // total time enroute and elapsed time enroute.
totalTimeEnroute = i->getArrivalTime() - i->getDepartureTime(); totalTimeEnroute = i->getArrivalTime() - i->getDepartureTime();
elapsedTimeEnroute = now - i->getDepartureTime(); if (now > i->getDepartureTime())
remainingTimeEnroute = i->getArrivalTime() - now; {
//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); angle *= ( (double) elapsedTimeEnroute/ (double) totalTimeEnroute);
@ -236,32 +296,30 @@ void FGAISchedule::update(time_t now)
newPos[j] += matrix[j][k]*a[k]; newPos[j] += matrix[j][k]*a[k];
} }
} }
temp = sgCartToPolar3d(Point3D(newPos[0], newPos[1],newPos[2])); temp = sgCartToPolar3d(Point3D(newPos[0], newPos[1],newPos[2]));
if (now > i->getDepartureTime()) if (now > i->getDepartureTime())
{ {
//cerr << "Lat = " << lat << ", lon = " << lon << endl; //cerr << "Lat = " << lat << ", lon = " << lon << endl;
//cerr << "Time diff: " << now-i->getDepartureTime() << endl; //cerr << "Time diff: " << now-i->getDepartureTime() << endl;
lat = temp.lat() * SG_RADIANS_TO_DEGREES; lat = temp.lat() * SG_RADIANS_TO_DEGREES;
lon = temp.lon() * 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 else
{ {
lat = dep->_latitude; lat = dep->getLatitude();
lon = dep->_longitude; lon = dep->getLongitude();
} }
SGWayPoint current (lon, SGWayPoint current (lon,
lat, lat,
i->getCruiseAlt()); i->getCruiseAlt());
SGWayPoint user ( userLongitude, SGWayPoint user ( userLongitude,
userLatitude, userLatitude,
i->getCruiseAlt()); i->getCruiseAlt());
SGWayPoint dest ( arr->_longitude, SGWayPoint dest ( arr->getLongitude(),
arr->_latitude, arr->getLatitude(),
i->getCruiseAlt()); i->getCruiseAlt());
// We really only need distance to user // We really only need distance to user
// and course to destination // and course to destination
@ -278,9 +336,9 @@ void FGAISchedule::update(time_t now)
//cerr << registration << " is currently enroute from " //cerr << registration << " is currently enroute from "
// << dep->_id << " to " << arr->_id << "distance : " // << dep->_id << " to " << arr->_id << "distance : "
// << distanceToUser*SG_METER_TO_NM << endl; // << 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"); string(".xml");
int alt; int alt;
//if ((i->getDepartureTime() < now)) //if ((i->getDepartureTime() < now))
@ -294,32 +352,43 @@ void FGAISchedule::update(time_t now)
FGAIModelEntity entity; 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.path = modelPath.c_str();
entity.flightplan = flightPlanName.c_str(); entity.flightplan = flightPlanName.c_str();
entity.latitude = lat; entity.latitude = lat;
entity.longitude = lon; entity.longitude = lon;
entity.altitude = i->getCruiseAlt() *100; // convert from FL to feet entity.altitude = i->getCruiseAlt() *100; // convert from FL to feet
entity.speed = 450; entity.speed = speed;
entity.fp = new FGAIFlightPlan(&entity, courseToDest, i->getDepartureTime(), dep, arr); 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 // Fixme: A non-existent model path results in an
// abort, due to an unhandled exeption, in fg main loop. // abort, due to an unhandled exeption, in fg main loop.
AIManagerRef = aimgr->createAircraft( &entity, this); 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 // Both departure and arrival time are in the future, so this
// the aircraft is parked at the departure airport. // the aircraft is parked at the departure airport.
// Currently this status is mostly ignored, but in future // Currently this status is mostly ignored, but in future
// versions, code should go here that -if within user range- // versions, code should go here that -if within user range-
// positions these aircraft at parking locations at the airport. // 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(); dep = i->getDepartureAirport();
return; return true;
} }
} }
} }
@ -331,3 +400,71 @@ void FGAISchedule::next()
sort(flights.begin(), flights.end()); 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_ #ifndef _FGSCHEDULE_HXX_
#define _FGSCHEDULE_HXX_ #define _FGSCHEDULE_HXX_
#define TRAFFICTOAIDIST 150.0
class FGAISchedule class FGAISchedule
@ -37,34 +38,56 @@ class FGAISchedule
string modelPath; string modelPath;
string livery; string livery;
string registration; string registration;
string airline;
string acType;
string m_class;
string flightType;
bool heavy; bool heavy;
FGScheduledFlightVec flights; FGScheduledFlightVec flights;
float lat; float lat;
float lon; float lon;
double radius;
double groundOffset;
double distanceToUser;
void* AIManagerRef; void* AIManagerRef;
bool firstRun; bool firstRun;
public: public:
FGAISchedule(); // constructor 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(const FGAISchedule &other); // copy constructor
~FGAISchedule(); //destructor ~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. void next(); // forces the schedule to move on to the next flight.
time_t getDepartureTime () { return flights.begin()->getDepartureTime (); }; time_t getDepartureTime () { return flights.begin()->getDepartureTime (); };
FGAirport * getDepartureAirport () { return flights.begin()->getDepartureAirport(); }; FGAirport * getDepartureAirport () { return flights.begin()->getDepartureAirport(); };
FGAirport * getArrivalAirport () { return flights.begin()->getArrivalAirport (); }; FGAirport * getArrivalAirport () { return flights.begin()->getArrivalAirport (); };
int getCruiseAlt () { return flights.begin()->getCruiseAlt (); }; 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 // More member functions follow later
}; };
typedef vector<FGAISchedule> ScheduleVector; typedef vector<FGAISchedule > ScheduleVector;
typedef vector<FGAISchedule>::iterator ScheduleVectorIterator; typedef vector<FGAISchedule >::iterator ScheduleVectorIterator;
#endif #endif

View file

@ -53,6 +53,7 @@
#include <simgear/structure/subsystem_mgr.hxx> #include <simgear/structure/subsystem_mgr.hxx>
#include <simgear/xml/easyxml.hxx> #include <simgear/xml/easyxml.hxx>
#include <AIModel/AIAircraft.hxx>
#include <AIModel/AIFlightPlan.hxx> #include <AIModel/AIFlightPlan.hxx>
#include <AIModel/AIBase.hxx> #include <AIModel/AIBase.hxx>
#include <Airports/simple.hxx> #include <Airports/simple.hxx>
@ -72,22 +73,45 @@ FGTrafficManager::FGTrafficManager()
void FGTrafficManager::init() void FGTrafficManager::init()
{ {
//cerr << "Initializing Schedules" << endl;
time_t now = time(NULL) + fgGetLong("/sim/time/warp");
currAircraft = scheduledAircraft.begin(); 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) 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"); 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 = 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) void FGTrafficManager::release(void *id)
@ -146,6 +170,18 @@ void FGTrafficManager::endElement (const char * name) {
livery = value; livery = value;
else if (element == string("registration")) else if (element == string("registration"))
registration = value; 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")) else if (element == string("heavy"))
{ {
if(value == string("true")) if(value == string("true"))
@ -195,10 +231,16 @@ void FGTrafficManager::endElement (const char * name) {
{ {
//cerr << "Pushing back aircraft " << registration << endl; //cerr << "Pushing back aircraft " << registration << endl;
scheduledAircraft.push_back(FGAISchedule(mdl, scheduledAircraft.push_back(FGAISchedule(mdl,
livery, livery,
registration, registration,
heavy, heavy,
flights)); acType,
airline,
m_class,
flighttype,
radius,
offset,
flights));
while(flights.begin() != flights.end()) while(flights.begin() != flights.end())
flights.pop_back(); flights.pop_back();
} }

View file

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