]> git.mxchange.org Git - simgear.git/blob - simgear/hla/HLAFederate.cxx
hla: Use raw pointers for HLAFederate::_insert methods.
[simgear.git] / simgear / hla / HLAFederate.cxx
1 // Copyright (C) 2009 - 2012  Mathias Froehlich - Mathias.Froehlich@web.de
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Library General Public
5 // License as published by the Free Software Foundation; either
6 // version 2 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Library 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
18 #ifdef HAVE_CONFIG_H
19 #  include <simgear_config.h>
20 #endif
21
22 #include <simgear/compiler.h>
23
24 #include "HLAFederate.hxx"
25
26 #include <algorithm>
27
28 #include "simgear/debug/logstream.hxx"
29
30 #include "RTIFederate.hxx"
31 #include "RTIFederateFactoryRegistry.hxx"
32 #include "RTI13FederateFactory.hxx"
33 #include "RTIInteractionClass.hxx"
34 #include "RTIObjectClass.hxx"
35 #include "HLADataElement.hxx"
36 #include "HLADataType.hxx"
37 #include "HLAOMTXmlVisitor.hxx"
38
39 namespace simgear {
40
41 HLAFederate::HLAFederate() :
42     _version(RTI13),
43     _createFederationExecution(true),
44     _timeConstrained(false),
45     _timeRegulating(false),
46     _timeConstrainedByLocalClock(false),
47     _done(false)
48 {
49     // For now instantiate the current only available factory here explicitly
50     RTI13FederateFactory::instance();
51 }
52
53 HLAFederate::~HLAFederate()
54 {
55     _clearRTI();
56
57     // Remove the data type references from the data types.
58     // This is to remove the cycles from the data types that might happen if a data type references itself
59     for (DataTypeMap::iterator i = _dataTypeMap.begin(); i != _dataTypeMap.end(); ++i) {
60         i->second->releaseDataTypeReferences();
61     }
62 }
63
64 HLAFederate::Version
65 HLAFederate::getVersion() const
66 {
67     return _version;
68 }
69
70 bool
71 HLAFederate::setVersion(HLAFederate::Version version)
72 {
73     if (_rtiFederate.valid()) {
74         SG_LOG(SG_NETWORK, SG_ALERT, "HLA: Ignoring HLAFederate parameter setting on already connected federate!");
75         return false;
76     }
77     _version = version;
78     return true;
79 }
80
81 bool
82 HLAFederate::setVersion(const std::string& version)
83 {
84     if (version == "RTI13")
85         return setVersion(RTI13);
86     else if (version == "RTI1516")
87         return setVersion(RTI1516);
88     else if (version == "RTI1516E")
89         return setVersion(RTI1516E);
90     else {
91         /// at some time think about routing these down to the factory
92         SG_LOG(SG_NETWORK, SG_ALERT, "HLA: Unknown version string in HLAFederate::setVersion!");
93         return false;
94     }
95 }
96
97 const std::list<std::string>&
98 HLAFederate::getConnectArguments() const
99 {
100     return _connectArguments;
101 }
102
103 bool
104 HLAFederate::setConnectArguments(const std::list<std::string>& connectArguments)
105 {
106     if (_rtiFederate.valid()) {
107         SG_LOG(SG_NETWORK, SG_ALERT, "HLA: Ignoring HLAFederate parameter setting on already connected federate!");
108         return false;
109     }
110     _connectArguments = connectArguments;
111     return true;
112 }
113
114 bool
115 HLAFederate::getCreateFederationExecution() const
116 {
117     return _createFederationExecution;
118 }
119
120 bool
121 HLAFederate::setCreateFederationExecution(bool createFederationExecution)
122 {
123     _createFederationExecution = createFederationExecution;
124     return true;
125 }
126
127 const std::string&
128 HLAFederate::getFederationExecutionName() const
129 {
130     return _federationExecutionName;
131 }
132
133 bool
134 HLAFederate::setFederationExecutionName(const std::string& federationExecutionName)
135 {
136     if (_rtiFederate.valid()) {
137         SG_LOG(SG_NETWORK, SG_ALERT, "HLA: Ignoring HLAFederate parameter setting on already connected federate!");
138         return false;
139     }
140     _federationExecutionName = federationExecutionName;
141     return true;
142 }
143
144 const std::string&
145 HLAFederate::getFederationObjectModel() const
146 {
147     return _federationObjectModel;
148 }
149
150 bool
151 HLAFederate::setFederationObjectModel(const std::string& federationObjectModel)
152 {
153     if (_rtiFederate.valid()) {
154         SG_LOG(SG_NETWORK, SG_ALERT, "HLA: Ignoring HLAFederate parameter setting on already connected federate!");
155         return false;
156     }
157     _federationObjectModel = federationObjectModel;
158     return true;
159 }
160
161 const std::string&
162 HLAFederate::getFederateType() const
163 {
164     return _federateType;
165 }
166
167 bool
168 HLAFederate::setFederateType(const std::string& federateType)
169 {
170     if (_rtiFederate.valid()) {
171         SG_LOG(SG_NETWORK, SG_ALERT, "HLA: Ignoring HLAFederate parameter setting on already connected federate!");
172         return false;
173     }
174     _federateType = federateType;
175     return true;
176 }
177
178 const std::string&
179 HLAFederate::getFederateName() const
180 {
181     return _federateName;
182 }
183
184 bool
185 HLAFederate::setFederateName(const std::string& federateName)
186 {
187     if (_rtiFederate.valid()) {
188         SG_LOG(SG_NETWORK, SG_ALERT, "HLA: Ignoring HLAFederate parameter setting on already connected federate!");
189         return false;
190     }
191     _federateName = federateName;
192     return true;
193 }
194
195 bool
196 HLAFederate::connect(Version version, const std::list<std::string>& stringList)
197 {
198     _version = version;
199     _connectArguments = stringList;
200     return connect();
201 }
202
203 bool
204 HLAFederate::connect()
205 {
206     if (_rtiFederate.valid()) {
207         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Trying to connect to already connected federate!");
208         return false;
209     }
210
211     SGSharedPtr<RTIFederateFactoryRegistry> registry = RTIFederateFactoryRegistry::instance();
212     if (!registry) {
213         SG_LOG(SG_NETWORK, SG_ALERT, "HLA: RTIFederateFactoryRegistry is no longer available!");
214         return false;
215     }
216
217     switch (_version) {
218     case RTI13:
219         _rtiFederate = registry->create("RTI13", _connectArguments);
220         break;
221     case RTI1516:
222         _rtiFederate = registry->create("RTI1516", _connectArguments);
223         break;
224     case RTI1516E:
225         _rtiFederate = registry->create("RTI1516E", _connectArguments);
226         break;
227     default:
228         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Unknown rti version in connect!");
229     }
230     return _rtiFederate.valid();
231 }
232
233 bool
234 HLAFederate::disconnect()
235 {
236     if (!_rtiFederate.valid()) {
237         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
238         return false;
239     }
240
241     _clearRTI();
242     return true;
243 }
244
245 bool
246 HLAFederate::createFederationExecution(const std::string& federation, const std::string& objectModel)
247 {
248     if (!_rtiFederate.valid()) {
249         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
250         return false;
251     }
252
253     RTIFederate::FederationManagementResult createResult;
254     createResult = _rtiFederate->createFederationExecution(federation, objectModel);
255     if (createResult == RTIFederate::FederationManagementFatal)
256         return false;
257
258     _federationExecutionName = federation;
259     _federationObjectModel = objectModel;
260     return true;
261 }
262
263 bool
264 HLAFederate::destroyFederationExecution(const std::string& federation)
265 {
266     if (!_rtiFederate.valid()) {
267         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
268         return false;
269     }
270
271     RTIFederate::FederationManagementResult destroyResult;
272     destroyResult = _rtiFederate->destroyFederationExecution(federation);
273     if (destroyResult == RTIFederate::FederationManagementFatal)
274         return false;
275
276     return true;
277 }
278
279 bool
280 HLAFederate::createFederationExecution()
281 {
282     if (!_rtiFederate.valid()) {
283         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
284         return false;
285     }
286
287     RTIFederate::FederationManagementResult createResult;
288     createResult = _rtiFederate->createFederationExecution(_federationExecutionName, _federationObjectModel);
289     if (createResult != RTIFederate::FederationManagementSuccess)
290         return false;
291
292     return true;
293 }
294
295 bool
296 HLAFederate::destroyFederationExecution()
297 {
298     if (!_rtiFederate.valid()) {
299         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
300         return false;
301     }
302
303     RTIFederate::FederationManagementResult destroyResult;
304     destroyResult = _rtiFederate->destroyFederationExecution(_federationExecutionName);
305     if (destroyResult != RTIFederate::FederationManagementSuccess)
306         return false;
307
308     return true;
309 }
310
311 bool
312 HLAFederate::join(const std::string& federateType, const std::string& federation)
313 {
314     if (!_rtiFederate.valid()) {
315         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
316         return false;
317     }
318
319     RTIFederate::FederationManagementResult joinResult;
320     joinResult = _rtiFederate->join(federateType, federation);
321     if (joinResult == RTIFederate::FederationManagementFatal)
322         return false;
323
324     return true;
325 }
326
327 bool
328 HLAFederate::join()
329 {
330     if (!_rtiFederate.valid()) {
331         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
332         return false;
333     }
334
335     RTIFederate::FederationManagementResult joinResult;
336     joinResult = _rtiFederate->join(_federateType, _federationExecutionName);
337     if (joinResult != RTIFederate::FederationManagementSuccess)
338         return false;
339
340     return true;
341 }
342
343 bool
344 HLAFederate::resign()
345 {
346     if (!_rtiFederate.valid()) {
347         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
348         return false;
349     }
350     return _rtiFederate->resign();
351 }
352
353 bool
354 HLAFederate::createJoinFederationExecution()
355 {
356     if (!_rtiFederate.valid()) {
357         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
358         return false;
359     }
360
361     for (;;) {
362         // Try to join.
363         RTIFederate::FederationManagementResult joinResult;
364         joinResult = _rtiFederate->join(_federateType, _federationExecutionName);
365         switch (joinResult) {
366         case RTIFederate::FederationManagementSuccess:
367             // Fast return on success
368             return true;
369         case RTIFederate::FederationManagementFatal:
370             // Abort on fatal errors
371             return false;
372         default:
373             break;
374         };
375
376         // If not already joinable, try to create the requested federation
377         RTIFederate::FederationManagementResult createResult;
378         createResult = _rtiFederate->createFederationExecution(_federationExecutionName, _federationObjectModel);
379         switch (createResult) {
380         case RTIFederate::FederationManagementFatal:
381             // Abort on fatal errors
382             return false;
383         default:
384             // Try again to join
385             break;
386         }
387     }
388 }
389
390 bool
391 HLAFederate::resignDestroyFederationExecution()
392 {
393     if (!_rtiFederate.valid()) {
394         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
395         return false;
396     }
397     
398     // Resign ourselves
399     bool success = _rtiFederate->resign();
400
401     // and try to destroy, non fatal if still some federates joined
402     if (_rtiFederate->destroyFederationExecution(_federationExecutionName) == RTIFederate::FederationManagementFatal)
403         success = false;
404
405     return success;
406 }
407
408 bool
409 HLAFederate::getTimeConstrained() const
410 {
411     return _timeConstrained;
412 }
413
414 bool
415 HLAFederate::setTimeConstrained(bool timeConstrained)
416 {
417     _timeConstrained = timeConstrained;
418
419     if (_rtiFederate.valid() && _rtiFederate->getJoined()) {
420         if (_timeConstrained && !_rtiFederate->getTimeConstrainedEnabled()) {
421             if (!enableTimeConstrained())
422                 return false;
423         } else if (!_timeConstrained && _rtiFederate->getTimeConstrainedEnabled()) {
424             if (!disableTimeConstrained())
425                 return false;
426         }
427
428     }
429
430     return true;
431 }
432
433 bool
434 HLAFederate::getTimeConstrainedByLocalClock() const
435 {
436     return _timeConstrainedByLocalClock;
437 }
438
439 bool
440 HLAFederate::setTimeConstrainedByLocalClock(bool timeConstrainedByLocalClock)
441 {
442     _timeConstrainedByLocalClock = timeConstrainedByLocalClock;
443
444     if (_rtiFederate.valid() && _rtiFederate->getJoined()) {
445         if (_timeConstrainedByLocalClock) {
446             if (!enableTimeConstrainedByLocalClock())
447                 return false;
448         }
449     }
450
451     return true;
452 }
453
454 bool
455 HLAFederate::getTimeRegulating() const
456 {
457     return _timeRegulating;
458 }
459
460 bool
461 HLAFederate::setTimeRegulating(bool timeRegulating)
462 {
463     _timeRegulating = timeRegulating;
464
465     if (_rtiFederate.valid() && _rtiFederate->getJoined()) {
466         if (_timeRegulating && !_rtiFederate->getTimeRegulationEnabled()) {
467             if (!enableTimeRegulation())
468                 return false;
469         } else if (!_timeRegulating && _rtiFederate->getTimeRegulationEnabled()) {
470             if (!disableTimeRegulation())
471                 return false;
472         }
473
474     }
475     return true;
476 }
477
478 bool
479 HLAFederate::setLeadTime(const SGTimeStamp& leadTime)
480 {
481     if (leadTime < SGTimeStamp::fromSec(0)) {
482         SG_LOG(SG_NETWORK, SG_WARN, "Ignoring negative lead time!");
483         return false;
484     }
485
486     _leadTime = leadTime;
487
488     if (_rtiFederate.valid() && _rtiFederate->getJoined()) {
489         if (!modifyLookahead(_leadTime + SGTimeStamp::fromSec(_timeIncrement.toSecs()*0.9))) {
490             SG_LOG(SG_NETWORK, SG_WARN, "Cannot modify lookahead!");
491             return false;
492         }
493     }
494
495     return true;
496 }
497
498 const SGTimeStamp&
499 HLAFederate::getLeadTime() const
500 {
501     return _leadTime;
502 }
503
504 bool
505 HLAFederate::setTimeIncrement(const SGTimeStamp& timeIncrement)
506 {
507     if (timeIncrement < SGTimeStamp::fromSec(0)) {
508         SG_LOG(SG_NETWORK, SG_WARN, "Ignoring negative time increment!");
509         return false;
510     }
511
512     _timeIncrement = timeIncrement;
513
514     if (_rtiFederate.valid() && _rtiFederate->getJoined()) {
515         if (!modifyLookahead(_leadTime + SGTimeStamp::fromSec(_timeIncrement.toSecs()*0.9))) {
516             SG_LOG(SG_NETWORK, SG_WARN, "Cannot modify lookahead!");
517             return false;
518         }
519     }
520
521     return true;
522 }
523
524 const SGTimeStamp&
525 HLAFederate::getTimeIncrement() const
526 {
527     return _timeIncrement;
528 }
529
530 bool
531 HLAFederate::enableTimeConstrained()
532 {
533     if (!_rtiFederate.valid()) {
534         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
535         return false;
536     }
537
538     if (!_rtiFederate->enableTimeConstrained()) {
539         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Could not enable time constrained!");
540         return false;
541     }
542
543     while (!_rtiFederate->getTimeConstrainedEnabled()) {
544         _rtiFederate->processMessage();
545     }
546
547     return true;
548 }
549
550 bool
551 HLAFederate::disableTimeConstrained()
552 {
553     if (!_rtiFederate.valid()) {
554         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
555         return false;
556     }
557     return _rtiFederate->disableTimeConstrained();
558 }
559
560 bool
561 HLAFederate::enableTimeConstrainedByLocalClock()
562 {
563     // Compute the time offset from the system time to the simulation time
564     SGTimeStamp federateTime;
565     if (!queryFederateTime(federateTime)) {
566         SG_LOG(SG_NETWORK, SG_WARN, "Cannot get federate time!");
567         return false;
568     }
569     _localClockOffset = SGTimeStamp::now() - federateTime;
570     return true;
571 }
572
573 bool
574 HLAFederate::enableTimeRegulation(const SGTimeStamp& lookahead)
575 {
576     if (!_rtiFederate.valid()) {
577         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
578         return false;
579     }
580
581     if (!_rtiFederate->enableTimeRegulation(lookahead)) {
582         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Could not enable time regulation!");
583         return false;
584     }
585
586     while (!_rtiFederate->getTimeRegulationEnabled()) {
587         _rtiFederate->processMessage();
588     }
589
590     return true;
591 }
592
593 bool
594 HLAFederate::enableTimeRegulation()
595 {
596     if (!enableTimeRegulation(SGTimeStamp::fromSec(0))) {
597         SG_LOG(SG_NETWORK, SG_WARN, "Cannot enable time regulation!");
598         return false;
599     }
600     if (!modifyLookahead(_leadTime + SGTimeStamp::fromSec(_timeIncrement.toSecs()*0.9))) {
601         SG_LOG(SG_NETWORK, SG_WARN, "Cannot modify lookahead!");
602         return false;
603     }
604     return true;
605 }
606
607 bool
608 HLAFederate::disableTimeRegulation()
609 {
610     if (!_rtiFederate.valid()) {
611         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
612         return false;
613     }
614     return _rtiFederate->disableTimeRegulation();
615 }
616
617 bool
618 HLAFederate::modifyLookahead(const SGTimeStamp& timeStamp)
619 {
620     if (!_rtiFederate.valid()) {
621         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
622         return false;
623     }
624     return _rtiFederate->modifyLookahead(timeStamp);
625 }
626
627 bool
628 HLAFederate::timeAdvanceBy(const SGTimeStamp& timeIncrement)
629 {
630     if (!_rtiFederate.valid()) {
631         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
632         return false;
633     }
634
635     SGTimeStamp timeStamp;
636     if (!_rtiFederate->queryFederateTime(timeStamp)) {
637         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Could not query federate time!");
638         return false;
639     }
640
641     if (!_rtiFederate->timeAdvanceRequest(timeStamp + timeIncrement)) {
642         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Time advance request failed!");
643         return false;
644     }
645
646     return processMessages();
647 }
648
649 bool
650 HLAFederate::timeAdvance(const SGTimeStamp& timeStamp)
651 {
652     if (!_rtiFederate.valid()) {
653         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
654         return false;
655     }
656
657     if (!_rtiFederate->timeAdvanceRequest(timeStamp)) {
658         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Time advance request failed!");
659         return false;
660     }
661
662     return processMessages();
663 }
664
665 bool
666 HLAFederate::timeAdvanceAvailable()
667 {
668     if (!_rtiFederate.valid()) {
669         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
670         return false;
671     }
672
673     SGTimeStamp timeStamp;
674     if (_rtiFederate->queryGALT(timeStamp)) {
675         if (!_rtiFederate->timeAdvanceRequestAvailable(timeStamp)) {
676             SG_LOG(SG_NETWORK, SG_WARN, "HLA: Time advance request failed!");
677             return false;
678         }
679     }
680
681     return processMessages();
682 }
683
684 bool
685 HLAFederate::queryFederateTime(SGTimeStamp& timeStamp)
686 {
687     if (!_rtiFederate.valid()) {
688         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
689         return false;
690     }
691     return _rtiFederate->queryFederateTime(timeStamp);
692 }
693
694 bool
695 HLAFederate::queryLookahead(SGTimeStamp& timeStamp)
696 {
697     if (!_rtiFederate.valid()) {
698         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
699         return false;
700     }
701     return _rtiFederate->queryLookahead(timeStamp);
702 }
703
704 bool
705 HLAFederate::processMessage()
706 {
707     if (!_rtiFederate.valid()) {
708         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
709         return false;
710     }
711     return _rtiFederate->processMessage();
712 }
713
714 bool
715 HLAFederate::processMessage(const SGTimeStamp& timeout)
716 {
717     if (!_rtiFederate.valid()) {
718         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
719         return false;
720     }
721     return _rtiFederate->processMessages(timeout.toSecs(), 0);
722 }
723
724 bool
725 HLAFederate::processMessages()
726 {
727     if (!_rtiFederate.valid()) {
728         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
729         return false;
730     }
731
732     while (_rtiFederate->getTimeAdvancePending()) {
733         _rtiFederate->processMessage();
734     }
735
736     if (_timeConstrainedByLocalClock) {
737         SGTimeStamp federateTime;
738         if (!_rtiFederate->queryFederateTime(federateTime)) {
739             SG_LOG(SG_NETWORK, SG_WARN, "HLA: Error querying federate time!");
740             return false;
741         }
742         SGTimeStamp systemTime = federateTime + _localClockOffset;
743         for (;;) {
744             double rest = (systemTime - SGTimeStamp::now()).toSecs();
745             if (rest < 0)
746                 break;
747             _rtiFederate->processMessages(rest, rest);
748         }
749     }
750     
751     // Now flush just what is left
752     while (_rtiFederate->processMessages(0, 0));
753
754     return true;
755 }
756
757 bool
758 HLAFederate::readRTI13ObjectModelTemplate(const std::string& objectModel)
759 {
760     SG_LOG(SG_IO, SG_ALERT, "HLA version RTI13 not yet(!?) supported.");
761     return false;
762 }
763
764 bool
765 HLAFederate::readRTI1516ObjectModelTemplate(const std::string& objectModel)
766 {
767     // The XML version of the federate object model.
768     // This one covers the generic attributes, parameters and data types.
769     HLAOMTXmlVisitor omtXmlVisitor;
770     try {
771         readXML(objectModel, omtXmlVisitor);
772     } catch (const sg_throwable& e) {
773         SG_LOG(SG_IO, SG_ALERT, "Could not open HLA XML object model file: "
774                << e.getMessage());
775         return false;
776     } catch (...) {
777         SG_LOG(SG_IO, SG_ALERT, "Could not open HLA XML object model file");
778         return false;
779     }
780
781     omtXmlVisitor.setToFederate(*this);
782
783     return resolveObjectModel();
784 }
785
786 bool
787 HLAFederate::readRTI1516EObjectModelTemplate(const std::string& objectModel)
788 {
789     SG_LOG(SG_IO, SG_ALERT, "HLA version RTI1516E not yet(!?) supported.");
790     return false;
791 }
792
793 bool
794 HLAFederate::resolveObjectModel()
795 {
796     if (!_rtiFederate.valid()) {
797         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
798         return false;
799     }
800
801     for (InteractionClassMap::iterator i = _interactionClassMap.begin(); i != _interactionClassMap.end(); ++i) {
802         RTIInteractionClass* rtiInteractionClass = _rtiFederate->createInteractionClass(i->second->getName(), i->second.get());
803         if (!rtiInteractionClass) {
804             SG_LOG(SG_NETWORK, SG_ALERT, "HLAFederate::_insertInteractionClass(): "
805                    "No RTIInteractionClass found for \"" << i->second->getName() << "\"!");
806             return false;
807         }
808         i->second->_setRTIInteractionClass(rtiInteractionClass);
809     }
810
811     for (ObjectClassMap::iterator i = _objectClassMap.begin(); i != _objectClassMap.end(); ++i) {
812         RTIObjectClass* rtiObjectClass = _rtiFederate->createObjectClass(i->second->getName(), i->second.get());
813         if (!rtiObjectClass) {
814             SG_LOG(SG_NETWORK, SG_ALERT, "HLAFederate::_insertObjectClass(): "
815                    "No RTIObjectClass found for \"" << i->second->getName() << "\"!");
816             return false;
817         }
818         i->second->_setRTIObjectClass(rtiObjectClass);
819     }
820
821     return true;
822 }
823
824 const HLADataType*
825 HLAFederate::getDataType(const std::string& name) const
826 {
827     DataTypeMap::const_iterator i = _dataTypeMap.find(name);
828     if (i == _dataTypeMap.end())
829         return 0;
830     return i->second.get();
831 }
832
833 bool
834 HLAFederate::insertDataType(const std::string& name, const SGSharedPtr<HLADataType>& dataType)
835 {
836     if (!dataType.valid())
837         return false;
838     if (_dataTypeMap.find(name) != _dataTypeMap.end()) {
839         SG_LOG(SG_IO, SG_ALERT, "HLAFederate::insertDataType: data type with name \""
840                << name << "\" already known to federate!");
841         return false;
842     }
843     _dataTypeMap.insert(DataTypeMap::value_type(name, dataType));
844     return true;
845 }
846
847 void
848 HLAFederate::recomputeDataTypeAlignment()
849 {
850     // Finish alignment computations
851     bool changed;
852     do {
853         changed = false;
854         for (DataTypeMap::iterator i = _dataTypeMap.begin(); i != _dataTypeMap.end(); ++i) {
855             if (i->second->recomputeAlignment())
856                 changed = true;
857         }
858     } while (changed);
859 }
860
861 HLAInteractionClass*
862 HLAFederate::getInteractionClass(const std::string& name)
863 {
864     InteractionClassMap::const_iterator i = _interactionClassMap.find(name);
865     if (i == _interactionClassMap.end())
866         return 0;
867     return i->second.get();
868 }
869
870 const HLAInteractionClass*
871 HLAFederate::getInteractionClass(const std::string& name) const
872 {
873     InteractionClassMap::const_iterator i = _interactionClassMap.find(name);
874     if (i == _interactionClassMap.end())
875         return 0;
876     return i->second.get();
877 }
878
879 HLAInteractionClass*
880 HLAFederate::createInteractionClass(const std::string& name)
881 {
882     return new HLAInteractionClass(name, this);
883 }
884
885 HLAObjectClass*
886 HLAFederate::getObjectClass(const std::string& name)
887 {
888     ObjectClassMap::const_iterator i = _objectClassMap.find(name);
889     if (i == _objectClassMap.end())
890         return 0;
891     return i->second.get();
892 }
893
894 const HLAObjectClass*
895 HLAFederate::getObjectClass(const std::string& name) const
896 {
897     ObjectClassMap::const_iterator i = _objectClassMap.find(name);
898     if (i == _objectClassMap.end())
899         return 0;
900     return i->second.get();
901 }
902
903 HLAObjectClass*
904 HLAFederate::createObjectClass(const std::string& name)
905 {
906     return new HLAObjectClass(name, this);
907 }
908
909 HLAObjectInstance*
910 HLAFederate::getObjectInstance(const std::string& name)
911 {
912     ObjectInstanceMap::const_iterator i = _objectInstanceMap.find(name);
913     if (i == _objectInstanceMap.end())
914         return 0;
915     return i->second.get();
916 }
917
918 const HLAObjectInstance*
919 HLAFederate::getObjectInstance(const std::string& name) const
920 {
921     ObjectInstanceMap::const_iterator i = _objectInstanceMap.find(name);
922     if (i == _objectInstanceMap.end())
923         return 0;
924     return i->second.get();
925 }
926
927 HLAObjectInstance*
928 HLAFederate::createObjectInstance(HLAObjectClass* objectClass, const std::string& name)
929 {
930     return new HLAObjectInstance(objectClass);
931 }
932
933 void
934 HLAFederate::setDone(bool done)
935 {
936     _done = done;
937 }
938
939 bool
940 HLAFederate::getDone() const
941 {
942     return _done;
943 }
944
945 bool
946 HLAFederate::readObjectModel()
947 {
948     // Depending on the actual version, try to find an apropriate
949     // file format for the given file. The first one is always the
950     // version native object model file format.
951     switch (getVersion()) {
952     case RTI13:
953         if (readRTI13ObjectModelTemplate(getFederationObjectModel()))
954             return true;
955         if (readRTI1516ObjectModelTemplate(getFederationObjectModel()))
956             return true;
957         return readRTI1516EObjectModelTemplate(getFederationObjectModel());
958     case RTI1516:
959         if (readRTI1516ObjectModelTemplate(getFederationObjectModel()))
960             return true;
961         if (readRTI1516EObjectModelTemplate(getFederationObjectModel()))
962             return true;
963         return readRTI13ObjectModelTemplate(getFederationObjectModel());
964     case RTI1516E:
965         if (readRTI1516EObjectModelTemplate(getFederationObjectModel()))
966             return true;
967         if (readRTI1516ObjectModelTemplate(getFederationObjectModel()))
968             return true;
969         return readRTI13ObjectModelTemplate(getFederationObjectModel());
970     default:
971         return false;
972     }
973 }
974
975 bool
976 HLAFederate::subscribe()
977 {
978     for (InteractionClassMap::iterator i = _interactionClassMap.begin(); i != _interactionClassMap.end(); ++i) {
979         if (!i->second->subscribe())
980             return false;
981     }
982
983     for (ObjectClassMap::iterator i = _objectClassMap.begin(); i != _objectClassMap.end(); ++i) {
984         if (!i->second->subscribe())
985             return false;
986     }
987
988     return true;
989 }
990
991 bool
992 HLAFederate::publish()
993 {
994     for (InteractionClassMap::iterator i = _interactionClassMap.begin(); i != _interactionClassMap.end(); ++i) {
995         if (!i->second->publish())
996             return false;
997     }
998
999     for (ObjectClassMap::iterator i = _objectClassMap.begin(); i != _objectClassMap.end(); ++i) {
1000         if (!i->second->publish())
1001             return false;
1002     }
1003
1004     return true;
1005 }
1006
1007 bool
1008 HLAFederate::init()
1009 {
1010     // We need to talk to the rti
1011     if (!connect())
1012         return false;
1013     // Join ...
1014     if (_createFederationExecution) {
1015         if (!createJoinFederationExecution())
1016             return false;
1017     } else {
1018         if (!join())
1019             return false;
1020     }
1021     // Read the xml file containing the object model
1022     if (!readObjectModel()) {
1023         shutdown();
1024         return false;
1025     }
1026     // start being time constrained if required
1027     if (_timeConstrained) {
1028         if (!enableTimeConstrained()) {
1029             shutdown();
1030             return false;
1031         }
1032     }
1033     // Now that we are potentially time constrained, we can subscribe.
1034     // This is to make sure we do not get any time stamped message
1035     // converted to a non time stamped message by the rti.
1036     if (!subscribe()) {
1037         shutdown();
1038         return false;
1039     }
1040     // Before we publish anything start getting regulating if required
1041     if (_timeRegulating) {
1042         if (!enableTimeRegulation()) {
1043             shutdown();
1044             return false;
1045         }
1046     }
1047     // Note that starting from here, we need to be careful with things
1048     // requireing unbounded time. The rest of the federation might wait
1049     // for us to finish!
1050     
1051     // Compute the time offset from the system time to the simulation time
1052     if (_timeConstrainedByLocalClock) {
1053         if (!enableTimeConstrainedByLocalClock()) {
1054             SG_LOG(SG_NETWORK, SG_WARN, "Cannot enable time constrained by local clock!");
1055             shutdown();
1056             return false;
1057         }
1058     }
1059     
1060     // Publish what we want to write
1061     if (!publish()) {
1062         shutdown();
1063         return false;
1064     }
1065     
1066     return true;
1067 }
1068
1069 bool
1070 HLAFederate::update()
1071 {
1072     if (_timeIncrement <= SGTimeStamp::fromSec(0))
1073         return processMessages();
1074     else
1075         return timeAdvanceBy(_timeIncrement);
1076 }
1077
1078 bool
1079 HLAFederate::shutdown()
1080 {
1081     // On shutdown, just try all in order.
1082     // If something goes wrong, continue and try to get out here as good as possible.
1083     bool ret = true;
1084     
1085     if (_createFederationExecution) {
1086         if (!resignDestroyFederationExecution())
1087             ret = false;
1088     } else {
1089         if (!resign())
1090             ret = false;
1091     }
1092     
1093     if (!disconnect())
1094         ret = false;
1095     
1096     return ret;
1097 }
1098
1099 bool
1100 HLAFederate::exec()
1101 {
1102     if (!init())
1103         return false;
1104     
1105     while (!getDone()) {
1106         if (!update()) {
1107             shutdown();
1108             return false;
1109         }
1110     }
1111     
1112     if (!shutdown())
1113         return false;
1114     
1115     return true;
1116 }
1117
1118 void
1119 HLAFederate::_clearRTI()
1120 {
1121     for (InteractionClassMap::iterator i = _interactionClassMap.begin(); i != _interactionClassMap.end(); ++i)
1122         i->second->_clearRTIInteractionClass();
1123     for (ObjectInstanceMap::iterator i = _objectInstanceMap.begin(); i != _objectInstanceMap.end(); ++i)
1124         i->second->_clearRTIObjectInstance();
1125     for (ObjectClassMap::iterator i = _objectClassMap.begin(); i != _objectClassMap.end(); ++i)
1126         i->second->_clearRTIObjectClass();
1127
1128     _rtiFederate = 0;
1129 }
1130
1131 bool
1132 HLAFederate::_insertInteractionClass(HLAInteractionClass* interactionClass)
1133 {
1134     if (!interactionClass)
1135         return false;
1136     if (_interactionClassMap.find(interactionClass->getName()) != _interactionClassMap.end()) {
1137         SG_LOG(SG_IO, SG_ALERT, "HLA: _insertInteractionClass: object instance with name \""
1138                << interactionClass->getName() << "\" already known to federate!");
1139         return false;
1140     }
1141     _interactionClassMap.insert(InteractionClassMap::value_type(interactionClass->getName(), interactionClass));
1142     return true;
1143 }
1144
1145 bool
1146 HLAFederate::_insertObjectClass(HLAObjectClass* objectClass)
1147 {
1148     if (!objectClass)
1149         return false;
1150     if (_objectClassMap.find(objectClass->getName()) != _objectClassMap.end()) {
1151         SG_LOG(SG_IO, SG_ALERT, "HLA: _insertObjectClass: object instance with name \""
1152                << objectClass->getName() << "\" already known to federate!");
1153         return false;
1154     }
1155     _objectClassMap.insert(ObjectClassMap::value_type(objectClass->getName(), objectClass));
1156     return true;
1157 }
1158
1159 bool
1160 HLAFederate::_insertObjectInstance(HLAObjectInstance* objectInstance)
1161 {
1162     if (!objectInstance)
1163         return false;
1164     if (objectInstance->getName().empty()) {
1165         SG_LOG(SG_IO, SG_ALERT, "HLA: _insertObjectInstance: trying to insert object instance with empty name!");
1166         return false;
1167     }
1168     if (_objectInstanceMap.find(objectInstance->getName()) != _objectInstanceMap.end()) {
1169         SG_LOG(SG_IO, SG_WARN, "HLA: _insertObjectInstance: object instance with name \""
1170                << objectInstance->getName() << "\" already known to federate!");
1171         return false;
1172     }
1173     _objectInstanceMap.insert(ObjectInstanceMap::value_type(objectInstance->getName(), objectInstance));
1174     return true;
1175 }
1176
1177 void
1178 HLAFederate::_eraseObjectInstance(const std::string& name)
1179 {
1180     ObjectInstanceMap::iterator i = _objectInstanceMap.find(name);
1181     if (i == _objectInstanceMap.end()) {
1182         SG_LOG(SG_IO, SG_WARN, "HLA: _eraseObjectInstance: object instance with name \""
1183                << name << "\" not known to federate!");
1184         return;
1185     }
1186     _objectInstanceMap.erase(i);
1187 }
1188
1189 } // namespace simgear