]> git.mxchange.org Git - flightgear.git/blob - src/ATC/atc_mgr.cxx
Fix a typo breaking some takeoff-state logic.
[flightgear.git] / src / ATC / atc_mgr.cxx
1 /******************************************************************************
2  * atc_mgr.cxx
3  * Written by Durk Talsma, started August 1, 2010.
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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
18  *
19  *
20  **************************************************************************/
21
22
23 #ifdef HAVE_CONFIG_H
24 #  include "config.h"
25 #endif
26
27 #include <iostream>
28
29 #include <Airports/dynamics.hxx>
30 #include <Airports/airportdynamicsmanager.hxx>
31 #include <Airports/airport.hxx>
32 #include <Scenery/scenery.hxx>
33 #include <Main/globals.hxx>
34 #include <Main/fg_props.hxx>
35 #include <AIModel/AIAircraft.hxx>
36 #include <Traffic/Schedule.hxx>
37 #include <Traffic/SchedFlight.hxx>
38 #include <AIModel/AIFlightPlan.hxx>
39
40 #include "atc_mgr.hxx"
41
42
43 using std::string;
44
45 FGATCManager::FGATCManager() :
46     controller(NULL),
47     prevController(NULL),
48     networkVisible(false),
49     initSucceeded(false)
50 {
51 }
52
53 FGATCManager::~FGATCManager() {
54 }
55
56 void FGATCManager::init() {
57     SGSubsystem::init();
58
59     int leg = 0;
60
61     trans_num = globals->get_props()->getNode("/sim/atc/transmission-num", true);
62
63     // find a reasonable controller for our user's aircraft..
64     // Let's start by working out the following three scenarios: 
65     // Starting on ground at a parking position
66     // Starting on ground at the runway.
67     // Starting in the Air
68     bool onGround  = fgGetBool("/sim/presets/onground");
69     string runway  = fgGetString("/sim/atc/runway");
70     string airport = fgGetString("/sim/presets/airport-id");
71     string parking = fgGetString("/sim/presets/parkpos");
72     
73
74     // Create an (invisible) AIAircraft represenation of the current
75     // Users, aircraft, that mimicks the user aircraft's behavior.
76     string callsign= fgGetString("/sim/multiplay/callsign");
77     double longitude = fgGetDouble("/position/longitude-deg");
78     double latitude  = fgGetDouble("/position/latitude-deg");
79     double altitude  = fgGetDouble("/position/altitude-ft");
80     double heading   = fgGetDouble("/orientation/heading-deg");
81     double speed     = fgGetDouble("/velocities/groundspeed-kt");
82     double aircraftRadius = 40; // note that this is currently hardcoded to a one-size-fits all JumboJet value. Should change later;
83
84     ai_ac = new FGAIAircraft;
85     ai_ac->setCallSign ( callsign  );
86     ai_ac->setLongitude( longitude );
87     ai_ac->setLatitude ( latitude  );
88     ai_ac->setAltitude ( altitude  );
89     ai_ac->setPerformance("", "jet_transport");
90
91     // NEXT UP: Create a traffic Schedule and fill that with appropriate information. This we can use to flight planning.
92     // Note that these are currently only defaults. 
93     FGAISchedule *trafficRef = new FGAISchedule;
94     trafficRef->setFlightType("gate");
95
96     FGScheduledFlight *flight =  new FGScheduledFlight;
97     flight->setDepartureAirport(airport);
98     flight->setArrivalAirport(airport);
99     flight->initializeAirports();
100     flight->setFlightRules("IFR");
101     flight->setCallSign(callsign);
102     
103     trafficRef->assign(flight);
104     FGAIFlightPlan *fp = 0; 
105     ai_ac->setTrafficRef(trafficRef);
106     
107     string flightPlanName = airport + "-" + airport + ".xml";
108     //double cruiseAlt = 100; // Doesn't really matter right now.
109     //double courseToDest = 180; // Just use something neutral; this value might affect the runway that is used though...
110     //time_t deptime = 0;        // just make sure how flightplan processing is affected by this...
111
112
113     FGAirportDynamicsRef dcs(flightgear::AirportDynamicsManager::find(airport));
114     if (dcs && onGround) {// && !runway.empty()) {
115
116         ParkingAssignment pk(dcs->getParkingByName(parking));
117       
118         // No valid parking location, so either at the runway or at a random location.
119         if (pk.isValid()) {
120             dcs->setParkingAvailable(pk.parking(), false);
121             fp = new FGAIFlightPlan;
122             controller = dcs->getStartupController();
123             int stationFreq = dcs->getGroundFrequency(1);
124             if (stationFreq > 0)
125             {
126                 //cerr << "Setting radio frequency to : " << stationFreq << endl;
127                 fgSetDouble("/instrumentation/comm[0]/frequencies/selected-mhz", ((double) stationFreq / 100.0));
128             }
129             leg = 1;
130             //double, lat, lon, head; // Unused variables;
131             //int getId = apt->getDynamics()->getParking(gateId, &lat, &lon, &head);
132             aircraftRadius = pk.parking()->getRadius();
133             string fltType = pk.parking()->getType(); // gate / ramp, ga, etc etc.
134             string aircraftType; // Unused.
135             string airline;      // Currently used for gate selection, but a fallback mechanism will apply when not specified.
136             fp->setGate(pk);
137             if (!(fp->createPushBack(ai_ac,
138                                      false,
139                                      dcs->parent(),
140                                      aircraftRadius,
141                                      fltType,
142                                      aircraftType,
143                                      airline))) {
144                 controller = 0;
145                 return;
146             }
147
148             
149             
150         } else if (!runway.empty()) {
151             controller = dcs->getTowerController();
152             int stationFreq = dcs->getTowerFrequency(2);
153             if (stationFreq > 0)
154             {
155                 //cerr << "Setting radio frequency to in airfrequency: " << stationFreq << endl;
156                 fgSetDouble("/instrumentation/comm[0]/frequencies/selected-mhz", ((double) stationFreq / 100.0));
157             }
158             fp = new FGAIFlightPlan;
159             leg = 3;
160             string fltType = "ga";
161             fp->setRunway(runway);
162             fp->createTakeOff(ai_ac, false, dcs->parent(), 0, fltType);
163             ai_ac->setTakeOffStatus(2);
164         } else {
165                 // We're on the ground somewhere. Handle this case later.
166         }
167         
168         if (fp) {
169             fp->getLastWaypoint()->setName( fp->getLastWaypoint()->getName() + string("legend"));
170         }
171      } else {
172         controller = 0;
173      }
174
175     // Create an initial flightplan and assign it to the ai_ac. We won't use this flightplan, but it is necessary to
176     // keep the ATC code happy. 
177     if (fp) {
178         fp->restart();
179         fp->setLeg(leg);
180         ai_ac->SetFlightPlan(fp);
181     }
182     if (controller) {
183         controller->announcePosition(ai_ac->getID(), fp, fp->getCurrentWaypoint()->getRouteIndex(),
184                                       ai_ac->_getLatitude(), ai_ac->_getLongitude(), heading, speed, altitude,
185                                       aircraftRadius, leg, ai_ac);
186
187     //dialog.init();
188
189    //osg::Node* node = apt->getDynamics()->getGroundNetwork()->getRenderNode();
190    //cerr << "Adding groundnetWork to the scenegraph::init" << endl;
191    //globals->get_scenery()->get_scene_graph()->addChild(node);
192    }
193     initSucceeded = true;
194 }
195
196 void FGATCManager::shutdown()
197 {
198     ai_ac.clear();
199     activeStations.clear();
200 }
201
202 void FGATCManager::addController(FGATCController *controller) {
203     activeStations.push_back(controller);
204 }
205
206 void FGATCManager::removeController(FGATCController *controller)
207 {
208     AtcVecIterator it;
209     it = std::find(activeStations.begin(), activeStations.end(), controller);
210     if (it != activeStations.end()) {
211         activeStations.erase(it);
212     }
213 }
214
215 void FGATCManager::update ( double time ) {
216     //cerr << "ATC update code is running at time: " << time << endl;
217     // Test code: let my virtual co-pilot handle ATC:
218    
219     
220
221     FGAIFlightPlan *fp = ai_ac->GetFlightPlan();
222         
223     /* test code : find out how the routing develops */
224     if (fp) {
225         int size = fp->getNrOfWayPoints();
226         //cerr << "Setting pos" << pos << " ";
227         //cerr << "setting intentions " ;
228         // This indicates that we have run out of waypoints: Im future versions, the
229         // user should be able to select a new route, but for now just shut down the
230         // system. 
231         if (size < 3) {
232             //cerr << "Shutting down the atc_mgr" << endl;
233             return;
234         }
235 #if 0
236         // Test code: Print how far we're progressing along the taxi route. 
237         //std::cerr << "Size of waypoint cue " << size << " ";
238         for (int i = 0; i < size; i++) {
239             int val = fp->getRouteIndex(i);
240             //std::cerr << fp->getWayPoint(i)->getName() << " ";
241             //if ((val) && (val != pos)) {
242             //    intentions.push_back(val);
243             //    std::cerr << "[done ] " << std::endl;
244             //}
245         }
246         //std::cerr << "[done ] " << std::endl;
247 #endif
248     }
249     if (fp) {
250         //cerr << "Currently at leg : " << fp->getLeg() << endl;
251     }
252     double longitude = fgGetDouble("/position/longitude-deg");
253     double latitude  = fgGetDouble("/position/latitude-deg");
254     double heading   = fgGetDouble("/orientation/heading-deg");
255     double speed     = fgGetDouble("/velocities/groundspeed-kt");
256     double altitude  = fgGetDouble("/position/altitude-ft");
257     
258     /*
259     SGGeod me(SGGeod::fromDegM(longitude,
260                                latitude,
261                                altitude));
262     SGGeod wpt1(SGGeod::fromDegM(fp->getWayPoint(1)->getLongitude(), 
263                                 fp->getWayPoint(1)->getLatitude(),
264                                 fp->getWayPoint(1)->getAltitude()));
265     SGGeod wpt2(SGGeod::fromDegM(fp->getWayPoint(1)->getLongitude(), 
266                                 fp->getWayPoint(1)->getLatitude(),
267                                 fp->getWayPoint(1)->getAltitude()));
268         
269     double course1, az1, dist1;
270     double course2, az2, dist2;
271     SGGeodesy::inverse(me, wpt1, course1, az1, dist1);
272     
273     cerr << "Bearing to nearest waypoint : " << course1 << " " << dist1 << ". (course " << course2 << ")." <<  endl;
274     */
275     ai_ac->setLatitude(latitude);
276     ai_ac->setLongitude(longitude);
277     ai_ac->setAltitude(altitude);
278     ai_ac->setHeading(heading);
279     ai_ac->setSpeed(speed);
280     ai_ac->update(time);
281     controller = ai_ac->getATCController();
282     FGATCDialogNew::instance()->update(time);
283     if (controller) {
284        //cerr << "name of previous waypoint : " << fp->getPreviousWaypoint()->getName() << endl;
285
286         //cerr << "Running FGATCManager::update()" << endl;
287         //cerr << "Currently under control of " << controller->getName() << endl;
288         controller->updateAircraftInformation(ai_ac->getID(),
289                                               latitude,
290                                               longitude,
291                                               heading,
292                                               speed,
293                                               altitude, time);
294         //string airport = fgGetString("/sim/presets/airport-id");
295         //FGAirport *apt = FGAirport::findByIdent(airport); 
296         // AT this stage we should update the flightplan, so that waypoint incrementing is conducted as well as leg loading. 
297         int n = trans_num->getIntValue();
298         if (n == 1) {
299             //cerr << "Toggling ground network visibility " << networkVisible << endl;
300             networkVisible = !networkVisible;
301             trans_num->setIntValue(-1);
302         }
303         if ((controller != prevController) && (prevController)) {
304             prevController->render(false);
305         }
306         controller->render(networkVisible);
307
308         //cerr << "Adding groundnetWork to the scenegraph::update" << endl;
309         prevController = controller;
310    }
311    for (AtcVecIterator atc = activeStations.begin(); atc != activeStations.end(); atc++) {
312        (*atc)->update(time);
313    }
314 }