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