]> git.mxchange.org Git - flightgear.git/blob - utils/fgai/AIManager.cxx
Canvas: generate keypress event for text input.
[flightgear.git] / utils / fgai / AIManager.cxx
1 // Copyright (C) 2009 - 2012  Mathias Froehlich
2 //
3 // This program is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU General Public License as
5 // published by the Free Software Foundation; either version 2 of the
6 // License, or (at your option) any later version.
7 //
8 // This program is distributed in the hope that it will be useful, but
9 // WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with this program; if not, write to the Free Software
15 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
16
17 #ifdef HAVE_CONFIG_H
18 #include <config.h>
19 #endif
20
21 #include "AIManager.hxx"
22
23 #include <cassert>
24
25 #include "HLAAirVehicleClass.hxx"
26 #include "HLAAircraftClass.hxx"
27 #include "HLABaloonClass.hxx"
28 #include "HLAMPAircraftClass.hxx"
29
30 #include "AIObject.hxx"
31
32 namespace fgai {
33
34 AIManager::AIManager() :
35     _maxStep(SGTimeStamp::fromSecMSec(0, 200))
36 {
37     // Set sensible defaults
38     setFederationExecutionName("rti:///FlightGear");
39     setFederateType("AIFederate");
40     /// The hla ai module is running ahead of the simulation time of the federation.
41     /// This way we are sure that all required data has arrived at the client when it is needed.
42     /// This is the amount of simulation time the ai module leads the federations simulation time.
43     setLeadTime(SGTimeStamp::fromSec(10));
44     setTimeConstrainedByLocalClock(true);
45 }
46
47 AIManager::~AIManager()
48 {
49 }
50
51 simgear::HLAObjectClass*
52 AIManager::createObjectClass(const std::string& name)
53 {
54     // Just there for demonstration.
55     if (name == "MPAircraft")
56         return new HLAMPAircraftClass(name, this);
57
58     // These should be the future objects
59     // The air vehicle should be the one an atc looks at
60     if (name == "AirVehicle")
61         return new HLAAirVehicleClass(name, this);
62     // An aircraft with wings and that
63     if (name == "Aircraft")
64         return new HLAAircraftClass(name, this);
65     // A hot air baloon ...
66     if (name == "Baloon")
67         return new HLABaloonClass(name, this);
68
69     return 0;
70 }
71
72 bool
73 AIManager::init()
74 {
75     if (!simgear::HLAFederate::init())
76         return false;
77
78     SGTimeStamp federateTime;
79     queryFederateTime(federateTime);
80     _simTime = federateTime + getLeadTime();
81
82     _pager.start();
83
84     return true;
85 }
86
87 bool
88 AIManager::update()
89 {
90     // Mark newly requested paged nodes with the current simulation time.
91     _pager.setUseStamp((unsigned)_simTime.toSecs());
92
93     while (!_initObjectList.empty()) {
94         assert(_currentObject.empty());
95         _currentObject.splice(_currentObject.end(), _initObjectList, _initObjectList.begin());
96         _currentObject.front()->init(*this);
97         // If it did not reschedule itself, immediately delete it
98         if (_currentObject.empty())
99             continue;
100         _currentObject.front()->shutdown(*this);
101         _currentObject.clear();
102     }
103
104     // Find the first time slot we have anything scheduled for
105     TimeStampObjectListIteratorMap::iterator i;
106     i = _timeStampObjectListIteratorMap.begin();
107
108     if (i == _timeStampObjectListIteratorMap.end() || _simTime + _maxStep < i->first) {
109         // If the time slot is too far away, do a _maxStep time advance.
110
111         _simTime += _maxStep;
112
113     } else {
114         // Process the list object updates scheduled for this time slot
115
116         _simTime = i->first;
117
118         // Call the updates
119         while (_objectList.begin() != i->second) {
120             assert(_currentObject.empty());
121             _currentObject.splice(_currentObject.end(), _objectList, _objectList.begin());
122             _currentObject.front()->update(*this, _simTime);
123             // If it did not reschedule itself, immediately delete it
124             if (_currentObject.empty())
125                 continue;
126             _currentObject.front()->shutdown(*this);
127             _currentObject.clear();
128         }
129
130         // get rid of the null element
131         assert(!_objectList.front().valid());
132         _objectList.pop_front();
133
134         // The timestep has passed now
135         _timeStampObjectListIteratorMap.erase(i);
136     }
137     
138     if (!timeAdvance(_simTime - getLeadTime()))
139         return false;
140
141     // Expire bounding volume nodes older than 120 seconds
142     _pager.update(120);
143     
144     return true;
145 }
146
147 bool
148 AIManager::shutdown()
149 {
150     // don't care anmore
151     _timeStampObjectListIteratorMap.clear();
152     // Nothing has ever happened with these, just get rid of them
153     _initObjectList.clear();
154     // Call shutdown on them
155     while (!_objectList.empty()) {
156         SGSharedPtr<AIObject> object;
157         object.swap(_objectList.front());
158         _objectList.pop_front();
159         if (!object.valid())
160             continue;
161         object->shutdown(*this);
162     }
163
164     // Then do the hla shutdown part
165     if (!simgear::HLAFederate::shutdown())
166         return false;
167
168     // Expire bounding volume nodes
169     _pager.update(0);
170     _pager.stop();
171
172     return true;
173 }
174
175 void
176 AIManager::insert(const SGSharedPtr<AIObject>& object)
177 {
178     if (!object.valid())
179         return;
180     /// Note that this iterator is consistently spliced through the various lists,
181     /// This must stay stable.
182     object->_objectListIterator = _initObjectList.insert(_initObjectList.end(), object);
183 }
184
185 void
186 AIManager::schedule(AIObject& object, const SGTimeStamp& simTime)
187 {
188     if (simTime <= _simTime)
189         return;
190     if (_currentObject.empty())
191         return;
192
193     TimeStampObjectListIteratorMap::iterator i;
194     i = _timeStampObjectListIteratorMap.lower_bound(simTime);
195     if (i == _timeStampObjectListIteratorMap.end()) {
196         ObjectList::iterator j = _objectList.insert(_objectList.end(), 0);
197         typedef TimeStampObjectListIteratorMap::value_type value_type;
198         i = _timeStampObjectListIteratorMap.insert(value_type(simTime, j)).first;
199     } else if (i->first != simTime) {
200         if (i == _timeStampObjectListIteratorMap.begin()) {
201             ObjectList::iterator j = _objectList.insert(_objectList.begin(), 0);
202             typedef TimeStampObjectListIteratorMap::value_type value_type;
203             i = _timeStampObjectListIteratorMap.insert(value_type(simTime, j)).first;
204         } else {
205             --i;
206             ObjectList::iterator k = i->second;
207             ObjectList::iterator j = _objectList.insert(++k, 0);
208             typedef TimeStampObjectListIteratorMap::value_type value_type;
209             i = _timeStampObjectListIteratorMap.insert(value_type(simTime, j)).first;
210         }
211     }
212     // Note that the iterator stays stable
213     _objectList.splice(i->second, _currentObject, _currentObject.begin());
214 }
215
216 const AIBVHPager&
217 AIManager::getPager() const
218 {
219     return _pager;
220 }
221
222 AIBVHPager&
223 AIManager::getPager()
224 {
225     return _pager;
226 }
227
228 } // namespace fgai