Some tweaks and finetuning made possible by the multihreaded modelloader
and the pushback code: - Traffic manager starts modelload requests immediately upon program loading - Only create legs 1 (push back) or five (cruise) of AI traffic. - AIAircraft's rather obsessive behavior to circle around a waypoint is largely resolved - More realistic ground steering for AI aircraft.
This commit is contained in:
parent
78aaa1ce7a
commit
7783e64953
4 changed files with 77 additions and 43 deletions
|
@ -1,4 +1,4 @@
|
||||||
// // FGAIAircraft - FGAIBase-derived class creates an AI airplane
|
// // // FGAIAircraft - FGAIBase-derived class creates an AI airplane
|
||||||
//
|
//
|
||||||
// Written by David Culp, started October 2003.
|
// Written by David Culp, started October 2003.
|
||||||
//
|
//
|
||||||
|
@ -290,7 +290,7 @@ void FGAIAircraft::ProcessFlightPlan( double dt, time_t now ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (next) {
|
if (next) {
|
||||||
fp->setLeadDistance(speed, tgt_heading, curr, next);
|
fp->setLeadDistance(tgt_speed, tgt_heading, curr, next);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(prev->on_ground)) // only update the tgt altitude from flightplan if not on the ground
|
if (!(prev->on_ground)) // only update the tgt altitude from flightplan if not on the ground
|
||||||
|
@ -522,6 +522,7 @@ void FGAIAircraft::processATC(FGATCInstruction instruction) {
|
||||||
|
|
||||||
void FGAIAircraft::handleFirstWaypoint() {
|
void FGAIAircraft::handleFirstWaypoint() {
|
||||||
bool eraseWaypoints; //TODO YAGNI
|
bool eraseWaypoints; //TODO YAGNI
|
||||||
|
headingError = 0;
|
||||||
if (trafficRef) {
|
if (trafficRef) {
|
||||||
eraseWaypoints = true;
|
eraseWaypoints = true;
|
||||||
} else {
|
} else {
|
||||||
|
@ -609,7 +610,6 @@ bool FGAIAircraft::leadPointReached(FGAIFlightPlan::waypoint* curr) {
|
||||||
|
|
||||||
//cerr << "2" << endl;
|
//cerr << "2" << endl;
|
||||||
double lead_dist = fp->getLeadDistance();
|
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.
|
// experimental: Use fabs, because speed can be negative (I hope) during push_back.
|
||||||
|
|
||||||
if (lead_dist < fabs(2*speed)) {
|
if (lead_dist < fabs(2*speed)) {
|
||||||
|
@ -619,6 +619,8 @@ bool FGAIAircraft::leadPointReached(FGAIFlightPlan::waypoint* curr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//prev_dist_to_go = dist_to_go;
|
//prev_dist_to_go = dist_to_go;
|
||||||
|
//if (dist_to_go < lead_dist)
|
||||||
|
// cerr << trafficRef->getCallSign() << " Distance : " << dist_to_go << ": Lead distance " << lead_dist << " " << curr->name << endl;
|
||||||
return dist_to_go < lead_dist;
|
return dist_to_go < lead_dist;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -819,23 +821,54 @@ void FGAIAircraft::updateHeading() {
|
||||||
// If on ground, calculate heading change directly
|
// If on ground, calculate heading change directly
|
||||||
if (onGround()) {
|
if (onGround()) {
|
||||||
double headingDiff = fabs(hdg-tgt_heading);
|
double headingDiff = fabs(hdg-tgt_heading);
|
||||||
|
double bank_sense = 0.0;
|
||||||
|
/*
|
||||||
|
double diff = fabs(hdg - tgt_heading);
|
||||||
|
if (diff > 180)
|
||||||
|
diff = fabs(diff - 360);
|
||||||
|
|
||||||
|
double sum = hdg + diff;
|
||||||
|
if (sum > 360.0)
|
||||||
|
sum -= 360.0;
|
||||||
|
if (fabs(sum - tgt_heading) < 1.0) {
|
||||||
|
bank_sense = 1.0; // right turn
|
||||||
|
} else {
|
||||||
|
bank_sense = -1.0; // left turn
|
||||||
|
}*/
|
||||||
if (headingDiff > 180)
|
if (headingDiff > 180)
|
||||||
headingDiff = fabs(headingDiff - 360);
|
headingDiff = fabs(headingDiff - 360);
|
||||||
|
double sum = hdg + headingDiff;
|
||||||
groundTargetSpeed = tgt_speed - (tgt_speed * (headingDiff/45));
|
if (sum > 360.0)
|
||||||
|
sum -= 360.0;
|
||||||
|
if (fabs(sum - tgt_heading) > 0.0001) {
|
||||||
|
bank_sense = -1.0;
|
||||||
|
} else {
|
||||||
|
bank_sense = 1.0;
|
||||||
|
}
|
||||||
|
if (trafficRef)
|
||||||
|
//cerr << trafficRef->getCallSign() << " Heading "
|
||||||
|
// << hdg << ". Target " << tgt_heading << ". Diff " << fabs(sum - tgt_heading) << ". Speed " << speed << endl;
|
||||||
|
//if (headingDiff > 60) {
|
||||||
|
groundTargetSpeed = tgt_speed; // * cos(headingDiff * SG_DEGREES_TO_RADIANS);
|
||||||
|
//groundTargetSpeed = tgt_speed - tgt_speed * (headingDiff/180);
|
||||||
|
//} else {
|
||||||
|
// groundTargetSpeed = tgt_speed;
|
||||||
|
//}
|
||||||
if (sign(groundTargetSpeed) != sign(tgt_speed))
|
if (sign(groundTargetSpeed) != sign(tgt_speed))
|
||||||
groundTargetSpeed = 0.21 * sign(tgt_speed); // to prevent speed getting stuck in 'negative' mode
|
groundTargetSpeed = 0.21 * sign(tgt_speed); // to prevent speed getting stuck in 'negative' mode
|
||||||
|
|
||||||
if (headingDiff > 30.0) {
|
if (headingDiff > 30.0) {
|
||||||
// invert if pushed backward
|
// invert if pushed backward
|
||||||
headingChangeRate += dt * sign(roll);
|
headingChangeRate += 10.0 * dt * sign(roll);
|
||||||
|
|
||||||
|
// Clamp the maximum steering rate to 30 degrees per second,
|
||||||
|
// But only do this when the heading error is decreasing.
|
||||||
|
if ((headingDiff < headingError)) {
|
||||||
if (headingChangeRate > 30)
|
if (headingChangeRate > 30)
|
||||||
headingChangeRate = 30;
|
headingChangeRate = 30;
|
||||||
else if (headingChangeRate < -30)
|
else if (headingChangeRate < -30)
|
||||||
headingChangeRate = -30;
|
headingChangeRate = -30;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (fabs(headingChangeRate) > headingDiff)
|
if (fabs(headingChangeRate) > headingDiff)
|
||||||
headingChangeRate = headingDiff*sign(roll);
|
headingChangeRate = headingDiff*sign(roll);
|
||||||
|
@ -843,6 +876,7 @@ void FGAIAircraft::updateHeading() {
|
||||||
headingChangeRate += dt * sign(roll);
|
headingChangeRate += dt * sign(roll);
|
||||||
}
|
}
|
||||||
hdg += headingChangeRate * dt;
|
hdg += headingChangeRate * dt;
|
||||||
|
headingError = headingDiff;
|
||||||
} else {
|
} else {
|
||||||
if (fabs(speed) > 1.0) {
|
if (fabs(speed) > 1.0) {
|
||||||
turn_radius_ft = 0.088362 * speed * speed
|
turn_radius_ft = 0.088362 * speed * speed
|
||||||
|
|
|
@ -95,6 +95,7 @@ private:
|
||||||
double dt_count;
|
double dt_count;
|
||||||
double dt_elev_count;
|
double dt_elev_count;
|
||||||
double headingChangeRate;
|
double headingChangeRate;
|
||||||
|
double headingError;
|
||||||
double groundTargetSpeed;
|
double groundTargetSpeed;
|
||||||
double groundOffset;
|
double groundOffset;
|
||||||
double dt;
|
double dt;
|
||||||
|
|
|
@ -172,7 +172,7 @@ FGAIFlightPlan::FGAIFlightPlan(const std::string& p,
|
||||||
cerr << "Errno = " << errno << endl;
|
cerr << "Errno = " << errno << endl;
|
||||||
if (errno == ENOENT)
|
if (errno == ENOENT)
|
||||||
{
|
{
|
||||||
cerr << "Reason: No such file or directory" << endl;
|
SG_LOG(SG_GENERAL, SG_WARN, "Reason: No such file or directory");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -184,6 +184,7 @@ FGAIFlightPlan::FGAIFlightPlan(const std::string& p,
|
||||||
time_t now = time(NULL) + fgGetLong("/sim/time/warp");
|
time_t now = time(NULL) + fgGetLong("/sim/time/warp");
|
||||||
time_t timeDiff = now-start;
|
time_t timeDiff = now-start;
|
||||||
leg = 1;
|
leg = 1;
|
||||||
|
/*
|
||||||
if ((timeDiff > 300) && (timeDiff < 1200))
|
if ((timeDiff > 300) && (timeDiff < 1200))
|
||||||
leg = 2;
|
leg = 2;
|
||||||
else if ((timeDiff >= 1200) && (timeDiff < 1500))
|
else if ((timeDiff >= 1200) && (timeDiff < 1500))
|
||||||
|
@ -192,6 +193,9 @@ FGAIFlightPlan::FGAIFlightPlan(const std::string& p,
|
||||||
leg = 4;
|
leg = 4;
|
||||||
else if (timeDiff >= 2000)
|
else if (timeDiff >= 2000)
|
||||||
leg = 5;
|
leg = 5;
|
||||||
|
*/
|
||||||
|
if (timeDiff >= 2000)
|
||||||
|
leg = 5;
|
||||||
|
|
||||||
SG_LOG(SG_GENERAL, SG_INFO, "Route from " << dep->getId() << " to " << arr->getId() << ". Set leg to : " << leg);
|
SG_LOG(SG_GENERAL, SG_INFO, "Route from " << dep->getId() << " to " << arr->getId() << ". Set leg to : " << leg);
|
||||||
wpt_iterator = waypoints.begin();
|
wpt_iterator = waypoints.begin();
|
||||||
|
@ -353,39 +357,44 @@ void FGAIFlightPlan::IncrementWaypoint(bool eraseWaypoints )
|
||||||
|
|
||||||
// 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) const{
|
double FGAIFlightPlan::getDistanceToGo(double lat, double lon, waypoint* wp) const{
|
||||||
|
double course, distance;
|
||||||
// get size of a degree2 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);
|
||||||
double lat_diff_ft = fabs(wp->latitude - lat) * ft_per_deg_lat;
|
//double lat_diff_ft = fabs(wp->latitude - lat) * ft_per_deg_lat;
|
||||||
double lon_diff_ft = fabs(wp->longitude - lon) * ft_per_deg_lon;
|
//double lon_diff_ft = fabs(wp->longitude - lon) * ft_per_deg_lon;
|
||||||
return sqrt((lat_diff_ft * lat_diff_ft) + (lon_diff_ft * lon_diff_ft));
|
//return sqrt((lat_diff_ft * lat_diff_ft) + (lon_diff_ft * lon_diff_ft));
|
||||||
|
SGWayPoint sgWp(wp->longitude,wp->latitude, wp->altitude, SGWayPoint::WGS84, string("temp"));
|
||||||
|
sgWp.CourseAndDistance(lon, lat, wp->altitude, &course, &distance);
|
||||||
|
return distance;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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;
|
double turn_radius;
|
||||||
if (fabs(speed) > 1)
|
// Handle Ground steering
|
||||||
|
// At a turn rate of 30 degrees per second, it takes 12 seconds to do a full 360 degree turn
|
||||||
|
// So, to get an estimate of the turn radius, calculate the cicumference of the circle
|
||||||
|
// we travel on. Get the turn radius by dividing by PI (*2).
|
||||||
|
if (speed < 25) {
|
||||||
|
turn_radius = ((360/30)*15) / (2*M_PI);
|
||||||
|
} else
|
||||||
turn_radius = 0.1911 * speed * speed; // an estimate for 25 degrees bank
|
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);
|
||||||
leadInAngle = fabs(inbound - outbound);
|
leadInAngle = fabs(inbound - outbound);
|
||||||
if (leadInAngle > 180.0)
|
if (leadInAngle > 180.0)
|
||||||
leadInAngle = 360.0 - leadInAngle;
|
leadInAngle = 360.0 - leadInAngle;
|
||||||
if (leadInAngle < 1.0) // To prevent lead_dist from getting so small it is skipped
|
//if (leadInAngle < 30.0) // To prevent lead_dist from getting so small it is skipped
|
||||||
leadInAngle = 1.0;
|
// leadInAngle = 30.0;
|
||||||
|
|
||||||
lead_distance = turn_radius * sin(leadInAngle * SG_DEGREES_TO_RADIANS);
|
//lead_distance = turn_radius * sin(leadInAngle * SG_DEGREES_TO_RADIANS);
|
||||||
|
lead_distance = turn_radius * tan((leadInAngle * SG_DEGREES_TO_RADIANS)/2);
|
||||||
// if ((errno == EDOM) || (errno == ERANGE) || lead_distance < 1.0)
|
// if ((errno == EDOM) || (errno == ERANGE) || lead_distance < 1.0)
|
||||||
// {
|
// {
|
||||||
// cerr << "Lead Distance = " << lead_distance
|
|
||||||
// << "Diff = " << diff
|
|
||||||
// << "Turn Radius = " << turn_radius
|
|
||||||
// << "Speed = " << speed << endl;
|
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -167,16 +167,7 @@ void FGTrafficManager::init()
|
||||||
|
|
||||||
void FGTrafficManager::update(double /*dt*/)
|
void FGTrafficManager::update(double /*dt*/)
|
||||||
{
|
{
|
||||||
//SG_LOG( SG_GENERAL, SG_INFO, "Running TrafficManager::Update() ");
|
|
||||||
// Hack alert: Skip running for the first frames 1000 after
|
|
||||||
// initialization to allow proper initialization of wheather stuff
|
|
||||||
// and runway assignments
|
|
||||||
if (runCount < 1000)
|
|
||||||
{
|
|
||||||
runCount++;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
//runCount = 0;
|
|
||||||
time_t now = time(NULL) + fgGetLong("/sim/time/warp");
|
time_t now = time(NULL) + fgGetLong("/sim/time/warp");
|
||||||
if (scheduledAircraft.size() == 0) {
|
if (scheduledAircraft.size() == 0) {
|
||||||
//SG_LOG( SG_GENERAL, SG_INFO, "Returned Running TrafficManager::Update() ");
|
//SG_LOG( SG_GENERAL, SG_INFO, "Returned Running TrafficManager::Update() ");
|
||||||
|
@ -184,7 +175,6 @@ void FGTrafficManager::update(double /*dt*/)
|
||||||
}
|
}
|
||||||
if(currAircraft == scheduledAircraft.end())
|
if(currAircraft == scheduledAircraft.end())
|
||||||
{
|
{
|
||||||
//cerr << "resetting schedule " << endl;
|
|
||||||
currAircraft = scheduledAircraft.begin();
|
currAircraft = scheduledAircraft.begin();
|
||||||
}
|
}
|
||||||
if (!((*currAircraft)->update(now)))
|
if (!((*currAircraft)->update(now)))
|
||||||
|
|
Loading…
Add table
Reference in a new issue