From: durk Date: Sat, 26 Aug 2006 07:22:20 +0000 (+0000) Subject: Ground network distance tracking code. AIAircraft taxiing at airports X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=5b2e16ca730fc0e7f6730192a2744131b195e7fa;p=flightgear.git Ground network distance tracking code. AIAircraft taxiing at airports maintain a resonable distance from each other while taxiing on the same route. The current code does not yet take crossing routes or aircraft taxiing into opposite directions into account. --- diff --git a/src/AIModel/AIAircraft.cxx b/src/AIModel/AIAircraft.cxx index 62edd2761..93f6f96be 100644 --- a/src/AIModel/AIAircraft.cxx +++ b/src/AIModel/AIAircraft.cxx @@ -74,6 +74,8 @@ FGAIAircraft::FGAIAircraft(FGAISchedule *ref) : groundOffset = 0; fp = 0; + controller = 0; + prevController = 0; dt_count = 0; dt_elev_count = 0; use_perf_vs = true; @@ -217,6 +219,19 @@ void FGAIAircraft::Run(double dt) { AccelTo( props->getDoubleValue("controls/flight/target-spd" ) ); } + if (controller) + { + controller->update(getID(), + pos.getLatitudeDeg(), + pos.getLongitudeDeg(), + hdg, + speed, + altitude_ft); + //if (controller->hasInstruction(getID())) + // { + processATC(controller->getInstruction(getID())); + // } + } double turn_radius_ft; double turn_circum_ft; @@ -553,22 +568,11 @@ void FGAIAircraft::SetFlightPlan(FGAIFlightPlan *f) { void FGAIAircraft::ProcessFlightPlan( double dt, time_t now ) { bool eraseWaypoints; if (trafficRef) { -// FGAirport *arr; -// FGAirport *dep; eraseWaypoints = true; -// cerr << trafficRef->getRegistration(); -// cerr << "Departure airport " << endl; -// dep = trafficRef->getDepartureAirport(); -// if (dep) -// cerr << dep->getId() << endl; -// cerr << "Arrival airport " << endl; -// arr = trafficRef->getArrivalAirport(); -// if (arr) -// cerr << arr->getId() <getNextWaypoint(); dt_count += dt; - if (!prev) { //beginning of flightplan, do this initialization once - //setBank(0.0); - spinCounter = 0; - tempReg = ""; - //prev_dist_to_go = HUGE; - //cerr << "Before increment " << curr-> name << endl; - fp->IncrementWaypoint(eraseWaypoints); - //prev = fp->getPreviousWaypoint(); //first waypoint - //curr = fp->getCurrentWaypoint(); //second waypoint - //next = fp->getNextWaypoint(); //third waypoint (might not exist!) - //cerr << "After increment " << prev-> name << endl; - if (!(fp->getNextWaypoint()) && trafficRef) - loadNextLeg(); + /////////////////////////////////////////////////////////////////////////// + // Initialize the flightplan + ////////////////////////////////////////////////////////////////////////// + if (!prev) { - //cerr << "After load " << prev-> name << endl; - prev = fp->getPreviousWaypoint(); //first waypoint - curr = fp->getCurrentWaypoint(); //second waypoint - next = fp->getNextWaypoint(); //third waypoint (might not exist!) - //cerr << "After load " << prev-> name << endl; - setLatitude(prev->latitude); - setLongitude(prev->longitude); - setSpeed(prev->speed); - setAltitude(prev->altitude); - - if (prev->speed > 0.0) - setHeading(fp->getBearing(prev->latitude, prev->longitude, curr)); - else - setHeading(fp->getBearing(curr->latitude, curr->longitude, prev)); - - // If next doesn't exist, as in incrementally created flightplans for - // AI/Trafficmanager created plans, - // Make sure lead distance is initialized otherwise - if (next) - fp->setLeadDistance(speed, hdg, curr, next); - - if (curr->crossat > -1000.0) { //use a calculated descent/climb rate - use_perf_vs = false; - tgt_vs = (curr->crossat - prev->altitude) - / (fp->getDistanceToGo(pos.getLatitudeDeg(), pos.getLongitudeDeg(), curr) - / 6076.0 / prev->speed*60.0); - tgt_altitude_ft = curr->crossat; - } else { - use_perf_vs = true; - tgt_altitude_ft = prev->altitude; - } - alt_lock = hdg_lock = true; - no_roll = prev->on_ground; - if (no_roll) { - Transform(); // make sure aip is initialized. - getGroundElev(60.1); // make sure it's exectuted first time around, so force a large dt value - //getGroundElev(60.1); // Need to do this twice. - //cerr << trafficRef->getRegistration() << " Setting altitude to " << tgt_altitude << endl; - doGroundAltitude(); //(tgt_altitude); - } - prevSpeed = 0; - //cout << "First waypoint: " << prev->name << endl; - //cout << " Target speed: " << tgt_speed << endl; - //cout << " Target altitude: " << tgt_altitude << endl; - //cout << " Target heading: " << tgt_heading << endl << endl; - //cerr << "Done Flightplan init" << endl; - return; + spinCounter = 0; + tempReg = ""; + fp->IncrementWaypoint(eraseWaypoints); + if (!(fp->getNextWaypoint()) && trafficRef) + loadNextLeg(); + + prev = fp->getPreviousWaypoint(); //first waypoint + curr = fp->getCurrentWaypoint(); //second waypoint + next = fp->getNextWaypoint(); //third waypoint (might not exist!) + + setLatitude(prev->latitude); + setLongitude(prev->longitude); + setSpeed(prev->speed); + setAltitude(prev->altitude); + + if (prev->speed > 0.0) + setHeading(fp->getBearing(prev->latitude, prev->longitude, curr)); + else + setHeading(fp->getBearing(curr->latitude, curr->longitude, prev)); + + // If next doesn't exist, as in incrementally created flightplans for + // AI/Trafficmanager created plans, + // Make sure lead distance is initialized otherwise + if (next) + fp->setLeadDistance(speed, hdg, curr, next); + + if (curr->crossat > -1000.0) { //use a calculated descent/climb rate + use_perf_vs = false; + tgt_vs = (curr->crossat - prev->altitude) + / (fp->getDistanceToGo(pos.getLatitudeDeg(), pos.getLongitudeDeg(), curr) + / 6076.0 / prev->speed*60.0); + tgt_altitude_ft = curr->crossat; + } else { + use_perf_vs = true; + tgt_altitude_ft = prev->altitude; + } + alt_lock = hdg_lock = true; + no_roll = prev->on_ground; + if (no_roll) { + Transform(); // make sure aip is initialized. + getGroundElev(60.1); // make sure it's exectuted first time around, so force a large dt value + doGroundAltitude(); + } + // Make sure to announce the aircraft's position + announcePositionToController(); + prevSpeed = 0; + return; } // end of initialization - - // let's only process the flight plan every 100 ms. + + /////////////////////////////////////////////////////////////////////////// + // Check Execution time (currently once every 100 ms + /////////////////////////////////////////////////////////////////////////// if ((dt_count < 0.1) || (now < fp->getStartTime())) { - //cerr << "done fp dt" << endl; - return; + //cerr << "done fp dt" << endl; + return; } else { - dt_count = 0; + dt_count = 0; } // check to see if we've reached the lead point for our next turn double dist_to_go = fp->getDistanceToGo(pos.getLatitudeDeg(), pos.getLongitudeDeg(), curr); @@ -659,45 +656,18 @@ void FGAIAircraft::ProcessFlightPlan( double dt, time_t now ) { lead_dist = fabs(2*speed); //don't skip over the waypoint //cerr << "Extending lead distance to " << lead_dist << endl; } -// FGAirport * apt = trafficRef->getDepartureAirport(); -// if ((dist_to_go > prev_dist_to_go) && trafficRef && apt) { -// if (apt->getId() == string("EHAM")) -// cerr << "Alert: " << trafficRef->getRegistration() << " is moving away from waypoint " << curr->name << endl -// << "Target heading : " << tgt_heading << "act heading " << hdg << " Tgt speed : " << tgt_speed << endl -// << "Lead distance : " << lead_dist << endl -// << "Distance to go: " << dist_to_go << endl; -// } - - prev_dist_to_go = dist_to_go; - //cerr << "2" << endl; - //if (no_roll) - // lead_dist = 10.0; - //cout << "Leg : " << (fp->getLeg()-1) << ". dist_to_go: " << dist_to_go << ", lead_dist: " - // << lead_dist << ", tgt_speed " << tgt_speed << ", tgt_heading " << tgt_heading - // << " speed " << speed << " hdg " << hdg << ". Altitude " << altitude << " TAget alt :" - // << tgt_altitude << endl; + + //prev_dist_to_go = dist_to_go; if ( dist_to_go < lead_dist ) { - //prev_dist_to_go = HUGE; - // For traffic manager generated aircraft: - // check if the aircraft flies of of user range. And adjust the - // Current waypoint's elevation according to Terrain Elevation if (curr->finished) { //end of the flight plan if (fp->getRepeat()) fp->restart(); else setDie(true); - - //cerr << "Done die end of fp" << endl; return; } - // we've reached the lead-point for the waypoint ahead - //cerr << "4" << endl; - //cerr << "Situation after lead point" << endl; - //cerr << "Prviious: " << prev->name << endl; - //cerr << "Current : " << curr->name << endl; - //cerr << "Next : " << next->name << endl; if (next) { tgt_heading = fp->getBearing(curr, next); spinCounter = 0; @@ -712,7 +682,6 @@ void FGAIAircraft::ProcessFlightPlan( double dt, time_t now ) { next = fp->getNextWaypoint(); // Now that we have incremented the waypoints, excute some traffic manager specific code - // based on the name of the waypoint we just passed. if (trafficRef) { double userLatitude = fgGetDouble("/position/latitude-deg"); double userLongitude = fgGetDouble("/position/longitude-deg"); @@ -722,57 +691,32 @@ void FGAIAircraft::ProcessFlightPlan( double dt, time_t now ) { user.CourseAndDistance(current, &course, &distance); if ((distance * SG_METER_TO_NM) > TRAFFICTOAIDIST) { setDie(true); - //cerr << "done fp die out of range" << endl; return; } FGAirport * dep = trafficRef->getDepartureAirport(); FGAirport * arr = trafficRef->getArrivalAirport(); - // At parking the beginning of the airport if (!( dep && arr)) { setDie(true); return; } - - //if ((dep->getId() == string("EHAM") || (arr->getId() == string("EHAM")))) { - // cerr << trafficRef->getRegistration() - // << " Enroute from " << dep->getId() - // << " to " << arr->getId() - // << " just crossed " << prev->name - // << " Assigned rwy " << fp->getRunwayId() - // << " " << fp->getRunway() << endl; - // } - //if ((dep->getId() == string("EHAM")) && (prev->name == "park2")) { - // cerr << "Schiphol ground " - // << trafficRef->getCallSign(); - // if (trafficRef->getHeavy()) - // cerr << "Heavy"; - // cerr << ", is type " - // << trafficRef->getAircraft() - // << " ready to go. IFR to " - // << arr->getId() <name == "park2") dep->getDynamics()->releaseParking(fp->getGate()); - - // Some debug messages, specific to testing the Logical networks. - // if ((arr->getId() == string("EHAM")) && (prev->name == "Center")) { - // cerr << "Schiphol ground " - // << trafficRef->getRegistration() << " " - // << trafficRef->getCallSign(); - // if (trafficRef->getHeavy()) - // cerr << "Heavy"; - // cerr << ", arriving from " << dep->getName() ; - // cerr << " landed runway " - // << fp->getRunway() - // << " request taxi to gate " - // << arr->getDynamics()->getParkingName(fp->getGate()) - // << endl; - // } - if (prev->name == "END") - fp->setTime(trafficRef->getDepartureTime()); - //cerr << "5" << endl; + // 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. + if (prev->name == "END") { + // make sure to wait at least 20 minutes at parking to prevent "nervous" taxi behavior + // delayed aircraft. + time_t nextDeparture = trafficRef->getDepartureTime(); + if (nextDeparture < (now+1200)) { + nextDeparture = now + 1200; + } + fp->setTime(trafficRef->getDepartureTime()); + } + announcePositionToController(); + } if (next) { @@ -843,6 +787,11 @@ void FGAIAircraft::ProcessFlightPlan( double dt, time_t now ) { } } +void FGAIAircraft::initializeFlightPlan() +{ + +} + bool FGAIAircraft::_getGearDown() const { return ((props->getFloatValue("position/altitude-agl-ft") < 900.0) @@ -1013,3 +962,82 @@ void FGAIAircraft::doGroundAltitude() { altitude_ft += 0.1 * ((tgt_altitude_ft+groundOffset) - altitude_ft); } + +void FGAIAircraft::announcePositionToController() +{ + if (trafficRef) { + //FGTaxiRoute *taxiRoute = fp->getTaxiRoute(); + + int leg = fp->getLeg(); + + // For starters, I'll only do this for departure and arrival taxi. The mechanism + // could be extended to include any controller however. + //int node, currentTaxiSegment; + //if (taxiRoute->next(&node, ¤tTaxiSegment)) { + if (fp->getCurrentWaypoint()->routeIndex != 0) { + //char buffer[10]; + //snprintf (buffer, 10, "%d", node); + switch (leg) { + case 3: + cerr << trafficRef->getRegistration() + << " taxiing to runway at segment " + << fp->getCurrentWaypoint()->routeIndex + << endl; + //cerr << "Match check between taxisegment and taxiroute : " << node << " " + // << fp->getCurrentWaypoint()->name << endl; + if (trafficRef->getDepartureAirport()->getDynamics()->getGroundNetwork()->exists()) + controller = trafficRef->getDepartureAirport()->getDynamics()->getGroundNetwork(); + break; + case 9: + cerr << trafficRef->getRegistration() + << " taxiing to parking at segment " + << fp->getCurrentWaypoint()->routeIndex + << endl; + if (trafficRef->getArrivalAirport()->getDynamics()->getGroundNetwork()->exists()) + controller = trafficRef->getArrivalAirport()->getDynamics()->getGroundNetwork(); + break; + default: + controller = 0; + break; + } + } else { + //fp->deleteTaxiRoute(); + controller = 0; + } + if ((controller != prevController) && (prevController != 0)) { + prevController->signOff(getID()); + cerr << trafficRef->getRegistration() + << " signing off " << endl; + } + prevController = controller; + if (controller) { + controller->announcePosition(getID(), fp, fp->getCurrentWaypoint()->routeIndex, + _getLatitude(), _getLongitude(), hdg, speed, altitude_ft, + trafficRef->getRadius()); + } + } +} + + +void FGAIAircraft::processATC(FGATCInstruction instruction) +{ + //cerr << "Processing ATC instruction (not Implimented yet)" << endl; + if (instruction.getHoldPattern ()) { + } + if (instruction.getHoldPosition ()) { + } + if (instruction.getChangeSpeed ()) { + AccelTo(instruction.getSpeed()); + }else { + if (fp) AccelTo(fp->getPreviousWaypoint()->speed); + } + if (instruction.getChangeHeading ()) { + hdg_lock = false; + TurnTo(instruction.getHeading()); + } else { + if (fp) {hdg_lock = true;} + } + if (instruction.getChangeAltitude()) { + } + +} diff --git a/src/AIModel/AIAircraft.hxx b/src/AIModel/AIAircraft.hxx index b50ea691f..095b21b37 100644 --- a/src/AIModel/AIAircraft.hxx +++ b/src/AIModel/AIAircraft.hxx @@ -71,6 +71,7 @@ public: void SetPerformance(const PERF_STRUCT *ps); void setFlightPlan(const std::string& fp, bool repat = false); void SetFlightPlan(FGAIFlightPlan *f); + void initializeFlightPlan(); FGAIFlightPlan* GetFlightPlan() const { return fp; }; void AccelTo(double speed); void PitchTo(double angle); @@ -89,11 +90,15 @@ public: void setAcType(const string& ac) { acType = ac; }; void setCompany(const string& comp) { company = comp;}; + void announcePositionToController(); + void processATC(FGATCInstruction instruction); + inline void SetTanker(bool setting) { isTanker = setting; }; virtual const char* getTypeString(void) const { return "aircraft"; } private: FGAISchedule *trafficRef; + FGATCController *controller, *prevController; bool hdg_lock; bool alt_lock; diff --git a/src/AIModel/AIFlightPlan.cxx b/src/AIModel/AIFlightPlan.cxx index 1ffc43283..8f03b93a7 100644 --- a/src/AIModel/AIFlightPlan.cxx +++ b/src/AIModel/AIFlightPlan.cxx @@ -296,12 +296,6 @@ FGAIFlightPlan::FGAIFlightPlan(const std::string& p, FGAIFlightPlan::~FGAIFlightPlan() { deleteWaypoints(); - //waypoints.clear(); - //while (waypoints.begin() != waypoints.end()) - // { - // delete *(waypoints.begin()); - // waypoints.erase (waypoints.begin()); - // } if (taxiRoute) delete taxiRoute; } @@ -491,3 +485,20 @@ void FGAIFlightPlan::restart() { wpt_iterator = waypoints.begin(); } + + +void FGAIFlightPlan::deleteTaxiRoute() +{ + if (taxiRoute) + delete taxiRoute; + taxiRoute = 0; +} + + +int FGAIFlightPlan::getRouteIndex(int i) { + if ((i > 0) && (i < waypoints.size())) { + return waypoints[i]->routeIndex; + } + else + return 0; +} diff --git a/src/AIModel/AIFlightPlan.hxx b/src/AIModel/AIFlightPlan.hxx index 023ad85a0..28f285b17 100644 --- a/src/AIModel/AIFlightPlan.hxx +++ b/src/AIModel/AIFlightPlan.hxx @@ -48,6 +48,7 @@ public: bool gear_down; bool flaps_down; bool on_ground; + int routeIndex; // For AI/ATC purposes; } waypoint; FGAIFlightPlan(const string& filename); @@ -93,8 +94,11 @@ public: void setRepeat(bool r) { repeat = r; }; bool getRepeat(void) const { return repeat; }; void restart(void); + int getNrOfWayPoints() { return waypoints.size(); }; + int getRouteIndex(int i); // returns the AI related index of this current routes. + FGTaxiRoute *getTaxiRoute() { return taxiRoute; }; + void deleteTaxiRoute(); - int getNrOfWayPoints() { return waypoints.end() - waypoints.begin(); }; private: FGRunway rwy; diff --git a/src/AIModel/AIFlightPlanCreate.cxx b/src/AIModel/AIFlightPlanCreate.cxx index 2c6646d85..adeb775f9 100644 --- a/src/AIModel/AIFlightPlanCreate.cxx +++ b/src/AIModel/AIFlightPlanCreate.cxx @@ -44,7 +44,7 @@ void FGAIFlightPlan::create(FGAirport *dep, FGAirport *arr, int legNr, int currWpt = wpt_iterator - waypoints.begin(); switch(legNr) { - case 1: + case 1: createPushBack(firstFlight,dep, latitude, longitude, radius, fltType, aircraftType, airline); break; @@ -140,10 +140,9 @@ void FGAIFlightPlan::createPushBack(bool firstFlight, FGAirport *dep, wpt->flaps_down= true; wpt->finished = false; wpt->on_ground = true; + waypoints.push_back(wpt); - // Add park twice, because it uses park once for initialization and once - // to trigger the departure ATC message geo_direct_wgs_84 ( 0, lat, lon, heading, 10, &lat2, &lon2, &az2 ); @@ -158,6 +157,7 @@ void FGAIFlightPlan::createPushBack(bool firstFlight, FGAirport *dep, wpt->flaps_down= true; wpt->finished = false; wpt->on_ground = true; + wpt->routeIndex = 0; waypoints.push_back(wpt); geo_direct_wgs_84 ( 0, lat, lon, heading, 2.2*radius, @@ -173,6 +173,7 @@ void FGAIFlightPlan::createPushBack(bool firstFlight, FGAirport *dep, wpt->flaps_down= true; wpt->finished = false; wpt->on_ground = true; + wpt->routeIndex = 0; waypoints.push_back(wpt); } @@ -280,6 +281,7 @@ void FGAIFlightPlan::createTaxi(bool firstFlight, int direction, wpt->flaps_down= true; wpt->finished = false; wpt->on_ground = true; + wpt->routeIndex = 0; waypoints.push_back(wpt); //Add the runway startpoint; @@ -294,6 +296,7 @@ void FGAIFlightPlan::createTaxi(bool firstFlight, int direction, wpt->flaps_down= true; wpt->finished = false; wpt->on_ground = true; + wpt->routeIndex = 0; waypoints.push_back(wpt); } else { int node; @@ -312,8 +315,7 @@ void FGAIFlightPlan::createTaxi(bool firstFlight, int direction, isPushBackPoint = false; taxiRoute->next(&node); } - } - else { + } else { //chop off the first two waypoints, because // those have already been created // by create pushback @@ -323,13 +325,16 @@ void FGAIFlightPlan::createTaxi(bool firstFlight, int direction, taxiRoute->next(&node); } } - while(taxiRoute->next(&node)) + int route; + while(taxiRoute->next(&node, &route)) { //FGTaxiNode *tn = apt->getDynamics()->getGroundNetwork()->findSegment(node)->getEnd(); + char buffer[10]; + snprintf (buffer, 10, "%d", node); FGTaxiNode *tn = apt->getDynamics()->getGroundNetwork()->findNode(node); //ids.pop_back(); wpt = new waypoint; - wpt->name = "taxiway"; // fixme: should be the name of the taxiway + wpt->name = string(buffer); // fixme: should be the name of the taxiway wpt->latitude = tn->getLatitude(); wpt->longitude = tn->getLongitude(); // Elevation is currently disregarded when on_ground is true @@ -347,23 +352,27 @@ void FGAIFlightPlan::createTaxi(bool firstFlight, int direction, wpt->flaps_down= true; wpt->finished = false; wpt->on_ground = true; + wpt->routeIndex = route; waypoints.push_back(wpt); } //cerr << endl; // finally, rewind the taxiRoute object to the point where we started + // generating the Flightplan, for AI use. + // This is a bit tricky, because the taxiRoute->first(); if (firstFlight) { - for (int i = 0; i < nrWaypointsToSkip-2; i++) { + for (int i = 0; i < nrWaypointsToSkip-1; i++) { taxiRoute->next(&node); } } else { int size = taxiRoute->size(); if (size > 2) { - taxiRoute->next(&node); - taxiRoute->next(&node); + //taxiRoute->next(&node); + //taxiRoute->next(&node); + //taxiRoute->next(&node); } } - } + } // taxiRoute not empty } else { @@ -380,6 +389,7 @@ void FGAIFlightPlan::createTaxi(bool firstFlight, int direction, wpt->flaps_down= true; wpt->finished = false; wpt->on_ground = true; + wpt->routeIndex = 0; waypoints.push_back(wpt); //Add the runway startpoint; @@ -394,6 +404,7 @@ void FGAIFlightPlan::createTaxi(bool firstFlight, int direction, wpt->flaps_down= true; wpt->finished = false; wpt->on_ground = true; + wpt->routeIndex = 0; waypoints.push_back(wpt); } } @@ -441,6 +452,7 @@ void FGAIFlightPlan::createTaxi(bool firstFlight, int direction, wpt->flaps_down= true; wpt->finished = false; wpt->on_ground = true; + wpt->routeIndex = 0; waypoints.push_back(wpt); //Add the runway startpoint; @@ -455,6 +467,7 @@ void FGAIFlightPlan::createTaxi(bool firstFlight, int direction, wpt->flaps_down= true; wpt->finished = false; wpt->on_ground = true; + wpt->routeIndex = 0; waypoints.push_back(wpt); } else { int node; @@ -462,13 +475,17 @@ void FGAIFlightPlan::createTaxi(bool firstFlight, int direction, int size = taxiRoute->size(); // Omit the last two waypoints, as // those are created by createParking() + int route; for (int i = 0; i < size-2; i++) { - taxiRoute->next(&node); + taxiRoute->next(&node, &route); + char buffer[10]; + snprintf (buffer, 10, "%d", node); //FGTaxiNode *tn = apt->getDynamics()->getGroundNetwork()->findNode(node); FGTaxiNode *tn = apt->getDynamics()->getGroundNetwork()->findNode(node); wpt = new waypoint; - wpt->name = "taxiway"; // fixme: should be the name of the taxiway + //wpt->name = "taxiway"; // fixme: should be the name of the taxiway + wpt->name = string(buffer);// fixme: should be the name of the taxiway wpt->latitude = tn->getLatitude(); wpt->longitude = tn->getLongitude(); wpt->altitude = apt->getElevation(); @@ -478,8 +495,11 @@ void FGAIFlightPlan::createTaxi(bool firstFlight, int direction, wpt->flaps_down= true; wpt->finished = false; wpt->on_ground = true; + wpt->routeIndex = route; waypoints.push_back(wpt); } + //taxiRoute->first(); + //taxiRoute->next(&node); } } else @@ -503,6 +523,7 @@ void FGAIFlightPlan::createTaxi(bool firstFlight, int direction, wpt->flaps_down= true; wpt->finished = false; wpt->on_ground = true; + wpt->routeIndex = 0; waypoints.push_back(wpt); wpt = new waypoint; @@ -516,6 +537,7 @@ void FGAIFlightPlan::createTaxi(bool firstFlight, int direction, wpt->flaps_down= true; wpt->finished = false; wpt->on_ground = true; + wpt->routeIndex = 0; waypoints.push_back(wpt); //waypoint* wpt; @@ -538,6 +560,7 @@ void FGAIFlightPlan::createTaxi(bool firstFlight, int direction, wpt->flaps_down= true; wpt->finished = false; wpt->on_ground = true; + wpt->routeIndex = 0; waypoints.push_back(wpt); } @@ -592,6 +615,7 @@ void FGAIFlightPlan::createTakeOff(bool firstFlight, FGAirport *apt, double spee wpt->flaps_down= true; wpt->finished = false; wpt->on_ground = true; + wpt->routeIndex = 0; waypoints.push_back(wpt); lat = lat2; @@ -614,6 +638,7 @@ void FGAIFlightPlan::createTakeOff(bool firstFlight, FGAirport *apt, double spee wpt->flaps_down= true; wpt->finished = false; wpt->on_ground = false; + wpt->routeIndex = 0; waypoints.push_back(wpt); } @@ -667,6 +692,7 @@ void FGAIFlightPlan::createClimb(bool firstFlight, FGAirport *apt, double speed, wpt->flaps_down= true; wpt->finished = false; wpt->on_ground = false; + wpt->routeIndex = 0; waypoints.push_back(wpt); @@ -684,6 +710,7 @@ void FGAIFlightPlan::createClimb(bool firstFlight, FGAirport *apt, double speed, wpt->flaps_down= true; wpt->finished = false; wpt->on_ground = false; + wpt->routeIndex = 0; waypoints.push_back(wpt); } @@ -799,6 +826,7 @@ void FGAIFlightPlan::createDecent(FGAirport *apt) wpt->flaps_down= false; wpt->finished = false; wpt->on_ground = false; + wpt->routeIndex = 0; waypoints.push_back(wpt); // Three thousand ft. Slowing down to 160 kts @@ -816,6 +844,7 @@ void FGAIFlightPlan::createDecent(FGAirport *apt) wpt->flaps_down= true; wpt->finished = false; wpt->on_ground = false; + wpt->routeIndex = 0; waypoints.push_back(wpt); } /******************************************************************* @@ -852,6 +881,7 @@ void FGAIFlightPlan::createLanding(FGAirport *apt) wpt->flaps_down= true; wpt->finished = false; wpt->on_ground = true; + wpt->routeIndex = 0; waypoints.push_back(wpt); //Full stop at the runway centerpoint @@ -869,6 +899,7 @@ void FGAIFlightPlan::createLanding(FGAirport *apt) wpt->flaps_down= true; wpt->finished = false; wpt->on_ground = true; + wpt->routeIndex = 0; waypoints.push_back(wpt); geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, heading, @@ -885,6 +916,7 @@ void FGAIFlightPlan::createLanding(FGAirport *apt) wpt->flaps_down= true; wpt->finished = false; wpt->on_ground = true; + wpt->routeIndex = 0; waypoints.push_back(wpt); } @@ -917,6 +949,7 @@ void FGAIFlightPlan::createParking(FGAirport *apt, double radius) wpt->flaps_down= true; wpt->finished = false; wpt->on_ground = true; + wpt->routeIndex = 0; waypoints.push_back(wpt); geo_direct_wgs_84 ( 0, lat, lon, heading, 0.1 *radius, @@ -932,6 +965,7 @@ void FGAIFlightPlan::createParking(FGAirport *apt, double radius) wpt->flaps_down= true; wpt->finished = false; wpt->on_ground = true; + wpt->routeIndex = 0; waypoints.push_back(wpt); wpt = new waypoint; @@ -945,5 +979,6 @@ void FGAIFlightPlan::createParking(FGAirport *apt, double radius) wpt->flaps_down= true; wpt->finished = false; wpt->on_ground = true; + wpt->routeIndex = 0; waypoints.push_back(wpt); } diff --git a/src/AIModel/AIFlightPlanCreateCruise.cxx b/src/AIModel/AIFlightPlanCreateCruise.cxx index c60e40bb2..fc81c4dbd 100755 --- a/src/AIModel/AIFlightPlanCreateCruise.cxx +++ b/src/AIModel/AIFlightPlanCreateCruise.cxx @@ -340,6 +340,7 @@ void FGAIFlightPlan::createCruise(bool firstFlight, FGAirport *dep, wpt->flaps_down= false; wpt->finished = false; wpt->on_ground = false; + wpt->routeIndex = 0; waypoints.push_back(wpt); @@ -373,5 +374,6 @@ void FGAIFlightPlan::createCruise(bool firstFlight, FGAirport *dep, wpt->flaps_down= false; wpt->finished = false; wpt->on_ground = false; + wpt->routeIndex = 0; waypoints.push_back(wpt); } diff --git a/src/Airports/groundnetwork.cxx b/src/Airports/groundnetwork.cxx index 862c359df..835fbb52b 100644 --- a/src/Airports/groundnetwork.cxx +++ b/src/Airports/groundnetwork.cxx @@ -41,6 +41,8 @@ //#include
//#include +#include + //#include STL_STRING #include "groundnetwork.hxx" @@ -103,7 +105,9 @@ void FGTaxiSegment::setTrackDistance() 0); first.CourseAndDistance(second, &course, &length); } - +/*************************************************************************** + * FGTaxiRoute + **************************************************************************/ bool FGTaxiRoute::next(int *nde) { //for (intVecIterator i = nodes.begin(); i != nodes.end(); i++) @@ -119,8 +123,9 @@ bool FGTaxiRoute::next(int *nde) if (currNode == nodes.end()) return false; *nde = *(currNode); + if (currNode != nodes.begin()) // make sure route corresponds to the end node + currRoute++; currNode++; - currRoute++; return true; }; @@ -140,11 +145,123 @@ bool FGTaxiRoute::next(int *nde, int *rte) if (currNode == nodes.end()) return false; *nde = *(currNode); - *rte = *(currRoute); + //*rte = *(currRoute); + if (currNode != nodes.begin()) // Make sure route corresponds to the end node + { + *rte = *(currRoute); + currRoute++; + } + else + { + // If currNode points to the first node, this means the aircraft is not on the taxi node + // yet. Make sure to return a unique identifyer in this situation though, because otherwise + // the speed adjust AI code may be unable to resolve whether two aircraft are on the same + // taxi route or not. the negative of the preceding route seems a logical choice, as it is + // unique for any starting location. + // Note that this is probably just a temporary fix until I get Parking / tower control working. + *rte = -1 * *(currRoute); + } currNode++; - currRoute++; return true; }; + +void FGTaxiRoute::rewind(int route) +{ + int currPoint; + int currRoute; + first(); + do { + if (!(next(&currPoint, &currRoute))) { + SG_LOG(SG_GENERAL,SG_ALERT, "Error in rewinding TaxiRoute: current" << currRoute + << " goal " << route); + } + } while (currRoute != route); +} + +/*************************************************************************** + * FGTrafficRecord + **************************************************************************/ +void FGTrafficRecord::setPositionAndIntentions(int pos, FGAIFlightPlan *route) +{ + + currentPos = pos; + if (intentions.size()) { + if (*intentions.begin() != pos) { + SG_LOG(SG_GENERAL, SG_ALERT, "Error in FGTrafficRecord::setPositionAndIntentions"); + cerr << "Pos : " << pos << " Curr " << *(intentions.begin()) << endl; + for (intVecIterator i = intentions.begin(); i != intentions.end() ; i++) { + cerr << (*i) << " "; + } + cerr << endl; + } + intentions.erase(intentions.begin()); + } else { + //int legNr, routeNr; + //FGAIFlightPlan::waypoint* const wpt= route->getCurrentWaypoint(); + int size = route->getNrOfWayPoints(); + cerr << "Setting pos" << pos << " "; + cerr << "setting intentions "; + for (int i = 0; i < size; i++) { + int val = route->getRouteIndex(i); + + if ((val) && (val != pos)) + { + intentions.push_back(val); + cerr << val<< " "; + } + } + cerr << endl; + //while (route->next(&legNr, &routeNr)) { + //intentions.push_back(routeNr); + //} + //route->rewind(currentPos); + } + //exit(1); +} + +bool FGTrafficRecord::checkPositionAndIntentions(FGTrafficRecord &other) +{ + bool result = false; + //cerr << "Start check 1" << endl; + if (currentPos == other.currentPos) + { + //cerr << "Check Position and intentions: current matches" << endl; + result = true; + } + // else if (other.intentions.size()) +// { +// cerr << "Start check 2" << endl; +// intVecIterator i = other.intentions.begin(); +// while (!((i == other.intentions.end()) || ((*i) == currentPos))) +// i++; +// if (i != other.intentions.end()) { +// cerr << "Check Position and intentions: current matches other.intentions" << endl; +// result = true; +// } + else if (intentions.size()) { + //cerr << "Start check 3" << endl; + intVecIterator i = intentions.begin(); + while (!((i == intentions.end()) || ((*i) == other.currentPos))) + i++; + if (i != intentions.end()) { + //cerr << "Check Position and intentions: .other.current matches" << endl; + result = true; + } + } + //cerr << "Done !!" << endl; + return result; +} + +void FGTrafficRecord::setPositionAndHeading(double lat, double lon, double hdg, + double spd, double alt) +{ + latitude = lat; + longitude = lon; + heading = hdg; + speed = spd; + altitude = alt; +} + /*************************************************************************** * FGGroundNetwork() **************************************************************************/ @@ -155,6 +272,7 @@ FGGroundNetwork::FGGroundNetwork() foundRoute = false; totalDistance = 0; maxDistance = 0; + currTraffic = activeTraffic.begin(); } void FGGroundNetwork::addSegment(const FGTaxiSegment &seg) @@ -187,7 +305,7 @@ void FGGroundNetwork::addNodes(FGParkingVec *parkings) void FGGroundNetwork::init() { hasNetwork = true; - int index = 0; + int index = 1; FGTaxiSegmentVectorIterator i = segments.begin(); while(i != segments.end()) { //cerr << "initializing node " << i->getIndex() << endl; @@ -421,3 +539,250 @@ void FGGroundNetwork::printRoutingError(string mess) } //exit(1); } + + +void FGGroundNetwork::announcePosition(int id, FGAIFlightPlan *intendedRoute, int currentPosition, + double lat, double lon, double heading, + double speed, double alt, double radius) +{ + TrafficVectorIterator i = activeTraffic.begin(); + // Search search if the current id alread has an entry + // This might be faster using a map instead of a vector, but let's start by taking a safe route + if (activeTraffic.size()) { + while ((i->getId() != id) && i != activeTraffic.end()) { + i++; + } + } + // Add a new TrafficRecord if no one exsists for this aircraft. + if (i == activeTraffic.end() || (activeTraffic.size() == 0)) { + FGTrafficRecord rec; + rec.setId(id); + rec.setPositionAndIntentions(currentPosition, intendedRoute); + rec.setPositionAndHeading(lat, lon, heading, speed, alt); + rec.setRadius(radius); // only need to do this when creating the record. + activeTraffic.push_back(rec); + } else { + i->setPositionAndIntentions(currentPosition, intendedRoute); + i->setPositionAndHeading(lat, lon, heading, speed, alt); + } +} + +void FGGroundNetwork::signOff(int id) { + TrafficVectorIterator i = activeTraffic.begin(); + // Search search if the current id alread has an entry + // This might be faster using a map instead of a vector, but let's start by taking a safe route + if (activeTraffic.size()) { + while ((i->getId() != id) && i != activeTraffic.end()) { + i++; + } + } + if (i == activeTraffic.end() || (activeTraffic.size() == 0)) { + SG_LOG(SG_GENERAL, SG_ALERT, "AI error: Aircraft without traffic record is signing off"); + } else { + i = activeTraffic.erase(i); + } +} + +void FGGroundNetwork::update(int id, double lat, double lon, double heading, double speed, double alt) { + TrafficVectorIterator i = activeTraffic.begin(); + // Search search if the current id has an entry + // This might be faster using a map instead of a vector, but let's start by taking a safe route + TrafficVectorIterator current, closest; + if (activeTraffic.size()) { + while ((i->getId() != id) && i != activeTraffic.end()) { + i++; + } + } + // update position of the current aircraft + if (i == activeTraffic.end() || (activeTraffic.size() == 0)) { + SG_LOG(SG_GENERAL, SG_ALERT, "AI error: updating aircraft without traffic record"); + } else { + i->setPositionAndHeading(lat, lon, heading, speed, alt); + current = i; + } + + // Scan for a speed adjustment change. Find the nearest aircraft that is in front + // and adjust speed when we get too close. Only do this when current position and/or + // intentions of the current aircraft match current taxiroute position of the proximate + // aircraft. + double mindist = HUGE; + if (activeTraffic.size()) + { + double course, dist, bearing, minbearing; + + //TrafficVector iterator closest; + for (TrafficVectorIterator i = activeTraffic.begin(); + i != activeTraffic.end(); i++) + { + if (i != current) { + SGWayPoint curr (lon, + lat, + alt); + SGWayPoint other (i->getLongitude (), + i->getLatitude (), + i->getAltitude ()); + other.CourseAndDistance(curr, &course, &dist); + bearing = fabs(heading-course); + if (bearing > 180) + bearing = 360-bearing; + if ((dist < mindist) && (bearing < 60.0)) + { + mindist = dist; + closest = i; + minbearing = bearing; + } + } + } + //cerr << "Distance : " << dist << " bearing : " << bearing << " heading : " << heading + // << " course : " << course << endl; + current->clearSpeedAdjustment(); + // Only clear the heading adjustment at positive speeds, otherwise the waypoint following + // code wreaks havoc + if (speed > 0.2) + current->clearHeadingAdjustment(); + // All clear + if (mindist > 100) + { + //current->clearSpeedAdjustment(); + //current->clearHeadingAdjustment(); + } + else + { + if (current->getId() == closest->getWaitsForId()) + return; + else + current->setWaitsForId(closest->getId()); + + // Getting close: Slow down to a bit less than the other aircraft + double maxAllowableDistance = (1.1*current->getRadius()) + (1.1*closest->getRadius()); + if (mindist > maxAllowableDistance) + { + if (current->checkPositionAndIntentions(*closest)) + { + // Adjust speed, but don't let it drop to below 1 knots + //if (fabs(speed) > 1) + if (!(current->hasHeadingAdjustment())) + { + current->setSpeedAdjustment(closest->getSpeed()* (mindist/100)); + //cerr << "Adjusting speed to " << closest->getSpeed() * (mindist / 100) << " " + // << "Bearing = " << minbearing << " Distance = " << mindist + // << " Latitude = " <getId() << " Closest : " << closest->getId() + // << endl; + // } + } + } + } + } + } +} + +bool FGGroundNetwork::hasInstruction(int id) +{ + TrafficVectorIterator i = activeTraffic.begin(); + // Search search if the current id has an entry + // This might be faster using a map instead of a vector, but let's start by taking a safe route + if (activeTraffic.size()) { + while ((i->getId() != id) && i != activeTraffic.end()) { + i++; + } + } + if (i == activeTraffic.end() || (activeTraffic.size() == 0)) { + SG_LOG(SG_GENERAL, SG_ALERT, "AI error: checking ATC instruction for aircraft without traffic record"); + } else { + return i->hasInstruction(); + } +} + +FGATCInstruction FGGroundNetwork::getInstruction(int id) +{ + TrafficVectorIterator i = activeTraffic.begin(); + // Search search if the current id has an entry + // This might be faster using a map instead of a vector, but let's start by taking a safe route + if (activeTraffic.size()) { + while ((i->getId() != id) && i != activeTraffic.end()) { + i++; + } + } + if (i == activeTraffic.end() || (activeTraffic.size() == 0)) { + SG_LOG(SG_GENERAL, SG_ALERT, "AI error: requesting ATC instruction for aircraft without traffic record"); + } else { + return i->getInstruction(); + } +} + + + + +/*************************************************************************** + * FGATCInstruction + * + * This class is really out of place here, and should be combined with + * FGATC controller and go into it's own file / directory + * I'm leaving it for now though, because I'm testing this stuff quite + * heavily. + **************************************************************************/ +FGATCInstruction::FGATCInstruction() +{ + holdPattern = false; + holdPosition = false; + changeSpeed = false; + changeHeading = false; + changeAltitude = false; + + double speed = 0; + double heading = 0; + double alt = 0; +} + +bool FGATCInstruction::hasInstruction() +{ + return (holdPattern || holdPosition || changeSpeed || changeHeading || changeAltitude); +} + + diff --git a/src/Airports/groundnetwork.hxx b/src/Airports/groundnetwork.hxx index 4c8bdb2eb..f4a8dd41f 100644 --- a/src/Airports/groundnetwork.hxx +++ b/src/Airports/groundnetwork.hxx @@ -26,15 +26,21 @@ #include + #include STL_STRING #include SG_USING_STD(string); SG_USING_STD(vector); + #include "parking.hxx" +//#include + + class FGTaxiSegment; // forward reference +class FGAIFlightPlan; // forward reference typedef vector FGTaxiSegmentVector; typedef vector FGTaxiSegmentPointerVector; @@ -137,6 +143,7 @@ public: bool empty () { return nodes.begin() == nodes.end(); }; bool next(int *nde); bool next(int *nde, int *rte); + void rewind(int legNr); void first() { currNode = nodes.begin(); currRoute = routes.begin(); }; int size() { return nodes.size(); }; @@ -145,10 +152,133 @@ public: typedef vector TaxiRouteVector; typedef vector::iterator TaxiRouteVectorIterator; +/************************************************************************************** + * class FGATCInstruction + * like class FGATC Controller, this class definition should go into its own file + * and or directory... For now, just testing this stuff out though... + *************************************************************************************/ +class FGATCInstruction +{ +private: + bool holdPattern; + bool holdPosition; + bool changeSpeed; + bool changeHeading; + bool changeAltitude; + + double speed; + double heading; + double alt; +public: + + FGATCInstruction(); + bool hasInstruction (); + bool getHoldPattern () { return holdPattern; }; + bool getHoldPosition () { return holdPosition; }; + bool getChangeSpeed () { return changeSpeed; }; + bool getChangeHeading () { return changeHeading; }; + bool getChangeAltitude() { return changeAltitude; }; + + double getSpeed () { return speed; }; + double getHeading () { return heading; }; + double getAlt () { return alt; }; + + void setHoldPattern (bool val) { holdPattern = val; }; + void setHoldPosition (bool val) { holdPosition = val; }; + void setChangeSpeed (bool val) { changeSpeed = val; }; + void setChangeHeading (bool val) { changeHeading = val; }; + void setChangeAltitude(bool val) { changeAltitude = val; }; + + void setSpeed (double val) { speed = val; }; + void setHeading (double val) { heading = val; }; + void setAlt (double val) { alt = val; }; +}; + + +/************************************************************************************** + * class FGTrafficRecord + *************************************************************************************/ +class FGTrafficRecord +{ +private: + int id, waitsForId; + int currentPos; + intVec intentions; + FGATCInstruction instruction; + double latitude, longitude, heading, speed, altitude, radius; + + +public: + FGTrafficRecord() {}; + + void setId(int val) { id = val; }; + void setRadius(double rad) { radius = rad;}; + void setPositionAndIntentions(int pos, FGAIFlightPlan *route); + int getId() { return id;}; + FGATCInstruction getInstruction() { return instruction;}; + bool hasInstruction() { return instruction.hasInstruction(); }; + void setPositionAndHeading(double lat, double lon, double hdg, double spd, double alt); + bool checkPositionAndIntentions(FGTrafficRecord &other); + + double getLatitude () { return latitude ; }; + double getLongitude() { return longitude; }; + double getHeading () { return heading ; }; + double getSpeed () { return speed ; }; + double getAltitude () { return altitude ; }; + double getRadius () { return radius ; }; + + int getWaitsForId () { return waitsForId; }; + + void setSpeedAdjustment(double spd) { instruction.setChangeSpeed(true); + instruction.setSpeed(spd); }; + void setHeadingAdjustment(double heading) { instruction.setChangeHeading(true); + instruction.setHeading(heading); }; + void clearSpeedAdjustment () { instruction.setChangeSpeed (false); }; + void clearHeadingAdjustment() { instruction.setChangeHeading(false); }; + + bool hasHeadingAdjustment() { return instruction.getChangeHeading(); }; + + void setWaitsForId(int id) { waitsForId = id; }; + +}; + +typedef vector TrafficVector; +typedef vector::iterator TrafficVectorIterator; + + + + +/************************************************************************************** + * class FGATCController + * NOTE: this class serves as an abstraction layer for all sorts of ATC controller, + * Ground and air, so eventually it should move to its own file / directory. + *************************************************************************************/ +class FGATCController +{ +private: + double dt_count; +public: + FGATCController() { dt_count = 0;}; + virtual ~FGATCController() {}; + virtual void announcePosition(int id, FGAIFlightPlan *intendedRoute, int currentRoute, + double lat, double lon, + double hdg, double spd, double alt, double radius) = 0; + virtual void signOff(int id) = 0; + virtual void update(int id, double lat, double lon, + double heading, double speed, double alt) = 0; + virtual bool hasInstruction(int id) = 0; + virtual FGATCInstruction getInstruction(int id) = 0; + + double getDt() { return dt_count; }; + void setDt(double dt) { dt_count = dt;}; +}; + + + /************************************************************************************** * class FGGroundNetWork *************************************************************************************/ -class FGGroundNetwork +class FGGroundNetwork : public FGATCController { private: bool hasNetwork; @@ -158,6 +288,8 @@ private: intVec nodesStack; intVec routesStack; TaxiRouteVector routes; + TrafficVector activeTraffic; + TrafficVectorIterator currTraffic; bool foundRoute; double totalDistance, maxDistance; @@ -178,7 +310,14 @@ public: FGTaxiSegment *findSegment(int idx); FGTaxiRoute findShortestRoute(int start, int end); void trace(FGTaxiNode *, int, int, double dist); - + + virtual void announcePosition(int id, FGAIFlightPlan *intendedRoute, int currentRoute, + double lat, double lon, double hdg, double spd, double alt, double radius); + virtual void signOff(int id); + virtual void update(int id, double lat, double lon, double heading, double speed, double alt); + virtual bool hasInstruction(int id); + virtual FGATCInstruction getInstruction(int id); }; + #endif diff --git a/src/Airports/simple.hxx b/src/Airports/simple.hxx index 39521fc15..72256bf5f 100644 --- a/src/Airports/simple.hxx +++ b/src/Airports/simple.hxx @@ -50,6 +50,7 @@ #include "groundnetwork.hxx" #include "dynamics.hxx" + SG_USING_STD(string); SG_USING_STD(map); SG_USING_STD(set); diff --git a/src/Traffic/SchedFlight.cxx b/src/Traffic/SchedFlight.cxx index 1e45921cd..0247b7064 100644 --- a/src/Traffic/SchedFlight.cxx +++ b/src/Traffic/SchedFlight.cxx @@ -271,7 +271,7 @@ bool FGScheduledFlight::initializeAirports() arrivalPort = globals->get_airports()->search(arrId); if(arrivalPort == NULL) { - SG_LOG( SG_GENERAL, SG_WARN, "Traffic manager could not find arrival airort : " << arrId); + SG_LOG( SG_GENERAL, SG_WARN, "Traffic manager could not find arrival airport : " << arrId); return false; } diff --git a/src/Traffic/Schedule.cxx b/src/Traffic/Schedule.cxx index f80667687..d1e181e6e 100644 --- a/src/Traffic/Schedule.cxx +++ b/src/Traffic/Schedule.cxx @@ -185,7 +185,7 @@ bool FGAISchedule::update(time_t now) time_t totalTimeEnroute, elapsedTimeEnroute, - remainingTimeEnroute; + remainingTimeEnroute, deptime = 0; double userLatitude, userLongitude; @@ -218,6 +218,8 @@ bool FGAISchedule::update(time_t now) { i->adjustTime(now); } + if (fgGetBool("/sim/traffic-manager/instantaneous-action") == true) + deptime = now; firstRun = false; } @@ -225,6 +227,8 @@ bool FGAISchedule::update(time_t now) // Because this is done at every update, we only need to check the status // of the first listed flight. sort(flights.begin(), flights.end()); + if (!deptime) + deptime = flights.begin()->getDepartureTime(); FGScheduledFlightVecIterator i = flights.begin(); if (AIManagerRef) { @@ -391,8 +395,11 @@ bool FGAISchedule::update(time_t now) aircraft->setAltitude(i->getCruiseAlt()*100); // convert from FL to feet aircraft->setSpeed(speed); aircraft->setBank(0); - aircraft->SetFlightPlan(new FGAIFlightPlan(flightPlanName, courseToDest, i->getDepartureTime(), dep, - arr,true, radius, i->getCruiseAlt()*100, lat, lon, speed, flightType, acType, airline)); + aircraft->SetFlightPlan(new FGAIFlightPlan(flightPlanName, courseToDest, deptime, + dep, arr,true, radius, + i->getCruiseAlt()*100, + lat, lon, speed, flightType, acType, + airline)); aimgr->attach(aircraft); diff --git a/src/Traffic/Schedule.hxx b/src/Traffic/Schedule.hxx index a79585e0b..e29329ab9 100644 --- a/src/Traffic/Schedule.hxx +++ b/src/Traffic/Schedule.hxx @@ -60,6 +60,8 @@ class FGAISchedule int, FGScheduledFlightVec); // construct & init FGAISchedule(const FGAISchedule &other); // copy constructor + + ~FGAISchedule(); //destructor bool update(time_t now);