1 // Copyright (C) 2009 - 2012 Mathias Froehlich
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.
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.
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.
21 #include "AIManager.hxx"
25 #include "HLAAirVehicleClass.hxx"
26 #include "HLAAircraftClass.hxx"
27 #include "HLABaloonClass.hxx"
28 #include "HLAMPAircraftClass.hxx"
30 #include "AIObject.hxx"
34 AIManager::AIManager() :
35 _maxStep(SGTimeStamp::fromSecMSec(0, 200))
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);
47 AIManager::~AIManager()
51 simgear::HLAObjectClass*
52 AIManager::createObjectClass(const std::string& name)
54 // Just there for demonstration.
55 if (name == "MPAircraft")
56 return new HLAMPAircraftClass(name, this);
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 ...
67 return new HLABaloonClass(name, this);
75 if (!simgear::HLAFederate::init())
78 SGTimeStamp federateTime;
79 queryFederateTime(federateTime);
80 _simTime = federateTime + getLeadTime();
90 // Mark newly requested paged nodes with the current simulation time.
91 _pager.setUseStamp((unsigned)_simTime.toSecs());
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())
100 _currentObject.front()->shutdown(*this);
101 _currentObject.clear();
104 // Find the first time slot we have anything scheduled for
105 TimeStampObjectListIteratorMap::iterator i;
106 i = _timeStampObjectListIteratorMap.begin();
108 if (i == _timeStampObjectListIteratorMap.end() || _simTime + _maxStep < i->first) {
109 // If the time slot is too far away, do a _maxStep time advance.
111 _simTime += _maxStep;
114 // Process the list object updates scheduled for this time slot
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())
126 _currentObject.front()->shutdown(*this);
127 _currentObject.clear();
130 // get rid of the null element
131 assert(!_objectList.front().valid());
132 _objectList.pop_front();
134 // The timestep has passed now
135 _timeStampObjectListIteratorMap.erase(i);
138 if (!timeAdvance(_simTime - getLeadTime()))
141 // Expire bounding volume nodes older than 120 seconds
148 AIManager::shutdown()
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();
161 object->shutdown(*this);
164 // Then do the hla shutdown part
165 if (!simgear::HLAFederate::shutdown())
168 // Expire bounding volume nodes
176 AIManager::insert(const SGSharedPtr<AIObject>& object)
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);
186 AIManager::schedule(AIObject& object, const SGTimeStamp& simTime)
188 if (simTime <= _simTime)
190 if (_currentObject.empty())
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;
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;
212 // Note that the iterator stays stable
213 _objectList.splice(i->second, _currentObject, _currentObject.begin());
217 AIManager::getPager() const
223 AIManager::getPager()