]> git.mxchange.org Git - simgear.git/blob - simgear/hla/HLAFederate.cxx
fa1cc576bc93be63b95bc6994ad7b224c2f4ac82
[simgear.git] / simgear / hla / HLAFederate.cxx
1 // Copyright (C) 2009 - 2010  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 {
32 }
33
34 HLAFederate::~HLAFederate()
35 {
36 }
37
38 HLAFederate::Version
39 HLAFederate::getVersion() const
40 {
41     return _version;
42 }
43
44 bool
45 HLAFederate::setVersion(HLAFederate::Version version)
46 {
47     if (_rtiFederate.valid()) {
48         SG_LOG(SG_NETWORK, SG_ALERT, "HLA: Ignoring HLAFederate parameter setting on already connected federate!");
49         return false;
50     }
51     _version = version;
52     return true;
53 }
54
55 const std::list<std::string>&
56 HLAFederate::getConnectArguments() const
57 {
58     return _connectArguments;
59 }
60
61 bool
62 HLAFederate::setConnectArguments(const std::list<std::string>& connectArguments)
63 {
64     if (_rtiFederate.valid()) {
65         SG_LOG(SG_NETWORK, SG_ALERT, "HLA: Ignoring HLAFederate parameter setting on already connected federate!");
66         return false;
67     }
68     _connectArguments = connectArguments;
69     return true;
70 }
71
72 const std::string&
73 HLAFederate::getFederationExecutionName() const
74 {
75     return _federationExecutionName;
76 }
77
78 bool
79 HLAFederate::setFederationExecutionName(const std::string& federationExecutionName)
80 {
81     if (_rtiFederate.valid()) {
82         SG_LOG(SG_NETWORK, SG_ALERT, "HLA: Ignoring HLAFederate parameter setting on already connected federate!");
83         return false;
84     }
85     _federationExecutionName = federationExecutionName;
86     return true;
87 }
88
89 const std::string&
90 HLAFederate::getFederationObjectModel() const
91 {
92     return _federationObjectModel;
93 }
94
95 bool
96 HLAFederate::setFederationObjectModel(const std::string& federationObjectModel)
97 {
98     if (_rtiFederate.valid()) {
99         SG_LOG(SG_NETWORK, SG_ALERT, "HLA: Ignoring HLAFederate parameter setting on already connected federate!");
100         return false;
101     }
102     _federationObjectModel = federationObjectModel;
103     return true;
104 }
105
106 const std::string&
107 HLAFederate::getFederateType() const
108 {
109     return _federateType;
110 }
111
112 bool
113 HLAFederate::setFederateType(const std::string& federateType)
114 {
115     if (_rtiFederate.valid()) {
116         SG_LOG(SG_NETWORK, SG_ALERT, "HLA: Ignoring HLAFederate parameter setting on already connected federate!");
117         return false;
118     }
119     _federateType = federateType;
120     return true;
121 }
122
123 const std::string&
124 HLAFederate::getFederateName() const
125 {
126     return _federateName;
127 }
128
129 bool
130 HLAFederate::setFederateName(const std::string& federateName)
131 {
132     if (_rtiFederate.valid()) {
133         SG_LOG(SG_NETWORK, SG_ALERT, "HLA: Ignoring HLAFederate parameter setting on already connected federate!");
134         return false;
135     }
136     _federateName = federateName;
137     return true;
138 }
139
140 bool
141 HLAFederate::connect(Version version, const std::list<std::string>& stringList)
142 {
143     if (_rtiFederate.valid()) {
144         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Trying to connect to already connected federate!");
145         return false;
146     }
147     switch (version) {
148     case RTI13:
149         _rtiFederate = new RTI13Federate(stringList);
150         _version = version;
151         _connectArguments = stringList;
152         break;
153     case RTI1516:
154         SG_LOG(SG_IO, SG_ALERT, "HLA version RTI1516 not yet(!?) supported.");
155         // _rtiFederate = new RTI1516Federate(stringList);
156         break;
157     case RTI1516E:
158         SG_LOG(SG_IO, SG_ALERT, "HLA version RTI1516E not yet(!?) supported.");
159         // _rtiFederate = new RTI1516eFederate(stringList);
160         break;
161     default:
162         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Unknown rti version in connect!");
163     }
164     return _rtiFederate.valid();
165 }
166
167 bool
168 HLAFederate::connect()
169 {
170     if (_rtiFederate.valid()) {
171         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Trying to connect to already connected federate!");
172         return false;
173     }
174     switch (_version) {
175     case RTI13:
176         _rtiFederate = new RTI13Federate(_connectArguments);
177         break;
178     case RTI1516:
179         SG_LOG(SG_IO, SG_ALERT, "HLA version RTI1516 not yet(!?) supported.");
180         // _rtiFederate = new RTI1516Federate(_connectArguments);
181         break;
182     case RTI1516E:
183         SG_LOG(SG_IO, SG_ALERT, "HLA version RTI1516E not yet(!?) supported.");
184         // _rtiFederate = new RTI1516eFederate(_connectArguments);
185         break;
186     default:
187         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Unknown rti version in connect!");
188     }
189     return _rtiFederate.valid();
190 }
191
192 bool
193 HLAFederate::disconnect()
194 {
195     if (!_rtiFederate.valid()) {
196         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
197         return false;
198     }
199     _rtiFederate = 0;
200     return true;
201 }
202
203 bool
204 HLAFederate::createFederationExecution(const std::string& federation, const std::string& objectModel)
205 {
206     if (!_rtiFederate.valid()) {
207         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
208         return false;
209     }
210
211     RTIFederate::FederationManagementResult createResult;
212     createResult = _rtiFederate->createFederationExecution(federation, objectModel);
213     if (createResult == RTIFederate::FederationManagementFatal)
214         return false;
215
216     _federationExecutionName = federation;
217     _federationObjectModel = objectModel;
218     return true;
219 }
220
221 bool
222 HLAFederate::destroyFederationExecution(const std::string& federation)
223 {
224     if (!_rtiFederate.valid()) {
225         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
226         return false;
227     }
228
229     RTIFederate::FederationManagementResult destroyResult;
230     destroyResult = _rtiFederate->destroyFederationExecution(federation);
231     if (destroyResult == RTIFederate::FederationManagementFatal)
232         return false;
233
234     return true;
235 }
236
237 bool
238 HLAFederate::createFederationExecution()
239 {
240     if (!_rtiFederate.valid()) {
241         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
242         return false;
243     }
244
245     RTIFederate::FederationManagementResult createResult;
246     createResult = _rtiFederate->createFederationExecution(_federationExecutionName, _federationObjectModel);
247     if (createResult != RTIFederate::FederationManagementSuccess)
248         return false;
249
250     return true;
251 }
252
253 bool
254 HLAFederate::destroyFederationExecution()
255 {
256     if (!_rtiFederate.valid()) {
257         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
258         return false;
259     }
260
261     RTIFederate::FederationManagementResult destroyResult;
262     destroyResult = _rtiFederate->destroyFederationExecution(_federationExecutionName);
263     if (destroyResult != RTIFederate::FederationManagementSuccess)
264         return false;
265
266     return true;
267 }
268
269 bool
270 HLAFederate::join(const std::string& federateType, const std::string& federation)
271 {
272     if (!_rtiFederate.valid()) {
273         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
274         return false;
275     }
276
277     RTIFederate::FederationManagementResult joinResult;
278     joinResult = _rtiFederate->join(federateType, federation);
279     if (joinResult == RTIFederate::FederationManagementFatal)
280         return false;
281
282     return true;
283 }
284
285 bool
286 HLAFederate::join()
287 {
288     if (!_rtiFederate.valid()) {
289         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
290         return false;
291     }
292
293     RTIFederate::FederationManagementResult joinResult;
294     joinResult = _rtiFederate->join(_federateType, _federationExecutionName);
295     if (joinResult != RTIFederate::FederationManagementSuccess)
296         return false;
297
298     return true;
299 }
300
301 bool
302 HLAFederate::resign()
303 {
304     if (!_rtiFederate.valid()) {
305         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
306         return false;
307     }
308     return _rtiFederate->resign();
309 }
310
311 bool
312 HLAFederate::createJoinFederationExecution()
313 {
314     if (!_rtiFederate.valid()) {
315         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
316         return false;
317     }
318
319     for (;;) {
320         // Try to join.
321         RTIFederate::FederationManagementResult joinResult;
322         joinResult = _rtiFederate->join(_federateType, _federationExecutionName);
323         switch (joinResult) {
324         case RTIFederate::FederationManagementSuccess:
325             // Fast return on success
326             return true;
327         case RTIFederate::FederationManagementFatal:
328             // Abort on fatal errors
329             return false;
330         default:
331             break;
332         };
333
334         // If not already joinable, try to create the requested federation
335         RTIFederate::FederationManagementResult createResult;
336         createResult = _rtiFederate->createFederationExecution(_federationExecutionName, _federationObjectModel);
337         switch (createResult) {
338         case RTIFederate::FederationManagementFatal:
339             // Abort on fatal errors
340             return false;
341         default:
342             // Try again to join
343             break;
344         }
345     }
346 }
347
348 bool
349 HLAFederate::resignDestroyFederationExecution()
350 {
351     if (!_rtiFederate.valid()) {
352         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
353         return false;
354     }
355     
356     // Resign ourselves
357     bool success = _rtiFederate->resign();
358
359     // and try to destroy, non fatal if still some federates joined
360     if (_rtiFederate->destroyFederationExecution(_federationExecutionName) == RTIFederate::FederationManagementFatal)
361         success = false;
362
363     return success;
364 }
365
366 bool
367 HLAFederate::enableTimeConstrained()
368 {
369     if (!_rtiFederate.valid()) {
370         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
371         return false;
372     }
373     return _rtiFederate->enableTimeConstrained();
374 }
375
376 bool
377 HLAFederate::disableTimeConstrained()
378 {
379     if (!_rtiFederate.valid()) {
380         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
381         return false;
382     }
383     return _rtiFederate->disableTimeConstrained();
384 }
385
386 bool
387 HLAFederate::enableTimeRegulation(const SGTimeStamp& lookahead)
388 {
389     if (!_rtiFederate.valid()) {
390         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
391         return false;
392     }
393     return _rtiFederate->enableTimeRegulation(lookahead);
394 }
395
396 bool
397 HLAFederate::disableTimeRegulation()
398 {
399     if (!_rtiFederate.valid()) {
400         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
401         return false;
402     }
403     return _rtiFederate->disableTimeRegulation();
404 }
405
406 bool
407 HLAFederate::timeAdvanceRequestBy(const SGTimeStamp& dt)
408 {
409     if (!_rtiFederate.valid()) {
410         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
411         return false;
412     }
413     return _rtiFederate->timeAdvanceRequestBy(dt);
414 }
415
416 bool
417 HLAFederate::timeAdvanceRequest(const SGTimeStamp& dt)
418 {
419     if (!_rtiFederate.valid()) {
420         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
421         return false;
422     }
423     return _rtiFederate->timeAdvanceRequest(dt);
424 }
425
426 bool
427 HLAFederate::queryFederateTime(SGTimeStamp& timeStamp)
428 {
429     if (!_rtiFederate.valid()) {
430         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
431         return false;
432     }
433     return _rtiFederate->queryFederateTime(timeStamp);
434 }
435
436 bool
437 HLAFederate::modifyLookahead(const SGTimeStamp& timeStamp)
438 {
439     if (!_rtiFederate.valid()) {
440         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
441         return false;
442     }
443     return _rtiFederate->modifyLookahead(timeStamp);
444 }
445
446 bool
447 HLAFederate::queryLookahead(SGTimeStamp& timeStamp)
448 {
449     if (!_rtiFederate.valid()) {
450         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
451         return false;
452     }
453     return _rtiFederate->queryLookahead(timeStamp);
454 }
455
456 bool
457 HLAFederate::tick()
458 {
459     if (!_rtiFederate.valid()) {
460         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
461         return false;
462     }
463     return _rtiFederate->tick();
464 }
465
466 bool
467 HLAFederate::tick(const double& minimum, const double& maximum)
468 {
469     if (!_rtiFederate.valid()) {
470         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
471         return false;
472     }
473     return _rtiFederate->tick(minimum, maximum);
474 }
475
476 bool
477 HLAFederate::readObjectModelTemplate(const std::string& objectModel,
478                                      HLAFederate::ObjectModelFactory& objectModelFactory)
479 {
480     if (!_rtiFederate.valid()) {
481         SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!");
482         return false;
483     }
484
485     // The XML version of the federate object model.
486     // This one covers the generic attributes, parameters and data types.
487     HLAOMTXmlVisitor omtXmlVisitor;
488     try {
489         readXML(objectModel, omtXmlVisitor);
490     } catch (const sg_throwable& e) {
491         SG_LOG(SG_IO, SG_ALERT, "Could not open HLA XML object model file: "
492                << e.getMessage());
493         return false;
494     } catch (...) {
495         SG_LOG(SG_IO, SG_ALERT, "Could not open HLA XML object model file");
496         return false;
497     }
498
499     unsigned numObjectClasses = omtXmlVisitor.getNumObjectClasses();
500     for (unsigned i = 0; i < numObjectClasses; ++i) {
501         const HLAOMTXmlVisitor::ObjectClass* objectClass = omtXmlVisitor.getObjectClass(i);
502         std::string objectClassName = objectClass->getName();
503
504         SGSharedPtr<HLAObjectClass> hlaObjectClass = objectModelFactory.createObjectClass(objectClassName, *this);
505         if (!hlaObjectClass.valid()) {
506             SG_LOG(SG_IO, SG_INFO, "Ignoring object class \"" << objectClassName << "\".");
507             continue;
508         }
509
510         bool publish = objectModelFactory.publishObjectClass(objectClassName, objectClass->getSharing());
511         bool subscribe = objectModelFactory.subscribeObjectClass(objectClassName, objectClass->getSharing());
512
513         std::set<unsigned> subscriptions;
514         std::set<unsigned> publications;
515
516         // process the attributes
517         for (unsigned j = 0; j < objectClass->getNumAttributes(); ++j) {
518             const simgear::HLAOMTXmlVisitor::Attribute* attribute;
519             attribute = objectClass->getAttribute(j);
520
521             std::string attributeName = attribute->getName();
522             unsigned index = hlaObjectClass->getAttributeIndex(attributeName);
523
524             if (index == ~0u) {
525                 SG_LOG(SG_IO, SG_WARN, "RTI does not know the \"" << attributeName << "\" attribute!");
526                 continue;
527             }
528
529             SGSharedPtr<HLADataType> dataType;
530             dataType = omtXmlVisitor.getAttributeDataType(objectClassName, attributeName);
531             if (!dataType.valid()) {
532                 SG_LOG(SG_IO, SG_WARN, "Could not find data type for attribute \""
533                        << attributeName << "\" in object class \"" << objectClassName << "\"!");
534             }
535             hlaObjectClass->setAttributeDataType(index, dataType);
536
537             HLAUpdateType updateType = HLAUndefinedUpdate;
538             if (attribute->_updateType == "Periodic")
539                 updateType = HLAPeriodicUpdate;
540             else if (attribute->_updateType == "Static")
541                 updateType = HLAStaticUpdate;
542             else if (attribute->_updateType == "Conditional")
543                 updateType = HLAConditionalUpdate;
544             hlaObjectClass->setAttributeUpdateType(index, updateType);
545
546             if (subscribe && objectModelFactory.subscribeAttribute(objectClassName, attributeName, attribute->_sharing))
547                 subscriptions.insert(index);
548             if (publish && objectModelFactory.publishAttribute(objectClassName, attributeName, attribute->_sharing))
549                 publications.insert(index);
550         }
551
552         if (publish)
553             hlaObjectClass->publish(publications);
554         if (subscribe)
555             hlaObjectClass->subscribe(subscriptions, true);
556
557         _objectClassMap[objectClassName] = hlaObjectClass;
558     }
559
560     return true;
561 }
562
563 HLAObjectClass*
564 HLAFederate::getObjectClass(const std::string& name)
565 {
566     ObjectClassMap::const_iterator i = _objectClassMap.find(name);
567     if (i == _objectClassMap.end())
568         return 0;
569     return i->second.get();
570 }
571
572 const HLAObjectClass*
573 HLAFederate::getObjectClass(const std::string& name) const
574 {
575     ObjectClassMap::const_iterator i = _objectClassMap.find(name);
576     if (i == _objectClassMap.end())
577         return 0;
578     return i->second.get();
579 }
580
581 HLAInteractionClass*
582 HLAFederate::getInteractionClass(const std::string& name)
583 {
584     InteractionClassMap::const_iterator i = _interactionClassMap.find(name);
585     if (i == _interactionClassMap.end())
586         return 0;
587     return i->second.get();
588 }
589
590 const HLAInteractionClass*
591 HLAFederate::getInteractionClass(const std::string& name) const
592 {
593     InteractionClassMap::const_iterator i = _interactionClassMap.find(name);
594     if (i == _interactionClassMap.end())
595         return 0;
596     return i->second.get();
597 }
598
599 } // namespace simgear