]> git.mxchange.org Git - simgear.git/blob - simgear/hla/HLAObjectInstance.cxx
math: Move lerp function into SGMisc.
[simgear.git] / simgear / hla / HLAObjectInstance.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 "HLAObjectInstance.hxx"
19
20 #include <algorithm>
21 #include "simgear/debug/logstream.hxx"
22 #include "HLAArrayDataElement.hxx"
23 #include "HLABasicDataElement.hxx"
24 #include "HLADataElement.hxx"
25 #include "HLAEnumeratedDataElement.hxx"
26 #include "HLAFederate.hxx"
27 #include "HLAFixedRecordDataElement.hxx"
28 #include "HLAObjectClass.hxx"
29 #include "HLAVariantRecordDataElement.hxx"
30 #include "RTIObjectClass.hxx"
31 #include "RTIObjectInstance.hxx"
32
33 namespace simgear {
34
35 HLAObjectInstance::UpdateCallback::~UpdateCallback()
36 {
37 }
38
39 HLAObjectInstance::ReflectCallback::~ReflectCallback()
40 {
41 }
42
43 HLAObjectInstance::HLAObjectInstance(HLAObjectClass* objectClass) :
44     _federate(objectClass->_federate),
45     _objectClass(objectClass)
46 {
47 }
48
49 HLAObjectInstance::~HLAObjectInstance()
50 {
51     _clearRTIObjectInstance();
52 }
53
54 unsigned
55 HLAObjectInstance::getNumAttributes() const
56 {
57     return _objectClass->getNumAttributes();
58 }
59
60 unsigned
61 HLAObjectInstance::getAttributeIndex(const std::string& name) const
62 {
63     return _objectClass->getAttributeIndex(name);
64 }
65
66 std::string
67 HLAObjectInstance::getAttributeName(unsigned index) const
68 {
69     return _objectClass->getAttributeName(index);
70 }
71
72 bool
73 HLAObjectInstance::getAttributeOwned(unsigned index) const
74 {
75     if (!_rtiObjectInstance.valid())
76         return false;
77     return _rtiObjectInstance->getAttributeOwned(index);
78 }
79
80 const HLADataType*
81 HLAObjectInstance::getAttributeDataType(unsigned index) const
82 {
83     return _objectClass->getAttributeDataType(index);
84 }
85
86 HLADataElement*
87 HLAObjectInstance::getAttributeDataElement(unsigned index)
88 {
89     if (_attributeVector.size() <= index)
90         return 0;
91     return _attributeVector[index]._dataElement.get();
92 }
93
94 const HLADataElement*
95 HLAObjectInstance::getAttributeDataElement(unsigned index) const
96 {
97     if (_attributeVector.size() <= index)
98         return 0;
99     return _attributeVector[index]._dataElement.get();
100 }
101
102 bool
103 HLAObjectInstance::getAttributeData(unsigned index, RTIData& data) const
104 {
105     if (!_rtiObjectInstance.valid()) {
106         SG_LOG(SG_IO, SG_ALERT, "Trying to get raw attribute data without rti object instance for \"" << getName() << "\"!");
107         return false;
108     }
109     return _rtiObjectInstance->getAttributeData(index, data);
110 }
111
112 void
113 HLAObjectInstance::setAttributeDataElement(unsigned index, const SGSharedPtr<HLADataElement>& dataElement)
114 {
115     unsigned numAttributes = getNumAttributes();
116     if (numAttributes <= index)
117         return;
118     _attributeVector.resize(numAttributes);
119     if (_attributeVector[index]._dataElement.valid())
120         _attributeVector[index]._dataElement->clearStamp();
121     _attributeVector[index]._dataElement = dataElement;
122     if (_attributeVector[index]._dataElement.valid())
123         _attributeVector[index]._dataElement->createStamp();
124 }
125
126 class HLAObjectInstance::DataElementFactoryVisitor : public HLADataElementFactoryVisitor {
127 public:
128     DataElementFactoryVisitor(const HLAPathElementMap& pathElementMap) :
129         _pathElementMap(pathElementMap)
130     { }
131     DataElementFactoryVisitor(const HLADataElement::Path& path, const HLAPathElementMap& pathElementMap) :
132         _pathElementMap(pathElementMap),
133         _path(path)
134     { }
135     virtual ~DataElementFactoryVisitor() {}
136
137     virtual void apply(const HLADataType& dataType)
138     {
139         _dataElement = createDataElement(_path, dataType);
140         if (_dataElement.valid())
141             return;
142
143         SG_LOG(SG_NETWORK, SG_ALERT, "HLA: Can not find a suitable data element for data type \""
144                << dataType.getName() << "\"");
145     }
146
147     virtual void apply(const HLAInt8DataType& dataType)
148     {
149         _dataElement = createDataElement(_path, dataType);
150         if (_dataElement.valid())
151             return;
152
153         HLADataElementFactoryVisitor::apply(dataType);
154     }
155     virtual void apply(const HLAUInt8DataType& dataType)
156     {
157         _dataElement = createDataElement(_path, dataType);
158         if (_dataElement.valid())
159             return;
160
161         HLADataElementFactoryVisitor::apply(dataType);
162     }
163     virtual void apply(const HLAInt16DataType& dataType)
164     {
165         _dataElement = createDataElement(_path, dataType);
166         if (_dataElement.valid())
167             return;
168
169         HLADataElementFactoryVisitor::apply(dataType);
170     }
171     virtual void apply(const HLAUInt16DataType& dataType)
172     {
173         _dataElement = createDataElement(_path, dataType);
174         if (_dataElement.valid())
175             return;
176
177         HLADataElementFactoryVisitor::apply(dataType);
178     }
179     virtual void apply(const HLAInt32DataType& dataType)
180     {
181         _dataElement = createDataElement(_path, dataType);
182         if (_dataElement.valid())
183             return;
184
185         HLADataElementFactoryVisitor::apply(dataType);
186     }
187     virtual void apply(const HLAUInt32DataType& dataType)
188     {
189         _dataElement = createDataElement(_path, dataType);
190         if (_dataElement.valid())
191             return;
192
193         HLADataElementFactoryVisitor::apply(dataType);
194     }
195     virtual void apply(const HLAInt64DataType& dataType)
196     {
197         _dataElement = createDataElement(_path, dataType);
198         if (_dataElement.valid())
199             return;
200
201         HLADataElementFactoryVisitor::apply(dataType);
202     }
203     virtual void apply(const HLAUInt64DataType& dataType)
204     {
205         _dataElement = createDataElement(_path, dataType);
206         if (_dataElement.valid())
207             return;
208
209         HLADataElementFactoryVisitor::apply(dataType);
210     }
211     virtual void apply(const HLAFloat32DataType& dataType)
212     {
213         _dataElement = createDataElement(_path, dataType);
214         if (_dataElement.valid())
215             return;
216
217         HLADataElementFactoryVisitor::apply(dataType);
218     }
219     virtual void apply(const HLAFloat64DataType& dataType)
220     {
221         _dataElement = createDataElement(_path, dataType);
222         if (_dataElement.valid())
223             return;
224
225         HLADataElementFactoryVisitor::apply(dataType);
226     }
227
228     class ArrayDataElementFactory : public HLAArrayDataElement::DataElementFactory {
229     public:
230         ArrayDataElementFactory(const HLADataElement::Path& path, const HLAPathElementMap& pathElementMap) :
231             _path(path)
232         {
233             for (HLAPathElementMap::const_iterator i = pathElementMap.lower_bound(path);
234                  i != pathElementMap.end(); ++i) {
235                 if (i->first.begin() != std::search(i->first.begin(), i->first.end(),
236                                                     path.begin(), path.end()))
237                     break;
238                 _pathElementMap.insert(*i);
239             }
240         }
241         virtual HLADataElement* createElement(const HLAArrayDataElement& element, unsigned index)
242         {
243             const HLADataType* dataType = element.getElementDataType();
244             if (!dataType)
245                 return 0;
246             HLADataElement::Path path = _path;
247             path.push_back(HLADataElement::PathElement(index));
248             DataElementFactoryVisitor visitor(path, _pathElementMap);
249             dataType->accept(visitor);
250             return visitor._dataElement.release();
251         }
252     private:
253         HLADataElement::Path _path;
254         HLAPathElementMap _pathElementMap;
255     };
256
257     virtual void apply(const HLAFixedArrayDataType& dataType)
258     {
259         _dataElement = createDataElement(_path, dataType);
260         if (_dataElement.valid())
261             return;
262
263         SGSharedPtr<HLAArrayDataElement> arrayDataElement;
264         arrayDataElement = new HLAArrayDataElement(&dataType);
265         arrayDataElement->setDataElementFactory(new ArrayDataElementFactory(_path, _pathElementMap));
266         arrayDataElement->setNumElements(dataType.getNumElements());
267
268         _dataElement = arrayDataElement;
269     }
270
271     virtual void apply(const HLAVariableArrayDataType& dataType)
272     {
273         _dataElement = createDataElement(_path, dataType);
274         if (_dataElement.valid())
275             return;
276
277         SGSharedPtr<HLAArrayDataElement> arrayDataElement;
278         arrayDataElement = new HLAArrayDataElement(&dataType);
279         arrayDataElement->setDataElementFactory(new ArrayDataElementFactory(_path, _pathElementMap));
280
281         _dataElement = arrayDataElement;
282     }
283
284     virtual void apply(const HLAEnumeratedDataType& dataType)
285     {
286         _dataElement = createDataElement(_path, dataType);
287         if (_dataElement.valid())
288             return;
289
290         HLADataElementFactoryVisitor::apply(dataType);
291     }
292
293     virtual void apply(const HLAFixedRecordDataType& dataType)
294     {
295         _dataElement = createDataElement(_path, dataType);
296         if (_dataElement.valid())
297             return;
298
299         SGSharedPtr<HLAFixedRecordDataElement> recordDataElement;
300         recordDataElement = new HLAFixedRecordDataElement(&dataType);
301
302         unsigned numFields = dataType.getNumFields();
303         for (unsigned i = 0; i < numFields; ++i) {
304
305             _path.push_back(HLADataElement::PathElement(dataType.getFieldName(i)));
306
307             dataType.getFieldDataType(i)->accept(*this);
308             recordDataElement->setField(i, _dataElement.release());
309
310             _path.pop_back();
311         }
312         _dataElement = recordDataElement;
313     }
314
315     class VariantRecordDataElementFactory : public HLAVariantRecordDataElement::DataElementFactory {
316     public:
317         VariantRecordDataElementFactory(const HLADataElement::Path& path, const HLAPathElementMap& pathElementMap) :
318             _path(path)
319         {
320             for (HLAPathElementMap::const_iterator i = pathElementMap.lower_bound(path);
321                  i != pathElementMap.end(); ++i) {
322                 if (i->first.begin() != std::search(i->first.begin(), i->first.end(),
323                                                     path.begin(), path.end()))
324                     break;
325                 _pathElementMap.insert(*i);
326             }
327         }
328         virtual HLADataElement* createElement(const HLAVariantRecordDataElement& element, unsigned index)
329         {
330             const HLAVariantRecordDataType* dataType = element.getDataType();
331             if (!dataType)
332                 return 0;
333             const HLADataType* alternativeDataType = element.getAlternativeDataType();
334             if (!alternativeDataType)
335                 return 0;
336             HLADataElement::Path path = _path;
337             path.push_back(HLADataElement::PathElement(dataType->getAlternativeName(index)));
338             DataElementFactoryVisitor visitor(path, _pathElementMap);
339             alternativeDataType->accept(visitor);
340             return visitor._dataElement.release();
341         }
342     private:
343         HLADataElement::Path _path;
344         HLAPathElementMap _pathElementMap;
345     };
346
347     virtual void apply(const HLAVariantRecordDataType& dataType)
348     {
349         _dataElement = createDataElement(_path, dataType);
350         if (_dataElement.valid())
351             return;
352
353         SGSharedPtr<HLAVariantRecordDataElement> variantRecordDataElement;
354         variantRecordDataElement = new HLAVariantRecordDataElement(&dataType);
355         variantRecordDataElement->setDataElementFactory(new VariantRecordDataElementFactory(_path, _pathElementMap));
356
357         _dataElement = variantRecordDataElement;
358     }
359
360 private:
361     SGSharedPtr<HLADataElement> createDataElement(const HLADataElement::Path& path, const HLADataType& dataType)
362     {
363         HLAPathElementMap::const_iterator i = _pathElementMap.find(path);
364         if (i == _pathElementMap.end()) {
365             SG_LOG(SG_IO, SG_WARN, "No dataElement provided for \""
366                    << HLADataElement::toString(path) << "\".");
367
368             return 0;
369         }
370         SGSharedPtr<HLADataElement> dataElement = i->second.getDataElement(path);
371         if (!dataElement->setDataType(&dataType)) {
372             SG_LOG(SG_IO, SG_ALERT, "Cannot set data type for data element at \""
373                    << HLADataElement::toString(path) <<  "\"!");
374             return 0;
375         }
376         SG_LOG(SG_IO, SG_DEBUG, "Using provided dataElement for \""
377                << HLADataElement::toString(path) << "\".");
378         return dataElement;
379     }
380
381     const HLAPathElementMap& _pathElementMap;
382     HLADataElement::Path _path;
383 };
384
385 void
386 HLAObjectInstance::setAttribute(unsigned index, const HLAPathElementMap& pathElementMap)
387 {
388     const HLADataType* dataType = getAttributeDataType(index);
389     if (!dataType) {
390         SG_LOG(SG_IO, SG_ALERT, "Cannot get attribute data type for setting attribute \""
391                << getAttributeName(index) << "\" at index " << index << "!");
392         return;
393     }
394
395     SG_LOG(SG_IO, SG_DEBUG, "Setting DataElement for attribute \""
396            << getAttributeName(index) << "\".");
397
398     DataElementFactoryVisitor visitor(pathElementMap);
399     dataType->accept(visitor);
400     setAttributeDataElement(index, visitor.getDataElement());
401 }
402
403 void
404 HLAObjectInstance::setAttributes(const HLAAttributePathElementMap& attributePathElementMap)
405 {
406     for (HLAAttributePathElementMap::const_iterator i = attributePathElementMap.begin();
407          i != attributePathElementMap.end(); ++i) {
408         setAttribute(i->first, i->second);
409     }
410 }
411
412 void
413 HLAObjectInstance::registerInstance()
414 {
415     if (_rtiObjectInstance.valid()) {
416         SG_LOG(SG_IO, SG_ALERT, "Trying to register object " << getName() << " already known to the RTI!");
417         return;
418     }
419     if (!_objectClass.valid()) {
420         SG_LOG(SG_IO, SG_ALERT, "Could not register object with unknown object class!");
421         return;
422     }
423     // This error must have been flagged before
424     if (!_objectClass->_rtiObjectClass.valid())
425         return;
426     _setRTIObjectInstance(_objectClass->_rtiObjectClass->registerObjectInstance(this));
427     if (!_rtiObjectInstance.valid()) {
428         SG_LOG(SG_IO, SG_ALERT, "Could not register object at the RTI!");
429         return;
430     }
431     _objectClass->_registerInstance(this);
432 }
433
434 void
435 HLAObjectInstance::deleteInstance(const RTIData& tag)
436 {
437     if (!_rtiObjectInstance.valid()) {
438         SG_LOG(SG_IO, SG_ALERT, "Trying to delete inactive object!");
439         return;
440     }
441     if (!_objectClass.valid())
442         return;
443     _objectClass->_deleteInstance(*this);
444     _rtiObjectInstance->deleteObjectInstance(tag);
445 }
446
447 void
448 HLAObjectInstance::updateAttributeValues(const RTIData& tag)
449 {
450     if (_attributeCallback.valid())
451         _attributeCallback->updateAttributeValues(*this, tag);
452     if (_updateCallback.valid()) {
453         _updateCallback->updateAttributeValues(*this, tag);
454     } else {
455         encodeAttributeValues();
456         sendAttributeValues(tag);
457     }
458 }
459
460 void
461 HLAObjectInstance::updateAttributeValues(const SGTimeStamp& timeStamp, const RTIData& tag)
462 {
463     if (_attributeCallback.valid())
464         _attributeCallback->updateAttributeValues(*this, tag);
465     if (_updateCallback.valid()) {
466         _updateCallback->updateAttributeValues(*this, timeStamp, tag);
467     } else {
468         encodeAttributeValues();
469         sendAttributeValues(timeStamp, tag);
470     }
471 }
472
473 void
474 HLAObjectInstance::encodeAttributeValues()
475 {
476     unsigned numAttributes = _attributeVector.size();
477     for (unsigned i = 0; i < numAttributes;++i) {
478         if (_attributeVector[i]._unconditionalUpdate) {
479             encodeAttributeValue(i);
480         } else if (_attributeVector[i]._enabledUpdate) {
481             const HLADataElement* dataElement = getAttributeDataElement(i);
482             if (dataElement && dataElement->getDirty())
483                 encodeAttributeValue(i);
484         }
485     }
486 }
487
488 void
489 HLAObjectInstance::encodeAttributeValue(unsigned index)
490 {
491     if (!_rtiObjectInstance.valid()) {
492         SG_LOG(SG_IO, SG_INFO, "Not updating inactive object!");
493         return;
494     }
495     HLADataElement* dataElement = getAttributeDataElement(index);
496     if (!dataElement)
497         return;
498     _rtiObjectInstance->encodeAttributeData(index, *dataElement);
499     dataElement->setDirty(false);
500 }
501
502 void
503 HLAObjectInstance::sendAttributeValues(const RTIData& tag)
504 {
505     if (!_rtiObjectInstance.valid()) {
506         SG_LOG(SG_IO, SG_INFO, "Not updating inactive object!");
507         return;
508     }
509     _rtiObjectInstance->updateAttributeValues(tag);
510 }
511
512 void
513 HLAObjectInstance::sendAttributeValues(const SGTimeStamp& timeStamp, const RTIData& tag)
514 {
515     if (!_rtiObjectInstance.valid()) {
516         SG_LOG(SG_IO, SG_INFO, "Not updating inactive object!");
517         return;
518     }
519     _rtiObjectInstance->updateAttributeValues(timeStamp, tag);
520 }
521
522 void
523 HLAObjectInstance::reflectAttributeValues(const HLAIndexList& indexList, const RTIData& tag)
524 {
525     for (HLAIndexList::const_iterator i = indexList.begin(); i != indexList.end(); ++i)
526         reflectAttributeValue(*i, tag);
527 }
528
529 void
530 HLAObjectInstance::reflectAttributeValues(const HLAIndexList& indexList,
531                                           const SGTimeStamp& timeStamp, const RTIData& tag)
532 {
533     for (HLAIndexList::const_iterator i = indexList.begin(); i != indexList.end(); ++i)
534         reflectAttributeValue(*i, timeStamp, tag);
535 }
536
537 void
538 HLAObjectInstance::reflectAttributeValue(unsigned index, const RTIData& tag)
539 {
540     HLADataElement* dataElement = getAttributeDataElement(index);
541     if (!dataElement)
542         return;
543     dataElement->setTimeStampValid(false);
544     _rtiObjectInstance->decodeAttributeData(index, *dataElement);
545 }
546
547 void
548 HLAObjectInstance::reflectAttributeValue(unsigned index, const SGTimeStamp& timeStamp, const RTIData& tag)
549 {
550     HLADataElement* dataElement = getAttributeDataElement(index);
551     if (!dataElement)
552         return;
553     dataElement->setTimeStamp(timeStamp);
554     dataElement->setTimeStampValid(true);
555     _rtiObjectInstance->decodeAttributeData(index, *dataElement);
556 }
557
558 void
559 HLAObjectInstance::_setRTIObjectInstance(RTIObjectInstance* rtiObjectInstance)
560 {
561     _rtiObjectInstance = rtiObjectInstance;
562     _rtiObjectInstance->setObjectInstance(this);
563     _name = _rtiObjectInstance->getName();
564
565     unsigned numAttributes = getNumAttributes();
566     _attributeVector.resize(numAttributes);
567     for (unsigned i = 0; i < numAttributes; ++i) {
568         HLAUpdateType updateType = getObjectClass()->getAttributeUpdateType(i);
569         if (getAttributeOwned(i) && updateType != HLAUndefinedUpdate) {
570             _attributeVector[i]._enabledUpdate = true;
571             _attributeVector[i]._unconditionalUpdate = (updateType == HLAPeriodicUpdate);
572             // In case of an owned attribute, now encode its value
573             encodeAttributeValue(i);
574         } else {
575             _attributeVector[i]._enabledUpdate = false;
576             _attributeVector[i]._unconditionalUpdate = false;
577         }
578     }
579
580     // This makes sense with any new object. Even if we registered one, there might be unpublished attributes.
581     HLAIndexList indexList;
582     for (unsigned i = 0; i < numAttributes; ++i) {
583         HLAUpdateType updateType = getObjectClass()->getAttributeUpdateType(i);
584         if (getAttributeOwned(i))
585             continue;
586         if (updateType == HLAUndefinedUpdate)
587             continue;
588         if (updateType == HLAPeriodicUpdate)
589             continue;
590         indexList.push_back(i);
591     }
592     _rtiObjectInstance->requestObjectAttributeValueUpdate(indexList);
593 }
594
595 void
596 HLAObjectInstance::_clearRTIObjectInstance()
597 {
598     if (!_rtiObjectInstance.valid())
599         return;
600
601     for (unsigned i = 0; i < _attributeVector.size(); ++i) {
602         _attributeVector[i]._enabledUpdate = false;
603         _attributeVector[i]._unconditionalUpdate = false;
604     }
605
606     _rtiObjectInstance->setObjectInstance(0);
607     _rtiObjectInstance = 0;
608 }
609
610 void
611 HLAObjectInstance::_removeInstance(const RTIData& tag)
612 {
613     if (!_objectClass.valid())
614         return;
615     _objectClass->_removeInstance(*this, tag);
616 }
617
618 void
619 HLAObjectInstance::_reflectAttributeValues(const HLAIndexList& indexList, const RTIData& tag)
620 {
621     if (_reflectCallback.valid()) {
622         _reflectCallback->reflectAttributeValues(*this, indexList, tag);
623     } else if (_attributeCallback.valid()) {
624         reflectAttributeValues(indexList, tag);
625
626         RTIIndexDataPairList dataPairList;
627         for (HLAIndexList::const_iterator i = indexList.begin(); i != indexList.end(); ++i) {
628             dataPairList.push_back(RTIIndexDataPair());
629             dataPairList.back().first = *i;
630             getAttributeData(*i, dataPairList.back().second);
631         }
632         _attributeCallback->reflectAttributeValues(*this, dataPairList, tag);
633     } else {
634         reflectAttributeValues(indexList, tag);
635     }
636 }
637
638 void
639 HLAObjectInstance::_reflectAttributeValues(const HLAIndexList& indexList, const SGTimeStamp& timeStamp, const RTIData& tag)
640 {
641     if (_reflectCallback.valid()) {
642         _reflectCallback->reflectAttributeValues(*this, indexList, timeStamp, tag);
643     } else if (_attributeCallback.valid()) {
644         reflectAttributeValues(indexList, timeStamp, tag);
645
646         RTIIndexDataPairList dataPairList;
647         for (HLAIndexList::const_iterator i = indexList.begin(); i != indexList.end(); ++i) {
648             dataPairList.push_back(RTIIndexDataPair());
649             dataPairList.back().first = *i;
650             getAttributeData(*i, dataPairList.back().second);
651         }
652         _attributeCallback->reflectAttributeValues(*this, dataPairList, timeStamp, tag);
653     } else {
654         reflectAttributeValues(indexList, timeStamp, tag);
655     }
656 }
657
658 } // namespace simgear