1
0
Fork 0

More work on AI/ATC integration:

- Fixed a bug in AI aircraft ground steering code: When aircraft were not moving, the value of headingchangeRate kept increasing to insane levels. Although this was clamped to a maximum of 30 degrees per second, the initial rate could still push the aircraft in the wrong direction. In practice, this bug would be visible when an AI aicraft would be pushed back, when it tended to veer to the right.
 - Make sure that the aircraft slows down well ahead of the pushback point. This change ensures that the AC will actually reach the pushback point. It also ensures a slightly tighter steering range.
 - AI ground steering rate is tuned to 30 degrees per second at a nominal taxispeed of 15. I now modulate the heading adjustment rate by manipulating the adjustment using a non-linear function (the sqrt). This allows for a slightly tighter turn radius at speeds < 15 and slightly looser turns at speeds > 15.
 - The AI Flightplan generation code can return false. This can be used to determine whether any additional AI aircraft may be created. Currently, the function returns false when no more parkings are available. This should limit the build-up of huge AIAircraft tower stacks.
 - The ground network can now graphically display all aircraft actitivy on the ground network by using a virtual marker system.
This commit is contained in:
Durk Talsma 2011-04-19 18:01:24 +02:00
parent ee9a5cf73d
commit a7ccae9fca
14 changed files with 258 additions and 108 deletions

View file

