AI
* Parking on parking with right heading * Leg 6 Descent improved (teardrop like entry) * Inner/Outer tangents in VectorMath TODO Move to SG
This commit is contained in:
parent
3ee54cbd72
commit
e85e5d2e5b
13 changed files with 611 additions and 266 deletions
|
@ -333,7 +333,9 @@ void FGAIAircraft::ProcessFlightPlan( double dt, time_t now ) {
|
||||||
dt_count = 0;
|
dt_count = 0;
|
||||||
|
|
||||||
double distanceToDescent;
|
double distanceToDescent;
|
||||||
if (reachedEndOfCruise(distanceToDescent)) {
|
// Not the best solution. Double adding of legs is possible
|
||||||
|
if (*fp->getLastWayPoint() == fp->getNextWaypoint() &&
|
||||||
|
reachedEndOfCruise(distanceToDescent)) {
|
||||||
if (!loadNextLeg(distanceToDescent)) {
|
if (!loadNextLeg(distanceToDescent)) {
|
||||||
setDie(true);
|
setDie(true);
|
||||||
return;
|
return;
|
||||||
|
@ -591,7 +593,6 @@ bool FGAIAircraft::loadNextLeg(double distance) {
|
||||||
FGAirport *arr = trafficRef->getArrivalAirport();
|
FGAirport *arr = trafficRef->getArrivalAirport();
|
||||||
if (!(dep && arr)) {
|
if (!(dep && arr)) {
|
||||||
setDie(true);
|
setDie(true);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
double cruiseAlt = trafficRef->getCruiseAlt() * 100;
|
double cruiseAlt = trafficRef->getCruiseAlt() * 100;
|
||||||
|
|
||||||
|
@ -1473,7 +1474,7 @@ bool FGAIAircraft::reachedEndOfCruise(double &distance) {
|
||||||
|
|
||||||
distance = distanceCoveredByDescent;
|
distance = distanceCoveredByDescent;
|
||||||
if (dist < distanceCoveredByDescent) {
|
if (dist < distanceCoveredByDescent) {
|
||||||
SG_LOG(SG_AI, SG_BULK, "End Of Cruise");
|
SG_LOG(SG_AI, SG_BULK, getCallSign() << "|End Of Cruise");
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -131,16 +131,19 @@ FGAIFlightPlan::FGAIFlightPlan(const string& filename) :
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// This is a modified version of the constructor,
|
/**
|
||||||
// Which not only reads the waypoints from a
|
* This is a modified version of the constructor,
|
||||||
// Flight plan file, but also adds the current
|
* Which not only reads the waypoints from a
|
||||||
// Position computed by the traffic manager, as well
|
* Flight plan file, but also adds the current
|
||||||
// as setting speeds and altitude computed by the
|
* Position computed by the traffic manager, as well
|
||||||
// traffic manager.
|
* as setting speeds and altitude computed by the
|
||||||
|
* traffic manager.
|
||||||
|
*/
|
||||||
FGAIFlightPlan::FGAIFlightPlan(FGAIAircraft *ac,
|
FGAIFlightPlan::FGAIFlightPlan(FGAIAircraft *ac,
|
||||||
const std::string& p,
|
const std::string& p,
|
||||||
double course,
|
double course,
|
||||||
time_t start,
|
time_t start,
|
||||||
|
time_t remainingTime,
|
||||||
FGAirport *dep,
|
FGAirport *dep,
|
||||||
FGAirport *arr,
|
FGAirport *arr,
|
||||||
bool firstLeg,
|
bool firstLeg,
|
||||||
|
@ -168,7 +171,7 @@ FGAIFlightPlan::FGAIFlightPlan(FGAIAircraft *ac,
|
||||||
if (parseProperties(p)) {
|
if (parseProperties(p)) {
|
||||||
isValid = true;
|
isValid = true;
|
||||||
} else {
|
} else {
|
||||||
createWaypoints(ac, course, start, dep, arr, firstLeg, radius,
|
createWaypoints(ac, course, start, remainingTime, dep, arr, firstLeg, radius,
|
||||||
alt, lat, lon, speed, fltType, acType, airline);
|
alt, lat, lon, speed, fltType, acType, airline);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -182,6 +185,7 @@ FGAIFlightPlan::~FGAIFlightPlan()
|
||||||
void FGAIFlightPlan::createWaypoints(FGAIAircraft *ac,
|
void FGAIFlightPlan::createWaypoints(FGAIAircraft *ac,
|
||||||
double course,
|
double course,
|
||||||
time_t start,
|
time_t start,
|
||||||
|
time_t remainingTime,
|
||||||
FGAirport *dep,
|
FGAirport *dep,
|
||||||
FGAirport *arr,
|
FGAirport *arr,
|
||||||
bool firstLeg,
|
bool firstLeg,
|
||||||
|
@ -196,25 +200,22 @@ void FGAIFlightPlan::createWaypoints(FGAIAircraft *ac,
|
||||||
{
|
{
|
||||||
time_t now = globals->get_time_params()->get_cur_time();
|
time_t now = globals->get_time_params()->get_cur_time();
|
||||||
time_t timeDiff = now-start;
|
time_t timeDiff = now-start;
|
||||||
leg = 1;
|
leg = AILeg::STARTUP_PUSHBACK;
|
||||||
|
|
||||||
if ((timeDiff > 60) && (timeDiff < 1500))
|
if ((timeDiff > 60) && (timeDiff < 1500))
|
||||||
leg = 2;
|
leg = AILeg::TAXI;
|
||||||
//else if ((timeDiff >= 1200) && (timeDiff < 1500)) {
|
|
||||||
//leg = 3;
|
|
||||||
//ac->setTakeOffStatus(2);
|
|
||||||
//}
|
|
||||||
else if ((timeDiff >= 1500) && (timeDiff < 2000))
|
else if ((timeDiff >= 1500) && (timeDiff < 2000))
|
||||||
leg = 4;
|
leg = AILeg::TAKEOFF;
|
||||||
else if (timeDiff >= 2000)
|
else if (timeDiff >= 2000) {
|
||||||
leg = 5;
|
if (remainingTime > 2000) {
|
||||||
/*
|
leg = AILeg::CRUISE;
|
||||||
if (timeDiff >= 2000)
|
} else {
|
||||||
leg = 5;
|
leg = AILeg::APPROACH;
|
||||||
*/
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SG_LOG(SG_AI, SG_DEBUG, "Route from " << dep->getId() << " to " << arr->getId() <<
|
SG_LOG(SG_AI, SG_DEBUG, ac->getTrafficRef()->getCallSign() << "|Route from " << dep->getId() << " to " << arr->getId() <<
|
||||||
". Set leg to : " << leg << " " << ac->getTrafficRef()->getCallSign());
|
". Set leg to : " << leg << " " << remainingTime);
|
||||||
|
|
||||||
wpt_iterator = waypoints.begin();
|
wpt_iterator = waypoints.begin();
|
||||||
bool dist = 0;
|
bool dist = 0;
|
||||||
|
@ -392,6 +393,8 @@ void FGAIFlightPlan::IncrementWaypoint(bool eraseWaypoints )
|
||||||
return;
|
return;
|
||||||
if (wpt_iterator+1 == waypoints.end())
|
if (wpt_iterator+1 == waypoints.end())
|
||||||
return;
|
return;
|
||||||
|
if (waypoints.size()<3)
|
||||||
|
return;
|
||||||
FGAIWaypoint* previousWP = *(wpt_iterator -1);
|
FGAIWaypoint* previousWP = *(wpt_iterator -1);
|
||||||
FGAIWaypoint* currentWP = *(wpt_iterator);
|
FGAIWaypoint* currentWP = *(wpt_iterator);
|
||||||
FGAIWaypoint* nextWP = *(wpt_iterator + 1);
|
FGAIWaypoint* nextWP = *(wpt_iterator + 1);
|
||||||
|
|
|
@ -137,6 +137,7 @@ public:
|
||||||
const std::string& p,
|
const std::string& p,
|
||||||
double course,
|
double course,
|
||||||
time_t start,
|
time_t start,
|
||||||
|
time_t remainingTime,
|
||||||
FGAirport *dep,
|
FGAirport *dep,
|
||||||
FGAirport *arr,
|
FGAirport *arr,
|
||||||
bool firstLeg,
|
bool firstLeg,
|
||||||
|
@ -276,7 +277,7 @@ private:
|
||||||
|
|
||||||
/**Create an arc flightplan around a center from startAngle to endAngle.*/
|
/**Create an arc flightplan around a center from startAngle to endAngle.*/
|
||||||
void createArc(FGAIAircraft *ac, const SGGeod& center, int startAngle, int endAngle, int increment, int radius, double aElev, double aSpeed, const char* pattern);
|
void createArc(FGAIAircraft *ac, const SGGeod& center, int startAngle, int endAngle, int increment, int radius, double aElev, double aSpeed, const char* pattern);
|
||||||
void createLine(FGAIAircraft *ac, const SGGeod& startPoint, double azimuth, double dist, double dAlt, double vDescent);
|
void createLine(FGAIAircraft *ac, const SGGeod& startPoint, double azimuth, double dist, double dAlt, double vDescent, const char* pattern);
|
||||||
bool createLandingTaxi(FGAIAircraft *, FGAirport *apt, double radius, const std::string& fltType, const std::string& acType, const std::string& airline);
|
bool createLandingTaxi(FGAIAircraft *, FGAirport *apt, double radius, const std::string& fltType, const std::string& acType, const std::string& airline);
|
||||||
void createDefaultLandingTaxi(FGAIAircraft *, FGAirport* aAirport);
|
void createDefaultLandingTaxi(FGAIAircraft *, FGAirport* aAirport);
|
||||||
void createDefaultTakeoffTaxi(FGAIAircraft *, FGAirport* aAirport, FGRunway* aRunway);
|
void createDefaultTakeoffTaxi(FGAIAircraft *, FGAirport* aAirport, FGRunway* aRunway);
|
||||||
|
@ -300,9 +301,14 @@ private:
|
||||||
*/
|
*/
|
||||||
bool parseProperties(const std::string& filename);
|
bool parseProperties(const std::string& filename);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the waypoints for this Flightplan.
|
||||||
|
*/
|
||||||
|
|
||||||
void createWaypoints(FGAIAircraft *ac,
|
void createWaypoints(FGAIAircraft *ac,
|
||||||
double course,
|
double course,
|
||||||
time_t start,
|
time_t start,
|
||||||
|
time_t remainingTime,
|
||||||
FGAirport *dep,
|
FGAirport *dep,
|
||||||
FGAirport *arr,
|
FGAirport *arr,
|
||||||
bool firstLeg,
|
bool firstLeg,
|
||||||
|
|
|
@ -69,9 +69,9 @@ bool FGAIFlightPlan::create(FGAIAircraft * ac, FGAirport * dep,
|
||||||
const string & aircraftType,
|
const string & aircraftType,
|
||||||
const string & airline, double distance)
|
const string & airline, double distance)
|
||||||
{
|
{
|
||||||
if( legNr <= 3 )
|
if( legNr <= AILeg::TAKEOFF )
|
||||||
SG_LOG(SG_AI, SG_BULK, "Create Leg " << legNr << " " << (firstFlight?"First":"") << " Old Leg " << getLeg() << " At Airport : " << dep->getId());
|
SG_LOG(SG_AI, SG_BULK, "Create Leg " << legNr << " " << (firstFlight?"First":"") << " Old Leg " << getLeg() << " At Airport : " << dep->getId());
|
||||||
else if( legNr<= 6 )
|
else if( legNr<= AILeg::APPROACH )
|
||||||
SG_LOG(SG_AI, SG_BULK, "Create Leg " << legNr << " " << (firstFlight?"First":"") << " Old Leg " << getLeg() << " Departure Airport : " << dep->getId() << " Arrival Airport : " << arr->getId());
|
SG_LOG(SG_AI, SG_BULK, "Create Leg " << legNr << " " << (firstFlight?"First":"") << " Old Leg " << getLeg() << " Departure Airport : " << dep->getId() << " Arrival Airport : " << arr->getId());
|
||||||
else
|
else
|
||||||
SG_LOG(SG_AI, SG_BULK, "Create Leg " << legNr << " " << (firstFlight?"First":"") << " Old Leg " << getLeg() << " At Airport : " << arr->getId());
|
SG_LOG(SG_AI, SG_BULK, "Create Leg " << legNr << " " << (firstFlight?"First":"") << " Old Leg " << getLeg() << " At Airport : " << arr->getId());
|
||||||
|
@ -79,35 +79,35 @@ bool FGAIFlightPlan::create(FGAIAircraft * ac, FGAirport * dep,
|
||||||
bool retVal = true;
|
bool retVal = true;
|
||||||
int currWpt = wpt_iterator - waypoints.begin();
|
int currWpt = wpt_iterator - waypoints.begin();
|
||||||
switch (legNr) {
|
switch (legNr) {
|
||||||
case 1:
|
case AILeg::STARTUP_PUSHBACK:
|
||||||
retVal = createPushBack(ac, firstFlight, dep,
|
retVal = createPushBack(ac, firstFlight, dep,
|
||||||
radius, fltType, aircraftType, airline);
|
radius, fltType, aircraftType, airline);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case AILeg::TAXI:
|
||||||
retVal = createTakeoffTaxi(ac, firstFlight, dep, radius, fltType,
|
retVal = createTakeoffTaxi(ac, firstFlight, dep, radius, fltType,
|
||||||
aircraftType, airline);
|
aircraftType, airline);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case AILeg::TAKEOFF:
|
||||||
retVal = createTakeOff(ac, firstFlight, dep, SGGeod::fromDeg(longitude, latitude), speed, fltType);
|
retVal = createTakeOff(ac, firstFlight, dep, SGGeod::fromDeg(longitude, latitude), speed, fltType);
|
||||||
break;
|
break;
|
||||||
case 4:
|
case AILeg::CLIMB:
|
||||||
retVal = createClimb(ac, firstFlight, dep, arr, speed, alt, fltType);
|
retVal = createClimb(ac, firstFlight, dep, arr, speed, alt, fltType);
|
||||||
break;
|
break;
|
||||||
case 5:
|
case AILeg::CRUISE:
|
||||||
retVal = createCruise(ac, firstFlight, dep, arr, SGGeod::fromDeg(longitude, latitude), speed,
|
retVal = createCruise(ac, firstFlight, dep, arr, SGGeod::fromDeg(longitude, latitude), speed,
|
||||||
alt, fltType);
|
alt, fltType);
|
||||||
break;
|
break;
|
||||||
case 6:
|
case AILeg::APPROACH:
|
||||||
retVal = createDescent(ac, arr, SGGeod::fromDeg(longitude, latitude), speed, alt, fltType,
|
retVal = createDescent(ac, arr, SGGeod::fromDeg(longitude, latitude), speed, alt, fltType,
|
||||||
distance);
|
distance);
|
||||||
break;
|
break;
|
||||||
case 7:
|
case AILeg::LANDING:
|
||||||
retVal = createLanding(ac, arr, fltType);
|
retVal = createLanding(ac, arr, fltType);
|
||||||
break;
|
break;
|
||||||
case 8:
|
case AILeg::PARKING_TAXI:
|
||||||
retVal = createLandingTaxi(ac, arr, radius, fltType, aircraftType, airline);
|
retVal = createLandingTaxi(ac, arr, radius, fltType, aircraftType, airline);
|
||||||
break;
|
break;
|
||||||
case 9:
|
case AILeg::PARKING:
|
||||||
retVal = createParking(ac, arr, radius);
|
retVal = createParking(ac, arr, radius);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -202,7 +202,7 @@ int endAngle, int increment, int radius, double aElev, double aSpeed, const char
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FGAIFlightPlan::createLine( FGAIAircraft *ac, const SGGeod& startPoint, double azimuth, double dist, double dAlt, double vDescent) {
|
void FGAIFlightPlan::createLine( FGAIAircraft *ac, const SGGeod& startPoint, double azimuth, double dist, double dAlt, double vDescent, const char* pattern) {
|
||||||
SGGeod dummyAz2;
|
SGGeod dummyAz2;
|
||||||
double nPoints = dist/(vDescent/2);
|
double nPoints = dist/(vDescent/2);
|
||||||
char buffer[20];
|
char buffer[20];
|
||||||
|
@ -211,7 +211,7 @@ void FGAIFlightPlan::createLine( FGAIAircraft *ac, const SGGeod& startPoint, dou
|
||||||
double currentDist = i * (dist / nPoints);
|
double currentDist = i * (dist / nPoints);
|
||||||
double currentAltitude = ac->getAltitude() - (i * (dAlt / nPoints));
|
double currentAltitude = ac->getAltitude() - (i * (dAlt / nPoints));
|
||||||
SGGeod result = SGGeodesy::direct(startPoint, azimuth, currentDist);
|
SGGeod result = SGGeodesy::direct(startPoint, azimuth, currentDist);
|
||||||
snprintf(buffer, sizeof(buffer), "descent%03d", i);
|
snprintf(buffer, sizeof(buffer), pattern, i);
|
||||||
FGAIWaypoint* wpt = createInAir(ac, buffer, result, currentAltitude, vDescent);
|
FGAIWaypoint* wpt = createInAir(ac, buffer, result, currentAltitude, vDescent);
|
||||||
wpt->setCrossat(currentAltitude);
|
wpt->setCrossat(currentAltitude);
|
||||||
wpt->setTrackLength((dist / nPoints));
|
wpt->setTrackLength((dist / nPoints));
|
||||||
|
@ -744,9 +744,11 @@ bool FGAIFlightPlan::createClimb(FGAIAircraft * ac, bool firstFlight,
|
||||||
* Generate a flight path from the last waypoint of the cruise to
|
* Generate a flight path from the last waypoint of the cruise to
|
||||||
* the permission to land point
|
* the permission to land point
|
||||||
******************************************************************/
|
******************************************************************/
|
||||||
bool FGAIFlightPlan::createDescent(FGAIAircraft * ac, FGAirport * apt,
|
bool FGAIFlightPlan::createDescent(FGAIAircraft * ac,
|
||||||
|
FGAirport * apt,
|
||||||
const SGGeod& current,
|
const SGGeod& current,
|
||||||
double speed, double alt,
|
double speed,
|
||||||
|
double alt,
|
||||||
const string & fltType,
|
const string & fltType,
|
||||||
double requiredDistance)
|
double requiredDistance)
|
||||||
{
|
{
|
||||||
|
@ -762,16 +764,21 @@ bool FGAIFlightPlan::createDescent(FGAIAircraft * ac, FGAirport * apt,
|
||||||
|
|
||||||
//Beginning of Descent
|
//Beginning of Descent
|
||||||
const string& rwyClass = getRunwayClassFromTrafficType(fltType);
|
const string& rwyClass = getRunwayClassFromTrafficType(fltType);
|
||||||
double heading = ac->getTrafficRef()->getCourse();
|
double heading = ac->getTrueHeadingDeg();
|
||||||
apt->getDynamics()->getActiveRunway(rwyClass, 2, activeRunway,
|
apt->getDynamics()->getActiveRunway(rwyClass, 2, activeRunway,
|
||||||
heading);
|
heading);
|
||||||
if (!apt->hasRunwayWithIdent(activeRunway))
|
if (!apt->hasRunwayWithIdent(activeRunway))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
FGRunwayRef rwy = apt->getRunwayByIdent(activeRunway);
|
FGRunwayRef rwy = apt->getRunwayByIdent(activeRunway);
|
||||||
|
if (waypoints.size()==0 && ac->getTrueHeadingDeg()==0) {
|
||||||
|
// we obviously have no previous state and are free to position the aircraft
|
||||||
|
double courseTowardsThreshold = SGGeodesy::courseDeg(current, rwy->pointOnCenterlineDisplaced(0));
|
||||||
|
ac->setHeading(courseTowardsThreshold);
|
||||||
|
}
|
||||||
|
|
||||||
// depending on entry we differ approach (teardrop/direct/parallel)
|
// depending on entry we differ approach (teardrop/direct/parallel)
|
||||||
|
|
||||||
// Create a slow descent path that ends 250 lateral to the runway.
|
|
||||||
double initialTurnRadius = getTurnRadius(vDescent, true);
|
double initialTurnRadius = getTurnRadius(vDescent, true);
|
||||||
//double finalTurnRadius = getTurnRadius(vApproach, true);
|
//double finalTurnRadius = getTurnRadius(vApproach, true);
|
||||||
|
|
||||||
|
@ -787,6 +794,7 @@ bool FGAIFlightPlan::createDescent(FGAIAircraft * ac, FGAirport * apt,
|
||||||
}
|
}
|
||||||
|
|
||||||
SGGeod initialTarget = rwy->pointOnCenterline(-distanceOut);
|
SGGeod initialTarget = rwy->pointOnCenterline(-distanceOut);
|
||||||
|
SGGeod otherRwyEnd = rwy->pointOnCenterline(rwy->lengthM());
|
||||||
SGGeod secondaryTarget =
|
SGGeod secondaryTarget =
|
||||||
rwy->pointOffCenterline(-2 * distanceOut, lateralOffset);
|
rwy->pointOffCenterline(-2 * distanceOut, lateralOffset);
|
||||||
SGGeod secondHoldCenter =
|
SGGeod secondHoldCenter =
|
||||||
|
@ -797,50 +805,204 @@ bool FGAIFlightPlan::createDescent(FGAIAircraft * ac, FGAirport * apt,
|
||||||
double secondaryAzimuth = SGGeodesy::courseDeg(current, secondaryTarget);
|
double secondaryAzimuth = SGGeodesy::courseDeg(current, secondaryTarget);
|
||||||
double initialHeadingDiff = SGMiscd::normalizePeriodic(-180, 180, azimuth-secondaryAzimuth);
|
double initialHeadingDiff = SGMiscd::normalizePeriodic(-180, 180, azimuth-secondaryAzimuth);
|
||||||
double dummyAz2;
|
double dummyAz2;
|
||||||
|
double courseTowardsThreshold = SGGeodesy::courseDeg(current, rwy->pointOnCenterlineDisplaced(0));
|
||||||
|
double courseTowardsRwyEnd = SGGeodesy::courseDeg(current, otherRwyEnd);
|
||||||
|
double headingDiffToRunwayThreshold = SGMiscd::normalizePeriodic(-180, 180, ac->getTrueHeadingDeg() - courseTowardsThreshold);
|
||||||
|
double headingDiffToRunwayEnd = SGMiscd::normalizePeriodic(-180, 180, ac->getTrueHeadingDeg() - courseTowardsRwyEnd);
|
||||||
|
|
||||||
SG_LOG(SG_AI, SG_BULK, " Heading Diff " << headingDiffRunway <<
|
SG_LOG(SG_AI, SG_BULK, ac->getCallSign() <<
|
||||||
" Distance " << distance <<
|
"| " <<
|
||||||
|
" WPs : " << waypoints.size() <<
|
||||||
|
" Heading Diff (rwy) : " << headingDiffRunway <<
|
||||||
|
" Distance : " << distance <<
|
||||||
" Azimuth : " << azimuth <<
|
" Azimuth : " << azimuth <<
|
||||||
" Heading : " << ac->getTrueHeadingDeg() << " Lateral : " << lateralOffset);
|
" Heading : " << ac->getTrueHeadingDeg() <<
|
||||||
|
" Initial Headingdiff " << initialHeadingDiff <<
|
||||||
|
" Lateral : " << lateralOffset);
|
||||||
|
// Erase the two bogus BOD points: Note check for conflicts with scripted AI flightPlans
|
||||||
|
IncrementWaypoint(false);
|
||||||
|
IncrementWaypoint(false);
|
||||||
|
|
||||||
if (fabs(headingDiffRunway)>=30) {
|
if (fabs(headingDiffRunway)>=30 && fabs(headingDiffRunway)<=150 ) {
|
||||||
// Entering not "straight" into runway so we do a s-curve
|
if (distance < (2*initialTurnRadius)) {
|
||||||
int rightAngle = initialHeadingDiff<0?90:-90;
|
// Too near so we pass over and enter over other side
|
||||||
SGGeod firstTurnCenter = SGGeodesy::direct(current, ac->getTrueHeadingDeg() + rightAngle, initialTurnRadius);
|
SG_LOG(SG_AI, SG_BULK, ac->getCallSign() << "| Enter near S curve");
|
||||||
int firstTurnIncrement = initialHeadingDiff<0?2:-2;
|
secondaryTarget =
|
||||||
const double heading = VectorMath::innerTangentsAngle(firstTurnCenter, secondaryTarget, initialTurnRadius, initialTurnRadius )[0];
|
rwy->pointOffCenterline(-2 * distanceOut, -lateralOffset);
|
||||||
createArc(ac, firstTurnCenter, ac->_getHeading()-rightAngle, heading-rightAngle, firstTurnIncrement, initialTurnRadius, ac->getAltitude(), vDescent, "initialturn%03d");
|
secondHoldCenter =
|
||||||
double length = VectorMath::innerTangentsLength(firstTurnCenter, secondaryTarget, initialTurnRadius, initialTurnRadius );
|
rwy->pointOffCenterline(-3 * distanceOut, -lateralOffset);
|
||||||
createLine(ac, waypoints.back()->getPos(), heading, length, 50, vDescent);
|
|
||||||
int holdsPatterns = 0;
|
// Entering not "straight" into runway so we do a s-curve
|
||||||
// Length of
|
int rightAngle = headingDiffRunway>0?90:-90;
|
||||||
if (holdsPatterns>0) {
|
int firstTurnIncrement = headingDiffRunway>0?2:-2;
|
||||||
// Turn into hold
|
|
||||||
createArc(ac, secondaryTarget, heading+rightAngle, rwy->headingDeg()+rightAngle, firstTurnIncrement*-1, initialTurnRadius,
|
SGGeod firstTurnCenter = SGGeodesy::direct(current, ac->getTrueHeadingDeg() + rightAngle, initialTurnRadius);
|
||||||
waypoints.back()->getAltitude(), vDescent, "turnintohold%03d");
|
SGGeod newCurrent = current;
|
||||||
for (int t = 0; t < holdsPatterns; t++)
|
// If we are not far enough cross over
|
||||||
{
|
if (abs(headingDiffToRunwayThreshold)<90) {
|
||||||
/*
|
newCurrent = SGGeodesy::direct(current, ac->getTrueHeadingDeg(), distance + 1000);
|
||||||
createArc(ac, secondaryTarget, endval, endval+180, increment, initialTurnRadius,
|
firstTurnCenter = SGGeodesy::direct(newCurrent, ac->getTrueHeadingDeg() + rightAngle, initialTurnRadius);
|
||||||
currentAltitude, vDescent, "hold_1_%03d");
|
createLine(ac, current, ac->getTrueHeadingDeg(), distance + 1000, 50, vDescent, "move%03d");
|
||||||
createArc(ac, secondHoldCenter, endval+180, endval, increment, initialTurnRadius,
|
}
|
||||||
currentAltitude, vDescent, "hold_2_%03d");
|
int offset = 1000;
|
||||||
*/
|
while (SGGeodesy::distanceM(firstTurnCenter, secondaryTarget) < 2*initialTurnRadius) {
|
||||||
|
newCurrent = SGGeodesy::direct(newCurrent, ac->getTrueHeadingDeg(), offset+=100);
|
||||||
|
firstTurnCenter = SGGeodesy::direct(newCurrent, ac->getTrueHeadingDeg() + rightAngle, initialTurnRadius);
|
||||||
|
}
|
||||||
|
const double heading = VectorMath::outerTangentsAngle(firstTurnCenter, secondaryTarget, initialTurnRadius, initialTurnRadius )[0];
|
||||||
|
createArc(ac, firstTurnCenter, ac->_getHeading()-rightAngle, heading-rightAngle, firstTurnIncrement, initialTurnRadius, ac->getAltitude(), vDescent, "near-initialturn%03d");
|
||||||
|
double length = VectorMath::innerTangentsLength(firstTurnCenter, secondaryTarget, initialTurnRadius, initialTurnRadius );
|
||||||
|
createLine(ac, waypoints.back()->getPos(), heading, length, 50, vDescent, "descent%03d");
|
||||||
|
int holdsPatterns = 0;
|
||||||
|
// Length of
|
||||||
|
if (holdsPatterns>0) {
|
||||||
|
// Turn into hold
|
||||||
|
createArc(ac, secondaryTarget, heading+rightAngle, rwy->headingDeg()+rightAngle, firstTurnIncrement*-1, initialTurnRadius,
|
||||||
|
waypoints.back()->getAltitude(), vDescent, "turnintohold%03d");
|
||||||
|
for (int t = 0; t < holdsPatterns; t++)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
createArc(ac, secondaryTarget, endval, endval+180, increment, initialTurnRadius,
|
||||||
|
currentAltitude, vDescent, "hold_1_%03d");
|
||||||
|
createArc(ac, secondHoldCenter, endval+180, endval, increment, initialTurnRadius,
|
||||||
|
currentAltitude, vDescent, "hold_2_%03d");
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
int startVal = SGMiscd::normalizePeriodic(0, 360, heading-rightAngle);
|
||||||
|
int endVal = SGMiscd::normalizePeriodic(0, 360, rwy->headingDeg()-rightAngle);
|
||||||
|
// Turn into runway
|
||||||
|
createArc(ac, secondaryTarget, startVal ,endVal , firstTurnIncrement, initialTurnRadius,
|
||||||
|
waypoints.back()->getAltitude(), vDescent, "turn%03d");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
int startVal = SGMiscd::normalizePeriodic(0, 360, heading+rightAngle);
|
SG_LOG(SG_AI, SG_BULK, ac->getCallSign() << "| Enter far S curve");
|
||||||
int endVal = SGMiscd::normalizePeriodic(0, 360, rwy->headingDeg()+rightAngle);
|
// Entering not "straight" into runway so we do a s-curve
|
||||||
// Turn into runway
|
int rightAngle = headingDiffRunway>0?90:-90;
|
||||||
createArc(ac, secondaryTarget, startVal, endVal, firstTurnIncrement*-1, initialTurnRadius,
|
int firstTurnIncrement = headingDiffRunway>0?2:-2;
|
||||||
waypoints.back()->getAltitude(), vDescent, "turn%03d");
|
SGGeod firstTurnCenter = SGGeodesy::direct(current, ac->getTrueHeadingDeg() + rightAngle, initialTurnRadius);
|
||||||
|
int innerTangent = headingDiffRunway<0?0:1;
|
||||||
|
int offset = 1000;
|
||||||
|
while (SGGeodesy::distanceM(firstTurnCenter, secondaryTarget)<2*initialTurnRadius) {
|
||||||
|
secondaryTarget = rwy->pointOffCenterline(-2 * distanceOut + (offset+=1000), lateralOffset);
|
||||||
|
}
|
||||||
|
const double heading = VectorMath::innerTangentsAngle(firstTurnCenter, secondaryTarget, initialTurnRadius, initialTurnRadius )[innerTangent];
|
||||||
|
createArc(ac, firstTurnCenter, ac->_getHeading()-rightAngle, heading-rightAngle, firstTurnIncrement, initialTurnRadius, ac->getAltitude(), vDescent, "far-initialturn%03d");
|
||||||
|
double length = VectorMath::innerTangentsLength(firstTurnCenter, secondaryTarget, initialTurnRadius, initialTurnRadius );
|
||||||
|
createLine(ac, waypoints.back()->getPos(), heading, length, 50, vDescent, "descent%03d");
|
||||||
|
int holdsPatterns = 0;
|
||||||
|
// Length of
|
||||||
|
if (holdsPatterns>0) {
|
||||||
|
// Turn into hold
|
||||||
|
createArc(ac, secondaryTarget, heading+rightAngle, rwy->headingDeg()+rightAngle, firstTurnIncrement*-1, initialTurnRadius,
|
||||||
|
waypoints.back()->getAltitude(), vDescent, "turnintohold%03d");
|
||||||
|
for (int t = 0; t < holdsPatterns; t++)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
createArc(ac, secondaryTarget, endval, endval+180, increment, initialTurnRadius,
|
||||||
|
currentAltitude, vDescent, "hold_1_%03d");
|
||||||
|
createArc(ac, secondHoldCenter, endval+180, endval, increment, initialTurnRadius,
|
||||||
|
currentAltitude, vDescent, "hold_2_%03d");
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
int startVal = SGMiscd::normalizePeriodic(0, 360, heading+rightAngle);
|
||||||
|
int endVal = SGMiscd::normalizePeriodic(0, 360, rwy->headingDeg()+rightAngle);
|
||||||
|
// Turn into runway
|
||||||
|
createArc(ac, secondaryTarget, startVal, endVal, firstTurnIncrement*-1, initialTurnRadius,
|
||||||
|
waypoints.back()->getAltitude(), vDescent, "s-turn%03d");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (fabs(headingDiffRunway)>=150 ) {
|
||||||
|
// We are entering downwind
|
||||||
|
if (distance < (2*initialTurnRadius)) {
|
||||||
|
// Too near so we pass over and enter over other side
|
||||||
|
SG_LOG(SG_AI, SG_BULK, ac->getCallSign() << "| Enter near downrunway");
|
||||||
|
secondaryTarget =
|
||||||
|
rwy->pointOffCenterline(-2 * distanceOut, -lateralOffset);
|
||||||
|
secondHoldCenter =
|
||||||
|
rwy->pointOffCenterline(-3 * distanceOut, -lateralOffset);
|
||||||
|
|
||||||
|
// Entering not "straight" into runway so we do a s-curve
|
||||||
|
int rightAngle = azimuth>0?90:-90;
|
||||||
|
int firstTurnIncrement = azimuth>0?2:-2;
|
||||||
|
|
||||||
|
SGGeod firstTurnCenter = SGGeodesy::direct(current, ac->getTrueHeadingDeg() + rightAngle, initialTurnRadius);
|
||||||
|
// rwy->headingDeg()-rightAngle
|
||||||
|
int endVal = SGMiscd::normalizePeriodic(0, 360, rwy->headingDeg()-180);
|
||||||
|
SGGeod secondTurnCenter = SGGeodesy::direct(firstTurnCenter, endVal, 2*initialTurnRadius);
|
||||||
|
createArc(ac, firstTurnCenter, ac->_getHeading()-rightAngle, endVal, firstTurnIncrement, initialTurnRadius, ac->getAltitude(), vDescent, "d-near-initialturn%03d");
|
||||||
|
endVal = SGMiscd::normalizePeriodic(0, 360, rwy->headingDeg());
|
||||||
|
// int endVal2 = SGMiscd::normalizePeriodic(0, 360, rwy->headingDeg()-rightAngle);
|
||||||
|
const double endVal2 = VectorMath::outerTangentsAngle(secondTurnCenter, secondaryTarget, initialTurnRadius, initialTurnRadius )[0];
|
||||||
|
createArc(ac, secondTurnCenter, endVal, endVal2+rightAngle, -firstTurnIncrement, initialTurnRadius, ac->getAltitude(), vDescent, "secondturn%03d");
|
||||||
|
//outer
|
||||||
|
double length = VectorMath::outerTangentsLength(secondTurnCenter, secondaryTarget, initialTurnRadius, initialTurnRadius );
|
||||||
|
int reverseRwyHeading = SGMiscd::normalizePeriodic(0, 360, rwy->headingDeg() - 180);
|
||||||
|
createLine(ac, waypoints.back()->getPos(), endVal2, length, 50, vDescent, "descent%03d");
|
||||||
|
int holdsPatterns = 0;
|
||||||
|
// Length of
|
||||||
|
if (holdsPatterns>0) {
|
||||||
|
// Turn into hold
|
||||||
|
createArc(ac, secondaryTarget, heading+rightAngle, rwy->headingDeg()+rightAngle, firstTurnIncrement*-1, initialTurnRadius,
|
||||||
|
waypoints.back()->getAltitude(), vDescent, "turnintohold%03d");
|
||||||
|
for (int t = 0; t < holdsPatterns; t++)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
createArc(ac, secondaryTarget, endval, endval+180, increment, initialTurnRadius,
|
||||||
|
currentAltitude, vDescent, "hold_1_%03d");
|
||||||
|
createArc(ac, secondHoldCenter, endval+180, endval, increment, initialTurnRadius,
|
||||||
|
currentAltitude, vDescent, "hold_2_%03d");
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
int endVal = SGMiscd::normalizePeriodic(0, 360, rwy->headingDeg()+rightAngle);
|
||||||
|
// Turn into runway
|
||||||
|
createArc(ac, secondaryTarget, endVal2+rightAngle, endVal, -firstTurnIncrement, initialTurnRadius,
|
||||||
|
waypoints.back()->getAltitude(), vDescent, "turn%03d");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
SG_LOG(SG_AI, SG_BULK, ac->getCallSign() << "| Enter far S downrunway");
|
||||||
|
// Entering not "straight" into runway so we do a s-curve
|
||||||
|
int rightAngle = azimuth<0?90:-90;
|
||||||
|
int firstTurnIncrement = azimuth<0?2:-2;
|
||||||
|
int innerTangent = headingDiffRunway<0?0:1;
|
||||||
|
SGGeod firstTurnCenter = SGGeodesy::direct(current, ac->getTrueHeadingDeg() + rightAngle, initialTurnRadius);
|
||||||
|
const double heading = VectorMath::innerTangentsAngle(firstTurnCenter, secondaryTarget, initialTurnRadius, initialTurnRadius )[innerTangent];
|
||||||
|
createArc(ac, firstTurnCenter, ac->_getHeading()-rightAngle, heading-rightAngle, firstTurnIncrement, initialTurnRadius, ac->getAltitude(), vDescent, "d-far-initialturn%03d");
|
||||||
|
double length = VectorMath::innerTangentsLength(firstTurnCenter, secondaryTarget, initialTurnRadius, initialTurnRadius );
|
||||||
|
createLine(ac, waypoints.back()->getPos(), heading, length, 50, vDescent, "descent%03d");
|
||||||
|
int holdsPatterns = 0;
|
||||||
|
// Length of
|
||||||
|
if (holdsPatterns>0) {
|
||||||
|
// Turn into hold
|
||||||
|
createArc(ac, secondaryTarget, heading+rightAngle, rwy->headingDeg()+rightAngle, firstTurnIncrement*-1, initialTurnRadius,
|
||||||
|
waypoints.back()->getAltitude(), vDescent, "turnintohold%03d");
|
||||||
|
for (int t = 0; t < holdsPatterns; t++)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
createArc(ac, secondaryTarget, endval, endval+180, increment, initialTurnRadius,
|
||||||
|
currentAltitude, vDescent, "hold_1_%03d");
|
||||||
|
createArc(ac, secondHoldCenter, endval+180, endval, increment, initialTurnRadius,
|
||||||
|
currentAltitude, vDescent, "hold_2_%03d");
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
int startVal = SGMiscd::normalizePeriodic(0, 360, heading+rightAngle);
|
||||||
|
int endVal = SGMiscd::normalizePeriodic(0, 360, rwy->headingDeg()+rightAngle);
|
||||||
|
// Turn into runway
|
||||||
|
createArc(ac, secondaryTarget, startVal, endVal, -firstTurnIncrement, initialTurnRadius,
|
||||||
|
waypoints.back()->getAltitude(), vDescent, "d-s-turn%03d");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
SG_LOG(SG_AI, SG_BULK, ac->getCallSign() << "| Enter far straight");
|
||||||
// Entering "straight" into runway so only one turn
|
// Entering "straight" into runway so only one turn
|
||||||
int rightAngle = headingDiffRunway>0?90:-90;
|
int rightAngle = headingDiffRunway>0?90:-90;
|
||||||
SGGeod firstTurnCenter = SGGeodesy::direct(current, ac->getTrueHeadingDeg() - rightAngle, initialTurnRadius);
|
SGGeod firstTurnCenter = SGGeodesy::direct(current, ac->getTrueHeadingDeg() - rightAngle, initialTurnRadius);
|
||||||
int firstTurnIncrement = headingDiffRunway>0?-2:2;
|
int firstTurnIncrement = headingDiffRunway>0?-2:2;
|
||||||
const double heading = rwy->headingDeg();
|
const double heading = rwy->headingDeg();
|
||||||
createArc(ac, firstTurnCenter, ac->_getHeading()+rightAngle, heading+rightAngle, firstTurnIncrement, initialTurnRadius, ac->getAltitude(), vDescent, "initialturn_%03d");
|
createArc(ac, secondaryTarget, ac->_getHeading()+rightAngle, heading+rightAngle, firstTurnIncrement, initialTurnRadius, ac->getAltitude(), vDescent, "straight_turn_%03d");
|
||||||
}
|
}
|
||||||
|
|
||||||
// To prevent absurdly steep approaches, compute the origin from where the approach should have started
|
// To prevent absurdly steep approaches, compute the origin from where the approach should have started
|
||||||
|
@ -861,55 +1023,12 @@ bool FGAIFlightPlan::createDescent(FGAIAircraft * ac, FGAirport * apt,
|
||||||
azimuth = SGGeodesy::courseDeg(origin, initialTarget);
|
azimuth = SGGeodesy::courseDeg(origin, initialTarget);
|
||||||
}
|
}
|
||||||
|
|
||||||
double dAlt = 0; // = alt - (apt->getElevation() + 2000);
|
|
||||||
FGTaxiNodeRef tn;
|
|
||||||
if (apt->groundNetwork()) {
|
|
||||||
tn = apt->groundNetwork()->findNearestNode(refPoint);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tn) {
|
|
||||||
dAlt = alt - ((tn->getElevationFt()) + 2000);
|
|
||||||
} else {
|
|
||||||
dAlt = alt - (apt->getElevation() + 2000);
|
|
||||||
}
|
|
||||||
|
|
||||||
//cerr << "Phase 1: Linear Descent path to runway" << rwy->name() << endl;
|
|
||||||
// Create an initial destination point on a semicircle
|
|
||||||
//cerr << "lateral offset : " << lateralOffset << endl;
|
|
||||||
//cerr << "Distance : " << distance << endl;
|
|
||||||
//cerr << "Azimuth : " << azimuth << endl;
|
|
||||||
//cerr << "Initial Lateral point: " << lateralOffset << endl;
|
|
||||||
// double lat = refPoint.getLatitudeDeg();
|
|
||||||
// double lon = refPoint.getLongitudeDeg();
|
|
||||||
//cerr << "Reference point (" << lat << ", " << lon << ")." << endl;
|
|
||||||
// lat = initialTarget.getLatitudeDeg();
|
|
||||||
// lon = initialTarget.getLongitudeDeg();
|
|
||||||
//cerr << "Initial Target point (" << lat << ", " << lon << ")." << endl;
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
double ratio = initialTurnRadius / distance;
|
|
||||||
if (ratio > 1.0)
|
|
||||||
ratio = 1.0;
|
|
||||||
if (ratio < -1.0)
|
|
||||||
ratio = -1.0;
|
|
||||||
|
|
||||||
double newHeading = asin(ratio) * SG_RADIANS_TO_DEGREES;
|
|
||||||
double newDistance =
|
|
||||||
cos(newHeading * SG_DEGREES_TO_RADIANS) * distance;
|
|
||||||
//cerr << "new distance " << newDistance << ". additional Heading " << newHeading << endl;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
double side = azimuth - rwy->headingDeg();
|
|
||||||
if (side < 0.0)
|
|
||||||
side += 360.0;
|
|
||||||
|
|
||||||
// Calculate the ETA at final, based on remaining distance, and approach speed.
|
// Calculate the ETA at final, based on remaining distance, and approach speed.
|
||||||
// distance should really consist of flying time to terniary target, plus circle
|
// distance should really consist of flying time to terniary target, plus circle
|
||||||
// but the distance to secondary target should work as a reasonable approximation
|
// but the distance to secondary target should work as a reasonable approximation
|
||||||
// aditionally add the amount of distance covered by making a turn of "side"
|
// aditionally add the amount of distance covered by making a turn of "side"
|
||||||
double turnDistance = (2 * M_PI * initialTurnRadius) * (side / 360.0);
|
|
||||||
time_t remaining =
|
time_t remaining =
|
||||||
(turnDistance + distance) / ((vDescent * SG_NM_TO_METER) / 3600.0);
|
(initialTurnRadius + distance) / ((vDescent * SG_NM_TO_METER) / 3600.0);
|
||||||
time_t now = globals->get_time_params()->get_cur_time();
|
time_t now = globals->get_time_params()->get_cur_time();
|
||||||
|
|
||||||
//if (ac->getTrafficRef()->getCallSign() == fgGetString("/ai/track-callsign")) {
|
//if (ac->getTrafficRef()->getCallSign() == fgGetString("/ai/track-callsign")) {
|
||||||
|
@ -940,110 +1059,6 @@ bool FGAIFlightPlan::createDescent(FGAIAircraft * ac, FGAirport * apt,
|
||||||
|
|
||||||
additionalTimeNeeded -= holdsPatterns*240;
|
additionalTimeNeeded -= holdsPatterns*240;
|
||||||
|
|
||||||
double distanceCovered =
|
|
||||||
((vApproach * SG_NM_TO_METER) / 3600.0) * additionalTimeNeeded;
|
|
||||||
distanceOut += distanceCovered;
|
|
||||||
|
|
||||||
azimuth = SGGeodesy::courseDeg(origin, secondaryTarget);
|
|
||||||
distance = SGGeodesy::distanceM(origin, secondaryTarget);
|
|
||||||
double ratio = initialTurnRadius / distance;
|
|
||||||
if (ratio > 1.0)
|
|
||||||
ratio = 1.0;
|
|
||||||
if (ratio < -1.0)
|
|
||||||
ratio = -1.0;
|
|
||||||
|
|
||||||
double newHeading = asin(ratio) * SG_RADIANS_TO_DEGREES;
|
|
||||||
double newDistance = cos(newHeading * SG_DEGREES_TO_RADIANS) * distance;
|
|
||||||
//cerr << "new distance realative to secondary target: " << newDistance << ". additional Heading " << newHeading << endl;
|
|
||||||
|
|
||||||
if (side < 180) {
|
|
||||||
azimuth += newHeading;
|
|
||||||
} else {
|
|
||||||
azimuth -= newHeading;
|
|
||||||
}
|
|
||||||
|
|
||||||
SGGeod tertiaryTarget;
|
|
||||||
SGGeodesy::direct(origin, azimuth, newDistance, tertiaryTarget, dummyAz2);
|
|
||||||
|
|
||||||
// lat = tertiaryTarget.getLatitudeDeg();
|
|
||||||
// lon = tertiaryTarget.getLongitudeDeg();
|
|
||||||
//cerr << "tertiary Target point (" << lat << ", " << lon << ")." << endl;
|
|
||||||
|
|
||||||
|
|
||||||
//cerr << "Phase 2: Circle " << endl;
|
|
||||||
double initialAzimuth =
|
|
||||||
SGGeodesy::courseDeg(secondaryTarget, tertiaryTarget);
|
|
||||||
double finalAzimuth =
|
|
||||||
SGGeodesy::courseDeg(secondaryTarget, initialTarget);
|
|
||||||
|
|
||||||
//cerr << "Angles from secondary target: " << initialAzimuth << " " << finalAzimuth << endl;
|
|
||||||
int increment, startval, endval;
|
|
||||||
// circle right around secondary target if orig of position is to the right of the runway
|
|
||||||
// i.e. use negative angles; else circle leftward and use postivi
|
|
||||||
if (side < 180) {
|
|
||||||
increment = -2;
|
|
||||||
startval = floor(initialAzimuth);
|
|
||||||
endval = ceil(finalAzimuth);
|
|
||||||
if (endval > startval) {
|
|
||||||
endval -= 360;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
increment = 2;
|
|
||||||
startval = ceil(initialAzimuth);
|
|
||||||
endval = floor(finalAzimuth);
|
|
||||||
if (endval < startval) {
|
|
||||||
endval += 360;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//cerr << "creating circle between " << startval << " and " << endval << " using " << increment << endl;
|
|
||||||
//FGTaxiNode * tn = apt->getDynamics()->getGroundNetwork()->findNearestNode(initialTarget);
|
|
||||||
double currentAltitude = 0;
|
|
||||||
if (tn) {
|
|
||||||
currentAltitude = (tn->getElevationFt()) + 2000;
|
|
||||||
} else {
|
|
||||||
currentAltitude = apt->getElevation() + 2000;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// The approach leg should bring the aircraft to approximately 4-6 nm out, after which the landing phase should take over.
|
|
||||||
//cerr << "Phase 3: Approach" << endl;
|
|
||||||
|
|
||||||
//cerr << "Done" << endl;
|
|
||||||
|
|
||||||
// Erase the two bogus BOD points: Note check for conflicts with scripted AI flightPlans
|
|
||||||
IncrementWaypoint(true);
|
|
||||||
IncrementWaypoint(true);
|
|
||||||
|
|
||||||
if (reposition) {
|
|
||||||
double tempDistance = SGGeodesy::distanceM(current, initialTarget);
|
|
||||||
time_t eta2 =
|
|
||||||
tempDistance / ((vDescent * SG_NM_TO_METER) / 3600.0) + now;
|
|
||||||
SG_LOG(SG_ATC, SG_BULK, "Final 1 " << eta2);
|
|
||||||
time_t newEta2 =
|
|
||||||
apt->getDynamics()->getApproachController()->getRunway(rwy->name())->requestTimeSlot(eta2);
|
|
||||||
SG_LOG(SG_ATC, SG_BULK, "Final 1 " << eta2 << " " << newEta2);
|
|
||||||
arrivalTime = newEta2;
|
|
||||||
double newDistance2 =
|
|
||||||
((vDescent * SG_NM_TO_METER) / 3600.0) * (newEta2 - now);
|
|
||||||
|
|
||||||
IncrementWaypoint(true); // remove waypoint BOD2
|
|
||||||
|
|
||||||
while (checkTrackLength("final001") > newDistance2) {
|
|
||||||
SG_LOG(SG_ATC, SG_BULK, "Final 2 " << checkTrackLength("final001") );
|
|
||||||
IncrementWaypoint(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
ac->resetPositionFromFlightPlan();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!waypoints.empty()) {
|
|
||||||
SG_LOG(SG_AI, SG_BULK, "Setting Node " << waypoints.back()->getName() << " to a leg end");
|
|
||||||
waypoints.back()->setName( (waypoints.back()->getName() + string("legend")));
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -314,12 +314,22 @@ bool FGAIFlightPlan::createCruise(FGAIAircraft *ac, bool firstFlight, FGAirport
|
||||||
assert( rwy != NULL );
|
assert( rwy != NULL );
|
||||||
// begin descent 110km out
|
// begin descent 110km out
|
||||||
double distanceOut = arr->getDynamics()->getApproachController()->getRunway(rwy->name())->getApproachDistance(); //12 * SG_NM_TO_METER;
|
double distanceOut = arr->getDynamics()->getApproachController()->getRunway(rwy->name())->getApproachDistance(); //12 * SG_NM_TO_METER;
|
||||||
SGGeod beginDescentPoint = rwy->pointOnCenterline(-2*distanceOut);
|
|
||||||
|
SGGeod beginDescentPoint = rwy->pointOnCenterline(-3*distanceOut);
|
||||||
SGGeod secondaryDescentPoint = rwy->pointOnCenterline(0);
|
SGGeod secondaryDescentPoint = rwy->pointOnCenterline(0);
|
||||||
|
|
||||||
wpt = createInAir(ac, "BOD", beginDescentPoint, alt, vCruise);
|
double distanceToRwy = SGGeodesy::distanceM(current, secondaryDescentPoint);
|
||||||
pushBackWaypoint(wpt);
|
if (distanceToRwy>4*distanceOut) {
|
||||||
wpt = createInAir(ac, "BOD2", secondaryDescentPoint, alt, vCruise);
|
FGAIWaypoint *bodWpt = createInAir(ac, "BOD", beginDescentPoint, alt, vCruise);
|
||||||
pushBackWaypoint(wpt);
|
pushBackWaypoint(bodWpt);
|
||||||
|
FGAIWaypoint *bod2Wpt = createInAir(ac, "BOD2", secondaryDescentPoint, alt, vCruise);
|
||||||
|
pushBackWaypoint(bod2Wpt);
|
||||||
|
} else {
|
||||||
|
// We are too near. The descent leg takes care of this (teardrop etc)
|
||||||
|
FGAIWaypoint *bodWpt = createInAir(ac, "BOD", SGGeodesy::direct(current, ac->getTrueHeadingDeg(), 10000), alt, vCruise);
|
||||||
|
pushBackWaypoint(bodWpt);
|
||||||
|
FGAIWaypoint *bod2Wpt = createInAir(ac, "BOD2", SGGeodesy::direct(current, ac->getTrueHeadingDeg(), 15000), alt, vCruise);
|
||||||
|
pushBackWaypoint(bod2Wpt);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,4 +59,22 @@ double VectorMath::innerTangentsLength( SGGeod m1, SGGeod m2, double r1, double
|
||||||
SGGeod p2 = SGGeodesy::direct(m2, angle2, r2);
|
SGGeod p2 = SGGeodesy::direct(m2, angle2, r2);
|
||||||
|
|
||||||
return SGGeodesy::distanceM(p1, p2);
|
return SGGeodesy::distanceM(p1, p2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::array<double, 2> VectorMath::outerTangentsAngle( SGGeod m1, SGGeod m2, double r1, double r2) {
|
||||||
|
std::array<double, 2> ret;
|
||||||
|
double hypothenuse = SGGeodesy::distanceM(m1, m2);
|
||||||
|
double radiusDiff = abs(r1 - r2);
|
||||||
|
double beta = atan2( radiusDiff, hypothenuse ) * SG_RADIANS_TO_DEGREES;
|
||||||
|
double gamma = SGGeodesy::courseDeg(m1, m2);
|
||||||
|
ret[0] = SGMiscd::normalizePeriodic(0, 360, gamma - beta);
|
||||||
|
ret[1] = SGMiscd::normalizePeriodic(0, 360, gamma + beta);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
double VectorMath::outerTangentsLength( SGGeod m1, SGGeod m2, double r1, double r2) {
|
||||||
|
double hypothenuse = SGGeodesy::distanceM(m1, m2);
|
||||||
|
double radiusDiff = abs(r1 - r2);
|
||||||
|
double dist = sqrt(pow(hypothenuse,2)-pow(radiusDiff,2));
|
||||||
|
return dist;
|
||||||
|
}
|
||||||
|
|
|
@ -27,4 +27,8 @@ class VectorMath {
|
||||||
static std::array<double, 2> innerTangentsAngle( SGGeod m1, SGGeod m2, double r1, double r2);
|
static std::array<double, 2> innerTangentsAngle( SGGeod m1, SGGeod m2, double r1, double r2);
|
||||||
/**Length of inner tangent between two circles.*/
|
/**Length of inner tangent between two circles.*/
|
||||||
static double innerTangentsLength( SGGeod m1, SGGeod m2, double r1, double r2);
|
static double innerTangentsLength( SGGeod m1, SGGeod m2, double r1, double r2);
|
||||||
|
/**Angles of outer tangent between two circles normalized to 0-360*/
|
||||||
|
static std::array<double, 2> outerTangentsAngle( SGGeod m1, SGGeod m2, double r1, double r2);
|
||||||
|
/**Length of outer tangent between two circles.*/
|
||||||
|
static double outerTangentsLength( SGGeod m1, SGGeod m2, double r1, double r2);
|
||||||
};
|
};
|
||||||
|
|
|
@ -202,10 +202,10 @@ bool FGAISchedule::init()
|
||||||
bool FGAISchedule::update(time_t now, const SGVec3d& userCart)
|
bool FGAISchedule::update(time_t now, const SGVec3d& userCart)
|
||||||
{
|
{
|
||||||
|
|
||||||
time_t totalTimeEnroute,
|
time_t totalTimeEnroute;
|
||||||
elapsedTimeEnroute,
|
time_t elapsedTimeEnroute;
|
||||||
//remainingTimeEnroute,
|
time_t remainingTimeEnroute;
|
||||||
deptime = 0;
|
time_t deptime = 0;
|
||||||
|
|
||||||
if (!valid) {
|
if (!valid) {
|
||||||
return true; // processing complete
|
return true; // processing complete
|
||||||
|
@ -255,7 +255,7 @@ bool FGAISchedule::update(time_t now, const SGVec3d& userCart)
|
||||||
// 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 (flight->getArrivalTime() < now) {
|
if (flight->getArrivalTime() < now) {
|
||||||
SG_LOG (SG_AI, SG_BULK, "Traffic Manager: Flight is in the Past");
|
SG_LOG (SG_AI, SG_BULK, "Traffic Manager: " << flight->getCallSign() << " is in the Past");
|
||||||
// Don't just update: check whether we need to load a new leg. etc.
|
// Don't just update: check whether we need to load a new leg. etc.
|
||||||
// This update occurs for distant aircraft, so we can update the current leg
|
// This update occurs for distant aircraft, so we can update the current leg
|
||||||
// and detach it from the current list of aircraft.
|
// and detach it from the current list of aircraft.
|
||||||
|
@ -275,7 +275,7 @@ bool FGAISchedule::update(time_t now, const SGVec3d& userCart)
|
||||||
totalTimeEnroute = flight->getArrivalTime() - flight->getDepartureTime();
|
totalTimeEnroute = flight->getArrivalTime() - flight->getDepartureTime();
|
||||||
if (flight->getDepartureTime() < now) {
|
if (flight->getDepartureTime() < now) {
|
||||||
elapsedTimeEnroute = now - flight->getDepartureTime();
|
elapsedTimeEnroute = now - flight->getDepartureTime();
|
||||||
//remainingTimeEnroute = totalTimeEnroute - elapsedTimeEnroute;
|
remainingTimeEnroute = totalTimeEnroute - elapsedTimeEnroute;
|
||||||
double x = elapsedTimeEnroute / (double) totalTimeEnroute;
|
double x = elapsedTimeEnroute / (double) totalTimeEnroute;
|
||||||
|
|
||||||
// current pos is based on great-circle course between departure/arrival,
|
// current pos is based on great-circle course between departure/arrival,
|
||||||
|
@ -285,21 +285,22 @@ bool FGAISchedule::update(time_t now, const SGVec3d& userCart)
|
||||||
SGGeodesy::inverse(dep->geod(), arr->geod(), course, az2, distanceM);
|
SGGeodesy::inverse(dep->geod(), arr->geod(), course, az2, distanceM);
|
||||||
double coveredDistance = distanceM * x;
|
double coveredDistance = distanceM * x;
|
||||||
|
|
||||||
|
//FIXME very crude that doesn't harmonise with Legs
|
||||||
SGGeodesy::direct(dep->geod(), course, coveredDistance, position, az2);
|
SGGeodesy::direct(dep->geod(), course, coveredDistance, position, az2);
|
||||||
|
|
||||||
SG_LOG (SG_AI, SG_BULK, "Traffic Manager: Flight is in progress, %=" << x);
|
SG_LOG (SG_AI, SG_BULK, "Traffic Manager: " << flight->getCallSign() << " is in progress " << (x*100) << "%");
|
||||||
speed = ((distanceM - coveredDistance) * SG_METER_TO_NM) / 3600.0;
|
speed = ((distanceM - coveredDistance) * SG_METER_TO_NM) / 3600.0;
|
||||||
} else {
|
} else {
|
||||||
// not departed yet
|
// not departed yet
|
||||||
//remainingTimeEnroute = totalTimeEnroute;
|
remainingTimeEnroute = totalTimeEnroute;
|
||||||
elapsedTimeEnroute = 0;
|
elapsedTimeEnroute = 0;
|
||||||
position = dep->geod();
|
position = dep->geod();
|
||||||
SG_LOG (SG_AI, SG_BULK, "Traffic Manager: Flight is pending, departure in "
|
SG_LOG (SG_AI, SG_BULK, "Traffic Manager: " << flight->getCallSign() << " is pending, departure in "
|
||||||
<< flight->getDepartureTime() - now << " seconds ");
|
<< flight->getDepartureTime() - now << " seconds ");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// departure / arrival coincident
|
// departure / arrival coincident
|
||||||
//remainingTimeEnroute = totalTimeEnroute = 0.0;
|
remainingTimeEnroute = totalTimeEnroute = flight->getArrivalTime() - flight->getDepartureTime();
|
||||||
elapsedTimeEnroute = 0;
|
elapsedTimeEnroute = 0;
|
||||||
position = dep->geod();
|
position = dep->geod();
|
||||||
}
|
}
|
||||||
|
@ -320,12 +321,12 @@ bool FGAISchedule::update(time_t now, const SGVec3d& userCart)
|
||||||
return true; // out of visual range, for the moment.
|
return true; // out of visual range, for the moment.
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!createAIAircraft(flight, speed, deptime)) {
|
if (!createAIAircraft(flight, speed, deptime, remainingTimeEnroute)) {
|
||||||
valid = false;
|
valid = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return true; // processing complete
|
return true; // processing complete
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FGAISchedule::validModelPath(const std::string& modelPath)
|
bool FGAISchedule::validModelPath(const std::string& modelPath)
|
||||||
|
@ -353,12 +354,13 @@ SGPath FGAISchedule::resolveModelPath(const std::string& modelPath)
|
||||||
return SGPath();
|
return SGPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FGAISchedule::createAIAircraft(FGScheduledFlight* flight, double speedKnots, time_t deptime)
|
bool FGAISchedule::createAIAircraft(FGScheduledFlight* flight, double speedKnots, time_t deptime, time_t remainingTime)
|
||||||
{
|
{
|
||||||
|
//FIXME The position must be set here not in update
|
||||||
FGAirport* dep = flight->getDepartureAirport();
|
FGAirport* dep = flight->getDepartureAirport();
|
||||||
FGAirport* arr = flight->getArrivalAirport();
|
FGAirport* arr = flight->getArrivalAirport();
|
||||||
string flightPlanName = dep->getId() + "-" + arr->getId() + ".xml";
|
string flightPlanName = dep->getId() + "-" + arr->getId() + ".xml";
|
||||||
SG_LOG(SG_AI, SG_DEBUG, "Traffic manager: Creating AIModel from:" << flightPlanName);
|
SG_LOG(SG_AI, SG_DEBUG, flight->getCallSign() << "|Traffic manager: Creating AIModel from:" << flightPlanName);
|
||||||
|
|
||||||
aiAircraft = new FGAIAircraft(this);
|
aiAircraft = new FGAIAircraft(this);
|
||||||
aiAircraft->setPerformance(acType, m_class); //"jet_transport";
|
aiAircraft->setPerformance(acType, m_class); //"jet_transport";
|
||||||
|
@ -373,8 +375,15 @@ bool FGAISchedule::createAIAircraft(FGScheduledFlight* flight, double speedKnots
|
||||||
aiAircraft->setBank(0);
|
aiAircraft->setBank(0);
|
||||||
|
|
||||||
courseToDest = SGGeodesy::courseDeg(position, arr->geod());
|
courseToDest = SGGeodesy::courseDeg(position, arr->geod());
|
||||||
std::unique_ptr<FGAIFlightPlan> fp(new FGAIFlightPlan(aiAircraft, flightPlanName, courseToDest, deptime,
|
std::unique_ptr<FGAIFlightPlan> fp(new FGAIFlightPlan(aiAircraft,
|
||||||
dep, arr, true, radius,
|
flightPlanName,
|
||||||
|
courseToDest,
|
||||||
|
deptime,
|
||||||
|
remainingTime,
|
||||||
|
dep,
|
||||||
|
arr,
|
||||||
|
true,
|
||||||
|
radius,
|
||||||
flight->getCruiseAlt()*100,
|
flight->getCruiseAlt()*100,
|
||||||
position.getLatitudeDeg(),
|
position.getLatitudeDeg(),
|
||||||
position.getLongitudeDeg(),
|
position.getLongitudeDeg(),
|
||||||
|
@ -409,7 +418,6 @@ bool FGAISchedule::createAIAircraft(FGScheduledFlight* flight, double speedKnots
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create an initial heading for user controlled aircraft.
|
|
||||||
void FGAISchedule::setHeading()
|
void FGAISchedule::setHeading()
|
||||||
{
|
{
|
||||||
courseToDest = SGGeodesy::courseDeg((*flights.begin())->getDepartureAirport()->geod(), (*flights.begin())->getArrivalAirport()->geod());
|
courseToDest = SGGeodesy::courseDeg((*flights.begin())->getDepartureAirport()->geod(), (*flights.begin())->getArrivalAirport()->geod());
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
* This file contains the definition of the class Schedule.
|
* This file contains the definition of the class Schedule.
|
||||||
*
|
*
|
||||||
* A schedule is basically a number of scheduled flights, which can be
|
* A schedule is basically a number of scheduled flights, which can be
|
||||||
* assigned to an AI aircraft.
|
* assigned to an AI aircraft.
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
#ifndef _FGSCHEDULE_HXX_
|
#ifndef _FGSCHEDULE_HXX_
|
||||||
|
@ -69,13 +69,13 @@ class FGAISchedule
|
||||||
|
|
||||||
bool scheduleFlights(time_t now);
|
bool scheduleFlights(time_t now);
|
||||||
int groundTimeFromRadius();
|
int groundTimeFromRadius();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transition this schedule from distant mode to AI mode;
|
* Transition this schedule from distant mode to AI mode;
|
||||||
* create the AIAircraft (and flight plan) and register with the AIManager
|
* create the AIAircraft (and flight plan) and register with the AIManager
|
||||||
*/
|
*/
|
||||||
bool createAIAircraft(FGScheduledFlight* flight, double speedKnots, time_t deptime);
|
bool createAIAircraft(FGScheduledFlight* flight, double speedKnots, time_t deptime, time_t remainingTime);
|
||||||
|
|
||||||
// the aiAircraft associated with us
|
// the aiAircraft associated with us
|
||||||
SGSharedPtr<FGAIAircraft> aiAircraft;
|
SGSharedPtr<FGAIAircraft> aiAircraft;
|
||||||
public:
|
public:
|
||||||
|
@ -85,12 +85,12 @@ class FGAISchedule
|
||||||
const std::string& homePort,
|
const std::string& homePort,
|
||||||
const std::string& registration,
|
const std::string& registration,
|
||||||
const std::string& flightId,
|
const std::string& flightId,
|
||||||
bool heavy,
|
bool heavy,
|
||||||
const std::string& acType,
|
const std::string& acType,
|
||||||
const std::string& airline,
|
const std::string& airline,
|
||||||
const std::string& m_class,
|
const std::string& m_class,
|
||||||
const std::string& flight_type,
|
const std::string& flight_type,
|
||||||
double radius,
|
double radius,
|
||||||
double offset); // construct & init
|
double offset); // construct & init
|
||||||
FGAISchedule(const FGAISchedule &other); // copy constructor
|
FGAISchedule(const FGAISchedule &other); // copy constructor
|
||||||
|
|
||||||
|
@ -100,7 +100,7 @@ class FGAISchedule
|
||||||
|
|
||||||
static bool validModelPath(const std::string& model);
|
static bool validModelPath(const std::string& model);
|
||||||
static SGPath resolveModelPath(const std::string& model);
|
static SGPath resolveModelPath(const std::string& model);
|
||||||
|
|
||||||
bool update(time_t now, const SGVec3d& userCart);
|
bool update(time_t now, const SGVec3d& userCart);
|
||||||
bool init();
|
bool init();
|
||||||
|
|
||||||
|
@ -130,7 +130,8 @@ class FGAISchedule
|
||||||
void setHits (unsigned int count) { hits = count; };
|
void setHits (unsigned int count) { hits = count; };
|
||||||
void setScore ();
|
void setScore ();
|
||||||
double getScore () { return score; };
|
double getScore () { return score; };
|
||||||
void setHeading ();
|
/**Create an initial heading for user controlled aircraft.*/
|
||||||
|
void setHeading ();
|
||||||
void assign (FGScheduledFlight *ref);
|
void assign (FGScheduledFlight *ref);
|
||||||
void clearAllFlights();
|
void clearAllFlights();
|
||||||
void setFlightType (const std::string& val) { flightType = val; };
|
void setFlightType (const std::string& val) { flightType = val; };
|
||||||
|
|
|
@ -67,4 +67,18 @@ void VectorMathTests::testInnerTangent2()
|
||||||
auto angles = VectorMath::innerTangentsAngle(m1, m2, r1, r2);
|
auto angles = VectorMath::innerTangentsAngle(m1, m2, r1, r2);
|
||||||
CPPUNIT_ASSERT_DOUBLES_EQUAL( 330, angles[0], 0.1);
|
CPPUNIT_ASSERT_DOUBLES_EQUAL( 330, angles[0], 0.1);
|
||||||
CPPUNIT_ASSERT_DOUBLES_EQUAL( 30, angles[1], 0.1);
|
CPPUNIT_ASSERT_DOUBLES_EQUAL( 30, angles[1], 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VectorMathTests::testOuterTanget()
|
||||||
|
{
|
||||||
|
double r1 = 10;
|
||||||
|
double r2 = 50;
|
||||||
|
// when the circles are dist appart the angle will be 45°
|
||||||
|
double dist = 40;
|
||||||
|
SGGeod m1 = SGGeod::fromDeg(9,51);
|
||||||
|
SGGeod m2 = SGGeodesy::direct(m1, 90, dist);
|
||||||
|
|
||||||
|
auto angles = VectorMath::outerTangentsAngle(m1, m2, r1, r2);
|
||||||
|
CPPUNIT_ASSERT_DOUBLES_EQUAL( 45, angles[0], 0.1);
|
||||||
|
CPPUNIT_ASSERT_DOUBLES_EQUAL( 135, angles[1], 0.1);
|
||||||
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@ class VectorMathTests : public CppUnit::TestFixture
|
||||||
CPPUNIT_TEST_SUITE(VectorMathTests);
|
CPPUNIT_TEST_SUITE(VectorMathTests);
|
||||||
CPPUNIT_TEST(testInnerTanget);
|
CPPUNIT_TEST(testInnerTanget);
|
||||||
CPPUNIT_TEST(testInnerTangent2);
|
CPPUNIT_TEST(testInnerTangent2);
|
||||||
|
CPPUNIT_TEST(testOuterTanget);
|
||||||
|
|
||||||
CPPUNIT_TEST_SUITE_END();
|
CPPUNIT_TEST_SUITE_END();
|
||||||
|
|
||||||
|
@ -49,4 +50,5 @@ public:
|
||||||
// The tests.
|
// The tests.
|
||||||
void testInnerTanget();
|
void testInnerTanget();
|
||||||
void testInnerTangent2();
|
void testInnerTangent2();
|
||||||
|
void testOuterTanget();
|
||||||
};
|
};
|
||||||
|
|
|
@ -156,7 +156,8 @@ void TrafficTests::testPushback()
|
||||||
departureTime = departureTime + 90;
|
departureTime = departureTime + 90;
|
||||||
|
|
||||||
std::unique_ptr<FGAIFlightPlan> fp(new FGAIFlightPlan(aiAircraft,
|
std::unique_ptr<FGAIFlightPlan> fp(new FGAIFlightPlan(aiAircraft,
|
||||||
flightPlanName, crs, departureTime,
|
flightPlanName, crs,
|
||||||
|
departureTime, departureTime+3000,
|
||||||
departureAirport, arrivalAirport, true, radius,
|
departureAirport, arrivalAirport, true, radius,
|
||||||
cruiseAltFt, // cruise alt
|
cruiseAltFt, // cruise alt
|
||||||
position.getLatitudeDeg(),
|
position.getLatitudeDeg(),
|
||||||
|
@ -214,7 +215,8 @@ void TrafficTests::testPushbackCargo()
|
||||||
|
|
||||||
|
|
||||||
std::unique_ptr<FGAIFlightPlan> fp(new FGAIFlightPlan(aiAircraft,
|
std::unique_ptr<FGAIFlightPlan> fp(new FGAIFlightPlan(aiAircraft,
|
||||||
flightPlanName, crs, departureTime,
|
flightPlanName, crs,
|
||||||
|
departureTime, departureTime+3000,
|
||||||
egph, egpf, true, radius,
|
egph, egpf, true, radius,
|
||||||
cruiseAltFt, // cruise alt
|
cruiseAltFt, // cruise alt
|
||||||
position.getLatitudeDeg(),
|
position.getLatitudeDeg(),
|
||||||
|
@ -230,6 +232,253 @@ void TrafficTests::testPushbackCargo()
|
||||||
aiAircraft = flyAI(aiAircraft, "flight_cargo_EGPH_EGPF_" + std::to_string(departureTime));
|
aiAircraft = flyAI(aiAircraft, "flight_cargo_EGPH_EGPF_" + std::to_string(departureTime));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TrafficTests::testPushbackCargoInProgress()
|
||||||
|
{
|
||||||
|
FGAirportRef egph = FGAirport::getByIdent("EGPH");
|
||||||
|
|
||||||
|
FGAirportRef egpf = FGAirport::getByIdent("EGPF");
|
||||||
|
fgSetString("/sim/presets/airport-id", "EGPH");
|
||||||
|
|
||||||
|
// Time to depart
|
||||||
|
std::string dep = getTimeString(-100);
|
||||||
|
// Time to arrive
|
||||||
|
std::string arr = getTimeString(190);
|
||||||
|
|
||||||
|
|
||||||
|
FGAISchedule* schedule = new FGAISchedule(
|
||||||
|
"B737", "KLM", "EGPH", "G-BLA", "ID", false, "B737", "KLM", "N", "cargo", 24, 8);
|
||||||
|
FGScheduledFlight* flight = new FGScheduledFlight("testPushbackCargo", "", "EGPH", "EGPF", 24, dep, arr, "WEEK", "HBR_BN_2");
|
||||||
|
schedule->assign(flight);
|
||||||
|
|
||||||
|
SGSharedPtr<FGAIAircraft> aiAircraft = new FGAIAircraft{schedule};
|
||||||
|
|
||||||
|
const SGGeod position = SGGeodesy::direct(egph->geod(), 270, 50000);
|
||||||
|
const double crs = SGGeodesy::courseDeg(position, egpf->geod()); // direct course
|
||||||
|
ParkingAssignment parking = egph->getDynamics()->getParkingByName("north-cargo208");
|
||||||
|
|
||||||
|
FGTestApi::setPositionAndStabilise(egph->getDynamics()->getParkingByName("ga206").parking()->geod());
|
||||||
|
|
||||||
|
aiAircraft->setPerformance("jet_transport", "");
|
||||||
|
aiAircraft->setCompany("KLM");
|
||||||
|
aiAircraft->setAcType("B737");
|
||||||
|
aiAircraft->setSpeed(0);
|
||||||
|
aiAircraft->setBank(0);
|
||||||
|
aiAircraft->setHeading(crs);
|
||||||
|
|
||||||
|
const string flightPlanName = egph->getId() + "-" + egpf->getId() + ".xml";
|
||||||
|
|
||||||
|
const int radius = 16.0;
|
||||||
|
const int cruiseAltFt = 32000;
|
||||||
|
const int cruiseSpeedKnots = 80;
|
||||||
|
|
||||||
|
time_t departureTime = globals->get_time_params()->get_cur_time();
|
||||||
|
departureTime = departureTime - 6000;
|
||||||
|
|
||||||
|
|
||||||
|
std::unique_ptr<FGAIFlightPlan> fp(new FGAIFlightPlan(aiAircraft,
|
||||||
|
flightPlanName, crs,
|
||||||
|
departureTime, 100,
|
||||||
|
egph, egpf, true, radius,
|
||||||
|
cruiseAltFt, // cruise alt
|
||||||
|
position.getLatitudeDeg(),
|
||||||
|
position.getLongitudeDeg(),
|
||||||
|
cruiseSpeedKnots, "cargo",
|
||||||
|
aiAircraft->getAcType(),
|
||||||
|
aiAircraft->getCompany()));
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL(fp->isValidPlan(), true);
|
||||||
|
aiAircraft->FGAIBase::setFlightPlan(std::move(fp));
|
||||||
|
globals->get_subsystem<FGAIManager>()->attach(aiAircraft);
|
||||||
|
|
||||||
|
aiAircraft = flyAI(aiAircraft, "flight_cargo_in_progress_EGPH_EGPF_" + std::to_string(departureTime));
|
||||||
|
}
|
||||||
|
|
||||||
|
void TrafficTests::testPushbackCargoInProgressDownWind()
|
||||||
|
{
|
||||||
|
FGAirportRef egph = FGAirport::getByIdent("EGPH");
|
||||||
|
|
||||||
|
FGAirportRef egpf = FGAirport::getByIdent("EGPF");
|
||||||
|
fgSetString("/sim/presets/airport-id", "EGPH");
|
||||||
|
|
||||||
|
// Time to depart
|
||||||
|
std::string dep = getTimeString(-100);
|
||||||
|
// Time to arrive
|
||||||
|
std::string arr = getTimeString(190);
|
||||||
|
|
||||||
|
|
||||||
|
FGAISchedule* schedule = new FGAISchedule(
|
||||||
|
"B737", "KLM", "EGPH", "G-BLA", "ID", false, "B737", "KLM", "N", "cargo", 24, 8);
|
||||||
|
FGScheduledFlight* flight = new FGScheduledFlight("testPushbackCargoInProgressDownWind", "", "EGPH", "EGPF", 24, dep, arr, "WEEK", "HBR_BN_2");
|
||||||
|
schedule->assign(flight);
|
||||||
|
|
||||||
|
SGSharedPtr<FGAIAircraft> aiAircraft = new FGAIAircraft{schedule};
|
||||||
|
|
||||||
|
const SGGeod position = SGGeodesy::direct(egph->geod(), 0, 50000);
|
||||||
|
const double crs = SGGeodesy::courseDeg(position, egpf->geod()); // direct course
|
||||||
|
ParkingAssignment parking = egph->getDynamics()->getParkingByName("north-cargo208");
|
||||||
|
|
||||||
|
FGTestApi::setPositionAndStabilise(egph->getDynamics()->getParkingByName("ga206").parking()->geod());
|
||||||
|
|
||||||
|
aiAircraft->setPerformance("jet_transport", "");
|
||||||
|
aiAircraft->setCompany("KLM");
|
||||||
|
aiAircraft->setAcType("B737");
|
||||||
|
aiAircraft->setSpeed(0);
|
||||||
|
aiAircraft->setBank(0);
|
||||||
|
aiAircraft->setHeading(crs);
|
||||||
|
|
||||||
|
const string flightPlanName = egph->getId() + "-" + egpf->getId() + ".xml";
|
||||||
|
|
||||||
|
const int radius = 16.0;
|
||||||
|
const int cruiseAltFt = 32000;
|
||||||
|
const int cruiseSpeedKnots = 80;
|
||||||
|
|
||||||
|
time_t departureTime = globals->get_time_params()->get_cur_time();
|
||||||
|
departureTime = departureTime - 6000;
|
||||||
|
|
||||||
|
|
||||||
|
std::unique_ptr<FGAIFlightPlan> fp(new FGAIFlightPlan(aiAircraft,
|
||||||
|
flightPlanName, crs,
|
||||||
|
departureTime, 100,
|
||||||
|
egph, egpf, true, radius,
|
||||||
|
cruiseAltFt, // cruise alt
|
||||||
|
position.getLatitudeDeg(),
|
||||||
|
position.getLongitudeDeg(),
|
||||||
|
cruiseSpeedKnots, "cargo",
|
||||||
|
aiAircraft->getAcType(),
|
||||||
|
aiAircraft->getCompany()));
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL(fp->isValidPlan(), true);
|
||||||
|
aiAircraft->FGAIBase::setFlightPlan(std::move(fp));
|
||||||
|
globals->get_subsystem<FGAIManager>()->attach(aiAircraft);
|
||||||
|
|
||||||
|
aiAircraft = flyAI(aiAircraft, "flight_cargo_in_progress_downwind_EGPH_EGPF_" + std::to_string(departureTime));
|
||||||
|
}
|
||||||
|
|
||||||
|
void TrafficTests::testPushbackCargoInProgressNotBeyond()
|
||||||
|
{
|
||||||
|
FGAirportRef egph = FGAirport::getByIdent("EGPH");
|
||||||
|
|
||||||
|
FGAirportRef egpf = FGAirport::getByIdent("EGPF");
|
||||||
|
fgSetString("/sim/presets/airport-id", "EGPH");
|
||||||
|
|
||||||
|
// Time to depart
|
||||||
|
std::string dep = getTimeString(-100);
|
||||||
|
// Time to arrive
|
||||||
|
std::string arr = getTimeString(190);
|
||||||
|
|
||||||
|
|
||||||
|
FGAISchedule* schedule = new FGAISchedule(
|
||||||
|
"B737", "KLM", "EGPH", "G-BLA", "ID", false, "B737", "KLM", "N", "cargo", 24, 8);
|
||||||
|
FGScheduledFlight* flight = new FGScheduledFlight("testPushbackCargo", "", "EGPH", "EGPF", 24, dep, arr, "WEEK", "HBR_BN_2");
|
||||||
|
schedule->assign(flight);
|
||||||
|
|
||||||
|
SGSharedPtr<FGAIAircraft> aiAircraft = new FGAIAircraft{schedule};
|
||||||
|
|
||||||
|
// Position west of runway
|
||||||
|
const SGGeod position = SGGeodesy::direct(egpf->geod(), 270, 5000);
|
||||||
|
const double crs = SGGeodesy::courseDeg(position, egpf->geod()); // direct course
|
||||||
|
ParkingAssignment parking = egph->getDynamics()->getParkingByName("north-cargo208");
|
||||||
|
|
||||||
|
FGTestApi::setPositionAndStabilise(egph->getDynamics()->getParkingByName("ga206").parking()->geod());
|
||||||
|
|
||||||
|
aiAircraft->setPerformance("jet_transport", "");
|
||||||
|
aiAircraft->setCompany("KLM");
|
||||||
|
aiAircraft->setAcType("B737");
|
||||||
|
aiAircraft->setSpeed(0);
|
||||||
|
aiAircraft->setBank(0);
|
||||||
|
aiAircraft->setHeading(crs);
|
||||||
|
|
||||||
|
const string flightPlanName = egph->getId() + "-" + egpf->getId() + ".xml";
|
||||||
|
|
||||||
|
const int radius = 16.0;
|
||||||
|
const int cruiseAltFt = 32000;
|
||||||
|
const int cruiseSpeedKnots = 80;
|
||||||
|
|
||||||
|
time_t departureTime = globals->get_time_params()->get_cur_time();
|
||||||
|
departureTime = departureTime - 6000;
|
||||||
|
|
||||||
|
|
||||||
|
std::unique_ptr<FGAIFlightPlan> fp(new FGAIFlightPlan(aiAircraft,
|
||||||
|
flightPlanName, crs,
|
||||||
|
departureTime, 100,
|
||||||
|
egph, egpf, true, radius,
|
||||||
|
cruiseAltFt, // cruise alt
|
||||||
|
position.getLatitudeDeg(),
|
||||||
|
position.getLongitudeDeg(),
|
||||||
|
cruiseSpeedKnots, "cargo",
|
||||||
|
aiAircraft->getAcType(),
|
||||||
|
aiAircraft->getCompany()));
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL(fp->isValidPlan(), true);
|
||||||
|
aiAircraft->FGAIBase::setFlightPlan(std::move(fp));
|
||||||
|
globals->get_subsystem<FGAIManager>()->attach(aiAircraft);
|
||||||
|
|
||||||
|
aiAircraft = flyAI(aiAircraft, "flight_cargo_in_progress_not_beyond_EGPH_EGPF_" + std::to_string(departureTime));
|
||||||
|
}
|
||||||
|
|
||||||
|
void TrafficTests::testPushbackCargoInProgressBeyond()
|
||||||
|
{
|
||||||
|
FGAirportRef egph = FGAirport::getByIdent("EGPH");
|
||||||
|
|
||||||
|
FGAirportRef egpf = FGAirport::getByIdent("EGPF");
|
||||||
|
fgSetString("/sim/presets/airport-id", "EGPH");
|
||||||
|
|
||||||
|
// Time to depart
|
||||||
|
std::string dep = getTimeString(-100);
|
||||||
|
// Time to arrive
|
||||||
|
std::string arr = getTimeString(190);
|
||||||
|
|
||||||
|
|
||||||
|
FGAISchedule* schedule = new FGAISchedule(
|
||||||
|
"B737", "KLM", "EGPH", "G-BLA", "ID", false, "B737", "KLM", "N", "cargo", 24, 8);
|
||||||
|
FGScheduledFlight* flight = new FGScheduledFlight("testPushbackCargo", "", "EGPH", "EGPF", 24, dep, arr, "WEEK", "HBR_BN_2");
|
||||||
|
schedule->assign(flight);
|
||||||
|
|
||||||
|
SGSharedPtr<FGAIAircraft> aiAircraft = new FGAIAircraft{schedule};
|
||||||
|
|
||||||
|
// Position east of runway pointing away from runway
|
||||||
|
const SGGeod position = SGGeodesy::direct(egpf->geod(), 90, 5000);
|
||||||
|
|
||||||
|
const double crs = SGMiscd::normalizePeriodic(0, 360, SGGeodesy::courseDeg(position, egpf->geod()));
|
||||||
|
ParkingAssignment parking = egph->getDynamics()->getParkingByName("north-cargo208");
|
||||||
|
|
||||||
|
FGTestApi::setPositionAndStabilise(egph->getDynamics()->getParkingByName("ga206").parking()->geod());
|
||||||
|
|
||||||
|
aiAircraft->setPerformance("jet_transport", "");
|
||||||
|
aiAircraft->setCompany("KLM");
|
||||||
|
aiAircraft->setAcType("B737");
|
||||||
|
aiAircraft->setSpeed(0);
|
||||||
|
aiAircraft->setBank(0);
|
||||||
|
aiAircraft->setHeading(crs);
|
||||||
|
|
||||||
|
const string flightPlanName = egph->getId() + "-" + egpf->getId() + ".xml";
|
||||||
|
|
||||||
|
const int radius = 16.0;
|
||||||
|
const int cruiseAltFt = 32000;
|
||||||
|
const int cruiseSpeedKnots = 80;
|
||||||
|
|
||||||
|
time_t departureTime = globals->get_time_params()->get_cur_time();
|
||||||
|
departureTime = departureTime - 6000;
|
||||||
|
|
||||||
|
|
||||||
|
std::unique_ptr<FGAIFlightPlan> fp(new FGAIFlightPlan(aiAircraft,
|
||||||
|
flightPlanName, crs,
|
||||||
|
departureTime, 100,
|
||||||
|
egph, egpf, true, radius,
|
||||||
|
cruiseAltFt, // cruise alt
|
||||||
|
position.getLatitudeDeg(),
|
||||||
|
position.getLongitudeDeg(),
|
||||||
|
cruiseSpeedKnots, "cargo",
|
||||||
|
aiAircraft->getAcType(),
|
||||||
|
aiAircraft->getCompany()));
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL(fp->isValidPlan(), true);
|
||||||
|
aiAircraft->FGAIBase::setFlightPlan(std::move(fp));
|
||||||
|
globals->get_subsystem<FGAIManager>()->attach(aiAircraft);
|
||||||
|
|
||||||
|
aiAircraft = flyAI(aiAircraft, "flight_cargo_in_progress_beyond_EGPH_EGPF_" + std::to_string(departureTime));
|
||||||
|
}
|
||||||
|
|
||||||
void TrafficTests::testChangeRunway()
|
void TrafficTests::testChangeRunway()
|
||||||
{
|
{
|
||||||
FGAirportRef departureAirport = FGAirport::getByIdent("EGPH");
|
FGAirportRef departureAirport = FGAirport::getByIdent("EGPH");
|
||||||
|
@ -274,7 +523,8 @@ void TrafficTests::testChangeRunway()
|
||||||
|
|
||||||
|
|
||||||
std::unique_ptr<FGAIFlightPlan> fp(new FGAIFlightPlan(aiAircraft,
|
std::unique_ptr<FGAIFlightPlan> fp(new FGAIFlightPlan(aiAircraft,
|
||||||
flightPlanName, crs, departureTime,
|
flightPlanName, crs,
|
||||||
|
departureTime, departureTime+3000,
|
||||||
departureAirport, arrivalAirport, true, radius,
|
departureAirport, arrivalAirport, true, radius,
|
||||||
cruiseAltFt, // cruise alt
|
cruiseAltFt, // cruise alt
|
||||||
position.getLatitudeDeg(),
|
position.getLatitudeDeg(),
|
||||||
|
@ -287,7 +537,7 @@ void TrafficTests::testChangeRunway()
|
||||||
aiAircraft->FGAIBase::setFlightPlan(std::move(fp));
|
aiAircraft->FGAIBase::setFlightPlan(std::move(fp));
|
||||||
globals->get_subsystem<FGAIManager>()->attach(aiAircraft);
|
globals->get_subsystem<FGAIManager>()->attach(aiAircraft);
|
||||||
|
|
||||||
aiAircraft = flyAI(aiAircraft, "flight_runway_EGPH_EGPF_" + std::to_string(departureTime));
|
aiAircraft = flyAI(aiAircraft, "flight_change_runway_EGPH_EGPF_" + std::to_string(departureTime));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -332,7 +582,8 @@ void TrafficTests::testPushforward()
|
||||||
|
|
||||||
|
|
||||||
std::unique_ptr<FGAIFlightPlan> fp(new FGAIFlightPlan(aiAircraft,
|
std::unique_ptr<FGAIFlightPlan> fp(new FGAIFlightPlan(aiAircraft,
|
||||||
flightPlanName, crs, departureTime,
|
flightPlanName, crs,
|
||||||
|
departureTime, departureTime+3000,
|
||||||
departureAirport, arrivalAirport, true, radius,
|
departureAirport, arrivalAirport, true, radius,
|
||||||
cruiseAltFt, // cruise alt
|
cruiseAltFt, // cruise alt
|
||||||
position.getLatitudeDeg(),
|
position.getLatitudeDeg(),
|
||||||
|
@ -389,7 +640,8 @@ void TrafficTests::testPushforwardSpeedy()
|
||||||
|
|
||||||
|
|
||||||
std::unique_ptr<FGAIFlightPlan> fp(new FGAIFlightPlan(aiAircraft,
|
std::unique_ptr<FGAIFlightPlan> fp(new FGAIFlightPlan(aiAircraft,
|
||||||
flightPlanName, crs, departureTime,
|
flightPlanName, crs,
|
||||||
|
departureTime, departureTime+3000,
|
||||||
departureAirport, arrivalAirport, true, radius,
|
departureAirport, arrivalAirport, true, radius,
|
||||||
cruiseAltFt, // cruise alt
|
cruiseAltFt, // cruise alt
|
||||||
position.getLatitudeDeg(),
|
position.getLatitudeDeg(),
|
||||||
|
@ -447,7 +699,8 @@ void TrafficTests::testPushforwardParkYBBN()
|
||||||
|
|
||||||
|
|
||||||
std::unique_ptr<FGAIFlightPlan> fp(new FGAIFlightPlan(aiAircraft,
|
std::unique_ptr<FGAIFlightPlan> fp(new FGAIFlightPlan(aiAircraft,
|
||||||
flightPlanName, crs, departureTime,
|
flightPlanName, crs,
|
||||||
|
departureTime, departureTime+3000,
|
||||||
departureAirport, arrivalAirport, true, radius,
|
departureAirport, arrivalAirport, true, radius,
|
||||||
cruiseAltFt, // cruise alt
|
cruiseAltFt, // cruise alt
|
||||||
position.getLatitudeDeg(),
|
position.getLatitudeDeg(),
|
||||||
|
@ -528,7 +781,7 @@ void TrafficTests::testPushforwardParkYBBNRepeatGa()
|
||||||
|
|
||||||
|
|
||||||
std::unique_ptr<FGAIFlightPlan> fp(new FGAIFlightPlan(aiAircraft,
|
std::unique_ptr<FGAIFlightPlan> fp(new FGAIFlightPlan(aiAircraft,
|
||||||
flightPlanName, crs, departureTime,
|
flightPlanName, crs, departureTime, departureTime+3000,
|
||||||
departureAirport, arrivalAirport, true, radius,
|
departureAirport, arrivalAirport, true, radius,
|
||||||
cruiseAltFt, // cruise alt
|
cruiseAltFt, // cruise alt
|
||||||
position.getLatitudeDeg(),
|
position.getLatitudeDeg(),
|
||||||
|
@ -604,7 +857,8 @@ void TrafficTests::testPushforwardParkYBBNRepeatGaDelayed()
|
||||||
|
|
||||||
|
|
||||||
std::unique_ptr<FGAIFlightPlan> fp(new FGAIFlightPlan(aiAircraft,
|
std::unique_ptr<FGAIFlightPlan> fp(new FGAIFlightPlan(aiAircraft,
|
||||||
flightPlanName, crs, departureTime,
|
flightPlanName, crs,
|
||||||
|
departureTime, departureTime+3000,
|
||||||
departureAirport, arrivalAirport, true, radius,
|
departureAirport, arrivalAirport, true, radius,
|
||||||
cruiseAltFt, // cruise alt
|
cruiseAltFt, // cruise alt
|
||||||
position.getLatitudeDeg(),
|
position.getLatitudeDeg(),
|
||||||
|
@ -700,7 +954,8 @@ void TrafficTests::testPushforwardParkYBBNRepeatGate()
|
||||||
|
|
||||||
|
|
||||||
std::unique_ptr<FGAIFlightPlan> fp(new FGAIFlightPlan(aiAircraft,
|
std::unique_ptr<FGAIFlightPlan> fp(new FGAIFlightPlan(aiAircraft,
|
||||||
flightPlanName, crs, departureTime,
|
flightPlanName, crs,
|
||||||
|
departureTime, departureTime+3000,
|
||||||
departureAirport, arrivalAirport, true, radius,
|
departureAirport, arrivalAirport, true, radius,
|
||||||
cruiseAltFt, // cruise alt
|
cruiseAltFt, // cruise alt
|
||||||
position.getLatitudeDeg(),
|
position.getLatitudeDeg(),
|
||||||
|
|
|
@ -37,12 +37,16 @@ class TrafficTests : public CppUnit::TestFixture
|
||||||
CPPUNIT_TEST_SUITE(TrafficTests);
|
CPPUNIT_TEST_SUITE(TrafficTests);
|
||||||
CPPUNIT_TEST(testPushback);
|
CPPUNIT_TEST(testPushback);
|
||||||
CPPUNIT_TEST(testPushbackCargo);
|
CPPUNIT_TEST(testPushbackCargo);
|
||||||
|
CPPUNIT_TEST(testPushbackCargoInProgress);
|
||||||
|
CPPUNIT_TEST(testPushbackCargoInProgressDownWind);
|
||||||
|
CPPUNIT_TEST(testPushbackCargoInProgressNotBeyond);
|
||||||
|
CPPUNIT_TEST(testPushbackCargoInProgressBeyond);
|
||||||
CPPUNIT_TEST(testChangeRunway);
|
CPPUNIT_TEST(testChangeRunway);
|
||||||
CPPUNIT_TEST(testPushforward);
|
CPPUNIT_TEST(testPushforward);
|
||||||
CPPUNIT_TEST(testPushforwardSpeedy);
|
CPPUNIT_TEST(testPushforwardSpeedy);
|
||||||
CPPUNIT_TEST(testPushforwardParkYBBN);
|
CPPUNIT_TEST(testPushforwardParkYBBN);
|
||||||
CPPUNIT_TEST(testPushforwardParkYBBNRepeatGa);
|
CPPUNIT_TEST(testPushforwardParkYBBNRepeatGa);
|
||||||
CPPUNIT_TEST(testPushforwardParkYBBNRepeatGaDelayed);
|
CPPUNIT_TEST(testPushforwardParkYBBNRepeatGaDelayed);
|
||||||
CPPUNIT_TEST(testPushforwardParkYBBNRepeatGate);
|
CPPUNIT_TEST(testPushforwardParkYBBNRepeatGate);
|
||||||
CPPUNIT_TEST_SUITE_END();
|
CPPUNIT_TEST_SUITE_END();
|
||||||
public:
|
public:
|
||||||
|
@ -55,6 +59,10 @@ public:
|
||||||
// Pushback Tests
|
// Pushback Tests
|
||||||
void testPushback();
|
void testPushback();
|
||||||
void testPushbackCargo();
|
void testPushbackCargo();
|
||||||
|
void testPushbackCargoInProgress();
|
||||||
|
void testPushbackCargoInProgressDownWind();
|
||||||
|
void testPushbackCargoInProgressNotBeyond();
|
||||||
|
void testPushbackCargoInProgressBeyond();
|
||||||
void testChangeRunway();
|
void testChangeRunway();
|
||||||
//GA Tests with forward push
|
//GA Tests with forward push
|
||||||
void testPushforward();
|
void testPushforward();
|
||||||
|
|
Loading…
Reference in a new issue