1 // Copyright (C) 2009 - 2012 Mathias Froehlich - Mathias.Froehlich@web.de
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.
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.
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.
19 # include <simgear_config.h>
22 #include <simgear/compiler.h>
24 #include "HLAObjectInstance.hxx"
27 #include "simgear/debug/logstream.hxx"
28 #include "HLAArrayDataElement.hxx"
29 #include "HLABasicDataElement.hxx"
30 #include "HLADataElement.hxx"
31 #include "HLAEnumeratedDataElement.hxx"
32 #include "HLAFederate.hxx"
33 #include "HLAFixedRecordDataElement.hxx"
34 #include "HLAObjectClass.hxx"
35 #include "HLAVariantRecordDataElement.hxx"
36 #include "RTIObjectClass.hxx"
37 #include "RTIObjectInstance.hxx"
41 HLAObjectInstance::UpdateCallback::~UpdateCallback()
45 HLAObjectInstance::ReflectCallback::~ReflectCallback()
49 HLAObjectInstance::HLAObjectInstance(HLAObjectClass* objectClass) :
50 _federate(objectClass->_federate),
51 _objectClass(objectClass)
55 HLAObjectInstance::~HLAObjectInstance()
57 _clearRTIObjectInstance();
61 HLAObjectInstance::getName() const
66 const SGWeakPtr<HLAFederate>&
67 HLAObjectInstance::getFederate() const
72 const SGSharedPtr<HLAObjectClass>&
73 HLAObjectInstance::getObjectClass() const
79 HLAObjectInstance::getNumAttributes() const
81 return _objectClass->getNumAttributes();
85 HLAObjectInstance::getAttributeIndex(const std::string& name) const
87 return _objectClass->getAttributeIndex(name);
91 HLAObjectInstance::getAttributeName(unsigned index) const
93 return _objectClass->getAttributeName(index);
97 HLAObjectInstance::getAttributeOwned(unsigned index) const
99 if (!_rtiObjectInstance.valid())
101 return _rtiObjectInstance->getAttributeOwned(index);
105 HLAObjectInstance::getAttributeDataType(unsigned index) const
107 return _objectClass->getAttributeDataType(index);
111 HLAObjectInstance::getAttributeDataElement(unsigned index)
113 if (_attributeVector.size() <= index)
115 return _attributeVector[index]._dataElement.get();
118 const HLADataElement*
119 HLAObjectInstance::getAttributeDataElement(unsigned index) const
121 if (_attributeVector.size() <= index)
123 return _attributeVector[index]._dataElement.get();
127 HLAObjectInstance::getAttributeData(unsigned index, RTIData& data) const
129 if (!_rtiObjectInstance.valid()) {
130 SG_LOG(SG_IO, SG_ALERT, "Trying to get raw attribute data without rti object instance for \"" << getName() << "\"!");
133 return _rtiObjectInstance->getAttributeData(index, data);
137 HLAObjectInstance::setAttributeDataElement(unsigned index, const SGSharedPtr<HLADataElement>& dataElement)
139 unsigned numAttributes = getNumAttributes();
140 if (numAttributes <= index)
142 _attributeVector.resize(numAttributes);
143 if (_attributeVector[index]._dataElement.valid())
144 _attributeVector[index]._dataElement->clearStamp();
145 _attributeVector[index]._dataElement = dataElement;
146 if (_attributeVector[index]._dataElement.valid())
147 _attributeVector[index]._dataElement->createStamp();
150 class HLAObjectInstance::DataElementFactoryVisitor : public HLADataElementFactoryVisitor {
152 DataElementFactoryVisitor(const HLAPathElementMap& pathElementMap) :
153 _pathElementMap(pathElementMap)
155 DataElementFactoryVisitor(const HLADataElement::Path& path, const HLAPathElementMap& pathElementMap) :
156 _pathElementMap(pathElementMap),
159 virtual ~DataElementFactoryVisitor() {}
161 virtual void apply(const HLADataType& dataType)
163 _dataElement = createDataElement(_path, dataType);
164 if (_dataElement.valid())
167 SG_LOG(SG_NETWORK, SG_ALERT, "HLA: Can not find a suitable data element for data type \""
168 << dataType.getName() << "\"");
171 virtual void apply(const HLAInt8DataType& dataType)
173 _dataElement = createDataElement(_path, dataType);
174 if (_dataElement.valid())
177 HLADataElementFactoryVisitor::apply(dataType);
179 virtual void apply(const HLAUInt8DataType& dataType)
181 _dataElement = createDataElement(_path, dataType);
182 if (_dataElement.valid())
185 HLADataElementFactoryVisitor::apply(dataType);
187 virtual void apply(const HLAInt16DataType& dataType)
189 _dataElement = createDataElement(_path, dataType);
190 if (_dataElement.valid())
193 HLADataElementFactoryVisitor::apply(dataType);
195 virtual void apply(const HLAUInt16DataType& dataType)
197 _dataElement = createDataElement(_path, dataType);
198 if (_dataElement.valid())
201 HLADataElementFactoryVisitor::apply(dataType);
203 virtual void apply(const HLAInt32DataType& dataType)
205 _dataElement = createDataElement(_path, dataType);
206 if (_dataElement.valid())
209 HLADataElementFactoryVisitor::apply(dataType);
211 virtual void apply(const HLAUInt32DataType& dataType)
213 _dataElement = createDataElement(_path, dataType);
214 if (_dataElement.valid())
217 HLADataElementFactoryVisitor::apply(dataType);
219 virtual void apply(const HLAInt64DataType& dataType)
221 _dataElement = createDataElement(_path, dataType);
222 if (_dataElement.valid())
225 HLADataElementFactoryVisitor::apply(dataType);
227 virtual void apply(const HLAUInt64DataType& dataType)
229 _dataElement = createDataElement(_path, dataType);
230 if (_dataElement.valid())
233 HLADataElementFactoryVisitor::apply(dataType);
235 virtual void apply(const HLAFloat32DataType& dataType)
237 _dataElement = createDataElement(_path, dataType);
238 if (_dataElement.valid())
241 HLADataElementFactoryVisitor::apply(dataType);
243 virtual void apply(const HLAFloat64DataType& dataType)
245 _dataElement = createDataElement(_path, dataType);
246 if (_dataElement.valid())
249 HLADataElementFactoryVisitor::apply(dataType);
252 class ArrayDataElementFactory : public HLAArrayDataElement::DataElementFactory {
254 ArrayDataElementFactory(const HLADataElement::Path& path, const HLAPathElementMap& pathElementMap) :
257 for (HLAPathElementMap::const_iterator i = pathElementMap.lower_bound(path);
258 i != pathElementMap.end(); ++i) {
259 if (i->first.begin() != std::search(i->first.begin(), i->first.end(),
260 path.begin(), path.end()))
262 _pathElementMap.insert(*i);
265 virtual HLADataElement* createElement(const HLAArrayDataElement& element, unsigned index)
267 const HLADataType* dataType = element.getElementDataType();
270 HLADataElement::Path path = _path;
271 path.push_back(HLADataElement::PathElement(index));
272 DataElementFactoryVisitor visitor(path, _pathElementMap);
273 dataType->accept(visitor);
274 return visitor._dataElement.release();
277 HLADataElement::Path _path;
278 HLAPathElementMap _pathElementMap;
281 virtual void apply(const HLAFixedArrayDataType& dataType)
283 _dataElement = createDataElement(_path, dataType);
284 if (_dataElement.valid())
287 SGSharedPtr<HLAArrayDataElement> arrayDataElement;
288 arrayDataElement = new HLAArrayDataElement(&dataType);
289 arrayDataElement->setDataElementFactory(new ArrayDataElementFactory(_path, _pathElementMap));
290 arrayDataElement->setNumElements(dataType.getNumElements());
292 _dataElement = arrayDataElement;
295 virtual void apply(const HLAVariableArrayDataType& dataType)
297 _dataElement = createDataElement(_path, dataType);
298 if (_dataElement.valid())
301 SGSharedPtr<HLAArrayDataElement> arrayDataElement;
302 arrayDataElement = new HLAArrayDataElement(&dataType);
303 arrayDataElement->setDataElementFactory(new ArrayDataElementFactory(_path, _pathElementMap));
305 _dataElement = arrayDataElement;
308 virtual void apply(const HLAEnumeratedDataType& dataType)
310 _dataElement = createDataElement(_path, dataType);
311 if (_dataElement.valid())
314 HLADataElementFactoryVisitor::apply(dataType);
317 virtual void apply(const HLAFixedRecordDataType& dataType)
319 _dataElement = createDataElement(_path, dataType);
320 if (_dataElement.valid())
323 SGSharedPtr<HLAFixedRecordDataElement> recordDataElement;
324 recordDataElement = new HLAFixedRecordDataElement(&dataType);
326 unsigned numFields = dataType.getNumFields();
327 for (unsigned i = 0; i < numFields; ++i) {
329 _path.push_back(HLADataElement::PathElement(dataType.getFieldName(i)));
331 dataType.getFieldDataType(i)->accept(*this);
332 recordDataElement->setField(i, _dataElement.release());
336 _dataElement = recordDataElement;
339 class VariantRecordDataElementFactory : public HLAVariantRecordDataElement::DataElementFactory {
341 VariantRecordDataElementFactory(const HLADataElement::Path& path, const HLAPathElementMap& pathElementMap) :
344 for (HLAPathElementMap::const_iterator i = pathElementMap.lower_bound(path);
345 i != pathElementMap.end(); ++i) {
346 if (i->first.begin() != std::search(i->first.begin(), i->first.end(),
347 path.begin(), path.end()))
349 _pathElementMap.insert(*i);
352 virtual HLADataElement* createElement(const HLAVariantRecordDataElement& element, unsigned index)
354 const HLAVariantRecordDataType* dataType = element.getDataType();
357 const HLADataType* alternativeDataType = element.getAlternativeDataType();
358 if (!alternativeDataType)
360 HLADataElement::Path path = _path;
361 path.push_back(HLADataElement::PathElement(dataType->getAlternativeName(index)));
362 DataElementFactoryVisitor visitor(path, _pathElementMap);
363 alternativeDataType->accept(visitor);
364 return visitor._dataElement.release();
367 HLADataElement::Path _path;
368 HLAPathElementMap _pathElementMap;
371 virtual void apply(const HLAVariantRecordDataType& dataType)
373 _dataElement = createDataElement(_path, dataType);
374 if (_dataElement.valid())
377 SGSharedPtr<HLAVariantRecordDataElement> variantRecordDataElement;
378 variantRecordDataElement = new HLAVariantRecordDataElement(&dataType);
379 variantRecordDataElement->setDataElementFactory(new VariantRecordDataElementFactory(_path, _pathElementMap));
381 _dataElement = variantRecordDataElement;
385 SGSharedPtr<HLADataElement> createDataElement(const HLADataElement::Path& path, const HLADataType& dataType)
387 HLAPathElementMap::const_iterator i = _pathElementMap.find(path);
388 if (i == _pathElementMap.end()) {
389 SG_LOG(SG_IO, SG_WARN, "No dataElement provided for \""
390 << HLADataElement::toString(path) << "\".");
394 SGSharedPtr<HLADataElement> dataElement = i->second.getDataElement(path);
395 if (!dataElement->setDataType(&dataType)) {
396 SG_LOG(SG_IO, SG_ALERT, "Cannot set data type for data element at \""
397 << HLADataElement::toString(path) << "\"!");
400 SG_LOG(SG_IO, SG_DEBUG, "Using provided dataElement for \""
401 << HLADataElement::toString(path) << "\".");
405 const HLAPathElementMap& _pathElementMap;
406 HLADataElement::Path _path;
410 HLAObjectInstance::setAttribute(unsigned index, const HLAPathElementMap& pathElementMap)
412 const HLADataType* dataType = getAttributeDataType(index);
414 SG_LOG(SG_IO, SG_ALERT, "Cannot get attribute data type for setting attribute \""
415 << getAttributeName(index) << "\" at index " << index << "!");
419 SG_LOG(SG_IO, SG_DEBUG, "Setting DataElement for attribute \""
420 << getAttributeName(index) << "\".");
422 DataElementFactoryVisitor visitor(pathElementMap);
423 dataType->accept(visitor);
424 setAttributeDataElement(index, visitor.getDataElement());
428 HLAObjectInstance::setAttributes(const HLAAttributePathElementMap& attributePathElementMap)
430 for (HLAAttributePathElementMap::const_iterator i = attributePathElementMap.begin();
431 i != attributePathElementMap.end(); ++i) {
432 setAttribute(i->first, i->second);
437 HLAObjectInstance::registerInstance()
439 if (_rtiObjectInstance.valid()) {
440 SG_LOG(SG_IO, SG_ALERT, "Trying to register object " << getName() << " already known to the RTI!");
443 if (!_objectClass.valid()) {
444 SG_LOG(SG_IO, SG_ALERT, "Could not register object with unknown object class!");
447 // This error must have been flagged before
448 if (!_objectClass->_rtiObjectClass.valid())
450 _setRTIObjectInstance(_objectClass->_rtiObjectClass->registerObjectInstance(this));
451 if (!_rtiObjectInstance.valid()) {
452 SG_LOG(SG_IO, SG_ALERT, "Could not register object at the RTI!");
455 _objectClass->_registerInstance(this);
459 HLAObjectInstance::deleteInstance(const RTIData& tag)
461 if (!_rtiObjectInstance.valid()) {
462 SG_LOG(SG_IO, SG_ALERT, "Trying to delete inactive object!");
465 if (!_objectClass.valid())
467 _objectClass->_deleteInstance(*this);
468 _rtiObjectInstance->deleteObjectInstance(tag);
472 HLAObjectInstance::updateAttributeValues(const RTIData& tag)
474 if (_attributeCallback.valid())
475 _attributeCallback->updateAttributeValues(*this, tag);
476 if (_updateCallback.valid()) {
477 _updateCallback->updateAttributeValues(*this, tag);
479 encodeAttributeValues();
480 sendAttributeValues(tag);
485 HLAObjectInstance::updateAttributeValues(const SGTimeStamp& timeStamp, const RTIData& tag)
487 if (_attributeCallback.valid())
488 _attributeCallback->updateAttributeValues(*this, tag);
489 if (_updateCallback.valid()) {
490 _updateCallback->updateAttributeValues(*this, timeStamp, tag);
492 encodeAttributeValues();
493 sendAttributeValues(timeStamp, tag);
498 HLAObjectInstance::encodeAttributeValues()
500 unsigned numAttributes = _attributeVector.size();
501 for (unsigned i = 0; i < numAttributes;++i) {
502 if (_attributeVector[i]._unconditionalUpdate) {
503 encodeAttributeValue(i);
504 } else if (_attributeVector[i]._enabledUpdate) {
505 const HLADataElement* dataElement = getAttributeDataElement(i);
506 if (dataElement && dataElement->getDirty())
507 encodeAttributeValue(i);
513 HLAObjectInstance::encodeAttributeValue(unsigned index)
515 if (!_rtiObjectInstance.valid()) {
516 SG_LOG(SG_IO, SG_INFO, "Not updating inactive object!");
519 HLADataElement* dataElement = getAttributeDataElement(index);
522 _rtiObjectInstance->encodeAttributeData(index, *dataElement);
523 dataElement->setDirty(false);
527 HLAObjectInstance::sendAttributeValues(const RTIData& tag)
529 if (!_rtiObjectInstance.valid()) {
530 SG_LOG(SG_IO, SG_INFO, "Not updating inactive object!");
533 _rtiObjectInstance->updateAttributeValues(tag);
537 HLAObjectInstance::sendAttributeValues(const SGTimeStamp& timeStamp, const RTIData& tag)
539 if (!_rtiObjectInstance.valid()) {
540 SG_LOG(SG_IO, SG_INFO, "Not updating inactive object!");
543 _rtiObjectInstance->updateAttributeValues(timeStamp, tag);
547 HLAObjectInstance::reflectAttributeValues(const HLAIndexList& indexList, const RTIData& tag)
549 for (HLAIndexList::const_iterator i = indexList.begin(); i != indexList.end(); ++i)
550 reflectAttributeValue(*i, tag);
554 HLAObjectInstance::reflectAttributeValues(const HLAIndexList& indexList,
555 const SGTimeStamp& timeStamp, const RTIData& tag)
557 for (HLAIndexList::const_iterator i = indexList.begin(); i != indexList.end(); ++i)
558 reflectAttributeValue(*i, timeStamp, tag);
562 HLAObjectInstance::reflectAttributeValue(unsigned index, const RTIData& tag)
564 HLADataElement* dataElement = getAttributeDataElement(index);
567 dataElement->setTimeStampValid(false);
568 _rtiObjectInstance->decodeAttributeData(index, *dataElement);
572 HLAObjectInstance::reflectAttributeValue(unsigned index, const SGTimeStamp& timeStamp, const RTIData& tag)
574 HLADataElement* dataElement = getAttributeDataElement(index);
577 dataElement->setTimeStamp(timeStamp);
578 dataElement->setTimeStampValid(true);
579 _rtiObjectInstance->decodeAttributeData(index, *dataElement);
583 HLAObjectInstance::_setRTIObjectInstance(RTIObjectInstance* rtiObjectInstance)
585 _rtiObjectInstance = rtiObjectInstance;
586 _rtiObjectInstance->setObjectInstance(this);
587 _name = _rtiObjectInstance->getName();
589 unsigned numAttributes = getNumAttributes();
590 _attributeVector.resize(numAttributes);
591 for (unsigned i = 0; i < numAttributes; ++i) {
592 HLAUpdateType updateType = getObjectClass()->getAttributeUpdateType(i);
593 if (getAttributeOwned(i) && updateType != HLAUndefinedUpdate) {
594 _attributeVector[i]._enabledUpdate = true;
595 _attributeVector[i]._unconditionalUpdate = (updateType == HLAPeriodicUpdate);
596 // In case of an owned attribute, now encode its value
597 encodeAttributeValue(i);
599 _attributeVector[i]._enabledUpdate = false;
600 _attributeVector[i]._unconditionalUpdate = false;
604 // This makes sense with any new object. Even if we registered one, there might be unpublished attributes.
605 HLAIndexList indexList;
606 for (unsigned i = 0; i < numAttributes; ++i) {
607 HLAUpdateType updateType = getObjectClass()->getAttributeUpdateType(i);
608 if (getAttributeOwned(i))
610 if (updateType == HLAUndefinedUpdate)
612 if (updateType == HLAPeriodicUpdate)
614 indexList.push_back(i);
616 _rtiObjectInstance->requestObjectAttributeValueUpdate(indexList);
620 HLAObjectInstance::_clearRTIObjectInstance()
622 if (!_rtiObjectInstance.valid())
625 for (unsigned i = 0; i < _attributeVector.size(); ++i) {
626 _attributeVector[i]._enabledUpdate = false;
627 _attributeVector[i]._unconditionalUpdate = false;
630 _rtiObjectInstance->setObjectInstance(0);
631 _rtiObjectInstance = 0;
635 HLAObjectInstance::_removeInstance(const RTIData& tag)
637 if (!_objectClass.valid())
639 _objectClass->_removeInstance(*this, tag);
643 HLAObjectInstance::_reflectAttributeValues(const HLAIndexList& indexList, const RTIData& tag)
645 if (_reflectCallback.valid()) {
646 _reflectCallback->reflectAttributeValues(*this, indexList, tag);
647 } else if (_attributeCallback.valid()) {
648 reflectAttributeValues(indexList, tag);
650 RTIIndexDataPairList dataPairList;
651 for (HLAIndexList::const_iterator i = indexList.begin(); i != indexList.end(); ++i) {
652 dataPairList.push_back(RTIIndexDataPair());
653 dataPairList.back().first = *i;
654 getAttributeData(*i, dataPairList.back().second);
656 _attributeCallback->reflectAttributeValues(*this, dataPairList, tag);
658 reflectAttributeValues(indexList, tag);
663 HLAObjectInstance::_reflectAttributeValues(const HLAIndexList& indexList, const SGTimeStamp& timeStamp, const RTIData& tag)
665 if (_reflectCallback.valid()) {
666 _reflectCallback->reflectAttributeValues(*this, indexList, timeStamp, tag);
667 } else if (_attributeCallback.valid()) {
668 reflectAttributeValues(indexList, timeStamp, tag);
670 RTIIndexDataPairList dataPairList;
671 for (HLAIndexList::const_iterator i = indexList.begin(); i != indexList.end(); ++i) {
672 dataPairList.push_back(RTIIndexDataPair());
673 dataPairList.back().first = *i;
674 getAttributeData(*i, dataPairList.back().second);
676 _attributeCallback->reflectAttributeValues(*this, dataPairList, timeStamp, tag);
678 reflectAttributeValues(indexList, timeStamp, tag);
682 } // namespace simgear