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