]> git.mxchange.org Git - simgear.git/blob - simgear/hla/HLAFederate.cxx
hla: Remove deprecated tick method.
[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::readObjectModelTemplate(const std::string& objectModel,
759                                      HLAFederate::ObjectModelFactory& objectModelFactory)
760 {
761     // The XML version of the federate object model.
762     // This one covers the generic attributes, parameters and data types.
763     HLAOMTXmlVisitor omtXmlVisitor;
764     try {
765         readXML(objectModel, omtXmlVisitor);
766     } catch (const sg_throwable& e) {
767         SG_LOG(SG_IO, SG_ALERT, "Could not open HLA XML object model file: "
768                << e.getMessage());
769         return false;
770     } catch (...) {
771         SG_LOG(SG_IO, SG_ALERT, "Could not open HLA XML object model file");
772         return false;
773     }
774
775     omtXmlVisitor.setDataTypesToFederate(*this);
776
777     unsigned numObjectClasses = omtXmlVisitor.getNumObjectClasses();
778     for (unsigned i = 0; i < numObjectClasses; ++i) {
779         const HLAOMTXmlVisitor::ObjectClass* objectClass = omtXmlVisitor.getObjectClass(i);
780         std::string objectClassName = objectClass->getName();
781
782         SGSharedPtr<HLAObjectClass> hlaObjectClass = objectModelFactory.createObjectClass(objectClassName, *this);
783         if (!hlaObjectClass.valid()) {
784             SG_LOG(SG_IO, SG_INFO, "Ignoring object class \"" << objectClassName << "\".");
785             continue;
786         }
787
788         bool publish = objectModelFactory.publishObjectClass(objectClassName, objectClass->getSharing());
789         bool subscribe = objectModelFactory.subscribeObjectClass(objectClassName, objectClass->getSharing());
790
791         // process the attributes
792         for (unsigned j = 0; j < objectClass->getNumAttributes(); ++j) {
793             const simgear::HLAOMTXmlVisitor::Attribute* attribute;
794             attribute = objectClass->getAttribute(j);
795
796             std::string attributeName = attribute->getName();
797             unsigned index = hlaObjectClass->addAttribute(attributeName);
798
799             if (index == ~0u) {
800                 SG_LOG(SG_IO, SG_WARN, "RTI does not know the \"" << attributeName << "\" attribute!");
801                 continue;
802             }
803
804             // the attributes datatype
805             SGSharedPtr<const HLADataType> dataType = getDataType(attribute->getDataType());
806             if (!dataType.valid()) {
807                 SG_LOG(SG_IO, SG_WARN, "Could not find data type for attribute \""
808                        << attributeName << "\" in object class \"" << objectClassName << "\"!");
809             }
810             hlaObjectClass->setAttributeDataType(index, dataType);
811             hlaObjectClass->setAttributeUpdateType(index, attribute->getUpdateType());
812             if (subscribe && objectModelFactory.subscribeAttribute(objectClassName, attributeName, attribute->_sharing))
813                 hlaObjectClass->setAttributeSubscriptionType(index, attribute->getSubscriptionType());
814             if (publish && objectModelFactory.publishAttribute(objectClassName, attributeName, attribute->_sharing))
815                 hlaObjectClass->setAttributePublicationType(index, attribute->getPublicationType());
816         }
817
818         if (publish)
819             hlaObjectClass->publish();
820         if (subscribe)
821             hlaObjectClass->subscribe();
822
823     }
824
825     return resolveObjectModel();
826 }
827
828 bool
829 HLAFederate::readRTI13ObjectModelTemplate(const std::string& objectModel)
830 {
831     SG_LOG(SG_IO, SG_ALERT, "HLA version RTI13 not yet(!?) supported.");
832     return false;
833 }
834
835 bool
836 HLAFederate::readRTI1516ObjectModelTemplate(const std::string& objectModel)
837 {
838     // The XML version of the federate object model.
839     // This one covers the generic attributes, parameters and data types.
840     HLAOMTXmlVisitor omtXmlVisitor;
841     try {
842         readXML(objectModel, omtXmlVisitor);
843     } catch (const sg_throwable& e) {
844         SG_LOG(SG_IO, SG_ALERT, "Could not open HLA XML object model file: "
845                << e.getMessage());
846         return false;
847     } catch (...) {
848         SG_LOG(SG_IO, SG_ALERT, "Could not open HLA XML object model file");
849         return false;
850     }
851
852     omtXmlVisitor.setToFederate(*this);
853
854     return resolveObjectModel();
855 }
856
857 bool
858 HLAFederate::readRTI1516EObjectModelTemplate(const std::string& objectModel)
859 {
860     SG_LOG(SG_IO, SG_ALERT, "HLA version RTI1516E not yet(!?) supported.");
861     return false;
862 }
863
864 bool
865 HLAFederate::resolveObjectModel()
866 {
867     if (!_rtiFederate.valid()) {
868         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
869         return false;
870     }
871
872     for (InteractionClassMap::iterator i = _interactionClassMap.begin(); i != _interactionClassMap.end(); ++i) {
873         RTIInteractionClass* rtiInteractionClass = _rtiFederate->createInteractionClass(i->second->getName(), i->second.get());
874         if (!rtiInteractionClass) {
875             SG_LOG(SG_NETWORK, SG_ALERT, "HLAFederate::_insertInteractionClass(): "
876                    "No RTIInteractionClass found for \"" << i->second->getName() << "\"!");
877             return false;
878         }
879         i->second->_setRTIInteractionClass(rtiInteractionClass);
880     }
881
882     for (ObjectClassMap::iterator i = _objectClassMap.begin(); i != _objectClassMap.end(); ++i) {
883         RTIObjectClass* rtiObjectClass = _rtiFederate->createObjectClass(i->second->getName(), i->second.get());
884         if (!rtiObjectClass) {
885             SG_LOG(SG_NETWORK, SG_ALERT, "HLAFederate::_insertObjectClass(): "
886                    "No RTIObjectClass found for \"" << i->second->getName() << "\"!");
887             return false;
888         }
889         i->second->_setRTIObjectClass(rtiObjectClass);
890     }
891
892     return true;
893 }
894
895 const HLADataType*
896 HLAFederate::getDataType(const std::string& name) const
897 {
898     DataTypeMap::const_iterator i = _dataTypeMap.find(name);
899     if (i == _dataTypeMap.end())
900         return 0;
901     return i->second.get();
902 }
903
904 bool
905 HLAFederate::insertDataType(const std::string& name, const SGSharedPtr<HLADataType>& dataType)
906 {
907     if (!dataType.valid())
908         return false;
909     if (_dataTypeMap.find(name) != _dataTypeMap.end()) {
910         SG_LOG(SG_IO, SG_ALERT, "HLAFederate::insertDataType: data type with name \""
911                << name << "\" already known to federate!");
912         return false;
913     }
914     _dataTypeMap.insert(DataTypeMap::value_type(name, dataType));
915     return true;
916 }
917
918 void
919 HLAFederate::recomputeDataTypeAlignment()
920 {
921     // Finish alignment computations
922     bool changed;
923     do {
924         changed = false;
925         for (DataTypeMap::iterator i = _dataTypeMap.begin(); i != _dataTypeMap.end(); ++i) {
926             if (i->second->recomputeAlignment())
927                 changed = true;
928         }
929     } while (changed);
930 }
931
932 HLAInteractionClass*
933 HLAFederate::getInteractionClass(const std::string& name)
934 {
935     InteractionClassMap::const_iterator i = _interactionClassMap.find(name);
936     if (i == _interactionClassMap.end())
937         return 0;
938     return i->second.get();
939 }
940
941 const HLAInteractionClass*
942 HLAFederate::getInteractionClass(const std::string& name) const
943 {
944     InteractionClassMap::const_iterator i = _interactionClassMap.find(name);
945     if (i == _interactionClassMap.end())
946         return 0;
947     return i->second.get();
948 }
949
950 HLAInteractionClass*
951 HLAFederate::createInteractionClass(const std::string& name)
952 {
953     return new HLAInteractionClass(name, this);
954 }
955
956 HLAObjectClass*
957 HLAFederate::getObjectClass(const std::string& name)
958 {
959     ObjectClassMap::const_iterator i = _objectClassMap.find(name);
960     if (i == _objectClassMap.end())
961         return 0;
962     return i->second.get();
963 }
964
965 const HLAObjectClass*
966 HLAFederate::getObjectClass(const std::string& name) const
967 {
968     ObjectClassMap::const_iterator i = _objectClassMap.find(name);
969     if (i == _objectClassMap.end())
970         return 0;
971     return i->second.get();
972 }
973
974 HLAObjectClass*
975 HLAFederate::createObjectClass(const std::string& name)
976 {
977     return new HLAObjectClass(name, this);
978 }
979
980 HLAObjectInstance*
981 HLAFederate::getObjectInstance(const std::string& name)
982 {
983     ObjectInstanceMap::const_iterator i = _objectInstanceMap.find(name);
984     if (i == _objectInstanceMap.end())
985         return 0;
986     return i->second.get();
987 }
988
989 const HLAObjectInstance*
990 HLAFederate::getObjectInstance(const std::string& name) const
991 {
992     ObjectInstanceMap::const_iterator i = _objectInstanceMap.find(name);
993     if (i == _objectInstanceMap.end())
994         return 0;
995     return i->second.get();
996 }
997
998 HLAObjectInstance*
999 HLAFederate::createObjectInstance(HLAObjectClass* objectClass, const std::string& name)
1000 {
1001     return new HLAObjectInstance(objectClass);
1002 }
1003
1004 void
1005 HLAFederate::setDone(bool done)
1006 {
1007     _done = done;
1008 }
1009
1010 bool
1011 HLAFederate::getDone() const
1012 {
1013     return _done;
1014 }
1015
1016 bool
1017 HLAFederate::readObjectModel()
1018 {
1019     // Depending on the actual version, try to find an apropriate
1020     // file format for the given file. The first one is always the
1021     // version native object model file format.
1022     switch (getVersion()) {
1023     case RTI13:
1024         if (readRTI13ObjectModelTemplate(getFederationObjectModel()))
1025             return true;
1026         if (readRTI1516ObjectModelTemplate(getFederationObjectModel()))
1027             return true;
1028         return readRTI1516EObjectModelTemplate(getFederationObjectModel());
1029     case RTI1516:
1030         if (readRTI1516ObjectModelTemplate(getFederationObjectModel()))
1031             return true;
1032         if (readRTI1516EObjectModelTemplate(getFederationObjectModel()))
1033             return true;
1034         return readRTI13ObjectModelTemplate(getFederationObjectModel());
1035     case RTI1516E:
1036         if (readRTI1516EObjectModelTemplate(getFederationObjectModel()))
1037             return true;
1038         if (readRTI1516ObjectModelTemplate(getFederationObjectModel()))
1039             return true;
1040         return readRTI13ObjectModelTemplate(getFederationObjectModel());
1041     default:
1042         return false;
1043     }
1044 }
1045
1046 bool
1047 HLAFederate::subscribe()
1048 {
1049     for (InteractionClassMap::iterator i = _interactionClassMap.begin(); i != _interactionClassMap.end(); ++i) {
1050         if (!i->second->subscribe())
1051             return false;
1052     }
1053
1054     for (ObjectClassMap::iterator i = _objectClassMap.begin(); i != _objectClassMap.end(); ++i) {
1055         if (!i->second->subscribe())
1056             return false;
1057     }
1058
1059     return true;
1060 }
1061
1062 bool
1063 HLAFederate::publish()
1064 {
1065     for (InteractionClassMap::iterator i = _interactionClassMap.begin(); i != _interactionClassMap.end(); ++i) {
1066         if (!i->second->publish())
1067             return false;
1068     }
1069
1070     for (ObjectClassMap::iterator i = _objectClassMap.begin(); i != _objectClassMap.end(); ++i) {
1071         if (!i->second->publish())
1072             return false;
1073     }
1074
1075     return true;
1076 }
1077
1078 bool
1079 HLAFederate::init()
1080 {
1081     // We need to talk to the rti
1082     if (!connect())
1083         return false;
1084     // Join ...
1085     if (_createFederationExecution) {
1086         if (!createJoinFederationExecution())
1087             return false;
1088     } else {
1089         if (!join())
1090             return false;
1091     }
1092     // Read the xml file containing the object model
1093     if (!readObjectModel()) {
1094         shutdown();
1095         return false;
1096     }
1097     // start being time constrained if required
1098     if (_timeConstrained) {
1099         if (!enableTimeConstrained()) {
1100             shutdown();
1101             return false;
1102         }
1103     }
1104     // Now that we are potentially time constrained, we can subscribe.
1105     // This is to make sure we do not get any time stamped message
1106     // converted to a non time stamped message by the rti.
1107     if (!subscribe()) {
1108         shutdown();
1109         return false;
1110     }
1111     // Before we publish anything start getting regulating if required
1112     if (_timeRegulating) {
1113         if (!enableTimeRegulation()) {
1114             shutdown();
1115             return false;
1116         }
1117     }
1118     // Note that starting from here, we need to be careful with things
1119     // requireing unbounded time. The rest of the federation might wait
1120     // for us to finish!
1121     
1122     // Compute the time offset from the system time to the simulation time
1123     if (_timeConstrainedByLocalClock) {
1124         if (!enableTimeConstrainedByLocalClock()) {
1125             SG_LOG(SG_NETWORK, SG_WARN, "Cannot enable time constrained by local clock!");
1126             shutdown();
1127             return false;
1128         }
1129     }
1130     
1131     // Publish what we want to write
1132     if (!publish()) {
1133         shutdown();
1134         return false;
1135     }
1136     
1137     return true;
1138 }
1139
1140 bool
1141 HLAFederate::update()
1142 {
1143     return timeAdvanceBy(_timeIncrement);
1144 }
1145
1146 bool
1147 HLAFederate::shutdown()
1148 {
1149     // On shutdown, just try all in order.
1150     // If something goes wrong, continue and try to get out here as good as possible.
1151     bool ret = true;
1152     
1153     if (_createFederationExecution) {
1154         if (!resignDestroyFederationExecution())
1155             ret = false;
1156     } else {
1157         if (!resign())
1158             ret = false;
1159     }
1160     
1161     if (!disconnect())
1162         ret = false;
1163     
1164     return ret;
1165 }
1166
1167 bool
1168 HLAFederate::exec()
1169 {
1170     if (!init())
1171         return false;
1172     
1173     while (!getDone()) {
1174         if (!update()) {
1175             shutdown();
1176             return false;
1177         }
1178     }
1179     
1180     if (!shutdown())
1181         return false;
1182     
1183     return true;
1184 }
1185
1186 void
1187 HLAFederate::_clearRTI()
1188 {
1189     for (InteractionClassMap::iterator i = _interactionClassMap.begin(); i != _interactionClassMap.end(); ++i)
1190         i->second->_clearRTIInteractionClass();
1191     for (ObjectInstanceMap::iterator i = _objectInstanceMap.begin(); i != _objectInstanceMap.end(); ++i)
1192         i->second->_clearRTIObjectInstance();
1193     for (ObjectClassMap::iterator i = _objectClassMap.begin(); i != _objectClassMap.end(); ++i)
1194         i->second->_clearRTIObjectClass();
1195
1196     _rtiFederate = 0;
1197 }
1198
1199 bool
1200 HLAFederate::_insertInteractionClass(const SGSharedPtr<HLAInteractionClass>& interactionClass)
1201 {
1202     if (!interactionClass.valid())
1203         return false;
1204     if (_interactionClassMap.find(interactionClass->getName()) != _interactionClassMap.end()) {
1205         SG_LOG(SG_IO, SG_ALERT, "HLA: _insertInteractionClass: object instance with name \""
1206                << interactionClass->getName() << "\" already known to federate!");
1207         return false;
1208     }
1209     _interactionClassMap.insert(InteractionClassMap::value_type(interactionClass->getName(), interactionClass));
1210     return true;
1211 }
1212
1213 bool
1214 HLAFederate::_insertObjectClass(const SGSharedPtr<HLAObjectClass>& objectClass)
1215 {
1216     if (!objectClass.valid())
1217         return false;
1218     if (_objectClassMap.find(objectClass->getName()) != _objectClassMap.end()) {
1219         SG_LOG(SG_IO, SG_ALERT, "HLA: _insertObjectClass: object instance with name \""
1220                << objectClass->getName() << "\" already known to federate!");
1221         return false;
1222     }
1223     _objectClassMap.insert(ObjectClassMap::value_type(objectClass->getName(), objectClass));
1224     return true;
1225 }
1226
1227 bool
1228 HLAFederate::_insertObjectInstance(const SGSharedPtr<HLAObjectInstance>& objectInstance)
1229 {
1230     if (!objectInstance.valid())
1231         return false;
1232     if (objectInstance->getName().empty()) {
1233         SG_LOG(SG_IO, SG_ALERT, "HLA: _insertObjectInstance: trying to insert object instance with empty name!");
1234         return false;
1235     }
1236     if (_objectInstanceMap.find(objectInstance->getName()) != _objectInstanceMap.end()) {
1237         SG_LOG(SG_IO, SG_WARN, "HLA: _insertObjectInstance: object instance with name \""
1238                << objectInstance->getName() << "\" already known to federate!");
1239         return false;
1240     }
1241     _objectInstanceMap.insert(ObjectInstanceMap::value_type(objectInstance->getName(), objectInstance));
1242     return true;
1243 }
1244
1245 void
1246 HLAFederate::_eraseObjectInstance(const std::string& name)
1247 {
1248     ObjectInstanceMap::iterator i = _objectInstanceMap.find(name);
1249     if (i == _objectInstanceMap.end()) {
1250         SG_LOG(SG_IO, SG_WARN, "HLA: _eraseObjectInstance: object instance with name \""
1251                << name << "\" not known to federate!");
1252         return;
1253     }
1254     _objectInstanceMap.erase(i);
1255 }
1256
1257 } // namespace simgear