@ -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.
// //
@ -276,6 +276,19 @@ void FGAIAircraft::ProcessFlightPlan( double dt, time_t now ) {
if (! leadPointReached(curr)) { if (! leadPointReached(curr)) {
controlHeading(curr); controlHeading(curr);
controlSpeed(curr, next); controlSpeed(curr, next);
if (speed < 0) {
cerr << getCallSign()
<< ": verifying lead distance to waypoint : "
<< fp->getCurrentWaypoint()->name << " "
<< fp->getLeadDistance() << ". Distance to go "
<< (fp->getDistanceToGo(pos.getLatitudeDeg(), pos.getLongitudeDeg(), curr))
<< ". Target speed = "
<< tgt_speed
<< ". Current speed = "
<< speed
<< ". Minimum Bearing " << minBearing
<< endl;
}
} else { } else {
if (curr->finished) //end of the flight plan if (curr->finished) //end of the flight plan
{ {
@ -676,7 +689,15 @@ bool FGAIAircraft::leadPointReached(FGAIFlightPlan::waypoint* curr) {
//cerr << "2" << endl; //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()->name == string("PushBackPoint")) {
tgt_speed = -(dist_to_go / 10.0);
if (tgt_speed > -0.5) {
tgt_speed = -0.5;
}
if (fp->getPreviousWaypoint()->speed < tgt_speed) {
fp->getPreviousWaypoint()->speed = 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);
@ -936,8 +957,8 @@ void FGAIAircraft::updateHeading() {
bank_sense = 1.0; bank_sense = 1.0;
} }
//if (trafficRef) //if (trafficRef)
//cerr << trafficRef->getCallSign() << " Heading " // cerr << trafficRef->getCallSign() << " Heading "
// << hdg << ". Target " << tgt_heading << ". Diff " << fabs(sum - tgt_heading) << ". Speed " << speed << endl; // << hdg << ". Target " << tgt_heading << ". Diff " << fabs(sum - tgt_heading) << ". Speed " << speed << endl;
//if (headingDiff > 60) { //if (headingDiff > 60) {
groundTargetSpeed = tgt_speed; // * cos(headingDiff * SG_DEGREES_TO_RADIANS); groundTargetSpeed = tgt_speed; // * cos(headingDiff * SG_DEGREES_TO_RADIANS);
//groundTargetSpeed = tgt_speed - tgt_speed * (headingDiff/180); //groundTargetSpeed = tgt_speed - tgt_speed * (headingDiff/180);
@ -946,27 +967,34 @@ void FGAIAircraft::updateHeading() {
//} //}
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
// Only update the target values when we're not moving because otherwise we might introduce an enormous target change rate while waiting a the gate, or holding.
if (speed != 0) {
if (headingDiff > 30.0) {
// invert if pushed backward
headingChangeRate += 10.0 * dt * sign(roll);
if (headingDiff > 30.0) { // Clamp the maximum steering rate to 30 degrees per second,
// invert if pushed backward // But only do this when the heading error is decreasing.
headingChangeRate += 10.0 * dt * sign(roll); if ((headingDiff < headingError)) {
if (headingChangeRate > 30)
// Clamp the maximum steering rate to 30 degrees per second, headingChangeRate = 30;
// But only do this when the heading error is decreasing. else if (headingChangeRate < -30)
if ((headingDiff < headingError)) { headingChangeRate = -30;
if (headingChangeRate > 30) }
headingChangeRate = 30; } else {
else if (headingChangeRate < -30) if (speed != 0) {
headingChangeRate = -30; if (fabs(headingChangeRate) > headingDiff)
headingChangeRate = headingDiff*sign(roll);
else
headingChangeRate += dt * sign(roll);
}
} }
} else {
if (fabs(headingChangeRate) > headingDiff)
headingChangeRate = headingDiff*sign(roll);
else
headingChangeRate += dt * sign(roll);
} }
if (trafficRef)
hdg += headingChangeRate * dt * (fabs(speed) / 15); cerr << trafficRef->getCallSign() << " Heading "
<< hdg << ". Target " << tgt_heading << ". Diff " << fabs(sum - tgt_heading) << ". Speed " << speed << "Heading change rate : " << headingChangeRate << " bacnk sence " << bank_sense << endl;
hdg += headingChangeRate * dt * sqrt(fabs(speed) / 15);
headingError = headingDiff; headingError = headingDiff;
} else { } else {
if (fabs(speed) > 1.0) { if (fabs(speed) > 1.0) {

View file

@ -1,4 +1,4 @@
// FGAIFlightPlan - class for loading and storing AI flight plans // // FGAIFlightPlan - class for loading and storing AI flight plans
// Written by David Culp, started May 2004 // Written by David Culp, started May 2004
// - davidculp2@comcast.net // - davidculp2@comcast.net
// //
@ -50,6 +50,7 @@ FGAIFlightPlan::FGAIFlightPlan()
{ {
sid = 0; sid = 0;
wpt_iterator = waypoints.begin(); wpt_iterator = waypoints.begin();
isValid = true;
} }
FGAIFlightPlan::FGAIFlightPlan(const string& filename) FGAIFlightPlan::FGAIFlightPlan(const string& filename)
@ -98,6 +99,7 @@ FGAIFlightPlan::FGAIFlightPlan(const string& filename)
} }
wpt_iterator = waypoints.begin(); wpt_iterator = waypoints.begin();
isValid = true;
//cout << waypoints.size() << " waypoints read." << endl; //cout << waypoints.size() << " waypoints read." << endl;
} }
@ -137,7 +139,7 @@ FGAIFlightPlan::FGAIFlightPlan(FGAIAircraft *ac,
path.append( p ); path.append( p );
SGPropertyNode root; SGPropertyNode root;
isValid = true;
// This is a bit of a hack: // This is a bit of a hack:
// Normally the value of course will be used to evaluate whether // Normally the value of course will be used to evaluate whether
// or not a waypoint will be used for midair initialization of // or not a waypoint will be used for midair initialization of
@ -205,7 +207,7 @@ FGAIFlightPlan::FGAIFlightPlan(FGAIAircraft *ac,
SG_LOG(SG_GENERAL, SG_INFO, "Route from " << dep->getId() << " to " << arr->getId() << ". Set leg to : " << leg << " " << ac->getTrafficRef()->getCallSign()); SG_LOG(SG_GENERAL, SG_INFO, "Route from " << dep->getId() << " to " << arr->getId() << ". Set leg to : " << leg << " " << ac->getTrafficRef()->getCallSign());
wpt_iterator = waypoints.begin(); wpt_iterator = waypoints.begin();
bool dist = 0; bool dist = 0;
create(ac, dep,arr, leg, alt, speed, lat, lon, isValid = create(ac, dep,arr, leg, alt, speed, lat, lon,
firstLeg, radius, fltType, acType, airline, dist); firstLeg, radius, fltType, acType, airline, dist);
wpt_iterator = waypoints.begin(); wpt_iterator = waypoints.begin();
//cerr << "after create: " << (*wpt_iterator)->name << endl; //cerr << "after create: " << (*wpt_iterator)->name << endl;

View file

@ -87,10 +87,10 @@ public:
time_t getStartTime() const { return start_time; } time_t getStartTime() const { return start_time; }
time_t getArrivalTime() const { return arrivalTime; } time_t getArrivalTime() const { return arrivalTime; }
void create(FGAIAircraft *, FGAirport *dep, FGAirport *arr, int leg, double alt, double speed, double lat, double lon, bool create(FGAIAircraft *, FGAirport *dep, FGAirport *arr, int leg, double alt, double speed, double lat, double lon,
bool firstLeg, double radius, const std::string& fltType, const std::string& aircraftType, const std::string& airline, double distance); bool firstLeg, double radius, const std::string& fltType, const std::string& aircraftType, const std::string& airline, double distance);
void createPushBack(FGAIAircraft *, bool, FGAirport*, double, double, double, const std::string&, const std::string&, const std::string&); bool createPushBack(FGAIAircraft *, bool, FGAirport*, double, double, double, const std::string&, const std::string&, const std::string&);
void createTakeOff(FGAIAircraft *, bool, FGAirport *, double, const std::string&); bool createTakeOff(FGAIAircraft *, bool, FGAirport *, double, const std::string&);
void setLeg(int val) { leg = val;} void setLeg(int val) { leg = val;}
void setTime(time_t st) { start_time = st; } void setTime(time_t st) { start_time = st; }
@ -142,20 +142,21 @@ private:
std::string activeRunway; std::string activeRunway;
FGTaxiRoute *taxiRoute; FGTaxiRoute *taxiRoute;
std::string name; std::string name;
bool isValid;
void createPushBackFallBack(FGAIAircraft *, bool, FGAirport*, double, double, double, const std::string&, const std::string&, const std::string&); void createPushBackFallBack(FGAIAircraft *, bool, FGAirport*, double, double, double, const std::string&, const std::string&, const std::string&);
void createClimb(FGAIAircraft *, bool, FGAirport *, double, double, const std::string&); bool createClimb(FGAIAircraft *, bool, FGAirport *, double, double, const std::string&);
void createCruise(FGAIAircraft *, bool, FGAirport*, FGAirport*, double, double, double, double, const std::string&); bool createCruise(FGAIAircraft *, bool, FGAirport*, FGAirport*, double, double, double, double, const std::string&);
void createDescent(FGAIAircraft *, FGAirport *, double latitude, double longitude, double speed, double alt,const std::string&, double distance); bool createDescent(FGAIAircraft *, FGAirport *, double latitude, double longitude, double speed, double alt,const std::string&, double distance);
void createLanding(FGAIAircraft *, FGAirport *, const std::string&); bool createLanding(FGAIAircraft *, FGAirport *, const std::string&);
void createParking(FGAIAircraft *, FGAirport *, double radius); bool createParking(FGAIAircraft *, FGAirport *, double radius);
void deleteWaypoints(); void deleteWaypoints();
void resetWaypoints(); void resetWaypoints();
void 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);
void createTakeoffTaxi(FGAIAircraft *, bool firstFlight, FGAirport *apt, double radius, const std::string& fltType, const std::string& acType, const std::string& airline); bool createTakeoffTaxi(FGAIAircraft *, bool firstFlight, FGAirport *apt, double radius, const std::string& fltType, const std::string& acType, const std::string& airline);
double getTurnRadius(double, bool); double getTurnRadius(double, bool);
@ -170,7 +171,7 @@ private:
public: public:
wpt_vector_iterator getFirstWayPoint() { return waypoints.begin(); }; wpt_vector_iterator getFirstWayPoint() { return waypoints.begin(); };
wpt_vector_iterator getLastWayPoint() { return waypoints.end(); }; wpt_vector_iterator getLastWayPoint() { return waypoints.end(); };
bool isValidPlan() { return isValid; };
}; };
#endif // _FG_AIFLIGHTPLAN_HXX #endif // _FG_AIFLIGHTPLAN_HXX

View file

@ -47,7 +47,7 @@
// Check lat/lon values during initialization; // Check lat/lon values during initialization;
void FGAIFlightPlan::create(FGAIAircraft * ac, FGAirport * dep, bool FGAIFlightPlan::create(FGAIAircraft * ac, FGAirport * dep,
FGAirport * arr, int legNr, double alt, FGAirport * arr, int legNr, double alt,
double speed, double latitude, double speed, double latitude,
double longitude, bool firstFlight, double longitude, bool firstFlight,
@ -55,38 +55,39 @@ void FGAIFlightPlan::create(FGAIAircraft * ac, FGAirport * dep,
const string & aircraftType, const string & aircraftType,
const string & airline, double distance) const string & airline, double distance)
{ {
bool retVal = true;
int currWpt = wpt_iterator - waypoints.begin(); int currWpt = wpt_iterator - waypoints.begin();
switch (legNr) { switch (legNr) {
case 1: case 1:
createPushBack(ac, firstFlight, dep, latitude, longitude, retVal = createPushBack(ac, firstFlight, dep, latitude, longitude,
radius, fltType, aircraftType, airline); radius, fltType, aircraftType, airline);
break; break;
case 2: case 2:
createTakeoffTaxi(ac, firstFlight, dep, radius, fltType, retVal = createTakeoffTaxi(ac, firstFlight, dep, radius, fltType,
aircraftType, airline); aircraftType, airline);
break; break;
case 3: case 3:
createTakeOff(ac, firstFlight, dep, speed, fltType); retVal = createTakeOff(ac, firstFlight, dep, speed, fltType);
break; break;
case 4: case 4:
createClimb(ac, firstFlight, dep, speed, alt, fltType); retVal = createClimb(ac, firstFlight, dep, speed, alt, fltType);
break; break;
case 5: case 5:
createCruise(ac, firstFlight, dep, arr, latitude, longitude, speed, retVal = createCruise(ac, firstFlight, dep, arr, latitude, longitude, speed,
alt, fltType); alt, fltType);
break; break;
case 6: case 6:
createDescent(ac, arr, latitude, longitude, speed, alt, fltType, retVal = createDescent(ac, arr, latitude, longitude, speed, alt, fltType,
distance); distance);
break; break;
case 7: case 7:
createLanding(ac, arr, fltType); retVal = createLanding(ac, arr, fltType);
break; break;
case 8: case 8:
createLandingTaxi(ac, arr, radius, fltType, aircraftType, airline); retVal = createLandingTaxi(ac, arr, radius, fltType, aircraftType, airline);
break; break;
case 9: case 9:
createParking(ac, arr, radius); retVal = createParking(ac, arr, radius);
break; break;
default: default:
//exit(1); //exit(1);
@ -96,6 +97,7 @@ void FGAIFlightPlan::create(FGAIAircraft * ac, FGAirport * dep,
} }
wpt_iterator = waypoints.begin() + currWpt; wpt_iterator = waypoints.begin() + currWpt;
leg++; leg++;
return retVal;
} }
FGAIFlightPlan::waypoint * FGAIFlightPlan::waypoint *
@ -200,7 +202,7 @@ void FGAIFlightPlan::createDefaultTakeoffTaxi(FGAIAircraft * ac,
waypoints.push_back(wpt); waypoints.push_back(wpt);
} }
void FGAIFlightPlan::createTakeoffTaxi(FGAIAircraft * ac, bool firstFlight, bool FGAIFlightPlan::createTakeoffTaxi(FGAIAircraft * ac, bool firstFlight,
FGAirport * apt, FGAirport * apt,
double radius, double radius,
const string & fltType, const string & fltType,
@ -240,7 +242,7 @@ void FGAIFlightPlan::createTakeoffTaxi(FGAIAircraft * ac, bool firstFlight,
FGGroundNetwork *gn = apt->getDynamics()->getGroundNetwork(); FGGroundNetwork *gn = apt->getDynamics()->getGroundNetwork();
if (!gn->exists()) { if (!gn->exists()) {
createDefaultTakeoffTaxi(ac, apt, rwy); createDefaultTakeoffTaxi(ac, apt, rwy);
return; return true;
} }
intVec ids; intVec ids;
@ -278,7 +280,7 @@ void FGAIFlightPlan::createTakeoffTaxi(FGAIAircraft * ac, bool firstFlight,
if (taxiRoute->empty()) { if (taxiRoute->empty()) {
createDefaultTakeoffTaxi(ac, apt, rwy); createDefaultTakeoffTaxi(ac, apt, rwy);
return; return true;
} }
taxiRoute->first(); taxiRoute->first();
@ -313,6 +315,7 @@ void FGAIFlightPlan::createTakeoffTaxi(FGAIAircraft * ac, bool firstFlight,
wpt->routeIndex = route; wpt->routeIndex = route;
waypoints.push_back(wpt); waypoints.push_back(wpt);
} }
return true;
} }
void FGAIFlightPlan::createDefaultLandingTaxi(FGAIAircraft * ac, void FGAIFlightPlan::createDefaultLandingTaxi(FGAIAircraft * ac,
@ -341,7 +344,7 @@ void FGAIFlightPlan::createDefaultLandingTaxi(FGAIAircraft * ac,
waypoints.push_back(wpt); waypoints.push_back(wpt);
} }
void FGAIFlightPlan::createLandingTaxi(FGAIAircraft * ac, FGAirport * apt, bool FGAIFlightPlan::createLandingTaxi(FGAIAircraft * ac, FGAirport * apt,
double radius, double radius,
const string & fltType, const string & fltType,
const string & acType, const string & acType,
@ -360,7 +363,7 @@ void FGAIFlightPlan::createLandingTaxi(FGAIAircraft * ac, FGAirport * apt,
// Find a route from runway end to parking/gate. // Find a route from runway end to parking/gate.
if (!gn->exists()) { if (!gn->exists()) {
createDefaultLandingTaxi(ac, apt); createDefaultLandingTaxi(ac, apt);
return; return true;
} }
intVec ids; intVec ids;
@ -379,7 +382,7 @@ void FGAIFlightPlan::createLandingTaxi(FGAIAircraft * ac, FGAirport * apt,
if (taxiRoute->empty()) { if (taxiRoute->empty()) {
createDefaultLandingTaxi(ac, apt); createDefaultLandingTaxi(ac, apt);
return; return true;
} }
int node; int node;
@ -399,6 +402,7 @@ void FGAIFlightPlan::createLandingTaxi(FGAIAircraft * ac, FGAirport * apt,
wpt->routeIndex = route; wpt->routeIndex = route;
waypoints.push_back(wpt); waypoints.push_back(wpt);
} }
return true;
} }
/******************************************************************* /*******************************************************************
@ -412,7 +416,7 @@ void FGAIFlightPlan::createLandingTaxi(FGAIAircraft * ac, FGAirport * apt,
* more likely however. * more likely however.
* *
******************************************************************/ ******************************************************************/
void FGAIFlightPlan::createTakeOff(FGAIAircraft * ac, bool firstFlight, bool FGAIFlightPlan::createTakeOff(FGAIAircraft * ac, bool firstFlight,
FGAirport * apt, double speed, FGAirport * apt, double speed,
const string & fltType) const string & fltType)
{ {
@ -487,13 +491,14 @@ void FGAIFlightPlan::createTakeOff(FGAIAircraft * ac, bool firstFlight,
wpt = cloneWithPos(ac, wpt, "5000 ft", pt); wpt = cloneWithPos(ac, wpt, "5000 ft", pt);
wpt->altitude = airportElev + 5000; wpt->altitude = airportElev + 5000;
waypoints.push_back(wpt); waypoints.push_back(wpt);
return true;
} }
/******************************************************************* /*******************************************************************
* CreateClimb * CreateClimb
* initialize the Aircraft at the parking location * initialize the Aircraft at the parking location
******************************************************************/ ******************************************************************/
void FGAIFlightPlan::createClimb(FGAIAircraft * ac, bool firstFlight, bool FGAIFlightPlan::createClimb(FGAIAircraft * ac, bool firstFlight,
FGAirport * apt, double speed, double alt, FGAirport * apt, double speed, double alt,
const string & fltType) const string & fltType)
{ {
@ -527,6 +532,7 @@ void FGAIFlightPlan::createClimb(FGAIAircraft * ac, bool firstFlight,
wpt->altitude = 18000; wpt->altitude = 18000;
waypoints.push_back(wpt); waypoints.push_back(wpt);
} }
return true;
} }
@ -536,7 +542,7 @@ void 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
******************************************************************/ ******************************************************************/
void FGAIFlightPlan::createDescent(FGAIAircraft * ac, FGAirport * apt, bool FGAIFlightPlan::createDescent(FGAIAircraft * ac, FGAirport * apt,
double latitude, double longitude, double latitude, double longitude,
double speed, double alt, double speed, double alt,
const string & fltType, const string & fltType,
@ -823,8 +829,7 @@ void FGAIFlightPlan::createDescent(FGAIAircraft * ac, FGAirport * apt,
//cerr << "Repositioning to waypoint " << (*waypoints.begin())->name << endl; //cerr << "Repositioning to waypoint " << (*waypoints.begin())->name << endl;
ac->resetPositionFromFlightPlan(); ac->resetPositionFromFlightPlan();
} }
return true;
} }
/******************************************************************* /*******************************************************************
@ -833,7 +838,7 @@ void FGAIFlightPlan::createDescent(FGAIAircraft * ac, FGAirport * apt,
hardcoded at 5000 meters from the threshold) to the threshold, at hardcoded at 5000 meters from the threshold) to the threshold, at
a standard glide slope angle of 3 degrees. a standard glide slope angle of 3 degrees.
******************************************************************/ ******************************************************************/
void FGAIFlightPlan::createLanding(FGAIAircraft * ac, FGAirport * apt, bool FGAIFlightPlan::createLanding(FGAIAircraft * ac, FGAirport * apt,
const string & fltType) const string & fltType)
{ {
double vTouchdown = ac->getPerformance()->vTouchdown(); double vTouchdown = ac->getPerformance()->vTouchdown();
@ -873,13 +878,14 @@ void FGAIFlightPlan::createLanding(FGAIAircraft * ac, FGAirport * apt,
wpt->crossat = apt->getElevation(); wpt->crossat = apt->getElevation();
waypoints.push_back(wpt); waypoints.push_back(wpt);
*/ */
return true;
} }
/******************************************************************* /*******************************************************************
* CreateParking * CreateParking
* initialize the Aircraft at the parking location * initialize the Aircraft at the parking location
******************************************************************/ ******************************************************************/
void FGAIFlightPlan::createParking(FGAIAircraft * ac, FGAirport * apt, bool FGAIFlightPlan::createParking(FGAIAircraft * ac, FGAirport * apt,
double radius) double radius)
{ {
waypoint *wpt; waypoint *wpt;
@ -914,6 +920,7 @@ void FGAIFlightPlan::createParking(FGAIAircraft * ac, FGAirport * apt,
createOnGround(ac, "END", SGGeod::fromDeg(lon, lat), aptElev, createOnGround(ac, "END", SGGeod::fromDeg(lon, lat), aptElev,
vTaxiReduced); vTaxiReduced);
waypoints.push_back(wpt); waypoints.push_back(wpt);
return true;
} }
/** /**

View file

@ -286,7 +286,7 @@ void FGAIFlightPlan::createCruise(bool firstFlight, FGAirport *dep,
* Note that this is the original version that does not * Note that this is the original version that does not
* do any dynamic route computation. * do any dynamic route computation.
******************************************************************/ ******************************************************************/
void FGAIFlightPlan::createCruise(FGAIAircraft *ac, bool firstFlight, FGAirport *dep, bool FGAIFlightPlan::createCruise(FGAIAircraft *ac, bool firstFlight, FGAirport *dep,
FGAirport *arr, double latitude, FGAirport *arr, double latitude,
double longitude, double speed, double longitude, double speed,
double alt, const string& fltType) double alt, const string& fltType)

View file

@ -37,7 +37,7 @@
// TODO: Use James Turner's createOnGround functions. // TODO: Use James Turner's createOnGround functions.
void FGAIFlightPlan::createPushBack(FGAIAircraft *ac, bool FGAIFlightPlan::createPushBack(FGAIAircraft *ac,
bool firstFlight, FGAirport *dep, bool firstFlight, FGAirport *dep,
double latitude, double latitude,
double longitude, double longitude,
@ -71,6 +71,7 @@ void FGAIFlightPlan::createPushBack(FGAIAircraft *ac,
" of flight type " << fltType << " of flight type " << fltType <<
" of airline " << airline << " of airline " << airline <<
" at airport " << dep->getId()); " at airport " << dep->getId());
return false;
char buffer[10]; char buffer[10];
snprintf (buffer, 10, "%d", gateId); snprintf (buffer, 10, "%d", gateId);
//FGTaxiNode *tn = dep->getDynamics()->getGroundNetwork()->findNode(node); //FGTaxiNode *tn = dep->getDynamics()->getGroundNetwork()->findNode(node);
@ -104,7 +105,7 @@ void FGAIFlightPlan::createPushBack(FGAIAircraft *ac,
if (gateId < 0) { if (gateId < 0) {
createPushBackFallBack(ac, firstFlight, dep, latitude, longitude, createPushBackFallBack(ac, firstFlight, dep, latitude, longitude,
radius, fltType, aircraftType, airline); radius, fltType, aircraftType, airline);
return; return true;
} }
//cerr << "getting parking " << gateId; //cerr << "getting parking " << gateId;
@ -231,6 +232,7 @@ void FGAIFlightPlan::createPushBack(FGAIAircraft *ac,
} }
} }
return true;
} }
/******************************************************************* /*******************************************************************
* createPushBackFallBack * createPushBackFallBack

View file

@ -157,9 +157,9 @@ void FGATCManager::init() {
//dialog.init(); //dialog.init();
osg::Node* node = apt->getDynamics()->getGroundNetwork()->getRenderNode(); //osg::Node* node = apt->getDynamics()->getGroundNetwork()->getRenderNode();
cerr << "Adding groundnetWork to the scenegraph" << endl; //cerr << "Adding groundnetWork to the scenegraph::init" << endl;
globals->get_scenery()->get_scene_graph()->addChild(node); //globals->get_scenery()->get_scene_graph()->addChild(node);
} }
} }
@ -177,7 +177,7 @@ void FGATCManager::update ( double time ) {
double speed = fgGetDouble("/velocities/groundspeed-kt"); double speed = fgGetDouble("/velocities/groundspeed-kt");
double altitude = fgGetDouble("/position/altitude-ft"); double altitude = fgGetDouble("/position/altitude-ft");
cerr << "Running FGATCManager::update()" << endl; //cerr << "Running FGATCManager::update()" << endl;
controller->updateAircraftInformation(ai_ac.getID(), controller->updateAircraftInformation(ai_ac.getID(),
latitude, latitude,
longitude, longitude,
@ -185,10 +185,10 @@ void FGATCManager::update ( double time ) {
speed, speed,
altitude, time); altitude, time);
} }
/*string airport = fgGetString("/sim/presets/airport-id"); string airport = fgGetString("/sim/presets/airport-id");
FGAirport *apt = FGAirport::findByIdent(airport); FGAirport *apt = FGAirport::findByIdent(airport);
osg::Node* node = apt->getDynamics()->getGroundNetwork()->getRenderNode(); osg::Node* node = apt->getDynamics()->getGroundNetwork()->getRenderNode();
cerr << "Adding groundnetWork to the scenegraph" << endl; //cerr << "Adding groundnetWork to the scenegraph::update" << endl;
globals->get_scenery()->get_scene_graph()->addChild(node); globals->get_scenery()->get_scene_graph()->addChild(node);
*/
} }

View file

@ -419,6 +419,7 @@ bool FGTrafficRecord::pushBackAllowed()
// In essence, we should check whether the pusbback route itself, as well as the associcated // In essence, we should check whether the pusbback route itself, as well as the associcated
// taxiways near the pushback point are free of traffic. // taxiways near the pushback point are free of traffic.
// To do so, we need to // To do so, we need to
return true;
} }

View file

@ -182,6 +182,8 @@ public:
void allowRepeatedTransmissions () { allowTransmission=true; }; void allowRepeatedTransmissions () { allowTransmission=true; };
void nextFrequency() { frequencyId++; }; void nextFrequency() { frequencyId++; };
int getNextFrequency() { return frequencyId; }; int getNextFrequency() { return frequencyId; };
intVec& getIntentions() { return intentions; };
int getCurrentPosition() { return currentPos; };
}; };
typedef vector<FGTrafficRecord> TrafficVector; typedef vector<FGTrafficRecord> TrafficVector;

