]> git.mxchange.org Git - flightgear.git/blob - src/AIModel/AIManager.cxx
Fix line endings
[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 <Main/globals.hxx>
22
23 #include <Airports/simple.hxx>
24 #include <Traffic/TrafficMgr.hxx>
25
26 #include "AIManager.hxx"
27 #include "AIAircraft.hxx"
28 #include "AIShip.hxx"
29 #include "AIBallistic.hxx"
30 #include "AIStorm.hxx"
31 #include "AIThermal.hxx"
32 #include "AICarrier.hxx"
33 #include "AIStatic.hxx"
34 #include "AIMultiplayer.hxx"
35
36 FGAIManager::FGAIManager() {
37   _dt = 0.0;
38   mNumAiModels = 0;
39 }
40
41 FGAIManager::~FGAIManager() {
42   ai_list_iterator ai_list_itr = ai_list.begin();
43   while(ai_list_itr != ai_list.end()) {
44       (*ai_list_itr)->unbind();
45       ++ai_list_itr;
46   }
47 }
48
49
50 void FGAIManager::init() {
51   root = fgGetNode("sim/ai", true);
52
53   enabled = root->getNode("enabled", true)->getBoolValue();
54   if (!enabled)
55       return;
56
57   wind_from_down_node = fgGetNode("/environment/wind-from-down-fps", true);
58   wind_from_east_node  = fgGetNode("/environment/wind-from-east-fps",true);
59   wind_from_north_node = fgGetNode("/environment/wind-from-north-fps",true);
60
61   user_latitude_node  = fgGetNode("/position/latitude-deg", true);
62   user_longitude_node = fgGetNode("/position/longitude-deg", true);
63   user_altitude_node  = fgGetNode("/position/altitude-ft", true);
64   user_heading_node   = fgGetNode("/orientation/heading-deg", true);
65   user_pitch_node     = fgGetNode("/orientation/pitch-deg", true);
66   user_yaw_node       = fgGetNode("/orientation/side-slip-deg", true);
67   user_speed_node     = fgGetNode("/velocities/uBody-fps", true);
68
69
70   /// Move that into the constructor
71   for(int i = 0 ; i < root->nChildren() ; i++) {
72     SGPropertyNode *aiEntry = root->getChild( i );
73     if( !strcmp( aiEntry->getName(), "scenario" ) ) {
74       scenario_filename = aiEntry->getStringValue();
75       if (!scenario_filename.empty())
76         processScenario( scenario_filename );
77     }
78   }
79 }
80
81
82 void FGAIManager::reinit() {
83    update(0.0);
84 }
85
86
87 void FGAIManager::bind() {
88    root = globals->get_props()->getNode("ai/models", true);
89    root->tie("count", SGRawValueMethods<FGAIManager, int>(*this,
90              &FGAIManager::getNumAiObjects));
91 }
92
93
94 void FGAIManager::unbind() {
95     root->untie("count");
96 }
97
98
99 void FGAIManager::update(double dt) {
100
101   // initialize these for finding nearest thermals
102   range_nearest = 10000.0;
103   strength = 0.0;
104   if (!enabled)
105     return;
106
107   FGTrafficManager *tmgr = (FGTrafficManager*) globals->get_subsystem("Traffic Manager");
108   _dt = dt;
109
110   ai_list_iterator ai_list_itr = ai_list.begin();
111   while(ai_list_itr != ai_list.end()) {
112     if ((*ai_list_itr)->getDie()) {      
113       tmgr->release((*ai_list_itr)->getID());
114       --mNumAiModels;
115       (*ai_list_itr)->unbind();
116       ai_list_itr = ai_list.erase(ai_list_itr);
117     } else {
118       fetchUserState();
119       if ((*ai_list_itr)->isa(FGAIBase::otThermal)) {
120         FGAIBase *base = *ai_list_itr;
121         processThermal((FGAIThermal*)base); 
122       } else { 
123         (*ai_list_itr)->update(_dt);
124       }
125       ++ai_list_itr;
126     }
127   }
128   wind_from_down_node->setDoubleValue( strength ); // for thermals
129 }
130
131 void
132 FGAIManager::attach(SGSharedPtr<FGAIBase> model)
133 {
134   model->setManager(this);
135   ai_list.push_back(model);
136   ++mNumAiModels;
137   model->init();
138   model->bind();
139 }
140
141
142 void FGAIManager::destroyObject( int ID ) {
143   ai_list_iterator ai_list_itr = ai_list.begin();
144   while(ai_list_itr != ai_list.end()) {
145     if ((*ai_list_itr)->getID() == ID) {
146       --mNumAiModels;
147       (*ai_list_itr)->unbind();
148       ai_list_itr = ai_list.erase(ai_list_itr);
149     } else
150       ++ai_list_itr;
151   }
152 }
153
154 int
155 FGAIManager::getNumAiObjects(void) const
156 {
157   return mNumAiModels;
158 }
159
160 void FGAIManager::fetchUserState( void ) {
161      user_latitude  = user_latitude_node->getDoubleValue();
162      user_longitude = user_longitude_node->getDoubleValue();
163      user_altitude  = user_altitude_node->getDoubleValue();
164      user_heading   = user_heading_node->getDoubleValue();
165      user_pitch     = user_pitch_node->getDoubleValue();
166      user_yaw       = user_yaw_node->getDoubleValue();
167      user_speed     = user_speed_node->getDoubleValue() * 0.592484;
168      wind_from_east = wind_from_east_node->getDoubleValue();
169      wind_from_north = wind_from_north_node->getDoubleValue();
170 }
171
172
173 // only keep the results from the nearest thermal
174 void FGAIManager::processThermal( FGAIThermal* thermal ) {
175   thermal->update(_dt);
176   if ( thermal->_getRange() < range_nearest ) {
177      range_nearest = thermal->_getRange();
178      strength = thermal->getStrength();
179   }
180 }
181
182
183 void FGAIManager::processScenario( const string &filename ) {
184
185   SGPropertyNode_ptr scenarioTop = loadScenarioFile(filename);
186   if (!scenarioTop)
187     return;
188   SGPropertyNode* scenarios = scenarioTop->getChild("scenario");
189   if (!scenarios)
190     return;
191
192   for (int i = 0; i < scenarios->nChildren(); i++) { 
193     SGPropertyNode* scEntry = scenarios->getChild(i);
194     std::string type = scEntry->getStringValue("type", "aircraft");
195
196     if (type == "aircraft") {
197       FGAIAircraft* aircraft = new FGAIAircraft;
198       aircraft->readFromScenario(scEntry);
199       attach(aircraft);
200
201     } else if (type == "ship") {
202       FGAIShip* ship = new FGAIShip;
203       ship->readFromScenario(scEntry);
204       attach(ship);
205       
206     } else if (type == "carrier") {
207       FGAICarrier* carrier = new FGAICarrier;
208       carrier->readFromScenario(scEntry);
209       attach(carrier);
210       
211     } else if (type == "thunderstorm") {
212       FGAIStorm* storm = new FGAIStorm;
213       storm->readFromScenario(scEntry);
214       attach(storm);
215       
216     } else if (type == "thermal") {
217       FGAIThermal* thermal = new FGAIThermal;
218       thermal->readFromScenario(scEntry);
219       attach(thermal);
220       
221     } else if (type == "ballistic") {
222       FGAIBallistic* ballistic = new FGAIBallistic;
223       ballistic->readFromScenario(scEntry);
224       attach(ballistic);
225       
226     } else if (type == "static") {
227       FGAIStatic* aistatic = new FGAIStatic;
228       aistatic->readFromScenario(scEntry);
229       attach(aistatic);
230       
231     }
232   }
233 }
234
235 SGPropertyNode_ptr
236 FGAIManager::loadScenarioFile(const std::string& filename)
237 {
238   SGPath path(globals->get_fg_root());
239   path.append("AI/" + filename + ".xml");
240   try {
241     SGPropertyNode_ptr root = new SGPropertyNode;
242     readProperties(path.str(), root);
243     return root;
244   } catch (const sg_exception &e) {
245     SG_LOG(SG_GENERAL, SG_ALERT, "Incorrect path specified for AI "
246            "scenario: \"" << path.str() << "\"");
247     return 0;
248   }
249 }
250
251 // This code keeps track of models that have already been loaded
252 // Eventually we'd prbably need to find a way to keep track of models
253 // that are unloaded again
254 ssgBranch * FGAIManager::getModel(const string& path) const
255 {
256   ModelVecIterator i = loadedModels.begin();
257   while (i != loadedModels.end())
258     {
259       if (i->getPath() == path)
260         return i->getModelId();
261       i++;
262     }
263   return 0;
264 }
265
266 void FGAIManager::setModel(const string& path, ssgBranch *model)
267 {
268   loadedModels.push_back(FGModelID(path,model));
269 }
270
271 bool FGAIManager::getStartPosition(const string& id, const string& pid,
272                                    Point3D& geodPos, double& heading,
273                                    sgdVec3 uvw)
274 {
275   bool found = false;
276   SGPropertyNode* root = fgGetNode("sim/ai", true);
277   if (!root->getNode("enabled", true)->getBoolValue())
278       return found;
279
280   for(int i = 0 ; (!found) && i < root->nChildren() ; i++) {
281     SGPropertyNode *aiEntry = root->getChild( i );
282     if( !strcmp( aiEntry->getName(), "scenario" ) ) {
283       string filename = aiEntry->getStringValue();
284       SGPropertyNode_ptr scenarioTop = loadScenarioFile(filename);
285       if (scenarioTop) {
286         SGPropertyNode* scenarios = scenarioTop->getChild("scenario");
287         if (scenarios) {
288           for (int i = 0; i < scenarios->nChildren(); i++) { 
289             SGPropertyNode* scEntry = scenarios->getChild(i);
290             std::string type = scEntry->getStringValue("type");
291             std::string pnumber = scEntry->getStringValue("pennant-number");
292             std::string name = scEntry->getStringValue("name");
293             if (type == "carrier" && (pnumber == id || name == id)) {
294               SGSharedPtr<FGAICarrier> carrier = new FGAICarrier;
295               carrier->readFromScenario(scEntry);
296               
297               if (carrier->getParkPosition(pid, geodPos, heading, uvw)) {
298                 found = true;
299                 break;
300               }
301             }
302           }
303         }
304       }
305     }
306   }
307   return found;
308 }
309
310 //end AIManager.cxx