]> git.mxchange.org Git - flightgear.git/blob - src/AIModel/AIManager.cxx
a3d670e33f4148c656e82a5591553e38f0ce7744
[flightgear.git] / src / AIModel / AIManager.cxx
1 // AIManager.cxx  Based on David Luff's AIMgr:
2 // - a global management type for AI objects
3 //
4 // Written by David Culp, started October 2003.
5 // - davidculp2@comcast.net
6 //
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License as
9 // published by the Free Software Foundation; either version 2 of the
10 // License, or (at your option) any later version.
11 //
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 // General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20
21 #include <simgear/misc/sg_path.hxx>
22 #include <Main/fg_props.hxx>
23 #include <Main/globals.hxx>
24
25 #include <list>
26
27 #include "AIManager.hxx"
28 #include "AIAircraft.hxx"
29 #include "AIShip.hxx"
30 #include "AIBallistic.hxx"
31 #include "AIStorm.hxx"
32 #include "AIThermal.hxx"
33
34 SG_USING_STD(list);
35
36
37 FGAIManager::FGAIManager() {
38   initDone = false;
39   for (int i=0; i < FGAIBase::MAX_OBJECTS; i++)
40      numObjects[i] = 0;
41   _dt = 0.0;
42   dt_count = 9;
43   scenario_filename = "";
44   ai_list.clear();
45 }
46
47 FGAIManager::~FGAIManager() {
48   ai_list_itr = ai_list.begin();
49   while(ai_list_itr != ai_list.end()) {
50       (*ai_list_itr)->unbind();
51       delete (*ai_list_itr);
52       ++ai_list_itr;
53     }
54   ai_list.clear();
55 }
56
57
58 void FGAIManager::init() {
59   root = fgGetNode("sim/ai", true);
60
61   enabled = root->getNode("enabled", true)->getBoolValue();
62   if (!enabled)
63       return;
64
65   wind_from_down_node = fgGetNode("/environment/wind-from-down-fps", true);
66  
67   scenario_filename = root->getNode("scenario", true)->getStringValue();
68   if (scenario_filename != "") processScenario( scenario_filename );
69
70   initDone = true;
71 }
72
73
74 void FGAIManager::bind() {
75    root = globals->get_props()->getNode("ai/models", true);
76    root->tie("count", SGRawValuePointer<int>(&numObjects[0]));
77 }
78
79
80 void FGAIManager::unbind() {
81     root->untie("count");
82 }
83
84
85 void FGAIManager::update(double dt) {
86
87         // initialize these for finding nearest thermals
88         range_nearest = 10000.0;
89         strength = 0.0;
90
91         if (!enabled)
92             return;
93
94         _dt = dt;
95
96         ai_list_itr = ai_list.begin();
97         while(ai_list_itr != ai_list.end()) {
98                 if ((*ai_list_itr)->getDie()) {      
99                    --numObjects[(*ai_list_itr)->getType()];
100                    --numObjects[0];
101                    (*ai_list_itr)->unbind();
102                    delete (*ai_list_itr);
103                    if ( ai_list_itr == ai_list.begin() ) {
104                        ai_list.erase(ai_list_itr);
105                        ai_list_itr = ai_list.begin();
106                        continue;
107                    } else {
108                        ai_list.erase(ai_list_itr--);
109                    }
110                 } else {
111                    fetchUserState();
112                    if ((*ai_list_itr)->isa(FGAIBase::otThermal)) {
113                        processThermal((FGAIThermal*)*ai_list_itr); 
114                    } else { 
115                       (*ai_list_itr)->update(_dt);
116                    }
117                 }
118                 ++ai_list_itr;
119         }
120         wind_from_down_node->setDoubleValue( strength );
121
122 }
123
124
125 void*
126 FGAIManager::createAircraft( FGAIModelEntity *entity ) {
127      
128         FGAIAircraft* ai_plane = new FGAIAircraft(this);
129         ai_list.push_back(ai_plane);
130         ++numObjects[0];
131         ++numObjects[FGAIBase::otAircraft];
132         if (entity->m_class == "light") {
133           ai_plane->SetPerformance(&FGAIAircraft::settings[FGAIAircraft::LIGHT]);
134         } else if (entity->m_class == "ww2_fighter") {
135           ai_plane->SetPerformance(&FGAIAircraft::settings[FGAIAircraft::WW2_FIGHTER]);
136         } else if (entity->m_class ==  "jet_transport") {
137           ai_plane->SetPerformance(&FGAIAircraft::settings[FGAIAircraft::JET_TRANSPORT]);
138         } else if (entity->m_class == "jet_fighter") {
139           ai_plane->SetPerformance(&FGAIAircraft::settings[FGAIAircraft::JET_FIGHTER]);
140         } else if (entity->m_class ==  "tanker") {
141           ai_plane->SetPerformance(&FGAIAircraft::settings[FGAIAircraft::JET_TRANSPORT]);
142           ai_plane->SetTanker(true);
143         } else {
144           ai_plane->SetPerformance(&FGAIAircraft::settings[FGAIAircraft::JET_TRANSPORT]);
145         }
146         ai_plane->setHeading(entity->heading);
147         ai_plane->setSpeed(entity->speed);
148         ai_plane->setPath(entity->path.c_str());
149         ai_plane->setAltitude(entity->altitude);
150         ai_plane->setLongitude(entity->longitude);
151         ai_plane->setLatitude(entity->latitude);
152         ai_plane->setBank(entity->roll);
153
154         if ( entity->fp ) {
155           ai_plane->SetFlightPlan(entity->fp);
156         }
157
158         ai_plane->init();
159         ai_plane->bind();
160         return ai_plane;
161 }
162
163 void*
164 FGAIManager::createShip( FGAIModelEntity *entity ) {
165
166         FGAIShip* ai_ship = new FGAIShip(this);
167         ai_list.push_back(ai_ship);
168         ++numObjects[0];
169         ++numObjects[FGAIBase::otShip];
170         ai_ship->setHeading(entity->heading);
171         ai_ship->setSpeed(entity->speed);
172         ai_ship->setPath(entity->path.c_str());
173         ai_ship->setAltitude(entity->altitude);
174         ai_ship->setLongitude(entity->longitude);
175         ai_ship->setLatitude(entity->latitude);
176         ai_ship->setBank(entity->rudder);
177
178         if ( entity->fp ) {
179            ai_ship->setFlightPlan(entity->fp);
180         }
181
182         ai_ship->init();
183         ai_ship->bind();
184         return ai_ship;
185 }
186
187 void*
188 FGAIManager::createBallistic( FGAIModelEntity *entity ) {
189
190         FGAIBallistic* ai_ballistic = new FGAIBallistic(this);
191         ai_list.push_back(ai_ballistic);
192         ++numObjects[0];
193         ++numObjects[FGAIBase::otBallistic];
194         ai_ballistic->setAzimuth(entity->azimuth);
195         ai_ballistic->setElevation(entity->elevation);
196         ai_ballistic->setSpeed(entity->speed);
197         ai_ballistic->setPath(entity->path.c_str());
198         ai_ballistic->setAltitude(entity->altitude);
199         ai_ballistic->setLongitude(entity->longitude);
200         ai_ballistic->setLatitude(entity->latitude);
201         ai_ballistic->setDragArea(entity->eda);
202         ai_ballistic->setLife(entity->life);
203         ai_ballistic->setBuoyancy(entity->buoyancy);
204         ai_ballistic->setWind_from_east(entity->wind_from_east);
205         ai_ballistic->setWind_from_north(entity->wind_from_north);
206         ai_ballistic->setWind(entity->wind);
207         ai_ballistic->setRoll(entity->roll);
208         ai_ballistic->setCd(entity->cd);
209         ai_ballistic->setMass(entity->mass);
210         ai_ballistic->setStabilisation(entity->aero_stabilised);
211         ai_ballistic->init();
212         ai_ballistic->bind();
213         return ai_ballistic;
214 }
215
216 void*
217 FGAIManager::createStorm( FGAIModelEntity *entity ) {
218
219         FGAIStorm* ai_storm = new FGAIStorm(this);
220         ++numObjects[0];
221         ++numObjects[FGAIBase::otStorm];
222         ai_storm->setHeading(entity->heading);
223         ai_storm->setSpeed(entity->speed);
224         ai_storm->setPath(entity->path.c_str());
225         ai_storm->setAltitude(entity->altitude);
226         ai_storm->setLongitude(entity->longitude);
227         ai_storm->setLatitude(entity->latitude);
228         ai_storm->init();
229         ai_storm->bind();
230         ai_list.push_back(ai_storm);
231         return ai_storm;
232 }
233
234 void*
235 FGAIManager::createThermal( FGAIModelEntity *entity ) {
236
237         FGAIThermal* ai_thermal = new FGAIThermal(this);
238         ++numObjects[0];
239         ++numObjects[FGAIBase::otThermal];
240         ai_thermal->setLongitude(entity->longitude);
241         ai_thermal->setLatitude(entity->latitude);
242         ai_thermal->setMaxStrength(entity->strength);
243         ai_thermal->setDiameter(entity->diameter / 6076.11549);
244         ai_thermal->init();
245         ai_thermal->bind();
246         ai_list.push_back(ai_thermal);
247         return ai_thermal;
248 }
249
250 void FGAIManager::destroyObject( void* ID ) {
251         ai_list_itr = ai_list.begin();
252         while(ai_list_itr != ai_list.end()) {
253             if ((*ai_list_itr)->getID() == ID) {
254               --numObjects[0];
255               --numObjects[(*ai_list_itr)->getType()];
256               (*ai_list_itr)->unbind();
257               delete (*ai_list_itr);
258               ai_list.erase(ai_list_itr);
259
260               break;
261             }
262             ++ai_list_itr;
263         }
264 }
265
266 // fetch the user's state every 10 sim cycles
267 void FGAIManager::fetchUserState( void ) {
268    ++dt_count;
269    if (dt_count == 10) {
270      user_latitude  = fgGetDouble("/position/latitude-deg");
271      user_longitude = fgGetDouble("/position/longitude-deg");
272      user_altitude  = fgGetDouble("/position/altitude-ft");
273      user_heading   = fgGetDouble("/orientation/heading-deg");
274      user_pitch     = fgGetDouble("/orientation/pitch-deg");
275      user_yaw       = fgGetDouble("/orientation/side-slip-deg");
276      user_speed     = fgGetDouble("/velocities/uBody-fps") * 0.592484;
277      dt_count = 0;
278    }
279 }
280
281
282 // only keep the results from the nearest thermal
283 void FGAIManager::processThermal( FGAIThermal* thermal ) {
284   thermal->update(_dt);
285   if ( thermal->_getRange() < range_nearest ) {
286      range_nearest = thermal->_getRange();
287      strength = thermal->getStrength();
288   }
289 }
290
291
292 void FGAIManager::processScenario( string &filename ) {
293   FGAIScenario* s = new FGAIScenario( filename );
294   for (int i=0;i<s->nEntries();i++) {
295     FGAIModelEntity* en = s->getNextEntry();
296
297     if (en) {
298       if ( en->m_type == "aircraft") {
299         createAircraft( en );
300
301       } else if ( en->m_type == "ship") {
302         createShip( en );
303
304       } else if ( en->m_type == "thunderstorm") {
305         createStorm( en );
306
307       } else if ( en->m_type == "thermal") {
308         createThermal( en );
309
310       } else if ( en->m_type == "ballistic") {
311         createBallistic( en );
312       }      
313     }
314   }
315
316   delete s;
317 }
318
319 //end AIManager.cxx