]> git.mxchange.org Git - flightgear.git/blob - src/AIModel/AIFlightPlanCreateCruise.cxx
Merge branch 'topic/gcintersect' into next
[flightgear.git] / src / AIModel / AIFlightPlanCreateCruise.cxx
1 /******************************************************************************
2  * AIFlightPlanCreateCruise.cxx
3  * Written by Durk Talsma, started February, 2006.
4  *
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.
9  *
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.
14  *
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., 675 Mass Ave, Cambridge, MA 02139, USA.
18  *
19  *
20  **************************************************************************/
21
22 #ifdef HAVE_CONFIG_H
23 #  include <config.h>
24 #endif
25
26 #include <fstream>
27 #include <iostream>
28 #include "AIFlightPlan.hxx"
29 #include <simgear/math/polar3d.hxx>
30 #include <simgear/math/sg_geodesy.hxx>
31 #include <simgear/route/waypoint.hxx>
32
33 #include <Navaids/awynet.hxx>
34 #include <Airports/runways.hxx>
35 #include <Airports/dynamics.hxx>
36
37 #include <Environment/environment_mgr.hxx>
38 #include <Environment/environment.hxx>
39
40 using std::iostream;
41
42 void FGAIFlightPlan::evaluateRoutePart(double deplat,
43                                        double deplon,
44                                        double arrlat,
45                                        double arrlon)
46 {
47   // First do a prescan of all the waypoints that are within a reasonable distance of the
48   // ideal route.
49   intVec nodes;
50   int tmpNode, prevNode;
51
52
53   SGWayPoint first (deplon,
54                     deplat,
55                     100);
56   SGWayPoint sec (arrlon,
57                   arrlat,
58                   100);
59   double course, distance;
60   first.CourseAndDistance(sec, &course, &distance);
61   distance *= SG_METER_TO_NM;
62
63   SGVec3d a = SGVec3d::fromGeoc(SGGeoc::fromDegM(deplon, deplat, 1));
64   SGVec3d b = SGVec3d::fromGeoc(SGGeoc::fromDegM(arrlon, arrlat, 1));
65   SGVec3d _cross = cross(b, a);
66
67   double angle = sgACos(dot(a, b));
68   tmpNode = 0;
69   for (double ang = 0.0; ang < angle; ang += 0.05)
70     {
71       sgdVec3 newPos;
72       sgdMat4 matrix;
73       //cerr << "Angle = " << ang << endl;
74       sgdMakeRotMat4(matrix, ang, _cross.sg());
75       for(int j = 0; j < 3; j++)
76         {
77           newPos[j] =0.0;
78           for (int k = 0; k<3; k++)
79             {
80               newPos[j] += matrix[j][k]*a[k];
81             }
82         }
83       //cerr << "1"<< endl;
84       SGGeoc geoc = SGGeoc::fromCart(SGVec3d(newPos[0], newPos[1], newPos[2]));
85
86       double midlat = geoc.getLatitudeDeg();
87       double midlon = geoc.getLongitudeDeg();
88
89       prevNode = tmpNode;
90       tmpNode = globals->get_airwaynet()->findNearestNode(midlat, midlon);
91
92       double nodelat = globals->get_airwaynet()->findNode(tmpNode)->getLatitude  ();
93       double nodelon = globals->get_airwaynet()->findNode(tmpNode)->getLongitude ();
94       SGWayPoint curr(midlat,
95                       midlon,
96                       100);
97       SGWayPoint node(nodelat,
98                       nodelon,
99                       100);
100       curr.CourseAndDistance(node, &course, &distance);
101       if ((distance < 25000) && (tmpNode != prevNode))
102         nodes.push_back(tmpNode);
103     }
104
105     intVecIterator i = nodes.begin();
106     intVecIterator j = nodes.end();
107     while (i != nodes.end())
108     {
109                 j = nodes.end();
110                 while (j != i)
111                 {
112                         j--;
113                         FGAirRoute routePart = globals->get_airwaynet()->findShortestRoute(*i, *j);
114                         if (!(routePart.empty()))
115                         {
116                                 airRoute.add(routePart);
117                                 i = j;
118                                 break;
119                         }
120                 }
121                 i++;
122         }
123 }
124
125
126 /*
127 void FGAIFlightPlan::createCruise(bool firstFlight, FGAirport *dep,
128                                   FGAirport *arr, double latitude,
129                                   double longitude, double speed, double alt)
130 {
131   bool useInitialWayPoint = true;
132   bool useCurrentWayPoint = false;
133   double heading;
134   double lat, lon, az;
135    double lat2, lon2, az2;
136    double azimuth;
137   waypoint *wpt;
138   waypoint *init_waypoint;
139     intVec ids;
140     char buffer[32];
141     SGPath routefile = globals->get_fg_root();
142     init_waypoint = new waypoint;
143     init_waypoint->name      = "Initial waypoint";
144     init_waypoint->latitude  = latitude;
145     init_waypoint->longitude = longitude;;
146     //wpt->altitude  = apt->getElevation(); // should maybe be tn->elev too
147     init_waypoint->altitude  = alt;
148     init_waypoint->speed     = 450; //speed;
149     init_waypoint->crossat   = -10000;
150     init_waypoint->gear_down = false;
151     init_waypoint->flaps_down= false;
152     init_waypoint->finished  = false;
153     init_waypoint->on_ground = false;
154     waypoints.push_back(init_waypoint);
155     routefile.append("Data/AI/FlightPlans");
156     snprintf(buffer, 32, "%s-%s.txt",
157              dep->getId().c_str(),
158              arr->getId().c_str());
159     routefile.append(buffer);
160     cerr << "trying to read " << routefile.c_str()<< endl;
161     //exit(1);
162     if (routefile.exists())
163       {
164          sg_gzifstream in( routefile.str() );
165         do {
166           in >> route;
167         } while (!(in.eof()));
168       }
169     else {
170     //int runwayId = apt->getDynamics()->getGroundNetwork()->findNearestNode(lat2, lon2);
171     //int startId = globals->get_airwaynet()->findNearestNode(dep->getLatitude(), dep->getLongitude());
172     //int endId   = globals->get_airwaynet()->findNearestNode(arr->getLatitude(), arr->getLongitude());
173     //FGAirRoute route;
174     evaluateRoutePart(dep->getLatitude(), dep->getLongitude(),
175                       arr->getLatitude(), arr->getLongitude());
176     //exit(1);
177     }
178     route.first();
179     int node;
180     if (route.empty()) {
181       // if no route could be found, create a direct gps route...
182       cerr << "still no route found from " << dep->getName() << " to << " << arr->getName() <<endl;
183
184       //exit(1);
185     } else {
186       while(route.next(&node))
187         {
188           FGNode *fn = globals->get_airwaynet()->findNode(node);
189           //cerr << "Checking status of each waypoint: " << fn->getIdent();
190
191           SGWayPoint first(init_waypoint->longitude,
192                            init_waypoint->latitude,
193                            alt);
194           SGWayPoint curr (fn->getLongitude(),
195                            fn->getLatitude(),
196                            alt);
197           SGWayPoint arr  (arr->getLongitude(),
198                            arr->getLatitude(),
199                            alt);
200           
201           double crse, crsDiff;
202           double dist;
203           first.CourseAndDistance(arr,   &course, &distance);
204           first.CourseAndDistance(curr, &crse, &dist);
205
206           dist *= SG_METER_TO_NM;
207
208           // We're only interested in the absolute value of crsDiff
209           // wich should fall in the 0-180 deg range.
210           crsDiff = fabs(crse-course);
211           if (crsDiff > 180)
212             crsDiff = 360-crsDiff;
213           // These are the three conditions that we consider including
214           // in our flight plan:
215           // 1) current waypoint is less then 100 miles away OR
216           // 2) curren waypoint is ahead of us, at any distance
217           //cerr << " Distance : " << dist << " : Course diff " << crsDiff 
218           //     << " crs to dest : " << course
219           //     << " crs to wpt  : " << crse;
220           if ((dist > 20.0) && (crsDiff > 90.0))
221             {
222               //useWpt = false;
223               // Once we start including waypoints, we have to continue, even though
224               // one of the following way point would suffice.
225               // so once is the useWpt flag is set to true, we cannot reset it to false.
226               //cerr << " discarding " << endl;
227               //   << ": Course difference = " << crsDiff
228               //  << "Course = " << course
229               // << "crse   = " << crse << endl;
230             }
231           else {
232             //i = ids.end()-1;
233             //cerr << " accepting " << endl;
234
235             //ids.pop_back();
236             wpt = new waypoint;
237             wpt->name      = "Airway"; // fixme: should be the name of the waypoint
238             wpt->latitude  = fn->getLatitude();
239             wpt->longitude = fn->getLongitude();
240             //wpt->altitude  = apt->getElevation(); // should maybe be tn->elev too
241             wpt->altitude  = alt;
242             wpt->speed     = 450; //speed;
243             wpt->crossat   = -10000;
244             wpt->gear_down = false;
245             wpt->flaps_down= false;
246             wpt->finished  = false;
247             wpt->on_ground = false;
248             waypoints.push_back(wpt);
249           }
250
251           if (!(routefile.exists()))
252             {
253               route.first();
254               fstream outf( routefile.c_str(), fstream::out );
255               while (route.next(&node))
256                 outf << node << endl;
257             }
258         }
259     }
260     arr->getDynamics()->getActiveRunway("com", 2, activeRunway);
261     if (!(globals->get_runways()->search(arr->getId(),
262                                          activeRunway,
263                                          &rwy)))
264   {
265     cout << "Failed to find runway for " << arr->getId() << endl;
266     // Hmm, how do we handle a potential error like this?
267     exit(1);
268   }
269     //string test;
270     //arr->getActiveRunway(string("com"), 1, test);
271     //exit(1);
272
273     //cerr << "Altitude = " << alt << endl;
274     //cerr << "Done" << endl;
275     //if (arr->getId() == "EHAM")
276     //  {
277     //    cerr << "Creating cruise to EHAM " << latitude << " " << longitude << endl;
278     //  }
279     heading = rwy._heading;
280     azimuth = heading + 180.0;
281     while ( azimuth >= 360.0 ) { azimuth -= 360.0; }
282
283
284     // Note: This places us at the location of the active
285     // runway during initial cruise. This needs to be
286     // fixed later.
287     geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, azimuth,
288                         110000,
289                         &lat2, &lon2, &az2 );
290     wpt = new waypoint;
291     wpt->name      = "BOD"; //wpt_node->getStringValue("name", "END");
292     wpt->latitude  = lat2;
293     wpt->longitude = lon2;
294     wpt->altitude  = alt;
295     wpt->speed     = speed;
296     wpt->crossat   = alt;
297     wpt->gear_down = false;
298     wpt->flaps_down= false;
299     wpt->finished  = false;
300     wpt->on_ground = false;
301     waypoints.push_back(wpt);
302 }
303 */
304
305
306 /*******************************************************************
307  * CreateCruise
308  * initialize the Aircraft at the parking location
309  *
310  * Note that this is the original version that does not 
311  * do any dynamic route computation.
312  ******************************************************************/
313 void FGAIFlightPlan::createCruise(bool firstFlight, FGAirport *dep, 
314                                   FGAirport *arr, double latitude, 
315                                   double longitude, double speed, 
316                                   double alt, const string& fltType)
317 {
318   waypoint *wpt;
319   wpt = createInAir("Cruise", SGGeod::fromDeg(longitude, latitude), alt, speed);
320   waypoints.push_back(wpt); 
321   
322   string rwyClass = getRunwayClassFromTrafficType(fltType);
323   arr->getDynamics()->getActiveRunway(rwyClass, 2, activeRunway);
324   rwy = arr->getRunwayByIdent(activeRunway);
325   // begin descent 110km out
326   SGGeod beginDescentPoint = rwy->pointOnCenterline(-110000);
327   
328   wpt = createInAir("BOD", beginDescentPoint, alt, speed);
329   waypoints.push_back(wpt); 
330 }