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:
parent
03f0ac8519
commit
5bc15d7a69
29 changed files with 3436 additions and 623 deletions
|
@ -23,9 +23,13 @@
|
|||
#endif
|
||||
|
||||
#include <simgear/math/point3d.hxx>
|
||||
#include <simgear/route/waypoint.hxx>
|
||||
#include <Main/fg_props.hxx>
|
||||
#include <Main/globals.hxx>
|
||||
#include <Main/viewer.hxx>
|
||||
#include <Scenery/scenery.hxx>
|
||||
#include <Scenery/tilemgr.hxx>
|
||||
|
||||
#include <string>
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
|
@ -33,7 +37,7 @@
|
|||
SG_USING_STD(string);
|
||||
|
||||
#include "AIAircraft.hxx"
|
||||
|
||||
static string tempReg;
|
||||
//
|
||||
// accel, decel, climb_rate, descent_rate, takeoff_speed, climb_speed,
|
||||
// cruise_speed, descent_speed, land_speed
|
||||
|
@ -54,17 +58,24 @@ const FGAIAircraft::PERF_STRUCT FGAIAircraft::settings[] = {
|
|||
|
||||
FGAIAircraft::FGAIAircraft(FGAIManager* mgr, FGAISchedule *ref) {
|
||||
trafficRef = ref;
|
||||
if (trafficRef)
|
||||
groundOffset = trafficRef->getGroundOffset();
|
||||
else
|
||||
groundOffset = 0;
|
||||
manager = mgr;
|
||||
_type_str = "aircraft";
|
||||
_otype = otAircraft;
|
||||
fp = 0;
|
||||
dt_count = 0;
|
||||
dt_elev_count = 0;
|
||||
use_perf_vs = true;
|
||||
isTanker = false;
|
||||
|
||||
// set heading and altitude locks
|
||||
hdg_lock = false;
|
||||
alt_lock = false;
|
||||
roll = 0;
|
||||
headingChangeRate = 0.0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -118,13 +129,24 @@ void FGAIAircraft::Run(double dt) {
|
|||
|
||||
if (fp)
|
||||
{
|
||||
ProcessFlightPlan(dt);
|
||||
time_t now = time(NULL) + fgGetLong("/sim/time/warp");
|
||||
ProcessFlightPlan(dt, now);
|
||||
if (now < fp->getStartTime())
|
||||
return;
|
||||
//ProcessFlightPlan(dt);
|
||||
{
|
||||
// Do execute Ground elev for inactive aircraft, so they
|
||||
// Are repositioned to the correct ground altitude when the user flies within visibility range.
|
||||
if (no_roll)
|
||||
{
|
||||
Transform(); // make sure aip is initialized.
|
||||
getGroundElev(dt); // make sure it's exectuted first time around, so force a large dt value
|
||||
//getGroundElev(dt); // Need to do this twice.
|
||||
//cerr << trafficRef->getRegistration() << " Setting altitude to " << tgt_altitude << endl;
|
||||
setAltitude(tgt_altitude);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
double turn_radius_ft;
|
||||
double turn_circum_ft;
|
||||
double speed_north_deg_sec;
|
||||
|
@ -133,11 +155,19 @@ void FGAIAircraft::Run(double dt) {
|
|||
double alpha;
|
||||
|
||||
// adjust speed
|
||||
double speed_diff = tgt_speed - speed;
|
||||
double speed_diff; //= tgt_speed - speed;
|
||||
if (!no_roll)
|
||||
{
|
||||
speed_diff = tgt_speed - speed;
|
||||
}
|
||||
else
|
||||
{
|
||||
speed_diff = groundTargetSpeed - speed;
|
||||
}
|
||||
if (fabs(speed_diff) > 0.2) {
|
||||
if (speed_diff > 0.0) speed += performance->accel * dt;
|
||||
if (speed_diff < 0.0) {
|
||||
if (!no_roll) {
|
||||
if (no_roll) { // was (!no_roll) but seems more logical this way (ground brakes).
|
||||
speed -= performance->decel * dt * 3;
|
||||
} else {
|
||||
speed -= performance->decel * dt;
|
||||
|
@ -154,19 +184,98 @@ void FGAIAircraft::Run(double dt) {
|
|||
// set new position
|
||||
pos.setlat( pos.lat() + speed_north_deg_sec * dt);
|
||||
pos.setlon( pos.lon() + speed_east_deg_sec * dt);
|
||||
//if (!(finite(pos.lat()) && finite(pos.lon())))
|
||||
// {
|
||||
// cerr << "Position is not finite" << endl;
|
||||
// cerr << "speed = " << speed << endl;
|
||||
// cerr << "dt" << dt << endl;
|
||||
// cerr << "heading " << hdg << endl;
|
||||
// cerr << "speed east " << speed_east_deg_sec << endl;
|
||||
// cerr << "speed nrth " << speed_north_deg_sec << endl;
|
||||
// cerr << "deg_lat " << ft_per_deg_lat << endl;
|
||||
// cerr << "deg_lon " << ft_per_deg_lon << endl;
|
||||
// }
|
||||
|
||||
// adjust heading based on current bank angle
|
||||
if (roll == 0.0)
|
||||
roll = 0.01;
|
||||
if (roll != 0.0) {
|
||||
turn_radius_ft = 0.088362 * speed * speed
|
||||
/ tan( fabs(roll) / SG_RADIANS_TO_DEGREES );
|
||||
turn_circum_ft = SGD_2PI * turn_radius_ft;
|
||||
dist_covered_ft = speed * 1.686 * dt;
|
||||
alpha = dist_covered_ft / turn_circum_ft * 360.0;
|
||||
hdg += alpha * sign( roll );
|
||||
if ( hdg > 360.0 ) hdg -= 360.0;
|
||||
if ( hdg < 0.0) hdg += 360.0;
|
||||
// double turnConstant;
|
||||
//if (no_roll)
|
||||
// turnConstant = 0.0088362;
|
||||
//else
|
||||
// turnConstant = 0.088362;
|
||||
// If on ground, calculate heading change directly
|
||||
if (no_roll) {
|
||||
double headingDiff = fabs(hdg-tgt_heading);
|
||||
|
||||
if (headingDiff > 180)
|
||||
headingDiff = fabs(headingDiff - 360);
|
||||
groundTargetSpeed = tgt_speed - (tgt_speed * (headingDiff/45));
|
||||
if (sign(groundTargetSpeed) != sign(tgt_speed))
|
||||
groundTargetSpeed = 0.21 * sign(tgt_speed); // to prevent speed getting stuck in 'negative' mode
|
||||
if (headingDiff > 30.0)
|
||||
{
|
||||
|
||||
headingChangeRate += dt * sign(roll); // invert if pushed backward
|
||||
// Print some debug statements to find out why aircraft may get stuck
|
||||
// forever turning
|
||||
//if (trafficRef->getDepartureAirport()->getId() == string("EHAM"))
|
||||
// {
|
||||
//cerr << "Turning : " << trafficRef->getRegistration()
|
||||
//cerr << " Speed = " << speed << " Heading " << hdg
|
||||
//<< " Target Heading " << tgt_heading
|
||||
// << " Lead Distance " << fp->getLeadDistance()
|
||||
// << " Distance to go "
|
||||
// << fp->getDistanceToGo(pos.lat(), pos.lon(), fp->getCurrentWaypoint())
|
||||
// << "waypoint name " << fp->getCurrentWaypoint()->name
|
||||
// << endl;
|
||||
//}
|
||||
if (headingChangeRate > 30)
|
||||
{
|
||||
headingChangeRate = 30;
|
||||
}
|
||||
else if (headingChangeRate < -30)
|
||||
{
|
||||
headingChangeRate = -30;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fabs(headingChangeRate) > headingDiff)
|
||||
headingChangeRate = headingDiff*sign(roll);
|
||||
else
|
||||
headingChangeRate += dt * sign(roll);
|
||||
}
|
||||
hdg += headingChangeRate * dt;
|
||||
//cerr << "On ground. Heading: " << hdg << ". Target Heading: " << tgt_heading << ". Target speed: " << groundTargetSpeed << ". heading change rate" << headingChangeRate << endl;
|
||||
}
|
||||
else {
|
||||
if (fabs(speed) > 1.0) {
|
||||
turn_radius_ft = 0.088362 * speed * speed
|
||||
/ tan( fabs(roll) / SG_RADIANS_TO_DEGREES );
|
||||
}
|
||||
else
|
||||
{
|
||||
turn_radius_ft = 1.0; // Check if turn_radius_ft == 0; this might lead to a division by 0.
|
||||
}
|
||||
turn_circum_ft = SGD_2PI * turn_radius_ft;
|
||||
dist_covered_ft = speed * 1.686 * dt;
|
||||
alpha = dist_covered_ft / turn_circum_ft * 360.0;
|
||||
hdg += alpha * sign(roll);
|
||||
}
|
||||
while ( hdg > 360.0 ) {
|
||||
hdg -= 360.0;
|
||||
spinCounter++;
|
||||
}
|
||||
while ( hdg < 0.0)
|
||||
{
|
||||
hdg += 360.0;
|
||||
spinCounter--;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// adjust target bank angle if heading lock engaged
|
||||
if (hdg_lock) {
|
||||
double bank_sense = 0.0;
|
||||
|
@ -174,7 +283,7 @@ void FGAIAircraft::Run(double dt) {
|
|||
if (diff > 180) diff = fabs(diff - 360);
|
||||
double sum = hdg + diff;
|
||||
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
|
||||
} else {
|
||||
bank_sense = -1.0; // left turn
|
||||
|
@ -184,6 +293,27 @@ void FGAIAircraft::Run(double dt) {
|
|||
} else {
|
||||
tgt_roll = 30.0 * bank_sense;
|
||||
}
|
||||
if ((fabs((double) spinCounter) > 1) && (diff > 30))
|
||||
{
|
||||
tgt_speed *= 0.999; // Ugly hack: If aircraft get stuck, they will continually spin around.
|
||||
// The only way to resolve this is to make them slow down.
|
||||
//if (tempReg.empty())
|
||||
// tempReg = trafficRef->getRegistration();
|
||||
//if (trafficRef->getRegistration() == tempReg)
|
||||
// {
|
||||
// cerr << trafficRef->getRegistration()
|
||||
// << " appears to be spinning: " << spinCounter << endl
|
||||
// << " speed " << speed << endl
|
||||
// << " heading " << hdg << endl
|
||||
// << " lead distance " << fp->getLeadDistance() << endl
|
||||
// << " waypoint " << fp->getCurrentWaypoint()->name
|
||||
// << " target heading " << tgt_heading << endl
|
||||
// << " lead in angle " << fp->getLeadInAngle()<< endl
|
||||
// << " roll " << roll << endl
|
||||
// << " target_roll " << tgt_roll << endl;
|
||||
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
// adjust bank angle, use 9 degrees per second
|
||||
|
@ -191,6 +321,8 @@ void FGAIAircraft::Run(double dt) {
|
|||
if (fabs(bank_diff) > 0.2) {
|
||||
if (bank_diff > 0.0) roll += 9.0 * dt;
|
||||
if (bank_diff < 0.0) roll -= 9.0 * dt;
|
||||
//while (roll > 180) roll -= 360;
|
||||
//while (roll < 180) roll += 360;
|
||||
}
|
||||
|
||||
// adjust altitude (meters) based on current vertical speed (fpm)
|
||||
|
@ -198,6 +330,11 @@ void FGAIAircraft::Run(double dt) {
|
|||
pos.setelev(altitude * SG_FEET_TO_METER);
|
||||
double altitude_ft = altitude;
|
||||
|
||||
// adjust target Altitude, based on ground elevation when on ground
|
||||
if (no_roll)
|
||||
{
|
||||
getGroundElev(dt);
|
||||
}
|
||||
// find target vertical speed if altitude lock engaged
|
||||
if (alt_lock && use_perf_vs) {
|
||||
if (altitude_ft < tgt_altitude) {
|
||||
|
@ -303,9 +440,28 @@ void FGAIAircraft::SetFlightPlan(FGAIFlightPlan *f) {
|
|||
fp = f;
|
||||
}
|
||||
|
||||
void FGAIAircraft::ProcessFlightPlan( double dt ) {
|
||||
|
||||
void FGAIAircraft::ProcessFlightPlan( double dt, time_t now )
|
||||
{
|
||||
bool eraseWaypoints;
|
||||
if (trafficRef)
|
||||
{
|
||||
// FGAirport *arr;
|
||||
// FGAirport *dep;
|
||||
eraseWaypoints = true;
|
||||
// cerr << trafficRef->getRegistration();
|
||||
// cerr << "Departure airport " << endl;
|
||||
// dep = trafficRef->getDepartureAirport();
|
||||
// if (dep)
|
||||
// cerr << dep->getId() << endl;
|
||||
// cerr << "Arrival airport " << endl;
|
||||
// arr = trafficRef->getArrivalAirport();
|
||||
// if (arr)
|
||||
// cerr << arr->getId() <<endl << endl;;
|
||||
}
|
||||
else
|
||||
eraseWaypoints = false;
|
||||
|
||||
//cerr << "Processing Flightplan" << endl;
|
||||
FGAIFlightPlan::waypoint* prev = 0; // the one behind you
|
||||
FGAIFlightPlan::waypoint* curr = 0; // the one ahead
|
||||
FGAIFlightPlan::waypoint* next = 0; // the next plus 1
|
||||
|
@ -313,118 +469,483 @@ void FGAIAircraft::ProcessFlightPlan( double dt ) {
|
|||
curr = fp->getCurrentWaypoint();
|
||||
next = fp->getNextWaypoint();
|
||||
dt_count += dt;
|
||||
|
||||
|
||||
if (!prev) { //beginning of flightplan, do this initialization once
|
||||
fp->IncrementWaypoint();
|
||||
//setBank(0.0);
|
||||
spinCounter = 0;
|
||||
tempReg = "";
|
||||
//prev_dist_to_go = HUGE;
|
||||
//cerr << "Before increment " << curr-> name << endl;
|
||||
fp->IncrementWaypoint(eraseWaypoints);
|
||||
//prev = fp->getPreviousWaypoint(); //first waypoint
|
||||
//curr = fp->getCurrentWaypoint(); //second waypoint
|
||||
//next = fp->getNextWaypoint(); //third waypoint (might not exist!)
|
||||
//cerr << "After increment " << prev-> name << endl;
|
||||
if (!(fp->getNextWaypoint()) && trafficRef)
|
||||
{
|
||||
loadNextLeg();
|
||||
}
|
||||
//cerr << "After load " << prev-> name << endl;
|
||||
prev = fp->getPreviousWaypoint(); //first waypoint
|
||||
curr = fp->getCurrentWaypoint(); //second waypoint
|
||||
next = fp->getNextWaypoint(); //third waypoint (might not exist!)
|
||||
//cerr << "After load " << prev-> name << endl;
|
||||
setLatitude(prev->latitude);
|
||||
setLongitude(prev->longitude);
|
||||
setSpeed(prev->speed);
|
||||
setAltitude(prev->altitude);
|
||||
setHeading(fp->getBearing(prev->latitude, prev->longitude, curr));
|
||||
if (next) fp->setLeadDistance(speed, hdg, curr, next);
|
||||
if (prev->speed > 0.0)
|
||||
setHeading(fp->getBearing(prev->latitude, prev->longitude, curr));
|
||||
else
|
||||
{
|
||||
setHeading(fp->getBearing(curr->latitude, curr->longitude, prev));
|
||||
}
|
||||
// If next doesn't exist, as in incrementally created flightplans for
|
||||
// AI/Trafficmanager created plans,
|
||||
// Make sure lead distance is initialized otherwise
|
||||
if (next)
|
||||
fp->setLeadDistance(speed, hdg, curr, next);
|
||||
|
||||
if (curr->crossat > -1000.0) { //use a calculated descent/climb rate
|
||||
use_perf_vs = false;
|
||||
tgt_vs = (curr->crossat - prev->altitude)/
|
||||
(fp->getDistanceToGo(pos.lat(), pos.lon(), curr)/
|
||||
6076.0/prev->speed*60.0);
|
||||
use_perf_vs = false;
|
||||
tgt_vs = (curr->crossat - prev->altitude)/
|
||||
(fp->getDistanceToGo(pos.lat(), pos.lon(), curr)/
|
||||
6076.0/prev->speed*60.0);
|
||||
tgt_altitude = curr->crossat;
|
||||
} else {
|
||||
use_perf_vs = true;
|
||||
tgt_altitude = prev->altitude;
|
||||
use_perf_vs = true;
|
||||
tgt_altitude = prev->altitude;
|
||||
}
|
||||
alt_lock = hdg_lock = true;
|
||||
no_roll = prev->on_ground;
|
||||
if (no_roll)
|
||||
{
|
||||
Transform(); // make sure aip is initialized.
|
||||
getGroundElev(60.1); // make sure it's exectuted first time around, so force a large dt value
|
||||
//getGroundElev(60.1); // Need to do this twice.
|
||||
//cerr << trafficRef->getRegistration() << " Setting altitude to " << tgt_altitude << endl;
|
||||
setAltitude(tgt_altitude);
|
||||
}
|
||||
prevSpeed = 0;
|
||||
//cout << "First waypoint: " << prev->name << endl;
|
||||
//cout << " Target speed: " << tgt_speed << endl;
|
||||
//cout << " Target altitude: " << tgt_altitude << endl;
|
||||
//cout << " Target heading: " << tgt_heading << endl << endl;
|
||||
//cerr << "Done Flightplan init" << endl;
|
||||
return;
|
||||
} // end of initialization
|
||||
|
||||
|
||||
// let's only process the flight plan every 100 ms.
|
||||
if (dt_count < 0.1) {
|
||||
return;
|
||||
} else {
|
||||
dt_count = 0;
|
||||
|
||||
// check to see if we've reached the lead point for our next turn
|
||||
double dist_to_go = fp->getDistanceToGo(pos.lat(), pos.lon(), curr);
|
||||
double lead_dist = fp->getLeadDistance();
|
||||
if (lead_dist < (2*speed)) lead_dist = 2*speed; //don't skip over the waypoint
|
||||
//cout << "dist_to_go: " << dist_to_go << ", lead_dist: " << lead_dist << endl;
|
||||
|
||||
if ( dist_to_go < lead_dist ) {
|
||||
if (curr->finished) { //end of the flight plan, so terminate
|
||||
if (trafficRef)
|
||||
{
|
||||
delete fp;
|
||||
//time_t now = time(NULL) + fgGetLong("/sim/time/warp");
|
||||
trafficRef->next();
|
||||
|
||||
FGAIModelEntity entity;
|
||||
entity.m_class = "jet_transport";
|
||||
//entity.path = modelPath.c_str();
|
||||
entity.flightplan = "none";
|
||||
entity.latitude = _getLatitude();
|
||||
entity.longitude = _getLongitude();
|
||||
entity.altitude = trafficRef->getCruiseAlt() * 100; // convert from FL to feet
|
||||
entity.speed = 450;
|
||||
//entity.fp = new FGAIFlightPlan(&entity, courseToDest, i->getDepartureTime(), dep, arr);
|
||||
entity.fp = new FGAIFlightPlan(&entity,
|
||||
999, // A hack
|
||||
trafficRef->getDepartureTime(),
|
||||
trafficRef->getDepartureAirport(),
|
||||
trafficRef->getArrivalAirport());
|
||||
SetFlightPlan(entity.fp);
|
||||
}
|
||||
else
|
||||
{
|
||||
setDie(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// we've reached the lead-point for the waypoint ahead
|
||||
if (next) tgt_heading = fp->getBearing(curr, next);
|
||||
fp->IncrementWaypoint();
|
||||
prev = fp->getPreviousWaypoint();
|
||||
curr = fp->getCurrentWaypoint();
|
||||
next = fp->getNextWaypoint();
|
||||
if (next) fp->setLeadDistance(speed, tgt_heading, curr, next);
|
||||
if (curr->crossat > -1000.0) {
|
||||
use_perf_vs = false;
|
||||
tgt_vs = (curr->crossat - altitude)/
|
||||
(fp->getDistanceToGo(pos.lat(), pos.lon(), curr)/6076.0/speed*60.0);
|
||||
tgt_altitude = curr->crossat;
|
||||
} else {
|
||||
use_perf_vs = true;
|
||||
tgt_altitude = prev->altitude;
|
||||
}
|
||||
tgt_speed = prev->speed;
|
||||
hdg_lock = alt_lock = true;
|
||||
no_roll = prev->on_ground;
|
||||
//cout << "Crossing waypoint: " << prev->name << endl;
|
||||
//cout << " Target speed: " << tgt_speed << endl;
|
||||
//cout << " Target altitude: " << tgt_altitude << endl;
|
||||
//cout << " Target heading: " << tgt_heading << endl << endl;
|
||||
if ((dt_count < 0.1) || (now < fp->getStartTime()))
|
||||
{
|
||||
//cerr << "done fp dt" << endl;
|
||||
return;
|
||||
} else {
|
||||
double calc_bearing = fp->getBearing(pos.lat(), pos.lon(), curr);
|
||||
double hdg_error = calc_bearing - tgt_heading;
|
||||
if (fabs(hdg_error) > 1.0) {
|
||||
TurnTo( calc_bearing );
|
||||
}
|
||||
dt_count = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// check to see if we've reached the lead point for our next turn
|
||||
double dist_to_go = fp->getDistanceToGo(pos.lat(), pos.lon(), curr);
|
||||
|
||||
//cerr << "2" << endl;
|
||||
double lead_dist = fp->getLeadDistance();
|
||||
//cerr << " Distance : " << dist_to_go << ": Lead distance " << lead_dist << endl;
|
||||
// experimental: Use fabs, because speed can be negative (I hope) during push_back.
|
||||
if (lead_dist < fabs(2*speed))
|
||||
{
|
||||
lead_dist = fabs(2*speed); //don't skip over the waypoint
|
||||
//cerr << "Extending lead distance to " << lead_dist << endl;
|
||||
}
|
||||
// FGAirport * apt = trafficRef->getDepartureAirport();
|
||||
// if ((dist_to_go > prev_dist_to_go) && trafficRef && apt)
|
||||
// {
|
||||
// if (apt->getId() == string("EHAM"))
|
||||
// cerr << "Alert: " << trafficRef->getRegistration() << " is moving away from waypoint " << curr->name << endl
|
||||
// << "Target heading : " << tgt_heading << "act heading " << hdg << " Tgt speed : " << tgt_speed << endl
|
||||
// << "Lead distance : " << lead_dist << endl
|
||||
// << "Distance to go: " << dist_to_go << endl;
|
||||
|
||||
// }
|
||||
prev_dist_to_go = dist_to_go;
|
||||
//cerr << "2" << endl;
|
||||
//if (no_roll)
|
||||
// lead_dist = 10.0;
|
||||
//cout << "Leg : " << (fp->getLeg()-1) << ". dist_to_go: " << dist_to_go << ", lead_dist: " << lead_dist << ", tgt_speed " << tgt_speed << ", tgt_heading " << tgt_heading << " speed " << speed << " hdg " << hdg << ". Altitude " << altitude << " TAget alt :" << tgt_altitude << endl;
|
||||
|
||||
if ( dist_to_go < lead_dist ) {
|
||||
//prev_dist_to_go = HUGE;
|
||||
// For traffic manager generated aircraft:
|
||||
// check if the aircraft flies of of user range. And adjust the
|
||||
// Current waypoint's elevation according to Terrain Elevation
|
||||
if (curr->finished) { //end of the flight plan
|
||||
{
|
||||
setDie(true);
|
||||
//cerr << "Done die end of fp" << endl;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// we've reached the lead-point for the waypoint ahead
|
||||
//cerr << "4" << endl;
|
||||
//cerr << "Situation after lead point" << endl;
|
||||
//cerr << "Prviious: " << prev->name << endl;
|
||||
//cerr << "Current : " << curr->name << endl;
|
||||
//cerr << "Next : " << next->name << endl;
|
||||
if (next)
|
||||
{
|
||||
tgt_heading = fp->getBearing(curr, next);
|
||||
spinCounter = 0;
|
||||
}
|
||||
fp->IncrementWaypoint(eraseWaypoints);
|
||||
if (!(fp->getNextWaypoint()) && trafficRef)
|
||||
{
|
||||
loadNextLeg();
|
||||
}
|
||||
prev = fp->getPreviousWaypoint();
|
||||
curr = fp->getCurrentWaypoint();
|
||||
next = fp->getNextWaypoint();
|
||||
// Now that we have incremented the waypoints, excute some traffic manager specific code
|
||||
// based on the name of the waypoint we just passed.
|
||||
if (trafficRef)
|
||||
{
|
||||
double userLatitude = fgGetDouble("/position/latitude-deg");
|
||||
double userLongitude = fgGetDouble("/position/longitude-deg");
|
||||
double course, distance;
|
||||
SGWayPoint current (pos.lon(),
|
||||
pos.lat(),
|
||||
0);
|
||||
SGWayPoint user ( userLongitude,
|
||||
userLatitude,
|
||||
0);
|
||||
user.CourseAndDistance(current, &course, &distance);
|
||||
if ((distance * SG_METER_TO_NM) > TRAFFICTOAIDIST)
|
||||
{
|
||||
setDie(true);
|
||||
//cerr << "done fp die out of range" << endl;
|
||||
return;
|
||||
}
|
||||
|
||||
FGAirport * dep = trafficRef->getDepartureAirport();
|
||||
FGAirport * arr = trafficRef->getArrivalAirport();
|
||||
// At parking the beginning of the airport
|
||||
if (!( dep && arr))
|
||||
{
|
||||
setDie(true);
|
||||
return;
|
||||
}
|
||||
//if ((dep->getId() == string("EHAM") || (arr->getId() == string("EHAM"))))
|
||||
// {
|
||||
// cerr << trafficRef->getRegistration()
|
||||
// << " Enroute from " << dep->getId()
|
||||
// << " to " << arr->getId()
|
||||
// << " just crossed " << prev->name
|
||||
// << " Assigned rwy " << fp->getRunwayId()
|
||||
// << " " << fp->getRunway() << endl;
|
||||
// }
|
||||
//if ((dep->getId() == string("EHAM")) && (prev->name == "park2"))
|
||||
// {
|
||||
// cerr << "Schiphol ground "
|
||||
// << trafficRef->getCallSign();
|
||||
// if (trafficRef->getHeavy())
|
||||
// cerr << "Heavy";
|
||||
// cerr << ", is type "
|
||||
// << trafficRef->getAircraft()
|
||||
// << " ready to go. IFR to "
|
||||
// << arr->getId() <<endl;
|
||||
// }
|
||||
if (prev->name == "park2")
|
||||
dep->releaseParking(fp->getGate());
|
||||
|
||||
//if ((arr->getId() == string("EHAM")) && (prev->name == "Center"))
|
||||
// {
|
||||
//
|
||||
// cerr << "Schiphol ground "
|
||||
// << trafficRef->getCallSign();
|
||||
// if (trafficRef->getHeavy())
|
||||
// cerr << "Heavy";
|
||||
// cerr << " landed runway "
|
||||
// << fp->getRunway()
|
||||
// << " request taxi to gate "
|
||||
// << arr->getParkingName(fp->getGate())
|
||||
// << endl;
|
||||
// }
|
||||
if (prev->name == "END")
|
||||
fp->setTime(trafficRef->getDepartureTime());
|
||||
//cerr << "5" << endl;
|
||||
}
|
||||
if (next)
|
||||
{
|
||||
//cerr << "Current waypoint" << curr->name << endl;
|
||||
//cerr << "Next waypoint" << next->name << endl;
|
||||
fp->setLeadDistance(speed, tgt_heading, curr, next);
|
||||
}
|
||||
//cerr << "5.1" << endl;
|
||||
if (curr->crossat > -1000.0) {
|
||||
//cerr << "5.1a" << endl;
|
||||
use_perf_vs = false;
|
||||
tgt_vs = (curr->crossat - altitude)/
|
||||
(fp->getDistanceToGo(pos.lat(), pos.lon(), curr)/6076.0/speed*60.0);
|
||||
//cerr << "5.1b" << endl;
|
||||
tgt_altitude = curr->crossat;
|
||||
} else {
|
||||
//cerr << "5.1c" << endl;
|
||||
use_perf_vs = true;
|
||||
//cerr << "5.1d" << endl;
|
||||
tgt_altitude = prev->altitude;
|
||||
//cerr << "Setting target altitude : " <<tgt_altitude << endl;
|
||||
}
|
||||
//cerr << "6" << endl;
|
||||
tgt_speed = prev->speed;
|
||||
hdg_lock = alt_lock = true;
|
||||
no_roll = prev->on_ground;
|
||||
//cout << "Crossing waypoint: " << prev->name << endl;
|
||||
//cout << " Target speed: " << tgt_speed << endl;
|
||||
//cout << " Target altitude: " << tgt_altitude << endl;
|
||||
//cout << " Target heading: " << tgt_heading << endl << endl;
|
||||
} else {
|
||||
|
||||
double calc_bearing = fp->getBearing(pos.lat(), pos.lon(), curr);
|
||||
//cerr << "Bearing = " << calc_bearing << endl;
|
||||
if (speed < 0)
|
||||
{
|
||||
calc_bearing +=180;
|
||||
if (calc_bearing > 360)
|
||||
calc_bearing -= 360;
|
||||
}
|
||||
if (finite(calc_bearing))
|
||||
{
|
||||
double hdg_error = calc_bearing - tgt_heading;
|
||||
if (fabs(hdg_error) > 1.0) {
|
||||
TurnTo( calc_bearing );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cerr << "calc_bearing is not a finite number : "
|
||||
<< "Speed " << speed
|
||||
<< "pos : " << pos.lat() << ", " << pos.lon()
|
||||
<< "waypoint " << curr->latitude << ", " << curr->longitude << endl;
|
||||
cerr << "waypoint name " << curr->name;
|
||||
exit(1);
|
||||
}
|
||||
double speed_diff = speed - prevSpeed;
|
||||
// Update the lead distance calculation if speed has changed sufficiently
|
||||
// to prevent spinning (hopefully);
|
||||
if (fabs(speed_diff) > 10)
|
||||
{
|
||||
prevSpeed = speed;
|
||||
fp->setLeadDistance(speed, tgt_heading, curr, next);
|
||||
}
|
||||
|
||||
//cerr << "Done Processing FlightPlan"<< endl;
|
||||
} // if (dt count) else
|
||||
}
|
||||
|
||||
|
||||
bool FGAIAircraft::_getGearDown() const {
|
||||
bool FGAIAircraft::_getGearDown() const {
|
||||
return ((props->getFloatValue("position/altitude-agl-ft") < 900.0)
|
||||
&& (props->getFloatValue("velocities/airspeed-kt")
|
||||
< performance->land_speed*1.25));
|
||||
}
|
||||
|
||||
|
||||
void FGAIAircraft::loadNextLeg()
|
||||
{
|
||||
//delete fp;
|
||||
//time_t now = time(NULL) + fgGetLong("/sim/time/warp");
|
||||
|
||||
|
||||
//FGAIModelEntity entity;
|
||||
//entity.m_class = "jet_transport";
|
||||
//entity.path = modelPath.c_str();
|
||||
//entity.flightplan = "none";
|
||||
//entity.latitude = _getLatitude();
|
||||
//entity.longitude = _getLongitude();
|
||||
//entity.altitude = trafficRef->getCruiseAlt() * 100; // convert from FL to feet
|
||||
//entity.speed = 450; // HACK ALERT
|
||||
//entity.fp = new FGAIFlightPlan(&entity, courseToDest, i->getDepartureTime(), dep, arr);
|
||||
int leg;
|
||||
if ((leg = fp->getLeg()) == 10)
|
||||
{
|
||||
trafficRef->next();
|
||||
leg = 1;
|
||||
fp->setLeg(leg);
|
||||
|
||||
//cerr << "Resetting leg : " << leg << endl;
|
||||
}
|
||||
//{
|
||||
//leg++;
|
||||
//fp->setLeg(leg);
|
||||
//cerr << "Creating leg number : " << leg << endl;
|
||||
FGAirport *dep = trafficRef->getDepartureAirport();
|
||||
FGAirport *arr = trafficRef->getArrivalAirport();
|
||||
if (!(dep && arr))
|
||||
{
|
||||
setDie(true);
|
||||
//cerr << "Failed to get airport in AIAircraft::ProcessFlightplan()" << endl;
|
||||
//if (dep)
|
||||
// cerr << "Departure " << dep->getId() << endl;
|
||||
//if (arr)
|
||||
// cerr << "Arrival " << arr->getId() << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
double cruiseAlt = trafficRef->getCruiseAlt() * 100;
|
||||
//cerr << "Creating new leg using " << cruiseAlt << " as cruise altitude."<< endl;
|
||||
|
||||
fp->create (dep,
|
||||
arr,
|
||||
leg,
|
||||
cruiseAlt, //(trafficRef->getCruiseAlt() * 100), // convert from FL to feet
|
||||
trafficRef->getSpeed(),
|
||||
_getLatitude(),
|
||||
_getLongitude(),
|
||||
false,
|
||||
trafficRef->getRadius(),
|
||||
trafficRef->getFlightType(),
|
||||
acType,
|
||||
company);
|
||||
//prev = fp->getPreviousWaypoint();
|
||||
//curr = fp->getCurrentWaypoint();
|
||||
//next = fp->getNextWaypoint();
|
||||
//cerr << "25" << endl;
|
||||
//if (next)
|
||||
// {
|
||||
// //cerr << "Next waypoint" << next->name << endl;
|
||||
// fp->setLeadDistance(speed, tgt_heading, curr, next);
|
||||
// }
|
||||
//cerr << "25.1" << endl;
|
||||
//if (curr->crossat > -1000.0) {
|
||||
// //cerr << "25.1a" << endl;
|
||||
// use_perf_vs = false;
|
||||
//
|
||||
// tgt_vs = (curr->crossat - altitude)/
|
||||
// (fp->getDistanceToGo(pos.lat(), pos.lon(), curr)/6076.0/speed*60.0);
|
||||
// //cerr << "25.1b" << endl;
|
||||
// tgt_altitude = curr->crossat;
|
||||
//} else {
|
||||
// //cerr << "25.1c" << endl;
|
||||
// use_perf_vs = true;
|
||||
// //cerr << "25.1d" << endl;
|
||||
// tgt_altitude = prev->altitude;
|
||||
// //cerr << "Setting target altitude : " <<tgt_altitude << endl;
|
||||
// }
|
||||
//cerr << "26" << endl;
|
||||
//tgt_speed = prev->speed;
|
||||
//hdg_lock = alt_lock = true;
|
||||
//no_roll = prev->on_ground;
|
||||
|
||||
}
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
//delete entity.fp;
|
||||
//entity.fp = new FGAIFlightPlan(&entity,
|
||||
// 999, // A hack
|
||||
// trafficRef->getDepartureTime(),
|
||||
// trafficRef->getDepartureAirport(),
|
||||
// trafficRef->getArrivalAirport(),
|
||||
// false,
|
||||
// acType,
|
||||
// company);
|
||||
//SetFlightPlan(entity.fp);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Note: This code is copied from David Luff's AILocalTraffic
|
||||
// Warning - ground elev determination is CPU intensive
|
||||
// Either this function or the logic of how often it is called
|
||||
// will almost certainly change.
|
||||
|
||||
void FGAIAircraft::getGroundElev(double dt) {
|
||||
dt_elev_count += dt;
|
||||
//return;
|
||||
if (dt_elev_count < (10.0 + (rand() % 100))) // Update minimally every 10 secs, but add some randomness to prevent them all IA objects doing this synced
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
dt_elev_count = 0;
|
||||
}
|
||||
// It would be nice if we could set the correct tile center here in order to get a correct
|
||||
// answer with one call to the function, but what I tried in the two commented-out lines
|
||||
// below only intermittently worked, and I haven't quite groked why yet.
|
||||
//SGBucket buck(pos.lon(), pos.lat());
|
||||
//aip.getSGLocation()->set_tile_center(Point3D(buck.get_center_lon(), buck.get_center_lat(), 0.0));
|
||||
|
||||
// Only do the proper hitlist stuff if we are within visible range of the viewer.
|
||||
double visibility_meters = fgGetDouble("/environment/visibility-m");
|
||||
|
||||
|
||||
FGViewer* vw = globals->get_current_view();
|
||||
double
|
||||
course,
|
||||
distance;
|
||||
|
||||
//Point3D currView(vw->getLongitude_deg(),
|
||||
// vw->getLatitude_deg(), 0.0);
|
||||
SGWayPoint current (pos.lon(),
|
||||
pos.lat(),
|
||||
0);
|
||||
SGWayPoint view ( vw->getLongitude_deg(),
|
||||
vw->getLatitude_deg(),
|
||||
0);
|
||||
view.CourseAndDistance(current, &course, &distance);
|
||||
if(distance > visibility_meters) {
|
||||
//aip.getSGLocation()->set_cur_elev_m(aptElev);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
//globals->get_tile_mgr()->prep_ssg_nodes( acmodel_location,
|
||||
globals->get_tile_mgr()->prep_ssg_nodes( aip.getSGLocation(), visibility_meters );
|
||||
Point3D scenery_center = globals->get_scenery()->get_center();
|
||||
|
||||
globals->get_tile_mgr()->update( aip.getSGLocation(),
|
||||
visibility_meters,
|
||||
(aip.getSGLocation())->get_absolute_view_pos( scenery_center ) );
|
||||
// save results of update in SGLocation for fdm...
|
||||
|
||||
//if ( globals->get_scenery()->get_cur_elev() > -9990 ) {
|
||||
// acmodel_location->
|
||||
// set_cur_elev_m( globals->get_scenery()->get_cur_elev() );
|
||||
//}
|
||||
|
||||
// The need for this here means that at least 2 consecutive passes are needed :-(
|
||||
aip.getSGLocation()->set_tile_center( globals->get_scenery()->get_next_center() );
|
||||
globals->get_tile_mgr()->prep_ssg_nodes( aip.getSGLocation(), visibility_meters );
|
||||
//Point3D scenery_center = globals->get_scenery()->get_center();
|
||||
|
||||
globals->get_tile_mgr()->update( aip.getSGLocation(),
|
||||
visibility_meters,
|
||||
(aip.getSGLocation())->get_absolute_view_pos( scenery_center ) );
|
||||
// save results of update in SGLocation for fdm...
|
||||
|
||||
//if ( globals->get_scenery()->get_cur_elev() > -9990 ) {
|
||||
// acmodel_location->
|
||||
// set_cur_elev_m( globals->get_scenery()->get_cur_elev() );
|
||||
//}
|
||||
|
||||
// The need for this here means that at least 2 consecutive passes are needed :-(
|
||||
aip.getSGLocation()->set_tile_center( globals->get_scenery()->get_next_center() );
|
||||
//cerr << "Transform Elev is " << globals->get_scenery()->get_cur_elev() << '\n';
|
||||
tgt_altitude = (globals->get_scenery()->get_cur_elev() * SG_METER_TO_FEET) + groundOffset;
|
||||
}
|
||||
|
||||
//globals->get_tile_mgr()->prep_ssg_nodes( _aip.getSGLocation(), visibility_meters );
|
||||
//Point3D scenery_center = globals->get_scenery()->get_center();
|
||||
//globals->get_tile_mgr()->update(_aip.getSGLocation(), visibility_meters, (_aip.getSGLocation())->get_absolute_view_pos( scenery_center ) );
|
||||
// save results of update in SGLocation for fdm...
|
||||
|
||||
//if ( globals->get_scenery()->get_cur_elev() > -9990 ) {
|
||||
// acmodel_location->
|
||||
// set_cur_elev_m( globals->get_scenery()->get_cur_elev() );
|
||||
//}
|
||||
|
||||
// The need for this here means that at least 2 consecutive passes are needed :-(
|
||||
//_aip.getSGLocation()->set_tile_center( globals->get_scenery()->get_next_center() );
|
||||
|
||||
//cout << "Transform Elev is " << globals->get_scenery()->get_cur_elev() << '\n';
|
||||
//_aip.getSGLocation()->set_cur_elev_m(globals->get_scenery()->get_cur_elev());
|
||||
//return(globals->get_scenery()->get_cur_elev());
|
||||
//}
|
||||
|
|
|
@ -48,7 +48,6 @@ private:
|
|||
} PERF_STRUCT;
|
||||
|
||||
public:
|
||||
|
||||
enum aircraft_e {LIGHT=0, WW2_FIGHTER, JET_TRANSPORT, JET_FIGHTER, TANKER};
|
||||
static const PERF_STRUCT settings[];
|
||||
|
||||
|
@ -68,7 +67,13 @@ public:
|
|||
void YawTo(double angle);
|
||||
void ClimbTo(double altitude);
|
||||
void TurnTo(double heading);
|
||||
void ProcessFlightPlan( double dt );
|
||||
void ProcessFlightPlan( double dt, time_t now );
|
||||
void getGroundElev(double dt);
|
||||
void loadNextLeg ();
|
||||
|
||||
void setAcType(string ac) { acType = ac; };
|
||||
void setCompany(string comp) { company = comp;};
|
||||
//void setSchedule(FGAISchedule *ref) { trafficRef = ref;};
|
||||
|
||||
inline void SetTanker(bool setting) { isTanker = setting; };
|
||||
|
||||
|
@ -78,6 +83,10 @@ private:
|
|||
bool hdg_lock;
|
||||
bool alt_lock;
|
||||
double dt_count;
|
||||
double dt_elev_count;
|
||||
double headingChangeRate;
|
||||
double groundTargetSpeed;
|
||||
double groundOffset;
|
||||
double dt;
|
||||
|
||||
const PERF_STRUCT *performance;
|
||||
|
@ -87,8 +96,15 @@ private:
|
|||
|
||||
void Run(double dt);
|
||||
double sign(double x);
|
||||
|
||||
string acType;
|
||||
string company;
|
||||
int spinCounter;
|
||||
double prevSpeed;
|
||||
double prev_dist_to_go;
|
||||
|
||||
bool _getGearDown() const;
|
||||
bool reachedWaypoint;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <simgear/constants.h>
|
||||
#include <simgear/math/point3d.hxx>
|
||||
#include <simgear/scene/model/placement.hxx>
|
||||
#include <simgear/misc/sg_path.hxx>
|
||||
|
||||
#include <Main/fg_props.hxx>
|
||||
|
||||
|
@ -75,7 +76,9 @@ typedef struct {
|
|||
double radius; // used by ship ojects, in feet
|
||||
double x_offset; // used by ship ojects, in meters
|
||||
double y_offset; // used by ship ojects, in meters
|
||||
double z_offset; // used by ship ojects, in meters
|
||||
double z_offset; // used by ship ojects, in meters
|
||||
string acType; // used by aircraft objects
|
||||
string company; // used by aircraft objects
|
||||
} FGAIModelEntity;
|
||||
|
||||
|
||||
|
|
|
@ -45,6 +45,8 @@ FGAIFlightPlan::FGAIFlightPlan(string filename)
|
|||
{
|
||||
int i;
|
||||
start_time = 0;
|
||||
leg = 10;
|
||||
gateId = 0;
|
||||
SGPath path( globals->get_fg_root() );
|
||||
path.append( ("/Data/AI/FlightPlans/" + filename).c_str() );
|
||||
SGPropertyNode root;
|
||||
|
@ -55,7 +57,7 @@ FGAIFlightPlan::FGAIFlightPlan(string filename)
|
|||
SG_LOG(SG_GENERAL, SG_ALERT,
|
||||
"Error reading AI flight plan: " << path.str());
|
||||
// cout << path.str() << endl;
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
SGPropertyNode * node = root.getNode("flightplan");
|
||||
|
@ -94,8 +96,15 @@ FGAIFlightPlan::FGAIFlightPlan(FGAIModelEntity *entity,
|
|||
double course,
|
||||
time_t start,
|
||||
FGAirport *dep,
|
||||
FGAirport *arr)
|
||||
FGAirport *arr,
|
||||
bool firstLeg,
|
||||
double radius,
|
||||
string fltType,
|
||||
string acType,
|
||||
string airline)
|
||||
{
|
||||
leg = 10;
|
||||
gateId=0;
|
||||
start_time = start;
|
||||
bool useInitialWayPoint = true;
|
||||
bool useCurrentWayPoint = false;
|
||||
|
@ -116,55 +125,86 @@ FGAIFlightPlan::FGAIFlightPlan(FGAIModelEntity *entity,
|
|||
useCurrentWayPoint = true;
|
||||
}
|
||||
|
||||
try {
|
||||
readProperties(path.str(), &root);
|
||||
|
||||
SGPropertyNode * node = root.getNode("flightplan");
|
||||
|
||||
//waypoints.push_back( init_waypoint );
|
||||
for (int i = 0; i < node->nChildren(); i++) {
|
||||
//cout << "Reading waypoint " << i << endl;
|
||||
waypoint* wpt = new waypoint;
|
||||
SGPropertyNode * wpt_node = node->getChild(i);
|
||||
wpt->name = wpt_node->getStringValue("name", "END");
|
||||
wpt->latitude = wpt_node->getDoubleValue("lat", 0);
|
||||
wpt->longitude = wpt_node->getDoubleValue("lon", 0);
|
||||
wpt->altitude = wpt_node->getDoubleValue("alt", 0);
|
||||
wpt->speed = wpt_node->getDoubleValue("ktas", 0);
|
||||
//wpt->speed = speed;
|
||||
wpt->crossat = wpt_node->getDoubleValue("crossat", -10000);
|
||||
wpt->gear_down = wpt_node->getBoolValue("gear-down", false);
|
||||
wpt->flaps_down= wpt_node->getBoolValue("flaps-down", false);
|
||||
|
||||
if (wpt->name == "END") wpt->finished = true;
|
||||
else wpt->finished = false;
|
||||
waypoints.push_back(wpt);
|
||||
if (path.exists())
|
||||
{
|
||||
try
|
||||
{
|
||||
readProperties(path.str(), &root);
|
||||
|
||||
SGPropertyNode * node = root.getNode("flightplan");
|
||||
|
||||
//waypoints.push_back( init_waypoint );
|
||||
for (int i = 0; i < node->nChildren(); i++) {
|
||||
//cout << "Reading waypoint " << i << endl;
|
||||
waypoint* wpt = new waypoint;
|
||||
SGPropertyNode * wpt_node = node->getChild(i);
|
||||
wpt->name = wpt_node->getStringValue("name", "END");
|
||||
wpt->latitude = wpt_node->getDoubleValue("lat", 0);
|
||||
wpt->longitude = wpt_node->getDoubleValue("lon", 0);
|
||||
wpt->altitude = wpt_node->getDoubleValue("alt", 0);
|
||||
wpt->speed = wpt_node->getDoubleValue("ktas", 0);
|
||||
//wpt->speed = speed;
|
||||
wpt->crossat = wpt_node->getDoubleValue("crossat", -10000);
|
||||
wpt->gear_down = wpt_node->getBoolValue("gear-down", false);
|
||||
wpt->flaps_down= wpt_node->getBoolValue("flaps-down", false);
|
||||
|
||||
if (wpt->name == "END") wpt->finished = true;
|
||||
else wpt->finished = false;
|
||||
waypoints.push_back(wpt);
|
||||
}
|
||||
}
|
||||
catch (const sg_exception &e) {
|
||||
SG_LOG(SG_GENERAL, SG_ALERT,
|
||||
"Error reading AI flight plan: ");
|
||||
cerr << "Errno = " << errno << endl;
|
||||
if (errno == ENOENT)
|
||||
{
|
||||
cerr << "Reason: No such file or directory" << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const sg_exception &e) {
|
||||
//SG_LOG(SG_GENERAL, SG_ALERT,
|
||||
// "Error reading AI flight plan: ");
|
||||
// cout << path.str() << endl;
|
||||
// cout << "Trying to create this plan dynamically" << endl;
|
||||
// cout << "Route from " << dep->id << " to " << arr->id << endl;
|
||||
create(dep,arr, entity->altitude, entity->speed);
|
||||
// Now that we have dynamically created a flight plan,
|
||||
// we need to add some code that pops any waypoints already past.
|
||||
//return;
|
||||
}
|
||||
waypoint* init_waypoint = new waypoint;
|
||||
init_waypoint->name = string("initial position");
|
||||
init_waypoint->latitude = entity->latitude;
|
||||
init_waypoint->longitude = entity->longitude;
|
||||
init_waypoint->altitude = entity->altitude;
|
||||
init_waypoint->speed = entity->speed;
|
||||
init_waypoint->crossat = - 10000;
|
||||
init_waypoint->gear_down = false;
|
||||
init_waypoint->flaps_down = false;
|
||||
init_waypoint->finished = false;
|
||||
|
||||
wpt_vector_iterator i = waypoints.begin();
|
||||
while (i != waypoints.end())
|
||||
else
|
||||
{
|
||||
// cout << path.str() << endl;
|
||||
// cout << "Trying to create this plan dynamically" << endl;
|
||||
// cout << "Route from " << dep->id << " to " << arr->id << endl;
|
||||
time_t now = time(NULL) + fgGetLong("/sim/time/warp");
|
||||
time_t timeDiff = now-start;
|
||||
leg = 1;
|
||||
if ((timeDiff > 300) && (timeDiff < 1200))
|
||||
leg = 2;
|
||||
else if ((timeDiff >= 1200) && (timeDiff < 1500))
|
||||
leg = 3;
|
||||
else if ((timeDiff >= 1500) && (timeDiff < 2000))
|
||||
leg = 4;
|
||||
else if (timeDiff >= 2000)
|
||||
leg = 5;
|
||||
|
||||
//cerr << "Set leg to : " << leg << endl;
|
||||
wpt_iterator = waypoints.begin();
|
||||
create(dep,arr, leg, entity->altitude, entity->speed, entity->latitude, entity->longitude,
|
||||
firstLeg, radius, fltType, acType, airline);
|
||||
wpt_iterator = waypoints.begin();
|
||||
//cerr << "after create: " << (*wpt_iterator)->name << endl;
|
||||
//leg++;
|
||||
// Now that we have dynamically created a flight plan,
|
||||
// we need to add some code that pops any waypoints already past.
|
||||
//return;
|
||||
}
|
||||
/*
|
||||
waypoint* init_waypoint = new waypoint;
|
||||
init_waypoint->name = string("initial position");
|
||||
init_waypoint->latitude = entity->latitude;
|
||||
init_waypoint->longitude = entity->longitude;
|
||||
init_waypoint->altitude = entity->altitude;
|
||||
init_waypoint->speed = entity->speed;
|
||||
init_waypoint->crossat = - 10000;
|
||||
init_waypoint->gear_down = false;
|
||||
init_waypoint->flaps_down = false;
|
||||
init_waypoint->finished = false;
|
||||
|
||||
wpt_vector_iterator i = waypoints.begin();
|
||||
while (i != waypoints.end())
|
||||
{
|
||||
//cerr << "Checking status of each waypoint: " << (*i)->name << endl;
|
||||
SGWayPoint first(init_waypoint->longitude,
|
||||
|
@ -229,11 +269,13 @@ FGAIFlightPlan::FGAIFlightPlan(FGAIModelEntity *entity,
|
|||
//delete wpt;
|
||||
delete *(i);
|
||||
i = waypoints.erase(i);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
*/
|
||||
//for (i = waypoints.begin(); i != waypoints.end(); i++)
|
||||
// cerr << "Using waypoint : " << (*i)->name << endl;
|
||||
wpt_iterator = waypoints.begin();
|
||||
//wpt_iterator = waypoints.begin();
|
||||
//cout << waypoints.size() << " waypoints read." << endl;
|
||||
}
|
||||
|
||||
|
@ -242,7 +284,13 @@ FGAIFlightPlan::FGAIFlightPlan(FGAIModelEntity *entity,
|
|||
|
||||
FGAIFlightPlan::~FGAIFlightPlan()
|
||||
{
|
||||
waypoints.clear();
|
||||
deleteWaypoints();
|
||||
//waypoints.clear();
|
||||
//while (waypoints.begin() != waypoints.end())
|
||||
// {
|
||||
// delete *(waypoints.begin());
|
||||
// waypoints.erase (waypoints.begin());
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
|
@ -266,7 +314,9 @@ FGAIFlightPlan::getCurrentWaypoint( void )
|
|||
FGAIFlightPlan::waypoint*
|
||||
FGAIFlightPlan::getNextWaypoint( void )
|
||||
{
|
||||
if (wpt_iterator == waypoints.end()) {
|
||||
wpt_vector_iterator i = waypoints.end();
|
||||
i--; // end() points to one element after the last one.
|
||||
if (wpt_iterator == i) {
|
||||
return 0;
|
||||
} else {
|
||||
wpt_vector_iterator next = wpt_iterator;
|
||||
|
@ -274,14 +324,27 @@ FGAIFlightPlan::getNextWaypoint( void )
|
|||
}
|
||||
}
|
||||
|
||||
void FGAIFlightPlan::IncrementWaypoint( void )
|
||||
void FGAIFlightPlan::IncrementWaypoint(bool eraseWaypoints )
|
||||
{
|
||||
wpt_iterator++;
|
||||
if (eraseWaypoints)
|
||||
{
|
||||
if (wpt_iterator == waypoints.begin())
|
||||
wpt_iterator++;
|
||||
else
|
||||
{
|
||||
delete *(waypoints.begin());
|
||||
waypoints.erase(waypoints.begin());
|
||||
wpt_iterator = waypoints.begin();
|
||||
wpt_iterator++;
|
||||
}
|
||||
}
|
||||
else
|
||||
wpt_iterator++;
|
||||
}
|
||||
|
||||
// gives distance in feet from a position to a waypoint
|
||||
double FGAIFlightPlan::getDistanceToGo(double lat, double lon, waypoint* wp){
|
||||
// get size of a degree at the present latitude
|
||||
// get size of a degree2 at the present latitude
|
||||
// this won't work over large distances
|
||||
double ft_per_deg_lat = 366468.96 - 3717.12 * cos(lat / SG_RADIANS_TO_DEGREES);
|
||||
double ft_per_deg_lon = 365228.16 * cos(lat / SG_RADIANS_TO_DEGREES);
|
||||
|
@ -293,12 +356,28 @@ double FGAIFlightPlan::getDistanceToGo(double lat, double lon, waypoint* wp){
|
|||
// sets distance in feet from a lead point to the current waypoint
|
||||
void FGAIFlightPlan::setLeadDistance(double speed, double bearing,
|
||||
waypoint* current, waypoint* next){
|
||||
double turn_radius = 0.1911 * speed * speed; // an estimate for 25 degrees bank
|
||||
double turn_radius;
|
||||
if (fabs(speed) > 1)
|
||||
turn_radius = 0.1911 * speed * speed; // an estimate for 25 degrees bank
|
||||
else
|
||||
turn_radius = 1.0;
|
||||
|
||||
double inbound = bearing;
|
||||
double outbound = getBearing(current, next);
|
||||
double diff = fabs(inbound - outbound);
|
||||
if (diff > 180.0) diff = 360.0 - diff;
|
||||
lead_distance = turn_radius * sin(diff * SG_DEGREES_TO_RADIANS);
|
||||
leadInAngle = fabs(inbound - outbound);
|
||||
if (leadInAngle > 180.0)
|
||||
leadInAngle = 360.0 - leadInAngle;
|
||||
if (leadInAngle < 1.0) // To prevent lead_dist from getting so small it is skipped
|
||||
leadInAngle = 1.0;
|
||||
|
||||
lead_distance = turn_radius * sin(leadInAngle * SG_DEGREES_TO_RADIANS);
|
||||
// if ((errno == EDOM) || (errno == ERANGE) || lead_distance < 1.0)
|
||||
// {
|
||||
// cerr << "Lead Distance = " << lead_distance
|
||||
// << "Diff = " << diff
|
||||
// << "Turn Radius = " << turn_radius
|
||||
// << "Speed = " << speed << endl;
|
||||
// }
|
||||
}
|
||||
|
||||
void FGAIFlightPlan::setLeadDistance(double distance_ft){
|
||||
|
@ -345,310 +424,51 @@ double FGAIFlightPlan::getBearing(double lat, double lon, waypoint* wp){
|
|||
// if (!southerly && !easterly) return 270.0 + angle;
|
||||
SGWayPoint sgWp(wp->longitude,wp->latitude, wp->altitude, SGWayPoint::WGS84, string("temp"));
|
||||
sgWp.CourseAndDistance(lon, lat, wp->altitude, &course, &distance);
|
||||
|
||||
return course;
|
||||
// Omit a compiler warning.
|
||||
|
||||
// Omit a compiler warning.
|
||||
//if ((errno == EDOM) || (errno == ERANGE))
|
||||
// {
|
||||
// cerr << "Lon: " << wp->longitude
|
||||
// << "Lat = " << wp->latitude
|
||||
// << "Tgt Lon = " <<
|
||||
// << "TgT Lat = " << speed << endl;
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
/* FGAIFlightPlan::create()
|
||||
* dynamically create a flight plan for AI traffic, based on data provided by the
|
||||
* Traffic Manager, when reading a filed flightplan failes. (DT, 2004/07/10)
|
||||
*
|
||||
* Probably need to split this into separate functions for different parts of the flight
|
||||
|
||||
* once the code matures a bit more.
|
||||
*
|
||||
*/
|
||||
void FGAIFlightPlan::create(FGAirport *dep, FGAirport *arr, double alt, double speed)
|
||||
|
||||
void FGAIFlightPlan::deleteWaypoints()
|
||||
{
|
||||
double wind_speed;
|
||||
double wind_heading;
|
||||
FGRunway rwy;
|
||||
double lat, lon, az;
|
||||
double lat2, lon2, az2;
|
||||
int direction;
|
||||
|
||||
//waypoints.push_back(wpt);
|
||||
// Create the outbound taxi leg, for now simplified as a
|
||||
// Direct route from the airport center point to the start
|
||||
// of the runway.
|
||||
///////////////////////////////////////////////////////////
|
||||
//cerr << "Cruise Alt << " << alt << endl;
|
||||
// Temporary code to add some small random variation to aircraft parking positions;
|
||||
direction = (rand() % 360);
|
||||
geo_direct_wgs_84 ( 0, dep->_latitude, dep->_longitude, direction,
|
||||
100,
|
||||
&lat2, &lon2, &az2 );
|
||||
waypoint *wpt = new waypoint;
|
||||
wpt->name = dep->_id; //wpt_node->getStringValue("name", "END");
|
||||
wpt->latitude = lat2;
|
||||
wpt->longitude = lon2;
|
||||
wpt->altitude = dep->_elevation + 19; // probably need to add some model height to it
|
||||
wpt->speed = 15;
|
||||
wpt->crossat = -10000;
|
||||
wpt->gear_down = true;
|
||||
wpt->flaps_down= true;
|
||||
wpt->finished = false;
|
||||
wpt->on_ground = true;
|
||||
waypoints.push_back(wpt);
|
||||
|
||||
// Get the current active runway, based on code from David Luff
|
||||
FGEnvironment
|
||||
stationweather = ((FGEnvironmentMgr *) globals->get_subsystem("environment"))
|
||||
->getEnvironment(dep->_latitude, dep->_longitude, dep->_elevation);
|
||||
|
||||
wind_speed = stationweather.get_wind_speed_kt();
|
||||
wind_heading = stationweather.get_wind_from_heading_deg();
|
||||
if (wind_speed == 0) {
|
||||
wind_heading = 270; // This forces West-facing rwys to be used in no-wind situations
|
||||
// which is consistent with Flightgear's initial setup.
|
||||
}
|
||||
|
||||
string rwy_no = globals->get_runways()->search(dep->_id, int(wind_heading));
|
||||
if (!(globals->get_runways()->search(dep->_id, (int) wind_heading, &rwy )))
|
||||
{
|
||||
cout << "Failed to find runway for " << dep->_id << endl;
|
||||
// Hmm, how do we handle a potential error like this?
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
double heading = rwy._heading;
|
||||
double azimuth = heading + 180.0;
|
||||
while ( azimuth >= 360.0 ) { azimuth -= 360.0; }
|
||||
geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, azimuth,
|
||||
rwy._length * SG_FEET_TO_METER * 0.5 - 5.0,
|
||||
&lat2, &lon2, &az2 );
|
||||
|
||||
//Add the runway startpoint;
|
||||
wpt = new waypoint;
|
||||
wpt->name = rwy._id;
|
||||
wpt->latitude = lat2;
|
||||
wpt->longitude = lon2;
|
||||
wpt->altitude = dep->_elevation + 19;
|
||||
wpt->speed = 15;
|
||||
wpt->crossat = -10000;
|
||||
wpt->gear_down = true;
|
||||
wpt->flaps_down= true;
|
||||
wpt->finished = false;
|
||||
wpt->on_ground = true;
|
||||
waypoints.push_back(wpt);
|
||||
|
||||
//Next: The point on the runway where we begin to accelerate to take-off speed
|
||||
//100 meters down the runway seems to work. Shorter distances cause problems with
|
||||
// the turn with larger aircraft
|
||||
geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, azimuth,
|
||||
rwy._length * SG_FEET_TO_METER * 0.5 - 105.0,
|
||||
&lat2, &lon2, &az2 );
|
||||
wpt = new waypoint;
|
||||
wpt->name = "accel";
|
||||
wpt->latitude = lat2;
|
||||
wpt->longitude = lon2;
|
||||
wpt->altitude = dep->_elevation + 19;
|
||||
wpt->speed = speed;
|
||||
wpt->crossat = -10000;
|
||||
wpt->gear_down = true;
|
||||
wpt->flaps_down= true;
|
||||
wpt->finished = false;
|
||||
wpt->on_ground = true;
|
||||
waypoints.push_back(wpt);
|
||||
|
||||
lat = lat2;
|
||||
lon = lon2;
|
||||
az = az2;
|
||||
|
||||
//Next: the Start of Climb
|
||||
geo_direct_wgs_84 ( 0, lat, lon, heading,
|
||||
2560 * SG_FEET_TO_METER,
|
||||
&lat2, &lon2, &az2 );
|
||||
|
||||
wpt = new waypoint;
|
||||
wpt->name = "SOC";
|
||||
wpt->latitude = lat2;
|
||||
wpt->longitude = lon2;
|
||||
wpt->altitude = alt + 19;
|
||||
wpt->speed = speed;
|
||||
wpt->crossat = -10000;
|
||||
wpt->gear_down = true;
|
||||
wpt->flaps_down= true;
|
||||
wpt->finished = false;
|
||||
wpt->on_ground = false;
|
||||
waypoints.push_back(wpt);
|
||||
|
||||
//Next: the Top of Climb
|
||||
geo_direct_wgs_84 ( 0, lat, lon, heading,
|
||||
20*SG_NM_TO_METER,
|
||||
&lat2, &lon2, &az2 );
|
||||
wpt = new waypoint;
|
||||
wpt->name = "10000ft climb";
|
||||
wpt->latitude = lat2;
|
||||
wpt->longitude = lon2;
|
||||
wpt->altitude = 10000;
|
||||
wpt->speed = speed;
|
||||
wpt->crossat = -10000;
|
||||
wpt->gear_down = true;
|
||||
wpt->flaps_down= true;
|
||||
wpt->finished = false;
|
||||
wpt->on_ground = false;
|
||||
waypoints.push_back(wpt);
|
||||
|
||||
|
||||
|
||||
//Beginning of Decent
|
||||
stationweather = ((FGEnvironmentMgr *)globals->get_subsystem("environment"))
|
||||
->getEnvironment(arr->_latitude, arr->_longitude, arr->_elevation);
|
||||
|
||||
wind_speed = stationweather.get_wind_speed_kt();
|
||||
wind_heading = stationweather.get_wind_from_heading_deg();
|
||||
|
||||
if (wind_speed == 0) {
|
||||
wind_heading = 270; // This forces West-facing rwys to be used in no-wind situations
|
||||
// which is consistent with Flightgear's initial setup.
|
||||
}
|
||||
|
||||
rwy_no = globals->get_runways()->search(arr->_id, int(wind_heading));
|
||||
//cout << "Using runway # " << rwy_no << " for departure at " << dep->_id << endl;
|
||||
|
||||
if (!(globals->get_runways()->search(arr->_id, (int) wind_heading, &rwy )))
|
||||
{
|
||||
cout << "Failed to find runway for " << arr->_id << endl;
|
||||
// Hmm, how do we handle a potential error like this?
|
||||
exit(1);
|
||||
}
|
||||
//cerr << "Done" << endl;
|
||||
heading = rwy._heading;
|
||||
azimuth = heading + 180.0;
|
||||
while ( azimuth >= 360.0 ) { azimuth -= 360.0; }
|
||||
|
||||
|
||||
|
||||
geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, azimuth,
|
||||
100000,
|
||||
&lat2, &lon2, &az2 );
|
||||
wpt = new waypoint;
|
||||
wpt->name = "BOD"; //wpt_node->getStringValue("name", "END");
|
||||
wpt->latitude = lat2;
|
||||
wpt->longitude = lon2;
|
||||
wpt->altitude = 10000;
|
||||
wpt->speed = speed;
|
||||
wpt->crossat = alt +19;
|
||||
wpt->gear_down = false;
|
||||
wpt->flaps_down= false;
|
||||
wpt->finished = false;
|
||||
wpt->on_ground = false;
|
||||
waypoints.push_back(wpt);
|
||||
|
||||
// Ten thousand ft. Slowing down to 240 kts
|
||||
geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, azimuth,
|
||||
20*SG_NM_TO_METER,
|
||||
&lat2, &lon2, &az2 );
|
||||
wpt = new waypoint;
|
||||
wpt->name = "Dec 10000ft"; //wpt_node->getStringValue("name", "END");
|
||||
wpt->latitude = lat2;
|
||||
wpt->longitude = lon2;
|
||||
wpt->altitude = arr->_elevation + 19;
|
||||
wpt->speed = 240;
|
||||
wpt->crossat = 10000;
|
||||
wpt->gear_down = false;
|
||||
wpt->flaps_down= false;
|
||||
wpt->finished = false;
|
||||
wpt->on_ground = false;
|
||||
waypoints.push_back(wpt);
|
||||
|
||||
// Three thousand ft. Slowing down to 160 kts
|
||||
geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, azimuth,
|
||||
8*SG_NM_TO_METER,
|
||||
&lat2, &lon2, &az2 );
|
||||
wpt = new waypoint;
|
||||
wpt->name = "DEC 3000ft"; //wpt_node->getStringValue("name", "END");
|
||||
wpt->latitude = lat2;
|
||||
wpt->longitude = lon2;
|
||||
wpt->altitude = arr->_elevation + 19;
|
||||
wpt->speed = 160;
|
||||
wpt->crossat = 3000;
|
||||
wpt->gear_down = true;
|
||||
wpt->flaps_down= true;
|
||||
wpt->finished = false;
|
||||
wpt->on_ground = false;
|
||||
waypoints.push_back(wpt);
|
||||
//Runway Threshold
|
||||
geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, azimuth,
|
||||
rwy._length*0.45 * SG_FEET_TO_METER,
|
||||
&lat2, &lon2, &az2 );
|
||||
wpt = new waypoint;
|
||||
wpt->name = "Threshold"; //wpt_node->getStringValue("name", "END");
|
||||
wpt->latitude = lat2;
|
||||
wpt->longitude = lon2;
|
||||
wpt->altitude = arr->_elevation + 19;
|
||||
wpt->speed = 15;
|
||||
wpt->crossat = arr->_elevation + 19;
|
||||
wpt->gear_down = true;
|
||||
wpt->flaps_down= true;
|
||||
wpt->finished = false;
|
||||
wpt->on_ground = true;
|
||||
waypoints.push_back(wpt);
|
||||
|
||||
//Full stop at the runway centerpoint
|
||||
geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, azimuth,
|
||||
rwy._length*0.45,
|
||||
&lat2, &lon2, &az2 );
|
||||
wpt = new waypoint;
|
||||
wpt->name = "Center"; //wpt_node->getStringValue("name", "END");
|
||||
wpt->latitude = rwy._lat;
|
||||
wpt->longitude = rwy._lon;
|
||||
wpt->altitude = arr->_elevation + 19;
|
||||
wpt->speed = 15;
|
||||
wpt->crossat = -10000;
|
||||
wpt->gear_down = true;
|
||||
wpt->flaps_down= true;
|
||||
wpt->finished = false;
|
||||
wpt->on_ground = true;
|
||||
waypoints.push_back(wpt);
|
||||
|
||||
direction = (rand() % 360);
|
||||
geo_direct_wgs_84 ( 0, arr->_latitude, arr->_longitude, direction,
|
||||
100,
|
||||
&lat2, &lon2, &az2 );
|
||||
|
||||
// Add the final destination waypoint
|
||||
wpt = new waypoint;
|
||||
wpt->name = arr->_id; //wpt_node->getStringValue("name", "END");
|
||||
wpt->latitude = lat2;
|
||||
wpt->longitude = lon2;
|
||||
wpt->altitude = arr->_elevation+19;
|
||||
wpt->speed = 15;
|
||||
wpt->crossat = -10000;
|
||||
wpt->gear_down = true;
|
||||
wpt->flaps_down= true;
|
||||
wpt->finished = false;
|
||||
wpt->on_ground = true;
|
||||
waypoints.push_back(wpt);
|
||||
|
||||
// And finally one more named "END"
|
||||
wpt = new waypoint;
|
||||
wpt->name = "END"; //wpt_node->getStringValue("name", "END");
|
||||
wpt->latitude = lat2;
|
||||
wpt->longitude = lon2;
|
||||
wpt->altitude = 19;
|
||||
wpt->speed = 15;
|
||||
wpt->crossat = -10000;
|
||||
wpt->gear_down = true;
|
||||
wpt->flaps_down= true;
|
||||
wpt->finished = true;
|
||||
wpt->on_ground = true;
|
||||
waypoints.push_back(wpt);
|
||||
|
||||
// And finally one more named "EOF"
|
||||
wpt = new waypoint;
|
||||
wpt->name = "EOF"; //wpt_node->getStringValue("name", "END");
|
||||
wpt->latitude = lat2;
|
||||
wpt->longitude = lon2;
|
||||
wpt->altitude = 19;
|
||||
wpt->speed = 15;
|
||||
wpt->crossat = -10000;
|
||||
wpt->gear_down = true;
|
||||
wpt->flaps_down= true;
|
||||
wpt->finished = true;
|
||||
wpt->on_ground = true;
|
||||
waypoints.push_back(wpt);
|
||||
for (wpt_vector_iterator i = waypoints.begin(); i != waypoints.end();i++)
|
||||
delete (*i);
|
||||
waypoints.clear();
|
||||
}
|
||||
|
||||
// Delete all waypoints except the last,
|
||||
// which we will recycle as the first waypoint in the next leg;
|
||||
void FGAIFlightPlan::resetWaypoints()
|
||||
{
|
||||
if (waypoints.begin() == waypoints.end())
|
||||
return;
|
||||
else
|
||||
{
|
||||
waypoint *wpt = new waypoint;
|
||||
wpt_vector_iterator i = waypoints.end();
|
||||
i--;
|
||||
wpt->name = (*i)->name;
|
||||
wpt->latitude = (*i)->latitude;
|
||||
wpt->longitude = (*i)->longitude;
|
||||
wpt->altitude = (*i)->altitude;
|
||||
wpt->speed = (*i)->speed;
|
||||
wpt->crossat = (*i)->crossat;
|
||||
wpt->gear_down = (*i)->gear_down;
|
||||
wpt->flaps_down= (*i)->flaps_down;
|
||||
wpt->finished = false;
|
||||
wpt->on_ground = (*i)->on_ground;
|
||||
//cerr << "Recycling waypoint " << wpt->name << endl;
|
||||
deleteWaypoints();
|
||||
waypoints.push_back(wpt);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include <string>
|
||||
|
||||
#include <Airports/simple.hxx>
|
||||
#include <Airports/runways.hxx>
|
||||
|
||||
#include "AIBase.hxx"
|
||||
|
||||
|
@ -53,15 +54,21 @@ public:
|
|||
double course,
|
||||
time_t start,
|
||||
FGAirport *dep,
|
||||
FGAirport *arr);
|
||||
FGAirport *arr,
|
||||
bool firstLeg,
|
||||
double radius,
|
||||
string fltType,
|
||||
string acType,
|
||||
string airline);
|
||||
~FGAIFlightPlan();
|
||||
|
||||
waypoint* getPreviousWaypoint( void );
|
||||
waypoint* getCurrentWaypoint( void );
|
||||
waypoint* getNextWaypoint( void );
|
||||
void IncrementWaypoint( void );
|
||||
void IncrementWaypoint( bool erase );
|
||||
|
||||
double getDistanceToGo(double lat, double lon, waypoint* wp);
|
||||
int getLeg () { return leg;};
|
||||
void setLeadDistance(double speed, double bearing, waypoint* current, waypoint* next);
|
||||
void setLeadDistance(double distance_ft);
|
||||
double getLeadDistance( void ) const {return lead_distance;}
|
||||
|
@ -69,10 +76,17 @@ public:
|
|||
double getBearing(double lat, double lon, waypoint* next);
|
||||
time_t getStartTime() { return start_time; };
|
||||
|
||||
void create(FGAirport *dep, FGAirport *arr, double alt, double speed);
|
||||
void create(FGAirport *dep, FGAirport *arr, int leg, double alt, double speed, double lat, double lon,
|
||||
bool firstLeg, double radius, string fltType, string aircraftType, string airline);
|
||||
|
||||
void setLeg(int val) { leg = val;};
|
||||
void setTime(time_t st) { start_time = st; };
|
||||
int getGate() { return gateId; };
|
||||
double getLeadInAngle() { return leadInAngle; };
|
||||
string getRunway() { return rwy._rwy_no; };
|
||||
string getRunwayId() { return rwy._id; };
|
||||
private:
|
||||
|
||||
FGRunway rwy;
|
||||
typedef vector <waypoint*> wpt_vector_type;
|
||||
typedef wpt_vector_type::iterator wpt_vector_iterator;
|
||||
|
||||
|
@ -81,8 +95,21 @@ private:
|
|||
|
||||
double distance_to_go;
|
||||
double lead_distance;
|
||||
double leadInAngle;
|
||||
time_t start_time;
|
||||
int leg;
|
||||
int gateId;
|
||||
|
||||
void createPushBack(bool, FGAirport*, double, double, double, string, string, string);
|
||||
void createTaxi(bool, int, FGAirport *, double, string, string, string);
|
||||
void createTakeOff(bool, FGAirport *, double);
|
||||
void createClimb(bool, FGAirport *, double, double);
|
||||
void createCruise(bool, FGAirport*, FGAirport*, double, double, double, double);
|
||||
void createDecent(FGAirport *);
|
||||
void createLanding(FGAirport *);
|
||||
void createParking(FGAirport *);
|
||||
void deleteWaypoints();
|
||||
void resetWaypoints();
|
||||
};
|
||||
|
||||
|
||||
|
|
822
src/AIModel/AIFlightPlanCreate.cxx
Normal file
822
src/AIModel/AIFlightPlanCreate.cxx
Normal 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++;
|
||||
}
|
|
@ -156,6 +156,8 @@ FGAIManager::createAircraft( FGAIModelEntity *entity, FGAISchedule *ref) {
|
|||
} else {
|
||||
ai_plane->SetPerformance(&FGAIAircraft::settings[FGAIAircraft::JET_TRANSPORT]);
|
||||
}
|
||||
ai_plane->setAcType(entity->acType);
|
||||
ai_plane->setCompany(entity->company);
|
||||
ai_plane->setHeading(entity->heading);
|
||||
ai_plane->setSpeed(entity->speed);
|
||||
ai_plane->setPath(entity->path.c_str());
|
||||
|
|
|
@ -9,7 +9,7 @@ libAIModel_a_SOURCES = \
|
|||
AIBallistic.hxx AIBallistic.cxx \
|
||||
AIStorm.hxx AIStorm.cxx \
|
||||
AIThermal.hxx AIThermal.cxx \
|
||||
AIFlightPlan.hxx AIFlightPlan.cxx \
|
||||
AIFlightPlan.hxx AIFlightPlan.cxx AIFlightPlanCreate.cxx \
|
||||
AIScenario.hxx AIScenario.cxx \
|
||||
AICarrier.hxx AICarrier.cxx
|
||||
|
||||
|
|
|
@ -133,7 +133,7 @@ void FGAIMgr::init() {
|
|||
f_ident = file.substr(0, pos);
|
||||
FGAirport a;
|
||||
if(dclFindAirportID(f_ident, &a)) {
|
||||
SGBucket sgb(a._longitude, a._latitude);
|
||||
SGBucket sgb(a.getLongitude(), a.getLatitude());
|
||||
int idx = sgb.gen_index();
|
||||
if(facilities.find(idx) != facilities.end()) {
|
||||
facilities[idx]->push_back(f_ident);
|
||||
|
|
|
@ -460,7 +460,7 @@ void FGATCDialog::FreqDisplay(string ident) {
|
|||
FGAirport a;
|
||||
if ( dclFindAirportID( ident, &a ) ) {
|
||||
comm_list_type stations;
|
||||
int found = current_commlist->FindByPos(a._longitude, a._latitude, a._elevation, 20.0, &stations);
|
||||
int found = current_commlist->FindByPos(a.getLongitude(), a.getLatitude(), a.getElevation(), 20.0, &stations);
|
||||
if(found) {
|
||||
ostringstream ostr;
|
||||
comm_list_iterator itr = stations.begin();
|
||||
|
|
|
@ -221,9 +221,9 @@ bool FGATCMgr::AIRegisterAirport(string ident) {
|
|||
//cout << "ident = " << ident << '\n';
|
||||
AirportATC *a = new AirportATC;
|
||||
// I'm not entirely sure that this AirportATC structure business is actually needed - it just duplicates what we can find out anyway!
|
||||
a->lon = ap._longitude;
|
||||
a->lat = ap._latitude;
|
||||
a->elev = ap._elevation;
|
||||
a->lon = ap.getLongitude();
|
||||
a->lat = ap.getLatitude();
|
||||
a->elev = ap.getElevation();
|
||||
a->atis_freq = GetFrequency(ident, ATIS);
|
||||
//cout << "ATIS freq = " << a->atis_freq << '\n';
|
||||
a->atis_active = false;
|
||||
|
@ -270,9 +270,9 @@ bool FGATCMgr::CommRegisterAirport(string ident, int chan, atc_type tp) {
|
|||
if(dclFindAirportID(ident, &ap)) {
|
||||
AirportATC *a = new AirportATC;
|
||||
// I'm not entirely sure that this AirportATC structure business is actually needed - it just duplicates what we can find out anyway!
|
||||
a->lon = ap._longitude;
|
||||
a->lat = ap._latitude;
|
||||
a->elev = ap._elevation;
|
||||
a->lon = ap.getLongitude();
|
||||
a->lat = ap.getLatitude();
|
||||
a->elev = ap.getElevation();
|
||||
a->atis_freq = GetFrequency(ident, ATIS);
|
||||
a->atis_active = false;
|
||||
a->tower_freq = GetFrequency(ident, TOWER);
|
||||
|
|
|
@ -314,7 +314,7 @@ bool dclFindAirportID( const string& id, FGAirport *a ) {
|
|||
SG_LOG( SG_GENERAL, SG_INFO, "Searching for airport code = " << id );
|
||||
|
||||
result = globals->get_airports()->search( id );
|
||||
if ( result._id.empty() ) {
|
||||
if ( result.getId().empty() ) {
|
||||
SG_LOG( SG_GENERAL, SG_WARN,
|
||||
"Failed to find " << id << " in basic.dat.gz" );
|
||||
return false;
|
||||
|
@ -327,8 +327,8 @@ bool dclFindAirportID( const string& id, FGAirport *a ) {
|
|||
|
||||
SG_LOG( SG_GENERAL, SG_INFO,
|
||||
"Position for " << id << " is ("
|
||||
<< a->_longitude << ", "
|
||||
<< a->_latitude << ")" );
|
||||
<< a->getLongitude() << ", "
|
||||
<< a->getLatitude() << ")" );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -342,7 +342,7 @@ double dclGetAirportElev( const string& id ) {
|
|||
"Finding elevation for airport: " << id );
|
||||
|
||||
if ( dclFindAirportID( id, &a ) ) {
|
||||
return a._elevation * SG_FEET_TO_METER;
|
||||
return a.getElevation() * SG_FEET_TO_METER;
|
||||
} else {
|
||||
return -9999.0;
|
||||
}
|
||||
|
@ -357,7 +357,7 @@ Point3D dclGetAirportPos( const string& id ) {
|
|||
"Finding position for airport: " << id );
|
||||
|
||||
if ( dclFindAirportID( id, &a ) ) {
|
||||
return Point3D(a._longitude, a._latitude, a._elevation);
|
||||
return Point3D(a.getLongitude(), a.getLatitude(), a.getElevation());
|
||||
} else {
|
||||
return Point3D(0.0, 0.0, -9999.0);
|
||||
}
|
||||
|
|
|
@ -276,7 +276,7 @@ bool FGCommList::FindByCode( string ICAO, ATCData& ad, atc_type tp ) {
|
|||
FGAirport a;
|
||||
if ( dclFindAirportID( ICAO, &a ) ) {
|
||||
comm_list_type stations;
|
||||
int found = FindByPos(a._longitude, a._latitude, a._elevation, 10.0, &stations, tp);
|
||||
int found = FindByPos(a.getLongitude(), a.getLatitude(), a.getElevation(), 10.0, &stations, tp);
|
||||
if(found) {
|
||||
comm_list_iterator itr = stations.begin();
|
||||
while(itr != stations.end()) {
|
||||
|
|
|
@ -232,8 +232,8 @@ bool fgAirportDBLoad( FGAirportList *airports, FGRunwayList *runways,
|
|||
if ( ident == "#" || ident == "//" ) {
|
||||
metar_in >> skipeol;
|
||||
} else {
|
||||
FGAirport a = airports->search( ident );
|
||||
if ( a._id == ident ) {
|
||||
const FGAirport &a = airports->search( ident );
|
||||
if ( a.getId() == ident ) {
|
||||
airports->has_metar( ident );
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -3,6 +3,7 @@
|
|||
// elevation in feet.
|
||||
//
|
||||
// Written by Curtis Olson, started April 1998.
|
||||
// Updated by Durk Talsma, started December 2004.
|
||||
//
|
||||
// Copyright (C) 1998 Curtis L. Olson - http://www.flightgear.org/~curt
|
||||
//
|
||||
|
@ -37,6 +38,7 @@
|
|||
#endif
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
#include <simgear/xml/easyxml.hxx>
|
||||
|
||||
#include STL_STRING
|
||||
#include <map>
|
||||
|
@ -46,17 +48,249 @@ SG_USING_STD(string);
|
|||
SG_USING_STD(map);
|
||||
SG_USING_STD(vector);
|
||||
|
||||
typedef vector<string> stringVec;
|
||||
typedef vector<string>::iterator stringVecIterator;
|
||||
typedef vector<string>::const_iterator stringVecConstIterator;
|
||||
|
||||
struct FGAirport {
|
||||
string _id;
|
||||
double _longitude;
|
||||
double _latitude;
|
||||
double _elevation;
|
||||
string _code; // depricated and can be removed
|
||||
string _name;
|
||||
bool _has_metar;
|
||||
typedef vector<time_t> timeVec;
|
||||
typedef vector<time_t>::const_iterator timeVecConstIterator;
|
||||
/***************************************************************************/
|
||||
class ScheduleTime {
|
||||
private:
|
||||
timeVec start;
|
||||
timeVec end;
|
||||
stringVec scheduleNames;
|
||||
double tailWind;
|
||||
double crssWind;
|
||||
public:
|
||||
ScheduleTime() {};
|
||||
ScheduleTime(const ScheduleTime &other);
|
||||
ScheduleTime &operator= (const ScheduleTime &other);
|
||||
string getName(time_t dayStart);
|
||||
|
||||
FGAirport() : _longitude(0), _latitude(0), _elevation(0) {}
|
||||
void clear();
|
||||
void addStartTime(time_t time) { start.push_back(time); };
|
||||
void addEndTime (time_t time) { end. push_back(time); };
|
||||
void addScheduleName(string sched) { scheduleNames.push_back(sched); };
|
||||
void setTailWind(double wnd) { tailWind = wnd; };
|
||||
void setCrossWind(double wnd) { tailWind = wnd; };
|
||||
|
||||
double getTailWind() { return tailWind; };
|
||||
double getCrossWind() { return crssWind; };
|
||||
};
|
||||
|
||||
//typedef vector<ScheduleTime> ScheduleTimes;
|
||||
/*****************************************************************************/
|
||||
|
||||
class RunwayList
|
||||
{
|
||||
private:
|
||||
string type;
|
||||
stringVec preferredRunways;
|
||||
public:
|
||||
RunwayList() {};
|
||||
RunwayList(const RunwayList &other);
|
||||
RunwayList& operator= (const RunwayList &other);
|
||||
|
||||
void set(string, string);
|
||||
void clear();
|
||||
|
||||
string getType() { return type; };
|
||||
stringVec *getRwyList() { return &preferredRunways; };
|
||||
string getRwyList(int j) { return preferredRunways[j]; };
|
||||
};
|
||||
|
||||
typedef vector<RunwayList> RunwayListVec;
|
||||
typedef vector<RunwayList>::iterator RunwayListVectorIterator;
|
||||
typedef vector<RunwayList>::const_iterator RunwayListVecConstIterator;
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
class RunwayGroup
|
||||
{
|
||||
private:
|
||||
string name;
|
||||
RunwayListVec rwyList;
|
||||
int active;
|
||||
//stringVec runwayNames;
|
||||
int choice[2];
|
||||
int nrActive;
|
||||
public:
|
||||
RunwayGroup() {};
|
||||
RunwayGroup(const RunwayGroup &other);
|
||||
RunwayGroup &operator= (const RunwayGroup &other);
|
||||
|
||||
void setName(string nm) { name = nm; };
|
||||
void add(RunwayList list) { rwyList.push_back(list);};
|
||||
void setActive(string aptId, double windSpeed, double windHeading, double maxTail, double maxCross);
|
||||
|
||||
int getNrActiveRunways() { return nrActive;};
|
||||
void getActive(int i, string *name, string *type);
|
||||
|
||||
string getName() { return name; };
|
||||
void clear() { rwyList.clear(); };
|
||||
//void add(string, string);
|
||||
};
|
||||
|
||||
typedef vector<RunwayGroup> PreferenceList;
|
||||
typedef vector<RunwayGroup>::iterator PreferenceListIterator;
|
||||
typedef vector<RunwayGroup>::const_iterator PreferenceListConstIterator;
|
||||
/******************************************************************************/
|
||||
|
||||
class FGRunwayPreference : public XMLVisitor {
|
||||
private:
|
||||
string value;
|
||||
string scheduleName;
|
||||
|
||||
ScheduleTime comTimes; // Commercial Traffic;
|
||||
ScheduleTime genTimes; // General Aviation;
|
||||
ScheduleTime milTimes; // Military Traffic;
|
||||
ScheduleTime currTimes; // Needed for parsing;
|
||||
|
||||
RunwayList rwyList;
|
||||
RunwayGroup rwyGroup;
|
||||
PreferenceList preferences;
|
||||
|
||||
time_t processTime(string);
|
||||
bool initialized;
|
||||
|
||||
public:
|
||||
FGRunwayPreference();
|
||||
FGRunwayPreference(const FGRunwayPreference &other);
|
||||
|
||||
FGRunwayPreference & operator= (const FGRunwayPreference &other);
|
||||
ScheduleTime *getSchedule(const char *trafficType);
|
||||
RunwayGroup *getGroup(const string groupName);
|
||||
bool available() { return initialized; };
|
||||
|
||||
// Some overloaded virtual XMLVisitor members
|
||||
virtual void startXML ();
|
||||
virtual void endXML ();
|
||||
virtual void startElement (const char * name, const XMLAttributes &atts);
|
||||
virtual void endElement (const char * name);
|
||||
virtual void data (const char * s, int len);
|
||||
virtual void pi (const char * target, const char * data);
|
||||
virtual void warning (const char * message, int line, int column);
|
||||
virtual void error (const char * message, int line, int column);
|
||||
};
|
||||
|
||||
class FGParking {
|
||||
private:
|
||||
double latitude;
|
||||
double longitude;
|
||||
double heading;
|
||||
double radius;
|
||||
int index;
|
||||
string parkingName;
|
||||
string type;
|
||||
string airlineCodes;
|
||||
|
||||
|
||||
bool available;
|
||||
|
||||
double processPosition(string pos);
|
||||
|
||||
public:
|
||||
FGParking() { available = true;};
|
||||
//FGParking(FGParking &other);
|
||||
FGParking(double lat,
|
||||
double lon,
|
||||
double hdg,
|
||||
double rad,
|
||||
int idx,
|
||||
string name,
|
||||
string tpe,
|
||||
string codes);
|
||||
void setLatitude (string lat) { latitude = processPosition(lat); };
|
||||
void setLongitude(string lon) { longitude = processPosition(lon); };
|
||||
void setHeading (double hdg) { heading = hdg; };
|
||||
void setRadius (double rad) { radius = rad; };
|
||||
void setIndex (int idx) { index = idx; };
|
||||
void setName (string name) { parkingName = name; };
|
||||
void setType (string tpe) { type = tpe; };
|
||||
void setCodes (string codes){ airlineCodes= codes;};
|
||||
|
||||
bool isAvailable () { return available;};
|
||||
void setAvailable(bool val) { available = val; };
|
||||
|
||||
double getLatitude () { return latitude; };
|
||||
double getLongitude() { return longitude; };
|
||||
double getHeading () { return heading; };
|
||||
double getRadius () { return radius; };
|
||||
int getIndex () { return index; };
|
||||
string getType () { return type; };
|
||||
string getCodes () { return airlineCodes;};
|
||||
string getName () { return parkingName; };
|
||||
|
||||
bool operator< (const FGParking &other) const {return radius < other.radius; };
|
||||
};
|
||||
|
||||
typedef vector<FGParking> FGParkingVec;
|
||||
typedef vector<FGParking>::iterator FGParkingVecIterator;
|
||||
typedef vector<FGParking>::const_iterator FGParkingVecConstIterator;
|
||||
|
||||
|
||||
class FGAirport : public XMLVisitor{
|
||||
private:
|
||||
string _id;
|
||||
double _longitude;
|
||||
double _latitude;
|
||||
double _elevation;
|
||||
string _code; // depricated and can be removed
|
||||
string _name;
|
||||
bool _has_metar;
|
||||
FGParkingVec parkings;
|
||||
FGRunwayPreference rwyPrefs;
|
||||
|
||||
time_t lastUpdate;
|
||||
string prevTrafficType;
|
||||
stringVec landing;
|
||||
stringVec takeoff;
|
||||
|
||||
// Experimental keep a running average of wind dir and speed to prevent
|
||||
// Erratic runway changes.
|
||||
// Note: I should add these to the copy constructor and assigment operator to be
|
||||
// constistent
|
||||
double avWindHeading [10];
|
||||
double avWindSpeed [10];
|
||||
|
||||
public:
|
||||
FGAirport();
|
||||
FGAirport(const FGAirport &other);
|
||||
//operator= (FGAirport &other);
|
||||
FGAirport(string id, double lon, double lat, double elev, string name, bool has_metar);
|
||||
void getActiveRunway(string trafficType, int action, string *runway);
|
||||
void chooseRunwayFallback(string *runway);
|
||||
bool getAvailableParking(double *lat, double *lon, double *heading, int *gate, double rad, string fltype,
|
||||
string acType, string airline);
|
||||
void getParking (int id, double *lat, double* lon, double *heading);
|
||||
FGParking *getParking(int i); // { if (i < parkings.size()) return parkings[i]; else return 0;};
|
||||
void releaseParking(int id);
|
||||
string getParkingName(int i);
|
||||
const string getId() const { return _id;};
|
||||
const string &getName() const { return _name;};
|
||||
FGAirport *getAddress() { return this; };
|
||||
double getLongitude() { return _longitude;};
|
||||
double getLatitude() { return _latitude; };
|
||||
double getElevation() { return _elevation;};
|
||||
bool getMetar() { return _has_metar;};
|
||||
|
||||
|
||||
void setId(string id) { _id = id;};
|
||||
void setMetar(bool value) { _has_metar = value; };
|
||||
|
||||
void setRwyUse(FGRunwayPreference& ref);
|
||||
|
||||
// Some overloaded virtual XMLVisitor members
|
||||
virtual void startXML ();
|
||||
virtual void endXML ();
|
||||
virtual void startElement (const char * name, const XMLAttributes &atts);
|
||||
virtual void endElement (const char * name);
|
||||
virtual void data (const char * s, int len);
|
||||
virtual void pi (const char * target, const char * data);
|
||||
virtual void warning (const char * message, int line, int column);
|
||||
virtual void error (const char * message, int line, int column);
|
||||
};
|
||||
|
||||
typedef map < string, FGAirport > airport_map;
|
||||
|
@ -97,6 +331,8 @@ public:
|
|||
// return station id's marked as having metar data.
|
||||
FGAirport search( double lon_deg, double lat_deg, bool with_metar );
|
||||
|
||||
// search and return a pointer;
|
||||
FGAirport* search( const string& id, FGAirport *result);
|
||||
|
||||
/**
|
||||
* Return the number of airports in the list.
|
||||
|
|
|
@ -668,7 +668,7 @@ int NewWaypoint( string Tgt_Alt )
|
|||
|
||||
sprintf( NewTgtAirportId, "%s", TgtAptId.c_str() );
|
||||
|
||||
SGWayPoint wp( a._longitude, a._latitude, alt,
|
||||
SGWayPoint wp( a.getLongitude(), a.getLatitude(), alt,
|
||||
SGWayPoint::WGS84, TgtAptId );
|
||||
rm->add_waypoint( wp );
|
||||
|
||||
|
|
|
@ -399,11 +399,11 @@ FGMetarEnvironmentCtrl::init ()
|
|||
->search( longitude->getDoubleValue(),
|
||||
latitude->getDoubleValue(),
|
||||
true );
|
||||
FGMetarResult result = fetch_data( a._id );
|
||||
FGMetarResult result = fetch_data( a.getId() );
|
||||
if ( result.m != NULL ) {
|
||||
SG_LOG( SG_GENERAL, SG_INFO, "closest station w/ metar = " << a._id);
|
||||
SG_LOG( SG_GENERAL, SG_INFO, "closest station w/ metar = " << a.getId());
|
||||
last_apt = a;
|
||||
_icao = a._id;
|
||||
_icao = a.getId();
|
||||
search_elapsed = 0.0;
|
||||
fetch_elapsed = 0.0;
|
||||
update_metar_properties( result.m );
|
||||
|
@ -413,8 +413,8 @@ FGMetarEnvironmentCtrl::init ()
|
|||
} else {
|
||||
// mark as no metar so it doesn't show up in subsequent
|
||||
// searches.
|
||||
SG_LOG( SG_GENERAL, SG_INFO, "no metar at metar = " << a._id );
|
||||
globals->get_airports()->no_metar( a._id );
|
||||
SG_LOG( SG_GENERAL, SG_INFO, "no metar at metar = " << a.getId() );
|
||||
globals->get_airports()->no_metar( a.getId() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -456,13 +456,13 @@ FGMetarEnvironmentCtrl::update(double delta_time_sec)
|
|||
->search( longitude->getDoubleValue(),
|
||||
latitude->getDoubleValue(),
|
||||
true );
|
||||
if ( last_apt._id != a._id
|
||||
if ( last_apt.getId() != a.getId()
|
||||
|| fetch_elapsed > same_station_interval_sec )
|
||||
{
|
||||
SG_LOG( SG_GENERAL, SG_INFO, "closest station w/ metar = " << a._id);
|
||||
request_queue.push( a._id );
|
||||
SG_LOG( SG_GENERAL, SG_INFO, "closest station w/ metar = " << a.getId());
|
||||
request_queue.push( a.getId() );
|
||||
last_apt = a;
|
||||
_icao = a._id;
|
||||
_icao = a.getId();
|
||||
search_elapsed = 0.0;
|
||||
fetch_elapsed = 0.0;
|
||||
} else {
|
||||
|
@ -534,7 +534,7 @@ FGMetarEnvironmentCtrl::fetch_data( const string &icao )
|
|||
|
||||
// fetch station elevation if exists
|
||||
FGAirport a = globals->get_airports()->search( icao );
|
||||
station_elevation_ft = a._elevation;
|
||||
station_elevation_ft = a.getElevation();
|
||||
|
||||
// fetch current metar data
|
||||
try {
|
||||
|
|
|
@ -18,8 +18,8 @@ AirportList::AirportList (int x, int y, int width, int height)
|
|||
for (int i = 0; i < _nAirports; i++) {
|
||||
const FGAirport *airport = _airports->getAirport(i);
|
||||
snprintf(buf, 1023, "%s %s",
|
||||
airport->_id.c_str(),
|
||||
airport->_name.c_str());
|
||||
airport->getId().c_str(),
|
||||
airport->getName().c_str());
|
||||
|
||||
unsigned int buf_len = (strlen(buf) > 1023) ? 1023 : strlen(buf);
|
||||
|
||||
|
@ -43,7 +43,7 @@ AirportList::~AirportList ()
|
|||
char *
|
||||
AirportList::getListStringValue ()
|
||||
{
|
||||
return (char *)_airports->getAirport(getListIntegerValue())->_id.c_str();
|
||||
return (char *)_airports->getAirport(getListIntegerValue())->getId().c_str();
|
||||
}
|
||||
|
||||
// end of AirportList.cxx
|
||||
|
|
|
@ -22,4 +22,4 @@ layout_test_SOURCES = layout-test.cxx
|
|||
|
||||
layout_test_LDADD = libGUI.a \
|
||||
-lsgprops -lsgdebug -lsgstructure -lsgmisc -lsgxml \
|
||||
-lplibpw -lplibpu -lplibfnt -lplibul $(opengl_LIBS)
|
||||
-lplibpw -lplibpu -lplibfnt -lplibul $(opengl_LIBS)
|
||||
|
|
|
@ -325,12 +325,12 @@ GPS::update (double delta_time_sec)
|
|||
FGAirport a;
|
||||
//cout << "Airport found" << endl;
|
||||
a = globals->get_airports()->search(longitude_deg, latitude_deg, false);
|
||||
_wp1_ID_node->setStringValue(a._id.c_str());
|
||||
wp1_longitude_deg = a._longitude;
|
||||
wp1_latitude_deg = a._latitude;
|
||||
_wp1_name_node->setStringValue(a._name.c_str());
|
||||
_wp1_ID_node->setStringValue(a.getId().c_str());
|
||||
wp1_longitude_deg = a.getLongitude();
|
||||
wp1_latitude_deg = a.getLatitude();
|
||||
_wp1_name_node->setStringValue(a.getName().c_str());
|
||||
_get_nearest_airport_node->setBoolValue(false);
|
||||
_last_wp1_ID = wp1_ID = a._id.c_str();
|
||||
_last_wp1_ID = wp1_ID = a.getId().c_str();
|
||||
}
|
||||
|
||||
// If the waypoint 0 ID has changed, try to find the new ID
|
||||
|
@ -341,11 +341,11 @@ GPS::update (double delta_time_sec)
|
|||
if (waypont_type == "airport") {
|
||||
FGAirport a;
|
||||
a = globals->get_airports()->search( wp0_ID );
|
||||
if ( a._id == wp0_ID ) {
|
||||
if ( a.getId() == wp0_ID ) {
|
||||
//cout << "Airport found" << endl;
|
||||
wp0_longitude_deg = a._longitude;
|
||||
wp0_latitude_deg = a._latitude;
|
||||
_wp0_name_node->setStringValue(a._name.c_str());
|
||||
wp0_longitude_deg = a.getLongitude();
|
||||
wp0_latitude_deg = a.getLatitude();
|
||||
_wp0_name_node->setStringValue(a.getName().c_str());
|
||||
}
|
||||
}
|
||||
else if (waypont_type == "nav") {
|
||||
|
@ -380,11 +380,11 @@ GPS::update (double delta_time_sec)
|
|||
if (waypont_type == "airport") {
|
||||
FGAirport a;
|
||||
a = globals->get_airports()->search( wp1_ID );
|
||||
if ( a._id == wp1_ID ) {
|
||||
if ( a.getId() == wp1_ID ) {
|
||||
//cout << "Airport found" << endl;
|
||||
wp1_longitude_deg = a._longitude;
|
||||
wp1_latitude_deg = a._latitude;
|
||||
_wp1_name_node->setStringValue(a._name.c_str());
|
||||
wp1_longitude_deg = a.getLongitude();
|
||||
wp1_latitude_deg = a.getLatitude();
|
||||
_wp1_name_node->setStringValue(a.getName().c_str());
|
||||
}
|
||||
}
|
||||
else if (waypont_type == "nav") {
|
||||
|
|
|
@ -636,7 +636,7 @@ bool fgFindAirportID( const string& id, FGAirport *a ) {
|
|||
|
||||
result = globals->get_airports()->search( id );
|
||||
|
||||
if ( result._id.empty() ) {
|
||||
if ( result.getId().empty() ) {
|
||||
SG_LOG( SG_GENERAL, SG_ALERT,
|
||||
"Failed to find " << id << " in basic.dat.gz" );
|
||||
return false;
|
||||
|
@ -649,8 +649,8 @@ bool fgFindAirportID( const string& id, FGAirport *a ) {
|
|||
|
||||
SG_LOG( SG_GENERAL, SG_INFO,
|
||||
"Position for " << id << " is ("
|
||||
<< a->_longitude << ", "
|
||||
<< a->_latitude << ")" );
|
||||
<< a->getLongitude() << ", "
|
||||
<< a->getLatitude() << ")" );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -665,7 +665,7 @@ static double fgGetAirportElev( const string& id ) {
|
|||
"Finding elevation for airport: " << id );
|
||||
|
||||
if ( fgFindAirportID( id, &a ) ) {
|
||||
return a._elevation;
|
||||
return a.getElevation();
|
||||
} else {
|
||||
return -9999.0;
|
||||
}
|
||||
|
@ -718,9 +718,9 @@ static bool fgSetTowerPosFromAirportID( const string& id, double hdg ) {
|
|||
float fudge_lat = .003f - fudge_lon;
|
||||
|
||||
if ( fgFindAirportID( id, &a ) ) {
|
||||
fgSetDouble("/sim/tower/longitude-deg", a._longitude + fudge_lon);
|
||||
fgSetDouble("/sim/tower/latitude-deg", a._latitude + fudge_lat);
|
||||
fgSetDouble("/sim/tower/altitude-ft", a._elevation + towerheight);
|
||||
fgSetDouble("/sim/tower/longitude-deg", a.getLongitude() + fudge_lon);
|
||||
fgSetDouble("/sim/tower/latitude-deg", a.getLatitude() + fudge_lat);
|
||||
fgSetDouble("/sim/tower/altitude-ft", a.getElevation() + towerheight);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
|
@ -1715,11 +1715,11 @@ bool fgInitSubsystems() {
|
|||
globals->add_subsystem("Traffic Manager", new FGTrafficManager);
|
||||
FGTrafficManager *dispatcher =
|
||||
(FGTrafficManager*) globals->get_subsystem("Traffic Manager");
|
||||
SGPath path =globals->get_fg_root();
|
||||
path.append("Traffic/fgtraffic.xml");
|
||||
SGPath path = globals->get_fg_root();
|
||||
path.append("/Traffic/fgtraffic.xml");
|
||||
readXML(path.str(),
|
||||
*dispatcher);
|
||||
globals->get_subsystem("Traffic Manager")->init();
|
||||
*dispatcher);
|
||||
//globals->get_subsystem("Traffic Manager")->init();
|
||||
|
||||
globals->add_subsystem("instrumentation", new FGInstrumentMgr);
|
||||
globals->add_subsystem("systems", new FGSystemMgr);
|
||||
|
|
|
@ -96,8 +96,8 @@ bool fgNavDBInit( FGAirportList *airports,
|
|||
// cout << r->get_type() << " " << r->get_apt_id() << " zero elev"
|
||||
// << endl;
|
||||
FGAirport a = airports->search( r->get_apt_id() );
|
||||
if ( a._id == r->get_apt_id() ) {
|
||||
r->set_elev_ft( a._elevation );
|
||||
if ( a.getId() == r->get_apt_id() ) {
|
||||
r->set_elev_ft( a.getElevation() );
|
||||
// cout << " setting to " << a.elevation << endl;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -81,6 +81,8 @@ FGScheduledFlight::FGScheduledFlight(const FGScheduledFlight &other)
|
|||
callsign = other.callsign;
|
||||
fltRules = other.fltRules;
|
||||
departurePort = other.departurePort;
|
||||
depId = other.depId;
|
||||
arrId = other.arrId;
|
||||
departureTime = other.departureTime;
|
||||
cruiseAltitude = other.cruiseAltitude;
|
||||
arrivalPort = other.arrivalPort;
|
||||
|
@ -100,8 +102,11 @@ FGScheduledFlight::FGScheduledFlight(string cs,
|
|||
{
|
||||
callsign = cs;
|
||||
fltRules = fr;
|
||||
departurePort._id = depPrt;
|
||||
arrivalPort._id = arrPrt;
|
||||
//departurePort.setId(depPrt);
|
||||
//arrivalPort.setId(arrPrt);
|
||||
depId = depPrt;
|
||||
arrId = arrPrt;
|
||||
//cerr << "Constructor: departure " << depId << ". arrival " << arrId << endl;
|
||||
//departureTime = processTimeString(deptime);
|
||||
//arrivalTime = processTimeString(arrtime);
|
||||
cruiseAltitude = cruiseAlt;
|
||||
|
@ -225,7 +230,10 @@ FGAirport *FGScheduledFlight::getDepartureAirport()
|
|||
{
|
||||
initializeAirports();
|
||||
}
|
||||
return &departurePort;
|
||||
if (initialized)
|
||||
return departurePort;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
FGAirport * FGScheduledFlight::getArrivalAirport ()
|
||||
{
|
||||
|
@ -233,7 +241,10 @@ FGAirport * FGScheduledFlight::getArrivalAirport ()
|
|||
{
|
||||
initializeAirports();
|
||||
}
|
||||
return &arrivalPort;
|
||||
if (initialized)
|
||||
return arrivalPort;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Upon the first time of requesting airport information
|
||||
|
@ -243,15 +254,24 @@ FGAirport * FGScheduledFlight::getArrivalAirport ()
|
|||
// but we should improve that. The best idea is probably to cancel
|
||||
// this flight entirely by removing it from the schedule, if one
|
||||
// of the airports cannot be found.
|
||||
void FGScheduledFlight::initializeAirports()
|
||||
bool FGScheduledFlight::initializeAirports()
|
||||
{
|
||||
if(!(fgFindAirportID(arrivalPort._id, &arrivalPort )))
|
||||
//cerr << "Initializing using : " << depId << " " << arrId << endl;
|
||||
departurePort = globals->get_airports()->search( depId, departurePort );
|
||||
if(departurePort->getId().empty())
|
||||
{
|
||||
//cerr << ": Could not find " << arrivalPort.id << endl;
|
||||
cerr << "Could not find " << depId << endl;
|
||||
return false;
|
||||
}
|
||||
if(!(fgFindAirportID(departurePort._id, &departurePort)))
|
||||
arrivalPort = globals->get_airports()->search(arrId, arrivalPort);
|
||||
if(arrivalPort->getId().empty())
|
||||
{
|
||||
//cerr << ": Could not find " << departurePort.id << endl;
|
||||
cerr << "Could not find " << arrId << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
//cerr << "Found : " << departurePort->getId() << endl;
|
||||
//cerr << "Found : " << arrivalPort->getId() << endl;
|
||||
initialized = true;
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -51,15 +51,17 @@ class FGScheduledFlight
|
|||
private:
|
||||
string callsign;
|
||||
string fltRules;
|
||||
FGAirport departurePort;
|
||||
FGAirport arrivalPort;
|
||||
FGAirport *departurePort;
|
||||
FGAirport *arrivalPort;
|
||||
string depId;
|
||||
string arrId;
|
||||
time_t departureTime;
|
||||
time_t arrivalTime;
|
||||
time_t repeatPeriod;
|
||||
int cruiseAltitude;
|
||||
bool initialized;
|
||||
|
||||
void initializeAirports();
|
||||
|
||||
|
||||
public:
|
||||
FGScheduledFlight();
|
||||
|
@ -77,6 +79,7 @@ public:
|
|||
~FGScheduledFlight();
|
||||
|
||||
void update();
|
||||
bool initializeAirports();
|
||||
|
||||
void adjustTime(time_t now);
|
||||
|
||||
|
@ -94,7 +97,7 @@ public:
|
|||
};
|
||||
|
||||
time_t processTimeString(string time);
|
||||
|
||||
string getCallSign() {return callsign; };
|
||||
};
|
||||
|
||||
typedef vector<FGScheduledFlight> FGScheduledFlightVec;
|
||||
|
|
|
@ -65,11 +65,23 @@ FGAISchedule::FGAISchedule(string mdl,
|
|||
string liv,
|
||||
string reg,
|
||||
bool hvy,
|
||||
string act,
|
||||
string arln,
|
||||
string mclass,
|
||||
string fltpe,
|
||||
double rad,
|
||||
double grnd,
|
||||
FGScheduledFlightVec flt)
|
||||
{
|
||||
modelPath = mdl;
|
||||
livery = liv;
|
||||
registration = reg;
|
||||
acType = act;
|
||||
airline = arln;
|
||||
m_class = mclass;
|
||||
flightType = fltpe;
|
||||
radius = rad;
|
||||
groundOffset = grnd;
|
||||
heavy = hvy;
|
||||
for (FGScheduledFlightVecIterator i = flt.begin();
|
||||
i != flt.end();
|
||||
|
@ -89,15 +101,49 @@ FGAISchedule::FGAISchedule(const FGAISchedule &other)
|
|||
lat = other.lat;
|
||||
lon = other.lon;
|
||||
AIManagerRef = other.AIManagerRef;
|
||||
acType = other.acType;
|
||||
airline = other.airline;
|
||||
m_class = other.m_class;
|
||||
firstRun = other.firstRun;
|
||||
radius = other.radius;
|
||||
groundOffset = other.groundOffset;
|
||||
flightType = other.flightType;
|
||||
distanceToUser = other.distanceToUser;
|
||||
}
|
||||
|
||||
|
||||
FGAISchedule::~FGAISchedule()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void FGAISchedule::update(time_t now)
|
||||
bool FGAISchedule::init()
|
||||
{
|
||||
//tm targetTimeDate;
|
||||
//SGTime* currTimeDate = globals->get_time_params();
|
||||
|
||||
//tm *temp = currTimeDate->getGmt();
|
||||
//char buffer[512];
|
||||
//sgTimeFormatTime(&targetTimeDate, buffer);
|
||||
//cout << "Scheduled Time " << buffer << endl;
|
||||
//cout << "Time :" << time(NULL) << " SGTime : " << sgTimeGetGMT(temp) << endl;
|
||||
for (FGScheduledFlightVecIterator i = flights.begin();
|
||||
i != flights.end();
|
||||
i++)
|
||||
{
|
||||
//i->adjustTime(now);
|
||||
if (!(i->initializeAirports()))
|
||||
return false;
|
||||
}
|
||||
//sort(flights.begin(), flights.end());
|
||||
// Since time isn't initialized yet when this function is called,
|
||||
// Find the closest possible airport.
|
||||
// This should give a reasonable initialization order.
|
||||
setClosestDistanceToUser();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FGAISchedule::update(time_t now)
|
||||
{
|
||||
FGAirport *dep;
|
||||
FGAirport *arr;
|
||||
|
@ -110,7 +156,7 @@ void FGAISchedule::update(time_t now)
|
|||
string airport;
|
||||
|
||||
double courseToUser, courseToDest;
|
||||
double distanceToUser, distanceToDest;
|
||||
double distanceToDest;
|
||||
double speed;
|
||||
|
||||
Point3D temp;
|
||||
|
@ -123,7 +169,7 @@ void FGAISchedule::update(time_t now)
|
|||
userLongitude;
|
||||
|
||||
if (fgGetBool("/sim/traffic-manager/enabled") == false)
|
||||
return;
|
||||
return true;
|
||||
|
||||
aimgr = (FGAIManager *) globals-> get_subsystem("ai_model");
|
||||
// Before the flight status of this traffic entity is updated
|
||||
|
@ -142,11 +188,11 @@ void FGAISchedule::update(time_t now)
|
|||
if (firstRun)
|
||||
{
|
||||
for (FGScheduledFlightVecIterator i = flights.begin();
|
||||
i != flights.end();
|
||||
i++)
|
||||
{
|
||||
i->adjustTime(now);
|
||||
}
|
||||
i != flights.end();
|
||||
i++)
|
||||
{
|
||||
i->adjustTime(now);
|
||||
}
|
||||
firstRun = false;
|
||||
}
|
||||
|
||||
|
@ -168,13 +214,13 @@ void FGAISchedule::update(time_t now)
|
|||
userLatitude = fgGetDouble("/position/latitude-deg");
|
||||
userLongitude = fgGetDouble("/position/longitude-deg");
|
||||
|
||||
|
||||
//cerr << "Estimated minimum distance to user: " << distanceToUser << endl;
|
||||
// This flight entry is entirely in the past, do we need to
|
||||
// push it forward in time to the next scheduled departure.
|
||||
if ((i->getDepartureTime() < now) && (i->getArrivalTime() < now))
|
||||
{
|
||||
i->update();
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Departure time in the past and arrival time in the future.
|
||||
|
@ -189,19 +235,21 @@ void FGAISchedule::update(time_t now)
|
|||
{
|
||||
dep = i->getDepartureAirport();
|
||||
arr = i->getArrivalAirport ();
|
||||
if (!(dep && arr))
|
||||
return false;
|
||||
|
||||
temp = sgPolarToCart3d(Point3D(dep->_longitude *
|
||||
temp = sgPolarToCart3d(Point3D(dep->getLongitude() *
|
||||
SG_DEGREES_TO_RADIANS,
|
||||
dep->_latitude *
|
||||
dep->getLatitude() *
|
||||
SG_DEGREES_TO_RADIANS,
|
||||
1.0));
|
||||
a[0] = temp.x();
|
||||
a[1] = temp.y();
|
||||
a[2] = temp.z();
|
||||
|
||||
temp = sgPolarToCart3d(Point3D(arr->_longitude *
|
||||
temp = sgPolarToCart3d(Point3D(arr->getLongitude() *
|
||||
SG_DEGREES_TO_RADIANS,
|
||||
arr->_latitude *
|
||||
arr->getLatitude() *
|
||||
SG_DEGREES_TO_RADIANS,
|
||||
1.0));
|
||||
b[0] = temp.x();
|
||||
|
@ -219,9 +267,21 @@ void FGAISchedule::update(time_t now)
|
|||
// total time enroute and elapsed time enroute.
|
||||
|
||||
totalTimeEnroute = i->getArrivalTime() - i->getDepartureTime();
|
||||
elapsedTimeEnroute = now - i->getDepartureTime();
|
||||
remainingTimeEnroute = i->getArrivalTime() - now;
|
||||
|
||||
if (now > i->getDepartureTime())
|
||||
{
|
||||
//err << "Lat = " << lat << ", lon = " << lon << endl;
|
||||
//cerr << "Time diff: " << now-i->getDepartureTime() << endl;
|
||||
elapsedTimeEnroute = now - i->getDepartureTime();
|
||||
remainingTimeEnroute = i->getArrivalTime() - now;
|
||||
}
|
||||
else
|
||||
{
|
||||
lat = dep->getLatitude();
|
||||
lon = dep->getLongitude();
|
||||
elapsedTimeEnroute = 0;
|
||||
remainingTimeEnroute = totalTimeEnroute;
|
||||
}
|
||||
|
||||
angle *= ( (double) elapsedTimeEnroute/ (double) totalTimeEnroute);
|
||||
|
||||
|
||||
|
@ -236,32 +296,30 @@ void FGAISchedule::update(time_t now)
|
|||
newPos[j] += matrix[j][k]*a[k];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
temp = sgCartToPolar3d(Point3D(newPos[0], newPos[1],newPos[2]));
|
||||
|
||||
if (now > i->getDepartureTime())
|
||||
{
|
||||
//cerr << "Lat = " << lat << ", lon = " << lon << endl;
|
||||
//cerr << "Time diff: " << now-i->getDepartureTime() << endl;
|
||||
lat = temp.lat() * SG_RADIANS_TO_DEGREES;
|
||||
lon = temp.lon() * SG_RADIANS_TO_DEGREES;
|
||||
//err << "Lat = " << lat << ", lon = " << lon << endl;
|
||||
//cerr << "Time diff: " << now-i->getDepartureTime() << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
lat = dep->_latitude;
|
||||
lon = dep->_longitude;
|
||||
lat = dep->getLatitude();
|
||||
lon = dep->getLongitude();
|
||||
}
|
||||
|
||||
|
||||
SGWayPoint current (lon,
|
||||
lat,
|
||||
i->getCruiseAlt());
|
||||
SGWayPoint user ( userLongitude,
|
||||
userLatitude,
|
||||
i->getCruiseAlt());
|
||||
SGWayPoint dest ( arr->_longitude,
|
||||
arr->_latitude,
|
||||
SGWayPoint dest ( arr->getLongitude(),
|
||||
arr->getLatitude(),
|
||||
i->getCruiseAlt());
|
||||
// We really only need distance to user
|
||||
// and course to destination
|
||||
|
@ -278,9 +336,9 @@ void FGAISchedule::update(time_t now)
|
|||
//cerr << registration << " is currently enroute from "
|
||||
// << dep->_id << " to " << arr->_id << "distance : "
|
||||
// << distanceToUser*SG_METER_TO_NM << endl;
|
||||
if ((distanceToUser*SG_METER_TO_NM) < 500.0)
|
||||
if ((distanceToUser*SG_METER_TO_NM) < TRAFFICTOAIDIST)
|
||||
{
|
||||
string flightPlanName = dep->_id + string("-") + arr->_id +
|
||||
string flightPlanName = dep->getId() + string("-") + arr->getId() +
|
||||
string(".xml");
|
||||
int alt;
|
||||
//if ((i->getDepartureTime() < now))
|
||||
|
@ -294,32 +352,43 @@ void FGAISchedule::update(time_t now)
|
|||
|
||||
FGAIModelEntity entity;
|
||||
|
||||
entity.m_class = "jet_transport";
|
||||
entity.m_class = m_class; //"jet_transport";
|
||||
entity.company = airline; //i->getAirline();
|
||||
entity.acType = acType; //i->getAcType();
|
||||
entity.path = modelPath.c_str();
|
||||
entity.flightplan = flightPlanName.c_str();
|
||||
entity.latitude = lat;
|
||||
entity.longitude = lon;
|
||||
entity.altitude = i->getCruiseAlt() *100; // convert from FL to feet
|
||||
entity.speed = 450;
|
||||
entity.fp = new FGAIFlightPlan(&entity, courseToDest, i->getDepartureTime(), dep, arr);
|
||||
|
||||
entity.speed = speed;
|
||||
entity.roll = 0.0;
|
||||
entity.fp = new FGAIFlightPlan(&entity, courseToDest, i->getDepartureTime(), dep,
|
||||
arr,true, radius, flightType, acType, airline);
|
||||
|
||||
// Fixme: A non-existent model path results in an
|
||||
// abort, due to an unhandled exeption, in fg main loop.
|
||||
AIManagerRef = aimgr->createAircraft( &entity, this);
|
||||
//cerr << "Created: " << AIManagerRef << endl;
|
||||
//cerr << "Class: " << m_class << ". acType: " << acType << ". Airline: " << airline << ". Speed = " << speed << ". From " << dep->getId() << " to " << arr->getId() << ". Time Fraction = " << (remainingTimeEnroute/(double) totalTimeEnroute) << endl;
|
||||
//cerr << "Latitude : " << lat << ". Longitude : " << lon << endl;
|
||||
//cerr << "Dep : " << dep->getLatitude()<< ", "<< dep->getLongitude() << endl;
|
||||
//cerr << "Arr : " << arr->getLatitude()<< ", "<< arr->getLongitude() << endl;
|
||||
//cerr << "Time remaining = " << (remainingTimeEnroute/3600.0) << endl;
|
||||
//cerr << "Total time = " << (totalTimeEnroute/3600.0) << endl;
|
||||
//cerr << "Distance remaining = " << distanceToDest*SG_METER_TO_NM << endl;
|
||||
|
||||
}
|
||||
return;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Both departure and arrival time are in the future, so this
|
||||
// the aircraft is parked at the departure airport.
|
||||
// Currently this status is mostly ignored, but in future
|
||||
// versions, code should go here that -if within user range-
|
||||
// positions these aircraft at parking locations at the airport.
|
||||
if ((i->getDepartureTime() > now) && (i->getArrivalTime() > now))
|
||||
if ((i->getDepartureTime() > now) && (i->getArrivalTime() > now))
|
||||
{
|
||||
dep = i->getDepartureAirport();
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -331,3 +400,71 @@ void FGAISchedule::next()
|
|||
sort(flights.begin(), flights.end());
|
||||
}
|
||||
|
||||
double FGAISchedule::getSpeed()
|
||||
{
|
||||
double courseToUser, courseToDest;
|
||||
double distanceToUser, distanceToDest;
|
||||
double speed, remainingTimeEnroute;
|
||||
FGAirport *dep, *arr;
|
||||
|
||||
FGScheduledFlightVecIterator i = flights.begin();
|
||||
dep = i->getDepartureAirport();
|
||||
arr = i->getArrivalAirport ();
|
||||
if (!(dep && arr))
|
||||
return 0;
|
||||
|
||||
SGWayPoint dest ( dep->getLongitude(),
|
||||
dep->getLatitude(),
|
||||
i->getCruiseAlt());
|
||||
SGWayPoint curr ( arr->getLongitude(),
|
||||
arr->getLatitude(),
|
||||
i->getCruiseAlt());
|
||||
remainingTimeEnroute = i->getArrivalTime() - i->getDepartureTime();
|
||||
dest.CourseAndDistance(curr, &courseToDest, &distanceToDest);
|
||||
speed = (distanceToDest*SG_METER_TO_NM) /
|
||||
((double) remainingTimeEnroute/3600.0);
|
||||
return speed;
|
||||
}
|
||||
|
||||
|
||||
void FGAISchedule::setClosestDistanceToUser()
|
||||
{
|
||||
|
||||
|
||||
double course;
|
||||
double dist;
|
||||
|
||||
Point3D temp;
|
||||
time_t
|
||||
totalTimeEnroute,
|
||||
elapsedTimeEnroute;
|
||||
|
||||
double userLatitude = fgGetDouble("/position/latitude-deg");
|
||||
double userLongitude = fgGetDouble("/position/longitude-deg");
|
||||
|
||||
FGAirport *dep;
|
||||
|
||||
distanceToUser = HUGE;
|
||||
FGScheduledFlightVecIterator i = flights.begin();
|
||||
while (i != flights.end())
|
||||
{
|
||||
dep = i->getDepartureAirport();
|
||||
//if (!(dep))
|
||||
//return HUGE;
|
||||
|
||||
SGWayPoint user ( userLongitude,
|
||||
userLatitude,
|
||||
i->getCruiseAlt());
|
||||
SGWayPoint current (dep->getLongitude(),
|
||||
dep->getLatitude(),
|
||||
0);
|
||||
user.CourseAndDistance(current, &course, &dist);
|
||||
if (dist < distanceToUser)
|
||||
{
|
||||
distanceToUser = dist;
|
||||
//cerr << "Found closest distance to user for " << registration << " to be " << distanceToUser << " at airport " << dep->getId() << endl;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
//return distToUser;
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#ifndef _FGSCHEDULE_HXX_
|
||||
#define _FGSCHEDULE_HXX_
|
||||
|
||||
#define TRAFFICTOAIDIST 150.0
|
||||
|
||||
|
||||
class FGAISchedule
|
||||
|
@ -37,34 +38,56 @@ class FGAISchedule
|
|||
string modelPath;
|
||||
string livery;
|
||||
string registration;
|
||||
string airline;
|
||||
string acType;
|
||||
string m_class;
|
||||
string flightType;
|
||||
bool heavy;
|
||||
FGScheduledFlightVec flights;
|
||||
float lat;
|
||||
float lon;
|
||||
double radius;
|
||||
double groundOffset;
|
||||
double distanceToUser;
|
||||
void* AIManagerRef;
|
||||
bool firstRun;
|
||||
|
||||
|
||||
public:
|
||||
FGAISchedule(); // constructor
|
||||
FGAISchedule(string, string, string, bool, FGScheduledFlightVec); // construct & init
|
||||
FGAISchedule(string, string, string, bool, string, string, string, string, double, double, FGScheduledFlightVec); // construct & init
|
||||
FGAISchedule(const FGAISchedule &other); // copy constructor
|
||||
|
||||
~FGAISchedule(); //destructor
|
||||
|
||||
void update(time_t now);
|
||||
bool update(time_t now);
|
||||
bool init();
|
||||
|
||||
double getSpeed ();
|
||||
void setClosestDistanceToUser();
|
||||
void next(); // forces the schedule to move on to the next flight.
|
||||
|
||||
time_t getDepartureTime () { return flights.begin()->getDepartureTime (); };
|
||||
FGAirport * getDepartureAirport () { return flights.begin()->getDepartureAirport(); };
|
||||
FGAirport * getArrivalAirport () { return flights.begin()->getArrivalAirport (); };
|
||||
int getCruiseAlt () { return flights.begin()->getCruiseAlt (); };
|
||||
double getRadius () { return radius; };
|
||||
double getGroundOffset () { return groundOffset;};
|
||||
string getFlightType () { return flightType;};
|
||||
string getAirline () { return airline; };
|
||||
string getAircraft () { return acType; };
|
||||
string getCallSign () { return flights.begin()->getCallSign (); };
|
||||
string getRegistration () { return registration;};
|
||||
bool getHeavy () { return heavy; };
|
||||
bool operator< (const FGAISchedule &other) const { return (distanceToUser < other.distanceToUser); };
|
||||
//void * getAiRef () { return AIManagerRef; };
|
||||
//FGAISchedule* getAddress () { return this;};
|
||||
// More member functions follow later
|
||||
|
||||
};
|
||||
|
||||
typedef vector<FGAISchedule> ScheduleVector;
|
||||
typedef vector<FGAISchedule>::iterator ScheduleVectorIterator;
|
||||
typedef vector<FGAISchedule > ScheduleVector;
|
||||
typedef vector<FGAISchedule >::iterator ScheduleVectorIterator;
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
#include <simgear/structure/subsystem_mgr.hxx>
|
||||
#include <simgear/xml/easyxml.hxx>
|
||||
|
||||
#include <AIModel/AIAircraft.hxx>
|
||||
#include <AIModel/AIFlightPlan.hxx>
|
||||
#include <AIModel/AIBase.hxx>
|
||||
#include <Airports/simple.hxx>
|
||||
|
@ -72,22 +73,45 @@ FGTrafficManager::FGTrafficManager()
|
|||
|
||||
|
||||
void FGTrafficManager::init()
|
||||
{
|
||||
{
|
||||
//cerr << "Initializing Schedules" << endl;
|
||||
time_t now = time(NULL) + fgGetLong("/sim/time/warp");
|
||||
currAircraft = scheduledAircraft.begin();
|
||||
while (currAircraft != scheduledAircraft.end())
|
||||
{
|
||||
if (!(currAircraft->init()))
|
||||
{
|
||||
currAircraft=scheduledAircraft.erase(currAircraft);
|
||||
//cerr << "Erasing " << currAircraft->getRegistration() << endl;
|
||||
currAircraft--;
|
||||
}
|
||||
else
|
||||
{
|
||||
currAircraft++;
|
||||
}
|
||||
}
|
||||
//cerr << "Sorting by distance " << endl;
|
||||
sort(scheduledAircraft.begin(), scheduledAircraft.end());
|
||||
currAircraft = scheduledAircraft.begin();
|
||||
currAircraftClosest = scheduledAircraft.begin();
|
||||
//cerr << "Done initializing schedules" << endl;
|
||||
}
|
||||
|
||||
void FGTrafficManager::update(double something)
|
||||
{
|
||||
|
||||
//static const SGPropertyNode *warp = globals->get_props()->getNode("/sim/time/warp");
|
||||
|
||||
//time_t now = time(NULL) + globals->get_warp();
|
||||
time_t now = time(NULL) + fgGetLong("/sim/time/warp");
|
||||
// cerr << "TrafficManager update" << globals->get_warp() << endl;
|
||||
if(currAircraft == scheduledAircraft.end())
|
||||
if(currAircraft == scheduledAircraft.end())
|
||||
{
|
||||
//cerr << "resetting schedule " << endl;
|
||||
currAircraft = scheduledAircraft.begin();
|
||||
currAircraft->update(now);
|
||||
currAircraft++;
|
||||
}
|
||||
if (!(currAircraft->update(now)))
|
||||
{
|
||||
// after proper initialization, we shouldnt get here.
|
||||
// But let's make sure
|
||||
cerr << "Failed to update aircraft schedule in traffic manager" << endl;
|
||||
}
|
||||
currAircraft++;
|
||||
}
|
||||
|
||||
void FGTrafficManager::release(void *id)
|
||||
|
@ -146,6 +170,18 @@ void FGTrafficManager::endElement (const char * name) {
|
|||
livery = value;
|
||||
else if (element == string("registration"))
|
||||
registration = value;
|
||||
else if (element == string("airline"))
|
||||
airline = value;
|
||||
else if (element == string("actype"))
|
||||
acType = value;
|
||||
else if (element == string("flighttype"))
|
||||
flighttype = value;
|
||||
else if (element == string("radius"))
|
||||
radius = atoi(value.c_str());
|
||||
else if (element == string("offset"))
|
||||
offset = atoi(value.c_str());
|
||||
else if (element == string("performance-class"))
|
||||
m_class = value;
|
||||
else if (element == string("heavy"))
|
||||
{
|
||||
if(value == string("true"))
|
||||
|
@ -195,10 +231,16 @@ void FGTrafficManager::endElement (const char * name) {
|
|||
{
|
||||
//cerr << "Pushing back aircraft " << registration << endl;
|
||||
scheduledAircraft.push_back(FGAISchedule(mdl,
|
||||
livery,
|
||||
registration,
|
||||
heavy,
|
||||
flights));
|
||||
livery,
|
||||
registration,
|
||||
heavy,
|
||||
acType,
|
||||
airline,
|
||||
m_class,
|
||||
flighttype,
|
||||
radius,
|
||||
offset,
|
||||
flights));
|
||||
while(flights.begin() != flights.end())
|
||||
flights.pop_back();
|
||||
}
|
||||
|
|
|
@ -42,13 +42,14 @@ class FGTrafficManager : public SGSubsystem, public XMLVisitor
|
|||
{
|
||||
private:
|
||||
ScheduleVector scheduledAircraft;
|
||||
ScheduleVectorIterator currAircraft;
|
||||
ScheduleVectorIterator currAircraft, currAircraftClosest;
|
||||
string value;
|
||||
|
||||
string mdl, livery, registration, callsign, fltrules,
|
||||
port, timeString, departurePort, departureTime, arrivalPort, arrivalTime,
|
||||
repeat;
|
||||
repeat, acType, airline, m_class, flighttype;
|
||||
int cruiseAlt;
|
||||
double radius, offset;
|
||||
bool heavy;
|
||||
|
||||
IdList releaseList;
|
||||
|
|
Loading…
Reference in a new issue