]> git.mxchange.org Git - simgear.git/blob - simgear/hla/HLAFederate.cxx
Windows versionhelpers.h support.
[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         if (RTIFederate::ProcessMessageFatal == _rtiFederate->processMessage()) {
545             SG_LOG(SG_NETWORK, SG_WARN, "HLA: Fatal error on processing messages!");
546             return false;
547         }
548     }
549
550     return true;
551 }
552
553 bool
554 HLAFederate::disableTimeConstrained()
555 {
556     if (!_rtiFederate.valid()) {
557         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
558         return false;
559     }
560     return _rtiFederate->disableTimeConstrained();
561 }
562
563 bool
564 HLAFederate::enableTimeConstrainedByLocalClock()
565 {
566     // Compute the time offset from the system time to the simulation time
567     SGTimeStamp federateTime;
568     if (!queryFederateTime(federateTime)) {
569         SG_LOG(SG_NETWORK, SG_WARN, "Cannot get federate time!");
570         return false;
571     }
572     _localClockOffset = SGTimeStamp::now() - federateTime;
573     return true;
574 }
575
576 bool
577 HLAFederate::enableTimeRegulation(const SGTimeStamp& lookahead)
578 {
579     if (!_rtiFederate.valid()) {
580         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
581         return false;
582     }
583
584     if (!_rtiFederate->enableTimeRegulation(lookahead)) {
585         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Could not enable time regulation!");
586         return false;
587     }
588
589     while (!_rtiFederate->getTimeRegulationEnabled()) {
590         if (RTIFederate::ProcessMessageFatal == _rtiFederate->processMessage()) {
591             SG_LOG(SG_NETWORK, SG_WARN, "HLA: Fatal error on processing messages!");
592             return false;
593         }
594     }
595
596     return true;
597 }
598
599 bool
600 HLAFederate::enableTimeRegulation()
601 {
602     if (!enableTimeRegulation(SGTimeStamp::fromSec(0))) {
603         SG_LOG(SG_NETWORK, SG_WARN, "Cannot enable time regulation!");
604         return false;
605     }
606     if (!modifyLookahead(_leadTime + SGTimeStamp::fromSec(_timeIncrement.toSecs()*0.9))) {
607         SG_LOG(SG_NETWORK, SG_WARN, "Cannot modify lookahead!");
608         return false;
609     }
610     return true;
611 }
612
613 bool
614 HLAFederate::disableTimeRegulation()
615 {
616     if (!_rtiFederate.valid()) {
617         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
618         return false;
619     }
620     return _rtiFederate->disableTimeRegulation();
621 }
622
623 bool
624 HLAFederate::modifyLookahead(const SGTimeStamp& timeStamp)
625 {
626     if (!_rtiFederate.valid()) {
627         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
628         return false;
629     }
630     return _rtiFederate->modifyLookahead(timeStamp);
631 }
632
633 bool
634 HLAFederate::timeAdvanceBy(const SGTimeStamp& timeIncrement)
635 {
636     if (!_rtiFederate.valid()) {
637         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
638         return false;
639     }
640
641     SGTimeStamp timeStamp;
642     if (!_rtiFederate->queryFederateTime(timeStamp)) {
643         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Could not query federate time!");
644         return false;
645     }
646
647     if (!_rtiFederate->timeAdvanceRequest(timeStamp + timeIncrement)) {
648         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Time advance request failed!");
649         return false;
650     }
651
652     return processMessages();
653 }
654
655 bool
656 HLAFederate::timeAdvance(const SGTimeStamp& timeStamp)
657 {
658     if (!_rtiFederate.valid()) {
659         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
660         return false;
661     }
662
663     if (!_rtiFederate->timeAdvanceRequest(timeStamp)) {
664         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Time advance request failed!");
665         return false;
666     }
667
668     return processMessages();
669 }
670
671 bool
672 HLAFederate::timeAdvanceAvailable()
673 {
674     if (!_rtiFederate.valid()) {
675         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
676         return false;
677     }
678
679     SGTimeStamp timeStamp;
680     if (_rtiFederate->queryGALT(timeStamp)) {
681         if (!_rtiFederate->timeAdvanceRequestAvailable(timeStamp)) {
682             SG_LOG(SG_NETWORK, SG_WARN, "HLA: Time advance request failed!");
683             return false;
684         }
685     }
686
687     return processMessages();
688 }
689
690 bool
691 HLAFederate::queryFederateTime(SGTimeStamp& timeStamp)
692 {
693     if (!_rtiFederate.valid()) {
694         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
695         return false;
696     }
697     return _rtiFederate->queryFederateTime(timeStamp);
698 }
699
700 bool
701 HLAFederate::queryLookahead(SGTimeStamp& timeStamp)
702 {
703     if (!_rtiFederate.valid()) {
704         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
705         return false;
706     }
707     return _rtiFederate->queryLookahead(timeStamp);
708 }
709
710 bool
711 HLAFederate::processMessage()
712 {
713     if (!_rtiFederate.valid()) {
714         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
715         return false;
716     }
717     
718     if (RTIFederate::ProcessMessageFatal == _rtiFederate->processMessage()) {
719         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Fatal error on processing messages!");
720         return false;
721     }
722     return true;
723 }
724
725 bool
726 HLAFederate::processMessage(const SGTimeStamp& timeout)
727 {
728     if (!_rtiFederate.valid()) {
729         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
730         return false;
731     }
732
733     if (RTIFederate::ProcessMessageFatal == _rtiFederate->processMessages(timeout.toSecs(), 0)) {
734         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Fatal error on processing messages!");
735         return false;
736     }
737     return true;
738 }
739
740 bool
741 HLAFederate::processMessages()
742 {
743     if (!_rtiFederate.valid()) {
744         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
745         return false;
746     }
747
748     while (_rtiFederate->getTimeAdvancePending()) {
749         if (RTIFederate::ProcessMessageFatal == _rtiFederate->processMessage()) {
750             SG_LOG(SG_NETWORK, SG_WARN, "HLA: Fatal error on processing messages!");
751             return false;
752         }
753     }
754
755     if (_timeConstrainedByLocalClock) {
756         SGTimeStamp federateTime;
757         if (!_rtiFederate->queryFederateTime(federateTime)) {
758             SG_LOG(SG_NETWORK, SG_WARN, "HLA: Error querying federate time!");
759             return false;
760         }
761         SGTimeStamp systemTime = federateTime + _localClockOffset;
762         for (;;) {
763             double rest = (systemTime - SGTimeStamp::now()).toSecs();
764             if (rest < 0)
765                 break;
766             if (RTIFederate::ProcessMessageFatal == _rtiFederate->processMessages(rest, rest)) {
767                 SG_LOG(SG_NETWORK, SG_WARN, "HLA: Fatal error on processing messages!");
768                 return false;
769             }
770         }
771     }
772     
773     // Now flush just what is left
774     while (true) {
775         RTIFederate::ProcessMessageResult result = _rtiFederate->processMessages(0, 0);
776         if (RTIFederate::ProcessMessageLast == result)
777             break;
778         if (RTIFederate::ProcessMessageFatal == result) {
779             SG_LOG(SG_NETWORK, SG_WARN, "HLA: Fatal error on processing messages!");
780             return false;
781         }
782     }
783
784     return true;
785 }
786
787 bool
788 HLAFederate::readRTI13ObjectModelTemplate(const std::string& objectModel)
789 {
790     SG_LOG(SG_IO, SG_WARN, "HLA version RTI13 not yet(!?) supported.");
791     return false;
792 }
793
794 bool
795 HLAFederate::readRTI1516ObjectModelTemplate(const std::string& objectModel)
796 {
797     // The XML version of the federate object model.
798     // This one covers the generic attributes, parameters and data types.
799     HLAOMTXmlVisitor omtXmlVisitor;
800     try {
801         readXML(objectModel, omtXmlVisitor);
802     } catch (const sg_throwable& e) {
803         SG_LOG(SG_IO, SG_ALERT, "Could not open HLA XML object model file: "
804                << e.getMessage());
805         return false;
806     } catch (...) {
807         SG_LOG(SG_IO, SG_ALERT, "Could not open HLA XML object model file");
808         return false;
809     }
810
811     omtXmlVisitor.setToFederate(*this);
812
813     return resolveObjectModel();
814 }
815
816 bool
817 HLAFederate::readRTI1516EObjectModelTemplate(const std::string& objectModel)
818 {
819     SG_LOG(SG_IO, SG_WARN, "HLA version RTI1516E not yet(!?) supported.");
820     return false;
821 }
822
823 bool
824 HLAFederate::resolveObjectModel()
825 {
826     if (!_rtiFederate.valid()) {
827         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
828         return false;
829     }
830
831     for (InteractionClassMap::iterator i = _interactionClassMap.begin(); i != _interactionClassMap.end(); ++i) {
832         RTIInteractionClass* rtiInteractionClass = _rtiFederate->createInteractionClass(i->second->getName(), i->second.get());
833         if (!rtiInteractionClass) {
834             SG_LOG(SG_NETWORK, SG_ALERT, "HLAFederate::_insertInteractionClass(): "
835                    "No RTIInteractionClass found for \"" << i->second->getName() << "\"!");
836             return false;
837         }
838         i->second->_setRTIInteractionClass(rtiInteractionClass);
839     }
840
841     for (ObjectClassMap::iterator i = _objectClassMap.begin(); i != _objectClassMap.end(); ++i) {
842         RTIObjectClass* rtiObjectClass = _rtiFederate->createObjectClass(i->second->getName(), i->second.get());
843         if (!rtiObjectClass) {
844             SG_LOG(SG_NETWORK, SG_ALERT, "HLAFederate::_insertObjectClass(): "
845                    "No RTIObjectClass found for \"" << i->second->getName() << "\"!");
846             return false;
847         }
848         i->second->_setRTIObjectClass(rtiObjectClass);
849     }
850
851     return true;
852 }
853
854 const HLADataType*
855 HLAFederate::getDataType(const std::string& name) const
856 {
857     DataTypeMap::const_iterator i = _dataTypeMap.find(name);
858     if (i == _dataTypeMap.end())
859         return 0;
860     return i->second.get();
861 }
862
863 bool
864 HLAFederate::insertDataType(const std::string& name, const SGSharedPtr<HLADataType>& dataType)
865 {
866     if (!dataType.valid())
867         return false;
868     if (_dataTypeMap.find(name) != _dataTypeMap.end()) {
869         SG_LOG(SG_IO, SG_ALERT, "HLAFederate::insertDataType: data type with name \""
870                << name << "\" already known to federate!");
871         return false;
872     }
873     _dataTypeMap.insert(DataTypeMap::value_type(name, dataType));
874     return true;
875 }
876
877 void
878 HLAFederate::recomputeDataTypeAlignment()
879 {
880     // Finish alignment computations
881     bool changed;
882     do {
883         changed = false;
884         for (DataTypeMap::iterator i = _dataTypeMap.begin(); i != _dataTypeMap.end(); ++i) {
885             if (i->second->recomputeAlignment())
886                 changed = true;
887         }
888     } while (changed);
889 }
890
891 HLAInteractionClass*
892 HLAFederate::getInteractionClass(const std::string& name)
893 {
894     InteractionClassMap::const_iterator i = _interactionClassMap.find(name);
895     if (i == _interactionClassMap.end())
896         return 0;
897     return i->second.get();
898 }
899
900 const HLAInteractionClass*
901 HLAFederate::getInteractionClass(const std::string& name) const
902 {
903     InteractionClassMap::const_iterator i = _interactionClassMap.find(name);
904     if (i == _interactionClassMap.end())
905         return 0;
906     return i->second.get();
907 }
908
909 HLAInteractionClass*
910 HLAFederate::createInteractionClass(const std::string& name)
911 {
912     return new HLAInteractionClass(name, this);
913 }
914
915 HLAObjectClass*
916 HLAFederate::getObjectClass(const std::string& name)
917 {
918     ObjectClassMap::const_iterator i = _objectClassMap.find(name);
919     if (i == _objectClassMap.end())
920         return 0;
921     return i->second.get();
922 }
923
924 const HLAObjectClass*
925 HLAFederate::getObjectClass(const std::string& name) const
926 {
927     ObjectClassMap::const_iterator i = _objectClassMap.find(name);
928     if (i == _objectClassMap.end())
929         return 0;
930     return i->second.get();
931 }
932
933 HLAObjectClass*
934 HLAFederate::createObjectClass(const std::string& name)
935 {
936     return new HLAObjectClass(name, this);
937 }
938
939 HLAObjectInstance*
940 HLAFederate::getObjectInstance(const std::string& name)
941 {
942     ObjectInstanceMap::const_iterator i = _objectInstanceMap.find(name);
943     if (i == _objectInstanceMap.end())
944         return 0;
945     return i->second.get();
946 }
947
948 const HLAObjectInstance*
949 HLAFederate::getObjectInstance(const std::string& name) const
950 {
951     ObjectInstanceMap::const_iterator i = _objectInstanceMap.find(name);
952     if (i == _objectInstanceMap.end())
953         return 0;
954     return i->second.get();
955 }
956
957 HLAObjectInstance*
958 HLAFederate::createObjectInstance(HLAObjectClass* objectClass, const std::string& name)
959 {
960     return new HLAObjectInstance(objectClass);
961 }
962
963 void
964 HLAFederate::setDone(bool done)
965 {
966     _done = done;
967 }
968
969 bool
970 HLAFederate::getDone() const
971 {
972     return _done;
973 }
974
975 bool
976 HLAFederate::readObjectModel()
977 {
978     // Depending on the actual version, try to find an apropriate
979     // file format for the given file. The first one is always the
980     // version native object model file format.
981     switch (getVersion()) {
982     case RTI13:
983         if (readRTI13ObjectModelTemplate(getFederationObjectModel()))
984             return true;
985         if (readRTI1516ObjectModelTemplate(getFederationObjectModel()))
986             return true;
987         return readRTI1516EObjectModelTemplate(getFederationObjectModel());
988     case RTI1516:
989         if (readRTI1516ObjectModelTemplate(getFederationObjectModel()))
990             return true;
991         if (readRTI1516EObjectModelTemplate(getFederationObjectModel()))
992             return true;
993         return readRTI13ObjectModelTemplate(getFederationObjectModel());
994     case RTI1516E:
995         if (readRTI1516EObjectModelTemplate(getFederationObjectModel()))
996             return true;
997         if (readRTI1516ObjectModelTemplate(getFederationObjectModel()))
998             return true;
999         return readRTI13ObjectModelTemplate(getFederationObjectModel());
1000     default:
1001         return false;
1002     }
1003 }
1004
1005 bool
1006 HLAFederate::subscribe()
1007 {
1008     for (InteractionClassMap::iterator i = _interactionClassMap.begin(); i != _interactionClassMap.end(); ++i) {
1009         if (!i->second->subscribe())
1010             return false;
1011     }
1012
1013     for (ObjectClassMap::iterator i = _objectClassMap.begin(); i != _objectClassMap.end(); ++i) {
1014         if (!i->second->subscribe())
1015             return false;
1016     }
1017
1018     return true;
1019 }
1020
1021 bool
1022 HLAFederate::publish()
1023 {
1024     for (InteractionClassMap::iterator i = _interactionClassMap.begin(); i != _interactionClassMap.end(); ++i) {
1025         if (!i->second->publish())
1026             return false;
1027     }
1028
1029     for (ObjectClassMap::iterator i = _objectClassMap.begin(); i != _objectClassMap.end(); ++i) {
1030         if (!i->second->publish())
1031             return false;
1032     }
1033
1034     return true;
1035 }
1036
1037 bool
1038 HLAFederate::init()
1039 {
1040     // We need to talk to the rti
1041     if (!connect())
1042         return false;
1043     // Join ...
1044     if (_createFederationExecution) {
1045         if (!createJoinFederationExecution())
1046             return false;
1047     } else {
1048         if (!join())
1049             return false;
1050     }
1051     // Read the xml file containing the object model
1052     if (!readObjectModel()) {
1053         shutdown();
1054         return false;
1055     }
1056     // start being time constrained if required
1057     if (_timeConstrained) {
1058         if (!enableTimeConstrained()) {
1059             shutdown();
1060             return false;
1061         }
1062     }
1063     // Now that we are potentially time constrained, we can subscribe.
1064     // This is to make sure we do not get any time stamped message
1065     // converted to a non time stamped message by the rti.
1066     if (!subscribe()) {
1067         shutdown();
1068         return false;
1069     }
1070     // Before we publish anything start getting regulating if required
1071     if (_timeRegulating) {
1072         if (!enableTimeRegulation()) {
1073             shutdown();
1074             return false;
1075         }
1076     }
1077     // Note that starting from here, we need to be careful with things
1078     // requireing unbounded time. The rest of the federation might wait
1079     // for us to finish!
1080     
1081     // Compute the time offset from the system time to the simulation time
1082     if (_timeConstrainedByLocalClock) {
1083         if (!enableTimeConstrainedByLocalClock()) {
1084             SG_LOG(SG_NETWORK, SG_WARN, "Cannot enable time constrained by local clock!");
1085             shutdown();
1086             return false;
1087         }
1088     }
1089     
1090     // Publish what we want to write
1091     if (!publish()) {
1092         shutdown();
1093         return false;
1094     }
1095     
1096     return true;
1097 }
1098
1099 bool
1100 HLAFederate::update()
1101 {
1102     if (_timeIncrement <= SGTimeStamp::fromSec(0))
1103         return processMessages();
1104     else
1105         return timeAdvanceBy(_timeIncrement);
1106 }
1107
1108 bool
1109 HLAFederate::shutdown()
1110 {
1111     // On shutdown, just try all in order.
1112     // If something goes wrong, continue and try to get out here as good as possible.
1113     bool ret = true;
1114     
1115     if (_createFederationExecution) {
1116         if (!resignDestroyFederationExecution())
1117             ret = false;
1118     } else {
1119         if (!resign())
1120             ret = false;
1121     }
1122     
1123     if (!disconnect())
1124         ret = false;
1125     
1126     return ret;
1127 }
1128
1129 bool
1130 HLAFederate::exec()
1131 {
1132     if (!init())
1133         return false;
1134     
1135     while (!getDone()) {
1136         if (!update()) {
1137             shutdown();
1138             return false;
1139         }
1140     }
1141     
1142     if (!shutdown())
1143         return false;
1144     
1145     return true;
1146 }
1147
1148 void
1149 HLAFederate::_clearRTI()
1150 {
1151     for (InteractionClassMap::iterator i = _interactionClassMap.begin(); i != _interactionClassMap.end(); ++i)
1152         i->second->_clearRTIInteractionClass();
1153     for (ObjectInstanceMap::iterator i = _objectInstanceMap.begin(); i != _objectInstanceMap.end(); ++i)
1154         i->second->_clearRTIObjectInstance();
1155     for (ObjectClassMap::iterator i = _objectClassMap.begin(); i != _objectClassMap.end(); ++i)
1156         i->second->_clearRTIObjectClass();
1157
1158     _rtiFederate = 0;
1159 }
1160
1161 bool
1162 HLAFederate::_insertInteractionClass(HLAInteractionClass* interactionClass)
1163 {
1164     if (!interactionClass)
1165         return false;
1166     if (_interactionClassMap.find(interactionClass->getName()) != _interactionClassMap.end()) {
1167         SG_LOG(SG_IO, SG_ALERT, "HLA: _insertInteractionClass: object instance with name \""
1168                << interactionClass->getName() << "\" already known to federate!");
1169         return false;
1170     }
1171     _interactionClassMap.insert(InteractionClassMap::value_type(interactionClass->getName(), interactionClass));
1172     return true;
1173 }
1174
1175 bool
1176 HLAFederate::_insertObjectClass(HLAObjectClass* objectClass)
1177 {
1178     if (!objectClass)
1179         return false;
1180     if (_objectClassMap.find(objectClass->getName()) != _objectClassMap.end()) {
1181         SG_LOG(SG_IO, SG_ALERT, "HLA: _insertObjectClass: object instance with name \""
1182                << objectClass->getName() << "\" already known to federate!");
1183         return false;
1184     }
1185     _objectClassMap.insert(ObjectClassMap::value_type(objectClass->getName(), objectClass));
1186     return true;
1187 }
1188
1189 bool
1190 HLAFederate::_insertObjectInstance(HLAObjectInstance* objectInstance)
1191 {
1192     if (!objectInstance)
1193         return false;
1194     if (objectInstance->getName().empty()) {
1195         SG_LOG(SG_IO, SG_ALERT, "HLA: _insertObjectInstance: trying to insert object instance with empty name!");
1196         return false;
1197     }
1198     if (_objectInstanceMap.find(objectInstance->getName()) != _objectInstanceMap.end()) {
1199         SG_LOG(SG_IO, SG_WARN, "HLA: _insertObjectInstance: object instance with name \""
1200                << objectInstance->getName() << "\" already known to federate!");
1201         return false;
1202     }
1203     _objectInstanceMap.insert(ObjectInstanceMap::value_type(objectInstance->getName(), objectInstance));
1204     return true;
1205 }
1206
1207 void
1208 HLAFederate::_eraseObjectInstance(const std::string& name)
1209 {
1210     ObjectInstanceMap::iterator i = _objectInstanceMap.find(name);
1211     if (i == _objectInstanceMap.end()) {
1212         SG_LOG(SG_IO, SG_WARN, "HLA: _eraseObjectInstance: object instance with name \""
1213                << name << "\" not known to federate!");
1214         return;
1215     }
1216     _objectInstanceMap.erase(i);
1217 }
1218
1219 } // namespace simgear