]> git.mxchange.org Git - simgear.git/blob - simgear/hla/HLAFederate.cxx
hla: Introduce backend factory infrastructure.
[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 #include "HLAFederate.hxx"
19
20 #include "simgear/debug/logstream.hxx"
21
22 #include "RTIFederate.hxx"
23 #include "RTIFederateFactoryRegistry.hxx"
24 #include "RTI13FederateFactory.hxx"
25 #include "RTIInteractionClass.hxx"
26 #include "RTIObjectClass.hxx"
27 #include "HLADataElement.hxx"
28 #include "HLADataType.hxx"
29 #include "HLAOMTXmlVisitor.hxx"
30
31 namespace simgear {
32
33 HLAFederate::HLAFederate() :
34     _version(RTI13),
35     _createFederationExecution(true),
36     _timeConstrained(false),
37     _timeRegulating(false),
38     _timeConstrainedByLocalClock(false),
39     _done(false)
40 {
41     // For now instantiate the current only available factory here explicitly
42     RTI13FederateFactory::instance();
43 }
44
45 HLAFederate::~HLAFederate()
46 {
47 }
48
49 HLAFederate::Version
50 HLAFederate::getVersion() const
51 {
52     return _version;
53 }
54
55 bool
56 HLAFederate::setVersion(HLAFederate::Version version)
57 {
58     if (_rtiFederate.valid()) {
59         SG_LOG(SG_NETWORK, SG_ALERT, "HLA: Ignoring HLAFederate parameter setting on already connected federate!");
60         return false;
61     }
62     _version = version;
63     return true;
64 }
65
66 const std::list<std::string>&
67 HLAFederate::getConnectArguments() const
68 {
69     return _connectArguments;
70 }
71
72 bool
73 HLAFederate::setConnectArguments(const std::list<std::string>& connectArguments)
74 {
75     if (_rtiFederate.valid()) {
76         SG_LOG(SG_NETWORK, SG_ALERT, "HLA: Ignoring HLAFederate parameter setting on already connected federate!");
77         return false;
78     }
79     _connectArguments = connectArguments;
80     return true;
81 }
82
83 bool
84 HLAFederate::getCreateFederationExecution() const
85 {
86     return _createFederationExecution;
87 }
88
89 bool
90 HLAFederate::setCreateFederationExecution(bool createFederationExecution)
91 {
92     _createFederationExecution = createFederationExecution;
93     return true;
94 }
95
96 const std::string&
97 HLAFederate::getFederationExecutionName() const
98 {
99     return _federationExecutionName;
100 }
101
102 bool
103 HLAFederate::setFederationExecutionName(const std::string& federationExecutionName)
104 {
105     if (_rtiFederate.valid()) {
106         SG_LOG(SG_NETWORK, SG_ALERT, "HLA: Ignoring HLAFederate parameter setting on already connected federate!");
107         return false;
108     }
109     _federationExecutionName = federationExecutionName;
110     return true;
111 }
112
113 const std::string&
114 HLAFederate::getFederationObjectModel() const
115 {
116     return _federationObjectModel;
117 }
118
119 bool
120 HLAFederate::setFederationObjectModel(const std::string& federationObjectModel)
121 {
122     if (_rtiFederate.valid()) {
123         SG_LOG(SG_NETWORK, SG_ALERT, "HLA: Ignoring HLAFederate parameter setting on already connected federate!");
124         return false;
125     }
126     _federationObjectModel = federationObjectModel;
127     return true;
128 }
129
130 const std::string&
131 HLAFederate::getFederateType() const
132 {
133     return _federateType;
134 }
135
136 bool
137 HLAFederate::setFederateType(const std::string& federateType)
138 {
139     if (_rtiFederate.valid()) {
140         SG_LOG(SG_NETWORK, SG_ALERT, "HLA: Ignoring HLAFederate parameter setting on already connected federate!");
141         return false;
142     }
143     _federateType = federateType;
144     return true;
145 }
146
147 const std::string&
148 HLAFederate::getFederateName() const
149 {
150     return _federateName;
151 }
152
153 bool
154 HLAFederate::setFederateName(const std::string& federateName)
155 {
156     if (_rtiFederate.valid()) {
157         SG_LOG(SG_NETWORK, SG_ALERT, "HLA: Ignoring HLAFederate parameter setting on already connected federate!");
158         return false;
159     }
160     _federateName = federateName;
161     return true;
162 }
163
164 bool
165 HLAFederate::connect(Version version, const std::list<std::string>& stringList)
166 {
167     _version = version;
168     _connectArguments = stringList;
169     return connect();
170 }
171
172 bool
173 HLAFederate::connect()
174 {
175     if (_rtiFederate.valid()) {
176         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Trying to connect to already connected federate!");
177         return false;
178     }
179
180     SGSharedPtr<RTIFederateFactoryRegistry> registry = RTIFederateFactoryRegistry::instance();
181     if (!registry) {
182         SG_LOG(SG_NETWORK, SG_ALERT, "HLA: RTIFederateFactoryRegistry is no longer available!");
183         return false;
184     }
185
186     switch (_version) {
187     case RTI13:
188         _rtiFederate = registry->create("RTI13", _connectArguments);
189         break;
190     case RTI1516:
191         _rtiFederate = registry->create("RTI1516", _connectArguments);
192         break;
193     case RTI1516E:
194         _rtiFederate = registry->create("RTI1516E", _connectArguments);
195         break;
196     default:
197         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Unknown rti version in connect!");
198     }
199     return _rtiFederate.valid();
200 }
201
202 bool
203 HLAFederate::disconnect()
204 {
205     if (!_rtiFederate.valid()) {
206         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
207         return false;
208     }
209     _rtiFederate = 0;
210     return true;
211 }
212
213 bool
214 HLAFederate::createFederationExecution(const std::string& federation, const std::string& objectModel)
215 {
216     if (!_rtiFederate.valid()) {
217         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
218         return false;
219     }
220
221     RTIFederate::FederationManagementResult createResult;
222     createResult = _rtiFederate->createFederationExecution(federation, objectModel);
223     if (createResult == RTIFederate::FederationManagementFatal)
224         return false;
225
226     _federationExecutionName = federation;
227     _federationObjectModel = objectModel;
228     return true;
229 }
230
231 bool
232 HLAFederate::destroyFederationExecution(const std::string& federation)
233 {
234     if (!_rtiFederate.valid()) {
235         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
236         return false;
237     }
238
239     RTIFederate::FederationManagementResult destroyResult;
240     destroyResult = _rtiFederate->destroyFederationExecution(federation);
241     if (destroyResult == RTIFederate::FederationManagementFatal)
242         return false;
243
244     return true;
245 }
246
247 bool
248 HLAFederate::createFederationExecution()
249 {
250     if (!_rtiFederate.valid()) {
251         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
252         return false;
253     }
254
255     RTIFederate::FederationManagementResult createResult;
256     createResult = _rtiFederate->createFederationExecution(_federationExecutionName, _federationObjectModel);
257     if (createResult != RTIFederate::FederationManagementSuccess)
258         return false;
259
260     return true;
261 }
262
263 bool
264 HLAFederate::destroyFederationExecution()
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(_federationExecutionName);
273     if (destroyResult != RTIFederate::FederationManagementSuccess)
274         return false;
275
276     return true;
277 }
278
279 bool
280 HLAFederate::join(const std::string& federateType, const std::string& federation)
281 {
282     if (!_rtiFederate.valid()) {
283         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
284         return false;
285     }
286
287     RTIFederate::FederationManagementResult joinResult;
288     joinResult = _rtiFederate->join(federateType, federation);
289     if (joinResult == RTIFederate::FederationManagementFatal)
290         return false;
291
292     return true;
293 }
294
295 bool
296 HLAFederate::join()
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, _federationExecutionName);
305     if (joinResult != RTIFederate::FederationManagementSuccess)
306         return false;
307
308     return true;
309 }
310
311 bool
312 HLAFederate::resign()
313 {
314     if (!_rtiFederate.valid()) {
315         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
316         return false;
317     }
318     return _rtiFederate->resign();
319 }
320
321 bool
322 HLAFederate::createJoinFederationExecution()
323 {
324     if (!_rtiFederate.valid()) {
325         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
326         return false;
327     }
328
329     for (;;) {
330         // Try to join.
331         RTIFederate::FederationManagementResult joinResult;
332         joinResult = _rtiFederate->join(_federateType, _federationExecutionName);
333         switch (joinResult) {
334         case RTIFederate::FederationManagementSuccess:
335             // Fast return on success
336             return true;
337         case RTIFederate::FederationManagementFatal:
338             // Abort on fatal errors
339             return false;
340         default:
341             break;
342         };
343
344         // If not already joinable, try to create the requested federation
345         RTIFederate::FederationManagementResult createResult;
346         createResult = _rtiFederate->createFederationExecution(_federationExecutionName, _federationObjectModel);
347         switch (createResult) {
348         case RTIFederate::FederationManagementFatal:
349             // Abort on fatal errors
350             return false;
351         default:
352             // Try again to join
353             break;
354         }
355     }
356 }
357
358 bool
359 HLAFederate::resignDestroyFederationExecution()
360 {
361     if (!_rtiFederate.valid()) {
362         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
363         return false;
364     }
365     
366     // Resign ourselves
367     bool success = _rtiFederate->resign();
368
369     // and try to destroy, non fatal if still some federates joined
370     if (_rtiFederate->destroyFederationExecution(_federationExecutionName) == RTIFederate::FederationManagementFatal)
371         success = false;
372
373     return success;
374 }
375
376 bool
377 HLAFederate::getTimeConstrained() const
378 {
379     return _timeConstrained;
380 }
381
382 bool
383 HLAFederate::setTimeConstrained(bool timeConstrained)
384 {
385     _timeConstrained = timeConstrained;
386
387     if (_rtiFederate.valid() && _rtiFederate->getJoined()) {
388         if (_timeConstrained && !_rtiFederate->getTimeConstrainedEnabled()) {
389             if (!enableTimeConstrained())
390                 return false;
391         } else if (!_timeConstrained && _rtiFederate->getTimeConstrainedEnabled()) {
392             if (!disableTimeConstrained())
393                 return false;
394         }
395
396     }
397
398     return true;
399 }
400
401 bool
402 HLAFederate::getTimeConstrainedByLocalClock() const
403 {
404     return _timeConstrainedByLocalClock;
405 }
406
407 bool
408 HLAFederate::setTimeConstrainedByLocalClock(bool timeConstrainedByLocalClock)
409 {
410     _timeConstrainedByLocalClock = timeConstrainedByLocalClock;
411
412     if (_rtiFederate.valid() && _rtiFederate->getJoined()) {
413         if (_timeConstrainedByLocalClock) {
414             if (!enableTimeConstrainedByLocalClock())
415                 return false;
416         }
417     }
418
419     return true;
420 }
421
422 bool
423 HLAFederate::getTimeRegulating() const
424 {
425     return _timeRegulating;
426 }
427
428 bool
429 HLAFederate::setTimeRegulating(bool timeRegulating)
430 {
431     _timeRegulating = timeRegulating;
432
433     if (_rtiFederate.valid() && _rtiFederate->getJoined()) {
434         if (_timeRegulating && !_rtiFederate->getTimeRegulationEnabled()) {
435             if (!enableTimeRegulation())
436                 return false;
437         } else if (!_timeRegulating && _rtiFederate->getTimeRegulationEnabled()) {
438             if (!disableTimeRegulation())
439                 return false;
440         }
441
442     }
443     return true;
444 }
445
446 bool
447 HLAFederate::setLeadTime(const SGTimeStamp& leadTime)
448 {
449     if (leadTime < SGTimeStamp::fromSec(0)) {
450         SG_LOG(SG_NETWORK, SG_WARN, "Ignoring negative lead time!");
451         return false;
452     }
453
454     _leadTime = leadTime;
455
456     if (_rtiFederate.valid() && _rtiFederate->getJoined()) {
457         if (!modifyLookahead(_leadTime + SGTimeStamp::fromSec(_timeIncrement.toSecs()*0.9))) {
458             SG_LOG(SG_NETWORK, SG_WARN, "Cannot modify lookahead!");
459             return false;
460         }
461     }
462
463     return true;
464 }
465
466 const SGTimeStamp&
467 HLAFederate::getLeadTime() const
468 {
469     return _leadTime;
470 }
471
472 bool
473 HLAFederate::setTimeIncrement(const SGTimeStamp& timeIncrement)
474 {
475     if (timeIncrement < SGTimeStamp::fromSec(0)) {
476         SG_LOG(SG_NETWORK, SG_WARN, "Ignoring negative time increment!");
477         return false;
478     }
479
480     _timeIncrement = timeIncrement;
481
482     if (_rtiFederate.valid() && _rtiFederate->getJoined()) {
483         if (!modifyLookahead(_leadTime + SGTimeStamp::fromSec(_timeIncrement.toSecs()*0.9))) {
484             SG_LOG(SG_NETWORK, SG_WARN, "Cannot modify lookahead!");
485             return false;
486         }
487     }
488
489     return true;
490 }
491
492 const SGTimeStamp&
493 HLAFederate::getTimeIncrement() const
494 {
495     return _timeIncrement;
496 }
497
498 bool
499 HLAFederate::enableTimeConstrained()
500 {
501     if (!_rtiFederate.valid()) {
502         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
503         return false;
504     }
505
506     if (!_rtiFederate->enableTimeConstrained()) {
507         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Could not enable time constrained!");
508         return false;
509     }
510
511     while (!_rtiFederate->getTimeConstrainedEnabled()) {
512         _rtiFederate->processMessage();
513     }
514
515     return true;
516 }
517
518 bool
519 HLAFederate::disableTimeConstrained()
520 {
521     if (!_rtiFederate.valid()) {
522         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
523         return false;
524     }
525     return _rtiFederate->disableTimeConstrained();
526 }
527
528 bool
529 HLAFederate::enableTimeConstrainedByLocalClock()
530 {
531     // Compute the time offset from the system time to the simulation time
532     SGTimeStamp federateTime;
533     if (!queryFederateTime(federateTime)) {
534         SG_LOG(SG_NETWORK, SG_WARN, "Cannot get federate time!");
535         return false;
536     }
537     _localClockOffset = SGTimeStamp::now() - federateTime;
538     return true;
539 }
540
541 bool
542 HLAFederate::enableTimeRegulation(const SGTimeStamp& lookahead)
543 {
544     if (!_rtiFederate.valid()) {
545         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
546         return false;
547     }
548
549     if (!_rtiFederate->enableTimeRegulation(lookahead)) {
550         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Could not enable time regulation!");
551         return false;
552     }
553
554     while (!_rtiFederate->getTimeRegulationEnabled()) {
555         _rtiFederate->processMessage();
556     }
557
558     return true;
559 }
560
561 bool
562 HLAFederate::enableTimeRegulation()
563 {
564     if (!enableTimeRegulation(SGTimeStamp::fromSec(0))) {
565         SG_LOG(SG_NETWORK, SG_WARN, "Cannot enable time regulation!");
566         return false;
567     }
568     if (!modifyLookahead(_leadTime + SGTimeStamp::fromSec(_timeIncrement.toSecs()*0.9))) {
569         SG_LOG(SG_NETWORK, SG_WARN, "Cannot modify lookahead!");
570         return false;
571     }
572     return true;
573 }
574
575 bool
576 HLAFederate::disableTimeRegulation()
577 {
578     if (!_rtiFederate.valid()) {
579         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
580         return false;
581     }
582     return _rtiFederate->disableTimeRegulation();
583 }
584
585 bool
586 HLAFederate::modifyLookahead(const SGTimeStamp& timeStamp)
587 {
588     if (!_rtiFederate.valid()) {
589         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
590         return false;
591     }
592     return _rtiFederate->modifyLookahead(timeStamp);
593 }
594
595 bool
596 HLAFederate::timeAdvanceBy(const SGTimeStamp& timeIncrement)
597 {
598     if (!_rtiFederate.valid()) {
599         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
600         return false;
601     }
602
603     SGTimeStamp timeStamp;
604     if (!_rtiFederate->queryFederateTime(timeStamp)) {
605         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Could not query federate time!");
606         return false;
607     }
608
609     if (!_rtiFederate->timeAdvanceRequest(timeStamp + timeIncrement)) {
610         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Time advance request failed!");
611         return false;
612     }
613
614     return processMessages();
615 }
616
617 bool
618 HLAFederate::timeAdvance(const SGTimeStamp& timeStamp)
619 {
620     if (!_rtiFederate.valid()) {
621         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
622         return false;
623     }
624
625     if (!_rtiFederate->timeAdvanceRequest(timeStamp)) {
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::timeAdvanceAvailable()
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->queryGALT(timeStamp)) {
643         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Could not query GALT!");
644         return false;
645     }
646
647     if (!_rtiFederate->timeAdvanceRequestAvailable(timeStamp)) {
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::queryFederateTime(SGTimeStamp& timeStamp)
657 {
658     if (!_rtiFederate.valid()) {
659         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
660         return false;
661     }
662     return _rtiFederate->queryFederateTime(timeStamp);
663 }
664
665 bool
666 HLAFederate::queryLookahead(SGTimeStamp& timeStamp)
667 {
668     if (!_rtiFederate.valid()) {
669         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
670         return false;
671     }
672     return _rtiFederate->queryLookahead(timeStamp);
673 }
674
675 bool
676 HLAFederate::processMessage()
677 {
678     if (!_rtiFederate.valid()) {
679         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
680         return false;
681     }
682     return _rtiFederate->processMessage();
683 }
684
685 bool
686 HLAFederate::processMessage(const SGTimeStamp& timeout)
687 {
688     if (!_rtiFederate.valid()) {
689         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
690         return false;
691     }
692     return _rtiFederate->processMessages(timeout.toSecs(), 0);
693 }
694
695 bool
696 HLAFederate::processMessages()
697 {
698     if (!_rtiFederate.valid()) {
699         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
700         return false;
701     }
702
703     while (_rtiFederate->getTimeAdvancePending()) {
704         _rtiFederate->processMessage();
705     }
706
707     if (_timeConstrainedByLocalClock) {
708         SGTimeStamp federateTime;
709         if (!_rtiFederate->queryFederateTime(federateTime)) {
710             SG_LOG(SG_NETWORK, SG_WARN, "HLA: Error querying federate time!");
711             return false;
712         }
713         SGTimeStamp systemTime = federateTime + _localClockOffset;
714         for (;;) {
715             double rest = (systemTime - SGTimeStamp::now()).toSecs();
716             if (rest < 0)
717                 break;
718             _rtiFederate->processMessages(rest, rest);
719         }
720     }
721     
722     // Now flush just what is left
723     while (_rtiFederate->processMessages(0, 0));
724
725     return true;
726 }
727
728 bool
729 HLAFederate::tick(const double& minimum, const double& maximum)
730 {
731     if (!_rtiFederate.valid()) {
732         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
733         return false;
734     }
735     return _rtiFederate->processMessages(minimum, maximum);
736 }
737
738 bool
739 HLAFederate::readObjectModelTemplate(const std::string& objectModel,
740                                      HLAFederate::ObjectModelFactory& objectModelFactory)
741 {
742     if (!_rtiFederate.valid()) {
743         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
744         return false;
745     }
746
747     // The XML version of the federate object model.
748     // This one covers the generic attributes, parameters and data types.
749     HLAOMTXmlVisitor omtXmlVisitor;
750     try {
751         readXML(objectModel, omtXmlVisitor);
752     } catch (const sg_throwable& e) {
753         SG_LOG(SG_IO, SG_ALERT, "Could not open HLA XML object model file: "
754                << e.getMessage());
755         return false;
756     } catch (...) {
757         SG_LOG(SG_IO, SG_ALERT, "Could not open HLA XML object model file");
758         return false;
759     }
760
761     unsigned numObjectClasses = omtXmlVisitor.getNumObjectClasses();
762     for (unsigned i = 0; i < numObjectClasses; ++i) {
763         const HLAOMTXmlVisitor::ObjectClass* objectClass = omtXmlVisitor.getObjectClass(i);
764         std::string objectClassName = objectClass->getName();
765
766         SGSharedPtr<HLAObjectClass> hlaObjectClass = objectModelFactory.createObjectClass(objectClassName, *this);
767         if (!hlaObjectClass.valid()) {
768             SG_LOG(SG_IO, SG_INFO, "Ignoring object class \"" << objectClassName << "\".");
769             continue;
770         }
771
772         bool publish = objectModelFactory.publishObjectClass(objectClassName, objectClass->getSharing());
773         bool subscribe = objectModelFactory.subscribeObjectClass(objectClassName, objectClass->getSharing());
774
775         std::set<unsigned> subscriptions;
776         std::set<unsigned> publications;
777
778         // process the attributes
779         for (unsigned j = 0; j < objectClass->getNumAttributes(); ++j) {
780             const simgear::HLAOMTXmlVisitor::Attribute* attribute;
781             attribute = objectClass->getAttribute(j);
782
783             std::string attributeName = attribute->getName();
784             unsigned index = hlaObjectClass->getAttributeIndex(attributeName);
785
786             if (index == ~0u) {
787                 SG_LOG(SG_IO, SG_WARN, "RTI does not know the \"" << attributeName << "\" attribute!");
788                 continue;
789             }
790
791             SGSharedPtr<HLADataType> dataType;
792             dataType = omtXmlVisitor.getAttributeDataType(objectClassName, attributeName);
793             if (!dataType.valid()) {
794                 SG_LOG(SG_IO, SG_WARN, "Could not find data type for attribute \""
795                        << attributeName << "\" in object class \"" << objectClassName << "\"!");
796             }
797             hlaObjectClass->setAttributeDataType(index, dataType);
798
799             HLAUpdateType updateType = HLAUndefinedUpdate;
800             if (attribute->_updateType == "Periodic")
801                 updateType = HLAPeriodicUpdate;
802             else if (attribute->_updateType == "Static")
803                 updateType = HLAStaticUpdate;
804             else if (attribute->_updateType == "Conditional")
805                 updateType = HLAConditionalUpdate;
806             hlaObjectClass->setAttributeUpdateType(index, updateType);
807
808             if (subscribe && objectModelFactory.subscribeAttribute(objectClassName, attributeName, attribute->_sharing))
809                 subscriptions.insert(index);
810             if (publish && objectModelFactory.publishAttribute(objectClassName, attributeName, attribute->_sharing))
811                 publications.insert(index);
812         }
813
814         if (publish)
815             hlaObjectClass->publish(publications);
816         if (subscribe)
817             hlaObjectClass->subscribe(subscriptions, true);
818
819         _objectClassMap[objectClassName] = hlaObjectClass;
820     }
821
822     return true;
823 }
824
825 bool
826 HLAFederate::readRTI13ObjectModelTemplate(const std::string& objectModel)
827 {
828     SG_LOG(SG_IO, SG_ALERT, "HLA version RTI13 not yet(!?) supported.");
829     return false;
830 }
831
832 bool
833 HLAFederate::readRTI1516ObjectModelTemplate(const std::string& objectModel)
834 {
835     ObjectModelFactory objectModelFactory;
836     return readObjectModelTemplate(objectModel, objectModelFactory);
837 }
838
839 bool
840 HLAFederate::readRTI1516EObjectModelTemplate(const std::string& objectModel)
841 {
842     SG_LOG(SG_IO, SG_ALERT, "HLA version RTI1516E not yet(!?) supported.");
843     return false;
844 }
845
846 HLAObjectClass*
847 HLAFederate::getObjectClass(const std::string& name)
848 {
849     ObjectClassMap::const_iterator i = _objectClassMap.find(name);
850     if (i == _objectClassMap.end())
851         return 0;
852     return i->second.get();
853 }
854
855 const HLAObjectClass*
856 HLAFederate::getObjectClass(const std::string& name) const
857 {
858     ObjectClassMap::const_iterator i = _objectClassMap.find(name);
859     if (i == _objectClassMap.end())
860         return 0;
861     return i->second.get();
862 }
863
864 HLAObjectClass*
865 HLAFederate::createObjectClass(const std::string& name)
866 {
867     return new HLAObjectClass(name, *this);
868 }
869
870 HLAInteractionClass*
871 HLAFederate::getInteractionClass(const std::string& name)
872 {
873     InteractionClassMap::const_iterator i = _interactionClassMap.find(name);
874     if (i == _interactionClassMap.end())
875         return 0;
876     return i->second.get();
877 }
878
879 const HLAInteractionClass*
880 HLAFederate::getInteractionClass(const std::string& name) const
881 {
882     InteractionClassMap::const_iterator i = _interactionClassMap.find(name);
883     if (i == _interactionClassMap.end())
884         return 0;
885     return i->second.get();
886 }
887
888 void
889 HLAFederate::setDone(bool done)
890 {
891     _done = done;
892 }
893
894 bool
895 HLAFederate::getDone() const
896 {
897     return _done;
898 }
899
900 bool
901 HLAFederate::readObjectModel()
902 {
903     /// Currently empty, but is called at the right time so that
904     /// the object model is present when it is needed
905     // switch (getVersion()) {
906     // case RTI13:
907     //     return readRTI13ObjectModelTemplate(getFederationObjectModel());
908     // case RTI1516:
909     //     return readRTI1516ObjectModelTemplate(getFederationObjectModel());
910     // case RTI1516E:
911     //     return readRTI1516EObjectModelTemplate(getFederationObjectModel());
912     // }
913     return true;
914 }
915
916 bool
917 HLAFederate::subscribe()
918 {
919     /// Currently empty, but is called at the right time
920     return true;
921 }
922
923 bool
924 HLAFederate::publish()
925 {
926     /// Currently empty, but is called at the right time
927     return true;
928 }
929
930 bool
931 HLAFederate::init()
932 {
933     // We need to talk to the rti
934     if (!connect())
935         return false;
936     // Join ...
937     if (_createFederationExecution) {
938         if (!createJoinFederationExecution())
939             return false;
940     } else {
941         if (!join())
942             return false;
943     }
944     // Read the xml file containing the object model
945     if (!readObjectModel()) {
946         shutdown();
947         return false;
948     }
949     // start being time constrained if required
950     if (_timeConstrained) {
951         if (!enableTimeConstrained()) {
952             shutdown();
953             return false;
954         }
955     }
956     // Now that we are potentially time constrained, we can subscribe.
957     // This is to make sure we do not get any time stamped message
958     // converted to a non time stamped message by the rti.
959     if (!subscribe()) {
960         shutdown();
961         return false;
962     }
963     // Before we publish anything start getting regulating if required
964     if (_timeRegulating) {
965         if (!enableTimeRegulation()) {
966             shutdown();
967             return false;
968         }
969     }
970     // Note that starting from here, we need to be careful with things
971     // requireing unbounded time. The rest of the federation might wait
972     // for us to finish!
973     
974     // Compute the time offset from the system time to the simulation time
975     if (_timeConstrainedByLocalClock) {
976         if (!enableTimeConstrainedByLocalClock()) {
977             SG_LOG(SG_NETWORK, SG_WARN, "Cannot enable time constrained by local clock!");
978             shutdown();
979             return false;
980         }
981     }
982     
983     // Publish what we want to write
984     if (!publish()) {
985         shutdown();
986         return false;
987     }
988     
989     return true;
990 }
991
992 bool
993 HLAFederate::update()
994 {
995     return timeAdvanceBy(_timeIncrement);
996 }
997
998 bool
999 HLAFederate::shutdown()
1000 {
1001     // On shutdown, just try all in order.
1002     // If something goes wrong, continue and try to get out here as good as possible.
1003     bool ret = true;
1004     
1005     if (_createFederationExecution) {
1006         if (!resignDestroyFederationExecution())
1007             ret = false;
1008     } else {
1009         if (!resign())
1010             ret = false;
1011     }
1012     
1013     if (!disconnect())
1014         ret = false;
1015     
1016     return ret;
1017 }
1018
1019 bool
1020 HLAFederate::exec()
1021 {
1022     if (!init())
1023         return false;
1024     
1025     while (!getDone()) {
1026         if (!update()) {
1027             shutdown();
1028             return false;
1029         }
1030     }
1031     
1032     if (!shutdown())
1033         return false;
1034     
1035     return true;
1036 }
1037
1038 } // namespace simgear