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