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