1
0
Fork 0

Better Turnprediction

This commit is contained in:
portree_kid 2021-04-24 20:53:29 +02:00 committed by James Turner
parent 54de08a3b6
commit 8fdc03981c
4 changed files with 102 additions and 43 deletions

View file

@ -290,10 +290,13 @@ void FGAIAircraft::ProcessFlightPlan( double dt, time_t now ) {
FGAIWaypoint* curr = 0; FGAIWaypoint* curr = 0;
// the next plus 1 // the next plus 1
FGAIWaypoint* next = 0; FGAIWaypoint* next = 0;
/**The angle of the next turn.*/
int nextTurnAngle = 0;
prev = fp->getPreviousWaypoint(); prev = fp->getPreviousWaypoint();
curr = fp->getCurrentWaypoint(); curr = fp->getCurrentWaypoint();
next = fp->getNextWaypoint(); next = fp->getNextWaypoint();
nextTurnAngle = fp->getNextTurnAngle();
dt_count += dt; dt_count += dt;
@ -304,12 +307,13 @@ void FGAIAircraft::ProcessFlightPlan( double dt, time_t now ) {
handleFirstWaypoint(); handleFirstWaypoint();
return; return;
} // end of initialization } // end of initialization
if (! fpExecutable(now)) if (!fpExecutable(now)) {
return; return;
}
dt_count = 0; dt_count = 0;
double distanceToDescent; double distanceToDescent;
if(reachedEndOfCruise(distanceToDescent)) { if (reachedEndOfCruise(distanceToDescent)) {
if (!loadNextLeg(distanceToDescent)) { if (!loadNextLeg(distanceToDescent)) {
setDie(true); setDie(true);
return; return;
@ -328,13 +332,11 @@ void FGAIAircraft::ProcessFlightPlan( double dt, time_t now ) {
return; return;
} }
if (! leadPointReached(curr)) { if (!leadPointReached(curr, next, nextTurnAngle)) {
controlHeading(curr); controlHeading(curr);
controlSpeed(curr, next); controlSpeed(curr, next);
} else { } else {
if (curr->isFinished()) //end of the flight plan if (curr->isFinished()) { //end of the flight plan
{
if (fp->getRepeat()) if (fp->getRepeat())
fp->restart(); fp->restart();
else else
@ -350,7 +352,7 @@ void FGAIAircraft::ProcessFlightPlan( double dt, time_t now ) {
//TODO let the fp handle this (loading of next leg) //TODO let the fp handle this (loading of next leg)
fp->IncrementWaypoint( trafficRef != 0 ); fp->IncrementWaypoint( trafficRef != 0 );
if ( ((!(fp->getNextWaypoint()))) && (trafficRef != 0) ) { if (((!(fp->getNextWaypoint()))) && (trafficRef != 0) ) {
if (!loadNextLeg()) { if (!loadNextLeg()) {
setDie(true); setDie(true);
return; return;
@ -358,12 +360,12 @@ void FGAIAircraft::ProcessFlightPlan( double dt, time_t now ) {
} }
prev = fp->getPreviousWaypoint(); prev = fp->getPreviousWaypoint();
SG_LOG(SG_AI, SG_BULK, "Previous WP \t" << prev->getName()); SG_LOG(SG_AI, SG_BULK, "Previous WP \t" << prev->getName() << "\t" << prev->getPos());
curr = fp->getCurrentWaypoint(); curr = fp->getCurrentWaypoint();
SG_LOG(SG_AI, SG_BULK, "Current WP \t" << curr->getName()); SG_LOG(SG_AI, SG_BULK, "Current WP \t" << curr->getName() << "\t" << curr->getPos());
next = fp->getNextWaypoint(); next = fp->getNextWaypoint();
if( next ) { if(next) {
SG_LOG(SG_AI, SG_BULK, "Next WP \t" << next->getName()); SG_LOG(SG_AI, SG_BULK, "Next WP \t" << next->getName() << "\t" << next->getPos());
} }
// Now that we have incremented the waypoints, excute some traffic manager specific code // Now that we have incremented the waypoints, excute some traffic manager specific code
@ -834,34 +836,48 @@ bool FGAIAircraft::fpExecutable(time_t now) {
/** /**
* Check to see if we've reached the lead point for our next turn * Check to see if we've reached the lead point for our next turn
* *
* @param curr * @param curr the WP we are currently targeting at.
* @param next the WP that will follow. Used to detect passed WPs (heading diff curr/next > 120°)
* @param nextTurnAngle to detect sharp corners
* @return * @return
*/ */
bool FGAIAircraft::leadPointReached(FGAIWaypoint* curr) { bool FGAIAircraft::leadPointReached(FGAIWaypoint* curr, FGAIWaypoint* next, int nextTurnAngle) {
double dist_to_go = fp->getDistanceToGo(pos.getLatitudeDeg(), pos.getLongitudeDeg(), curr); double dist_to_go_m = fp->getDistanceToGo(pos.getLatitudeDeg(), pos.getLongitudeDeg(), curr);
// Leaddistance should be ft
//cerr << "2" << endl;
double lead_dist = fp->getLeadDistance(); double lead_dist = fp->getLeadDistance();
// experimental: Use fabs, because speed can be negative (I hope) during push_back. // experimental: Use fabs, because speed can be negative (I hope) during push_back.
if ((dist_to_go < fabs(10.0* speed)) && (speed < 0) && (tgt_speed < 0) && fp->getCurrentWaypoint()->contains("PushBackPoint")) { if ((dist_to_go_m < fabs(10.0* speed)) && (speed < 0) && (tgt_speed < 0) && fp->getCurrentWaypoint()->contains("PushBackPoint")) {
tgt_speed = -(dist_to_go / 10.0); tgt_speed = -(dist_to_go_m / 10.0);
if (tgt_speed > -0.5) { if (tgt_speed > -0.5) {
tgt_speed = -0.5; tgt_speed = -0.5;
} }
if (fp->getPreviousWaypoint()->getSpeed() < tgt_speed) { if (fp->getPreviousWaypoint()->getSpeed() < tgt_speed) {
fp->getPreviousWaypoint()->setSpeed(tgt_speed); fp->getPreviousWaypoint()->setSpeed(tgt_speed);
} }
} }
if (lead_dist < fabs(2*speed)) { if (lead_dist < fabs(2*speed)) {
//don't skip over the waypoint //don't skip over the waypoint
lead_dist = fabs(2*speed); lead_dist = fabs(2*speed);
} }
double bearing = 0; double bearing = 0;
// don't do bearing calculations for ground traffic // don't do bearing calculations for ground traffic
bearing = getBearing(fp->getBearing(pos, curr)); bearing = getBearing(fp->getBearing(pos, curr));
double nextBearing = bearing;
if (next) {
nextBearing = getBearing(fp->getBearing(pos, next));
}
double bearingDiff = fabs(bearing-nextBearing);
if (onGround() && nextTurnAngle > 30 && bearingDiff > 50) {
// Next turn is pretty sharp so we do a preturn
SG_LOG(SG_AI, SG_BULK, "Leadpoint reached due to excessive heading diff " << bearingDiff);
minBearing = 360;
speedFraction = 1.0;
prev_dist_to_go = HUGE_VAL;
return true;
}
if (bearing < minBearing) { if (bearing < minBearing) {
minBearing = bearing; minBearing = bearing;
if (minBearing < 10) { if (minBearing < 10) {
@ -872,16 +888,17 @@ bool FGAIAircraft::leadPointReached(FGAIWaypoint* curr) {
} else { } else {
speedFraction = 1.0; speedFraction = 1.0;
} }
} }
if ((dist_to_go < lead_dist) || if ((dist_to_go_m < lead_dist) ||
((dist_to_go > prev_dist_to_go) && (bearing > (minBearing * 1.1))) ) { ((dist_to_go_m > prev_dist_to_go) && (bearing > (minBearing * 1.1))) ) {
SG_LOG(SG_AI, SG_BULK, "Leadpoint reached " << bearing << "\t" << nextBearing);
minBearing = 360; minBearing = 360;
speedFraction = 1.0; speedFraction = 1.0;
prev_dist_to_go = HUGE_VAL; prev_dist_to_go = HUGE_VAL;
return true; return true;
} else { } else {
prev_dist_to_go = dist_to_go; prev_dist_to_go = dist_to_go_m;
return false; return false;
} }
} }
@ -934,6 +951,7 @@ bool FGAIAircraft::handleAirportEndPoints(FGAIWaypoint* prev, time_t now) {
// This is the last taxi waypoint, and marks the the end of the flight plan // This is the last taxi waypoint, and marks the the end of the flight plan
// so, the schedule should update and wait for the next departure time. // so, the schedule should update and wait for the next departure time.
if (prev->contains("END")) { if (prev->contains("END")) {
//FIXME Heading Error should be reset
time_t nextDeparture = trafficRef->getDepartureTime(); time_t nextDeparture = trafficRef->getDepartureTime();
// make sure to wait at least 20 minutes at parking to prevent "nervous" taxi behavior // make sure to wait at least 20 minutes at parking to prevent "nervous" taxi behavior
if (nextDeparture < (now+1200)) { if (nextDeparture < (now+1200)) {
@ -1102,6 +1120,8 @@ void FGAIAircraft::updateHeading(double dt) {
} }
hdg += headingChangeRate * dt * sqrt(fabs(speed) / 15); hdg += headingChangeRate * dt * sqrt(fabs(speed) / 15);
SG_NORMALIZE_RANGE(headingDiff, 0.0, 360.0);
headingError = headingDiff; headingError = headingDiff;
if (fabs(headingError) < 1.0) { if (fabs(headingError) < 1.0) {
hdg = tgt_heading; hdg = tgt_heading;
@ -1159,7 +1179,6 @@ void FGAIAircraft::updateBankAngleTarget() {
} }
} }
void FGAIAircraft::updateVerticalSpeedTarget(double dt) { void FGAIAircraft::updateVerticalSpeedTarget(double dt) {
// adjust target Altitude, based on ground elevation when on ground // adjust target Altitude, based on ground elevation when on ground
if (onGround()) { if (onGround()) {
@ -1265,7 +1284,6 @@ void FGAIAircraft::updateSecondaryTargetValues(double dt) {
updateBankAngleTarget(); updateBankAngleTarget();
updateVerticalSpeedTarget(dt); updateVerticalSpeedTarget(dt);
updatePitchAngleTarget(); updatePitchAngleTarget();
//TODO calculate wind correction angle (tgt_yaw) //TODO calculate wind correction angle (tgt_yaw)
} }
@ -1296,7 +1314,8 @@ bool FGAIAircraft::reachedEndOfCruise(double &distance) {
double descentTimeNeeded = verticalDistance / descentRate; double descentTimeNeeded = verticalDistance / descentRate;
double distanceCovered = descentSpeed * descentTimeNeeded; double distanceCovered = descentSpeed * descentTimeNeeded;
if (trafficRef->getCallSign() == fgGetString("/ai/track-callsign")) { if (trafficRef->getCallSign() != "" &&
trafficRef->getCallSign() == fgGetString("/ai/track-callsign")) {
cerr << "Checking for end of cruise stage for :" << trafficRef->getCallSign() << endl; cerr << "Checking for end of cruise stage for :" << trafficRef->getCallSign() << endl;
cerr << "Descent rate : " << descentRate << endl; cerr << "Descent rate : " << descentRate << endl;
cerr << "Descent speed : " << descentSpeed << endl; cerr << "Descent speed : " << descentSpeed << endl;
@ -1307,10 +1326,11 @@ bool FGAIAircraft::reachedEndOfCruise(double &distance) {
distance = distanceCovered; distance = distanceCovered;
if (dist < distanceCovered) { if (dist < distanceCovered) {
if (trafficRef->getCallSign() == fgGetString("/ai/track-callsign")) { if (trafficRef->getCallSign() == fgGetString("/ai/track-callsign")) {
//exit(1); //exit(1);
} }
return true; SG_LOG(SG_AI, SG_BULK, "End Of Cruise");
return true;
} else { } else {
return false; return false;
} }
@ -1340,6 +1360,10 @@ void FGAIAircraft::resetPositionFromFlightPlan()
setSpeed(prev->getSpeed()); setSpeed(prev->getSpeed());
} }
/**
* Returns a normalised bearing
*/
double FGAIAircraft::getBearing(double crse) double FGAIAircraft::getBearing(double crse)
{ {
double hdgDiff = fabs(hdg-crse); double hdgDiff = fabs(hdg-crse);
@ -1435,10 +1459,13 @@ void FGAIAircraft::updateModelProperties(double dt)
} }
void FGAIAircraft::dumpCSVHeader(std::ofstream& o) { void FGAIAircraft::dumpCSVHeader(std::ofstream& o) {
o << "Index\t";
o << "Lat\t"; o << "Lat\t";
o << "Lon\t"; o << "Lon\t";
o << "heading change rate\t"; o << "heading change rate\t";
o << "headingErr\t"; o << "headingErr\t";
o << "hdg\t";
o << "tgt_heading\t";
o << "minBearing\t"; o << "minBearing\t";
o << "speedFraction\t"; o << "speedFraction\t";
o << "groundOffset\t"; o << "groundOffset\t";
@ -1449,8 +1476,13 @@ void FGAIAircraft::dumpCSVHeader(std::ofstream& o) {
o << "Bearing\t"; o << "Bearing\t";
o << "headingChangeRate\t"; o << "headingChangeRate\t";
o << "headingError\t"; o << "headingError\t";
o << "Name\tWP Lat\tWP Lon\tDist\t"; o << "Name\t";
o << "Leg\tNum WP\t"; o << "WP Lat\t";
o << "WP Lon\t";
o << "Dist\t";
o << "Time\t";
o << "Leg\t";
o << "Num WP\t";
o << endl; o << endl;
} }
@ -1460,6 +1492,8 @@ void FGAIAircraft::dumpCSV(std::ofstream& o, int lineIndex) {
o << this->getGeodPos().getLongitudeDeg() << "\t"; o << this->getGeodPos().getLongitudeDeg() << "\t";
o << headingChangeRate << "\t"; o << headingChangeRate << "\t";
o << headingError << "\t"; o << headingError << "\t";
o << hdg << "\t";
o << tgt_heading << "\t";
o << minBearing << "\t"; o << minBearing << "\t";
o << speedFraction << "\t"; o << speedFraction << "\t";
o << groundOffset << "\t"; o << groundOffset << "\t";

View file

@ -141,7 +141,7 @@ private:
//subclasses to override specific behaviour //subclasses to override specific behaviour
bool fpExecutable(time_t now); bool fpExecutable(time_t now);
void handleFirstWaypoint(void); void handleFirstWaypoint(void);
bool leadPointReached(FGAIWaypoint* curr); bool leadPointReached(FGAIWaypoint* curr, FGAIWaypoint* next, int nextTurnAngle);
bool handleAirportEndPoints(FGAIWaypoint* prev, time_t now); bool handleAirportEndPoints(FGAIWaypoint* prev, time_t now);
bool reachedEndOfCruise(double&); bool reachedEndOfCruise(double&);
bool aiTrafficVisible(void); bool aiTrafficVisible(void);

View file

@ -357,6 +357,29 @@ FGAIWaypoint* FGAIFlightPlan::getNextWaypoint( void ) const
} }
} }
int FGAIFlightPlan::getNextTurnAngle( void ) const
{
if (wpt_iterator == waypoints.end())
return 0;
if (wpt_iterator+1 == waypoints.end())
return 0;
if (wpt_iterator+2 == waypoints.end())
return 0;
FGAIWaypoint* currentWP = *(wpt_iterator);
FGAIWaypoint* nextWP = *(wpt_iterator + 1);
FGAIWaypoint* afterNextWP = *(wpt_iterator + 2);
int currentBearing = this->getBearing(currentWP, nextWP);
int nextBearing = this->getBearing(nextWP, afterNextWP);
int turnAngle = nextBearing - currentBearing;
if (turnAngle>180) {
turnAngle -= 180;
}
return turnAngle;
}
void FGAIFlightPlan::IncrementWaypoint(bool eraseWaypoints ) void FGAIFlightPlan::IncrementWaypoint(bool eraseWaypoints )
{ {
if (empty()) if (empty())
@ -375,8 +398,9 @@ void FGAIFlightPlan::IncrementWaypoint(bool eraseWaypoints )
wpt_iterator++; wpt_iterator++;
} }
} }
else else {
wpt_iterator++; wpt_iterator++;
}
} }
void FGAIFlightPlan::DecrementWaypoint() void FGAIFlightPlan::DecrementWaypoint()

View file

@ -166,6 +166,7 @@ public:
FGAIWaypoint* getPreviousWaypoint( void ) const; FGAIWaypoint* getPreviousWaypoint( void ) const;
FGAIWaypoint* getCurrentWaypoint( void ) const; FGAIWaypoint* getCurrentWaypoint( void ) const;
FGAIWaypoint* getNextWaypoint( void ) const; FGAIWaypoint* getNextWaypoint( void ) const;
int getNextTurnAngle( void ) const;
void IncrementWaypoint( bool erase ); void IncrementWaypoint( bool erase );
void DecrementWaypoint(); void DecrementWaypoint();