View file

@ -1,3 +1,4 @@
// groundnet.cxx - Implimentation of the FlightGear airport ground handling code // groundnet.cxx - Implimentation of the FlightGear airport ground handling code
// //
// Written by Durk Talsma, started June 2005. // Written by Durk Talsma, started June 2005.
@ -36,6 +37,8 @@
#include <simgear/debug/logstream.hxx> #include <simgear/debug/logstream.hxx>
#include <simgear/route/waypoint.hxx> #include <simgear/route/waypoint.hxx>
#include <simgear/scene/material/EffectGeode.hxx> #include <simgear/scene/material/EffectGeode.hxx>
#include <simgear/scene/material/matlib.hxx>
#include <simgear/scene/material/mat.hxx>
#include <Airports/simple.hxx> #include <Airports/simple.hxx>
#include <Airports/dynamics.hxx> #include <Airports/dynamics.hxx>
@ -43,6 +46,8 @@
#include <AIModel/AIAircraft.hxx> #include <AIModel/AIAircraft.hxx>
#include <AIModel/AIFlightPlan.hxx> #include <AIModel/AIFlightPlan.hxx>
#include <Scenery/scenery.hxx>
#include "groundnetwork.hxx" #include "groundnetwork.hxx"
/*************************************************************************** /***************************************************************************
@ -93,7 +98,7 @@ void FGTaxiSegment::setDimensions(double elevation)
SGGeodesy::inverse(start->getGeod(), end->getGeod(), heading, az2, length); SGGeodesy::inverse(start->getGeod(), end->getGeod(), heading, az2, length);
double coveredDistance = length * 0.5; double coveredDistance = length * 0.5;
SGGeodesy::direct(start->getGeod(), heading, coveredDistance, center, az2); SGGeodesy::direct(start->getGeod(), heading, coveredDistance, center, az2);
cerr << "Centerpoint = (" << center.getLatitudeDeg() << ", " << center.getLongitudeDeg() << "). Heading = " << heading << endl; //cerr << "Centerpoint = (" << center.getLatitudeDeg() << ", " << center.getLongitudeDeg() << "). Heading = " << heading << endl;
} }
@ -205,6 +210,7 @@ FGGroundNetwork::FGGroundNetwork()
//maxDepth = 1000; //maxDepth = 1000;
count = 0; count = 0;
currTraffic = activeTraffic.begin(); currTraffic = activeTraffic.begin();
group = 0;
} }
@ -1096,34 +1102,107 @@ static void WorldCoordinate(osg::Matrix& obj_pos, double lat,
osg::Node* FGGroundNetwork::getRenderNode() osg::Node* FGGroundNetwork::getRenderNode()
{ {
osg::Group* group = new osg::Group;
for ( FGTaxiSegmentVectorIterator i = segments.begin(); i != segments.end(); i++) { SGMaterialLib *matlib = globals->get_matlib();
osg::Matrix obj_pos; if (group) {
osg::MatrixTransform *obj_trans = new osg::MatrixTransform; //int nr = ;
obj_trans->setDataVariance(osg::Object::STATIC); globals->get_scenery()->get_scene_graph()->removeChild(group);
WorldCoordinate( obj_pos, (*i)->getLatitude(), (*i)->getLongitude(), parent->elevation()+10, -((*i)->getHeading()) ); //while (group->getNumChildren()) {
// cerr << "Number of children: " << group->getNumChildren() << endl;
simgear::EffectGeode* geode = (simgear::EffectGeode*) group->getChild(0);
//osg::MatrixTransform *obj_trans = (osg::MatrixTransform*) group->getChild(0);
//geode->releaseGLObjects();
//group->removeChild(geode);
//delete geode;
}
group = new osg::Group;
//for ( FGTaxiSegmentVectorIterator i = segments.begin(); i != segments.end(); i++) {
double dx = 0;
for (TrafficVectorIterator i = activeTraffic.begin(); i != activeTraffic.end(); i++) {
// Handle start point
int pos = i->getCurrentPosition() - 1;
if (pos >= 0) {
SGGeod start(SGGeod::fromDeg((i->getLongitude()), (i->getLatitude())));
SGGeod end (SGGeod::fromDeg(segments[pos]->getEnd()->getLongitude(), segments[pos]->getEnd()->getLatitude()));
double length = SGGeodesy::distanceM(start, end);
//heading = SGGeodesy::headingDeg(start->getGeod(), end->getGeod());
double az2, heading; //, distanceM;
SGGeodesy::inverse(start, end, heading, az2, length);
double coveredDistance = length * 0.5;
SGGeod center;
SGGeodesy::direct(start, heading, coveredDistance, center, az2);
//cerr << "Active Aircraft : Centerpoint = (" << center.getLatitudeDeg() << ", " << center.getLongitudeDeg() << "). Heading = " << heading << endl;
///////////////////////////////////////////////////////////////////////////////
// Make a helper function out of this
osg::Matrix obj_pos;
osg::MatrixTransform *obj_trans = new osg::MatrixTransform;
obj_trans->setDataVariance(osg::Object::STATIC);
WorldCoordinate( obj_pos, center.getLatitudeDeg(), center.getLongitudeDeg(), parent->elevation()+8+dx, -(heading) );
obj_trans->setMatrix( obj_pos ); obj_trans->setMatrix( obj_pos );
//osg::Vec3 center(0, 0, 0) //osg::Vec3 center(0, 0, 0)
float width = (*i)->getLength() /2.0; float width = length /2.0;
osg::Vec3 corner(-width, 0, 0.25f); osg::Vec3 corner(-width, 0, 0.25f);
osg::Vec3 widthVec(2*width + 1, 0, 0); osg::Vec3 widthVec(2*width + 1, 0, 0);
osg::Vec3 heightVec(0, 0, 1); osg::Vec3 heightVec(0, 1, 0);
osg::Geometry* geometry; osg::Geometry* geometry;
geometry = osg::createTexturedQuadGeometry(corner, widthVec, heightVec); geometry = osg::createTexturedQuadGeometry(corner, widthVec, heightVec);
simgear::EffectGeode* geode = new simgear::EffectGeode; simgear::EffectGeode* geode = new simgear::EffectGeode;
geode->setName("test"); geode->setName("test");
geode->addDrawable(geometry); geode->addDrawable(geometry);
//osg::Node *custom_obj; //osg::Node *custom_obj;
SGMaterial *mat = matlib->find("UnidirectionalTaper");
obj_trans->addChild(geode); if (mat)
// wire as much of the scene graph together as we can geode->setEffect(mat->get_effect());
//->addChild( obj_trans ); obj_trans->addChild(geode);
group->addChild( obj_trans ); // wire as much of the scene graph together as we can
//->addChild( obj_trans );
group->addChild( obj_trans );
/////////////////////////////////////////////////////////////////////
} else {
cerr << "BIG FAT WARNING: current position is here : " << pos << endl;
}
for(intVecIterator j = (i)->getIntentions().begin(); j != (i)->getIntentions().end(); j++) {
osg::Matrix obj_pos;
int k = (*j)-1;
if (k >= 0) {
osg::MatrixTransform *obj_trans = new osg::MatrixTransform;
obj_trans->setDataVariance(osg::Object::STATIC);
WorldCoordinate( obj_pos, segments[k]->getLatitude(), segments[k]->getLongitude(), parent->elevation()+8+dx, -(segments[k]->getHeading()) );
obj_trans->setMatrix( obj_pos );
//osg::Vec3 center(0, 0, 0)
float width = segments[k]->getLength() /2.0;
osg::Vec3 corner(-width, 0, 0.25f);
osg::Vec3 widthVec(2*width + 1, 0, 0);
osg::Vec3 heightVec(0, 1, 0);
osg::Geometry* geometry;
geometry = osg::createTexturedQuadGeometry(corner, widthVec, heightVec);
simgear::EffectGeode* geode = new simgear::EffectGeode;
geode->setName("test");
geode->addDrawable(geometry);
//osg::Node *custom_obj;
SGMaterial *mat = matlib->find("UnidirectionalTaper");
if (mat)
geode->setEffect(mat->get_effect());
obj_trans->addChild(geode);
// wire as much of the scene graph together as we can
//->addChild( obj_trans );
group->addChild( obj_trans );
}
}
dx += 0.1;
} }

View file

@ -24,6 +24,12 @@
#ifndef _GROUNDNETWORK_HXX_ #ifndef _GROUNDNETWORK_HXX_
#define _GROUNDNETWORK_HXX_ #define _GROUNDNETWORK_HXX_
#include <osg/Geode>
#include <osg/Geometry>
#include <osg/MatrixTransform>
#include <osg/Shape>
#include <simgear/compiler.h> #include <simgear/compiler.h>
#include <simgear/route/waypoint.hxx> #include <simgear/route/waypoint.hxx>
@ -37,6 +43,7 @@ using std::vector;
#include "parking.hxx" #include "parking.hxx"
#include <ATC/trafficcontrol.hxx> #include <ATC/trafficcontrol.hxx>
class FGTaxiSegment; // forward reference class FGTaxiSegment; // forward reference
class FGAIFlightPlan; // forward reference class FGAIFlightPlan; // forward reference
class FGAirport; // forward reference class FGAirport; // forward reference
@ -242,6 +249,8 @@ private:
void checkHoldPosition(int id, double lat, double lon, void checkHoldPosition(int id, double lat, double lon,
double heading, double speed, double alt); double heading, double speed, double alt);
osg::Group* group;
public: public:
FGGroundNetwork(); FGGroundNetwork();
~FGGroundNetwork(); ~FGGroundNetwork();

View file

@ -68,6 +68,7 @@ FGAISchedule::FGAISchedule()
radius = 0; radius = 0;
groundOffset = 0; groundOffset = 0;
distanceToUser = 0; distanceToUser = 0;
valid = true;
//score = 0; //score = 0;
} }
@ -120,6 +121,7 @@ FGAISchedule::FGAISchedule(string model,
runCount = 0; runCount = 0;
hits = 0; hits = 0;
initialized = false; initialized = false;
valid = true;
} }
FGAISchedule::FGAISchedule(const FGAISchedule &other) FGAISchedule::FGAISchedule(const FGAISchedule &other)
@ -146,6 +148,7 @@ FGAISchedule::FGAISchedule(const FGAISchedule &other)
runCount = other.runCount; runCount = other.runCount;
hits = other.hits; hits = other.hits;
initialized = other.initialized; initialized = other.initialized;
valid = other.valid;
} }
@ -192,9 +195,12 @@ bool FGAISchedule::update(time_t now, const SGVec3d& userCart)
elapsedTimeEnroute, elapsedTimeEnroute,
remainingTimeEnroute, remainingTimeEnroute,
deptime = 0; deptime = 0;
if (!valid) {
return false;
}
scheduleFlights(); scheduleFlights();
if (flights.empty()) { // No flights available for this aircraft if (flights.empty()) { // No flights available for this aircraft
valid = false;
return false; return false;
} }
@ -211,7 +217,7 @@ bool FGAISchedule::update(time_t now, const SGVec3d& userCart)
firstRun = false; firstRun = false;
} }
FGScheduledFlight* flight = flights.front(); FGScheduledFlight* flight = flights.front();
if (!deptime) { if (!deptime) {
deptime = flight->getDepartureTime(); deptime = flight->getDepartureTime();
//cerr << "Settiing departure time " << deptime << endl; //cerr << "Settiing departure time " << deptime << endl;
@ -329,19 +335,29 @@ bool FGAISchedule::createAIAircraft(FGScheduledFlight* flight, double speedKnots
aircraft->setBank(0); aircraft->setBank(0);
courseToDest = SGGeodesy::courseDeg(position, arr->geod()); courseToDest = SGGeodesy::courseDeg(position, arr->geod());
aircraft->SetFlightPlan(new FGAIFlightPlan(aircraft, flightPlanName, courseToDest, deptime, FGAIFlightPlan *fp = new FGAIFlightPlan(aircraft, flightPlanName, courseToDest, deptime,
dep, arr, true, radius, dep, arr, true, radius,
flight->getCruiseAlt()*100, flight->getCruiseAlt()*100,
position.getLatitudeDeg(), position.getLatitudeDeg(),
position.getLongitudeDeg(), position.getLongitudeDeg(),
speedKnots, flightType, acType, speedKnots, flightType, acType,
airline)); airline);
if (fp->isValidPlan()) {
aircraft->SetFlightPlan(fp);
FGAIManager* aimgr = (FGAIManager *) globals-> get_subsystem("ai_model"); FGAIManager* aimgr = (FGAIManager *) globals-> get_subsystem("ai_model");
aimgr->attach(aircraft); aimgr->attach(aircraft);
AIManagerRef = aircraft->getID(); AIManagerRef = aircraft->getID();
return true; return true;
} else {
delete aircraft;
delete fp;
//hand back the flights that had already been scheduled
while (!flights.empty()) {
flights.front()->release();
flights.erase(flights.begin());
}
return false;
}
} }
// Create an initial heading for user controlled aircraft. // Create an initial heading for user controlled aircraft.

View file

@ -59,6 +59,7 @@ class FGAISchedule
bool firstRun; bool firstRun;
double courseToDest; double courseToDest;
bool initialized; bool initialized;
bool valid;
void scheduleFlights(); void scheduleFlights();
@ -124,6 +125,7 @@ class FGAISchedule
// used to sort in decending order of score: I've probably found a better way to // used to sort in decending order of score: I've probably found a better way to
// decending order sorting, but still need to test that. // decending order sorting, but still need to test that.
bool operator< (const FGAISchedule &other) const { return (score > other.score); }; bool operator< (const FGAISchedule &other) const { return (score > other.score); };
void taint() { valid = false; };
//void * getAiRef () { return AIManagerRef; }; //void * getAiRef () { return AIManagerRef; };
//FGAISchedule* getAddress () { return this;}; //FGAISchedule* getAddress () { return this;};

View file

@ -258,6 +258,7 @@ void FGTrafficManager::update(double /*dt */ )
} }
//cerr << "Processing << " << (*currAircraft)->getRegistration() << " with score " << (*currAircraft)->getScore() << endl; //cerr << "Processing << " << (*currAircraft)->getRegistration() << " with score " << (*currAircraft)->getScore() << endl;
if (!((*currAircraft)->update(now, userCart))) { if (!((*currAircraft)->update(now, userCart))) {
(*currAircraft)->taint();
// NOTE: With traffic manager II, this statement below is no longer true // NOTE: With traffic manager II, this statement below is no longer true
// after proper initialization, we shouldnt get here. // after proper initialization, we shouldnt get here.
// But let's make sure // But let's make sure