1 /******************************************************************************
2 * AIFlightPlanCreatePushBack.cxx
3 * Written by Durk Talsma, started August 1, 2007.
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of the
8 * License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 **************************************************************************/
25 #include "AIFlightPlan.hxx"
26 #include <simgear/math/sg_geodesy.hxx>
27 #include <Airports/runways.hxx>
28 #include <Airports/dynamics.hxx>
30 #include <Environment/environment_mgr.hxx>
31 #include <Environment/environment.hxx>
34 void FGAIFlightPlan::createPushBack(FGAIAircraft *ac,
35 bool firstFlight, FGAirport *dep,
39 const string& fltType,
40 const string& aircraftType,
41 const string& airline)
43 double lat, lon, heading;
44 FGTaxiRoute *pushBackRoute;
45 // Active runway can be conditionally set by ATC, so at the start of a new flight, this
49 if (!(dep->getDynamics()->getGroundNetwork()->exists())) {
50 //cerr << "Push Back fallback" << endl;
51 createPushBackFallBack(ac, firstFlight, dep, latitude, longitude,
52 radius, fltType, aircraftType, airline);
56 if (!(dep->getDynamics()->getAvailableParking(&lat, &lon,
59 aircraftType, airline))) {
60 SG_LOG(SG_INPUT, SG_WARN, "Warning: Could not find parking for a " <<
62 " of flight type " << fltType <<
63 " of airline " << airline <<
64 " at airport " << dep->getId());
66 snprintf (buffer, 10, "%d", gateId);
67 //FGTaxiNode *tn = dep->getDynamics()->getGroundNetwork()->findNode(node);
70 wpt->name = string(buffer); // fixme: should be the name of the taxiway
73 // Elevation is currently disregarded when on_ground is true
74 // because the AIModel obtains a periodic ground elevation estimate.
75 wpt->altitude = dep->getElevation();
77 wpt->crossat = -10000;
78 wpt->gear_down = true;
79 wpt->flaps_down= true;
80 wpt->finished = false;
81 wpt->on_ground = true;
83 waypoints.push_back(wpt);
85 //cerr << "Success : GateId = " << gateId << endl;
86 SG_LOG(SG_INPUT, SG_WARN, "Warning: Succesfully found a parking for a " <<
88 " of flight type " << fltType <<
89 " of airline " << airline <<
90 " at airport " << dep->getId());
92 //cerr << "Push Back follow-up Flight" << endl;
93 dep->getDynamics()->getParking(gateId, &lat, &lon, &heading);
96 createPushBackFallBack(ac, firstFlight, dep, latitude, longitude,
97 radius, fltType, aircraftType, airline);
101 //cerr << "getting parking " << gateId;
102 //cerr << " for a " <<
104 // " of flight type " << fltType <<
105 // " of airline " << airline <<
106 // " at airport " << dep->getId() << endl;
107 FGParking *parking = dep->getDynamics()->getParking(gateId);
108 int pushBackNode = parking->getPushBackPoint();
111 pushBackRoute = parking->getPushBackRoute();
112 if ((pushBackNode > 0) && (pushBackRoute == 0)) {
115 //cerr << "Creating push-back for " << gateId << " (" << parking->getName() << ") using push-back point " << pushBackNode << endl;
116 route = dep->getDynamics()->getGroundNetwork()->findShortestRoute(gateId, pushBackNode, false);
117 parking->setPushBackRoute(new FGTaxiRoute(route));
120 pushBackRoute = parking->getPushBackRoute();
121 int size = pushBackRoute->size();
123 SG_LOG(SG_GENERAL, SG_WARN, "Push back route from gate " << gateId << " has only " << size << " nodes.");
124 SG_LOG(SG_GENERAL, SG_WARN, "Using " << pushBackNode);
126 pushBackRoute->first();
128 while(pushBackRoute->next(&node, &rte))
130 //FGTaxiNode *tn = apt->getDynamics()->getGroundNetwork()->findSegment(node)->getEnd();
132 snprintf (buffer, 10, "%d", node);
133 FGTaxiNode *tn = dep->getDynamics()->getGroundNetwork()->findNode(node);
136 wpt->name = string(buffer); // fixme: should be the name of the taxiway
137 wpt->latitude = tn->getLatitude();
138 wpt->longitude = tn->getLongitude();
139 // Elevation is currently disregarded when on_ground is true
140 // because the AIModel obtains a periodic ground elevation estimate.
141 wpt->altitude = dep->getElevation();
143 wpt->crossat = -10000;
144 wpt->gear_down = true;
145 wpt->flaps_down= true;
146 wpt->finished = false;
147 wpt->on_ground = true;
148 wpt->routeIndex = rte;
149 waypoints.push_back(wpt);
151 // some special considerations for the last point:
152 wpt->name = string("PushBackPoint");
154 //for (wpt_vector_iterator i = waypoints.begin(); i != waypoints.end(); i++) {
155 // cerr << "Waypoint Name: " << (*i)->name << endl;
158 //cerr << "Creating direct forward departure route fragment" << endl;
159 double lat2, lon2, az2;
161 geo_direct_wgs_84 ( 0, lat, lon, heading,
162 2, &lat2, &lon2, &az2 );
165 wpt->latitude = lat2;
166 wpt->longitude = lon2;
167 wpt->altitude = dep->getElevation();
169 wpt->crossat = -10000;
170 wpt->gear_down = true;
171 wpt->flaps_down= true;
172 wpt->finished = false;
173 wpt->on_ground = true;
175 waypoints.push_back(wpt);
177 geo_direct_wgs_84 ( 0, lat, lon, heading,
178 4, &lat2, &lon2, &az2 );
181 wpt->latitude = lat2;
182 wpt->longitude = lon2;
183 wpt->altitude = dep->getElevation();
185 wpt->crossat = -10000;
186 wpt->gear_down = true;
187 wpt->flaps_down= true;
188 wpt->finished = false;
189 wpt->on_ground = true;
191 waypoints.push_back(wpt);
193 //cerr << "Creating final push forward point for gate " << gateId << endl;
194 FGTaxiNode *tn = dep->getDynamics()->getGroundNetwork()->findNode(gateId);
195 FGTaxiSegmentVectorIterator ts = tn->getBeginRoute();
196 FGTaxiSegmentVectorIterator te = tn->getEndRoute();
198 SG_LOG(SG_GENERAL, SG_ALERT, "Gate " << gateId << "doesn't seem to have routes associated with it.");
201 tn = (*ts)->getEnd();
202 lastNodeVisited = tn->getIndex();
204 SG_LOG(SG_GENERAL, SG_ALERT, "No valid taxinode found");
208 wpt->name = "PushBackPoint";
209 wpt->latitude = tn->getLatitude();
210 wpt->longitude = tn->getLongitude();
211 wpt->altitude = dep->getElevation();
213 wpt->crossat = -10000;
214 wpt->gear_down = true;
215 wpt->flaps_down= true;
216 wpt->finished = false;
217 wpt->on_ground = true;
218 wpt->routeIndex = (*ts)->getIndex();
219 waypoints.push_back(wpt);
226 /*******************************************************************
227 * createPushBackFallBack
228 * This is the backup function for airports that don't have a
230 ******************************************************************/
231 void FGAIFlightPlan::createPushBackFallBack(FGAIAircraft *ac, bool firstFlight, FGAirport *dep,
235 const string& fltType,
236 const string& aircraftType,
237 const string& airline)
248 dep->getDynamics()->getParking(-1, &lat, &lon, &heading);
253 waypoint *wpt = new waypoint;
256 wpt->longitude = lon;
257 wpt->altitude = dep->getElevation();
259 wpt->crossat = -10000;
260 wpt->gear_down = true;
261 wpt->flaps_down= true;
262 wpt->finished = false;
263 wpt->on_ground = true;
265 waypoints.push_back(wpt);
267 geo_direct_wgs_84 ( 0, lat, lon, heading,
269 &lat2, &lon2, &az2 );
272 wpt->latitude = lat2;
273 wpt->longitude = lon2;
274 wpt->altitude = dep->getElevation();
276 wpt->crossat = -10000;
277 wpt->gear_down = true;
278 wpt->flaps_down= true;
279 wpt->finished = false;
280 wpt->on_ground = true;
282 waypoints.push_back(wpt);
283 geo_direct_wgs_84 ( 0, lat, lon, heading,
285 &lat2, &lon2, &az2 );
287 wpt->name = "taxiStart";
288 wpt->latitude = lat2;
289 wpt->longitude = lon2;
290 wpt->altitude = dep->getElevation();
292 wpt->crossat = -10000;
293 wpt->gear_down = true;
294 wpt->flaps_down= true;
295 wpt->finished = false;
296 wpt->on_ground = true;
298 waypoints.push_back(wpt);