]> git.mxchange.org Git - simgear.git/blob - simgear/hla/HLAFederate.cxx
hla: for rti13 queue all callbacks.
[simgear.git] / simgear / hla / HLAFederate.cxx
1 // Copyright (C) 2009 - 2011  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 HLAObjectClass*
835 HLAFederate::getObjectClass(const std::string& name)
836 {
837     ObjectClassMap::const_iterator i = _objectClassMap.find(name);
838     if (i == _objectClassMap.end())
839         return 0;
840     return i->second.get();
841 }
842
843 const HLAObjectClass*
844 HLAFederate::getObjectClass(const std::string& name) const
845 {
846     ObjectClassMap::const_iterator i = _objectClassMap.find(name);
847     if (i == _objectClassMap.end())
848         return 0;
849     return i->second.get();
850 }
851
852 HLAInteractionClass*
853 HLAFederate::getInteractionClass(const std::string& name)
854 {
855     InteractionClassMap::const_iterator i = _interactionClassMap.find(name);
856     if (i == _interactionClassMap.end())
857         return 0;
858     return i->second.get();
859 }
860
861 const HLAInteractionClass*
862 HLAFederate::getInteractionClass(const std::string& name) const
863 {
864     InteractionClassMap::const_iterator i = _interactionClassMap.find(name);
865     if (i == _interactionClassMap.end())
866         return 0;
867     return i->second.get();
868 }
869
870 void
871 HLAFederate::setDone(bool done)
872 {
873     _done = done;
874 }
875
876 bool
877 HLAFederate::getDone() const
878 {
879     return _done;
880 }
881
882 bool
883 HLAFederate::readObjectModel()
884 {
885     /// Currently empty, but is called at the right time so that
886     /// the object model is present when it is needed
887     return true;
888 }
889
890 bool
891 HLAFederate::subscribe()
892 {
893     /// Currently empty, but is called at the right time
894     return true;
895 }
896
897 bool
898 HLAFederate::publish()
899 {
900     /// Currently empty, but is called at the right time
901     return true;
902 }
903
904 bool
905 HLAFederate::init()
906 {
907     // We need to talk to the rti
908     if (!connect())
909         return false;
910     // Join ...
911     if (_createFederationExecution) {
912         if (!createJoinFederationExecution())
913             return false;
914     } else {
915         if (!join())
916             return false;
917     }
918     // Read the xml file containing the object model
919     if (!readObjectModel()) {
920         shutdown();
921         return false;
922     }
923     // start being time constrained if required
924     if (_timeConstrained) {
925         if (!enableTimeConstrained()) {
926             shutdown();
927             return false;
928         }
929     }
930     // Now that we are potentially time constrained, we can subscribe.
931     // This is to make sure we do not get any time stamped message
932     // converted to a non time stamped message by the rti.
933     if (!subscribe()) {
934         shutdown();
935         return false;
936     }
937     // Before we publish anything start getting regulating if required
938     if (_timeRegulating) {
939         if (!enableTimeRegulation()) {
940             shutdown();
941             return false;
942         }
943     }
944     // Note that starting from here, we need to be careful with things
945     // requireing unbounded time. The rest of the federation might wait
946     // for us to finish!
947     
948     // Compute the time offset from the system time to the simulation time
949     if (_timeConstrainedByLocalClock) {
950         if (!enableTimeConstrainedByLocalClock()) {
951             SG_LOG(SG_NETWORK, SG_WARN, "Cannot enable time constrained by local clock!");
952             shutdown();
953             return false;
954         }
955     }
956     
957     // Publish what we want to write
958     if (!publish()) {
959         shutdown();
960         return false;
961     }
962     
963     return true;
964 }
965
966 bool
967 HLAFederate::update()
968 {
969     return timeAdvanceBy(_timeIncrement);
970 }
971
972 bool
973 HLAFederate::shutdown()
974 {
975     // On shutdown, just try all in order.
976     // If something goes wrong, continue and try to get out here as good as possible.
977     bool ret = true;
978     
979     if (_createFederationExecution) {
980         if (!resignDestroyFederationExecution())
981             ret = false;
982     } else {
983         if (!resign())
984             ret = false;
985     }
986     
987     if (!disconnect())
988         ret = false;
989     
990     return ret;
991 }
992
993 bool
994 HLAFederate::exec()
995 {
996     if (!init())
997         return false;
998     
999     while (!getDone()) {
1000         if (!update()) {
1001             shutdown();
1002             return false;
1003         }
1004     }
1005     
1006     if (!shutdown())
1007         return false;
1008     
1009     return true;
1010 }
1011
1012 } // namespace simgear