From: Mathias Froehlich Date: Fri, 18 Jun 2010 21:28:14 +0000 (+0200) Subject: Add an initial implementation of a rti/hla dispatcher. X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=44ff23b227dcc1f3efbd10a4df4d8b723165c11c;p=simgear.git Add an initial implementation of a rti/hla dispatcher. --- diff --git a/configure.ac b/configure.ac index 094c5b1b..da1a6b1b 100644 --- a/configure.ac +++ b/configure.ac @@ -162,6 +162,14 @@ if test "x$with_rti13" != "x" ; then EXTRA_DIRS="${EXTRA_DIRS} $with_rti13" fi +# specify the rti13 location +AC_ARG_WITH(rti1516, [ --with-rti1516=PREFIX Specify the prefix path to a HLA1516 rti]) + +if test "x$with_rti1516" != "x" ; then + echo "rti1516 prefix is $with_rti1516" + EXTRA_DIRS="${EXTRA_DIRS} $with_rti1516" +fi + dnl Determine an extra directories to add to include/lib search paths case "${host}" in *-apple-darwin* | *-*-cygwin* | *-*-mingw32*) diff --git a/simgear/hla/HLA13Federate.cxx b/simgear/hla/HLA13Federate.cxx new file mode 100644 index 00000000..4f78344c --- /dev/null +++ b/simgear/hla/HLA13Federate.cxx @@ -0,0 +1,33 @@ +// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#include "HLA13Federate.hxx" + +#include "RTI13Federate.hxx" + +namespace simgear { + +HLA13Federate::HLA13Federate() : + HLAFederate(new RTI13Federate) +{ +} + +HLA13Federate::~HLA13Federate() +{ +} + +} // namespace simgear diff --git a/simgear/hla/HLA13Federate.hxx b/simgear/hla/HLA13Federate.hxx new file mode 100644 index 00000000..dc3fa0b6 --- /dev/null +++ b/simgear/hla/HLA13Federate.hxx @@ -0,0 +1,33 @@ +// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#ifndef HLA13Federate_hxx +#define HLA13Federate_hxx + +#include "HLAFederate.hxx" + +namespace simgear { + +class HLA13Federate : public HLAFederate { +public: + HLA13Federate(); + virtual ~HLA13Federate(); +}; + +} // namespace simgear + +#endif diff --git a/simgear/hla/HLAArrayDataElement.cxx b/simgear/hla/HLAArrayDataElement.cxx new file mode 100644 index 00000000..e2a7fc73 --- /dev/null +++ b/simgear/hla/HLAArrayDataElement.cxx @@ -0,0 +1,313 @@ +// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#include "HLAArrayDataElement.hxx" + +#include + +namespace simgear { + +HLAAbstractArrayDataElement::HLAAbstractArrayDataElement(const HLAArrayDataType* dataType) : + _dataType(dataType) +{ +} + +HLAAbstractArrayDataElement::~HLAAbstractArrayDataElement() +{ +} + +bool +HLAAbstractArrayDataElement::decode(HLADecodeStream& stream) +{ + if (!_dataType.valid()) + return false; + return _dataType->decode(stream, *this); +} + +bool +HLAAbstractArrayDataElement::encode(HLAEncodeStream& stream) const +{ + if (!_dataType.valid()) + return false; + return _dataType->encode(stream, *this); +} + +const HLAArrayDataType* +HLAAbstractArrayDataElement::getDataType() const +{ + return _dataType.get(); +} + +bool +HLAAbstractArrayDataElement::setDataType(const HLADataType* dataType) +{ + const HLAArrayDataType* arrayDataType = dynamic_cast(dataType); + if (!arrayDataType) { + SG_LOG(SG_NETWORK, SG_WARN, "HLAArrayDataType: unable to set data type!"); + return false; + } + _dataType = arrayDataType; + return true; +} + +const HLADataType* +HLAAbstractArrayDataElement::getElementDataType() const +{ + if (!_dataType.valid()) + return 0; + return _dataType->getElementDataType(); +} + +//////////////////////////////////////////////////////////////////////// + +HLAArrayDataElement::DataElementFactory::~DataElementFactory() +{ +} + +HLAArrayDataElement::HLAArrayDataElement(const HLAArrayDataType* dataType) : + HLAAbstractArrayDataElement(dataType) +{ +} + +HLAArrayDataElement::~HLAArrayDataElement() +{ +} + +bool +HLAArrayDataElement::setNumElements(unsigned size) +{ + unsigned oldSize = _elementVector.size(); + if (size == oldSize) + return true; + _elementVector.resize(size); + for (unsigned i = oldSize; i < size; ++i) + _elementVector[i] = newElement(i); + return true; +} + +bool +HLAArrayDataElement::decodeElement(HLADecodeStream& stream, unsigned i) +{ + HLADataElement* dataElement = getElement(i); + if (!dataElement) + return false; + return dataElement->decode(stream); +} + +unsigned +HLAArrayDataElement::getNumElements() const +{ + return _elementVector.size(); +} + +bool +HLAArrayDataElement::encodeElement(HLAEncodeStream& stream, unsigned i) const +{ + const HLADataElement* dataElement = getElement(i); + if (!dataElement) + return false; + return dataElement->encode(stream); +} + +const HLADataElement* +HLAArrayDataElement::getElement(unsigned index) const +{ + if (_elementVector.size() <= index) + return 0; + return _elementVector[index].get(); +} + +HLADataElement* +HLAArrayDataElement::getElement(unsigned index) +{ + if (_elementVector.size() <= index) + return 0; + return _elementVector[index].get(); +} + +HLADataElement* +HLAArrayDataElement::getOrCreateElement(unsigned index) +{ + if (_elementVector.size() <= index) + if (!setNumElements(index + 1)) + return 0; + return _elementVector[index].get(); +} + +void +HLAArrayDataElement::setElement(unsigned index, HLADataElement* value) +{ + unsigned oldSize = _elementVector.size(); + if (oldSize <= index) { + _elementVector.resize(index + 1); + for (unsigned j = oldSize; j < index; ++j) + _elementVector[j] = newElement(j); + } + _elementVector[index] = value; +} + +void +HLAArrayDataElement::setDataElementFactory(HLAArrayDataElement::DataElementFactory* dataElementFactory) +{ + _dataElementFactory = dataElementFactory; +} + +HLAArrayDataElement::DataElementFactory* +HLAArrayDataElement::getDataElementFactory() +{ + return _dataElementFactory.get(); +} + +HLADataElement* +HLAArrayDataElement::newElement(unsigned index) +{ + if (!_dataElementFactory.valid()) + return 0; + return _dataElementFactory->createElement(*this, index); +} + +//////////////////////////////////////////////////////////////////////// + +HLAVariantArrayDataElement::HLAVariantArrayDataElement() : + HLAAbstractArrayDataElement(0) +{ +} + +HLAVariantArrayDataElement::~HLAVariantArrayDataElement() +{ +} + +bool +HLAVariantArrayDataElement::setDataType(const HLADataType* dataType) +{ + const HLAArrayDataType* arrayDataType = dataType->toArrayDataType(); + if (!arrayDataType) { + SG_LOG(SG_NETWORK, SG_WARN, "HLAVariantArrayDataType: unable to set data type, dataType is not an array data type!"); + return false; + } + const HLAVariantDataType* variantDataType = arrayDataType->getElementDataType()->toVariantDataType(); + if (!variantDataType) { + SG_LOG(SG_NETWORK, SG_WARN, "HLAVariantArrayDataType: unable to set data type: arrayDataTypes element data type is no a variant data type!"); + return false; + } + _dataType = arrayDataType; + return true; +} + +bool +HLAVariantArrayDataElement::setNumElements(unsigned size) +{ + unsigned oldSize = _elementVector.size(); + if (size == oldSize) + return true; + _elementVector.resize(size); + for (unsigned i = oldSize; i < size; ++i) + _elementVector[i] = newElement(); + return true; +} + +bool +HLAVariantArrayDataElement::decodeElement(HLADecodeStream& stream, unsigned i) +{ + HLAVariantDataElement* dataElement = getElement(i); + if (!dataElement) + return false; + return dataElement->decode(stream); +} + +unsigned +HLAVariantArrayDataElement::getNumElements() const +{ + return _elementVector.size(); +} + +bool +HLAVariantArrayDataElement::encodeElement(HLAEncodeStream& stream, unsigned i) const +{ + const HLADataElement* dataElement = getElement(i); + if (!dataElement) + return false; + return dataElement->encode(stream); +} + +const HLAVariantDataElement* +HLAVariantArrayDataElement::getElement(unsigned index) const +{ + if (_elementVector.size() <= index) + return 0; + return _elementVector[index].get(); +} + +HLAVariantDataElement* +HLAVariantArrayDataElement::getElement(unsigned index) +{ + if (_elementVector.size() <= index) + return 0; + return _elementVector[index].get(); +} + +HLAVariantDataElement* +HLAVariantArrayDataElement::getOrCreateElement(unsigned index) +{ + if (_elementVector.size() <= index) + if (!setNumElements(index + 1)) + return 0; + return _elementVector[index].get(); +} + +void +HLAVariantArrayDataElement::setElement(unsigned index, HLAVariantDataElement* value) +{ + unsigned oldSize = _elementVector.size(); + if (oldSize <= index) { + _elementVector.resize(index + 1); + for (unsigned j = oldSize; j < index; ++j) + _elementVector[j] = newElement(); + } + _elementVector[index] = value; +} + +void +HLAVariantArrayDataElement::setAlternativeDataElementFactory(HLAVariantArrayDataElement::AlternativeDataElementFactory* alternativeDataElementFactory) +{ + _alternativeDataElementFactory = alternativeDataElementFactory; +} + +HLAVariantArrayDataElement::AlternativeDataElementFactory* +HLAVariantArrayDataElement::getAlternativeDataElementFactory() +{ + return _alternativeDataElementFactory.get(); +} + +HLAVariantDataElement* +HLAVariantArrayDataElement::newElement() +{ + const HLAArrayDataType* arrayDataType = getDataType(); + if (!arrayDataType) + return 0; + const HLADataType* elementDataType = arrayDataType->getElementDataType(); + if (!elementDataType) + return 0; + const HLAVariantDataType* variantDataType = elementDataType->toVariantDataType(); + if (!variantDataType) + return 0; + HLAVariantDataElement* variantDataElement = new HLAVariantDataElement(variantDataType); + variantDataElement->setDataElementFactory(_alternativeDataElementFactory.get()); + return variantDataElement; +} + +} diff --git a/simgear/hla/HLAArrayDataElement.hxx b/simgear/hla/HLAArrayDataElement.hxx new file mode 100644 index 00000000..f1acf8ef --- /dev/null +++ b/simgear/hla/HLAArrayDataElement.hxx @@ -0,0 +1,418 @@ +// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#ifndef HLAArrayDataElement_hxx +#define HLAArrayDataElement_hxx + +#include +#include +#include +#include "HLAArrayDataType.hxx" +#include "HLADataElement.hxx" +#include "HLAVariantDataElement.hxx" +#include "HLADataTypeVisitor.hxx" + +namespace simgear { + +class HLAAbstractArrayDataElement : public HLADataElement { +public: + HLAAbstractArrayDataElement(const HLAArrayDataType* dataType); + virtual ~HLAAbstractArrayDataElement(); + + virtual bool decode(HLADecodeStream& stream); + virtual bool encode(HLAEncodeStream& stream) const; + + virtual const HLAArrayDataType* getDataType() const; + virtual bool setDataType(const HLADataType* dataType); + + const HLADataType* getElementDataType() const; + + virtual bool setNumElements(unsigned count) = 0; + virtual bool decodeElement(HLADecodeStream& stream, unsigned i) = 0; + + virtual unsigned getNumElements() const = 0; + virtual bool encodeElement(HLAEncodeStream& stream, unsigned i) const = 0; + +protected: + SGSharedPtr _dataType; +}; + +class HLAArrayDataElement : public HLAAbstractArrayDataElement { +public: + HLAArrayDataElement(const HLAArrayDataType* dataType = 0); + virtual ~HLAArrayDataElement(); + + virtual bool setNumElements(unsigned size); + virtual bool decodeElement(HLADecodeStream& stream, unsigned i); + virtual unsigned getNumElements() const; + virtual bool encodeElement(HLAEncodeStream& stream, unsigned i) const; + + const HLADataElement* getElement(unsigned index) const; + HLADataElement* getElement(unsigned index); + HLADataElement* getOrCreateElement(unsigned index); + void setElement(unsigned i, HLADataElement* value); + + class DataElementFactory : public SGReferenced { + public: + virtual ~DataElementFactory(); + virtual HLADataElement* createElement(const HLAArrayDataElement&, unsigned) = 0; + }; + + void setDataElementFactory(DataElementFactory* dataElementFactory); + DataElementFactory* getDataElementFactory(); + +private: + HLADataElement* newElement(unsigned index); + + typedef std::vector > ElementVector; + ElementVector _elementVector; + + SGSharedPtr _dataElementFactory; +}; + +// Holds an array of variants. +// Factors out common code for that use case. +class HLAVariantArrayDataElement : public HLAAbstractArrayDataElement { +public: + HLAVariantArrayDataElement(); + virtual ~HLAVariantArrayDataElement(); + + // Overwrite this from the abstract class, need some more checks here + virtual bool setDataType(const HLADataType* dataType); + + virtual bool setNumElements(unsigned size); + virtual bool decodeElement(HLADecodeStream& stream, unsigned i); + virtual unsigned getNumElements() const; + virtual bool encodeElement(HLAEncodeStream& stream, unsigned i) const; + + const HLAVariantDataElement* getElement(unsigned index) const; + HLAVariantDataElement* getElement(unsigned index); + HLAVariantDataElement* getOrCreateElement(unsigned index); + void setElement(unsigned index, HLAVariantDataElement* value); + + typedef HLAVariantDataElement::DataElementFactory AlternativeDataElementFactory; + + void setAlternativeDataElementFactory(AlternativeDataElementFactory* alternativeDataElementFactory); + AlternativeDataElementFactory* getAlternativeDataElementFactory(); + +private: + HLAVariantDataElement* newElement(); + + typedef std::vector > ElementVector; + ElementVector _elementVector; + + SGSharedPtr _alternativeDataElementFactory; +}; + +class HLAStringDataElement : public HLAAbstractArrayDataElement { +public: + HLAStringDataElement(const HLAArrayDataType* dataType = 0) : + HLAAbstractArrayDataElement(dataType) + {} + HLAStringDataElement(const HLAArrayDataType* dataType, const std::string& value) : + HLAAbstractArrayDataElement(dataType), + _value(value) + {} + const std::string& getValue() const + { return _value; } + void setValue(const std::string& value) + { _value = value; } + + virtual bool setNumElements(unsigned count) + { + _value.resize(count); + return true; + } + virtual bool decodeElement(HLADecodeStream& stream, unsigned i) + { + HLATemplateDecodeVisitor visitor(stream); + getElementDataType()->accept(visitor); + _value[i] = visitor.getValue(); + return true; + } + + virtual unsigned getNumElements() const + { + return _value.size(); + } + virtual bool encodeElement(HLAEncodeStream& stream, unsigned i) const + { + HLATemplateEncodeVisitor visitor(stream, _value[i]); + getElementDataType()->accept(visitor); + return true; + } + +private: + std::string _value; +}; + +class HLAStringData { +public: + HLAStringData() : + _value(new HLAStringDataElement(0)) + { } + HLAStringData(const std::string& value) : + _value(new HLAStringDataElement(0)) + { _value->setValue(value); } + + operator const std::string&() const + { return _value->getValue(); } + HLAStringData& operator=(const std::string& value) + { _value->setValue(value); return *this; } + + const std::string& getValue() const + { return _value->getValue(); } + void setValue(const std::string& value) + { _value->setValue(value); } + + const HLAStringDataElement* getDataElement() const + { return _value.get(); } + HLAStringDataElement* getDataElement() + { return _value.get(); } + + const HLAArrayDataType* getDataType() const + { return _value->getDataType(); } + void setDataType(const HLAArrayDataType* dataType) + { _value->setDataType(dataType); } + +private: + SGSharedPtr _value; +}; + +template +class HLAVec2DataElement : public HLAAbstractArrayDataElement { +public: + HLAVec2DataElement(const HLAArrayDataType* dataType = 0) : + HLAAbstractArrayDataElement(dataType), + _value(SGVec2::zeros()) + {} + HLAVec2DataElement(const HLAArrayDataType* dataType, const SGVec2& value) : + HLAAbstractArrayDataElement(dataType), + _value(value) + {} + const SGVec2& getValue() const + { return _value; } + void setValue(const SGVec2& value) + { _value = value; } + + virtual bool setNumElements(unsigned count) + { + for (unsigned i = 2; i < count; ++i) + _value[i] = 0; + return true; + } + virtual bool decodeElement(HLADecodeStream& stream, unsigned i) + { + if (i < 2) { + HLATemplateDecodeVisitor::value_type> visitor(stream); + getElementDataType()->accept(visitor); + _value[i] = visitor.getValue(); + } else { + HLADataTypeDecodeVisitor visitor(stream); + getElementDataType()->accept(visitor); + } + return true; + } + + virtual unsigned getNumElements() const + { + return 2; + } + virtual bool encodeElement(HLAEncodeStream& stream, unsigned i) const + { + if (i < 2) { + HLATemplateEncodeVisitor::value_type> visitor(stream, _value[i]); + getElementDataType()->accept(visitor); + } else { + HLADataTypeEncodeVisitor visitor(stream); + getElementDataType()->accept(visitor); + } + return true; + } + +private: + SGVec2 _value; +}; + +template +class HLAVec3DataElement : public HLAAbstractArrayDataElement { +public: + HLAVec3DataElement(const HLAArrayDataType* dataType = 0) : + HLAAbstractArrayDataElement(dataType), + _value(SGVec3::zeros()) + {} + HLAVec3DataElement(const HLAArrayDataType* dataType, const SGVec3& value) : + HLAAbstractArrayDataElement(dataType), + _value(value) + {} + const SGVec3& getValue() const + { return _value; } + void setValue(const SGVec3& value) + { _value = value; } + + virtual bool setNumElements(unsigned count) + { + for (unsigned i = 3; i < count; ++i) + _value[i] = 0; + return true; + } + virtual bool decodeElement(HLADecodeStream& stream, unsigned i) + { + if (i < 3) { + HLATemplateDecodeVisitor::value_type> visitor(stream); + getElementDataType()->accept(visitor); + _value[i] = visitor.getValue(); + } else { + HLADataTypeDecodeVisitor visitor(stream); + getElementDataType()->accept(visitor); + } + return true; + } + + virtual unsigned getNumElements() const + { + return 3; + } + virtual bool encodeElement(HLAEncodeStream& stream, unsigned i) const + { + if (i < 3) { + HLATemplateEncodeVisitor::value_type> visitor(stream, _value[i]); + getElementDataType()->accept(visitor); + } else { + HLADataTypeEncodeVisitor visitor(stream); + getElementDataType()->accept(visitor); + } + return true; + } + +private: + SGVec3 _value; +}; + +template +class HLAVec4DataElement : public HLAAbstractArrayDataElement { +public: + HLAVec4DataElement(const HLAArrayDataType* dataType = 0) : + HLAAbstractArrayDataElement(dataType), + _value(SGVec4::zeros()) + {} + HLAVec4DataElement(const HLAArrayDataType* dataType, const SGVec4& value) : + HLAAbstractArrayDataElement(dataType), + _value(value) + {} + const SGVec4& getValue() const + { return _value; } + void setValue(const SGVec4& value) + { _value = value; } + + virtual bool setNumElements(unsigned count) + { + for (unsigned i = 4; i < count; ++i) + _value[i] = 0; + return true; + } + virtual bool decodeElement(HLADecodeStream& stream, unsigned i) + { + if (i < 4) { + HLATemplateDecodeVisitor::value_type> visitor(stream); + getElementDataType()->accept(visitor); + _value[i] = visitor.getValue(); + } else { + HLADataTypeDecodeVisitor visitor(stream); + getElementDataType()->accept(visitor); + } + return true; + } + + virtual unsigned getNumElements() const + { + return 4; + } + virtual bool encodeElement(HLAEncodeStream& stream, unsigned i) const + { + if (i < 4) { + HLATemplateEncodeVisitor::value_type> visitor(stream, _value[i]); + getElementDataType()->accept(visitor); + } else { + HLADataTypeEncodeVisitor visitor(stream); + getElementDataType()->accept(visitor); + } + return true; + } + +private: + SGVec4 _value; +}; + +template +class HLAQuatDataElement : public HLAAbstractArrayDataElement { +public: + HLAQuatDataElement(const HLAArrayDataType* dataType = 0) : + HLAAbstractArrayDataElement(dataType), + _value(SGQuat::zeros()) + {} + HLAQuatDataElement(const HLAArrayDataType* dataType, const SGQuat& value) : + HLAAbstractArrayDataElement(dataType), + _value(value) + {} + const SGQuat& getValue() const + { return _value; } + void setValue(const SGQuat& value) + { _value = value; } + + virtual bool setNumElements(unsigned count) + { + for (unsigned i = 4; i < count; ++i) + _value[i] = 0; + return true; + } + virtual bool decodeElement(HLADecodeStream& stream, unsigned i) + { + if (i < 4) { + HLATemplateDecodeVisitor::value_type> visitor(stream); + getElementDataType()->accept(visitor); + _value[i] = visitor.getValue(); + } else { + HLADataTypeDecodeVisitor visitor(stream); + getElementDataType()->accept(visitor); + } + return true; + } + + virtual unsigned getNumElements() const + { + return 4; + } + virtual bool encodeElement(HLAEncodeStream& stream, unsigned i) const + { + if (i < 4) { + HLATemplateEncodeVisitor::value_type> visitor(stream, _value[i]); + getElementDataType()->accept(visitor); + } else { + HLADataTypeEncodeVisitor visitor(stream); + getElementDataType()->accept(visitor); + } + return true; + } + +private: + SGQuat _value; +}; + +} + +#endif diff --git a/simgear/hla/HLAArrayDataType.cxx b/simgear/hla/HLAArrayDataType.cxx new file mode 100644 index 00000000..0eac2364 --- /dev/null +++ b/simgear/hla/HLAArrayDataType.cxx @@ -0,0 +1,158 @@ +// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#include "HLAArrayDataType.hxx" + +#include "HLAArrayDataElement.hxx" + +namespace simgear { + +HLAArrayDataType::HLAArrayDataType(const std::string& name) : + HLADataType(name) +{ +} + +HLAArrayDataType::~HLAArrayDataType() +{ +} + +void +HLAArrayDataType::accept(HLADataTypeVisitor& visitor) const +{ + visitor.apply(*this); +} + +const HLAArrayDataType* +HLAArrayDataType::toArrayDataType() const +{ + return this; +} + +void +HLAArrayDataType::setElementDataType(const HLADataType* elementDataType) +{ + // FIXME this only works if we do not reset the alignment to something smaller + if (getAlignment() < elementDataType->getAlignment()) + setAlignment(elementDataType->getAlignment()); + _elementDataType = elementDataType; +} + +/////////////////////////////////////////////////////////////////////////////////// + +HLAFixedArrayDataType::HLAFixedArrayDataType(const std::string& name) : + HLAArrayDataType(name) +{ +} + +HLAFixedArrayDataType::~HLAFixedArrayDataType() +{ +} + +void +HLAFixedArrayDataType::accept(HLADataTypeVisitor& visitor) const +{ + visitor.apply(*this); +} + +bool +HLAFixedArrayDataType::decode(HLADecodeStream& stream, HLAAbstractArrayDataElement& value) const +{ + stream.alignOffsetForSize(getAlignment()); + unsigned numElements = getNumElements(); + if (!value.setNumElements(numElements)) + return false; + for (unsigned i = 0; i < numElements; ++i) + if (!value.decodeElement(stream, i)) + return false; + return true; +} + +bool +HLAFixedArrayDataType::encode(HLAEncodeStream& stream, const HLAAbstractArrayDataElement& value) const +{ + stream.alignOffsetForSize(getAlignment()); + unsigned numElementsType = getNumElements(); + unsigned numElementsValue = value.getNumElements(); + unsigned numElements = SGMisc::min(numElementsType, numElementsValue); + unsigned i = 0; + for (; i < numElements; ++i) + if (!value.encodeElement(stream, i)) + return false; + for (; i < numElementsType; ++i) { + HLADataTypeEncodeVisitor visitor(stream); + getElementDataType()->accept(visitor); + } + return true; +} + +///////////////////////////////////////////////////////////////////////////////// + +HLAVariableArrayDataType::HLAVariableArrayDataType(const std::string& name) : + HLAArrayDataType(name) +{ + setSizeDataType(new HLAUInt32BEDataType); +} + +HLAVariableArrayDataType::~HLAVariableArrayDataType() +{ +} + +void +HLAVariableArrayDataType::accept(HLADataTypeVisitor& visitor) const +{ + visitor.apply(*this); +} + +bool +HLAVariableArrayDataType::decode(HLADecodeStream& stream, HLAAbstractArrayDataElement& value) const +{ + stream.alignOffsetForSize(getAlignment()); + HLATemplateDecodeVisitor numElementsVisitor(stream); + getSizeDataType()->accept(numElementsVisitor); + unsigned numElements = numElementsVisitor.getValue(); + if (!value.setNumElements(numElements)) + return false; + for (unsigned i = 0; i < numElements; ++i) + if (!value.decodeElement(stream, i)) + return false; + return true; +} + +bool +HLAVariableArrayDataType::encode(HLAEncodeStream& stream, const HLAAbstractArrayDataElement& value) const +{ + stream.alignOffsetForSize(getAlignment()); + unsigned numElements = value.getNumElements(); + HLATemplateEncodeVisitor numElementsVisitor(stream, numElements); + getSizeDataType()->accept(numElementsVisitor); + for (unsigned i = 0; i < numElements; ++i) + if (!value.encodeElement(stream, i)) + return false; + return true; +} + +void +HLAVariableArrayDataType::setSizeDataType(const HLADataType* sizeDataType) +{ + // FIXME this only works if we do not reset the alignment to something smaller + if (getAlignment() < sizeDataType->getAlignment()) + setAlignment(sizeDataType->getAlignment()); + _sizeDataType = sizeDataType; + // setAlignment(SGMisc::max(_sizeDataType->getAlignment(), _elementDataType->getAlignment()); +} + +} // namespace simgear diff --git a/simgear/hla/HLAArrayDataType.hxx b/simgear/hla/HLAArrayDataType.hxx new file mode 100644 index 00000000..eac645b4 --- /dev/null +++ b/simgear/hla/HLAArrayDataType.hxx @@ -0,0 +1,88 @@ +// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#ifndef HLAArrayDataType_hxx +#define HLAArrayDataType_hxx + +#include +#include +#include "HLADataType.hxx" + +namespace simgear { + +class HLAAbstractArrayDataElement; + +class HLAArrayDataType : public HLADataType { +public: + HLAArrayDataType(const std::string& name = "HLAArrayDataType"); + virtual ~HLAArrayDataType(); + + virtual void accept(HLADataTypeVisitor& visitor) const; + + virtual const HLAArrayDataType* toArrayDataType() const; + + virtual bool decode(HLADecodeStream& stream, HLAAbstractArrayDataElement& value) const = 0; + virtual bool encode(HLAEncodeStream& stream, const HLAAbstractArrayDataElement& value) const = 0; + + void setElementDataType(const HLADataType* elementDataType); + const HLADataType* getElementDataType() const + { return _elementDataType.get(); } + +private: + SGSharedPtr _elementDataType; +}; + +class HLAFixedArrayDataType : public HLAArrayDataType { +public: + HLAFixedArrayDataType(const std::string& name = "HLAFixedArrayDataType"); + virtual ~HLAFixedArrayDataType(); + + virtual void accept(HLADataTypeVisitor& visitor) const; + + virtual bool decode(HLADecodeStream& stream, HLAAbstractArrayDataElement& value) const; + virtual bool encode(HLAEncodeStream& stream, const HLAAbstractArrayDataElement& value) const; + + void setNumElements(unsigned numElements) + { _numElements = numElements; } + unsigned getNumElements() const + { return _numElements; } + +private: + unsigned _numElements; +}; + +class HLAVariableArrayDataType : public HLAArrayDataType { +public: + HLAVariableArrayDataType(const std::string& name = "HLAVariableArrayDataType"); + virtual ~HLAVariableArrayDataType(); + + virtual void accept(HLADataTypeVisitor& visitor) const; + + virtual bool decode(HLADecodeStream& stream, HLAAbstractArrayDataElement& value) const; + virtual bool encode(HLAEncodeStream& stream, const HLAAbstractArrayDataElement& value) const; + + void setSizeDataType(const HLADataType* sizeDataType); + const HLADataType* getSizeDataType() const + { return _sizeDataType.get(); } + +private: + SGSharedPtr _sizeDataType; +}; + +} // namespace simgear + +#endif diff --git a/simgear/hla/HLABasicDataElement.cxx b/simgear/hla/HLABasicDataElement.cxx new file mode 100644 index 00000000..69401104 --- /dev/null +++ b/simgear/hla/HLABasicDataElement.cxx @@ -0,0 +1,132 @@ +// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#include "HLABasicDataElement.hxx" + +#include "HLADataTypeVisitor.hxx" + +namespace simgear { + +HLABasicDataElement::HLABasicDataElement(const HLABasicDataType* dataType) : + _dataType(dataType) +{ +} + +HLABasicDataElement::~HLABasicDataElement() +{ +} + +const HLABasicDataType* +HLABasicDataElement::getDataType() const +{ + return _dataType.get(); +} + +bool +HLABasicDataElement::setDataType(const HLADataType* dataType) +{ + const HLABasicDataType* scalarDataType = dynamic_cast(dataType); + if (!scalarDataType) { + SG_LOG(SG_NETWORK, SG_WARN, "HLABasicDataType: unable to set data type!"); + return false; + } + setDataType(scalarDataType); + return true; +} + +void +HLABasicDataElement::setDataType(const HLABasicDataType* dataType) +{ + _dataType = dataType; +} + +#define IMPLEMENT_TYPED_HLA_BASIC_DATA_ELEMENT(type, ctype) \ +HLAAbstract##type##DataElement::HLAAbstract##type##DataElement(const HLABasicDataType* dataType) :\ + HLABasicDataElement(dataType) \ +{ \ +} \ + \ +HLAAbstract##type##DataElement::~HLAAbstract##type##DataElement() \ +{ \ +} \ + \ +bool \ +HLAAbstract##type##DataElement::encode(HLAEncodeStream& stream) const \ +{ \ + if (!_dataType.valid()) \ + return false; \ + HLATemplateEncodeVisitor visitor(stream, getValue()); \ + _dataType->accept(visitor); \ + return true; \ +} \ + \ +bool \ +HLAAbstract##type##DataElement::decode(HLADecodeStream& stream) \ +{ \ + if (!_dataType.valid()) \ + return false; \ + HLATemplateDecodeVisitor visitor(stream); \ + _dataType->accept(visitor); \ + setValue(visitor.getValue()); \ + return true; \ +} \ + \ +HLA##type##DataElement::HLA##type##DataElement(const HLABasicDataType* dataType) : \ + HLAAbstract##type##DataElement(dataType), \ + _value(0) \ +{ \ +} \ + \ +HLA##type##DataElement::HLA##type##DataElement(const HLABasicDataType* dataType, \ + const ctype& value) : \ + HLAAbstract##type##DataElement(dataType), \ + _value(value) \ +{ \ +} \ + \ +HLA##type##DataElement::~HLA##type##DataElement() \ +{ \ +} \ + \ +ctype \ +HLA##type##DataElement::getValue() const \ +{ \ + return _value; \ +} \ + \ +void \ +HLA##type##DataElement::setValue(ctype value) \ +{ \ + _value = value; \ +} + +IMPLEMENT_TYPED_HLA_BASIC_DATA_ELEMENT(Char, char); +IMPLEMENT_TYPED_HLA_BASIC_DATA_ELEMENT(WChar, wchar_t); +IMPLEMENT_TYPED_HLA_BASIC_DATA_ELEMENT(SChar, signed char); +IMPLEMENT_TYPED_HLA_BASIC_DATA_ELEMENT(UChar, unsigned char); +IMPLEMENT_TYPED_HLA_BASIC_DATA_ELEMENT(Short, short); +IMPLEMENT_TYPED_HLA_BASIC_DATA_ELEMENT(UShort, unsigned short); +IMPLEMENT_TYPED_HLA_BASIC_DATA_ELEMENT(Int, int); +IMPLEMENT_TYPED_HLA_BASIC_DATA_ELEMENT(UInt, unsigned int); +IMPLEMENT_TYPED_HLA_BASIC_DATA_ELEMENT(Long, long); +IMPLEMENT_TYPED_HLA_BASIC_DATA_ELEMENT(ULong, unsigned long); +IMPLEMENT_TYPED_HLA_BASIC_DATA_ELEMENT(Float, float); +IMPLEMENT_TYPED_HLA_BASIC_DATA_ELEMENT(Double, double); + +#undef IMPLEMENT_TYPED_HLA_BASIC_DATA_ELEMENT + +} diff --git a/simgear/hla/HLABasicDataElement.hxx b/simgear/hla/HLABasicDataElement.hxx new file mode 100644 index 00000000..e38499df --- /dev/null +++ b/simgear/hla/HLABasicDataElement.hxx @@ -0,0 +1,108 @@ +// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#ifndef HLABasicDataElement_hxx +#define HLABasicDataElement_hxx + +#include "HLABasicDataType.hxx" +#include "HLADataElement.hxx" + +namespace simgear { + +class HLABasicDataElement : public HLADataElement { +public: + HLABasicDataElement(const HLABasicDataType* dataType); + virtual ~HLABasicDataElement(); + + virtual const HLABasicDataType* getDataType() const; + virtual bool setDataType(const HLADataType* dataType); + void setDataType(const HLABasicDataType* dataType); + +protected: + SGSharedPtr _dataType; +}; + +#define TYPED_HLA_BASIC_DATA_ELEMENT(type, ctype) \ +class HLAAbstract##type##DataElement : public HLABasicDataElement { \ +public: \ + HLAAbstract##type##DataElement(const HLABasicDataType* dataType = 0); \ + virtual ~HLAAbstract##type##DataElement(); \ + virtual bool encode(HLAEncodeStream& stream) const; \ + virtual bool decode(HLADecodeStream& stream); \ + \ + virtual ctype getValue() const = 0; \ + virtual void setValue(ctype) = 0; \ +}; \ +class HLA##type##DataElement : public HLAAbstract##type##DataElement { \ +public: \ + HLA##type##DataElement(const HLABasicDataType* dataType = 0); \ + HLA##type##DataElement(const HLABasicDataType* dataType, \ + const ctype& value); \ + virtual ~HLA##type##DataElement(); \ + virtual ctype getValue() const; \ + virtual void setValue(ctype value); \ +private: \ + ctype _value; \ +}; \ +class HLA##type##Data { \ +public: \ + HLA##type##Data() : \ + _value(new HLA##type##DataElement(0)) \ + { } \ + HLA##type##Data(const ctype& value) : \ + _value(new HLA##type##DataElement(0, value)) \ + { } \ + operator ctype() const \ + { return _value->getValue(); } \ + HLA##type##Data& operator=(const ctype& value) \ + { _value->setValue(value); return *this; } \ + ctype getValue() const \ + { return _value->getValue(); } \ + void setValue(const ctype& value) \ + { _value->setValue(value); } \ + const HLA##type##DataElement* getDataElement() const \ + { return _value.get(); } \ + HLA##type##DataElement* getDataElement() \ + { return _value.get(); } \ + const HLABasicDataType* getDataType() const \ + { return _value->getDataType(); } \ + void setDataType(const HLABasicDataType* dataType) \ + { _value->setDataType(dataType); } \ + \ +private: \ + SGSharedPtr _value; \ +}; + + +TYPED_HLA_BASIC_DATA_ELEMENT(Char, char); +TYPED_HLA_BASIC_DATA_ELEMENT(WChar, wchar_t); +TYPED_HLA_BASIC_DATA_ELEMENT(SChar, signed char); +TYPED_HLA_BASIC_DATA_ELEMENT(UChar, unsigned char); +TYPED_HLA_BASIC_DATA_ELEMENT(Short, short); +TYPED_HLA_BASIC_DATA_ELEMENT(UShort, unsigned short); +TYPED_HLA_BASIC_DATA_ELEMENT(Int, int); +TYPED_HLA_BASIC_DATA_ELEMENT(UInt, unsigned int); +TYPED_HLA_BASIC_DATA_ELEMENT(Long, long); +TYPED_HLA_BASIC_DATA_ELEMENT(ULong, unsigned long); +TYPED_HLA_BASIC_DATA_ELEMENT(Float, float); +TYPED_HLA_BASIC_DATA_ELEMENT(Double, double); + +#undef TYPED_HLA_BASIC_DATA_ELEMENT + +} + +#endif diff --git a/simgear/hla/HLABasicDataType.cxx b/simgear/hla/HLABasicDataType.cxx new file mode 100644 index 00000000..106e8158 --- /dev/null +++ b/simgear/hla/HLABasicDataType.cxx @@ -0,0 +1,170 @@ +// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#include "HLABasicDataType.hxx" + +#include "HLADataType.hxx" +#include "HLADataTypeVisitor.hxx" + +namespace simgear { + +HLABasicDataType::HLABasicDataType(const std::string& name) : + HLADataType(name) +{ +} + +HLABasicDataType::~HLABasicDataType() +{ +} + +void +HLABasicDataType::accept(HLADataTypeVisitor& visitor) const +{ + visitor.apply(*this); +} + +const HLABasicDataType* +HLABasicDataType::toBasicDataType() const +{ + return this; +} + +////////////////////////////////////////////////////////////////////////////// + +HLAInt8DataType::HLAInt8DataType(const std::string& name) : + HLABasicDataType(name) +{ + setAlignment(sizeof(int8_t)); +} + +HLAInt8DataType::~HLAInt8DataType() +{ +} + +void +HLAInt8DataType::accept(HLADataTypeVisitor& visitor) const +{ + visitor.apply(*this); +} + +////////////////////////////////////////////////////////////////////////////// + +HLAUInt8DataType::HLAUInt8DataType(const std::string& name) : + HLABasicDataType(name) +{ + setAlignment(sizeof(uint8_t)); +} + +HLAUInt8DataType::~HLAUInt8DataType() +{ +} + +void +HLAUInt8DataType::accept(HLADataTypeVisitor& visitor) const +{ + visitor.apply(*this); +} + +////////////////////////////////////////////////////////////////////////////// + +#define BASIC_DATATYPE_IMPLEMENTATION(type, name) \ +HLA##name##DataType::HLA##name##DataType(const std::string& name) : \ + HLABasicDataType(name) \ +{ \ + setAlignment(sizeof(type)); \ +} \ + \ +HLA##name##DataType::~HLA##name##DataType() \ +{ \ +} \ + \ +void \ +HLA##name##DataType::accept(HLADataTypeVisitor& visitor) const \ +{ \ + visitor.apply(*this); \ +} \ + \ + \ + \ +HLA##name##LEDataType::HLA##name##LEDataType(const std::string& name) : \ + HLA##name##DataType(name) \ +{ \ +} \ + \ +HLA##name##LEDataType::~HLA##name##LEDataType() \ +{ \ +} \ + \ +bool \ +HLA##name##LEDataType::decode(HLADecodeStream& stream, \ + type& value) const \ +{ \ + if (!stream.alignOffsetForSize(getAlignment())) \ + return false; \ + return stream.decode##name##LE(value); \ +} \ + \ +bool \ +HLA##name##LEDataType::encode(HLAEncodeStream& stream, \ + const type& value) const \ +{ \ + if (!stream.alignOffsetForSize(getAlignment())) \ + return false; \ + return stream.encode##name##LE(value); \ +} \ + \ + \ + \ +HLA##name##BEDataType::HLA##name##BEDataType(const std::string& name) : \ + HLA##name##DataType(name) \ +{ \ +} \ + \ +HLA##name##BEDataType::~HLA##name##BEDataType() \ +{ \ +} \ + \ +bool \ +HLA##name##BEDataType::decode(HLADecodeStream& stream, \ + type& value) const \ +{ \ + if (!stream.alignOffsetForSize(getAlignment())) \ + return false; \ + return stream.decode##name##BE(value); \ +} \ + \ +bool \ +HLA##name##BEDataType::encode(HLAEncodeStream& stream, \ + const type& value) const \ +{ \ + if (!stream.alignOffsetForSize(getAlignment())) \ + return false; \ + return stream.encode##name##BE(value); \ +} + +BASIC_DATATYPE_IMPLEMENTATION(int16_t, Int16) +BASIC_DATATYPE_IMPLEMENTATION(uint16_t, UInt16) +BASIC_DATATYPE_IMPLEMENTATION(int32_t, Int32) +BASIC_DATATYPE_IMPLEMENTATION(uint32_t, UInt32) +BASIC_DATATYPE_IMPLEMENTATION(int64_t, Int64) +BASIC_DATATYPE_IMPLEMENTATION(uint64_t, UInt64) +BASIC_DATATYPE_IMPLEMENTATION(float, Float32) +BASIC_DATATYPE_IMPLEMENTATION(double, Float64) + +#undef BASIC_DATATYPE_IMPLEMENTATION + +} // namespace simgear diff --git a/simgear/hla/HLABasicDataType.hxx b/simgear/hla/HLABasicDataType.hxx new file mode 100644 index 00000000..60f1ba7d --- /dev/null +++ b/simgear/hla/HLABasicDataType.hxx @@ -0,0 +1,155 @@ +// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#ifndef HLABasicDataType_hxx +#define HLABasicDataType_hxx + +#include +#include "HLADataType.hxx" + +namespace simgear { + +class HLABasicDataType : public HLADataType { +public: + virtual ~HLABasicDataType(); + virtual void accept(HLADataTypeVisitor& visitor) const; + + virtual const HLABasicDataType* toBasicDataType() const; + +protected: + HLABasicDataType(const std::string& name); +}; + +class HLAInt8DataType : public HLABasicDataType { +public: + HLAInt8DataType(const std::string& name = "HLAInt8DataType"); + virtual ~HLAInt8DataType(); + + virtual void accept(HLADataTypeVisitor& visitor) const; + + bool skip(HLADecodeStream& stream) const + { + if (!stream.alignOffsetForSize(getAlignment())) + return false; + return stream.skip(1); + } + bool skip(HLAEncodeStream& stream) const + { + if (!stream.alignOffsetForSize(getAlignment())) + return false; + return stream.skip(1); + } + bool decode(HLADecodeStream& stream, int8_t& value) const + { + if (!stream.alignOffsetForSize(getAlignment())) + return false; + return stream.decodeInt8(value); + } + bool encode(HLAEncodeStream& stream, const int8_t& value) const + { + if (!stream.alignOffsetForSize(getAlignment())) + return false; + return stream.encodeInt8(value); + } +}; + +class HLAUInt8DataType : public HLABasicDataType { +public: + HLAUInt8DataType(const std::string& name = "HLAUInt8DataType"); + virtual ~HLAUInt8DataType(); + + virtual void accept(HLADataTypeVisitor& visitor) const; + + bool skip(HLADecodeStream& stream) const + { + if (!stream.alignOffsetForSize(getAlignment())) + return false; + return stream.skip(1); + } + bool skip(HLAEncodeStream& stream) const + { + if (!stream.alignOffsetForSize(getAlignment())) + return false; + return stream.skip(1); + } + bool decode(HLADecodeStream& stream, uint8_t& value) const + { + if (!stream.alignOffsetForSize(getAlignment())) + return false; + return stream.decodeUInt8(value); + } + bool encode(HLAEncodeStream& stream, const uint8_t& value) const + { + if (!stream.alignOffsetForSize(getAlignment())) + return false; + return stream.encodeUInt8(value); + } +}; + +#define BASIC_DATATYPE_IMPLEMENTATION(type, name) \ +class HLA##name##DataType : public HLABasicDataType { \ +public: \ + virtual ~HLA##name##DataType(); \ + \ + virtual void accept(HLADataTypeVisitor& visitor) const; \ + \ + bool skip(HLADecodeStream& stream) const \ + { \ + if (!stream.alignOffsetForSize(getAlignment())) \ + return false; \ + return stream.skip(sizeof(type)); \ + } \ + bool skip(HLAEncodeStream& stream) const \ + { \ + if (!stream.alignOffsetForSize(getAlignment())) \ + return false; \ + return stream.skip(sizeof(type)); \ + } \ + virtual bool decode(HLADecodeStream& stream, type& value) const = 0; \ + virtual bool encode(HLAEncodeStream& stream, const type& value) const = 0;\ +protected: \ + HLA##name##DataType(const std::string& name); \ +}; \ +class HLA##name##LEDataType : public HLA##name##DataType { \ +public: \ + HLA##name##LEDataType(const std::string& name = "HLA" #name "LEDataType");\ + virtual ~HLA##name##LEDataType(); \ + virtual bool decode(HLADecodeStream& stream, type& value) const; \ + virtual bool encode(HLAEncodeStream& stream, const type& value) const; \ +}; \ +class HLA##name##BEDataType : public HLA##name##DataType { \ +public: \ + HLA##name##BEDataType(const std::string& name = "HLA" #name "BEDataType");\ + virtual ~HLA##name##BEDataType(); \ + virtual bool decode(HLADecodeStream& stream, type& value) const; \ + virtual bool encode(HLAEncodeStream& stream, const type& value) const; \ +}; + +BASIC_DATATYPE_IMPLEMENTATION(int16_t, Int16) +BASIC_DATATYPE_IMPLEMENTATION(uint16_t, UInt16) +BASIC_DATATYPE_IMPLEMENTATION(int32_t, Int32) +BASIC_DATATYPE_IMPLEMENTATION(uint32_t, UInt32) +BASIC_DATATYPE_IMPLEMENTATION(int64_t, Int64) +BASIC_DATATYPE_IMPLEMENTATION(uint64_t, UInt64) +BASIC_DATATYPE_IMPLEMENTATION(float, Float32) +BASIC_DATATYPE_IMPLEMENTATION(double, Float64) + +#undef BASIC_DATATYPE_IMPLEMENTATION + +} // namespace simgear + +#endif diff --git a/simgear/hla/HLADataElement.cxx b/simgear/hla/HLADataElement.cxx new file mode 100644 index 00000000..ae981128 --- /dev/null +++ b/simgear/hla/HLADataElement.cxx @@ -0,0 +1,187 @@ +// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#include "HLADataElement.hxx" + +#include + +namespace simgear { + +HLADataElement::PathElement::Data::~Data() +{ +} + +const HLADataElement::PathElement::FieldData* +HLADataElement::PathElement::Data::toFieldData() const +{ + return 0; +} + +const HLADataElement::PathElement::IndexData* +HLADataElement::PathElement::Data::toIndexData() const +{ + return 0; +} + +HLADataElement::PathElement::FieldData::FieldData(const std::string& name) : + _name(name) +{ +} + +HLADataElement::PathElement::FieldData::~FieldData() +{ +} + +const HLADataElement::PathElement::FieldData* +HLADataElement::PathElement::FieldData::toFieldData() const +{ + return this; +} + +bool +HLADataElement::PathElement::FieldData::less(const Data* data) const +{ + const FieldData* fieldData = data->toFieldData(); + // IndexData is allways smaller than FieldData + if (!fieldData) + return false; + return _name < fieldData->_name; +} + +bool +HLADataElement::PathElement::FieldData::equal(const Data* data) const +{ + const FieldData* fieldData = data->toFieldData(); + // IndexData is allways smaller than FieldData + if (!fieldData) + return false; + return _name == fieldData->_name; +} + +void +HLADataElement::PathElement::FieldData::append(std::string& s) const +{ + s.append(1, std::string::value_type('.')); + s.append(_name); +} + +HLADataElement::PathElement::IndexData::IndexData(unsigned index) : + _index(index) +{ +} + +HLADataElement::PathElement::IndexData::~IndexData() +{ +} + +const HLADataElement::PathElement::IndexData* +HLADataElement::PathElement::IndexData::toIndexData() const +{ + return this; +} + +bool +HLADataElement::PathElement::IndexData::less(const Data* data) const +{ + const IndexData* indexData = data->toIndexData(); + // IndexData is allways smaller than FieldData + if (!indexData) + return true; + return _index < indexData->_index; +} + +bool +HLADataElement::PathElement::IndexData::equal(const Data* data) const +{ + const IndexData* indexData = data->toIndexData(); + // IndexData is allways smaller than FieldData + if (!indexData) + return false; + return _index == indexData->_index; +} + +void +HLADataElement::PathElement::IndexData::append(std::string& s) const +{ + s.append(1, std::string::value_type('[')); + unsigned value = _index; + do { + s.append(1, std::string::value_type('0' + value % 10)); + } while (value /= 10); + s.append(1, std::string::value_type(']')); +} + +HLADataElement::~HLADataElement() +{ +} + +std::string +HLADataElement::toString(const Path& path) +{ + std::string s; + for (Path::const_iterator i = path.begin(); i != path.end(); ++i) + i->append(s); + return s; +} + +HLADataElement::AttributePathPair +HLADataElement::toAttributePathPair(const std::string& s) +{ + Path path; + // Skip the initial attribute name if given + std::string::size_type i = s.find_first_of("[."); + std::string attribute = s.substr(0, i); + while (i < s.size()) { + if (s[i] == '[') { + ++i; + unsigned index = 0; + while (i < s.size()) { + if (s[i] == ']') + break; + unsigned v = s[i] - '0'; + // Error, no number + if (10 <= v) { + SG_LOG(SG_NETWORK, SG_WARN, "HLADataElement: invalid character in array subscript for \"" + << s << "\" at \"" << attribute << toString(path) << "\"!"); + return AttributePathPair(); + } + index *= 10; + index += v; + ++i; + } + path.push_back(index); + ++i; + continue; + } + if (s[i] == '.') { + // Error, . cannot be last + if (s.size() <= ++i) { + SG_LOG(SG_NETWORK, SG_WARN, "HLADataElement: invalid terminating '.' for \"" + << s << "\"!"); + return AttributePathPair(); + } + std::string::size_type e = s.find_first_of("[.", i); + path.push_back(s.substr(i, e - i)); + i = e; + continue; + } + } + + return AttributePathPair(attribute, path); +} + +} diff --git a/simgear/hla/HLADataElement.hxx b/simgear/hla/HLADataElement.hxx new file mode 100644 index 00000000..284422b8 --- /dev/null +++ b/simgear/hla/HLADataElement.hxx @@ -0,0 +1,217 @@ +// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#ifndef HLADataElement_hxx +#define HLADataElement_hxx + +#include +#include +#include +#include +#include +#include "RTIData.hxx" +#include "HLADataType.hxx" + +class SGTimeStamp; + +namespace simgear { + +class HLADataElement : public SGReferenced { +public: + virtual ~HLADataElement(); + + virtual bool encode(HLAEncodeStream& stream) const = 0; + virtual bool decode(HLADecodeStream& stream) = 0; + + virtual const HLADataType* getDataType() const = 0; + virtual bool setDataType(const HLADataType* dataType) = 0; + + // Container for the timestamp the originating attribute was last updated for + // class TimeStamp : public SGReferenced { + // public: + // const SGTimeStamp& getTimeStamp() const + // { return _timeStamp; } + // void setTimeStamp(const SGTimeStamp& timeStamp) + // { _timeStamp = timeStamp; } + // private: + // SGTimeStamp _timeStamp; + // }; + + // const TimeStamp* getTimeStamp() const + // { return _timeStamp.get(); } + // void setTimeStamp(const TimeStamp* timeStamp) + // { _timeStamp = timeStamp; } + + // struct ChangeCount : public SGReferenced { + // ChangeCount() : _value(0) {} + // unsigned _value; + // }; + // SGSharedPtr _changeCount; + // unsigned getChangeCount() const + // { + // // If we don't have return allways the same + // if (!_changeCount.valid()) + // return 0; + // return _changeCount->_value; + // } + + /// HLADataElements could be identified by path + /// These paths are composed of structure field names and array indices in the + /// order they appear while walking to the data element. + /// So provide here some tool functions to access these elements + /// Note that these functions are relatively expensive in execution time. + /// So only use them once at object creation time and store direct references to the values + + class PathElement { + public: + PathElement(unsigned index) : _data(new IndexData(index)) {} + PathElement(const std::string& name) : _data(new FieldData(name)) {} + + bool isFieldValue() const + { return _data->toFieldData(); } + bool isIndexValue() const + { return _data->toIndexData(); } + + unsigned getIndexValue() const + { + const IndexData* indexData = _data->toIndexData(); + if (!indexData) + return ~unsigned(0); + return indexData->_index; + } + + std::string getFieldValue() const + { + const FieldData* fieldData = _data->toFieldData(); + if (!fieldData) + return std::string(); + return fieldData->_name; + } + + // Want to be able to use that in std::map and std::set + bool operator<(const PathElement& pathElement) const + { return _data->less(pathElement._data.get()); } + bool operator==(const PathElement& pathElement) const + { return _data->equal(pathElement._data.get()); } + + void append(std::string& s) const + { _data->append(s); } + + private: + struct FieldData; + struct IndexData; + struct Data : public SGReferenced { + virtual ~Data(); + virtual const FieldData* toFieldData() const; + virtual const IndexData* toIndexData() const; + virtual bool less(const Data*) const = 0; + virtual bool equal(const Data*) const = 0; + virtual void append(std::string&) const = 0; + }; + struct FieldData : public Data { + FieldData(const std::string& name); + virtual ~FieldData(); + virtual const FieldData* toFieldData() const; + virtual bool less(const Data* data) const; + virtual bool equal(const Data* data) const; + virtual void append(std::string& s) const; + std::string _name; + }; + struct IndexData : public Data { + IndexData(unsigned index); + virtual ~IndexData(); + virtual const IndexData* toIndexData() const; + virtual bool less(const Data* data) const; + virtual bool equal(const Data* data) const; + virtual void append(std::string& s) const; + unsigned _index; + }; + + SGSharedPtr _data; + }; + typedef std::list Path; + typedef std::pair AttributePathPair; + typedef std::pair IndexPathPair; + + static std::string toString(const Path& path); + static std::string toString(const AttributePathPair& path) + { return path.first + toString(path.second); } + static AttributePathPair toAttributePathPair(const std::string& s); + static Path toPath(const std::string& s) + { return toAttributePathPair(s).second; } + +private: + // SGSharedPtr _timeStamp; +}; + +class HLADataElementProvider { +public: + class AbstractProvider : public SGReferenced { + public: + virtual ~AbstractProvider() { } + virtual HLADataElement* getDataElement(const HLADataElement::Path& path) = 0; + // virtual HLADataElement* getDataElement(const HLADataElement::Path& path, const HLADataType* dataType) + // { + // SGSharedPtr dataElement = getDataElement(path); + // if (!dataElement.valid()) + // return 0; + // if (!dataElement->setDataType(dataType)) + // return 0; + // return dataElement.release(); + // } + }; + + HLADataElementProvider() + { } + HLADataElementProvider(HLADataElement* dataElement) : + _provider(new ConcreteProvider(dataElement)) + { } + HLADataElementProvider(const SGSharedPtr& dataElement) : + _provider(new ConcreteProvider(dataElement)) + { } + HLADataElementProvider(AbstractProvider* provider) : + _provider(provider) + { } + + HLADataElement* getDataElement(const HLADataElement::Path& path) const + { + if (!_provider.valid()) + return 0; + return _provider->getDataElement(path); + } + +private: + class ConcreteProvider : public AbstractProvider { + public: + ConcreteProvider(const SGSharedPtr& dataElement) : + _dataElement(dataElement) + { } + virtual HLADataElement* getDataElement(const HLADataElement::Path&) + { return _dataElement.get(); } + private: + SGSharedPtr _dataElement; + }; + + SGSharedPtr _provider; +}; + +typedef std::map HLAPathElementMap; +typedef std::map HLAAttributePathElementMap; + +} + +#endif diff --git a/simgear/hla/HLADataType.cxx b/simgear/hla/HLADataType.cxx new file mode 100644 index 00000000..b22fb218 --- /dev/null +++ b/simgear/hla/HLADataType.cxx @@ -0,0 +1,104 @@ +// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#include "HLADataType.hxx" + +#include "HLADataElement.hxx" +#include "HLADataTypeVisitor.hxx" + +namespace simgear { + +HLADataType::HLADataType(const std::string& name, unsigned alignment) : + _name(name), + _alignment(1) +{ + setAlignment(alignment); +} + +HLADataType::~HLADataType() +{ +} + +void +HLADataType::accept(HLADataTypeVisitor& visitor) const +{ + visitor.apply(*this); +} + +const HLADataTypeReference* +HLADataType::toDataTypeReference() const +{ + return 0; +} + +const HLABasicDataType* +HLADataType::toBasicDataType() const +{ + return 0; +} + +const HLAArrayDataType* +HLADataType::toArrayDataType() const +{ + return 0; +} + +const HLAEnumeratedDataType* +HLADataType::toEnumeratedDataType() const +{ + return 0; +} + +const HLAFixedRecordDataType* +HLADataType::toFixedRecordDataType() const +{ + return 0; +} + +const HLAVariantDataType* +HLADataType::toVariantDataType() const +{ + return 0; +} + +void +HLADataType::setAlignment(unsigned alignment) +{ + /// FIXME: more checks + if (alignment == 0) + _alignment = 1; + else + _alignment = alignment; +} + +HLADataTypeReference::~HLADataTypeReference() +{ +} + +void +HLADataTypeReference::accept(HLADataTypeVisitor& visitor) const +{ + visitor.apply(*this); +} + +const HLADataTypeReference* +HLADataTypeReference::toDataTypeReference() const +{ + return this; +} + +} diff --git a/simgear/hla/HLADataType.hxx b/simgear/hla/HLADataType.hxx new file mode 100644 index 00000000..23fb5070 --- /dev/null +++ b/simgear/hla/HLADataType.hxx @@ -0,0 +1,99 @@ +// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#ifndef HLADataType_hxx +#define HLADataType_hxx + +#include +#include +#include +#include "RTIData.hxx" + +namespace simgear { + +class HLADataTypeVisitor; + +class HLADataTypeReference; +class HLABasicDataType; +class HLAArrayDataType; +class HLAEnumeratedDataType; +class HLAFixedRecordDataType; +class HLAVariantDataType; + +enum HLAUpdateType { + HLAStaticUpdate, + HLAPeriodicUpdate, + HLAConditionalUpdate, + HLAUndefinedUpdate +}; + +class HLADataType : public SGWeakReferenced { +public: + virtual ~HLADataType(); + + const std::string& getName() const + { return _name; } + + const std::string& getSemantics() const + { return _semantics; } + void setSemantics(const std::string& semantics) + { _semantics = semantics; } + + unsigned getAlignment() const + { return _alignment; } + + virtual void accept(HLADataTypeVisitor& visitor) const; + + virtual const HLADataTypeReference* toDataTypeReference() const; + virtual const HLABasicDataType* toBasicDataType() const; + virtual const HLAArrayDataType* toArrayDataType() const; + virtual const HLAEnumeratedDataType* toEnumeratedDataType() const; + virtual const HLAFixedRecordDataType* toFixedRecordDataType() const; + virtual const HLAVariantDataType* toVariantDataType() const; + +protected: + HLADataType(const std::string& name, unsigned alignment = 1); + void setAlignment(unsigned alignment); + +private: + std::string _name; + std::string _semantics; + unsigned _alignment; +}; + +// Weak reference to a data type. Used to implement self referencing data types +class HLADataTypeReference : public HLADataType { +public: + HLADataTypeReference(const SGSharedPtr& dataType) : + HLADataType(dataType->getName(), dataType->getAlignment()), + _dataType(dataType) + { } + virtual ~HLADataTypeReference(); + + SGSharedPtr getDataType() const + { return _dataType.lock(); } + + virtual void accept(HLADataTypeVisitor& visitor) const; + virtual const HLADataTypeReference* toDataTypeReference() const; + +private: + SGWeakPtr _dataType; +}; + +} // namespace simgear + +#endif diff --git a/simgear/hla/HLADataTypeVisitor.hxx b/simgear/hla/HLADataTypeVisitor.hxx new file mode 100644 index 00000000..d3cd9b22 --- /dev/null +++ b/simgear/hla/HLADataTypeVisitor.hxx @@ -0,0 +1,634 @@ +// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#ifndef HLADataTypeVisitor_hxx +#define HLADataTypeVisitor_hxx + +#include +#include +#include +#include +#include "HLAArrayDataType.hxx" +#include "HLABasicDataType.hxx" +#include "HLADataTypeVisitor.hxx" +#include "HLAEnumeratedDataType.hxx" +#include "HLAFixedRecordDataType.hxx" +#include "HLAVariantDataType.hxx" + +namespace simgear { + +class HLADataTypeVisitor { +public: + virtual ~HLADataTypeVisitor() {} + + virtual void apply(const HLADataType& dataType) + { } + + virtual void apply(const HLADataTypeReference& dataType) + { + SGSharedPtr dataTypeReference = dataType.getDataType(); + if (!dataTypeReference.valid()) { + SG_LOG(SG_NETWORK, SG_WARN, "HLADataTypeReference weak reference vanished!"); + return; + } + dataTypeReference->accept(*this); + } + + virtual void apply(const HLABasicDataType& dataType) + { apply(static_cast(dataType)); } + virtual void apply(const HLAInt8DataType& dataType) + { apply(static_cast(dataType)); } + virtual void apply(const HLAUInt8DataType& dataType) + { apply(static_cast(dataType)); } + virtual void apply(const HLAInt16DataType& dataType) + { apply(static_cast(dataType)); } + virtual void apply(const HLAUInt16DataType& dataType) + { apply(static_cast(dataType)); } + virtual void apply(const HLAInt32DataType& dataType) + { apply(static_cast(dataType)); } + virtual void apply(const HLAUInt32DataType& dataType) + { apply(static_cast(dataType)); } + virtual void apply(const HLAInt64DataType& dataType) + { apply(static_cast(dataType)); } + virtual void apply(const HLAUInt64DataType& dataType) + { apply(static_cast(dataType)); } + virtual void apply(const HLAFloat32DataType& dataType) + { apply(static_cast(dataType)); } + virtual void apply(const HLAFloat64DataType& dataType) + { apply(static_cast(dataType)); } + + virtual void apply(const HLAArrayDataType& dataType) + { apply(static_cast(dataType)); } + virtual void apply(const HLAFixedArrayDataType& dataType) + { apply(static_cast(dataType)); } + virtual void apply(const HLAVariableArrayDataType& dataType) + { apply(static_cast(dataType)); } + + virtual void apply(const HLAEnumeratedDataType& dataType) + { apply(static_cast(dataType)); } + + virtual void apply(const HLAFixedRecordDataType& dataType) + { apply(static_cast(dataType)); } + + virtual void apply(const HLAVariantDataType& dataType) + { apply(static_cast(dataType)); } +}; + +/// Walks the datatype tree and checks if it is completely defined +class HLADataTypeCheckVisitor : public HLADataTypeVisitor { +public: + HLADataTypeCheckVisitor() : _valid(true) {} + + bool valid() const { return _valid; } + + virtual void apply(const HLAInt8DataType& dataType) { } + virtual void apply(const HLAUInt8DataType& dataType) { } + virtual void apply(const HLAInt16DataType& dataType) { } + virtual void apply(const HLAUInt16DataType& dataType) { } + virtual void apply(const HLAInt32DataType& dataType) { } + virtual void apply(const HLAUInt32DataType& dataType) { } + virtual void apply(const HLAInt64DataType& dataType) { } + virtual void apply(const HLAUInt64DataType& dataType) { } + virtual void apply(const HLAFloat32DataType& dataType) { } + virtual void apply(const HLAFloat64DataType& dataType) { } + + virtual void apply(const HLAFixedArrayDataType& dataType) + { + if (!dataType.getElementDataType()) + _valid = false; + else + dataType.getElementDataType()->accept(*this); + } + virtual void apply(const HLAVariableArrayDataType& dataType) + { + if (!dataType.getElementDataType()) + _valid = false; + else + dataType.getElementDataType()->accept(*this); + + if (!dataType.getSizeDataType()) + _valid = false; + else + dataType.getSizeDataType()->accept(*this); + } + + virtual void apply(const HLAEnumeratedDataType& dataType) + { + if (!dataType.getRepresentation()) + _valid = false; + else + dataType.getRepresentation()->accept(*this); + } + + virtual void apply(const HLAFixedRecordDataType& dataType) + { + unsigned numFields = dataType.getNumFields(); + for (unsigned i = 0; i < numFields; ++i) { + if (!dataType.getFieldDataType(i)) + _valid = false; + else + dataType.getFieldDataType(i)->accept(*this); + } + } + + virtual void apply(const HLAVariantDataType& dataType) + { assert(0); } + +protected: + bool _valid; +}; + +class HLADataTypeDecodeVisitor : public HLADataTypeVisitor { +public: + HLADataTypeDecodeVisitor(HLADecodeStream& stream) : _stream(stream) {} + virtual ~HLADataTypeDecodeVisitor() {} + + virtual void apply(const HLAInt8DataType& dataType) { dataType.skip(_stream); } + virtual void apply(const HLAUInt8DataType& dataType) { dataType.skip(_stream); } + virtual void apply(const HLAInt16DataType& dataType) { dataType.skip(_stream); } + virtual void apply(const HLAUInt16DataType& dataType) { dataType.skip(_stream); } + virtual void apply(const HLAInt32DataType& dataType) { dataType.skip(_stream); } + virtual void apply(const HLAUInt32DataType& dataType) { dataType.skip(_stream); } + virtual void apply(const HLAInt64DataType& dataType) { dataType.skip(_stream); } + virtual void apply(const HLAUInt64DataType& dataType) { dataType.skip(_stream); } + virtual void apply(const HLAFloat32DataType& dataType) { dataType.skip(_stream); } + virtual void apply(const HLAFloat64DataType& dataType) { dataType.skip(_stream); } + + virtual void apply(const HLAFixedArrayDataType& dataType) + { + unsigned numElements = dataType.getNumElements(); + for (unsigned i = 0; i < numElements; ++i) + dataType.getElementDataType()->accept(*this); + } + virtual void apply(const HLAVariableArrayDataType& dataType); + + virtual void apply(const HLAEnumeratedDataType& dataType) + { + dataType.getRepresentation()->accept(*this); + } + + virtual void apply(const HLAFixedRecordDataType& dataType) + { + unsigned numFields = dataType.getNumFields(); + for (unsigned i = 0; i < numFields; ++i) + dataType.getFieldDataType(i)->accept(*this); + } + + virtual void apply(const HLAVariantDataType& dataType) { assert(0); } + +protected: + HLADecodeStream& _stream; +}; + +class HLADataTypeEncodeVisitor : public HLADataTypeVisitor { +public: + HLADataTypeEncodeVisitor(HLAEncodeStream& stream) : _stream(stream) {} + virtual ~HLADataTypeEncodeVisitor() {} + + virtual void apply(const HLAInt8DataType& dataType) { dataType.skip(_stream); } + virtual void apply(const HLAUInt8DataType& dataType) { dataType.skip(_stream); } + virtual void apply(const HLAInt16DataType& dataType) { dataType.skip(_stream); } + virtual void apply(const HLAUInt16DataType& dataType) { dataType.skip(_stream); } + virtual void apply(const HLAInt32DataType& dataType) { dataType.skip(_stream); } + virtual void apply(const HLAUInt32DataType& dataType) { dataType.skip(_stream); } + virtual void apply(const HLAInt64DataType& dataType) { dataType.skip(_stream); } + virtual void apply(const HLAUInt64DataType& dataType) { dataType.skip(_stream); } + virtual void apply(const HLAFloat32DataType& dataType) { dataType.skip(_stream); } + virtual void apply(const HLAFloat64DataType& dataType) { dataType.skip(_stream); } + + virtual void apply(const HLAFixedArrayDataType& dataType) + { + /// FIXME, might vanish in this sense ... + // dataType.encode(_stream, *this); + unsigned numElements = dataType.getNumElements(); + for (unsigned i = 0; i < numElements; ++i) + dataType.getElementDataType()->accept(*this); + } + virtual void apply(const HLAVariableArrayDataType& dataType); + + virtual void apply(const HLAEnumeratedDataType& dataType) + { + dataType.getRepresentation()->accept(*this); + } + + virtual void apply(const HLAFixedRecordDataType& dataType) + { + unsigned numFields = dataType.getNumFields(); + for (unsigned i = 0; i < numFields; ++i) + dataType.getFieldDataType(i)->accept(*this); + } + + virtual void apply(const HLAVariantDataType& dataType) { assert(0); } + +protected: + HLAEncodeStream& _stream; +}; + +/// Begin implementation of some get/set visitors + +class HLAScalarDecodeVisitor : public HLADataTypeDecodeVisitor { +public: + HLAScalarDecodeVisitor(HLADecodeStream& stream) : + HLADataTypeDecodeVisitor(stream) + {} + + virtual void apply(const HLAFixedArrayDataType& dataType) + { + SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while decodeing scalar value"); + HLADataTypeDecodeVisitor::apply(dataType); + } + virtual void apply(const HLAVariableArrayDataType& dataType) + { + SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while decodeing scalar value"); + HLADataTypeDecodeVisitor::apply(dataType); + } + + virtual void apply(const HLAEnumeratedDataType& dataType) + { + SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while decodeing scalar value"); + HLADataTypeDecodeVisitor::apply(dataType); + } + + virtual void apply(const HLAFixedRecordDataType& dataType) + { + SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while decodeing scalar value"); + HLADataTypeDecodeVisitor::apply(dataType); + } + + virtual void apply(const HLAVariantDataType& dataType) + { + SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while decodeing scalar value"); + HLADataTypeDecodeVisitor::apply(dataType); + } +}; + +class HLAScalarEncodeVisitor : public HLADataTypeEncodeVisitor { +public: + HLAScalarEncodeVisitor(HLAEncodeStream& stream) : + HLADataTypeEncodeVisitor(stream) + {} + + virtual void apply(const HLAFixedArrayDataType& dataType) + { + SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while writing scalar value"); + HLADataTypeEncodeVisitor::apply(dataType); + } + virtual void apply(const HLAVariableArrayDataType& dataType) + { + SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while writing scalar value"); + HLADataTypeEncodeVisitor::apply(dataType); + } + + virtual void apply(const HLAEnumeratedDataType& dataType) + { + SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while writing scalar value"); + HLADataTypeEncodeVisitor::apply(dataType); + } + + virtual void apply(const HLAFixedRecordDataType& dataType) + { + SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while writing scalar value"); + HLADataTypeEncodeVisitor::apply(dataType); + } + + virtual void apply(const HLAVariantDataType& dataType) + { + SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while writing scalar value"); + HLADataTypeEncodeVisitor::apply(dataType); + } +}; + +class HLAFixedRecordDecodeVisitor : public HLADataTypeDecodeVisitor { +public: + HLAFixedRecordDecodeVisitor(HLADecodeStream& stream) : + HLADataTypeDecodeVisitor(stream) + { } + + virtual void apply(const HLAInt8DataType& dataType) + { + SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while decodeing a fixed record value"); + HLADataTypeDecodeVisitor::apply(dataType); + } + virtual void apply(const HLAUInt8DataType& dataType) + { + SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while decodeing a fixed record value"); + HLADataTypeDecodeVisitor::apply(dataType); + } + virtual void apply(const HLAInt16DataType& dataType) + { + SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while decodeing a fixed record value"); + HLADataTypeDecodeVisitor::apply(dataType); + } + virtual void apply(const HLAUInt16DataType& dataType) + { + SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while decodeing a fixed record value"); + HLADataTypeDecodeVisitor::apply(dataType); + } + virtual void apply(const HLAInt32DataType& dataType) + { + SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while decodeing a fixed record value"); + HLADataTypeDecodeVisitor::apply(dataType); + } + virtual void apply(const HLAUInt32DataType& dataType) + { + SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while decodeing a fixed record value"); + HLADataTypeDecodeVisitor::apply(dataType); + } + virtual void apply(const HLAInt64DataType& dataType) + { + SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while decodeing a fixed record value"); + HLADataTypeDecodeVisitor::apply(dataType); + } + virtual void apply(const HLAUInt64DataType& dataType) + { + SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while decodeing a fixed record value"); + HLADataTypeDecodeVisitor::apply(dataType); + } + virtual void apply(const HLAFloat32DataType& dataType) + { + SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while decodeing a fixed record value"); + HLADataTypeDecodeVisitor::apply(dataType); + } + virtual void apply(const HLAFloat64DataType& dataType) + { + SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while decodeing a fixed record value"); + HLADataTypeDecodeVisitor::apply(dataType); + } + + virtual void apply(const HLAFixedArrayDataType& dataType) + { + SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while decodeing a fixed record value"); + HLADataTypeDecodeVisitor::apply(dataType); + } + virtual void apply(const HLAVariableArrayDataType& dataType) + { + SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while decodeing a fixed record value"); + HLADataTypeDecodeVisitor::apply(dataType); + } + + virtual void apply(const HLAEnumeratedDataType& dataType) + { + SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while decodeing a fixed record value"); + HLADataTypeDecodeVisitor::apply(dataType); + } + + virtual void apply(const HLAVariantDataType& dataType) + { + SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while decodeing a fixed record value"); + HLADataTypeDecodeVisitor::apply(dataType); + } +}; + +class HLAFixedRecordEncodeVisitor : public HLADataTypeEncodeVisitor { +public: + HLAFixedRecordEncodeVisitor(HLAEncodeStream& stream) : + HLADataTypeEncodeVisitor(stream) + { } + + virtual void apply(const HLAInt8DataType& dataType) + { + SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while writing a fixed record value"); + HLADataTypeEncodeVisitor::apply(dataType); + } + virtual void apply(const HLAUInt8DataType& dataType) + { + SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while writing a fixed record value"); + HLADataTypeEncodeVisitor::apply(dataType); + } + virtual void apply(const HLAInt16DataType& dataType) + { + SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while writing a fixed record value"); + HLADataTypeEncodeVisitor::apply(dataType); + } + virtual void apply(const HLAUInt16DataType& dataType) + { + SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while writing a fixed record value"); + HLADataTypeEncodeVisitor::apply(dataType); + } + virtual void apply(const HLAInt32DataType& dataType) + { + SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while writing a fixed record value"); + HLADataTypeEncodeVisitor::apply(dataType); + } + virtual void apply(const HLAUInt32DataType& dataType) + { + SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while writing a fixed record value"); + HLADataTypeEncodeVisitor::apply(dataType); + } + virtual void apply(const HLAInt64DataType& dataType) + { + SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while writing a fixed record value"); + HLADataTypeEncodeVisitor::apply(dataType); + } + virtual void apply(const HLAUInt64DataType& dataType) + { + SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while writing a fixed record value"); + HLADataTypeEncodeVisitor::apply(dataType); + } + virtual void apply(const HLAFloat32DataType& dataType) + { + SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while writing a fixed record value"); + HLADataTypeEncodeVisitor::apply(dataType); + } + virtual void apply(const HLAFloat64DataType& dataType) + { + SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while writing a fixed record value"); + HLADataTypeEncodeVisitor::apply(dataType); + } + + virtual void apply(const HLAFixedArrayDataType& dataType) + { + SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while writing a fixed record value"); + HLADataTypeEncodeVisitor::apply(dataType); + } + virtual void apply(const HLAVariableArrayDataType& dataType) + { + SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while writing a fixed record value"); + HLADataTypeEncodeVisitor::apply(dataType); + } + + virtual void apply(const HLAEnumeratedDataType& dataType) + { + SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while writing a fixed record value"); + HLADataTypeEncodeVisitor::apply(dataType); + } + + virtual void apply(const HLAVariantDataType& dataType) + { + SG_LOG(SG_NETWORK, SG_WARN, "Unexpected HLADataType while writing a fixed record value"); + HLADataTypeEncodeVisitor::apply(dataType); + } +}; + +template +class HLATemplateDecodeVisitor : public HLAScalarDecodeVisitor { +public: + typedef T value_type; + + HLATemplateDecodeVisitor(HLADecodeStream& stream, const value_type& value = value_type()) : + HLAScalarDecodeVisitor(stream), + _value(value) + {} + + void setValue(const value_type& value) + { _value = value; } + const value_type& getValue() const + { return _value; } + + virtual void apply(const HLAInt8DataType& dataType) + { + int8_t value = 0; + dataType.decode(_stream, value); + _value = value_type(value); + } + virtual void apply(const HLAUInt8DataType& dataType) + { + uint8_t value = 0; + dataType.decode(_stream, value); + _value = value_type(value); + } + virtual void apply(const HLAInt16DataType& dataType) + { + int16_t value = 0; + dataType.decode(_stream, value); + _value = value_type(value); + } + virtual void apply(const HLAUInt16DataType& dataType) + { + uint16_t value = 0; + dataType.decode(_stream, value); + _value = value_type(value); + } + virtual void apply(const HLAInt32DataType& dataType) + { + int32_t value = 0; + dataType.decode(_stream, value); + _value = value_type(value); + } + virtual void apply(const HLAUInt32DataType& dataType) + { + uint32_t value = 0; + dataType.decode(_stream, value); + _value = value_type(value); + } + virtual void apply(const HLAInt64DataType& dataType) + { + int64_t value = 0; + dataType.decode(_stream, value); + _value = value_type(value); + } + virtual void apply(const HLAUInt64DataType& dataType) + { + uint64_t value = 0; + dataType.decode(_stream, value); + _value = value_type(value); + } + virtual void apply(const HLAFloat32DataType& dataType) + { + float value = 0; + dataType.decode(_stream, value); + _value = value_type(value); + } + virtual void apply(const HLAFloat64DataType& dataType) + { + double value = 0; + dataType.decode(_stream, value); + _value = value_type(value); + } + +private: + value_type _value; +}; + +template +class HLATemplateEncodeVisitor : public HLAScalarEncodeVisitor { +public: + typedef T value_type; + + HLATemplateEncodeVisitor(HLAEncodeStream& stream, const value_type& value = value_type()) : + HLAScalarEncodeVisitor(stream), + _value(value) + {} + + void setValue(const value_type& value) + { _value = value; } + const value_type& getValue() const + { return _value; } + + virtual void apply(const HLAInt8DataType& dataType) + { + dataType.encode(_stream, _value); + } + virtual void apply(const HLAUInt8DataType& dataType) + { + dataType.encode(_stream, _value); + } + virtual void apply(const HLAInt16DataType& dataType) + { + dataType.encode(_stream, _value); + } + virtual void apply(const HLAUInt16DataType& dataType) + { + dataType.encode(_stream, _value); + } + virtual void apply(const HLAInt32DataType& dataType) + { + dataType.encode(_stream, _value); + } + virtual void apply(const HLAUInt32DataType& dataType) + { + dataType.encode(_stream, _value); + } + virtual void apply(const HLAInt64DataType& dataType) + { + dataType.encode(_stream, _value); + } + virtual void apply(const HLAUInt64DataType& dataType) + { + dataType.encode(_stream, _value); + } + virtual void apply(const HLAFloat32DataType& dataType) + { + dataType.encode(_stream, _value); + } + virtual void apply(const HLAFloat64DataType& dataType) + { + dataType.encode(_stream, _value); + } + +private: + value_type _value; +}; + +inline void HLADataTypeDecodeVisitor::apply(const HLAVariableArrayDataType& dataType) +{ + HLATemplateDecodeVisitor numElementsVisitor(_stream); + dataType.getSizeDataType()->accept(numElementsVisitor); + unsigned numElements = numElementsVisitor.getValue(); + for (unsigned i = 0; i < numElements; ++i) + dataType.getElementDataType()->accept(*this); +} + +inline void HLADataTypeEncodeVisitor::apply(const HLAVariableArrayDataType& dataType) +{ + HLATemplateEncodeVisitor numElementsVisitor(_stream, 0); + dataType.getSizeDataType()->accept(numElementsVisitor); +} + +} // namespace simgear + +#endif diff --git a/simgear/hla/HLAEnumeratedDataElement.cxx b/simgear/hla/HLAEnumeratedDataElement.cxx new file mode 100644 index 00000000..a09e0dec --- /dev/null +++ b/simgear/hla/HLAEnumeratedDataElement.cxx @@ -0,0 +1,128 @@ +// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#include "HLAEnumeratedDataElement.hxx" + +#include + +namespace simgear { + +HLAAbstractEnumeratedDataElement::HLAAbstractEnumeratedDataElement(const HLAEnumeratedDataType* dataType) : + _dataType(dataType) +{ +} + +HLAAbstractEnumeratedDataElement::~HLAAbstractEnumeratedDataElement() +{ +} + +bool +HLAAbstractEnumeratedDataElement::decode(HLADecodeStream& stream) +{ + if (!_dataType.valid()) + return false; + unsigned index; + if (!_dataType->decode(stream, index)) + return false; + setEnumeratorIndex(index); + return true; +} + +bool +HLAAbstractEnumeratedDataElement::encode(HLAEncodeStream& stream) const +{ + if (!_dataType.valid()) + return false; + return _dataType->encode(stream, getEnumeratorIndex()); +} + +const HLAEnumeratedDataType* +HLAAbstractEnumeratedDataElement::getDataType() const +{ + return _dataType.get(); +} + +bool +HLAAbstractEnumeratedDataElement::setDataType(const HLADataType* dataType) +{ + const HLAEnumeratedDataType* enumeratedDataType = dataType->toEnumeratedDataType(); + if (!enumeratedDataType) { + SG_LOG(SG_NETWORK, SG_WARN, "HLAEnumeratedDataType: unable to set data type!"); + return false; + } + setDataType(enumeratedDataType); + return true; +} + +void +HLAAbstractEnumeratedDataElement::setDataType(const HLAEnumeratedDataType* dataType) +{ + _dataType = dataType; +} + +const HLABasicDataType* +HLAAbstractEnumeratedDataElement::getRepresentationDataType() const +{ + if (!_dataType.valid()) + return 0; + return _dataType->getRepresentation(); +} + +std::string +HLAAbstractEnumeratedDataElement::getStringRepresentation() const +{ + if (!_dataType.valid()) + return std::string(); + return _dataType->getString(getEnumeratorIndex()); +} + +bool +HLAAbstractEnumeratedDataElement::setStringRepresentation(const std::string& name) +{ + if (!_dataType.valid()) + return false; + unsigned index = _dataType->getIndex(name); + if (_dataType->getNumEnumerators() <= index) + return false; + setEnumeratorIndex(index); + return true; +} + + +HLAEnumeratedDataElement::HLAEnumeratedDataElement(const HLAEnumeratedDataType* dataType) : + HLAAbstractEnumeratedDataElement(dataType), + _enumeratorIndex(~unsigned(0)) +{ +} + +HLAEnumeratedDataElement::~HLAEnumeratedDataElement() +{ +} + +unsigned +HLAEnumeratedDataElement::getEnumeratorIndex() const +{ + return _enumeratorIndex; +} + +void +HLAEnumeratedDataElement::setEnumeratorIndex(unsigned index) +{ + _enumeratorIndex = index; +} + +} diff --git a/simgear/hla/HLAEnumeratedDataElement.hxx b/simgear/hla/HLAEnumeratedDataElement.hxx new file mode 100644 index 00000000..f7dfbd38 --- /dev/null +++ b/simgear/hla/HLAEnumeratedDataElement.hxx @@ -0,0 +1,64 @@ +// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#ifndef HLAEnumeratedDataElement_hxx +#define HLAEnumeratedDataElement_hxx + +#include "HLADataElement.hxx" +#include "HLAEnumeratedDataType.hxx" + +namespace simgear { + +class HLAAbstractEnumeratedDataElement : public HLADataElement { +public: + HLAAbstractEnumeratedDataElement(const HLAEnumeratedDataType* dataType); + virtual ~HLAAbstractEnumeratedDataElement(); + + virtual bool decode(HLADecodeStream& stream); + virtual bool encode(HLAEncodeStream& stream) const; + + virtual const HLAEnumeratedDataType* getDataType() const; + virtual bool setDataType(const HLADataType* dataType); + void setDataType(const HLAEnumeratedDataType* dataType); + + const HLABasicDataType* getRepresentationDataType() const; + + std::string getStringRepresentation() const; + bool setStringRepresentation(const std::string& name); + + virtual unsigned getEnumeratorIndex() const = 0; + virtual void setEnumeratorIndex(unsigned index) = 0; + +private: + SGSharedPtr _dataType; +}; + +class HLAEnumeratedDataElement : public HLAAbstractEnumeratedDataElement { +public: + HLAEnumeratedDataElement(const HLAEnumeratedDataType* dataType); + virtual ~HLAEnumeratedDataElement(); + + virtual unsigned getEnumeratorIndex() const; + virtual void setEnumeratorIndex(unsigned index); + +private: + unsigned _enumeratorIndex; +}; + +} + +#endif diff --git a/simgear/hla/HLAEnumeratedDataType.cxx b/simgear/hla/HLAEnumeratedDataType.cxx new file mode 100644 index 00000000..56fd34dd --- /dev/null +++ b/simgear/hla/HLAEnumeratedDataType.cxx @@ -0,0 +1,180 @@ +// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#include "HLAEnumeratedDataType.hxx" + +#include +#include +#include +#include "HLAEnumeratedDataType.hxx" +#include "HLADataTypeVisitor.hxx" + +namespace simgear { + +template +class HLAEnumeratedDataType::Map : public HLAEnumeratedDataType::AbstractMap { +public: + typedef typename std::pair RepresentationPair; + typedef typename std::map RepresentationIndexMap; + typedef typename std::vector IndexRepresentationMap; + typedef typename std::map StringIndexMap; + + Map(const DataType* dataType) : + _dataType(dataType) + { } + virtual bool encode(HLAEncodeStream& stream, unsigned index) const + { + T value = _otherRepresentation; + if (index < _indexRepresentationMap.size()) + value = _indexRepresentationMap[index].second; + if (!_dataType->encode(stream, value)) + return false; + return true; + } + virtual bool decode(HLADecodeStream& stream, unsigned& index) const + { + T value; + if (!_dataType->decode(stream, value)) + return false; + typename RepresentationIndexMap::const_iterator i; + i = _representationIndexMap.find(value); + if (i == _representationIndexMap.end()) + index = _indexRepresentationMap.size(); + else + index = i->second; + return true; + } + virtual const HLABasicDataType* getDataType() const + { return _dataType.get(); } + + virtual bool add(const std::string& name, const std::string& number) + { + std::stringstream ss(number); + T value; + ss >> value; + if (ss.fail()) + return false; + if (_representationIndexMap.find(value) != _representationIndexMap.end()) + return false; + if (_stringIndexMap.find(name) != _stringIndexMap.end()) + return false; + _stringIndexMap[name] = _indexRepresentationMap.size(); + _representationIndexMap[value] = _indexRepresentationMap.size(); + _indexRepresentationMap.push_back(RepresentationPair(name, value)); + return true; + } + virtual std::string getString(unsigned index) const + { + if (_indexRepresentationMap.size() <= index) + return std::string(); + return _indexRepresentationMap[index].first; + } + virtual unsigned getIndex(const std::string& name) const + { + typename StringIndexMap::const_iterator i = _stringIndexMap.find(name); + if (i == _stringIndexMap.end()) + return ~unsigned(0); + return i->second; + } + virtual unsigned getNumEnumerators() const + { return _indexRepresentationMap.size(); } + +private: + IndexRepresentationMap _indexRepresentationMap; + StringIndexMap _stringIndexMap; + RepresentationIndexMap _representationIndexMap; + + T _otherRepresentation; + SGSharedPtr _dataType; +}; + +class HLAEnumeratedDataType::RepresentationVisitor : public HLADataTypeVisitor { +public: + virtual void apply(const HLAInt8DataType& dataType) + { _map = new Map(&dataType); } + virtual void apply(const HLAUInt8DataType& dataType) + { _map = new Map(&dataType); } + virtual void apply(const HLAInt16DataType& dataType) + { _map = new Map(&dataType); } + virtual void apply(const HLAUInt16DataType& dataType) + { _map = new Map(&dataType); } + virtual void apply(const HLAInt32DataType& dataType) + { _map = new Map(&dataType); } + virtual void apply(const HLAUInt32DataType& dataType) + { _map = new Map(&dataType); } + virtual void apply(const HLAInt64DataType& dataType) + { _map = new Map(&dataType); } + virtual void apply(const HLAUInt64DataType& dataType) + { _map = new Map(&dataType); } + + SGSharedPtr _map; +}; + +HLAEnumeratedDataType::HLAEnumeratedDataType(const std::string& name) : + HLADataType(name) +{ +} + +HLAEnumeratedDataType::~HLAEnumeratedDataType() +{ +} + +void +HLAEnumeratedDataType::accept(HLADataTypeVisitor& visitor) const +{ + visitor.apply(*this); +} + +const HLAEnumeratedDataType* +HLAEnumeratedDataType::toEnumeratedDataType() const +{ + return this; +} + +bool +HLAEnumeratedDataType::decode(HLADecodeStream& stream, unsigned& index) const +{ + if (!_map.valid()) + return false; + + if (!_map->decode(stream, index)) + return false; + return true; +} + +bool +HLAEnumeratedDataType::encode(HLAEncodeStream& stream, unsigned index) const +{ + if (!_map.valid()) + return false; + + return _map->encode(stream, index); +} + +void +HLAEnumeratedDataType::setRepresentation(HLABasicDataType* representation) +{ + if (!representation) + return; + + RepresentationVisitor representationVisitor; + representation->accept(representationVisitor); + _map.swap(representationVisitor._map); +} + +} // namespace simgear + diff --git a/simgear/hla/HLAEnumeratedDataType.hxx b/simgear/hla/HLAEnumeratedDataType.hxx new file mode 100644 index 00000000..7066adba --- /dev/null +++ b/simgear/hla/HLAEnumeratedDataType.hxx @@ -0,0 +1,95 @@ +// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#ifndef HLAEnumeratedDataType_hxx +#define HLAEnumeratedDataType_hxx + +#include +#include +#include "HLADataType.hxx" + +namespace simgear { + +class HLAEnumeratedDataType : public HLADataType { +public: + HLAEnumeratedDataType(const std::string& name = "HLAEnumeratedDataType"); + virtual ~HLAEnumeratedDataType(); + + virtual void accept(HLADataTypeVisitor& visitor) const; + + virtual const HLAEnumeratedDataType* toEnumeratedDataType() const; + + virtual bool decode(HLADecodeStream& stream, unsigned& index) const; + virtual bool encode(HLAEncodeStream& stream, unsigned index) const; + + std::string getString(unsigned index) const + { + if (!_map.valid()) + return std::string(); + return _map->getString(index); + } + unsigned getIndex(const std::string& name) const + { + if (!_map.valid()) + return ~unsigned(0); + return _map->getIndex(name); + } + unsigned getNumEnumerators() const + { + if (!_map.valid()) + return 0; + return _map->getNumEnumerators(); + } + + bool addEnumerator(const std::string& name, const std::string& number) + { + if (!_map.valid()) + return false; + return _map->add(name, number); + } + + void setRepresentation(HLABasicDataType* representation); + const HLABasicDataType* getRepresentation() const + { + if (!_map.valid()) + return 0; + return _map->getDataType(); + } + +private: + class AbstractMap : public SGReferenced { + public: + virtual ~AbstractMap() {} + virtual bool encode(HLAEncodeStream& stream, unsigned index) const = 0; + virtual bool decode(HLADecodeStream& stream, unsigned& index) const = 0; + virtual const HLABasicDataType* getDataType() const = 0; + virtual bool add(const std::string& name, const std::string& number) = 0; + virtual std::string getString(unsigned index) const = 0; + virtual unsigned getIndex(const std::string& name) const = 0; + virtual unsigned getNumEnumerators() const = 0; + }; + + template + class Map; + class RepresentationVisitor; + + SGSharedPtr _map; +}; + +} // namespace simgear + +#endif diff --git a/simgear/hla/HLAFederate.cxx b/simgear/hla/HLAFederate.cxx new file mode 100644 index 00000000..14f6c0ce --- /dev/null +++ b/simgear/hla/HLAFederate.cxx @@ -0,0 +1,246 @@ +// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#include "HLAFederate.hxx" + +#include "RTIFederate.hxx" +#include "RTIInteractionClass.hxx" +#include "RTIObjectClass.hxx" +#include "HLADataElement.hxx" +#include "HLADataType.hxx" +#include "HLAOMTXmlVisitor.hxx" + +namespace simgear { + +HLAFederate::HLAFederate(const SGSharedPtr& rtiFederate) : + _rtiFederate(rtiFederate) +{ +} + +HLAFederate::~HLAFederate() +{ +} + +const std::string& +HLAFederate::getFederateType() const +{ + return _rtiFederate->getFederateType(); +} + +const std::string& +HLAFederate::getFederationName() const +{ + return _rtiFederate->getFederationName(); +} + +bool +HLAFederate::createFederationExecution(const std::string& federation, const std::string& objectModel) +{ + return _rtiFederate->createFederationExecution(federation, objectModel); +} + +bool +HLAFederate::destroyFederationExecution(const std::string& federation) +{ + return _rtiFederate->destroyFederationExecution(federation); +} + +bool +HLAFederate::join(const std::string& federateType, const std::string& federation) +{ + return _rtiFederate->join(federateType, federation); +} + +bool +HLAFederate::resign() +{ + return _rtiFederate->resign(); +} + +bool +HLAFederate::enableTimeConstrained() +{ + return _rtiFederate->enableTimeConstrained(); +} + +bool +HLAFederate::disableTimeConstrained() +{ + return _rtiFederate->disableTimeConstrained(); +} + +bool +HLAFederate::enableTimeRegulation(const SGTimeStamp& lookahead) +{ + return _rtiFederate->enableTimeRegulation(lookahead); +} + +bool +HLAFederate::disableTimeRegulation() +{ + return _rtiFederate->disableTimeRegulation(); +} + +bool +HLAFederate::timeAdvanceRequestBy(const SGTimeStamp& dt) +{ + return _rtiFederate->timeAdvanceRequestBy(dt); +} + +bool +HLAFederate::timeAdvanceRequest(const SGTimeStamp& dt) +{ + return _rtiFederate->timeAdvanceRequest(dt); +} + +bool +HLAFederate::tick() +{ + return _rtiFederate->tick(); +} + +bool +HLAFederate::tick(const double& minimum, const double& maximum) +{ + return _rtiFederate->tick(minimum, maximum); +} + +bool +HLAFederate::readObjectModelTemplate(const std::string& objectModel, + HLAFederate::ObjectModelFactory& objectModelFactory) +{ + if (!_rtiFederate.valid()) { + SG_LOG(SG_IO, SG_ALERT, "Could not process HLA XML object model file: " + "No rti federate available!"); + return false; + } + + // The XML version of the federate object model. + // This one covers the generic attributes, parameters and data types. + HLAOMTXmlVisitor omtXmlVisitor; + try { + readXML(objectModel, omtXmlVisitor); + } catch (const sg_throwable& e) { + SG_LOG(SG_IO, SG_ALERT, "Could not open HLA XML object model file: " + << e.getMessage()); + return false; + } catch (...) { + SG_LOG(SG_IO, SG_ALERT, "Could not open HLA XML object model file"); + return false; + } + + unsigned numObjectClasses = omtXmlVisitor.getNumObjectClasses(); + for (unsigned i = 0; i < numObjectClasses; ++i) { + const HLAOMTXmlVisitor::ObjectClass* objectClass = omtXmlVisitor.getObjectClass(i); + std::string objectClassName = objectClass->getName(); + + SGSharedPtr hlaObjectClass = objectModelFactory.createObjectClass(objectClassName, *this); + if (!hlaObjectClass.valid()) { + SG_LOG(SG_IO, SG_INFO, "Ignoring object class \"" << objectClassName << "\"."); + continue; + } + + bool publish = objectModelFactory.publishObjectClass(objectClassName, objectClass->getSharing()); + bool subscribe = objectModelFactory.subscribeObjectClass(objectClassName, objectClass->getSharing()); + + std::set subscriptions; + std::set publications; + + // process the attributes + for (unsigned j = 0; j < objectClass->getNumAttributes(); ++j) { + const simgear::HLAOMTXmlVisitor::Attribute* attribute; + attribute = objectClass->getAttribute(j); + + std::string attributeName = attribute->getName(); + unsigned index = hlaObjectClass->getAttributeIndex(attributeName); + + if (index == ~0u) { + SG_LOG(SG_IO, SG_WARN, "RTI does not know the \"" << attributeName << "\" attribute!"); + continue; + } + + SGSharedPtr dataType; + dataType = omtXmlVisitor.getAttributeDataType(objectClassName, attributeName); + if (!dataType.valid()) { + SG_LOG(SG_IO, SG_WARN, "Could not find data type for attribute \"" + << attributeName << "\" in object class \"" << objectClassName << "\"!"); + } + hlaObjectClass->setAttributeDataType(index, dataType); + + HLAUpdateType updateType = HLAUndefinedUpdate; + if (attribute->_updateType == "Periodic") + updateType = HLAPeriodicUpdate; + else if (attribute->_updateType == "Static") + updateType = HLAStaticUpdate; + else if (attribute->_updateType == "Conditional") + updateType = HLAConditionalUpdate; + hlaObjectClass->setAttributeUpdateType(index, updateType); + + if (subscribe && objectModelFactory.subscribeAttribute(objectClassName, attributeName, attribute->_sharing)) + subscriptions.insert(index); + if (publish && objectModelFactory.publishAttribute(objectClassName, attributeName, attribute->_sharing)) + publications.insert(index); + } + + if (publish) + hlaObjectClass->publish(publications); + if (subscribe) + hlaObjectClass->subscribe(subscriptions, true); + + _objectClassMap[objectClassName] = hlaObjectClass; + } + + return true; +} + +HLAObjectClass* +HLAFederate::getObjectClass(const std::string& name) +{ + ObjectClassMap::const_iterator i = _objectClassMap.find(name); + if (i == _objectClassMap.end()) + return 0; + return i->second.get(); +} + +const HLAObjectClass* +HLAFederate::getObjectClass(const std::string& name) const +{ + ObjectClassMap::const_iterator i = _objectClassMap.find(name); + if (i == _objectClassMap.end()) + return 0; + return i->second.get(); +} + +HLAInteractionClass* +HLAFederate::getInteractionClass(const std::string& name) +{ + InteractionClassMap::const_iterator i = _interactionClassMap.find(name); + if (i == _interactionClassMap.end()) + return 0; + return i->second.get(); +} + +const HLAInteractionClass* +HLAFederate::getInteractionClass(const std::string& name) const +{ + InteractionClassMap::const_iterator i = _interactionClassMap.find(name); + if (i == _interactionClassMap.end()) + return 0; + return i->second.get(); +} + +} // namespace simgear diff --git a/simgear/hla/HLAFederate.hxx b/simgear/hla/HLAFederate.hxx new file mode 100644 index 00000000..64ea2b4e --- /dev/null +++ b/simgear/hla/HLAFederate.hxx @@ -0,0 +1,111 @@ +// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#ifndef HLAFederate_hxx +#define HLAFederate_hxx + +#include + +#include "HLAObjectInstance.hxx" +#include "HLAObjectClass.hxx" +#include "HLAInteractionClass.hxx" + +class SGTimeStamp; + +namespace simgear { + +class RTIFederate; + +class HLAFederate : public SGWeakReferenced { +public: + virtual ~HLAFederate(); + + /// Get the name of the joined federate/federation + const std::string& getFederateType() const; + const std::string& getFederationName() const; + + /// Create a federation execution + /// Semantically this methods should be static, + /// but the nonstatic case could reuse the connection to the server + /// FIXME: cannot determine from the return value if we created the execution + bool createFederationExecution(const std::string& federation, const std::string& objectModel); + bool destroyFederationExecution(const std::string& federation); + + /// Join with federateType the federation execution + bool join(const std::string& federateType, const std::string& federation); + bool resign(); + + bool enableTimeConstrained(); + bool disableTimeConstrained(); + + bool enableTimeRegulation(const SGTimeStamp& lookahead); + bool disableTimeRegulation(); + + bool timeAdvanceRequestBy(const SGTimeStamp& dt); + bool timeAdvanceRequest(const SGTimeStamp& dt); + + /// Process messages + bool tick(); + bool tick(const double& minimum, const double& maximum); + + class ObjectModelFactory { + public: + virtual ~ObjectModelFactory() + { } + + virtual HLAObjectClass* createObjectClass(const std::string& name, HLAFederate& federate) + { return new HLAObjectClass(name, federate); } + virtual bool subscribeObjectClass(const std::string& objectClassName, const std::string& sharing) + { return sharing.find("Subscribe") != std::string::npos; } + virtual bool publishObjectClass(const std::string& objectClassName, const std::string& sharing) + { return sharing.find("Publish") != std::string::npos; } + virtual bool subscribeAttribute(const std::string& objectClassName, const std::string& attributeName, const std::string& sharing) + { return sharing.find("Subscribe") != std::string::npos; } + virtual bool publishAttribute(const std::string& objectClassName, const std::string& attributeName, const std::string& sharing) + { return sharing.find("Publish") != std::string::npos; } + + }; + + /// Read an omt xml file + bool readObjectModelTemplate(const std::string& objectModel, + ObjectModelFactory& objectModelFactory); + + HLAObjectClass* getObjectClass(const std::string& name); + const HLAObjectClass* getObjectClass(const std::string& name) const; + + HLAInteractionClass* getInteractionClass(const std::string& name); + const HLAInteractionClass* getInteractionClass(const std::string& name) const; + +protected: + HLAFederate(const SGSharedPtr& rtiFederate); + +private: + SGSharedPtr _rtiFederate; + + typedef std::map > ObjectClassMap; + ObjectClassMap _objectClassMap; + + typedef std::map > InteractionClassMap; + InteractionClassMap _interactionClassMap; + + friend class HLAInteractionClass; + friend class HLAObjectClass; +}; + +} // namespace simgear + +#endif diff --git a/simgear/hla/HLAFixedRecordDataElement.cxx b/simgear/hla/HLAFixedRecordDataElement.cxx new file mode 100644 index 00000000..d0980b95 --- /dev/null +++ b/simgear/hla/HLAFixedRecordDataElement.cxx @@ -0,0 +1,179 @@ +// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#include "HLAFixedRecordDataElement.hxx" + +#include +#include +#include +#include "HLADataTypeVisitor.hxx" + +namespace simgear { + +HLAAbstractFixedRecordDataElement::HLAAbstractFixedRecordDataElement(const HLAFixedRecordDataType* dataType) : + _dataType(dataType) +{ +} + +HLAAbstractFixedRecordDataElement::~HLAAbstractFixedRecordDataElement() +{ +} + +bool +HLAAbstractFixedRecordDataElement::decode(HLADecodeStream& stream) +{ + if (!_dataType.valid()) + return false; + return _dataType->decode(stream, *this); +} + +bool +HLAAbstractFixedRecordDataElement::encode(HLAEncodeStream& stream) const +{ + if (!_dataType.valid()) + return false; + return _dataType->encode(stream, *this); +} + +const HLAFixedRecordDataType* +HLAAbstractFixedRecordDataElement::getDataType() const +{ + return _dataType.get(); +} + +bool +HLAAbstractFixedRecordDataElement::setDataType(const HLADataType* dataType) +{ + const HLAFixedRecordDataType* fixedRecordDataType = dataType->toFixedRecordDataType(); + if (!fixedRecordDataType) { + SG_LOG(SG_NETWORK, SG_WARN, "HLAFixedRecordDataType: unable to set data type!"); + return false; + } + setDataType(fixedRecordDataType); + return true; +} + +void +HLAAbstractFixedRecordDataElement::setDataType(const HLAFixedRecordDataType* dataType) +{ + _dataType = dataType; +} + +unsigned +HLAAbstractFixedRecordDataElement::getNumFields() const +{ + return _dataType->getNumFields(); +} + +unsigned +HLAAbstractFixedRecordDataElement::getFieldNumber(const std::string& name) const +{ + return _dataType->getFieldNumber(name); +} + +const HLADataType* +HLAAbstractFixedRecordDataElement::getFieldDataType(unsigned i) const +{ + return _dataType->getFieldDataType(i); +} + +const HLADataType* +HLAAbstractFixedRecordDataElement::getFieldDataType(const std::string& name) const +{ + return getFieldDataType(getFieldNumber(name)); +} + + +HLAFixedRecordDataElement::HLAFixedRecordDataElement(const HLAFixedRecordDataType* dataType) : + HLAAbstractFixedRecordDataElement(dataType) +{ + _fieldVector.resize(getNumFields()); +} + +HLAFixedRecordDataElement::~HLAFixedRecordDataElement() +{ +} + +bool +HLAFixedRecordDataElement::decodeField(HLADecodeStream& stream, unsigned i) +{ + HLADataElement* dataElement = getField(i); + if (dataElement) { + return dataElement->decode(stream); + } else { + HLADataTypeDecodeVisitor visitor(stream); + getDataType()->getFieldDataType(i)->accept(visitor); + return true; + } +} + +bool +HLAFixedRecordDataElement::encodeField(HLAEncodeStream& stream, unsigned i) const +{ + const HLADataElement* dataElement = getField(i); + if (dataElement) { + return dataElement->encode(stream); + } else { + HLADataTypeEncodeVisitor visitor(stream); + getDataType()->getFieldDataType(i)->accept(visitor); + return true; + } +} + +HLADataElement* +HLAFixedRecordDataElement::getField(const std::string& name) +{ + return getField(getFieldNumber(name)); +} + +const HLADataElement* +HLAFixedRecordDataElement::getField(const std::string& name) const +{ + return getField(getFieldNumber(name)); +} + +HLADataElement* +HLAFixedRecordDataElement::getField(unsigned i) +{ + if (_fieldVector.size() <= i) + return 0; + return _fieldVector[i].get(); +} + +const HLADataElement* +HLAFixedRecordDataElement::getField(unsigned i) const +{ + if (_fieldVector.size() <= i) + return 0; + return _fieldVector[i].get(); +} + +void +HLAFixedRecordDataElement::setField(unsigned index, HLADataElement* value) +{ + if (getNumFields() <= index) + return; + _fieldVector[index] = value; +} + +void +HLAFixedRecordDataElement::setField(const std::string& name, HLADataElement* value) +{ + setField(getFieldNumber(name), value); +} + +} diff --git a/simgear/hla/HLAFixedRecordDataElement.hxx b/simgear/hla/HLAFixedRecordDataElement.hxx new file mode 100644 index 00000000..d99719d0 --- /dev/null +++ b/simgear/hla/HLAFixedRecordDataElement.hxx @@ -0,0 +1,77 @@ +// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#ifndef HLAFixedRecordDataElement_hxx +#define HLAFixedRecordDataElement_hxx + +#include +#include +#include "HLADataElement.hxx" +#include "HLAFixedRecordDataType.hxx" + +namespace simgear { + +class HLAAbstractFixedRecordDataElement : public HLADataElement { +public: + HLAAbstractFixedRecordDataElement(const HLAFixedRecordDataType* dataType); + virtual ~HLAAbstractFixedRecordDataElement(); + + virtual bool decode(HLADecodeStream& stream); + virtual bool encode(HLAEncodeStream& stream) const; + + virtual const HLAFixedRecordDataType* getDataType() const; + virtual bool setDataType(const HLADataType* dataType); + void setDataType(const HLAFixedRecordDataType* dataType); + + unsigned getNumFields() const; + unsigned getFieldNumber(const std::string& name) const; + + const HLADataType* getFieldDataType(unsigned i) const; + const HLADataType* getFieldDataType(const std::string& name) const; + + virtual bool decodeField(HLADecodeStream& stream, unsigned i) = 0; + virtual bool encodeField(HLAEncodeStream& stream, unsigned i) const = 0; + +private: + SGSharedPtr _dataType; +}; + +class HLAFixedRecordDataElement : public HLAAbstractFixedRecordDataElement { +public: + HLAFixedRecordDataElement(const HLAFixedRecordDataType* dataType); + virtual ~HLAFixedRecordDataElement(); + + virtual bool decodeField(HLADecodeStream& stream, unsigned i); + virtual bool encodeField(HLAEncodeStream& stream, unsigned i) const; + + HLADataElement* getField(const std::string& name); + const HLADataElement* getField(const std::string& name) const; + + HLADataElement* getField(unsigned i); + const HLADataElement* getField(unsigned i) const; + + void setField(unsigned index, HLADataElement* value); + void setField(const std::string& name, HLADataElement* value); + +private: + typedef std::vector > FieldVector; + FieldVector _fieldVector; +}; + +} + +#endif diff --git a/simgear/hla/HLAFixedRecordDataType.cxx b/simgear/hla/HLAFixedRecordDataType.cxx new file mode 100644 index 00000000..acec73a1 --- /dev/null +++ b/simgear/hla/HLAFixedRecordDataType.cxx @@ -0,0 +1,77 @@ +// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#include "HLAFixedRecordDataType.hxx" + +#include "HLADataTypeVisitor.hxx" +#include "HLAFixedRecordDataElement.hxx" + +namespace simgear { + +HLAFixedRecordDataType::HLAFixedRecordDataType(const std::string& name) : + HLADataType(name) +{ +} + +HLAFixedRecordDataType::~HLAFixedRecordDataType() +{ +} + +void +HLAFixedRecordDataType::accept(HLADataTypeVisitor& visitor) const +{ + visitor.apply(*this); +} + +const HLAFixedRecordDataType* +HLAFixedRecordDataType::toFixedRecordDataType() const +{ + return this; +} + +bool +HLAFixedRecordDataType::decode(HLADecodeStream& stream, HLAAbstractFixedRecordDataElement& value) const +{ + stream.alignOffsetForSize(getAlignment()); + unsigned numFields = getNumFields(); + for (unsigned i = 0; i < numFields; ++i) + if (!value.decodeField(stream, i)) + return false; + return true; +} + +bool +HLAFixedRecordDataType::encode(HLAEncodeStream& stream, const HLAAbstractFixedRecordDataElement& value) const +{ + stream.alignOffsetForSize(getAlignment()); + unsigned numFields = getNumFields(); + for (unsigned i = 0; i < numFields; ++i) + if (!value.encodeField(stream, i)) + return false; + return true; +} + +void +HLAFixedRecordDataType::addField(const std::string& name, const HLADataType* dataType) +{ + // FIXME this only works if we do not reset the alignment to something smaller + if (getAlignment() < dataType->getAlignment()) + setAlignment(dataType->getAlignment()); + _fieldList.push_back(Field(name, dataType)); +} + +} // namespace simgear diff --git a/simgear/hla/HLAFixedRecordDataType.hxx b/simgear/hla/HLAFixedRecordDataType.hxx new file mode 100644 index 00000000..17c32ac4 --- /dev/null +++ b/simgear/hla/HLAFixedRecordDataType.hxx @@ -0,0 +1,91 @@ +// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#ifndef HLAFixedRecordDataType_hxx +#define HLAFixedRecordDataType_hxx + +#include +#include +#include +#include "HLADataType.hxx" + +namespace simgear { + +class HLAAbstractFixedRecordDataElement; + +class HLAFixedRecordDataType : public HLADataType { +public: + HLAFixedRecordDataType(const std::string& name = "HLAFixedRecordDataType"); + virtual ~HLAFixedRecordDataType(); + + virtual void accept(HLADataTypeVisitor& visitor) const; + + virtual const HLAFixedRecordDataType* toFixedRecordDataType() const; + + virtual bool decode(HLADecodeStream& stream, HLAAbstractFixedRecordDataElement& value) const; + virtual bool encode(HLAEncodeStream& stream, const HLAAbstractFixedRecordDataElement& value) const; + + unsigned getNumFields() const + { return _fieldList.size(); } + + std::string getFieldName(unsigned i) const + { + if (_fieldList.size() <= i) + return std::string(); + return _fieldList[i].getName(); + } + const HLADataType* getFieldDataType(unsigned i) const + { + if (_fieldList.size() <= i) + return 0; + return _fieldList[i].getDataType(); + } + + unsigned getFieldNumber(const std::string& name) const + { + for (unsigned i = 0; i < _fieldList.size(); ++i) { + if (_fieldList[i].getName() != name) + continue; + return i; + } + return ~0u; + } + + void addField(const std::string& name, const HLADataType* dataType); + +private: + struct Field { + Field(const std::string& name, const HLADataType* dataType) : + _name(name), _dataType(dataType) {} + const std::string& getName() const + { return _name; } + + const HLADataType* getDataType() const + { return _dataType.get(); } + + private: + std::string _name; + SGSharedPtr _dataType; + }; + + typedef std::vector FieldList; + FieldList _fieldList; +}; + +} // namespace simgear + +#endif diff --git a/simgear/hla/HLAInteractionClass.hxx b/simgear/hla/HLAInteractionClass.hxx new file mode 100644 index 00000000..c45c22d7 --- /dev/null +++ b/simgear/hla/HLAInteractionClass.hxx @@ -0,0 +1,32 @@ +// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#ifndef HLAInteractionClass_hxx +#define HLAInteractionClass_hxx + +namespace simgear { + +class RTIInteractionClass; + +class HLAInteractionClass : public SGWeakReferenced { +public: + virtual ~HLAInteractionClass() {} +}; + +} // namespace simgear + +#endif diff --git a/simgear/hla/HLALocation.hxx b/simgear/hla/HLALocation.hxx new file mode 100644 index 00000000..20aea837 --- /dev/null +++ b/simgear/hla/HLALocation.hxx @@ -0,0 +1,549 @@ +// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#ifndef HLALocation_hxx +#define HLALocation_hxx + +#include "HLABasicDataElement.hxx" + +namespace simgear { + +class HLAAbstractLocation : public SGReferenced { +public: + virtual ~HLAAbstractLocation() {} + + virtual SGVec3d getCartPosition() const = 0; + virtual void setCartPosition(const SGVec3d&) = 0; + + virtual SGQuatd getCartOrientation() const = 0; + virtual void setCartOrientation(const SGQuatd&) = 0; + + virtual SGVec3d getAngularBodyVelocity() const = 0; + virtual void setAngularBodyVelocity(const SGVec3d& angular) = 0; + + virtual SGVec3d getLinearBodyVelocity() const = 0; + virtual void setLinearBodyVelocity(const SGVec3d& linear) = 0; +}; + +class HLACartesianLocation : public HLAAbstractLocation { +public: + HLACartesianLocation() : + _position(SGVec3d::zeros()), + _imag(SGVec3d::zeros()), + _angularVelocity(SGVec3d::zeros()), + _linearVelocity(SGVec3d::zeros()) + { } + + virtual SGVec3d getCartPosition() const + { return _position; } + virtual void setCartPosition(const SGVec3d& position) + { _position = position; } + + virtual SGQuatd getCartOrientation() const + { return SGQuatd::fromPositiveRealImag(_imag); } + virtual void setCartOrientation(const SGQuatd& orientation) + { _imag = orientation.getPositiveRealImag(); } + + virtual SGVec3d getAngularBodyVelocity() const + { return _angularVelocity; } + virtual void setAngularBodyVelocity(const SGVec3d& angularVelocity) + { _angularVelocity = angularVelocity; } + + virtual SGVec3d getLinearBodyVelocity() const + { return _linearVelocity; } + virtual void setLinearBodyVelocity(const SGVec3d& linearVelocity) + { _linearVelocity = linearVelocity; } + + HLADataElementProvider getPositionDataElement(unsigned i) + { + if (3 <= i) + return HLADataElementProvider(); + return new PositionDataElement(this, i); + } + HLADataElementProvider getOrientationDataElement(unsigned i) + { + if (3 <= i) + return HLADataElementProvider(); + return new OrientationDataElement(this, i); + } + + HLADataElementProvider getAngularVelocityDataElement(unsigned i) + { + if (3 <= i) + return HLADataElementProvider(); + return new AngularVelocityDataElement(this, i); + } + HLADataElementProvider getLinearVelocityDataElement(unsigned i) + { + if (3 <= i) + return HLADataElementProvider(); + return new LinearVelocityDataElement(this, i); + } + +private: + class PositionDataElement : public HLAAbstractDoubleDataElement { + public: + PositionDataElement(HLACartesianLocation* data, unsigned index) : + _data(data), _index(index) + { } + virtual double getValue() const + { return _data->_position[_index]; } + virtual void setValue(double value) + { _data->_position[_index] = value; } + + private: + SGSharedPtr _data; + unsigned _index; + }; + + class OrientationDataElement : public HLAAbstractDoubleDataElement { + public: + OrientationDataElement(HLACartesianLocation* data, unsigned index) : + _data(data), _index(index) + { } + virtual double getValue() const + { return _data->_imag[_index]; } + virtual void setValue(double value) + { _data->_imag[_index] = value; } + + private: + SGSharedPtr _data; + unsigned _index; + }; + + class AngularVelocityDataElement : public HLAAbstractDoubleDataElement { + public: + AngularVelocityDataElement(HLACartesianLocation* data, unsigned index) : + _data(data), _index(index) + { } + virtual double getValue() const + { return _data->_angularVelocity[_index]; } + virtual void setValue(double value) + { _data->_angularVelocity[_index] = value; } + + private: + SGSharedPtr _data; + unsigned _index; + }; + + class LinearVelocityDataElement : public HLAAbstractDoubleDataElement { + public: + LinearVelocityDataElement(HLACartesianLocation* data, unsigned index) : + _data(data), _index(index) + { } + virtual double getValue() const + { return _data->_linearVelocity[_index]; } + virtual void setValue(double value) + { _data->_linearVelocity[_index] = value; } + + private: + SGSharedPtr _data; + unsigned _index; + }; + + SGVec3d _position; + SGVec3d _imag; + + SGVec3d _angularVelocity; + SGVec3d _linearVelocity; +}; + +class HLALocationFactory : public SGReferenced { +public: + virtual ~HLALocationFactory() {} + virtual HLAAbstractLocation* createLocation(HLAAttributePathElementMap&) const = 0; +}; + +class HLACartesianLocationFactory : public HLALocationFactory { +public: + virtual HLAAbstractLocation* createLocation(HLAAttributePathElementMap& attributePathElementMap) const + { + HLACartesianLocation* location = new HLACartesianLocation; + for (unsigned i = 0; i < 3; ++i) { + const HLADataElement::IndexPathPair& indexPathPair = _positonIndexPathPair[i]; + attributePathElementMap[indexPathPair.first][indexPathPair.second] = location->getPositionDataElement(i); + } + for (unsigned i = 0; i < 3; ++i) { + const HLADataElement::IndexPathPair& indexPathPair = _orientationIndexPathPair[i]; + attributePathElementMap[indexPathPair.first][indexPathPair.second] = location->getOrientationDataElement(i); + } + for (unsigned i = 0; i < 3; ++i) { + const HLADataElement::IndexPathPair& indexPathPair = _angularVelocityIndexPathPair[i]; + attributePathElementMap[indexPathPair.first][indexPathPair.second] = location->getAngularVelocityDataElement(i); + } + for (unsigned i = 0; i < 3; ++i) { + const HLADataElement::IndexPathPair& indexPathPair = _linearVelocityIndexPathPair[i]; + attributePathElementMap[indexPathPair.first][indexPathPair.second] = location->getLinearVelocityDataElement(i); + } + return location; + } + + void setPositionIndexPathPair(unsigned index, const HLADataElement::IndexPathPair& indexPathPair) + { + if (3 <= index) + return; + _positonIndexPathPair[index] = indexPathPair; + } + void setOrientationIndexPathPair(unsigned index, const HLADataElement::IndexPathPair& indexPathPair) + { + if (3 <= index) + return; + _orientationIndexPathPair[index] = indexPathPair; + } + + void setAngularVelocityIndexPathPair(unsigned index, const HLADataElement::IndexPathPair& indexPathPair) + { + if (3 <= index) + return; + _angularVelocityIndexPathPair[index] = indexPathPair; + } + void setLinearVelocityIndexPathPair(unsigned index, const HLADataElement::IndexPathPair& indexPathPair) + { + if (3 <= index) + return; + _linearVelocityIndexPathPair[index] = indexPathPair; + } + +private: + HLADataElement::IndexPathPair _positonIndexPathPair[3]; + HLADataElement::IndexPathPair _orientationIndexPathPair[3]; + + HLADataElement::IndexPathPair _angularVelocityIndexPathPair[3]; + HLADataElement::IndexPathPair _linearVelocityIndexPathPair[3]; +}; + +class HLAGeodeticLocation : public HLAAbstractLocation { +public: + HLAGeodeticLocation() : + _dirty(true), + _cartPosition(SGVec3d::zeros()), + _cartOrientation(SGQuatd::unit()), + _cartBodyVelocity(SGVec3d::zeros()), + _geodPosition(), + _geodEulerRad(SGVec3d::zeros()), + _groundTrackRad(0), + _groundSpeedMPerSec(0), + _verticalSpeedMPerSec(0) + { + updateCartesianFromGeodetic(); + } + + virtual SGVec3d getCartPosition() const + { updateCartesianFromGeodetic(); return _cartPosition; } + virtual void setCartPosition(const SGVec3d& position) + { _cartPosition = position; _dirty = true; } + + virtual SGQuatd getCartOrientation() const + { updateCartesianFromGeodetic(); return _cartOrientation; } + virtual void setCartOrientation(const SGQuatd& orientation) + { _cartOrientation = orientation; _dirty = true; } + + virtual SGVec3d getAngularBodyVelocity() const + { return SGVec3d::zeros(); } + virtual void setAngularBodyVelocity(const SGVec3d& angular) + { } + + virtual SGVec3d getLinearBodyVelocity() const + { updateCartesianFromGeodetic(); return _cartBodyVelocity; } + virtual void setLinearBodyVelocity(const SGVec3d& linear) + { _cartBodyVelocity = linear; _dirty = true; } + + void setLatitudeDeg(double value) + { _geodPosition.setLatitudeDeg(value); _dirty = true; } + double getLatitudeDeg() const + { updateGeodeticFromCartesian(); return _geodPosition.getLatitudeDeg(); } + void setLatitudeRad(double value) + { _geodPosition.setLatitudeRad(value); _dirty = true; } + double getLatitudeRad() const + { updateGeodeticFromCartesian(); return _geodPosition.getLatitudeRad(); } + void setLongitudeDeg(double value) + { _geodPosition.setLongitudeDeg(value); _dirty = true; } + double getLongitudeDeg() const + { updateGeodeticFromCartesian(); return _geodPosition.getLongitudeDeg(); } + void setLongitudeRad(double value) + { _geodPosition.setLongitudeRad(value); _dirty = true; } + double getLongitudeRad() const + { updateGeodeticFromCartesian(); return _geodPosition.getLongitudeRad(); } + void setElevationFt(double value) + { _geodPosition.setElevationFt(value); _dirty = true; } + double getElevationFt() const + { updateGeodeticFromCartesian(); return _geodPosition.getElevationFt(); } + void setElevationM(double value) + { _geodPosition.setElevationM(value); _dirty = true; } + double getElevationM() const + { updateGeodeticFromCartesian(); return _geodPosition.getElevationM(); } + + void setHeadingRad(double value) + { _geodEulerRad[2] = value; _dirty = true; } + double getHeadingRad() const + { updateGeodeticFromCartesian(); return _geodEulerRad[2]; } + void setHeadingDeg(double value) + { setHeadingRad(SGMiscd::deg2rad(value)); } + double getHeadingDeg() const + { return SGMiscd::rad2deg(getHeadingRad()); } + void setPitchRad(double value) + { _geodEulerRad[1] = value; _dirty = true; } + double getPitchRad() const + { updateGeodeticFromCartesian(); return _geodEulerRad[1]; } + void setPitchDeg(double value) + { setPitchRad(SGMiscd::deg2rad(value)); } + double getPitchDeg() const + { return SGMiscd::rad2deg(getPitchRad()); } + void setRollRad(double value) + { _geodEulerRad[0] = value; _dirty = true; } + double getRollRad() const + { updateGeodeticFromCartesian(); return _geodEulerRad[0]; } + void setRollDeg(double value) + { setRollRad(SGMiscd::deg2rad(value)); } + double getRollDeg() const + { return SGMiscd::rad2deg(getRollRad()); } + + void setGroundTrackRad(double value) + { _groundTrackRad = value; _dirty = true; } + double getGroundTrackRad() const + { updateGeodeticFromCartesian(); return _groundTrackRad; } + void setGroundTrackDeg(double value) + { setGroundTrackRad(SGMiscd::deg2rad(value)); } + double getGroundTrackDeg() const + { return SGMiscd::rad2deg(getGroundTrackRad()); } + + + void setGroundSpeedMPerSec(double value) + { _groundSpeedMPerSec = value; _dirty = true; } + double getGroundSpeedMPerSec() const + { updateGeodeticFromCartesian(); return _groundSpeedMPerSec; } + void setGroundSpeedFtPerSec(double value) + { setGroundSpeedMPerSec(SG_FEET_TO_METER*value); } + double getGroundSpeedFtPerSec() const + { return SG_METER_TO_FEET*getGroundSpeedMPerSec(); } + void setGroundSpeedKnots(double value) + { setGroundSpeedMPerSec(SG_KT_TO_MPS*value); } + double getGroundSpeedKnots() const + { return SG_MPS_TO_KT*getGroundSpeedMPerSec(); } + + void setVerticalSpeedMPerSec(double value) + { _verticalSpeedMPerSec = value; _dirty = true; } + double getVerticalSpeedMPerSec() const + { updateGeodeticFromCartesian(); return _verticalSpeedMPerSec; } + void setVerticalSpeedFtPerSec(double value) + { setVerticalSpeedMPerSec(SG_FEET_TO_METER*value); } + double getVerticalSpeedFtPerSec() const + { return SG_METER_TO_FEET*getVerticalSpeedMPerSec(); } + void setVerticalSpeedFtPerMin(double value) + { setVerticalSpeedFtPerSec(value/60); } + double getVerticalSpeedFtPerMin() const + { return 60*getVerticalSpeedFtPerSec(); } + +#define DATA_ELEMENT(name) \ + HLADataElementProvider get## name ## DataElement() \ + { return new DataElement<&HLAGeodeticLocation::get## name, &HLAGeodeticLocation::set ## name>(this); } + + DATA_ELEMENT(LatitudeDeg) + DATA_ELEMENT(LatitudeRad) + DATA_ELEMENT(LongitudeDeg) + DATA_ELEMENT(LongitudeRad) + DATA_ELEMENT(ElevationFt) + DATA_ELEMENT(ElevationM) + DATA_ELEMENT(HeadingDeg) + DATA_ELEMENT(HeadingRad) + DATA_ELEMENT(PitchDeg) + DATA_ELEMENT(PitchRad) + DATA_ELEMENT(RollDeg) + DATA_ELEMENT(RollRad) + + DATA_ELEMENT(GroundTrackDeg) + DATA_ELEMENT(GroundTrackRad) + DATA_ELEMENT(GroundSpeedMPerSec) + DATA_ELEMENT(GroundSpeedFtPerSec) + DATA_ELEMENT(GroundSpeedKnots) + DATA_ELEMENT(VerticalSpeedMPerSec) + DATA_ELEMENT(VerticalSpeedFtPerSec) + DATA_ELEMENT(VerticalSpeedFtPerMin) + +#undef DATA_ELEMENT + +private: + template + class DataElement : public HLAAbstractDoubleDataElement { + public: + DataElement(HLAGeodeticLocation* data) : + _data(data) + { } + virtual double getValue() const + { return (_data->*getter)(); } + virtual void setValue(double value) + { (_data->*setter)(value); } + + private: + SGSharedPtr _data; + }; + + void updateGeodeticFromCartesian() const + { + if (!_dirty) + return; + _geodPosition = SGGeod::fromCart(_cartPosition); + SGQuatd geodOrientation = inverse(SGQuatd::fromLonLat(_geodPosition))*_cartOrientation; + geodOrientation.getEulerRad(_geodEulerRad[2], _geodEulerRad[1], _geodEulerRad[0]); + SGVec3d nedVel = geodOrientation.backTransform(_cartBodyVelocity); + if (SGLimitsd::min() < SGMiscd::max(fabs(nedVel[0]), fabs(nedVel[1]))) + _groundTrackRad = atan2(nedVel[1], nedVel[0]); + else + _groundTrackRad = 0; + _groundSpeedMPerSec = sqrt(nedVel[0]*nedVel[0] + nedVel[1]*nedVel[1]); + _verticalSpeedMPerSec = -nedVel[2]; + _dirty = false; + } + void updateCartesianFromGeodetic() const + { + if (!_dirty) + return; + _cartPosition = SGVec3d::fromGeod(_geodPosition); + SGQuatd geodOrientation = SGQuatd::fromEulerRad(_geodEulerRad[2], _geodEulerRad[1], _geodEulerRad[0]); + _cartOrientation = SGQuatd::fromLonLat(_geodPosition)*geodOrientation; + SGVec3d nedVel(cos(_groundTrackRad)*_groundSpeedMPerSec, + sin(_groundTrackRad)*_groundSpeedMPerSec, + -_verticalSpeedMPerSec); + _cartBodyVelocity = geodOrientation.transform(nedVel); + _dirty = false; + } + + mutable bool _dirty; + + // the cartesian values + mutable SGVec3d _cartPosition; + mutable SGQuatd _cartOrientation; + mutable SGVec3d _cartBodyVelocity; + + // The geodetic values + mutable SGGeod _geodPosition; + mutable SGVec3d _geodEulerRad; + mutable double _groundTrackRad; + mutable double _groundSpeedMPerSec; + mutable double _verticalSpeedMPerSec; +}; + +class HLAGeodeticLocationFactory : public HLALocationFactory { +public: + enum Semantic { + LatitudeDeg, + LatitudeRad, + LongitudeDeg, + LongitudeRad, + ElevationM, + ElevationFt, + HeadingDeg, + HeadingRad, + PitchDeg, + PitchRad, + RollDeg, + RollRad, + GroundTrackDeg, + GroundTrackRad, + GroundSpeedKnots, + GroundSpeedFtPerSec, + GroundSpeedMPerSec, + VerticalSpeedFtPerSec, + VerticalSpeedFtPerMin, + VerticalSpeedMPerSec + }; + + virtual HLAGeodeticLocation* createLocation(HLAAttributePathElementMap& attributePathElementMap) const + { + HLAGeodeticLocation* location = new HLAGeodeticLocation; + + for (IndexPathPairSemanticMap::const_iterator i = _indexPathPairSemanticMap.begin(); + i != _indexPathPairSemanticMap.end(); ++i) { + switch (i->second) { + case LatitudeDeg: + attributePathElementMap[i->first.first][i->first.second] = location->getLatitudeDegDataElement(); + break; + case LatitudeRad: + attributePathElementMap[i->first.first][i->first.second] = location->getLatitudeRadDataElement(); + break; + case LongitudeDeg: + attributePathElementMap[i->first.first][i->first.second] = location->getLongitudeDegDataElement(); + break; + case LongitudeRad: + attributePathElementMap[i->first.first][i->first.second] = location->getLongitudeRadDataElement(); + break; + case ElevationM: + attributePathElementMap[i->first.first][i->first.second] = location->getElevationMDataElement(); + break; + case ElevationFt: + attributePathElementMap[i->first.first][i->first.second] = location->getElevationFtDataElement(); + break; + case HeadingDeg: + attributePathElementMap[i->first.first][i->first.second] = location->getHeadingDegDataElement(); + break; + case HeadingRad: + attributePathElementMap[i->first.first][i->first.second] = location->getHeadingRadDataElement(); + break; + case PitchDeg: + attributePathElementMap[i->first.first][i->first.second] = location->getPitchDegDataElement(); + break; + case PitchRad: + attributePathElementMap[i->first.first][i->first.second] = location->getPitchRadDataElement(); + break; + case RollDeg: + attributePathElementMap[i->first.first][i->first.second] = location->getRollDegDataElement(); + break; + case RollRad: + attributePathElementMap[i->first.first][i->first.second] = location->getRollRadDataElement(); + break; + case GroundTrackDeg: + attributePathElementMap[i->first.first][i->first.second] = location->getGroundTrackDegDataElement(); + break; + case GroundTrackRad: + attributePathElementMap[i->first.first][i->first.second] = location->getGroundTrackRadDataElement(); + break; + case GroundSpeedKnots: + attributePathElementMap[i->first.first][i->first.second] = location->getGroundSpeedKnotsDataElement(); + break; + case GroundSpeedFtPerSec: + attributePathElementMap[i->first.first][i->first.second] = location->getGroundSpeedFtPerSecDataElement(); + break; + case GroundSpeedMPerSec: + attributePathElementMap[i->first.first][i->first.second] = location->getGroundSpeedMPerSecDataElement(); + break; + case VerticalSpeedFtPerSec: + attributePathElementMap[i->first.first][i->first.second] = location->getVerticalSpeedFtPerSecDataElement(); + break; + case VerticalSpeedFtPerMin: + attributePathElementMap[i->first.first][i->first.second] = location->getVerticalSpeedFtPerMinDataElement(); + break; + case VerticalSpeedMPerSec: + attributePathElementMap[i->first.first][i->first.second] = location->getVerticalSpeedMPerSecDataElement(); + break; + } + } + + return location; + } + + void setIndexPathPair(Semantic semantic, const HLADataElement::IndexPathPair& indexPathPair) + { _indexPathPairSemanticMap[indexPathPair] = semantic; } + +private: + typedef std::map IndexPathPairSemanticMap; + IndexPathPairSemanticMap _indexPathPairSemanticMap; +}; + +} // namespace simgear + +#endif diff --git a/simgear/hla/HLAOMTXmlVisitor.cxx b/simgear/hla/HLAOMTXmlVisitor.cxx new file mode 100644 index 00000000..06351d6a --- /dev/null +++ b/simgear/hla/HLAOMTXmlVisitor.cxx @@ -0,0 +1,865 @@ +// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#include "HLAOMTXmlVisitor.hxx" + +#include +#include +#include + +#include +#include +#include "HLAArrayDataType.hxx" +#include "HLABasicDataType.hxx" +#include "HLADataTypeVisitor.hxx" +#include "HLAEnumeratedDataType.hxx" +#include "HLAFixedRecordDataType.hxx" +#include "HLAVariantDataType.hxx" + +namespace simgear { + +HLAOMTXmlVisitor::ObjectClass::ObjectClass(const std::string& name, const std::string& sharing) : + _name(name), + _sharing(sharing) +{ +} + +HLAOMTXmlVisitor::ObjectClass::~ObjectClass() +{ +} + +const std::string& +HLAOMTXmlVisitor::ObjectClass::getName() const +{ + return _name; +} + +const std::string& +HLAOMTXmlVisitor::ObjectClass::getSharing() const +{ + return _sharing; +} + +unsigned +HLAOMTXmlVisitor::ObjectClass::getNumAttributes() const +{ + return _attributes.size(); +} + +const HLAOMTXmlVisitor::Attribute* +HLAOMTXmlVisitor::ObjectClass::getAttribute(unsigned index) const +{ + if (_attributes.size() <= index) + return 0; + return _attributes[index]; +} + +const HLAOMTXmlVisitor::Attribute* +HLAOMTXmlVisitor::ObjectClass::getAttribute(const std::string& name) const +{ + for (AttributeList::const_iterator i = _attributes.begin(); i != _attributes.end(); ++i) { + if ((*i)->_name != name) + continue; + return i->get(); + } + SG_LOG(SG_IO, SG_ALERT, "Could not find class attribute \"" << name << "\"."); + return 0; +} + +const HLAOMTXmlVisitor::ObjectClass* +HLAOMTXmlVisitor::ObjectClass::getParentObjectClass() const +{ + return _parentObjectClass.get(); +} + +HLAOMTXmlVisitor::InteractionClass::InteractionClass(const std::string& name) : + _name(name) +{ +} + +HLAOMTXmlVisitor::InteractionClass::~InteractionClass() +{ +} + +const std::string& +HLAOMTXmlVisitor::InteractionClass::getName() const +{ + return _name; +} + +const std::string& +HLAOMTXmlVisitor::InteractionClass::getDimensions() const +{ + return _dimensions; +} + +const std::string& +HLAOMTXmlVisitor::InteractionClass::getTransportation() const +{ + return _transportation; +} + +const std::string& +HLAOMTXmlVisitor::InteractionClass::getOrder() const +{ + return _order; +} + +unsigned +HLAOMTXmlVisitor::InteractionClass::getNumParameters() const +{ + return _parameters.size(); +} + +const HLAOMTXmlVisitor::Parameter* +HLAOMTXmlVisitor::InteractionClass::getParameter(unsigned index) const +{ + if (_parameters.size() <= index) + return 0; + return _parameters[index]; +} + +const HLAOMTXmlVisitor::Parameter* +HLAOMTXmlVisitor::InteractionClass::getParameter(const std::string& name) const +{ + for (ParameterList::const_iterator i = _parameters.begin(); i != _parameters.end(); ++i) { + if ((*i)->_name != name) + continue; + return i->get(); + } + SG_LOG(SG_IO, SG_ALERT, "Could not find parameter \"" << name << "\"."); + return 0; +} + +const HLAOMTXmlVisitor::InteractionClass* +HLAOMTXmlVisitor::InteractionClass::getParentInteractionClass() const +{ + return _parentInteractionClass.get(); +} + +HLAOMTXmlVisitor::HLAOMTXmlVisitor() +{ +} + +HLAOMTXmlVisitor::~HLAOMTXmlVisitor() +{ +} + +unsigned +HLAOMTXmlVisitor::getNumObjectClasses() const +{ + return _objectClassList.size(); +} + +const HLAOMTXmlVisitor::ObjectClass* +HLAOMTXmlVisitor::getObjectClass(unsigned i) const +{ + if (_objectClassList.size() <= i) + return 0; + return _objectClassList[i]; +} + +const HLAOMTXmlVisitor::ObjectClass* +HLAOMTXmlVisitor::getObjectClass(const std::string& name) const +{ + for (ObjectClassList::const_iterator i = _objectClassList.begin(); i != _objectClassList.end(); ++i) { + if ((*i)->_name != name) + continue; + return i->get(); + } + SG_LOG(SG_IO, SG_ALERT, "Could not resolve ObjectClass \"" << name << "\"."); + return 0; +} + +const HLAOMTXmlVisitor::Attribute* +HLAOMTXmlVisitor::getAttribute(const std::string& objectClassName, const std::string& attributeName) const +{ + const ObjectClass* objectClass = getObjectClass(objectClassName); + if (!objectClass) + return 0; + return objectClass->getAttribute(attributeName); +} + +HLADataType* +HLAOMTXmlVisitor::getAttributeDataType(const std::string& objectClassName, const std::string& attributeName) const +{ + const Attribute* attribute = getAttribute(objectClassName, attributeName); + if (!attribute) + return 0; + return getDataType(attribute->_dataType); +} + +unsigned +HLAOMTXmlVisitor::getNumInteractionClasses() const +{ + return _interactionClassList.size(); +} + +const HLAOMTXmlVisitor::InteractionClass* +HLAOMTXmlVisitor::getInteractionClass(unsigned i) const +{ + if (_interactionClassList.size() <= i) + return 0; + return _interactionClassList[i]; +} + +const HLAOMTXmlVisitor::InteractionClass* +HLAOMTXmlVisitor::getInteractionClass(const std::string& name) const +{ + for (InteractionClassList::const_iterator i = _interactionClassList.begin(); i != _interactionClassList.end(); ++i) { + if ((*i)->_name != name) + continue; + return i->get(); + } + SG_LOG(SG_IO, SG_ALERT, "Could not resolve InteractionClass \"" << name << "\"."); + return 0; +} + +const HLAOMTXmlVisitor::Parameter* +HLAOMTXmlVisitor::getParameter(const std::string& interactionClassName, const std::string& parameterName) const +{ + const InteractionClass* interactionClass = getInteractionClass(interactionClassName); + if (!interactionClass) + return 0; + return interactionClass->getParameter(parameterName); +} + +HLADataType* +HLAOMTXmlVisitor::getParameterDataType(const std::string& interactionClassName, const std::string& parameterName) const +{ + const Parameter* parameter = getParameter(interactionClassName, parameterName); + if (!parameter) + return 0; + return getDataType(parameter->_dataType); +} + +HLADataType* +HLAOMTXmlVisitor::getDataType(const std::string& dataTypeName) const +{ + SGSharedPtr dataType; + { + // Playing dirty things with reference counts + StringDataTypeMap dataTypeMap; + dataType = getDataType(dataTypeName, dataTypeMap); + } + return dataType.release(); +} + +SGSharedPtr +HLAOMTXmlVisitor::getDataType(const std::string& dataTypeName, HLAOMTXmlVisitor::StringDataTypeMap& dataTypeMap) const +{ + StringDataTypeMap::const_iterator i = dataTypeMap.find(dataTypeName); + if (i != dataTypeMap.end()) + return new HLADataTypeReference(i->second); + + SGSharedPtr dataType; + dataType = getBasicDataType(dataTypeName); + if (dataType.valid()) + return dataType; + + dataType = getSimpleDataType(dataTypeName); + if (dataType.valid()) + return dataType; + + dataType = getEnumeratedDataType(dataTypeName); + if (dataType.valid()) + return dataType; + + dataType = getArrayDataType(dataTypeName, dataTypeMap); + if (dataType.valid()) + return dataType; + + dataType = getFixedRecordDataType(dataTypeName, dataTypeMap); + if (dataType.valid()) + return dataType; + + dataType = getVariantDataType(dataTypeName, dataTypeMap); + if (dataType.valid()) + return dataType; + + SG_LOG(SG_IO, SG_WARN, "Could not resolve dataType \"" << dataTypeName << "\"."); + return 0; +} + +SGSharedPtr +HLAOMTXmlVisitor::getBasicDataType(const std::string& dataTypeName) const +{ + BasicDataMap::const_iterator i = _basicDataMap.find(dataTypeName); + if (i == _basicDataMap.end()) + return 0; + if (i->second._size == "8") { + return new HLAUInt8DataType(dataTypeName); + } else if (i->second._size == "16") { + if (i->first.find("Unsigned") != std::string::npos) { + if (i->second._endian == "Little") { + return new HLAUInt16LEDataType(dataTypeName); + } else { + return new HLAUInt16BEDataType(dataTypeName); + } + } else if (i->first.find("octetPair") != std::string::npos) { + if (i->second._endian == "Little") { + return new HLAUInt16LEDataType(dataTypeName); + } else { + return new HLAUInt16BEDataType(dataTypeName); + } + } else { + if (i->second._endian == "Little") { + return new HLAInt16LEDataType(dataTypeName); + } else { + return new HLAInt16BEDataType(dataTypeName); + } + } + } else if (i->second._size == "32") { + if (i->first.find("Unsigned") != std::string::npos) { + if (i->second._endian == "Little") { + return new HLAUInt32LEDataType(dataTypeName); + } else { + return new HLAUInt32BEDataType(dataTypeName); + } + } else if (i->first.find("float") != std::string::npos) { + if (i->second._endian == "Little") { + return new HLAFloat32LEDataType(dataTypeName); + } else { + return new HLAFloat32BEDataType(dataTypeName); + } + } else { + if (i->second._endian == "Little") { + return new HLAInt32LEDataType(dataTypeName); + } else { + return new HLAInt32BEDataType(dataTypeName); + } + } + } else if (i->second._size == "64") { + if (i->first.find("Unsigned") != std::string::npos) { + if (i->second._endian == "Little") { + return new HLAUInt64LEDataType(dataTypeName); + } else { + return new HLAUInt64BEDataType(dataTypeName); + } + } else if (i->first.find("float") != std::string::npos) { + if (i->second._endian == "Little") { + return new HLAFloat64LEDataType(dataTypeName); + } else { + return new HLAFloat64BEDataType(dataTypeName); + } + } else { + if (i->second._endian == "Little") { + return new HLAInt64LEDataType(dataTypeName); + } else { + return new HLAInt64BEDataType(dataTypeName); + } + } + } + + return 0; +} + +SGSharedPtr +HLAOMTXmlVisitor::getSimpleDataType(const std::string& dataTypeName) const +{ + SimpleDataMap::const_iterator i = _simpleDataMap.find(dataTypeName); + if (i == _simpleDataMap.end()) + return 0; + return getDataType(i->second._representation); +} + +SGSharedPtr +HLAOMTXmlVisitor::getEnumeratedDataType(const std::string& dataTypeName) const +{ + EnumeratedDataMap::const_iterator i = _enumeratedDataMap.find(dataTypeName); + if (i == _enumeratedDataMap.end()) + return 0; + + SGSharedPtr enumeratedDataType = new HLAEnumeratedDataType(dataTypeName); + enumeratedDataType->setRepresentation(getBasicDataType(i->second._representation)); + + for (EnumeratorList::const_iterator j = i->second._enumeratorList.begin(); + j != i->second._enumeratorList.end(); ++j) { + if (!enumeratedDataType->addEnumerator(j->_name, j->_values)) { + SG_LOG(SG_IO, SG_ALERT, "Could not add enumerator \"" << j->_name + << "\" to find enumerated data type \"" << dataTypeName << "\"."); + return 0; + } + } + + return enumeratedDataType; +} + +SGSharedPtr +HLAOMTXmlVisitor::getArrayDataType(const std::string& dataTypeName, HLAOMTXmlVisitor::StringDataTypeMap& dataTypeMap) const +{ + ArrayDataMap::const_iterator i = _arrayDataMap.find(dataTypeName); + if (i == _arrayDataMap.end()) + return 0; + SGSharedPtr arrayDataType; + if (i->second._encoding == "HLAvariableArray") { + arrayDataType = new HLAVariableArrayDataType(dataTypeName); + } else if (i->second._encoding == "HLAfixedArray") { + std::stringstream ss(i->second._cardinality); + unsigned cardinality; + ss >> cardinality; + if (ss.fail()) { + SG_LOG(SG_IO, SG_ALERT, "Could not interpret cardinality \"" + << i->second._cardinality << "\" for dataType \"" + << dataTypeName << "\"."); + return 0; + } + SGSharedPtr dataType = new HLAFixedArrayDataType(dataTypeName); + dataType->setNumElements(cardinality); + arrayDataType = dataType; + } else { + SG_LOG(SG_IO, SG_ALERT, "Can not interpret encoding \"" + << i->second._encoding << "\" for dataType \"" + << dataTypeName << "\"."); + return 0; + } + + dataTypeMap[dataTypeName] = arrayDataType; + SGSharedPtr elementDataType = getDataType(i->second._dataType, dataTypeMap); + if (!elementDataType.valid()) { + SG_LOG(SG_IO, SG_ALERT, "Could not interpret dataType \"" + << i->second._dataType << "\" for array data type \"" + << dataTypeName << "\"."); + dataTypeMap.erase(dataTypeName); + return 0; + } + arrayDataType->setElementDataType(elementDataType.get()); + + return arrayDataType; +} + +SGSharedPtr +HLAOMTXmlVisitor::getFixedRecordDataType(const std::string& dataTypeName, HLAOMTXmlVisitor::StringDataTypeMap& dataTypeMap) const +{ + FixedRecordDataMap::const_iterator i = _fixedRecordDataMap.find(dataTypeName); + if (i == _fixedRecordDataMap.end()) + return 0; + + SGSharedPtr dataType = new HLAFixedRecordDataType(dataTypeName); + dataTypeMap[dataTypeName] = dataType; + for (FieldList::size_type j = 0; j < i->second._fieldList.size(); ++j) { + SGSharedPtr fieldDataType = getDataType(i->second._fieldList[j]._dataType, dataTypeMap); + if (!fieldDataType.valid()) { + SG_LOG(SG_IO, SG_ALERT, "Could not get data type \"" << i->second._fieldList[j]._dataType + << "\" for field " << j << "of fixed record data type \"" << dataTypeName << "\"."); + dataTypeMap.erase(dataTypeName); + return 0; + } + dataType->addField(i->second._fieldList[j]._name, fieldDataType.get()); + } + return dataType; +} + +SGSharedPtr +HLAOMTXmlVisitor::getVariantDataType(const std::string& dataTypeName, HLAOMTXmlVisitor::StringDataTypeMap& dataTypeMap) const +{ + VariantRecordDataMap::const_iterator i = _variantRecordDataMap.find(dataTypeName); + if (i == _variantRecordDataMap.end()) + return 0; + SGSharedPtr dataType = new HLAVariantDataType(dataTypeName); + dataTypeMap[dataTypeName] = dataType; + + SGSharedPtr enumeratedDataType = getEnumeratedDataType(i->second._dataType); + if (!enumeratedDataType.valid()) { + SG_LOG(SG_IO, SG_ALERT, "Could not find enumerted data type \"" << i->second._dataType + << "\" for variant data type \"" << dataTypeName << "\"."); + return 0; + } + dataType->setEnumeratedDataType(enumeratedDataType); + + for (AlternativeList::const_iterator j = i->second._alternativeList.begin(); + j != i->second._alternativeList.end(); ++j) { + SGSharedPtr alternativeDataType = getDataType(j->_dataType, dataTypeMap); + if (!alternativeDataType.valid()) { + SG_LOG(SG_IO, SG_ALERT, "Could not resolve alternative dataType \"" << j->_dataType + << "\" for alternative \"" << j->_name << "\"."); + dataTypeMap.erase(dataTypeName); + return 0; + } + if (!dataType->addAlternative(j->_name, j->_enumerator, alternativeDataType.get(), j->_semantics)) { + SG_LOG(SG_IO, SG_ALERT, "Could not add alternative \"" << j->_name << "\"."); + return 0; + } + } + return dataType; +} + +HLAOMTXmlVisitor::Mode +HLAOMTXmlVisitor::getCurrentMode() +{ + if (_modeStack.empty()) + return UnknownMode; + return _modeStack.back(); +} + +void +HLAOMTXmlVisitor::pushMode(HLAOMTXmlVisitor::Mode mode) +{ + _modeStack.push_back(mode); +} + +void +HLAOMTXmlVisitor::popMode() +{ + _modeStack.pop_back(); +} + +void +HLAOMTXmlVisitor::startXML() +{ + _modeStack.clear(); +} + +void +HLAOMTXmlVisitor::endXML() +{ + if (!_modeStack.empty()) + throw sg_exception("Internal parse error!"); + + // propagate parent attributes to the derived classes + for (ObjectClassList::const_iterator i = _objectClassList.begin(); i != _objectClassList.end(); ++i) { + SGSharedPtr objectClass = (*i)->_parentObjectClass; + while (objectClass) { + for (AttributeList::const_reverse_iterator j = objectClass->_attributes.rbegin(); + j != objectClass->_attributes.rend(); ++j) { + (*i)->_attributes.insert((*i)->_attributes.begin(), *j); + } + objectClass = objectClass->_parentObjectClass; + } + } + + // propagate parent parameter to the derived interactions + for (InteractionClassList::const_iterator i = _interactionClassList.begin(); i != _interactionClassList.end(); ++i) { + SGSharedPtr interactionClass = (*i)->_parentInteractionClass; + while (interactionClass) { + for (ParameterList::const_reverse_iterator j = interactionClass->_parameters.rbegin(); + j != interactionClass->_parameters.rend(); ++j) { + (*i)->_parameters.insert((*i)->_parameters.begin(), *j); + } + interactionClass = interactionClass->_parentInteractionClass; + } + } +} + +void +HLAOMTXmlVisitor::startElement(const char* name, const XMLAttributes& atts) +{ + if (strcmp(name, "attribute") == 0) { + if (getCurrentMode() != ObjectClassMode) + throw sg_exception("attribute tag outside objectClass!"); + pushMode(AttributeMode); + + if (_objectClassList.empty()) + throw sg_exception("attribute tag outside of an objectClass"); + + std::string name = getAttribute("name", atts); + if (name.empty()) + throw sg_exception("attribute tag without name attribute"); + + SGSharedPtr attribute = new Attribute(name); + + attribute->_dataType = getAttribute("dataType", atts); + attribute->_updateType = getAttribute("updateType", atts); + attribute->_updateCondition = getAttribute("updateCondition", atts); + attribute->_ownership = getAttribute("ownership", atts); + attribute->_sharing = getAttribute("sharing", atts); + attribute->_dimensions = getAttribute("dimensions", atts); + attribute->_transportation = getAttribute("transportation", atts); + attribute->_order = getAttribute("order", atts); + + _objectClassStack.back()->_attributes.push_back(attribute); + + } else if (strcmp(name, "objectClass") == 0) { + if (getCurrentMode() != ObjectsMode && getCurrentMode() != ObjectClassMode) + throw sg_exception("objectClass tag outside objectClass or objects!"); + pushMode(ObjectClassMode); + + std::string name = getAttribute("name", atts); + if (name.empty()) + throw sg_exception("objectClass tag without name attribute"); + + std::string sharing = getAttribute("sharing", atts); + + // The new ObjectClass + ObjectClass* objectClass = new ObjectClass(name, sharing); + + // Inherit all previous attributes + if (!_objectClassStack.empty()) + objectClass->_parentObjectClass = _objectClassStack.back(); + + _objectClassStack.push_back(objectClass); + _objectClassList.push_back(objectClass); + + } else if (strcmp(name, "objects") == 0) { + if (getCurrentMode() != ObjectModelMode) + throw sg_exception("objects tag outside objectModel!"); + pushMode(ObjectsMode); + + } else if (strcmp(name, "parameter") == 0) { + if (getCurrentMode() != InteractionClassMode) + throw sg_exception("parameter tag outside interactionClass!"); + pushMode(ParameterMode); + + if (_interactionClassList.empty()) + throw sg_exception("parameter tag outside of an interactionClass"); + + std::string name = getAttribute("name", atts); + if (name.empty()) + throw sg_exception("parameter tag without name parameter"); + + SGSharedPtr parameter = new Parameter(name); + parameter->_dataType = getAttribute("dataType", atts); + + _interactionClassStack.back()->_parameters.push_back(parameter); + + } else if (strcmp(name, "interactionClass") == 0) { + if (getCurrentMode() != InteractionsMode && getCurrentMode() != InteractionClassMode) + throw sg_exception("interactionClass tag outside interactions or interactionClass!"); + pushMode(InteractionClassMode); + + std::string name = getAttribute("name", atts); + if (name.empty()) + throw sg_exception("interactionClass tag without name attribute"); + + // The new ObjectClass + InteractionClass* interactionClass = new InteractionClass(name); + interactionClass->_dimensions = getAttribute("dimensions", atts); + interactionClass->_transportation = getAttribute("transportation", atts); + interactionClass->_order = getAttribute("order", atts); + + // Inherit all previous attributes + if (!_interactionClassStack.empty()) + interactionClass->_parentInteractionClass = _interactionClassStack.back(); + + _interactionClassStack.push_back(interactionClass); + _interactionClassList.push_back(interactionClass); + + } else if (strcmp(name, "interactions") == 0) { + if (getCurrentMode() != ObjectModelMode) + throw sg_exception("interactions tag outside objectModel!"); + pushMode(InteractionsMode); + + } else if (strcmp(name, "basicData") == 0) { + if (getCurrentMode() != BasicDataRepresentationsMode) + throw sg_exception("basicData tag outside basicDataRepresentations!"); + pushMode(BasicDataMode); + + std::string name = getAttribute("name", atts); + if (name.empty()) + throw sg_exception("basicData tag without name attribute"); + + _basicDataMap[name]._size = getAttribute("size", atts); + _basicDataMap[name]._endian = getAttribute("endian", atts); + + } else if (strcmp(name, "basicDataRepresentations") == 0) { + if (getCurrentMode() != DataTypesMode) + throw sg_exception("basicDataRepresentations tag outside dataTypes!"); + pushMode(BasicDataRepresentationsMode); + + } else if (strcmp(name, "simpleData") == 0) { + if (getCurrentMode() != SimpleDataTypesMode) + throw sg_exception("simpleData tag outside simpleDataTypes!"); + pushMode(SimpleDataMode); + + std::string name = getAttribute("name", atts); + if (name.empty()) + throw sg_exception("simpleData tag without name attribute"); + + _simpleDataMap[name]._representation = getAttribute("representation", atts); + _simpleDataMap[name]._units = getAttribute("units", atts); + _simpleDataMap[name]._resolution = getAttribute("resolution", atts); + _simpleDataMap[name]._accuracy = getAttribute("accuracy", atts); + + } else if (strcmp(name, "simpleDataTypes") == 0) { + if (getCurrentMode() != DataTypesMode) + throw sg_exception("simpleDataTypes tag outside dataTypes!"); + pushMode(SimpleDataTypesMode); + + } else if (strcmp(name, "enumerator") == 0) { + if (getCurrentMode() != EnumeratedDataMode) + throw sg_exception("enumerator tag outside enumeratedData!"); + pushMode(EnumeratorMode); + + std::string name = getAttribute("name", atts); + if (name.empty()) + throw sg_exception("enumerator tag without name attribute"); + + Enumerator enumerator; + enumerator._name = name; + enumerator._values = getAttribute("values", atts); + _enumeratedDataMap[_enumeratedDataName]._enumeratorList.push_back(enumerator); + + } else if (strcmp(name, "enumeratedData") == 0) { + if (getCurrentMode() != EnumeratedDataTypesMode) + throw sg_exception("enumeratedData tag outside enumeratedDataTypes!"); + pushMode(EnumeratedDataMode); + + std::string name = getAttribute("name", atts); + if (name.empty()) + throw sg_exception("enumeratedData tag without name attribute"); + + _enumeratedDataName = name; + _enumeratedDataMap[_enumeratedDataName]._representation = getAttribute("representation", atts); + + } else if (strcmp(name, "enumeratedDataTypes") == 0) { + if (getCurrentMode() != DataTypesMode) + throw sg_exception("enumeratedDataTypes tag outside dataTypes!"); + pushMode(EnumeratedDataTypesMode); + + Enumerator enumerator; + enumerator._name = getAttribute("name", atts); + enumerator._values = getAttribute("values", atts); + _enumeratedDataMap[_enumeratedDataName]._enumeratorList.push_back(enumerator); + + } else if (strcmp(name, "arrayData") == 0) { + if (getCurrentMode() != ArrayDataTypesMode) + throw sg_exception("arrayData tag outside arrayDataTypes!"); + pushMode(ArrayDataMode); + + std::string name = getAttribute("name", atts); + if (name.empty()) + throw sg_exception("arrayData tag without name attribute"); + + _arrayDataMap[name]._dataType = getAttribute("dataType", atts); + _arrayDataMap[name]._cardinality = getAttribute("cardinality", atts); + _arrayDataMap[name]._encoding = getAttribute("encoding", atts); + + } else if (strcmp(name, "arrayDataTypes") == 0) { + if (getCurrentMode() != DataTypesMode) + throw sg_exception("arrayDataTypes tag outside dataTypes!"); + pushMode(ArrayDataTypesMode); + + } else if (strcmp(name, "field") == 0) { + if (getCurrentMode() != FixedRecordDataMode) + throw sg_exception("field tag outside fixedRecordData!"); + pushMode(FieldMode); + + std::string name = getAttribute("name", atts); + if (name.empty()) + throw sg_exception("field tag without name attribute"); + + Field field; + field._name = name; + field._dataType = getAttribute("dataType", atts); + _fixedRecordDataMap[_fixedRecordDataName]._fieldList.push_back(field); + + } else if (strcmp(name, "fixedRecordData") == 0) { + if (getCurrentMode() != FixedRecordDataTypesMode) + throw sg_exception("fixedRecordData tag outside fixedRecordDataTypes!"); + pushMode(FixedRecordDataMode); + + std::string name = getAttribute("name", atts); + if (name.empty()) + throw sg_exception("fixedRecordData tag without name attribute"); + + _fixedRecordDataName = name; + _fixedRecordDataMap[name]._encoding = getAttribute("encoding", atts); + + } else if (strcmp(name, "fixedRecordDataTypes") == 0) { + if (getCurrentMode() != DataTypesMode) + throw sg_exception("fixedRecordDataTypes tag outside dataTypes!"); + pushMode(FixedRecordDataTypesMode); + + } else if (strcmp(name, "alternative") == 0) { + + if (getCurrentMode() != VariantRecordDataMode) + throw sg_exception("alternative tag outside variantRecordData!"); + pushMode(AlternativeDataMode); + + std::string name = getAttribute("name", atts); + if (name.empty()) + throw sg_exception("alternative tag without name attribute"); + + Alternative alternative; + alternative._name = name; + alternative._dataType = getAttribute("dataType", atts); + alternative._semantics = getAttribute("semantics", atts); + alternative._enumerator = getAttribute("enumerator", atts); + _variantRecordDataMap[_variantRecordDataName]._alternativeList.push_back(alternative); + + } else if (strcmp(name, "variantRecordData") == 0) { + if (getCurrentMode() != VariantRecordDataTypesMode) + throw sg_exception("variantRecordData tag outside variantRecordDataTypes!"); + pushMode(VariantRecordDataMode); + + std::string name = getAttribute("name", atts); + if (name.empty()) + throw sg_exception("fixedRecordData tag without name attribute"); + + _variantRecordDataName = name; + _variantRecordDataMap[name]._encoding = getAttribute("encoding", atts); + _variantRecordDataMap[name]._dataType = getAttribute("dataType", atts); + _variantRecordDataMap[name]._semantics = getAttribute("semantics", atts); + _variantRecordDataMap[name]._discriminant = getAttribute("discriminant", atts); + + } else if (strcmp(name, "variantRecordDataTypes") == 0) { + if (getCurrentMode() != DataTypesMode) + throw sg_exception("variantRecordDataTypes tag outside dataTypes!"); + pushMode(VariantRecordDataTypesMode); + + } else if (strcmp(name, "dataTypes") == 0) { + if (getCurrentMode() != ObjectModelMode) + throw sg_exception("dataTypes tag outside objectModel!"); + pushMode(DataTypesMode); + + } else if (strcmp(name, "objectModel") == 0) { + if (!_modeStack.empty()) + throw sg_exception("objectModel tag not at top level!"); + pushMode(ObjectModelMode); + + } else { + _modeStack.push_back(UnknownMode); + } +} + +void +HLAOMTXmlVisitor::endElement(const char* name) +{ + if (strcmp(name, "objectClass") == 0) { + _objectClassStack.pop_back(); + } else if (strcmp(name, "interactionClass") == 0) { + _interactionClassStack.pop_back(); + } else if (strcmp(name, "enumeratedData") == 0) { + _enumeratedDataName.clear(); + } else if (strcmp(name, "fixedRecordData") == 0) { + _fixedRecordDataName.clear(); + } else if (strcmp(name, "variantRecordData") == 0) { + _variantRecordDataName.clear(); + } + + _modeStack.pop_back(); +} + +std::string +HLAOMTXmlVisitor::getAttribute(const char* name, const XMLAttributes& atts) +{ + int index = atts.findAttribute(name); + if (index < 0 || atts.size() <= index) + return std::string(); + return std::string(atts.getValue(index)); +} + +std::string +HLAOMTXmlVisitor::getAttribute(const std::string& name, const XMLAttributes& atts) +{ + int index = atts.findAttribute(name.c_str()); + if (index < 0 || atts.size() <= index) + return std::string(); + return std::string(atts.getValue(index)); +} + +} // namespace simgear diff --git a/simgear/hla/HLAOMTXmlVisitor.hxx b/simgear/hla/HLAOMTXmlVisitor.hxx new file mode 100644 index 00000000..32a8cd64 --- /dev/null +++ b/simgear/hla/HLAOMTXmlVisitor.hxx @@ -0,0 +1,293 @@ +// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#ifndef HLAOMTXmlVisitor_hxx +#define HLAOMTXmlVisitor_hxx + +#include +#include + +#include +#include +#include +#include "HLADataType.hxx" + +namespace simgear { + +class HLAOMTXmlVisitor : public XMLVisitor { +public: + /// structures representing the federate object model data + struct Attribute : public SGReferenced { + Attribute(const std::string& name) : + _name(name) + { } + const std::string& getName() const + { return _name; } + const std::string& getDimensions() const + { return _dimensions; } + const std::string& getTransportation() const + { return _transportation; } + const std::string& getOrder() const + { return _order; } + + std::string _name; + std::string _dataType; + std::string _updateType; + std::string _updateCondition; + std::string _ownership; + std::string _sharing; + std::string _dimensions; + std::string _transportation; + std::string _order; + friend class HLAOMTXmlVisitor; + }; + typedef std::vector > AttributeList; + + struct ObjectClass : public SGReferenced { + ObjectClass(const std::string& name, const std::string& sharing); + ~ObjectClass(); + + const std::string& getName() const; + const std::string& getSharing() const; + + unsigned getNumAttributes() const; + const Attribute* getAttribute(unsigned index) const; + const Attribute* getAttribute(const std::string& name) const; + + const ObjectClass* getParentObjectClass() const; + + private: + friend class HLAOMTXmlVisitor; + std::string _name; + std::string _sharing; + AttributeList _attributes; + SGSharedPtr _parentObjectClass; + }; + typedef std::vector > ObjectClassList; + + struct Parameter : public SGReferenced { + Parameter(const std::string& name) : + _name(name) + { } + const std::string& getName() const + { return _name; } + const std::string& getDataType() const + { return _dataType; } + + private: + std::string _name; + std::string _dataType; + friend class HLAOMTXmlVisitor; + }; + typedef std::vector > ParameterList; + + struct InteractionClass : public SGReferenced { + InteractionClass(const std::string& name); + ~InteractionClass(); + + const std::string& getName() const; + const std::string& getDimensions() const; + const std::string& getTransportation() const; + const std::string& getOrder() const; + + unsigned getNumParameters() const; + const Parameter* getParameter(unsigned index) const; + const Parameter* getParameter(const std::string& name) const; + + const InteractionClass* getParentInteractionClass() const; + + private: + friend class HLAOMTXmlVisitor; + std::string _name; + std::string _dimensions; + std::string _transportation; + std::string _order; + ParameterList _parameters; + SGSharedPtr _parentInteractionClass; + }; + typedef std::vector > InteractionClassList; + + HLAOMTXmlVisitor(); + ~HLAOMTXmlVisitor(); + + unsigned getNumObjectClasses() const; + const ObjectClass* getObjectClass(unsigned i) const; + const ObjectClass* getObjectClass(const std::string& name) const; + + /// Return the data type from the fom data + const Attribute* getAttribute(const std::string& objectClassName, const std::string& attributeName) const; + /// Return the data type from the fom data + HLADataType* getAttributeDataType(const std::string& objectClassName, const std::string& attributeName) const; + + unsigned getNumInteractionClasses() const; + const InteractionClass* getInteractionClass(unsigned i) const; + const InteractionClass* getInteractionClass(const std::string& name) const; + + /// Return the data type from the fom data + const Parameter* getParameter(const std::string& interactionClassName, const std::string& parameterName) const; + + /// Return the data type from the fom data + HLADataType* getParameterDataType(const std::string& interactionClassName, const std::string& parameterName) const; + + HLADataType* getDataType(const std::string& dataTypeName) const; + +private: + typedef std::map > StringDataTypeMap; + SGSharedPtr getDataType(const std::string& dataTypeName, StringDataTypeMap& dataTypeMap) const; + SGSharedPtr getBasicDataType(const std::string& dataTypeName) const; + SGSharedPtr getSimpleDataType(const std::string& dataTypeName) const; + SGSharedPtr getEnumeratedDataType(const std::string& dataTypeName) const; + SGSharedPtr getArrayDataType(const std::string& dataTypeName, StringDataTypeMap& dataTypeMap) const; + SGSharedPtr getFixedRecordDataType(const std::string& dataTypeName, StringDataTypeMap& dataTypeMap) const; + SGSharedPtr getVariantDataType(const std::string& dataTypeName, StringDataTypeMap& dataTypeMap) const; + + enum Mode { + UnknownMode, + + ObjectModelMode, + + ObjectsMode, + ObjectClassMode, + AttributeMode, + + InteractionsMode, + InteractionClassMode, + ParameterMode, + + DataTypesMode, + BasicDataRepresentationsMode, + BasicDataMode, + SimpleDataTypesMode, + SimpleDataMode, + EnumeratedDataTypesMode, + EnumeratedDataMode, + EnumeratorMode, + ArrayDataTypesMode, + ArrayDataMode, + FixedRecordDataTypesMode, + FixedRecordDataMode, + FieldMode, + VariantRecordDataTypesMode, + VariantRecordDataMode, + AlternativeDataMode + }; + + Mode getCurrentMode(); + void pushMode(Mode mode); + void popMode(); + + virtual void startXML(); + virtual void endXML (); + virtual void startElement(const char* name, const XMLAttributes& atts); + virtual void endElement(const char* name); + + std::string getAttribute(const char* name, const XMLAttributes& atts); + std::string getAttribute(const std::string& name, const XMLAttributes& atts); + + struct BasicData { + // std::string _name; + std::string _size; + std::string _endian; + }; + typedef std::map BasicDataMap; + + struct SimpleData { + // std::string _name; + std::string _representation; + std::string _units; + std::string _resolution; + std::string _accuracy; + }; + typedef std::map SimpleDataMap; + + struct Enumerator { + std::string _name; + std::string _values; + }; + typedef std::vector EnumeratorList; + + struct EnumeratedData { + // std::string _name; + std::string _representation; + EnumeratorList _enumeratorList; + }; + typedef std::map EnumeratedDataMap; + + struct ArrayData { + // std::string _name; + std::string _dataType; + std::string _cardinality; + std::string _encoding; + }; + typedef std::map ArrayDataMap; + + struct Field { + std::string _name; + std::string _dataType; + }; + typedef std::vector FieldList; + + struct FixedRecordData { + // std::string _name; + std::string _encoding; + FieldList _fieldList; + }; + typedef std::map FixedRecordDataMap; + + struct Alternative { + std::string _name; + std::string _dataType; + std::string _semantics; + std::string _enumerator; + }; + typedef std::vector AlternativeList; + + struct VariantRecordData { + // std::string _name; + std::string _encoding; + std::string _dataType; + std::string _discriminant; + std::string _semantics; + AlternativeList _alternativeList; + }; + typedef std::map VariantRecordDataMap; + + std::vector _modeStack; + + /// The total list of object classes + ObjectClassList _objectClassList; + ObjectClassList _objectClassStack; + + /// The total list of interaction classes + InteractionClassList _interactionClassList; + InteractionClassList _interactionClassStack; + + /// DataType definitions + BasicDataMap _basicDataMap; + SimpleDataMap _simpleDataMap; + std::string _enumeratedDataName; + EnumeratedDataMap _enumeratedDataMap; + ArrayDataMap _arrayDataMap; + std::string _fixedRecordDataName; + FixedRecordDataMap _fixedRecordDataMap; + std::string _variantRecordDataName; + VariantRecordDataMap _variantRecordDataMap; +}; + +} // namespace simgear + +#endif diff --git a/simgear/hla/HLAObjectClass.cxx b/simgear/hla/HLAObjectClass.cxx new file mode 100644 index 00000000..4b826562 --- /dev/null +++ b/simgear/hla/HLAObjectClass.cxx @@ -0,0 +1,302 @@ +// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#include "HLAObjectClass.hxx" + +#include "RTIFederate.hxx" +#include "RTIObjectClass.hxx" +#include "RTIObjectInstance.hxx" +#include "HLADataType.hxx" +#include "HLAFederate.hxx" +#include "HLAObjectInstance.hxx" + +namespace simgear { + +HLAObjectClass::InstanceCallback::~InstanceCallback() +{ +} + +void +HLAObjectClass::InstanceCallback::discoverInstance(const HLAObjectClass&, HLAObjectInstance& objectInstance, const RTIData& tag) +{ +} + +void +HLAObjectClass::InstanceCallback::removeInstance(const HLAObjectClass&, HLAObjectInstance& objectInstance, const RTIData& tag) +{ +} + +void +HLAObjectClass::InstanceCallback::registerInstance(const HLAObjectClass&, HLAObjectInstance& objectInstance) +{ +} + +void +HLAObjectClass::InstanceCallback::deleteInstance(const HLAObjectClass&, HLAObjectInstance& objectInstance) +{ +} + +HLAObjectClass::RegistrationCallback::~RegistrationCallback() +{ +} + +HLAObjectClass::HLAObjectClass(const std::string& name, HLAFederate& federate) : + _name(name) +{ + _rtiObjectClass = federate._rtiFederate->createObjectClass(name, this); + if (!_rtiObjectClass.valid()) + SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::HLAObjectClass(): No RTIObjectClass found for \"" << name << "\"!"); +} + +HLAObjectClass::~HLAObjectClass() +{ +} + +unsigned +HLAObjectClass::getNumAttributes() const +{ + if (!_rtiObjectClass.valid()) { + SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::getAttributeIndex(): No RTIObject class for object class \"" << getName() << "\"!"); + return 0; + } + return _rtiObjectClass->getNumAttributes(); +} + +unsigned +HLAObjectClass::getAttributeIndex(const std::string& name) const +{ + if (!_rtiObjectClass.valid()) { + SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::getAttributeIndex(): No RTIObject class for object class \"" << getName() << "\"!"); + return ~0u; + } + return _rtiObjectClass->getOrCreateAttributeIndex(name); +} + +std::string +HLAObjectClass::getAttributeName(unsigned index) const +{ + if (!_rtiObjectClass.valid()) { + SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::getAttributeIndex(): No RTIObject class for object class \"" << getName() << "\"!"); + return 0; + } + return _rtiObjectClass->getAttributeName(index); +} + +const HLADataType* +HLAObjectClass::getAttributeDataType(unsigned index) const +{ + if (!_rtiObjectClass.valid()) { + SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::getAttributeDataType(): No RTIObject class for object class \"" << getName() << "\"!"); + return 0; + } + return _rtiObjectClass->getAttributeDataType(index); +} + +void +HLAObjectClass::setAttributeDataType(unsigned index, const HLADataType* dataType) +{ + if (!_rtiObjectClass.valid()) { + SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::setAttributeDataType(): No RTIObject class for object class \"" << getName() << "\"!"); + return; + } + _rtiObjectClass->setAttributeDataType(index, dataType); +} + +HLAUpdateType +HLAObjectClass::getAttributeUpdateType(unsigned index) const +{ + if (!_rtiObjectClass.valid()) { + SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::getAttributeUpdateType(): No RTIObject class for object class \"" << getName() << "\"!"); + return HLAUndefinedUpdate; + } + return _rtiObjectClass->getAttributeUpdateType(index); +} + +void +HLAObjectClass::setAttributeUpdateType(unsigned index, HLAUpdateType updateType) +{ + if (!_rtiObjectClass.valid()) { + SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::setAttributeUpdateType(): " + "No RTIObject class for object class \"" << getName() << "\"!"); + return; + } + _rtiObjectClass->setAttributeUpdateType(index, updateType); +} + +HLADataElement::IndexPathPair +HLAObjectClass::getIndexPathPair(const HLADataElement::AttributePathPair& attributePathPair) const +{ + unsigned index = getAttributeIndex(attributePathPair.first); + if (getNumAttributes() <= index) { + SG_LOG(SG_NETWORK, SG_ALERT, "HLAObjectClass::getIndexPathPair(\"" + << HLADataElement::toString(attributePathPair) + << "\"): Could not resolve attribute \"" << attributePathPair.first + << "\" for object class \"" << getName() << "\"!"); + } + return HLADataElement::IndexPathPair(index, attributePathPair.second); +} + +HLADataElement::IndexPathPair +HLAObjectClass::getIndexPathPair(const std::string& path) const +{ + return getIndexPathPair(HLADataElement::toAttributePathPair(path)); +} + +bool +HLAObjectClass::subscribe(const std::set& indexSet, bool active) +{ + if (!_rtiObjectClass.valid()) { + SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::subscribe(): No RTIObject class for object class \"" << getName() << "\"!"); + return false; + } + return _rtiObjectClass->subscribe(indexSet, active); +} + +bool +HLAObjectClass::unsubscribe() +{ + if (!_rtiObjectClass.valid()) { + SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::unsubscribe(): No RTIObject class for object class \"" << getName() << "\"!"); + return false; + } + return _rtiObjectClass->unsubscribe(); +} + +bool +HLAObjectClass::publish(const std::set& indexSet) +{ + if (!_rtiObjectClass.valid()) { + SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::publish(): No RTIObject class for object class \"" << getName() << "\"!"); + return false; + } + return _rtiObjectClass->publish(indexSet); +} + +bool +HLAObjectClass::unpublish() +{ + if (!_rtiObjectClass.valid()) { + SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::unpublish(): No RTIObject class for object class \"" << getName() << "\"!"); + return false; + } + return _rtiObjectClass->unpublish(); +} + +void +HLAObjectClass::startRegistration() const +{ +} + +void +HLAObjectClass::stopRegistration() const +{ +} + +HLAObjectInstance* +HLAObjectClass::createObjectInstance(RTIObjectInstance* rtiObjectInstance) +{ + return new HLAObjectInstance(this, rtiObjectInstance); +} + +void +HLAObjectClass::discoverInstance(RTIObjectInstance* objectInstance, const RTIData& tag) +{ + SGSharedPtr hlaObjectInstance = createObjectInstance(objectInstance); + if (hlaObjectInstance.valid()) { + SG_LOG(SG_NETWORK, SG_INFO, "RTI: create new object instance for discovered \"" + << hlaObjectInstance->getName() << "\" object"); + _objectInstanceSet.insert(hlaObjectInstance); + discoverInstanceCallback(*hlaObjectInstance, tag); + } else { + SG_LOG(SG_NETWORK, SG_INFO, "RTI: local delete of \"" << objectInstance->getName() << "\""); + objectInstance->localDeleteObjectInstance(); + } +} + +void +HLAObjectClass::removeInstance(HLAObjectInstance& hlaObjectInstance, const RTIData& tag) +{ + SG_LOG(SG_NETWORK, SG_INFO, "RTI: remove object instance \"" << hlaObjectInstance.getName() << "\""); + removeInstanceCallback(hlaObjectInstance, tag); + _objectInstanceSet.erase(&hlaObjectInstance); +} + +void +HLAObjectClass::registerInstance(HLAObjectInstance& objectInstance) +{ + _objectInstanceSet.insert(&objectInstance); + registerInstanceCallback(objectInstance); +} + +void +HLAObjectClass::deleteInstance(HLAObjectInstance& objectInstance) +{ + deleteInstanceCallback(objectInstance); + _objectInstanceSet.erase(&objectInstance); +} + +void +HLAObjectClass::discoverInstanceCallback(HLAObjectInstance& objectInstance, const RTIData& tag) const +{ + if (!_instanceCallback.valid()) + return; + _instanceCallback->discoverInstance(*this, objectInstance, tag); +} + +void +HLAObjectClass::removeInstanceCallback(HLAObjectInstance& objectInstance, const RTIData& tag) const +{ + if (!_instanceCallback.valid()) + return; + _instanceCallback->removeInstance(*this, objectInstance, tag); +} + +void +HLAObjectClass::registerInstanceCallback(HLAObjectInstance& objectInstance) const +{ + if (!_instanceCallback.valid()) + return; + _instanceCallback->registerInstance(*this, objectInstance); +} + +void +HLAObjectClass::deleteInstanceCallback(HLAObjectInstance& objectInstance) const +{ + if (!_instanceCallback.valid()) + return; + _instanceCallback->deleteInstance(*this, objectInstance); +} + +void +HLAObjectClass::startRegistrationCallback() +{ + if (_registrationCallback.valid()) + _registrationCallback->startRegistration(*this); + else + startRegistration(); +} + +void +HLAObjectClass::stopRegistrationCallback() +{ + if (_registrationCallback.valid()) + _registrationCallback->stopRegistration(*this); + else + stopRegistration(); +} + +} // namespace simgear diff --git a/simgear/hla/HLAObjectClass.hxx b/simgear/hla/HLAObjectClass.hxx new file mode 100644 index 00000000..b0db5ad1 --- /dev/null +++ b/simgear/hla/HLAObjectClass.hxx @@ -0,0 +1,131 @@ +// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#ifndef HLAObjectClass_hxx +#define HLAObjectClass_hxx + +#include +#include +#include + +#include "HLADataType.hxx" +#include "HLAObjectInstance.hxx" + +namespace simgear { + +class RTIObjectClass; +class HLAFederate; + +class HLAObjectClass : public SGWeakReferenced { +public: + HLAObjectClass(const std::string& name, HLAFederate& federate); + virtual ~HLAObjectClass(); + + const std::string& getName() const + { return _name; } + + unsigned getNumAttributes() const; + unsigned getAttributeIndex(const std::string& name) const; + std::string getAttributeName(unsigned index) const; + + const HLADataType* getAttributeDataType(unsigned index) const; + void setAttributeDataType(unsigned index, const HLADataType*); + + HLAUpdateType getAttributeUpdateType(unsigned index) const; + void setAttributeUpdateType(unsigned index, HLAUpdateType updateType); + + HLADataElement::IndexPathPair getIndexPathPair(const HLADataElement::AttributePathPair&) const; + HLADataElement::IndexPathPair getIndexPathPair(const std::string& path) const; + + bool subscribe(const std::set& indexSet, bool active); + bool unsubscribe(); + + bool publish(const std::set& indexSet); + bool unpublish(); + + // Object instance creation and destruction + class InstanceCallback : public SGReferenced { + public: + virtual ~InstanceCallback(); + + virtual void discoverInstance(const HLAObjectClass& objectClass, HLAObjectInstance& objectInstance, const RTIData& tag); + virtual void removeInstance(const HLAObjectClass& objectClass, HLAObjectInstance& objectInstance, const RTIData& tag); + + virtual void registerInstance(const HLAObjectClass& objectClass, HLAObjectInstance& objectInstance); + virtual void deleteInstance(const HLAObjectClass& objectClass, HLAObjectInstance& objectInstance); + }; + + void setInstanceCallback(const SGSharedPtr& instanceCallback) + { _instanceCallback = instanceCallback; } + const SGSharedPtr& getInstanceCallback() const + { return _instanceCallback; } + + // Handles startRegistrationForObjectClass and stopRegistrationForObjectClass events + class RegistrationCallback : public SGReferenced { + public: + virtual ~RegistrationCallback(); + virtual void startRegistration(HLAObjectClass& objectClass) = 0; + virtual void stopRegistration(HLAObjectClass& objectClass) = 0; + }; + + void setRegistrationCallback(const SGSharedPtr& registrationCallback) + { _registrationCallback = registrationCallback; } + const SGSharedPtr& getRegistrationCallback() const + { return _registrationCallback; } + + // Is called by the default registration callback if installed + void startRegistration() const; + void stopRegistration() const; + +protected: + virtual HLAObjectInstance* createObjectInstance(RTIObjectInstance* rtiObjectInstance); + +private: + // The internal entry points from the RTILObjectClass callback functions + void discoverInstance(RTIObjectInstance* objectInstance, const RTIData& tag); + void removeInstance(HLAObjectInstance& objectInstance, const RTIData& tag); + void registerInstance(HLAObjectInstance& objectInstance); + void deleteInstance(HLAObjectInstance& objectInstance); + + void discoverInstanceCallback(HLAObjectInstance& objectInstance, const RTIData& tag) const; + void removeInstanceCallback(HLAObjectInstance& objectInstance, const RTIData& tag) const; + void registerInstanceCallback(HLAObjectInstance& objectInstance) const; + void deleteInstanceCallback(HLAObjectInstance& objectInstance) const; + + void startRegistrationCallback(); + void stopRegistrationCallback(); + friend class HLAObjectInstance; + friend class RTIObjectClass; + + // The object class name + std::string _name; + + // The underlying rti dispatcher class + SGSharedPtr _rtiObjectClass; + + // Callback classes + SGSharedPtr _instanceCallback; + SGSharedPtr _registrationCallback; + + // The set of active objects + typedef std::set > ObjectInstanceSet; + ObjectInstanceSet _objectInstanceSet; +}; + +} // namespace simgear + +#endif diff --git a/simgear/hla/HLAObjectInstance.cxx b/simgear/hla/HLAObjectInstance.cxx new file mode 100644 index 00000000..0324d328 --- /dev/null +++ b/simgear/hla/HLAObjectInstance.cxx @@ -0,0 +1,544 @@ +// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#include "HLAObjectInstance.hxx" + +#include +#include "HLAArrayDataElement.hxx" +#include "HLABasicDataElement.hxx" +#include "HLADataElement.hxx" +#include "HLAEnumeratedDataElement.hxx" +#include "HLAFixedRecordDataElement.hxx" +#include "HLAObjectClass.hxx" +#include "HLAVariantDataElement.hxx" +#include "RTIObjectClass.hxx" +#include "RTIObjectInstance.hxx" + +namespace simgear { + +HLAObjectInstance::HLAObjectInstance(HLAObjectClass* objectClass) : + _objectClass(objectClass) +{ +} + +HLAObjectInstance::HLAObjectInstance(HLAObjectClass* objectClass, RTIObjectInstance* rtiObjectInstance) : + _objectClass(objectClass), + _rtiObjectInstance(rtiObjectInstance) +{ + _rtiObjectInstance->_hlaObjectInstance = this; + _name = _rtiObjectInstance->getName(); +} + +HLAObjectInstance::~HLAObjectInstance() +{ +} + +SGSharedPtr +HLAObjectInstance::getObjectClass() const +{ + return _objectClass.lock(); +} + +unsigned +HLAObjectInstance::getNumAttributes() const +{ + if (!_rtiObjectInstance.valid()) { + SG_LOG(SG_IO, SG_ALERT, "Trying to get number of attributes for inactive object!"); + return 0; + } + return _rtiObjectInstance->getNumAttributes(); +} + +unsigned +HLAObjectInstance::getAttributeIndex(const std::string& name) const +{ + if (!_rtiObjectInstance.valid()) { + SG_LOG(SG_IO, SG_ALERT, "Trying to get attribute index for inactive object!"); + return 0; + } + return _rtiObjectInstance->getAttributeIndex(name); +} + +std::string +HLAObjectInstance::getAttributeName(unsigned index) const +{ + if (!_rtiObjectInstance.valid()) { + SG_LOG(SG_IO, SG_ALERT, "Trying to get attribute name for inactive object!"); + return std::string(); + } + return _rtiObjectInstance->getAttributeName(index); +} + +const HLADataType* +HLAObjectInstance::getAttributeDataType(unsigned index) const +{ + if (!_rtiObjectInstance.valid()) { + SG_LOG(SG_IO, SG_ALERT, "Trying to get attribute index for inactive object!"); + return 0; + } + return _rtiObjectInstance->getAttributeDataType(index); +} + +void +HLAObjectInstance::setAttributeDataElement(unsigned index, SGSharedPtr dataElement) +{ + if (!_rtiObjectInstance.valid()) { + SG_LOG(SG_IO, SG_ALERT, "Trying to set data element for inactive object!"); + return; + } + _rtiObjectInstance->setDataElement(index, dataElement); +} + +HLADataElement* +HLAObjectInstance::getAttributeDataElement(unsigned index) +{ + if (!_rtiObjectInstance.valid()) { + SG_LOG(SG_IO, SG_ALERT, "Trying to set data element for inactive object!"); + return 0; + } + return _rtiObjectInstance->getDataElement(index); +} + +const HLADataElement* +HLAObjectInstance::getAttributeDataElement(unsigned index) const +{ + if (!_rtiObjectInstance.valid()) { + SG_LOG(SG_IO, SG_ALERT, "Trying to set data element for inactive object!"); + return 0; + } + return _rtiObjectInstance->getDataElement(index); +} + +class HLAObjectInstance::DataElementFactoryVisitor : public HLADataTypeVisitor { +public: + DataElementFactoryVisitor(const HLAPathElementMap& pathElementMap) : + _pathElementMap(pathElementMap) + { } + DataElementFactoryVisitor(const HLADataElement::Path& path, const HLAPathElementMap& pathElementMap) : + _pathElementMap(pathElementMap), + _path(path) + { } + virtual ~DataElementFactoryVisitor() {} + + virtual void apply(const HLADataType& dataType) + { + _dataElement = createDataElement(_path, dataType); + if (_dataElement.valid()) + return; + + SG_LOG(SG_NETWORK, SG_ALERT, "HLA: Can not find a suitable data element for data type \"" + << dataType.getName() << "\""); + } + + virtual void apply(const HLAInt8DataType& dataType) + { + _dataElement = createDataElement(_path, dataType); + if (_dataElement.valid()) + return; + + _dataElement = new HLASCharDataElement(&dataType); + } + virtual void apply(const HLAUInt8DataType& dataType) + { + _dataElement = createDataElement(_path, dataType); + if (_dataElement.valid()) + return; + + _dataElement = new HLAUCharDataElement(&dataType); + } + virtual void apply(const HLAInt16DataType& dataType) + { + _dataElement = createDataElement(_path, dataType); + if (_dataElement.valid()) + return; + + _dataElement = new HLAShortDataElement(&dataType); + } + virtual void apply(const HLAUInt16DataType& dataType) + { + _dataElement = createDataElement(_path, dataType); + if (_dataElement.valid()) + return; + + _dataElement = new HLAUShortDataElement(&dataType); + } + virtual void apply(const HLAInt32DataType& dataType) + { + _dataElement = createDataElement(_path, dataType); + if (_dataElement.valid()) + return; + + _dataElement = new HLAIntDataElement(&dataType); + } + virtual void apply(const HLAUInt32DataType& dataType) + { + _dataElement = createDataElement(_path, dataType); + if (_dataElement.valid()) + return; + + _dataElement = new HLAUIntDataElement(&dataType); + } + virtual void apply(const HLAInt64DataType& dataType) + { + _dataElement = createDataElement(_path, dataType); + if (_dataElement.valid()) + return; + + _dataElement = new HLALongDataElement(&dataType); + } + virtual void apply(const HLAUInt64DataType& dataType) + { + _dataElement = createDataElement(_path, dataType); + if (_dataElement.valid()) + return; + + _dataElement = new HLAULongDataElement(&dataType); + } + virtual void apply(const HLAFloat32DataType& dataType) + { + _dataElement = createDataElement(_path, dataType); + if (_dataElement.valid()) + return; + + _dataElement = new HLAFloatDataElement(&dataType); + } + virtual void apply(const HLAFloat64DataType& dataType) + { + _dataElement = createDataElement(_path, dataType); + if (_dataElement.valid()) + return; + + _dataElement = new HLADoubleDataElement(&dataType); + } + + class ArrayDataElementFactory : public HLAArrayDataElement::DataElementFactory { + public: + ArrayDataElementFactory(const HLADataElement::Path& path, const HLAPathElementMap& pathElementMap) : + _path(path) + { + for (HLAPathElementMap::const_iterator i = pathElementMap.lower_bound(path); + i != pathElementMap.end(); ++i) { + if (i->first.begin() != std::search(i->first.begin(), i->first.end(), + path.begin(), path.end())) + break; + _pathElementMap.insert(*i); + } + } + virtual HLADataElement* createElement(const HLAArrayDataElement& element, unsigned index) + { + const HLADataType* dataType = element.getElementDataType(); + if (!dataType) + return 0; + HLADataElement::Path path = _path; + path.push_back(HLADataElement::PathElement(index)); + DataElementFactoryVisitor visitor(path, _pathElementMap); + dataType->accept(visitor); + return visitor._dataElement.release(); + } + private: + HLADataElement::Path _path; + HLAPathElementMap _pathElementMap; + }; + + virtual void apply(const HLAFixedArrayDataType& dataType) + { + _dataElement = createDataElement(_path, dataType); + if (_dataElement.valid()) + return; + + SGSharedPtr arrayDataElement; + arrayDataElement = new HLAArrayDataElement(&dataType); + arrayDataElement->setDataElementFactory(new ArrayDataElementFactory(_path, _pathElementMap)); + arrayDataElement->setNumElements(dataType.getNumElements()); + + _dataElement = arrayDataElement; + } + + virtual void apply(const HLAVariableArrayDataType& dataType) + { + _dataElement = createDataElement(_path, dataType); + if (_dataElement.valid()) + return; + + SGSharedPtr arrayDataElement; + arrayDataElement = new HLAArrayDataElement(&dataType); + arrayDataElement->setDataElementFactory(new ArrayDataElementFactory(_path, _pathElementMap)); + + _dataElement = arrayDataElement; + } + + virtual void apply(const HLAEnumeratedDataType& dataType) + { + _dataElement = createDataElement(_path, dataType); + if (_dataElement.valid()) + return; + + _dataElement = new HLAEnumeratedDataElement(&dataType); + } + + virtual void apply(const HLAFixedRecordDataType& dataType) + { + _dataElement = createDataElement(_path, dataType); + if (_dataElement.valid()) + return; + + SGSharedPtr recordDataElement; + recordDataElement = new HLAFixedRecordDataElement(&dataType); + + unsigned numFields = dataType.getNumFields(); + for (unsigned i = 0; i < numFields; ++i) { + + _path.push_back(HLADataElement::PathElement(dataType.getFieldName(i))); + + dataType.getFieldDataType(i)->accept(*this); + recordDataElement->setField(i, _dataElement.release()); + + _path.pop_back(); + } + _dataElement = recordDataElement; + } + + class VariantDataElementFactory : public HLAVariantDataElement::DataElementFactory { + public: + VariantDataElementFactory(const HLADataElement::Path& path, const HLAPathElementMap& pathElementMap) : + _path(path) + { + for (HLAPathElementMap::const_iterator i = pathElementMap.lower_bound(path); + i != pathElementMap.end(); ++i) { + if (i->first.begin() != std::search(i->first.begin(), i->first.end(), + path.begin(), path.end())) + break; + _pathElementMap.insert(*i); + } + } + virtual HLADataElement* createElement(const HLAVariantDataElement& element, unsigned index) + { + const HLAVariantDataType* dataType = element.getDataType(); + if (!dataType) + return 0; + const HLADataType* alternativeDataType = element.getAlternativeDataType(); + if (!alternativeDataType) + return 0; + HLADataElement::Path path = _path; + path.push_back(HLADataElement::PathElement(dataType->getAlternativeName(index))); + DataElementFactoryVisitor visitor(path, _pathElementMap); + alternativeDataType->accept(visitor); + return visitor._dataElement.release(); + } + private: + HLADataElement::Path _path; + HLAPathElementMap _pathElementMap; + }; + + virtual void apply(const HLAVariantDataType& dataType) + { + _dataElement = createDataElement(_path, dataType); + if (_dataElement.valid()) + return; + + SGSharedPtr variantDataElement; + variantDataElement = new HLAVariantDataElement(&dataType); + variantDataElement->setDataElementFactory(new VariantDataElementFactory(_path, _pathElementMap)); + + _dataElement = variantDataElement; + } + + const SGSharedPtr& getDataElement() const + { return _dataElement; } + +private: + SGSharedPtr createDataElement(const HLADataElement::Path& path, const HLADataType& dataType) + { + HLAPathElementMap::const_iterator i = _pathElementMap.find(path); + if (i == _pathElementMap.end()) { + SG_LOG(SG_IO, SG_WARN, "No dataElement provided for \"" + << HLADataElement::toString(path) << "\"."); + + return 0; + } + SGSharedPtr dataElement = i->second.getDataElement(path); + if (!dataElement->setDataType(&dataType)) { + SG_LOG(SG_IO, SG_ALERT, "Cannot set data type for data element at \"" + << HLADataElement::toString(path) << "\"!"); + return 0; + } + SG_LOG(SG_IO, SG_DEBUG, "Using provided dataElement for \"" + << HLADataElement::toString(path) << "\"."); + return dataElement; + } + + SGSharedPtr _dataElement; + const HLAPathElementMap& _pathElementMap; + HLADataElement::Path _path; +}; + +void +HLAObjectInstance::setAttribute(unsigned index, const HLAPathElementMap& pathElementMap) +{ + const HLADataType* dataType = getAttributeDataType(index); + if (!dataType) { + SG_LOG(SG_IO, SG_ALERT, "Cannot get attribute data type for setting attribute at index " + << index << "!"); + return; + } + + SG_LOG(SG_IO, SG_DEBUG, "Setting DataElement for attribute \"" + << getAttributeName(index) << "\"."); + + DataElementFactoryVisitor visitor(pathElementMap); + dataType->accept(visitor); + setAttributeDataElement(index, visitor.getDataElement()); +} + +void +HLAObjectInstance::setAttributes(const HLAAttributePathElementMap& attributePathElementMap) +{ + for (HLAAttributePathElementMap::const_iterator i = attributePathElementMap.begin(); + i != attributePathElementMap.end(); ++i) { + setAttribute(i->first, i->second); + } +} + +void +HLAObjectInstance::requestAttributeUpdate(unsigned index) +{ + if (!_rtiObjectInstance.valid()) { + SG_LOG(SG_IO, SG_ALERT, "Trying to request attribute update for inactive object!"); + return; + } + _rtiObjectInstance->setRequestAttributeUpdate(index, true); +} + +void +HLAObjectInstance::requestAttributeUpdate() +{ + if (!_rtiObjectInstance.valid()) { + SG_LOG(SG_IO, SG_ALERT, "Trying to request attribute update for inactive object!"); + return; + } + _rtiObjectInstance->setRequestAttributeUpdate(true); +} + +void +HLAObjectInstance::registerInstance() +{ + if (_rtiObjectInstance.valid()) { + SG_LOG(SG_IO, SG_ALERT, "Trying to register object " << getName() << " already known to the RTI!"); + return; + } + SGSharedPtr objectClass = _objectClass.lock(); + if (!objectClass.valid()) { + SG_LOG(SG_IO, SG_ALERT, "Could not register object with unknown object class!"); + return; + } + // This error must have been flagged before + if (!objectClass->_rtiObjectClass.valid()) + return; + _rtiObjectInstance = objectClass->_rtiObjectClass->registerObjectInstance(this); + if (!_rtiObjectInstance.valid()) { + SG_LOG(SG_IO, SG_ALERT, "Could not register object at the RTI!"); + return; + } + _name = _rtiObjectInstance->getName(); + objectClass->registerInstance(*this); +} + +void +HLAObjectInstance::deleteInstance(const RTIData& tag) +{ + if (!_rtiObjectInstance.valid()) { + SG_LOG(SG_IO, SG_ALERT, "Trying to delete inactive object!"); + return; + } + SGSharedPtr objectClass = _objectClass.lock(); + if (!objectClass.valid()) + return; + objectClass->deleteInstance(*this); + _rtiObjectInstance->deleteObjectInstance(tag); +} + +void +HLAObjectInstance::localDeleteInstance() +{ + if (!_rtiObjectInstance.valid()) { + SG_LOG(SG_IO, SG_ALERT, "Trying to delete inactive object!"); + return; + } + _rtiObjectInstance->localDeleteObjectInstance(); +} + +void +HLAObjectInstance::updateAttributeValues(const RTIData& tag) +{ + if (!_rtiObjectInstance.valid()) { + SG_LOG(SG_IO, SG_INFO, "Not updating inactive object!"); + return; + } + if (_attributeCallback.valid()) + _attributeCallback->updateAttributeValues(*this, tag); + _rtiObjectInstance->updateAttributeValues(tag); +} + +void +HLAObjectInstance::updateAttributeValues(const SGTimeStamp& timeStamp, const RTIData& tag) +{ + if (!_rtiObjectInstance.valid()) { + SG_LOG(SG_IO, SG_INFO, "Not updating inactive object!"); + return; + } + if (_attributeCallback.valid()) + _attributeCallback->updateAttributeValues(*this, tag); + _rtiObjectInstance->updateAttributeValues(timeStamp, tag); +} + +void +HLAObjectInstance::reflectQueuedAttributeValues(const SGTimeStamp& timeStamp) +{ + if (!_rtiObjectInstance.valid()) { + SG_LOG(SG_IO, SG_INFO, "Not updating inactive object!"); + return; + } + _rtiObjectInstance->reflectQueuedAttributeValues(timeStamp); +} + +void +HLAObjectInstance::removeInstance(const RTIData& tag) +{ + SGSharedPtr objectClass = _objectClass.lock(); + if (!objectClass.valid()) + return; + objectClass->removeInstanceCallback(*this, tag); +} + +void +HLAObjectInstance::reflectAttributeValues(const RTIIndexDataPairList& dataPairList, const RTIData& tag) +{ + if (!_attributeCallback.valid()) + return; + _attributeCallback->reflectAttributeValues(*this, dataPairList, tag); +} + +void +HLAObjectInstance::reflectAttributeValues(const RTIIndexDataPairList& dataPairList, + const SGTimeStamp& timeStamp, const RTIData& tag) +{ + if (!_attributeCallback.valid()) + return; + _attributeCallback->reflectAttributeValues(*this, dataPairList, timeStamp, tag); +} + +} // namespace simgear diff --git a/simgear/hla/HLAObjectInstance.hxx b/simgear/hla/HLAObjectInstance.hxx new file mode 100644 index 00000000..c0420276 --- /dev/null +++ b/simgear/hla/HLAObjectInstance.hxx @@ -0,0 +1,111 @@ +// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#ifndef HLAObjectInstance_hxx +#define HLAObjectInstance_hxx + +#include + +#include "HLADataElement.hxx" + +class SGTimeStamp; + +namespace simgear { + +class RTIObjectInstance; +class HLAObjectClass; + +class HLAObjectInstance : public SGWeakReferenced { +public: + HLAObjectInstance(HLAObjectClass* objectClass); + HLAObjectInstance(HLAObjectClass* objectClass, RTIObjectInstance* rtiObjectInstance); + virtual ~HLAObjectInstance(); + + const std::string& getName() const + { return _name; } + + SGSharedPtr getObjectClass() const; + + unsigned getNumAttributes() const; + unsigned getAttributeIndex(const std::string& name) const; + std::string getAttributeName(unsigned index) const; + + const HLADataType* getAttributeDataType(unsigned index) const; + + void setAttributeDataElement(unsigned index, SGSharedPtr dataElement); + HLADataElement* getAttributeDataElement(unsigned index); + const HLADataElement* getAttributeDataElement(unsigned index) const; + void setAttribute(unsigned index, const HLAPathElementMap& pathElementMap); + void setAttributes(const HLAAttributePathElementMap& attributePathElementMap); + + // Ask the rti to provide the attribute at index + void requestAttributeUpdate(unsigned index); + void requestAttributeUpdate(); + + void registerInstance(); + void deleteInstance(const RTIData& tag); + void localDeleteInstance(); + + class AttributeCallback : public SGReferenced { + public: + virtual ~AttributeCallback() {} + // Notification about reflect and whatever TBD + // Hmm, don't know yet how this should look like + virtual void updateAttributeValues(HLAObjectInstance& objectInstance, const RTIData& tag) + { } + + virtual void reflectAttributeValues(HLAObjectInstance& objectInstance, + const RTIIndexDataPairList& dataPairList, const RTIData& tag) + { } + virtual void reflectAttributeValues(HLAObjectInstance& objectInstance, const RTIIndexDataPairList& dataPairList, + const SGTimeStamp& timeStamp, const RTIData& tag) + { reflectAttributeValues(objectInstance, dataPairList, tag); } + }; + + void setAttributeCallback(const SGSharedPtr& attributeCallback) + { _attributeCallback = attributeCallback; } + const SGSharedPtr& getAttributeCallback() const + { return _attributeCallback; } + + // Push the current values into the RTI + void updateAttributeValues(const RTIData& tag); + void updateAttributeValues(const SGTimeStamp& timeStamp, const RTIData& tag); + + // Retrieve queued up updates up to and including timestamp, + // Note that this only applies to timestamped updates. + // The unordered updates are reflected as they arrive + void reflectQueuedAttributeValues(const SGTimeStamp& timeStamp); + +private: + void removeInstance(const RTIData& tag); + void reflectAttributeValues(const RTIIndexDataPairList& dataPairList, const RTIData& tag); + void reflectAttributeValues(const RTIIndexDataPairList& dataPairList, const SGTimeStamp& timeStamp, const RTIData& tag); + friend class RTIObjectInstance; + friend class HLAObjectClass; + + class DataElementFactoryVisitor; + + std::string _name; + + SGWeakPtr _objectClass; + SGSharedPtr _rtiObjectInstance; + SGSharedPtr _attributeCallback; +}; + +} // namespace simgear + +#endif diff --git a/simgear/hla/HLAPropertyDataElement.cxx b/simgear/hla/HLAPropertyDataElement.cxx new file mode 100644 index 00000000..db4f00ba --- /dev/null +++ b/simgear/hla/HLAPropertyDataElement.cxx @@ -0,0 +1,269 @@ +// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#include "HLAPropertyDataElement.hxx" + +#include "HLADataTypeVisitor.hxx" + +namespace simgear { + +class HLAPropertyDataElement::DecodeVisitor : public HLADataTypeDecodeVisitor { +public: + DecodeVisitor(HLADecodeStream& stream, HLAPropertyReference& propertyReference) : + HLADataTypeDecodeVisitor(stream), + _propertyReference(propertyReference) + { } + + virtual void apply(const HLAInt8DataType& dataType) + { + int8_t value = 0; + dataType.decode(_stream, value); + _propertyReference.setIntValue(value); + } + virtual void apply(const HLAUInt8DataType& dataType) + { + uint8_t value = 0; + dataType.decode(_stream, value); + _propertyReference.setIntValue(value); + } + virtual void apply(const HLAInt16DataType& dataType) + { + int16_t value = 0; + dataType.decode(_stream, value); + _propertyReference.setIntValue(value); + } + virtual void apply(const HLAUInt16DataType& dataType) + { + uint16_t value = 0; + dataType.decode(_stream, value); + _propertyReference.setIntValue(value); + } + virtual void apply(const HLAInt32DataType& dataType) + { + int32_t value = 0; + dataType.decode(_stream, value); + _propertyReference.setIntValue(value); + } + virtual void apply(const HLAUInt32DataType& dataType) + { + uint32_t value = 0; + dataType.decode(_stream, value); + _propertyReference.setIntValue(value); + } + virtual void apply(const HLAInt64DataType& dataType) + { + int64_t value = 0; + dataType.decode(_stream, value); + _propertyReference.setLongValue(value); + } + virtual void apply(const HLAUInt64DataType& dataType) + { + uint64_t value = 0; + dataType.decode(_stream, value); + _propertyReference.setLongValue(value); + } + virtual void apply(const HLAFloat32DataType& dataType) + { + float value = 0; + dataType.decode(_stream, value); + _propertyReference.setFloatValue(value); + } + virtual void apply(const HLAFloat64DataType& dataType) + { + double value = 0; + dataType.decode(_stream, value); + _propertyReference.setDoubleValue(value); + } + + virtual void apply(const HLAFixedArrayDataType& dataType) + { + unsigned numElements = dataType.getNumElements(); + std::string value; + value.reserve(numElements); + for (unsigned i = 0; i < numElements; ++i) { + HLATemplateDecodeVisitor visitor(_stream); + dataType.getElementDataType()->accept(visitor); + value.push_back(visitor.getValue()); + } + _propertyReference.setStringValue(value); + } + virtual void apply(const HLAVariableArrayDataType& dataType) + { + HLATemplateDecodeVisitor numElementsVisitor(_stream); + dataType.getSizeDataType()->accept(numElementsVisitor); + unsigned numElements = numElementsVisitor.getValue(); + std::string value; + value.reserve(numElements); + for (unsigned i = 0; i < numElements; ++i) { + HLATemplateDecodeVisitor visitor(_stream); + dataType.getElementDataType()->accept(visitor); + value.push_back(visitor.getValue()); + } + _propertyReference.setStringValue(value); + } + +protected: + HLAPropertyReference& _propertyReference; +}; + +class HLAPropertyDataElement::EncodeVisitor : public HLADataTypeEncodeVisitor { +public: + EncodeVisitor(HLAEncodeStream& stream, const HLAPropertyReference& propertyReference) : + HLADataTypeEncodeVisitor(stream), + _propertyReference(propertyReference) + { } + + virtual void apply(const HLAInt8DataType& dataType) + { + dataType.encode(_stream, _propertyReference.getIntValue()); + } + virtual void apply(const HLAUInt8DataType& dataType) + { + dataType.encode(_stream, _propertyReference.getIntValue()); + } + virtual void apply(const HLAInt16DataType& dataType) + { + dataType.encode(_stream, _propertyReference.getIntValue()); + } + virtual void apply(const HLAUInt16DataType& dataType) + { + dataType.encode(_stream, _propertyReference.getIntValue()); + } + virtual void apply(const HLAInt32DataType& dataType) + { + dataType.encode(_stream, _propertyReference.getIntValue()); + } + virtual void apply(const HLAUInt32DataType& dataType) + { + dataType.encode(_stream, _propertyReference.getIntValue()); + } + virtual void apply(const HLAInt64DataType& dataType) + { + dataType.encode(_stream, _propertyReference.getLongValue()); + } + virtual void apply(const HLAUInt64DataType& dataType) + { + dataType.encode(_stream, _propertyReference.getLongValue()); + } + virtual void apply(const HLAFloat32DataType& dataType) + { + dataType.encode(_stream, _propertyReference.getFloatValue()); + } + virtual void apply(const HLAFloat64DataType& dataType) + { + dataType.encode(_stream, _propertyReference.getDoubleValue()); + } + + virtual void apply(const HLAFixedArrayDataType& dataType) + { + unsigned numElements = dataType.getNumElements(); + std::string value = _propertyReference.getStringValue(); + for (unsigned i = 0; i < numElements; ++i) { + if (i < value.size()) { + HLATemplateEncodeVisitor visitor(_stream, value[i]); + dataType.getElementDataType()->accept(visitor); + } else { + HLADataTypeEncodeVisitor visitor(_stream); + dataType.getElementDataType()->accept(visitor); + } + } + } + + virtual void apply(const HLAVariableArrayDataType& dataType) + { + std::string value = _propertyReference.getStringValue(); + HLATemplateEncodeVisitor numElementsVisitor(_stream, value.size()); + dataType.getSizeDataType()->accept(numElementsVisitor); + for (unsigned i = 0; i < value.size(); ++i) { + HLATemplateEncodeVisitor visitor(_stream, value[i]); + dataType.getElementDataType()->accept(visitor); + } + } + +protected: + const HLAPropertyReference& _propertyReference; +}; + +HLAPropertyDataElement::HLAPropertyDataElement(HLAPropertyReference* propertyReference) : + _propertyReference(propertyReference) +{ +} + +HLAPropertyDataElement::HLAPropertyDataElement(const simgear::HLADataType* dataType, HLAPropertyReference* propertyReference) : + _dataType(dataType), + _propertyReference(propertyReference) +{ +} + +HLAPropertyDataElement::~HLAPropertyDataElement() +{ +} + +bool +HLAPropertyDataElement::encode(HLAEncodeStream& stream) const +{ + if (!_dataType.valid()) + return false; + if (_propertyReference.valid()) { + EncodeVisitor visitor(stream, *_propertyReference); + _dataType->accept(visitor); + } else { + HLADataTypeEncodeVisitor visitor(stream); + _dataType->accept(visitor); + } + return true; +} + +bool +HLAPropertyDataElement::decode(HLADecodeStream& stream) +{ + if (!_dataType.valid()) + return false; + if (_propertyReference.valid()) { + DecodeVisitor visitor(stream, *_propertyReference); + _dataType->accept(visitor); + } else { + HLADataTypeDecodeVisitor visitor(stream); + _dataType->accept(visitor); + } + return true; +} + +const HLADataType* +HLAPropertyDataElement::getDataType() const +{ + return _dataType.get(); +} + +bool +HLAPropertyDataElement::setDataType(const HLADataType* dataType) +{ + if (dataType->toBasicDataType()) { + _dataType = dataType; + return true; + } else { + const HLAArrayDataType* arrayDataType = dataType->toArrayDataType(); + if (arrayDataType && arrayDataType->getElementDataType() && + arrayDataType->getElementDataType()->toBasicDataType()) { + _dataType = dataType; + return true; + } + } + return false; +} + +} // namespace simgear diff --git a/simgear/hla/HLAPropertyDataElement.hxx b/simgear/hla/HLAPropertyDataElement.hxx new file mode 100644 index 00000000..4441584e --- /dev/null +++ b/simgear/hla/HLAPropertyDataElement.hxx @@ -0,0 +1,172 @@ +// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#ifndef HLAPropertyDataElement_hxx +#define HLAPropertyDataElement_hxx + +#include +#include +#include "HLADataElement.hxx" + +namespace simgear { + +class HLAPropertyReference : public SGReferenced { +public: + HLAPropertyReference() + { } + HLAPropertyReference(const std::string& relativePath) : + _relativePath(relativePath) + { } + + void setIntValue(int value) + { + if (!_propertyNode.valid()) + return; + _propertyNode->setIntValue(value); + } + int getIntValue() const + { + if (!_propertyNode.valid()) + return 0; + return _propertyNode->getIntValue(); + } + + void setLongValue(long value) + { + if (!_propertyNode.valid()) + return; + _propertyNode->setLongValue(value); + } + long getLongValue() const + { + if (!_propertyNode.valid()) + return 0; + return _propertyNode->getLongValue(); + } + + void setFloatValue(float value) + { + if (!_propertyNode.valid()) + return; + _propertyNode->setFloatValue(value); + } + float getFloatValue() const + { + if (!_propertyNode.valid()) + return 0; + return _propertyNode->getFloatValue(); + } + + void setDoubleValue(double value) + { + if (!_propertyNode.valid()) + return; + _propertyNode->setDoubleValue(value); + } + double getDoubleValue() const + { + if (!_propertyNode.valid()) + return 0; + return _propertyNode->getDoubleValue(); + } + + void setStringValue(const std::string& value) + { + if (!_propertyNode.valid()) + return; + _propertyNode->setStringValue(value); + } + std::string getStringValue() const + { + if (!_propertyNode.valid()) + return std::string(); + return _propertyNode->getStringValue(); + } + + SGPropertyNode* getPropertyNode() + { return _propertyNode.get(); } + + void setRootNode(SGPropertyNode* rootNode) + { + if (!rootNode) + _propertyNode.clear(); + else + _propertyNode = rootNode->getNode(_relativePath, true); + } + +private: + std::string _relativePath; + SGSharedPtr _propertyNode; +}; + +class HLAPropertyReferenceSet : public SGReferenced { +public: + void insert(const SGSharedPtr& propertyReference) + { + _propertyReferenceSet.insert(propertyReference); + propertyReference->setRootNode(_rootNode.get()); + } + void remove(const SGSharedPtr& propertyReference) + { + PropertyReferenceSet::iterator i = _propertyReferenceSet.find(propertyReference); + if (i == _propertyReferenceSet.end()) + return; + _propertyReferenceSet.erase(i); + propertyReference->setRootNode(0); + } + + void setRootNode(SGPropertyNode* rootNode) + { + _rootNode = rootNode; + for (PropertyReferenceSet::iterator i = _propertyReferenceSet.begin(); + i != _propertyReferenceSet.end(); ++i) { + (*i)->setRootNode(_rootNode.get()); + } + } + SGPropertyNode* getRootNode() + { return _rootNode.get(); } + +private: + SGSharedPtr _rootNode; + + typedef std::set > PropertyReferenceSet; + PropertyReferenceSet _propertyReferenceSet; +}; + +class HLAPropertyDataElement : public HLADataElement { +public: + HLAPropertyDataElement(HLAPropertyReference* propertyReference); + HLAPropertyDataElement(const simgear::HLADataType* dataType, HLAPropertyReference* propertyReference); + ~HLAPropertyDataElement(); + + virtual bool encode(HLAEncodeStream& stream) const; + virtual bool decode(HLADecodeStream& stream); + + virtual const HLADataType* getDataType() const; + virtual bool setDataType(const HLADataType* dataType); + +private: + class DecodeVisitor; + class EncodeVisitor; + + SGSharedPtr _dataType; + SGSharedPtr _propertyReference; +}; + +} // namespace simgear + +#endif diff --git a/simgear/hla/HLARawDataElement.cxx b/simgear/hla/HLARawDataElement.cxx new file mode 100644 index 00000000..14dd3ea7 --- /dev/null +++ b/simgear/hla/HLARawDataElement.cxx @@ -0,0 +1,60 @@ +// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#include "HLARawDataElement.hxx" + +namespace simgear { + +HLARawDataElement::HLARawDataElement(const HLADataType* dataType) : + _dataType(dataType) +{ +} + +HLARawDataElement::~HLARawDataElement() +{ +} + +bool +HLARawDataElement::encode(HLAEncodeStream& stream) const +{ + stream.setData(_rtiData); + stream.skip(_rtiData.size()); + return true; +} + +bool +HLARawDataElement::decode(HLADecodeStream& stream) +{ + _rtiData = stream.getData(); + stream.skip(_rtiData.size()); + return true; +} + +const HLADataType* +HLARawDataElement::getDataType() const +{ + return _dataType.get(); +} + +bool +HLARawDataElement::setDataType(const HLADataType* dataType) +{ + _dataType = dataType; + return true; +} + +} diff --git a/simgear/hla/HLARawDataElement.hxx b/simgear/hla/HLARawDataElement.hxx new file mode 100644 index 00000000..ac6bbf66 --- /dev/null +++ b/simgear/hla/HLARawDataElement.hxx @@ -0,0 +1,52 @@ +// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#ifndef HLARawDataElement_hxx +#define HLARawDataElement_hxx + +#include "RTIData.hxx" +#include "HLADataElement.hxx" +#include "HLADataType.hxx" + +namespace simgear { + +class HLARawDataElement : public HLADataElement { +public: + HLARawDataElement(const HLADataType* dataType); + virtual ~HLARawDataElement(); + + virtual bool encode(HLAEncodeStream& stream) const; + virtual bool decode(HLADecodeStream& stream); + + virtual const HLADataType* getDataType() const; + virtual bool setDataType(const HLADataType* dataType); + + const RTIData& getData() const + { return _rtiData; } + RTIData& getData() + { return _rtiData; } + void setData(const RTIData& rtiData) + { _rtiData = rtiData; } + +protected: + SGSharedPtr _dataType; + RTIData _rtiData; +}; + +} + +#endif diff --git a/simgear/hla/HLAVariantDataElement.cxx b/simgear/hla/HLAVariantDataElement.cxx new file mode 100644 index 00000000..98c22f78 --- /dev/null +++ b/simgear/hla/HLAVariantDataElement.cxx @@ -0,0 +1,155 @@ +// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#include "HLAVariantDataElement.hxx" + +#include + +namespace simgear { + +HLAAbstractVariantDataElement::HLAAbstractVariantDataElement(const HLAVariantDataType* dataType) : + _dataType(dataType) +{ +} + +HLAAbstractVariantDataElement::~HLAAbstractVariantDataElement() +{ +} + +bool +HLAAbstractVariantDataElement::decode(HLADecodeStream& stream) +{ + if (!_dataType.valid()) + return false; + return _dataType->decode(stream, *this); +} + +bool +HLAAbstractVariantDataElement::encode(HLAEncodeStream& stream) const +{ + if (!_dataType.valid()) + return false; + return _dataType->encode(stream, *this); +} + +const HLAVariantDataType* +HLAAbstractVariantDataElement::getDataType() const +{ + return _dataType.get(); +} + +bool +HLAAbstractVariantDataElement::setDataType(const HLADataType* dataType) +{ + const HLAVariantDataType* variantDataType = dataType->toVariantDataType(); + if (!variantDataType) { + SG_LOG(SG_NETWORK, SG_WARN, "HLAVariantDataType: unable to set data type!"); + return false; + } + setDataType(variantDataType); + return true; +} + +void +HLAAbstractVariantDataElement::setDataType(const HLAVariantDataType* dataType) +{ + _dataType = dataType; +} + +std::string +HLAAbstractVariantDataElement::getAlternativeName() const +{ + if (!_dataType.valid()) + return std::string(); + return _dataType->getAlternativeName(getAlternativeIndex()); +} + +const HLADataType* +HLAAbstractVariantDataElement::getAlternativeDataType() const +{ + if (!_dataType.valid()) + return 0; + return _dataType->getAlternativeDataType(getAlternativeIndex()); +} + + +HLAVariantDataElement::DataElementFactory::~DataElementFactory() +{ +} + +HLAVariantDataElement::HLAVariantDataElement(const HLAVariantDataType* dataType) : + HLAAbstractVariantDataElement(dataType), + _alternativeIndex(~0u) +{ +} + +HLAVariantDataElement::~HLAVariantDataElement() +{ +} + +bool +HLAVariantDataElement::setAlternativeIndex(unsigned index) +{ + if (_alternativeIndex == index) + return true; + SGSharedPtr dataElement = newElement(index); + if (!dataElement.valid()) + return false; + _dataElement.swap(dataElement); + _alternativeIndex = index; + return true; +} + +bool +HLAVariantDataElement::decodeAlternative(HLADecodeStream& stream) +{ + return _dataElement->decode(stream); +} + +unsigned +HLAVariantDataElement::getAlternativeIndex() const +{ + return _alternativeIndex; +} + +bool +HLAVariantDataElement::encodeAlternative(HLAEncodeStream& stream) const +{ + return _dataElement->encode(stream); +} + +void +HLAVariantDataElement::setDataElementFactory(HLAVariantDataElement::DataElementFactory* dataElementFactory) +{ + _dataElementFactory = dataElementFactory; +} + +HLAVariantDataElement::DataElementFactory* +HLAVariantDataElement::getDataElementFactory() +{ + return _dataElementFactory; +} + +HLADataElement* +HLAVariantDataElement::newElement(unsigned index) +{ + if (!_dataElementFactory.valid()) + return 0; + return _dataElementFactory->createElement(*this, index); +} + +} diff --git a/simgear/hla/HLAVariantDataElement.hxx b/simgear/hla/HLAVariantDataElement.hxx new file mode 100644 index 00000000..b3ced7ca --- /dev/null +++ b/simgear/hla/HLAVariantDataElement.hxx @@ -0,0 +1,82 @@ +// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#ifndef HLAVariantDataElement_hxx +#define HLAVariantDataElement_hxx + +#include +#include +#include "HLADataElement.hxx" +#include "HLAVariantDataType.hxx" + +namespace simgear { + +class HLAAbstractVariantDataElement : public HLADataElement { +public: + HLAAbstractVariantDataElement(const HLAVariantDataType* dataType); + virtual ~HLAAbstractVariantDataElement(); + + virtual bool decode(HLADecodeStream& stream); + virtual bool encode(HLAEncodeStream& stream) const; + + virtual const HLAVariantDataType* getDataType() const; + virtual bool setDataType(const HLADataType* dataType); + void setDataType(const HLAVariantDataType* dataType); + + std::string getAlternativeName() const; + const HLADataType* getAlternativeDataType() const; + + virtual bool setAlternativeIndex(unsigned index) = 0; + virtual bool decodeAlternative(HLADecodeStream& stream) = 0; + virtual unsigned getAlternativeIndex() const = 0; + virtual bool encodeAlternative(HLAEncodeStream& stream) const = 0; + +private: + SGSharedPtr _dataType; +}; + +class HLAVariantDataElement : public HLAAbstractVariantDataElement { +public: + HLAVariantDataElement(const HLAVariantDataType* dataType); + virtual ~HLAVariantDataElement(); + + virtual bool setAlternativeIndex(unsigned index); + virtual bool decodeAlternative(HLADecodeStream& stream); + virtual unsigned getAlternativeIndex() const; + virtual bool encodeAlternative(HLAEncodeStream& stream) const; + + class DataElementFactory : public SGReferenced { + public: + virtual ~DataElementFactory(); + virtual HLADataElement* createElement(const HLAVariantDataElement&, unsigned) = 0; + }; + + void setDataElementFactory(DataElementFactory* dataElementFactory); + DataElementFactory* getDataElementFactory(); + +private: + HLADataElement* newElement(unsigned index); + + SGSharedPtr _dataElement; + unsigned _alternativeIndex; + + SGSharedPtr _dataElementFactory; +}; + +} + +#endif diff --git a/simgear/hla/HLAVariantDataType.cxx b/simgear/hla/HLAVariantDataType.cxx new file mode 100644 index 00000000..45e20dbf --- /dev/null +++ b/simgear/hla/HLAVariantDataType.cxx @@ -0,0 +1,101 @@ +// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#include "HLAVariantDataType.hxx" + +#include "HLADataTypeVisitor.hxx" +#include "HLAVariantDataElement.hxx" + +namespace simgear { + +HLAVariantDataType::HLAVariantDataType(const std::string& name) : + HLADataType(name) +{ +} + +HLAVariantDataType::~HLAVariantDataType() +{ +} + +void +HLAVariantDataType::accept(HLADataTypeVisitor& visitor) const +{ + visitor.apply(*this); +} + +const HLAVariantDataType* +HLAVariantDataType::toVariantDataType() const +{ + return this; +} + +bool +HLAVariantDataType::decode(HLADecodeStream& stream, HLAAbstractVariantDataElement& value) const +{ + if (!stream.alignOffsetForSize(getAlignment())) + return false; + if (!_enumeratedDataType.valid()) + return false; + unsigned index = ~0u; + if (!_enumeratedDataType->decode(stream, index)) + return false; + if (!value.setAlternativeIndex(index)) + return false; + if (!value.decodeAlternative(stream)) + return false; + return true; +} + +bool +HLAVariantDataType::encode(HLAEncodeStream& stream, const HLAAbstractVariantDataElement& value) const +{ + if (!stream.alignOffsetForSize(getAlignment())) + return false; + if (!_enumeratedDataType.valid()) + return false; + unsigned index = value.getAlternativeIndex(); + if (!_enumeratedDataType->encode(stream, index)) + return false; + if (!value.encodeAlternative(stream)) + return false; + return true; +} + +void +HLAVariantDataType::setEnumeratedDataType(HLAEnumeratedDataType* dataType) +{ + _enumeratedDataType = dataType; +} + +bool +HLAVariantDataType::addAlternative(const std::string& name, const std::string& enumerator, + const HLADataType* dataType, const std::string& semantics) +{ + if (!_enumeratedDataType.valid()) + return false; + unsigned index = _enumeratedDataType->getIndex(enumerator); + if (_enumeratedDataType->getNumEnumerators() <= index) + return false; + _alternativeList.resize(_enumeratedDataType->getNumEnumerators()); + _alternativeList[index]._name = name; + _alternativeList[index]._dataType = dataType; + _alternativeList[index]._semantics = semantics; + setAlignment(SGMisc::max(getAlignment(), dataType->getAlignment())); + return true; +} + +} // namespace simgear diff --git a/simgear/hla/HLAVariantDataType.hxx b/simgear/hla/HLAVariantDataType.hxx new file mode 100644 index 00000000..59b4aacd --- /dev/null +++ b/simgear/hla/HLAVariantDataType.hxx @@ -0,0 +1,102 @@ +// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#ifndef HLAVariantDataType_hxx +#define HLAVariantDataType_hxx + +#include +#include +#include "simgear/structure/SGSharedPtr.hxx" +#include "HLADataType.hxx" +#include "HLAEnumeratedDataType.hxx" + +namespace simgear { + +class HLAAbstractVariantDataElement; + +class HLAVariantDataType : public HLADataType { +public: + HLAVariantDataType(const std::string& name = "HLAVariantDataType"); + virtual ~HLAVariantDataType(); + + virtual void accept(HLADataTypeVisitor& visitor) const; + + virtual const HLAVariantDataType* toVariantDataType() const; + + virtual bool decode(HLADecodeStream& stream, HLAAbstractVariantDataElement& value) const; + virtual bool encode(HLAEncodeStream& stream, const HLAAbstractVariantDataElement& value) const; + + const HLAEnumeratedDataType* getEnumeratedDataType() const + { return _enumeratedDataType.get(); } + void setEnumeratedDataType(HLAEnumeratedDataType* dataType); + + bool addAlternative(const std::string& name, const std::string& enumerator, + const HLADataType* dataType, const std::string& semantics); + + unsigned getNumAlternatives() const + { return _alternativeList.size(); } + + unsigned getAlternativeIndex(const std::string& enumerator) const + { + if (!_enumeratedDataType.valid()) + return ~unsigned(0); + return _enumeratedDataType->getIndex(enumerator); + } + + const HLADataType* getAlternativeDataType(unsigned index) const + { + if (_alternativeList.size() <= index) + return 0; + return _alternativeList[index]._dataType.get(); + } + const HLADataType* getAlternativeDataType(const std::string& enumerator) const + { return getAlternativeDataType(getAlternativeIndex(enumerator)); } + + std::string getAlternativeName(unsigned index) const + { + if (_alternativeList.size() <= index) + return std::string(); + return _alternativeList[index]._name; + } + std::string getAlternativeName(const std::string& enumerator) const + { return getAlternativeName(getAlternativeIndex(enumerator)); } + + std::string getAlternativeSemantics(unsigned index) const + { + if (_alternativeList.size() <= index) + return std::string(); + return _alternativeList[index]._semantics; + } + std::string getAlternativeSemantics(const std::string& enumerator) const + { return getAlternativeSemantics(getAlternativeIndex(enumerator)); } + +private: + SGSharedPtr _enumeratedDataType; + + struct Alternative { + std::string _name; + SGSharedPtr _dataType; + std::string _semantics; + }; + + typedef std::vector AlternativeList; + AlternativeList _alternativeList; +}; + +} // namespace simgear + +#endif diff --git a/simgear/hla/Makefile.am b/simgear/hla/Makefile.am index 32ba3953..e4af1531 100644 --- a/simgear/hla/Makefile.am +++ b/simgear/hla/Makefile.am @@ -1,3 +1,69 @@ -includedir = @includedir@/hla - INCLUDES = -I$(top_srcdir) + +lib_LIBRARIES = libsghla.a + +libsghla_adir = @includedir@/hla + +libsghla_a_HEADERS = \ + RTIData.hxx \ + HLAArrayDataElement.hxx \ + HLAArrayDataType.hxx \ + HLABasicDataElement.hxx \ + HLABasicDataType.hxx \ + HLADataElement.hxx \ + HLADataType.hxx \ + HLADataTypeVisitor.hxx \ + HLAEnumeratedDataElement.hxx \ + HLAEnumeratedDataType.hxx \ + HLAFixedRecordDataElement.hxx \ + HLAFixedRecordDataType.hxx \ + HLAFederate.hxx \ + HLAInteractionClass.hxx \ + HLALocation.hxx \ + HLAObjectClass.hxx \ + HLAObjectInstance.hxx \ + HLAOMTXmlVisitor.hxx \ + HLAPropertyDataElement.hxx \ + HLARawDataElement.hxx \ + HLAVariantDataElement.hxx \ + HLAVariantDataType.hxx + +libsghla_a_SOURCES = \ + RTIObjectClass.cxx \ + RTIObjectInstance.cxx \ + RTIFederate.cxx \ + HLAArrayDataElement.cxx \ + HLAArrayDataType.cxx \ + HLABasicDataElement.cxx \ + HLABasicDataType.cxx \ + HLADataElement.cxx \ + HLADataType.cxx \ + HLAEnumeratedDataElement.cxx \ + HLAEnumeratedDataType.cxx \ + HLAFederate.cxx \ + HLAFixedRecordDataElement.cxx \ + HLAFixedRecordDataType.cxx \ + HLAObjectClass.cxx \ + HLAObjectInstance.cxx \ + HLAOMTXmlVisitor.cxx \ + HLAPropertyDataElement.cxx \ + HLARawDataElement.cxx \ + HLAVariantDataElement.cxx \ + HLAVariantDataType.cxx + +if ENABLE_HLA13 + +lib_LIBRARIES += libsghla13.a + +libsghla13_adir = @includedir@/hla + +libsghla13_a_HEADERS = \ + HLA13Federate.hxx + +libsghla13_a_SOURCES = \ + RTI13ObjectClass.cxx \ + RTI13ObjectInstance.cxx \ + RTI13Federate.cxx \ + HLA13Federate.cxx + +endif diff --git a/simgear/hla/RTI13Ambassador.hxx b/simgear/hla/RTI13Ambassador.hxx new file mode 100644 index 00000000..0415c4ad --- /dev/null +++ b/simgear/hla/RTI13Ambassador.hxx @@ -0,0 +1,1115 @@ +// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#ifndef RTIAmbassador_hxx +#define RTIAmbassador_hxx + +#include +#include +#include +#include +#include +#include + +#ifndef RTI_USES_STD_FSTREAM +#define RTI_USES_STD_FSTREAM +#endif + +#include +#include + +#include +#include +#include +#include +#include + +#include "RTIObjectClass.hxx" +#include "RTIData.hxx" +#include "RTI13Federate.hxx" +#include "RTI13ObjectInstance.hxx" + +namespace simgear { + +class RTI13Ambassador : public SGWeakReferenced { +public: + RTI13Ambassador() : + _federateAmbassador(*this), + _timeRegulationEnabled(false), + _timeConstrainedEnabled(false), + _timeAdvancePending(false) + { } + virtual ~RTI13Ambassador() + { } + + // processes the queues that filled up during the past + void processQueues() + { + while (!_queueCallbackList.empty()) { + (*_queueCallbackList.front())(); + _queueCallbackList.pop_front(); + } + + while (!_objectInstancePendingCallbackList.empty()) { + (*_objectInstancePendingCallbackList.begin())->flushPendingRequests(); + _objectInstancePendingCallbackList.erase(_objectInstancePendingCallbackList.begin()); + } + } + + bool getTimeRegulationEnabled() const + { return _timeRegulationEnabled; } + bool getTimeConstrainedEnabled() const + { return _timeConstrainedEnabled; } + bool getTimeAdvancePending() const + { return _timeAdvancePending; } + const SGTimeStamp& getCurrentLogicalTime() const + { return _federateTime; } + + bool getFederationSynchronizationPointAnnounced(const std::string& label) + { return _pendingSyncLabels.find(label) != _pendingSyncLabels.end(); } + bool getFederationSynchronized(const std::string& label) + { + std::set::iterator i = _syncronizedSyncLabels.find(label); + if (i == _syncronizedSyncLabels.end()) + return false; + _syncronizedSyncLabels.erase(i); + return true; + } + + void createFederationExecution(const std::string& name, const std::string& objectModel) + { _rtiAmbassador.createFederationExecution(name.c_str(), objectModel.c_str()); } + void destroyFederationExecution(const std::string& name) + { _rtiAmbassador.destroyFederationExecution(name.c_str()); } + + RTI::FederateHandle joinFederationExecution(const std::string& federate, const std::string& federation) + { return _rtiAmbassador.joinFederationExecution(federate.c_str(), federation.c_str(), &_federateAmbassador); } + void resignFederationExecution() + { _rtiAmbassador.resignFederationExecution(RTI::DELETE_OBJECTS_AND_RELEASE_ATTRIBUTES); } + + void registerFederationSynchronizationPoint(const std::string& label, const RTIData& tag) + { _rtiAmbassador.registerFederationSynchronizationPoint(label.c_str(), tag.data()); } + void synchronizationPointAchieved(const std::string& label) + { _rtiAmbassador.synchronizationPointAchieved(label.c_str()); } + + void publishObjectClass(const RTI::ObjectClassHandle& handle, const RTI::AttributeHandleSet& attributeHandleSet) + { _rtiAmbassador.publishObjectClass(handle, attributeHandleSet); } + void unpublishObjectClass(const RTI::ObjectClassHandle& handle) + { _rtiAmbassador.unpublishObjectClass(handle); } + void subscribeObjectClassAttributes(const RTI::ObjectClassHandle& handle, const RTI::AttributeHandleSet& attributeHandleSet, bool active) + { _rtiAmbassador.subscribeObjectClassAttributes(handle, attributeHandleSet, active ? RTI::RTI_TRUE : RTI::RTI_FALSE); } + void unsubscribeObjectClass(const RTI::ObjectClassHandle& handle) + { _rtiAmbassador.unsubscribeObjectClass(handle); } + + RTI13ObjectInstance* registerObjectInstance(const RTI13ObjectClass* objectClass, HLAObjectInstance* hlaObjectInstance) + { + RTI::ObjectHandle objectHandle = _rtiAmbassador.registerObjectInstance(objectClass->getHandle()); + RTI13ObjectInstance* objectInstance = new RTI13ObjectInstance(objectHandle, hlaObjectInstance, objectClass, this, true); + _objectInstanceMap[objectHandle] = objectInstance; + return objectInstance; + } + void updateAttributeValues(const RTI::ObjectHandle& objectHandle, const RTI::AttributeHandleValuePairSet& attributeValues, + const SGTimeStamp& timeStamp, const RTIData& tag) + { _rtiAmbassador.updateAttributeValues(objectHandle, attributeValues, toFedTime(timeStamp), tag.data()); } + void updateAttributeValues(const RTI::ObjectHandle& objectHandle, const RTI::AttributeHandleValuePairSet& attributeValues, const RTIData& tag) + { _rtiAmbassador.updateAttributeValues(objectHandle, attributeValues, tag.data()); } + + // RTI::EventRetractionHandle sendInteraction(RTI::InteractionClassHandle interactionClassHandle, const RTI::ParameterHandleValuePairSet& parameters, const RTI::FedTime& fedTime, const RTIData& tag) + // { return _rtiAmbassador.sendInteraction(interactionClassHandle, parameters, fedTime, tag.data()); } + // void sendInteraction(RTI::InteractionClassHandle interactionClassHandle, const RTI::ParameterHandleValuePairSet& parameters, const RTIData& tag) + // { _rtiAmbassador.sendInteraction(interactionClassHandle, parameters, tag.data()); } + + void deleteObjectInstance(const RTI::ObjectHandle& objectHandle, const SGTimeStamp& timeStamp, const RTIData& tag) + { + RTI::EventRetractionHandle h = _rtiAmbassador.deleteObjectInstance(objectHandle, toFedTime(timeStamp), tag.data()); + ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle); + if (i == _objectInstanceMap.end()) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class: ObjectInstance not found."); + return; + } + _objectInstancePendingCallbackList.erase(i->second); + _objectInstanceMap.erase(i); + } + void deleteObjectInstance(const RTI::ObjectHandle& objectHandle, const RTIData& tag) + { + _rtiAmbassador.deleteObjectInstance(objectHandle, tag.data()); + ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle); + if (i == _objectInstanceMap.end()) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class: ObjectInstance not found."); + return; + } + _objectInstancePendingCallbackList.erase(i->second); + _objectInstanceMap.erase(i); + } + void localDeleteObjectInstance(const RTI::ObjectHandle& objectHandle) + { + _rtiAmbassador.localDeleteObjectInstance(objectHandle); + ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle); + if (i == _objectInstanceMap.end()) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class: ObjectInstance not found."); + return; + } + _objectInstancePendingCallbackList.erase(i->second); + _objectInstanceMap.erase(i); + } + + void requestObjectAttributeValueUpdate(const RTI::ObjectHandle& handle, const RTI::AttributeHandleSet& attributeHandleSet) + { _rtiAmbassador.requestObjectAttributeValueUpdate(handle, attributeHandleSet); } + void requestClassAttributeValueUpdate(const RTI::ObjectClassHandle& handle, const RTI::AttributeHandleSet& attributeHandleSet) + { _rtiAmbassador.requestClassAttributeValueUpdate(handle, attributeHandleSet); } + + // Ownership Management ------------------- + + // bool unconditionalAttributeOwnershipDivestiture(const RTIHandle& objectHandle, const RTIHandleSet& attributeHandles) + // { + // try { + // std::auto_ptr attributeHandleSet(RTI::AttributeHandleSetFactory::create(attributeHandles.size())); + // for (RTIHandleSet::const_iterator i = attributeHandles.begin(); i != attributeHandles.end(); ++i) + // attributeHandleSet->add(*i); + // _rtiAmbassador.unconditionalAttributeOwnershipDivestiture(objectHandle, *attributeHandleSet); + // return true; + // } catch (RTI::ObjectNotKnown& e) { + // } catch (RTI::AttributeNotDefined& e) { + // } catch (RTI::AttributeNotOwned& e) { + // } catch (RTI::FederateNotExecutionMember& e) { + // } catch (RTI::ConcurrentAccessAttempted& e) { + // } catch (RTI::SaveInProgress& e) { + // } catch (RTI::RestoreInProgress& e) { + // } catch (RTI::RTIinternalError& e) { + // } + // return false; + // } + // bool negotiatedAttributeOwnershipDivestiture(const RTIHandle& objectHandle, const RTIHandleSet& attributeHandles, const RTIData& tag) + // { + // try { + // std::auto_ptr attributeHandleSet(RTI::AttributeHandleSetFactory::create(attributeHandles.size())); + // for (RTIHandleSet::const_iterator i = attributeHandles.begin(); i != attributeHandles.end(); ++i) + // attributeHandleSet->add(*i); + // _rtiAmbassador.negotiatedAttributeOwnershipDivestiture(objectHandle, *attributeHandleSet, tag.data()); + // return true; + // } catch (RTI::ObjectNotKnown& e) { + // } catch (RTI::AttributeNotDefined& e) { + // } catch (RTI::AttributeNotOwned& e) { + // } catch (RTI::AttributeAlreadyBeingDivested& e) { + // } catch (RTI::FederateNotExecutionMember& e) { + // } catch (RTI::ConcurrentAccessAttempted& e) { + // } catch (RTI::SaveInProgress& e) { + // } catch (RTI::RestoreInProgress& e) { + // } catch (RTI::RTIinternalError& e) { + // } + // return false; + // } + // bool attributeOwnershipAcquisition(const RTIHandle& objectHandle, const RTIHandleSet& attributeHandles, const RTIData& tag) + // { + // try { + // std::auto_ptr attributeHandleSet(RTI::AttributeHandleSetFactory::create(attributeHandles.size())); + // for (RTIHandleSet::const_iterator i = attributeHandles.begin(); i != attributeHandles.end(); ++i) + // attributeHandleSet->add(*i); + // _rtiAmbassador.attributeOwnershipAcquisition(objectHandle, *attributeHandleSet, tag.data()); + // return true; + // } catch (RTI::ObjectNotKnown& e) { + // } catch (RTI::ObjectClassNotPublished& e) { + // } catch (RTI::AttributeNotDefined& e) { + // } catch (RTI::AttributeNotPublished& e) { + // } catch (RTI::FederateOwnsAttributes& e) { + // } catch (RTI::FederateNotExecutionMember& e) { + // } catch (RTI::ConcurrentAccessAttempted& e) { + // } catch (RTI::SaveInProgress& e) { + // } catch (RTI::RestoreInProgress& e) { + // } catch (RTI::RTIinternalError& e) { + // } + // return false; + // } + // bool attributeOwnershipAcquisitionIfAvailable(const RTIHandle& objectHandle, const RTIHandleSet& attributeHandles) + // { + // try { + // std::auto_ptr attributeHandleSet(RTI::AttributeHandleSetFactory::create(attributeHandles.size())); + // for (RTIHandleSet::const_iterator i = attributeHandles.begin(); i != attributeHandles.end(); ++i) + // attributeHandleSet->add(*i); + // _rtiAmbassador.attributeOwnershipAcquisitionIfAvailable(objectHandle, *attributeHandleSet); + // return true; + // } catch (RTI::ObjectNotKnown& e) { + // } catch (RTI::ObjectClassNotPublished& e) { + // } catch (RTI::AttributeNotDefined& e) { + // } catch (RTI::AttributeNotPublished& e) { + // } catch (RTI::FederateOwnsAttributes& e) { + // } catch (RTI::AttributeAlreadyBeingAcquired& e) { + // } catch (RTI::FederateNotExecutionMember& e) { + // } catch (RTI::ConcurrentAccessAttempted& e) { + // } catch (RTI::SaveInProgress& e) { + // } catch (RTI::RestoreInProgress& e) { + // } catch (RTI::RTIinternalError& e) { + // } + // return false; + // } + // RTIHandleSet attributeOwnershipReleaseResponse(const RTIHandle& objectHandle, const RTIHandleSet& attributeHandles) + // { + // try { + // std::auto_ptr attributeHandleSet(RTI::AttributeHandleSetFactory::create(attributeHandles.size())); + // for (RTIHandleSet::const_iterator i = attributeHandles.begin(); i != attributeHandles.end(); ++i) + // attributeHandleSet->add(*i); + // attributeHandleSet.reset(_rtiAmbassador.attributeOwnershipReleaseResponse(objectHandle, *attributeHandleSet)); + // RTIHandleSet handleSet; + // RTI::ULong numAttribs = attributeHandleSet->size(); + // for (RTI::ULong i = 0; i < numAttribs; ++i) + // handleSet.insert(attributeHandleSet->getHandle(i)); + // return handleSet; + // } catch (RTI::ObjectNotKnown& e) { + // } catch (RTI::AttributeNotDefined& e) { + // } catch (RTI::AttributeNotOwned& e) { + // } catch (RTI::FederateWasNotAskedToReleaseAttribute& e) { + // } catch (RTI::FederateNotExecutionMember& e) { + // } catch (RTI::ConcurrentAccessAttempted& e) { + // } catch (RTI::SaveInProgress& e) { + // } catch (RTI::RestoreInProgress& e) { + // } catch (RTI::RTIinternalError& e) { + // } + // return RTIHandleSet(); + // } + // bool cancelNegotiatedAttributeOwnershipDivestiture(const RTIHandle& objectHandle, const RTIHandleSet& attributeHandles) + // { + // try { + // std::auto_ptr attributeHandleSet(RTI::AttributeHandleSetFactory::create(attributeHandles.size())); + // for (RTIHandleSet::const_iterator i = attributeHandles.begin(); i != attributeHandles.end(); ++i) + // attributeHandleSet->add(*i); + // _rtiAmbassador.cancelNegotiatedAttributeOwnershipDivestiture(objectHandle, *attributeHandleSet); + // return true; + // } catch (RTI::ObjectNotKnown& e) { + // } catch (RTI::AttributeNotDefined& e) { + // } catch (RTI::AttributeNotOwned& e) { + // } catch (RTI::AttributeDivestitureWasNotRequested& e) { + // } catch (RTI::FederateNotExecutionMember& e) { + // } catch (RTI::ConcurrentAccessAttempted& e) { + // } catch (RTI::SaveInProgress& e) { + // } catch (RTI::RestoreInProgress& e) { + // } catch (RTI::RTIinternalError& e) { + // } + // return false; + // } + // bool cancelAttributeOwnershipAcquisition(const RTIHandle& objectHandle, const RTIHandleSet& attributeHandles) + // { + // try { + // std::auto_ptr attributeHandleSet(RTI::AttributeHandleSetFactory::create(attributeHandles.size())); + // for (RTIHandleSet::const_iterator i = attributeHandles.begin(); i != attributeHandles.end(); ++i) + // attributeHandleSet->add(*i); + // _rtiAmbassador.cancelAttributeOwnershipAcquisition(objectHandle, *attributeHandleSet); + // return true; + // } catch (RTI::ObjectNotKnown& e) { + // } catch (RTI::AttributeNotDefined& e) { + // } catch (RTI::AttributeAlreadyOwned& e) { + // } catch (RTI::AttributeAcquisitionWasNotRequested& e) { + // } catch (RTI::FederateNotExecutionMember& e) { + // } catch (RTI::ConcurrentAccessAttempted& e) { + // } catch (RTI::SaveInProgress& e) { + // } catch (RTI::RestoreInProgress& e) { + // } catch (RTI::RTIinternalError& e) { + // } + // return false; + // } + // bool queryAttributeOwnership(const RTIHandle& objectHandle, const RTIHandle& attributeHandle) + // { + // try { + // _rtiAmbassador.queryAttributeOwnership(objectHandle, attributeHandle); + // return true; + // } catch (RTI::ObjectNotKnown& e) { + // } catch (RTI::AttributeNotDefined& e) { + // } catch (RTI::FederateNotExecutionMember& e) { + // } catch (RTI::ConcurrentAccessAttempted& e) { + // } catch (RTI::SaveInProgress& e) { + // } catch (RTI::RestoreInProgress& e) { + // } catch (RTI::RTIinternalError& e) { + // } + // return false; + // } + // bool isAttributeOwnedByFederate(const RTIHandle& objectHandle, const RTIHandle& attributeHandle) + // { + // try { + // return _rtiAmbassador.isAttributeOwnedByFederate(objectHandle, attributeHandle); + // } catch (RTI::ObjectNotKnown& e) { + // } catch (RTI::AttributeNotDefined& e) { + // } catch (RTI::FederateNotExecutionMember& e) { + // } catch (RTI::ConcurrentAccessAttempted& e) { + // } catch (RTI::SaveInProgress& e) { + // } catch (RTI::RestoreInProgress& e) { + // } catch (RTI::RTIinternalError& e) { + // } + // return false; + // } + + /// Time Management + + void enableTimeRegulation(const SGTimeStamp& federateTime, const SGTimeStamp& lookahead) + { _rtiAmbassador.enableTimeRegulation(toFedTime(federateTime), toFedTime(lookahead)); } + void disableTimeRegulation() + { _rtiAmbassador.disableTimeRegulation(); _timeRegulationEnabled = false; } + + void enableTimeConstrained() + { _rtiAmbassador.enableTimeConstrained(); } + void disableTimeConstrained() + { _rtiAmbassador.disableTimeConstrained(); _timeConstrainedEnabled = false; } + + void timeAdvanceRequest(const SGTimeStamp& time) + { _rtiAmbassador.timeAdvanceRequest(toFedTime(time)); _timeAdvancePending = true; } + void timeAdvanceRequestAvailable(const SGTimeStamp& time) + { _rtiAmbassador.timeAdvanceRequestAvailable(toFedTime(time)); _timeAdvancePending = true; } + + // bool queryLBTS(double& time) + // { + // try { + // RTIfedTime fedTime; + // _rtiAmbassador.queryLBTS(fedTime); + // time = fedTime.getTime(); + // return true; + // } catch (RTI::FederateNotExecutionMember& e) { + // } catch (RTI::ConcurrentAccessAttempted& e) { + // } catch (RTI::SaveInProgress& e) { + // } catch (RTI::RestoreInProgress& e) { + // } catch (RTI::RTIinternalError& e) { + // } + // return false; + // } + // bool queryFederateTime(double& time) + // { + // try { + // RTIfedTime fedTime; + // _rtiAmbassador.queryFederateTime(fedTime); + // time = fedTime.getTime(); + // return true; + // } catch (RTI::FederateNotExecutionMember& e) { + // } catch (RTI::ConcurrentAccessAttempted& e) { + // } catch (RTI::SaveInProgress& e) { + // } catch (RTI::RestoreInProgress& e) { + // } catch (RTI::RTIinternalError& e) { + // } + // return false; + // } + + // bool queryLookahead(double& time) + // { + // try { + // RTIfedTime fedTime; + // _rtiAmbassador.queryLookahead(fedTime); + // time = fedTime.getTime(); + // return true; + // } catch (RTI::FederateNotExecutionMember& e) { + // } catch (RTI::ConcurrentAccessAttempted& e) { + // } catch (RTI::SaveInProgress& e) { + // } catch (RTI::RestoreInProgress& e) { + // } catch (RTI::RTIinternalError& e) { + // } + // return false; + // } + + RTI13ObjectClass* createObjectClass(const std::string& name, HLAObjectClass* hlaObjectClass) + { + RTI::ObjectClassHandle objectClassHandle; + objectClassHandle = getObjectClassHandle(name); + if (_objectClassMap.find(objectClassHandle) != _objectClassMap.end()) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not create object class, object class already exists!"); + return 0; + } + RTI13ObjectClass* rtiObjectClass; + rtiObjectClass = new RTI13ObjectClass(hlaObjectClass, objectClassHandle, this); + _objectClassMap[objectClassHandle] = rtiObjectClass; + return rtiObjectClass; + } + RTI::ObjectClassHandle getObjectClassHandle(const std::string& name) + { return _rtiAmbassador.getObjectClassHandle(name.c_str()); } + std::string getObjectClassName(const RTI::ObjectClassHandle& handle) + { return rtiToStdString(_rtiAmbassador.getObjectClassName(handle)); } + + RTI::AttributeHandle getAttributeHandle(const std::string& attributeName, const RTI::ObjectClassHandle& objectClassHandle) + { return _rtiAmbassador.getAttributeHandle(attributeName.c_str(), objectClassHandle); } + std::string getAttributeName(const RTI::AttributeHandle& attributeHandle, const RTI::ObjectClassHandle& objectClassHandle) + { return rtiToStdString(_rtiAmbassador.getAttributeName(attributeHandle, objectClassHandle)); } + + // RTIHandle getInteractionClassHandle(const std::string& name) + // { + // try { + // return _rtiAmbassador.getInteractionClassHandle(name.c_str()); + // } catch (RTI::NameNotFound& e) { + // } catch (RTI::FederateNotExecutionMember& e) { + // } catch (RTI::ConcurrentAccessAttempted& e) { + // } catch (RTI::RTIinternalError& e) { + // } + // return RTIHandle(-1); + // } + // std::string getInteractionClassName(const RTIHandle& handle) + // { + // std::string name; + // try { + // rtiToStdString(name, _rtiAmbassador.getInteractionClassName(handle)); + // } catch (RTI::InteractionClassNotDefined& e) { + // } catch (RTI::FederateNotExecutionMember& e) { + // } catch (RTI::ConcurrentAccessAttempted& e) { + // } catch (RTI::RTIinternalError& e) { + // } + // return name; + // } + + // RTIHandle getParameterHandle(const std::string& parameterName, const RTIHandle& interactionClassHandle) + // { + // try { + // return _rtiAmbassador.getParameterHandle(parameterName.c_str(), interactionClassHandle); + // } catch (RTI::InteractionClassNotDefined& e) { + // } catch (RTI::NameNotFound& e) { + // } catch (RTI::FederateNotExecutionMember& e) { + // } catch (RTI::ConcurrentAccessAttempted& e) { + // } catch (RTI::RTIinternalError& e) { + // } + // return RTIHandle(-1); + // } + // std::string getParameterName(const RTIHandle& parameterHandle, const RTIHandle& interactionClassHandle) + // { + // std::string parameterName; + // try { + // rtiToStdString(parameterName, _rtiAmbassador.getParameterName(parameterHandle, interactionClassHandle)); + // } catch (RTI::InteractionClassNotDefined& e) { + // } catch (RTI::InteractionParameterNotDefined& e) { + // } catch (RTI::FederateNotExecutionMember& e) { + // } catch (RTI::ConcurrentAccessAttempted& e) { + // } catch (RTI::RTIinternalError& e) { + // } + // return parameterName; + // } + + RTI13ObjectInstance* getObjectInstance(const std::string& name) + { + RTI::ObjectHandle objectHandle; + objectHandle = getObjectInstanceHandle(name); + ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle); + if (i == _objectInstanceMap.end()) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class: ObjectInstance not found."); + return 0; + } + return i->second; + } + RTI::ObjectHandle getObjectInstanceHandle(const std::string& name) + { return _rtiAmbassador.getObjectInstanceHandle(name.c_str()); } + std::string getObjectInstanceName(const RTI::ObjectHandle& objectHandle) + { return rtiToStdString(_rtiAmbassador.getObjectInstanceName(objectHandle)); } + + // RTIHandle getRoutingSpaceHandle(const std::string& routingSpaceName) + // { + // try { + // return _rtiAmbassador.getRoutingSpaceHandle(routingSpaceName.c_str()); + // } catch (RTI::NameNotFound& e) { + // } catch (RTI::FederateNotExecutionMember& e) { + // } catch (RTI::ConcurrentAccessAttempted& e) { + // } catch (RTI::RTIinternalError& e) { + // } + // return RTIHandle(-1); + // } + // std::string getRoutingSpaceName(const RTIHandle& routingSpaceHandle) + // { + // std::string routingSpaceName; + // try { + // rtiToStdString(routingSpaceName, _rtiAmbassador.wgetRoutingSpaceName(routingSpaceHandle)); + // } catch (RTI::SpaceNotDefined& e) { + // } catch (RTI::FederateNotExecutionMember& e) { + // } catch (RTI::ConcurrentAccessAttempted& e) { + // } catch (RTI::RTIinternalError& e) { + // } + // return routingSpaceName; + // } + + void enableClassRelevanceAdvisorySwitch() + { _rtiAmbassador.enableClassRelevanceAdvisorySwitch(); } + void disableClassRelevanceAdvisorySwitch() + { _rtiAmbassador.disableClassRelevanceAdvisorySwitch(); } + + void enableAttributeRelevanceAdvisorySwitch() + { _rtiAmbassador.enableAttributeRelevanceAdvisorySwitch(); } + void disableAttributeRelevanceAdvisorySwitch() + { _rtiAmbassador.disableAttributeRelevanceAdvisorySwitch(); } + + void enableAttributeScopeAdvisorySwitch() + { _rtiAmbassador.enableAttributeScopeAdvisorySwitch(); } + void disableAttributeScopeAdvisorySwitch() + { _rtiAmbassador.disableAttributeScopeAdvisorySwitch(); } + + void enableInteractionRelevanceAdvisorySwitch() + { _rtiAmbassador.enableInteractionRelevanceAdvisorySwitch(); } + void disableInteractionRelevanceAdvisorySwitch() + { _rtiAmbassador.disableInteractionRelevanceAdvisorySwitch(); } + + + bool tick() + { return _rtiAmbassador.tick(); } + bool tick(double minimum, double maximum) + { return _rtiAmbassador.tick(minimum, maximum); } + + void addObjectInstanceForCallback(RTIObjectInstance* objectIntance) + { _objectInstancePendingCallbackList.insert(objectIntance); } + +private: + /// Generic callback to execute some notification on objects in a way that they are not prone to + /// ConcurrentAccess exceptions. + class QueueCallback : public SGReferenced { + public: + virtual ~QueueCallback() {} + virtual void operator()() = 0; + }; + + class RemoveObjectCallback : public QueueCallback { + public: + RemoveObjectCallback(SGSharedPtr objectInstance, const RTIData& tag) : + _objectInstance(objectInstance), + _tag(tag) + { } + virtual void operator()() + { + _objectInstance->removeInstance(_tag); + } + private: + SGSharedPtr _objectInstance; + RTIData _tag; + }; + + /// Just the interface class doing the callbacks into the parent class + struct FederateAmbassador : public RTI::FederateAmbassador { + FederateAmbassador(RTI13Ambassador& rtiAmbassador) : + _rtiAmbassador(rtiAmbassador) + { + } + virtual ~FederateAmbassador() + throw (RTI::FederateInternalError) + { + } + + /// RTI federate ambassador callback functions. + virtual void synchronizationPointRegistrationSucceeded(const char* label) + throw (RTI::FederateInternalError) + { + } + + virtual void synchronizationPointRegistrationFailed(const char* label) + throw (RTI::FederateInternalError) + { + } + + virtual void announceSynchronizationPoint(const char* label, const char* tag) + throw (RTI::FederateInternalError) + { + _rtiAmbassador._pendingSyncLabels.insert(toStdString(label)); + } + + virtual void federationSynchronized(const char* label) + throw (RTI::FederateInternalError) + { + std::string s = toStdString(label); + _rtiAmbassador._pendingSyncLabels.erase(s); + _rtiAmbassador._syncronizedSyncLabels.insert(s); + } + + virtual void initiateFederateSave(const char* label) + throw (RTI::UnableToPerformSave, + RTI::FederateInternalError) + { + } + + virtual void federationSaved() + throw (RTI::FederateInternalError) + { + } + + virtual void federationNotSaved() + throw (RTI::FederateInternalError) + { + } + + virtual void requestFederationRestoreSucceeded(const char* label) + throw (RTI::FederateInternalError) + { + } + + virtual void requestFederationRestoreFailed(const char* label, const char* reason) + throw (RTI::FederateInternalError) + { + } + + virtual void federationRestoreBegun() + throw (RTI::FederateInternalError) + { + } + + virtual void initiateFederateRestore(const char* label, RTI::FederateHandle federateHandle) + throw (RTI::SpecifiedSaveLabelDoesNotExist, + RTI::CouldNotRestore, + RTI::FederateInternalError) + { + } + + virtual void federationRestored() + throw (RTI::FederateInternalError) + { + } + + virtual void federationNotRestored() + throw (RTI::FederateInternalError) + { + } + + // Declaration Management + virtual void startRegistrationForObjectClass(RTI::ObjectClassHandle objectClassHandle) + throw (RTI::ObjectClassNotPublished, + RTI::FederateInternalError) + { + ObjectClassMap::iterator i = _rtiAmbassador._objectClassMap.find(objectClassHandle); + if (i == _rtiAmbassador._objectClassMap.end()) + return; + if (!i->second.valid()) + return; + i->second->startRegistration(); + } + + virtual void stopRegistrationForObjectClass(RTI::ObjectClassHandle objectClassHandle) + throw (RTI::ObjectClassNotPublished, + RTI::FederateInternalError) + { + ObjectClassMap::iterator i = _rtiAmbassador._objectClassMap.find(objectClassHandle); + if (i == _rtiAmbassador._objectClassMap.end()) + return; + if (!i->second.valid()) + return; + i->second->stopRegistration(); + } + + virtual void turnInteractionsOn(RTI::InteractionClassHandle interactionClassHandle) + throw (RTI::InteractionClassNotPublished, + RTI::FederateInternalError) + { + } + + virtual void turnInteractionsOff(RTI::InteractionClassHandle interactionClassHandle) + throw (RTI::InteractionClassNotPublished, + RTI::FederateInternalError) + { + } + + + // Object Management + virtual void discoverObjectInstance(RTI::ObjectHandle objectHandle, RTI::ObjectClassHandle objectClassHandle, const char* tag) + throw (RTI::CouldNotDiscover, + RTI::ObjectClassNotKnown, + RTI::FederateInternalError) + { + ObjectClassMap::iterator i = _rtiAmbassador._objectClassMap.find(objectClassHandle); + if (i == _rtiAmbassador._objectClassMap.end()) + throw RTI::ObjectClassNotKnown("Federate: discoverObjectInstance()!"); + if (!i->second.valid()) + return; + SGSharedPtr objectInstance = new RTI13ObjectInstance(objectHandle, 0, i->second, &_rtiAmbassador, false); + _rtiAmbassador._objectInstanceMap[objectHandle] = objectInstance; + _rtiAmbassador._objectInstancePendingCallbackList.insert(objectInstance); + i->second->discoverInstance(objectInstance.get(), tagToData(tag)); + } + + virtual void reflectAttributeValues(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleValuePairSet& attributeValuePairSet, + const RTI::FedTime& fedTime, const char* tag, RTI::EventRetractionHandle eventRetractionHandle) + throw (RTI::ObjectNotKnown, + RTI::AttributeNotKnown, + RTI::FederateOwnsAttributes, + RTI::InvalidFederationTime, + RTI::FederateInternalError) + { + ObjectInstanceMap::iterator i = _rtiAmbassador._objectInstanceMap.find(objectHandle); + if (i == _rtiAmbassador._objectInstanceMap.end()) + throw RTI::ObjectNotKnown("Reflect attributes for unknown object!"); + if (!i->second.valid()) + return; + i->second->reflectAttributeValues(attributeValuePairSet, toTimeStamp(fedTime), tagToData(tag)); + } + + virtual void reflectAttributeValues(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleValuePairSet& attributeValuePairSet, + const char* tag) + throw (RTI::ObjectNotKnown, + RTI::AttributeNotKnown, + RTI::FederateOwnsAttributes, + RTI::FederateInternalError) + { + ObjectInstanceMap::iterator i = _rtiAmbassador._objectInstanceMap.find(objectHandle); + if (i == _rtiAmbassador._objectInstanceMap.end()) + throw RTI::ObjectNotKnown("Reflect attributes for unknown object!"); + if (!i->second.valid()) + return; + i->second->reflectAttributeValues(attributeValuePairSet, tagToData(tag)); + } + + virtual void receiveInteraction(RTI::InteractionClassHandle interactionClassHandle, const RTI::ParameterHandleValuePairSet& parameters, + const RTI::FedTime& fedTime, const char* tag, RTI::EventRetractionHandle eventRetractionHandle) + throw (RTI::InteractionClassNotKnown, + RTI::InteractionParameterNotKnown, + RTI::InvalidFederationTime, + RTI::FederateInternalError) + { + } + + virtual void receiveInteraction(RTI::InteractionClassHandle interactionClassHandle, + const RTI::ParameterHandleValuePairSet& parameters, const char* tag) + throw (RTI::InteractionClassNotKnown, + RTI::InteractionParameterNotKnown, + RTI::FederateInternalError) + { + } + + virtual void removeObjectInstance(RTI::ObjectHandle objectHandle, const RTI::FedTime& fedTime, + const char* tag, RTI::EventRetractionHandle eventRetractionHandle) + throw (RTI::ObjectNotKnown, + RTI::InvalidFederationTime, + RTI::FederateInternalError) + { + ObjectInstanceMap::iterator i = _rtiAmbassador._objectInstanceMap.find(objectHandle); + if (i == _rtiAmbassador._objectInstanceMap.end()) + throw RTI::ObjectNotKnown("Federate: removeObjectInstance()!"); + if (i->second.valid()) + _rtiAmbassador._queueCallbackList.push_back(new RemoveObjectCallback(i->second, tagToData(tag))); + _rtiAmbassador._objectInstancePendingCallbackList.erase(i->second); + _rtiAmbassador._objectInstanceMap.erase(i); + } + + virtual void removeObjectInstance(RTI::ObjectHandle objectHandle, const char* tag) + throw (RTI::ObjectNotKnown, + RTI::FederateInternalError) + { + ObjectInstanceMap::iterator i = _rtiAmbassador._objectInstanceMap.find(objectHandle); + if (i == _rtiAmbassador._objectInstanceMap.end()) + throw RTI::ObjectNotKnown("Federate: removeObjectInstance()!"); + if (i->second.valid()) + _rtiAmbassador._queueCallbackList.push_back(new RemoveObjectCallback(i->second, tagToData(tag))); + _rtiAmbassador._objectInstancePendingCallbackList.erase(i->second); + _rtiAmbassador._objectInstanceMap.erase(i); + } + + virtual void attributesInScope(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes) + throw (RTI::ObjectNotKnown, + RTI::AttributeNotKnown, + RTI::FederateInternalError) + { + ObjectInstanceMap::iterator i = _rtiAmbassador._objectInstanceMap.find(objectHandle); + if (i == _rtiAmbassador._objectInstanceMap.end()) + throw RTI::ObjectNotKnown("Attributes in scope for unknown object!"); + if (!i->second.valid()) + return; + i->second->attributesInScope(attributes); + } + + virtual void attributesOutOfScope(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes) + throw (RTI::ObjectNotKnown, + RTI::AttributeNotKnown, + RTI::FederateInternalError) + { + ObjectInstanceMap::iterator i = _rtiAmbassador._objectInstanceMap.find(objectHandle); + if (i == _rtiAmbassador._objectInstanceMap.end()) + throw RTI::ObjectNotKnown("Attributes in scope for unknown object!"); + if (!i->second.valid()) + return; + i->second->attributesOutOfScope(attributes); + } + + virtual void provideAttributeValueUpdate(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes) + throw (RTI::ObjectNotKnown, + RTI::AttributeNotKnown, + RTI::AttributeNotOwned, + RTI::FederateInternalError) + { + ObjectInstanceMap::iterator i = _rtiAmbassador._objectInstanceMap.find(objectHandle); + if (i == _rtiAmbassador._objectInstanceMap.end()) + throw RTI::ObjectNotKnown("Reflect attributes for unknown object!"); + if (!i->second.valid()) + return; + i->second->provideAttributeValueUpdate(attributes); + } + + virtual void turnUpdatesOnForObjectInstance(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes) + throw (RTI::ObjectNotKnown, + RTI::AttributeNotOwned, + RTI::FederateInternalError) + { + ObjectInstanceMap::iterator i = _rtiAmbassador._objectInstanceMap.find(objectHandle); + if (i == _rtiAmbassador._objectInstanceMap.end()) + throw RTI::ObjectNotKnown("Turn on attributes for unknown object!"); + if (!i->second.valid()) + return; + i->second->turnUpdatesOnForObjectInstance(attributes); + } + + virtual void turnUpdatesOffForObjectInstance(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes) + throw (RTI::ObjectNotKnown, + RTI::AttributeNotOwned, + RTI::FederateInternalError) + { + ObjectInstanceMap::iterator i = _rtiAmbassador._objectInstanceMap.find(objectHandle); + if (i == _rtiAmbassador._objectInstanceMap.end()) + throw RTI::ObjectNotKnown("Turn off attributes for unknown object!"); + if (!i->second.valid()) + return; + i->second->turnUpdatesOffForObjectInstance(attributes); + } + + // Ownership Management + virtual void requestAttributeOwnershipAssumption(RTI::ObjectHandle objectHandle, + const RTI::AttributeHandleSet& attributes, const char* tag) + throw (RTI::ObjectNotKnown, + RTI::AttributeNotKnown, + RTI::AttributeAlreadyOwned, + RTI::AttributeNotPublished, + RTI::FederateInternalError) + { + ObjectInstanceMap::iterator i = _rtiAmbassador._objectInstanceMap.find(objectHandle); + if (i == _rtiAmbassador._objectInstanceMap.end()) + throw RTI::ObjectNotKnown("requestAttributeOwnershipAssumption for unknown object!"); + if (!i->second.valid()) + return; + i->second->requestAttributeOwnershipAssumption(attributes, tagToData(tag)); + } + + virtual void attributeOwnershipDivestitureNotification(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes) + throw (RTI::ObjectNotKnown, + RTI::AttributeNotKnown, + RTI::AttributeNotOwned, + RTI::AttributeDivestitureWasNotRequested, + RTI::FederateInternalError) + { + ObjectInstanceMap::iterator i = _rtiAmbassador._objectInstanceMap.find(objectHandle); + if (i == _rtiAmbassador._objectInstanceMap.end()) + throw RTI::ObjectNotKnown("attributeOwnershipDivestitureNotification for unknown object!"); + if (!i->second.valid()) + return; + i->second->attributeOwnershipDivestitureNotification(attributes); + } + + virtual void attributeOwnershipAcquisitionNotification(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes) + throw (RTI::ObjectNotKnown, + RTI::AttributeNotKnown, + RTI::AttributeAcquisitionWasNotRequested, + RTI::AttributeAlreadyOwned, + RTI::AttributeNotPublished, + RTI::FederateInternalError) + { + ObjectInstanceMap::iterator i = _rtiAmbassador._objectInstanceMap.find(objectHandle); + if (i == _rtiAmbassador._objectInstanceMap.end()) + throw RTI::ObjectNotKnown("attributeOwnershipAcquisitionNotification for unknown object!"); + if (!i->second.valid()) + return; + i->second->attributeOwnershipAcquisitionNotification(attributes); + } + + virtual void attributeOwnershipUnavailable(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes) + throw (RTI::ObjectNotKnown, + RTI::AttributeNotKnown, + RTI::AttributeAlreadyOwned, + RTI::AttributeAcquisitionWasNotRequested, + RTI::FederateInternalError) + { + ObjectInstanceMap::iterator i = _rtiAmbassador._objectInstanceMap.find(objectHandle); + if (i == _rtiAmbassador._objectInstanceMap.end()) + throw RTI::ObjectNotKnown("attributeOwnershipUnavailable for unknown object!"); + if (!i->second.valid()) + return; + i->second->attributeOwnershipUnavailable(attributes); + } + + virtual void requestAttributeOwnershipRelease(RTI::ObjectHandle objectHandle, + const RTI::AttributeHandleSet& attributes, const char* tag) + throw (RTI::ObjectNotKnown, + RTI::AttributeNotKnown, + RTI::AttributeNotOwned, + RTI::FederateInternalError) + { + ObjectInstanceMap::iterator i = _rtiAmbassador._objectInstanceMap.find(objectHandle); + if (i == _rtiAmbassador._objectInstanceMap.end()) + throw RTI::ObjectNotKnown("requestAttributeOwnershipRelease for unknown object!"); + if (!i->second.valid()) + return; + i->second->requestAttributeOwnershipRelease(attributes, tagToData(tag)); + } + + virtual void confirmAttributeOwnershipAcquisitionCancellation(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes) + throw (RTI::ObjectNotKnown, + RTI::AttributeNotKnown, + RTI::AttributeAlreadyOwned, + RTI::AttributeAcquisitionWasNotCanceled, + RTI::FederateInternalError) + { + ObjectInstanceMap::iterator i = _rtiAmbassador._objectInstanceMap.find(objectHandle); + if (i == _rtiAmbassador._objectInstanceMap.end()) + throw RTI::ObjectNotKnown("confirmAttributeOwnershipAcquisitionCancellation for unknown object!"); + if (!i->second.valid()) + return; + i->second->confirmAttributeOwnershipAcquisitionCancellation(attributes); + } + + virtual void informAttributeOwnership(RTI::ObjectHandle objectHandle, RTI::AttributeHandle attributeHandle, + RTI::FederateHandle federateHandle) + throw (RTI::ObjectNotKnown, + RTI::AttributeNotKnown, + RTI::FederateInternalError) + { + ObjectInstanceMap::iterator i = _rtiAmbassador._objectInstanceMap.find(objectHandle); + if (i == _rtiAmbassador._objectInstanceMap.end()) + throw RTI::ObjectNotKnown("informAttributeOwnership for unknown object!"); + if (!i->second.valid()) + return; + i->second->informAttributeOwnership(attributeHandle, federateHandle); + } + + virtual void attributeIsNotOwned(RTI::ObjectHandle objectHandle, RTI::AttributeHandle attributeHandle) + throw (RTI::ObjectNotKnown, + RTI::AttributeNotKnown, + RTI::FederateInternalError) + { + ObjectInstanceMap::iterator i = _rtiAmbassador._objectInstanceMap.find(objectHandle); + if (i == _rtiAmbassador._objectInstanceMap.end()) + throw RTI::ObjectNotKnown("attributeIsNotOwned for unknown object!"); + if (!i->second.valid()) + return; + i->second->attributeIsNotOwned(attributeHandle); + } + + virtual void attributeOwnedByRTI(RTI::ObjectHandle objectHandle, RTI::AttributeHandle attributeHandle) + throw (RTI::ObjectNotKnown, + RTI::AttributeNotKnown, + RTI::FederateInternalError) + { + ObjectInstanceMap::iterator i = _rtiAmbassador._objectInstanceMap.find(objectHandle); + if (i == _rtiAmbassador._objectInstanceMap.end()) + throw RTI::ObjectNotKnown("attributeOwnedByRTI for unknown object!"); + if (!i->second.valid()) + return; + i->second->attributeOwnedByRTI(attributeHandle); + } + + // Time Management + virtual void timeRegulationEnabled(const RTI::FedTime& fedTime) + throw (RTI::InvalidFederationTime, + RTI::EnableTimeRegulationWasNotPending, + RTI::FederateInternalError) + { + _rtiAmbassador._timeRegulationEnabled = true; + _rtiAmbassador._federateTime = toTimeStamp(fedTime); + SG_LOG(SG_NETWORK, SG_INFO, "RTI: timeRegulationEnabled: " << _rtiAmbassador._federateTime); + } + + virtual void timeConstrainedEnabled(const RTI::FedTime& fedTime) + throw (RTI::InvalidFederationTime, + RTI::EnableTimeConstrainedWasNotPending, + RTI::FederateInternalError) + { + _rtiAmbassador._timeConstrainedEnabled = true; + _rtiAmbassador._federateTime = toTimeStamp(fedTime); + SG_LOG(SG_NETWORK, SG_INFO, "RTI: timeConstrainedEnabled: " << _rtiAmbassador._federateTime); + } + + virtual void timeAdvanceGrant(const RTI::FedTime& fedTime) + throw (RTI::InvalidFederationTime, + RTI::TimeAdvanceWasNotInProgress, + RTI::FederateInternalError) + { + _rtiAmbassador._federateTime = toTimeStamp(fedTime); + _rtiAmbassador._timeAdvancePending = false; + SG_LOG(SG_NETWORK, SG_INFO, "RTI: timeAdvanceGrant: " << _rtiAmbassador._federateTime); + } + + virtual void requestRetraction(RTI::EventRetractionHandle eventRetractionHandle) + throw (RTI::EventNotKnown, + RTI::FederateInternalError) + { + // No retraction concept yet + } + + private: + const RTIData& tagToData(const char* tag) + { + if (tag) + _cachedTag.setData(tag, std::strlen(tag) + 1); + else + _cachedTag.setData("", 1); + return _cachedTag; + } + RTIData _cachedTag; + + RTI13Ambassador& _rtiAmbassador; + }; + + static SGTimeStamp toTimeStamp(const RTI::FedTime& fedTime) + { + RTIfedTime referenceTime(fedTime); + return SGTimeStamp::fromSec(referenceTime.getTime() + 0.5e-9); + } + + static RTIfedTime toFedTime(const SGTimeStamp& timeStamp) + { + RTIfedTime referenceTime; + referenceTime.setZero(); + referenceTime += timeStamp.toSecs(); + return referenceTime; + } + + static std::string rtiToStdString(char* n) + { + if (!n) + return std::string(); + std::string s; + s.assign(n); + delete[] n; + return s; + } + + static std::string toStdString(const char* n) + { + if (!n) + return std::string(); + return std::string(n); + } + + // The connection class + RTI::RTIambassador _rtiAmbassador; + + // The class with all the callbacks. + FederateAmbassador _federateAmbassador; + + // All the sync labels we got an announcement for + std::set _pendingSyncLabels; + std::set _syncronizedSyncLabels; + + // All that calls back into user code is just queued. + // That is to make sure we do not call recursively into the RTI + typedef std::list > QueueCallbackList; + QueueCallbackList _queueCallbackList; + // All object instances that need to be called due to some event are noted here + // That is to make sure we do not call recursively into the RTI + typedef std::set > ObjectInstanceSet; + ObjectInstanceSet _objectInstancePendingCallbackList; + + // Top level information for dispatching federate object attribute updates + typedef std::map > ObjectInstanceMap; + // Map of all available objects + ObjectInstanceMap _objectInstanceMap; + + // Top level information for dispatching creation of federate objects + typedef std::map > ObjectClassMap; + ObjectClassMap _objectClassMap; + + bool _timeRegulationEnabled; + bool _timeConstrainedEnabled; + bool _timeAdvancePending; + SGTimeStamp _federateTime; +}; + +} // namespace simgear + +#endif diff --git a/simgear/hla/RTI13Federate.cxx b/simgear/hla/RTI13Federate.cxx new file mode 100644 index 00000000..8dad3367 --- /dev/null +++ b/simgear/hla/RTI13Federate.cxx @@ -0,0 +1,510 @@ +// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#include "RTI13Federate.hxx" + +#include "RTI13Ambassador.hxx" + +namespace simgear { + +RTI13Federate::RTI13Federate() : + _tickTimeout(10), + _ambassador(new RTI13Ambassador) +{ +} + +RTI13Federate::~RTI13Federate() +{ +} + +bool +RTI13Federate::createFederationExecution(const std::string& federationName, const std::string& objectModel) +{ + try { + _ambassador->createFederationExecution(federationName, objectModel); + return true; + } catch (RTI::FederationExecutionAlreadyExists& e) { + return true; + } catch (RTI::CouldNotOpenFED& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not create federation execution: " << e._name << " " << e._reason); + return false; + } catch (RTI::ErrorReadingFED& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not create federation execution: " << e._name << " " << e._reason); + return false; + } catch (RTI::ConcurrentAccessAttempted& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not create federation execution: " << e._name << " " << e._reason); + return false; + } catch (RTI::RTIinternalError& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not create federation execution: " << e._name << " " << e._reason); + return false; + } +} + +bool +RTI13Federate::destroyFederationExecution(const std::string& federation) +{ + try { + _ambassador->destroyFederationExecution(federation); + return true; + } catch (RTI::FederatesCurrentlyJoined& e) { + return true; + } catch (RTI::FederationExecutionDoesNotExist& e) { + return true; + } catch (RTI::ConcurrentAccessAttempted& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not destroy federation execution: " << e._name << " " << e._reason); + return false; + } catch (RTI::RTIinternalError& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not destroy federation execution: " << e._name << " " << e._reason); + return false; + } +} + +bool +RTI13Federate::join(const std::string& federateType, const std::string& federationName) +{ + try { + _federateHandle = _ambassador->joinFederationExecution(federateType, federationName); + SG_LOG(SG_NETWORK, SG_INFO, "RTI: Joined federation \"" + << federationName << "\" as \"" << federateType << "\""); + setFederateType(federateType); + setFederationName(federationName); + return true; + } catch (RTI::FederateAlreadyExecutionMember& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not join federation execution: " << e._name << " " << e._reason); + return false; + } catch (RTI::FederationExecutionDoesNotExist& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not join federation execution: " << e._name << " " << e._reason); + return false; + } catch (RTI::CouldNotOpenFED& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not join federation execution: " << e._name << " " << e._reason); + return false; + } catch (RTI::ErrorReadingFED& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not join federation execution: " << e._name << " " << e._reason); + return false; + } catch (RTI::ConcurrentAccessAttempted& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not join federation execution: " << e._name << " " << e._reason); + return false; + } catch (RTI::SaveInProgress& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not join federation execution: " << e._name << " " << e._reason); + return false; + } catch (RTI::RestoreInProgress& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not join federation execution: " << e._name << " " << e._reason); + return false; + } catch (RTI::RTIinternalError& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not join federation execution: " << e._name << " " << e._reason); + return false; + } +} + +bool +RTI13Federate::resign() +{ + try { + _ambassador->resignFederationExecution(); + SG_LOG(SG_NETWORK, SG_INFO, "RTI: Resigned from federation."); + _federateHandle = -1; + return true; + } catch (RTI::FederateOwnsAttributes& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason); + return false; + } catch (RTI::FederateNotExecutionMember& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason); + return false; + } catch (RTI::InvalidResignAction& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason); + return false; + } catch (RTI::ConcurrentAccessAttempted& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason); + return false; + } catch (RTI::RTIinternalError& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason); + return false; + } +} + +bool +RTI13Federate::registerFederationSynchronizationPoint(const std::string& label, const RTIData& tag) +{ + try { + _ambassador->registerFederationSynchronizationPoint(label, tag); + SG_LOG(SG_NETWORK, SG_INFO, "RTI: registerFederationSynchronizationPoint(" << label << ", tag )"); + return true; + } catch (RTI::FederateNotExecutionMember& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not register federation synchronization point: " << e._name << " " << e._reason); + return false; + } catch (RTI::ConcurrentAccessAttempted& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not register federation synchronization point: " << e._name << " " << e._reason); + return false; + } catch (RTI::SaveInProgress& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not register federation synchronization point: " << e._name << " " << e._reason); + return false; + } catch (RTI::RestoreInProgress& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not register federation synchronization point: " << e._name << " " << e._reason); + return false; + } catch (RTI::RTIinternalError& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not register federation synchronization point: " << e._name << " " << e._reason); + return false; + } +} + +bool +RTI13Federate::waitForFederationSynchronizationPointAnnounced(const std::string& label) +{ + while (!_ambassador->getFederationSynchronizationPointAnnounced(label)) { + _ambassador->tick(_tickTimeout, 0); + _ambassador->processQueues(); + } + return true; +} + +bool +RTI13Federate::synchronizationPointAchieved(const std::string& label) +{ + try { + _ambassador->synchronizationPointAchieved(label); + SG_LOG(SG_NETWORK, SG_INFO, "RTI: synchronizationPointAchieved(" << label << ")"); + return true; + } catch (RTI::SynchronizationPointLabelWasNotAnnounced& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not signal synchronization point: " << e._name << " " << e._reason); + return false; + } catch (RTI::FederateNotExecutionMember& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not signal synchronization point: " << e._name << " " << e._reason); + return false; + } catch (RTI::ConcurrentAccessAttempted& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not signal synchronization point: " << e._name << " " << e._reason); + return false; + } catch (RTI::SaveInProgress& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not signal synchronization point: " << e._name << " " << e._reason); + return false; + } catch (RTI::RestoreInProgress& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not signal synchronization point: " << e._name << " " << e._reason); + return false; + } catch (RTI::RTIinternalError& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not signal synchronization point: " << e._name << " " << e._reason); + return false; + } +} + +bool +RTI13Federate::waitForFederationSynchronized(const std::string& label) +{ + while (!_ambassador->getFederationSynchronized(label)) { + _ambassador->tick(_tickTimeout, 0); + _ambassador->processQueues(); + } + return true; +} + +bool +RTI13Federate::enableTimeConstrained() +{ + if (!_ambassador.valid()) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not enable time constrained at unconnected federate."); + return false; + } + + if (_ambassador->getTimeConstrainedEnabled()) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Time constrained is already enabled."); + return false; + } + + try { + _ambassador->enableTimeConstrained(); + } catch (RTI::TimeConstrainedAlreadyEnabled& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason); + return false; + } catch (RTI::EnableTimeConstrainedPending& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason); + return false; + } catch (RTI::TimeAdvanceAlreadyInProgress& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason); + return false; + } catch (RTI::ConcurrentAccessAttempted& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason); + return false; + } catch (RTI::FederateNotExecutionMember& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason); + return false; + } catch (RTI::SaveInProgress& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason); + return false; + } catch (RTI::RestoreInProgress& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason); + return false; + } catch (RTI::RTIinternalError& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason); + return false; + } + + while (!_ambassador->getTimeConstrainedEnabled()) { + _ambassador->tick(_tickTimeout, 0); + _ambassador->processQueues(); + } + + return true; +} + +bool +RTI13Federate::disableTimeConstrained() +{ + if (!_ambassador.valid()) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not disable time constrained at unconnected federate."); + return false; + } + + if (!_ambassador->getTimeConstrainedEnabled()) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Time constrained is not enabled."); + return false; + } + + try { + _ambassador->disableTimeConstrained(); + } catch (RTI::TimeConstrainedWasNotEnabled& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason); + return false; + } catch (RTI::FederateNotExecutionMember& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason); + return false; + } catch (RTI::ConcurrentAccessAttempted& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason); + return false; + } catch (RTI::SaveInProgress& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason); + return false; + } catch (RTI::RestoreInProgress& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason); + return false; + } catch (RTI::RTIinternalError& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason); + return false; + } + + return true; +} + +bool +RTI13Federate::enableTimeRegulation(const SGTimeStamp& lookahead) +{ + if (!_ambassador.valid()) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not enable time regulation at unconnected federate."); + return false; + } + + if (_ambassador->getTimeRegulationEnabled()) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Time regulation already enabled."); + return false; + } + + try { + _ambassador->enableTimeRegulation(SGTimeStamp(), lookahead); + } catch (RTI::TimeRegulationAlreadyEnabled& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason); + return false; + } catch (RTI::EnableTimeRegulationPending& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason); + return false; + } catch (RTI::TimeAdvanceAlreadyInProgress& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason); + return false; + } catch (RTI::InvalidFederationTime& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason); + return false; + } catch (RTI::InvalidLookahead& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason); + return false; + } catch (RTI::ConcurrentAccessAttempted& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason); + return false; + } catch (RTI::FederateNotExecutionMember& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason); + return false; + } catch (RTI::SaveInProgress& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason); + return false; + } catch (RTI::RestoreInProgress& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason); + return false; + } catch (RTI::RTIinternalError& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason); + return false; + } + + while (!_ambassador->getTimeRegulationEnabled()) { + _ambassador->tick(_tickTimeout, 0); + _ambassador->processQueues(); + } + + return true; +} + +bool +RTI13Federate::disableTimeRegulation() +{ + if (!_ambassador.valid()) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not disable time regulation at unconnected federate."); + return false; + } + + if (!_ambassador->getTimeRegulationEnabled()) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Time regulation is not enabled."); + return false; + } + + try { + _ambassador->disableTimeRegulation(); + } catch (RTI::TimeRegulationWasNotEnabled& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason); + return false; + } catch (RTI::ConcurrentAccessAttempted& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason); + return false; + } catch (RTI::FederateNotExecutionMember& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason); + return false; + } catch (RTI::SaveInProgress& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason); + return false; + } catch (RTI::RestoreInProgress& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason); + return false; + } catch (RTI::RTIinternalError& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason); + return false; + } + + return true; +} + +bool +RTI13Federate::timeAdvanceRequestBy(const SGTimeStamp& dt) +{ + if (!_ambassador.valid()) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not disable time regulation at unconnected federate."); + return false; + } + + SGTimeStamp fedTime = _ambassador->getCurrentLogicalTime() + dt; + return timeAdvanceRequest(fedTime); +} + +bool +RTI13Federate::timeAdvanceRequest(const SGTimeStamp& fedTime) +{ + if (!_ambassador.valid()) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not disable time regulation at unconnected federate."); + return false; + } + + try { + _ambassador->timeAdvanceRequest(fedTime); + } catch (RTI::InvalidFederationTime& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason); + return false; + } catch (RTI::FederationTimeAlreadyPassed& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason); + return false; + } catch (RTI::TimeAdvanceAlreadyInProgress& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason); + return false; + } catch (RTI::EnableTimeRegulationPending& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason); + return false; + } catch (RTI::EnableTimeConstrainedPending& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason); + return false; + } catch (RTI::FederateNotExecutionMember& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason); + return false; + } catch (RTI::ConcurrentAccessAttempted& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason); + return false; + } catch (RTI::SaveInProgress& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason); + return false; + } catch (RTI::RestoreInProgress& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason); + return false; + } catch (RTI::RTIinternalError& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not resign federation execution: " << e._name << " " << e._reason); + return false; + } + + while (_ambassador->getTimeAdvancePending()) { + _ambassador->tick(_tickTimeout, 0); + _ambassador->processQueues(); + } + + return true; +} + +bool +RTI13Federate::tick() +{ + bool result = _ambassador->tick(); + _ambassador->processQueues(); + return result; +} + +bool +RTI13Federate::tick(const double& minimum, const double& maximum) +{ + bool result = _ambassador->tick(minimum, maximum); + _ambassador->processQueues(); + return result; +} + +RTI13ObjectClass* +RTI13Federate::createObjectClass(const std::string& objectClassName, HLAObjectClass* hlaObjectClass) +{ + try { + return _ambassador->createObjectClass(objectClassName, hlaObjectClass); + } catch (RTI::NameNotFound& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class: " << e._name << " " << e._reason); + return 0; + } catch (RTI::FederateNotExecutionMember& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class: " << e._name << " " << e._reason); + return 0; + } catch (RTI::ConcurrentAccessAttempted& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class: " << e._name << " " << e._reason); + return 0; + } catch (RTI::RTIinternalError& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class: " << e._name << " " << e._reason); + return 0; + } +} + +RTI13ObjectInstance* +RTI13Federate::getObjectInstance(const std::string& objectInstanceName) +{ + try { + return _ambassador->getObjectInstance(objectInstanceName); + } catch (RTI::ObjectNotKnown& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class: " << e._name << " " << e._reason); + return 0; + } catch (RTI::FederateNotExecutionMember& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class: " << e._name << " " << e._reason); + return 0; + } catch (RTI::ConcurrentAccessAttempted& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class: " << e._name << " " << e._reason); + return 0; + } catch (RTI::RTIinternalError& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class: " << e._name << " " << e._reason); + return 0; + } +} + +} diff --git a/simgear/hla/RTI13Federate.hxx b/simgear/hla/RTI13Federate.hxx new file mode 100644 index 00000000..3aa32aaf --- /dev/null +++ b/simgear/hla/RTI13Federate.hxx @@ -0,0 +1,88 @@ +// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#ifndef RTI13Federate_hxx +#define RTI13Federate_hxx + +#ifndef RTI_USES_STD_FSTREAM +#define RTI_USES_STD_FSTREAM +#endif + +#include + +#include "RTIFederate.hxx" +#include "RTI13ObjectClass.hxx" +#include "RTI13ObjectInstance.hxx" + +namespace simgear { + +class RTI13Ambassador; + +class RTI13Federate : public RTIFederate { +public: + RTI13Federate(); + virtual ~RTI13Federate(); + + virtual bool createFederationExecution(const std::string& federation, const std::string& objectModel); + virtual bool destroyFederationExecution(const std::string& federation); + + /// Join with federateName the federation execution federation + virtual bool join(const std::string& federateType, const std::string& federation); + virtual bool resign(); + + /// Synchronization Point handling + virtual bool registerFederationSynchronizationPoint(const std::string& label, const RTIData& tag); + virtual bool waitForFederationSynchronizationPointAnnounced(const std::string& label); + virtual bool synchronizationPointAchieved(const std::string& label); + virtual bool waitForFederationSynchronized(const std::string& label); + + /// Time management + virtual bool enableTimeConstrained(); + virtual bool disableTimeConstrained(); + + virtual bool enableTimeRegulation(const SGTimeStamp& lookahead); + virtual bool disableTimeRegulation(); + + virtual bool timeAdvanceRequestBy(const SGTimeStamp& dt); + virtual bool timeAdvanceRequest(const SGTimeStamp& fedTime); + + /// Process messages + virtual bool tick(); + virtual bool tick(const double& minimum, const double& maximum); + + virtual RTI13ObjectClass* createObjectClass(const std::string& name, HLAObjectClass* hlaObjectClass); + + virtual RTI13ObjectInstance* getObjectInstance(const std::string& name); + +private: + RTI13Federate(const RTI13Federate&); + RTI13Federate& operator=(const RTI13Federate&); + + /// The federate handle + RTI::FederateHandle _federateHandle; + + /// The timeout for the single callback tick function in + /// syncronous operations that need to wait for a callback + double _tickTimeout; + + /// RTI connection + SGSharedPtr _ambassador; +}; + +} + +#endif diff --git a/simgear/hla/RTI13ObjectClass.cxx b/simgear/hla/RTI13ObjectClass.cxx new file mode 100644 index 00000000..e2ccd497 --- /dev/null +++ b/simgear/hla/RTI13ObjectClass.cxx @@ -0,0 +1,405 @@ +// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#include "RTI13ObjectClass.hxx" +#include "RTI13Ambassador.hxx" + +namespace simgear { + +RTI13ObjectClass::RTI13ObjectClass(HLAObjectClass* hlaObjectClass, RTI::ObjectClassHandle& handle, RTI13Ambassador* ambassador) : + RTIObjectClass(hlaObjectClass), + _handle(handle), + _ambassador(ambassador) +{ + if (0 != getOrCreateAttributeIndex("privilegeToDelete") && + 0 != getOrCreateAttributeIndex("HLAprivilegeToDeleteObject")) + SG_LOG(SG_NETWORK, SG_WARN, "RTI13ObjectClass: Cannot find object root attribute."); +} + +RTI13ObjectClass::~RTI13ObjectClass() +{ +} + +std::string +RTI13ObjectClass::getName() const +{ + SGSharedPtr ambassador = _ambassador.lock(); + if (!ambassador.valid()) { + SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero."); + return std::string(); + } + return ambassador->getObjectClassName(_handle); +} + +unsigned +RTI13ObjectClass::getNumAttributes() const +{ + return _attributeHandleVector.size(); +} + +unsigned +RTI13ObjectClass::getAttributeIndex(const std::string& name) const +{ + SGSharedPtr ambassador = _ambassador.lock(); + if (!ambassador.valid()) { + SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero."); + return ~0u; + } + + try { + RTI::AttributeHandle attributeHandle = ambassador->getAttributeHandle(name, _handle); + + AttributeHandleIndexMap::const_iterator i = _attributeHandleIndexMap.find(attributeHandle); + if (i != _attributeHandleIndexMap.end()) + return i->second; + + return ~0u; + + } catch (RTI::ObjectClassNotDefined& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class attribute: " << e._name << " " << e._reason); + return ~0u; + } catch (RTI::NameNotFound& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class attribute: " << e._name << " " << e._reason); + return ~0u; + } catch (RTI::FederateNotExecutionMember& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class attribute: " << e._name << " " << e._reason); + return ~0u; + } catch (RTI::ConcurrentAccessAttempted& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class attribute: " << e._name << " " << e._reason); + return ~0u; + } catch (RTI::RTIinternalError& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class attribute: " << e._name << " " << e._reason); + return ~0u; + } catch (...) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class attribute."); + return ~0u; + } +} + +unsigned +RTI13ObjectClass::getOrCreateAttributeIndex(const std::string& name) +{ + SGSharedPtr ambassador = _ambassador.lock(); + if (!ambassador.valid()) { + SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero."); + return ~0u; + } + + try { + RTI::AttributeHandle attributeHandle = ambassador->getAttributeHandle(name, _handle); + + AttributeHandleIndexMap::const_iterator i = _attributeHandleIndexMap.find(attributeHandle); + if (i != _attributeHandleIndexMap.end()) + return i->second; + + unsigned index = _attributeHandleVector.size(); + _attributeHandleIndexMap[attributeHandle] = index; + _attributeHandleVector.push_back(attributeHandle); + _attributeDataVector.push_back(name); + + return index; + + } catch (RTI::ObjectClassNotDefined& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class attribute: " << e._name << " " << e._reason); + return ~0u; + } catch (RTI::NameNotFound& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class attribute: " << e._name << " " << e._reason); + return ~0u; + } catch (RTI::FederateNotExecutionMember& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class attribute: " << e._name << " " << e._reason); + return ~0u; + } catch (RTI::ConcurrentAccessAttempted& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class attribute: " << e._name << " " << e._reason); + return ~0u; + } catch (RTI::RTIinternalError& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class attribute: " << e._name << " " << e._reason); + return ~0u; + } catch (...) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class attribute."); + return ~0u; + } +} + +// std::string +// RTI13ObjectClass::getAttributeName(unsigned index) const +// { +// SGSharedPtr ambassador = _ambassador.lock(); +// if (!ambassador.valid()) { +// SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero."); +// return std::string(); +// } + +// try { +// return ambassador->getAttributeName(getAttributeHandle(index), _handle); +// } catch (RTI::ObjectClassNotDefined& e) { +// SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class attribute name: " << e._name << " " << e._reason); +// return std::string(); +// } catch (RTI::AttributeNotDefined& e) { +// SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class attribute name: " << e._name << " " << e._reason); +// return std::string(); +// } catch (RTI::FederateNotExecutionMember& e) { +// SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class attribute name: " << e._name << " " << e._reason); +// return std::string(); +// } catch (RTI::ConcurrentAccessAttempted& e) { +// SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class attribute name: " << e._name << " " << e._reason); +// return std::string(); +// } catch (RTI::RTIinternalError& e) { +// SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class attribute name: " << e._name << " " << e._reason); +// return std::string(); +// } catch (...) { +// SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class attribute name."); +// return std::string(); +// } +// } + +bool +RTI13ObjectClass::publish(const std::set& indexSet) +{ + SGSharedPtr ambassador = _ambassador.lock(); + if (!ambassador.valid()) { + SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero."); + return false; + } + + try { + std::auto_ptr attributeHandleSet(RTI::AttributeHandleSetFactory::create(indexSet.size())); + for (std::set::const_iterator i = indexSet.begin(); i != indexSet.end(); ++i) { + if (_attributeHandleVector.size() <= *i) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI13ObjectClass::publish(): Invalid attribute index!"); + continue; + } + attributeHandleSet->add(_attributeHandleVector[*i]); + } + + ambassador->publishObjectClass(_handle, *attributeHandleSet); + + for (unsigned i = 0; i < getNumAttributes(); ++i) { + _attributeDataVector[i]._published = true; + } + + return true; + } catch (RTI::ObjectClassNotDefined& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not publish object class: " << e._name << " " << e._reason); + return false; + } catch (RTI::AttributeNotDefined& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not publish object class: " << e._name << " " << e._reason); + return false; + } catch (RTI::OwnershipAcquisitionPending& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not publish object class: " << e._name << " " << e._reason); + return false; + } catch (RTI::FederateNotExecutionMember& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not publish object class: " << e._name << " " << e._reason); + return false; + } catch (RTI::ConcurrentAccessAttempted& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not publish object class: " << e._name << " " << e._reason); + return false; + } catch (RTI::SaveInProgress& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not publish object class: " << e._name << " " << e._reason); + return false; + } catch (RTI::RestoreInProgress& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not publish object class: " << e._name << " " << e._reason); + return false; + } catch (RTI::RTIinternalError& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not publish object class: " << e._name << " " << e._reason); + return false; + } catch (...) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not publish object class."); + return false; + } +} + +bool +RTI13ObjectClass::unpublish() +{ + SGSharedPtr ambassador = _ambassador.lock(); + if (!ambassador.valid()) { + SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero."); + return false; + } + + try { + ambassador->unpublishObjectClass(_handle); + + for (unsigned i = 0; i < getNumAttributes(); ++i) { + _attributeDataVector[i]._published = false; + } + + return true; + } catch (RTI::ObjectClassNotDefined& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not unpublish object class: " << e._name << " " << e._reason); + return false; + } catch (RTI::ObjectClassNotPublished& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not unpublish object class: " << e._name << " " << e._reason); + return false; + } catch (RTI::OwnershipAcquisitionPending& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not unpublish object class: " << e._name << " " << e._reason); + return false; + } catch (RTI::FederateNotExecutionMember& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not unpublish object class: " << e._name << " " << e._reason); + return false; + } catch (RTI::ConcurrentAccessAttempted& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not unpublish object class: " << e._name << " " << e._reason); + return false; + } catch (RTI::SaveInProgress& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not unpublish object class: " << e._name << " " << e._reason); + return false; + } catch (RTI::RestoreInProgress& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not unpublish object class: " << e._name << " " << e._reason); + return false; + } catch (RTI::RTIinternalError& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not unpublish object class: " << e._name << " " << e._reason); + return false; + } catch (...) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not unpublish object class."); + return false; + } +} + +bool +RTI13ObjectClass::subscribe(const std::set& indexSet, bool active) +{ + SGSharedPtr ambassador = _ambassador.lock(); + if (!ambassador.valid()) { + SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero."); + return false; + } + + try { + std::auto_ptr attributeHandleSet(RTI::AttributeHandleSetFactory::create(indexSet.size())); + for (std::set::const_iterator i = indexSet.begin(); + i != indexSet.end(); ++i) { + if (_attributeHandleVector.size() <= *i) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI13ObjectClass::subscribe(): Invalid attribute index!"); + continue; + } + attributeHandleSet->add(_attributeHandleVector[*i]); + } + + ambassador->subscribeObjectClassAttributes(_handle, *attributeHandleSet, active); + + for (unsigned i = 0; i < getNumAttributes(); ++i) { + _attributeDataVector[i]._subscribed = true; + } + + return true; + } catch (RTI::ObjectClassNotDefined& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not subscribe object class: " << e._name << " " << e._reason); + return false; + } catch (RTI::AttributeNotDefined& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not subscribe object class: " << e._name << " " << e._reason); + return false; + } catch (RTI::FederateNotExecutionMember& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not subscribe object class: " << e._name << " " << e._reason); + return false; + } catch (RTI::ConcurrentAccessAttempted& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not subscribe object class: " << e._name << " " << e._reason); + return false; + } catch (RTI::SaveInProgress& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not subscribe object class: " << e._name << " " << e._reason); + return false; + } catch (RTI::RestoreInProgress& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not subscribe object class: " << e._name << " " << e._reason); + return false; + } catch (RTI::RTIinternalError& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not subscribe object class: " << e._name << " " << e._reason); + return false; + } catch (...) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not subscribe object class."); + return false; + } +} + +bool +RTI13ObjectClass::unsubscribe() +{ + SGSharedPtr ambassador = _ambassador.lock(); + if (!ambassador.valid()) { + SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero."); + return 0; + } + + try { + ambassador->unsubscribeObjectClass(_handle); + + for (unsigned i = 0; i < getNumAttributes(); ++i) { + _attributeDataVector[i]._subscribed = false; + } + + return true; + } catch (RTI::ObjectClassNotDefined& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not unsubscribe object class: " << e._name << " " << e._reason); + return false; + } catch (RTI::ObjectClassNotSubscribed& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not unsubscribe object class: " << e._name << " " << e._reason); + return false; + } catch (RTI::FederateNotExecutionMember& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not unsubscribe object class: " << e._name << " " << e._reason); + return false; + } catch (RTI::ConcurrentAccessAttempted& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not unsubscribe object class: " << e._name << " " << e._reason); + return false; + } catch (RTI::SaveInProgress& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not unsubscribe object class: " << e._name << " " << e._reason); + return false; + } catch (RTI::RestoreInProgress& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not unsubscribe object class: " << e._name << " " << e._reason); + return false; + } catch (RTI::RTIinternalError& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not unsubscribe object class: " << e._name << " " << e._reason); + return false; + } catch (...) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not unsubscribe object class."); + return false; + } +} + +RTIObjectInstance* +RTI13ObjectClass::registerObjectInstance(HLAObjectInstance* hlaObjectInstance) +{ + SGSharedPtr ambassador = _ambassador.lock(); + if (!ambassador.valid()) { + SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero."); + return 0; + } + + try { + return ambassador->registerObjectInstance(this, hlaObjectInstance); + } catch (RTI::ObjectClassNotDefined& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not register object instance: " << e._name << " " << e._reason); + return 0; + } catch (RTI::ObjectClassNotPublished& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not register object instance: " << e._name << " " << e._reason); + return 0; + } catch (RTI::FederateNotExecutionMember& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not register object instance: " << e._name << " " << e._reason); + return 0; + } catch (RTI::ConcurrentAccessAttempted& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not register object instance: " << e._name << " " << e._reason); + return 0; + } catch (RTI::SaveInProgress& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not register object instance: " << e._name << " " << e._reason); + return 0; + } catch (RTI::RestoreInProgress& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not register object instance: " << e._name << " " << e._reason); + return 0; + } catch (RTI::RTIinternalError& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not register object instance: " << e._name << " " << e._reason); + return 0; + } +} + +} diff --git a/simgear/hla/RTI13ObjectClass.hxx b/simgear/hla/RTI13ObjectClass.hxx new file mode 100644 index 00000000..e8c25cd0 --- /dev/null +++ b/simgear/hla/RTI13ObjectClass.hxx @@ -0,0 +1,87 @@ +// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#ifndef RTI13ObjectClass_hxx +#define RTI13ObjectClass_hxx + +#include + +#ifndef RTI_USES_STD_FSTREAM +#define RTI_USES_STD_FSTREAM +#endif + +#include + +#include + +#include "RTIObjectClass.hxx" + +namespace simgear { + +class RTI13Ambassador; +class RTIObjectInstance; + +class RTI13ObjectClass : public RTIObjectClass { +public: + RTI13ObjectClass(HLAObjectClass* hlaObjectClass, RTI::ObjectClassHandle& handle, RTI13Ambassador* ambassador); + virtual ~RTI13ObjectClass(); + + const RTI::ObjectClassHandle& getHandle() const + { return _handle; } + + virtual std::string getName() const; + + virtual unsigned getNumAttributes() const; + virtual unsigned getAttributeIndex(const std::string& name) const; + virtual unsigned getOrCreateAttributeIndex(const std::string& name); + + unsigned getAttributeIndex(const RTI::AttributeHandle& handle) const + { + AttributeHandleIndexMap::const_iterator i = _attributeHandleIndexMap.find(handle); + if (i == _attributeHandleIndexMap.end()) + return ~0u; + return i->second; + } + RTI::AttributeHandle getAttributeHandle(unsigned index) const + { + if (_attributeHandleVector.size() <= index) + return -1; + return _attributeHandleVector[index]; + } + + virtual bool publish(const std::set& indexSet); + virtual bool unpublish(); + + virtual bool subscribe(const std::set& indexSet, bool); + virtual bool unsubscribe(); + + virtual RTIObjectInstance* registerObjectInstance(HLAObjectInstance* hlaObjectInstance); + +private: + RTI::ObjectClassHandle _handle; + SGWeakPtr _ambassador; + + typedef std::map AttributeHandleIndexMap; + AttributeHandleIndexMap _attributeHandleIndexMap; + + typedef std::vector AttributeHandleVector; + AttributeHandleVector _attributeHandleVector; +}; + +} + +#endif diff --git a/simgear/hla/RTI13ObjectInstance.cxx b/simgear/hla/RTI13ObjectInstance.cxx new file mode 100644 index 00000000..8fefc882 --- /dev/null +++ b/simgear/hla/RTI13ObjectInstance.cxx @@ -0,0 +1,488 @@ +// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#include "RTIObjectInstance.hxx" +#include "RTI13Ambassador.hxx" + +namespace simgear { + +RTI13ObjectInstance::RTI13ObjectInstance(const RTI::ObjectHandle& handle, HLAObjectInstance* hlaObjectInstance, + const RTI13ObjectClass* objectClass, RTI13Ambassador* ambassador, bool owned) : + RTIObjectInstance(hlaObjectInstance), + _handle(handle), + _objectClass(objectClass), + _ambassador(ambassador), + _attributeValuePairSet(RTI::AttributeSetFactory::create(objectClass->getNumAttributes())) +{ + updateAttributesFromClass(owned); +} + +RTI13ObjectInstance::~RTI13ObjectInstance() +{ +} + +const RTIObjectClass* +RTI13ObjectInstance::getObjectClass() const +{ + return _objectClass.get(); +} + +const RTI13ObjectClass* +RTI13ObjectInstance::get13ObjectClass() const +{ + return _objectClass.get(); +} + +std::string +RTI13ObjectInstance::getName() const +{ + SGSharedPtr ambassador = _ambassador.lock(); + if (!ambassador.valid()) { + SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero."); + return std::string(); + } + + try { + return ambassador->getObjectInstanceName(_handle); + } catch (RTI::ObjectNotKnown& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object name: " << e._name << " " << e._reason); + return std::string(); + } catch (RTI::FederateNotExecutionMember& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object name: " << e._name << " " << e._reason); + return std::string(); + } catch (RTI::ConcurrentAccessAttempted& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object name: " << e._name << " " << e._reason); + return std::string(); + } catch (RTI::RTIinternalError& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object name: " << e._name << " " << e._reason); + return std::string(); + } catch (...) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object name."); + return std::string(); + } +} + +void +RTI13ObjectInstance::addToRequestQueue() +{ + SGSharedPtr ambassador = _ambassador.lock(); + if (!ambassador.valid()) { + SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero."); + return; + } + + ambassador->addObjectInstanceForCallback(this); +} + +void +RTI13ObjectInstance::deleteObjectInstance(const RTIData& tag) +{ + SGSharedPtr ambassador = _ambassador.lock(); + if (!ambassador.valid()) { + SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero."); + return; + } + + try { + ambassador->deleteObjectInstance(_handle, tag); + } catch (RTI::ObjectNotKnown& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason); + } catch (RTI::DeletePrivilegeNotHeld& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason); + } catch (RTI::FederateNotExecutionMember& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason); + } catch (RTI::ConcurrentAccessAttempted& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason); + } catch (RTI::SaveInProgress& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason); + } catch (RTI::RestoreInProgress& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason); + } catch (RTI::RTIinternalError& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason); + } +} + +void +RTI13ObjectInstance::deleteObjectInstance(const SGTimeStamp& timeStamp, const RTIData& tag) +{ + SGSharedPtr ambassador = _ambassador.lock(); + if (!ambassador.valid()) { + SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero."); + return; + } + + try { + ambassador->deleteObjectInstance(_handle, timeStamp, tag); + } catch (RTI::ObjectNotKnown& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason); + } catch (RTI::DeletePrivilegeNotHeld& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason); + } catch (RTI::InvalidFederationTime& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason); + } catch (RTI::FederateNotExecutionMember& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason); + } catch (RTI::ConcurrentAccessAttempted& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason); + } catch (RTI::SaveInProgress& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason); + } catch (RTI::RestoreInProgress& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason); + } catch (RTI::RTIinternalError& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason); + } +} + +void +RTI13ObjectInstance::localDeleteObjectInstance() +{ + SGSharedPtr ambassador = _ambassador.lock(); + if (!ambassador.valid()) { + SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero."); + return; + } + + try { + ambassador->localDeleteObjectInstance(_handle); + } catch (RTI::ObjectNotKnown& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason); + } catch (RTI::FederateOwnsAttributes& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason); + } catch (RTI::FederateNotExecutionMember& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason); + } catch (RTI::ConcurrentAccessAttempted& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason); + } catch (RTI::SaveInProgress& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason); + } catch (RTI::RestoreInProgress& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason); + } catch (RTI::RTIinternalError& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason); + } +} + +void +RTI13ObjectInstance::reflectAttributeValues(const RTI::AttributeHandleValuePairSet& attributeValuePairSet, const RTIData& tag) +{ + // Retrieve an empty update struct from the memory pool + UpdateList updateList; + getUpdateFromPool(updateList); + + RTI::ULong numAttribs = attributeValuePairSet.size(); + for (RTI::ULong i = 0; i < numAttribs; ++i) { + unsigned index = getAttributeIndex(attributeValuePairSet.getHandle(i)); + // Get a RTIData from the data pool + getDataFromPool(index, updateList.back()._indexDataPairList); + RTI::ULong length = attributeValuePairSet.getValueLength(i); + updateList.back()._indexDataPairList.back().second.resize(length); + attributeValuePairSet.getValue(i, updateList.back()._indexDataPairList.back().second.data(), length); + updateList.back()._tag = tag; + } + + RTIObjectInstance::reflectAttributeValues(updateList.front()._indexDataPairList, tag); + // Return the update data back to the pool + putUpdateToPool(updateList); +} + +void +RTI13ObjectInstance::reflectAttributeValues(const RTI::AttributeHandleValuePairSet& attributeValuePairSet, const SGTimeStamp& timeStamp, const RTIData& tag) +{ + // Retrieve an empty update struct from the memory pool + UpdateList updateList; + getUpdateFromPool(updateList); + + RTI::ULong numAttribs = attributeValuePairSet.size(); + for (RTI::ULong i = 0; i < numAttribs; ++i) { + unsigned index = getAttributeIndex(attributeValuePairSet.getHandle(i)); + // Get a RTIData from the data pool + getDataFromPool(index, updateList.back()._indexDataPairList); + RTI::ULong length = attributeValuePairSet.getValueLength(i); + updateList.back()._indexDataPairList.back().second.resize(length); + attributeValuePairSet.getValue(i, updateList.back()._indexDataPairList.back().second.data(), length); + updateList.back()._tag = tag; + } + + scheduleUpdates(timeStamp, updateList); +} + +void +RTI13ObjectInstance::requestObjectAttributeValueUpdate() +{ + SGSharedPtr ambassador = _ambassador.lock(); + if (!ambassador.valid()) { + SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero."); + return; + } + + try { + unsigned numAttributes = getNumAttributes(); + std::auto_ptr attributeHandleSet(RTI::AttributeHandleSetFactory::create(numAttributes)); + for (unsigned i = 0; i < numAttributes; ++i) { + if (!getRequestAttributeUpdate(i)) + continue; + attributeHandleSet->add(getAttributeHandle(i)); + } + if (!attributeHandleSet->size()) + return; + + ambassador->requestObjectAttributeValueUpdate(_handle, *attributeHandleSet); + + for (unsigned i = 0; i < numAttributes; ++i) + setRequestAttributeUpdate(i, false); + + return; + } catch (RTI::ObjectNotKnown& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not request attribute update for object instance: " << e._name << " " << e._reason); + return; + } catch (RTI::AttributeNotDefined& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not request attribute update for object instance: " << e._name << " " << e._reason); + return; + } catch (RTI::FederateNotExecutionMember& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not request attribute update for object instance: " << e._name << " " << e._reason); + return; + } catch (RTI::ConcurrentAccessAttempted& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not request attribute update for object instance: " << e._name << " " << e._reason); + return; + } catch (RTI::SaveInProgress& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not request attribute update for object instance: " << e._name << " " << e._reason); + return; + } catch (RTI::RestoreInProgress& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not request attribute update for object instance: " << e._name << " " << e._reason); + return; + } catch (RTI::RTIinternalError& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not request attribute update for object instance: " << e._name << " " << e._reason); + return; + } catch (...) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not request attribute update for object instance."); + return; + } +} + +void +RTI13ObjectInstance::provideAttributeValueUpdate(const RTI::AttributeHandleSet& attributes) +{ + // Called from the ambassador. Just marks some instance attributes dirty so that they are sent with the next update + RTI::ULong numAttribs = attributes.size(); + for (RTI::ULong i = 0; i < numAttribs; ++i) { + unsigned index = getAttributeIndex(attributes.getHandle(i)); + setAttributeForceUpdate(index); + } +} + +void +RTI13ObjectInstance::updateAttributeValues(const RTIData& tag) +{ + SGSharedPtr ambassador = _ambassador.lock(); + if (!ambassador.valid()) { + SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero."); + return; + } + + try { + // That means clear() + _attributeValuePairSet->empty(); + + unsigned numAttributes = getNumAttributes(); + for (unsigned i = 0; i < numAttributes; ++i) { + if (!getAttributeEffectiveUpdateEnabled(i)) + continue; + const HLADataElement* dataElement = getDataElement(i); + if (!dataElement) + continue; + // FIXME cache somewhere + RTIData data; + HLAEncodeStream stream(data); + dataElement->encode(stream); + _attributeValuePairSet->add(getAttributeHandle(i), data.data(), data.size()); + } + + if (!_attributeValuePairSet->size()) + return; + + ambassador->updateAttributeValues(_handle, *_attributeValuePairSet, tag); + + for (unsigned i = 0; i < numAttributes; ++i) { + setAttributeUpdated(i); + } + + } catch (RTI::ObjectNotKnown& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason); + } catch (RTI::AttributeNotDefined& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason); + } catch (RTI::AttributeNotOwned& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason); + } catch (RTI::FederateNotExecutionMember& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason); + } catch (RTI::ConcurrentAccessAttempted& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason); + } catch (RTI::SaveInProgress& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason); + } catch (RTI::RestoreInProgress& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason); + } catch (RTI::RTIinternalError& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason); + } + + // That means clear() + _attributeValuePairSet->empty(); +} + +void +RTI13ObjectInstance::updateAttributeValues(const SGTimeStamp& timeStamp, const RTIData& tag) +{ + SGSharedPtr ambassador = _ambassador.lock(); + if (!ambassador.valid()) { + SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero."); + return; + } + + try { + // That means clear() + _attributeValuePairSet->empty(); + + unsigned numAttributes = getNumAttributes(); + for (unsigned i = 0; i < numAttributes; ++i) { + if (!getAttributeEffectiveUpdateEnabled(i)) + continue; + const HLADataElement* dataElement = getDataElement(i); + if (!dataElement) + continue; + // FIXME cache somewhere + RTIData data; + HLAEncodeStream stream(data); + dataElement->encode(stream); + _attributeValuePairSet->add(getAttributeHandle(i), data.data(), data.size()); + } + + if (!_attributeValuePairSet->size()) + return; + + ambassador->updateAttributeValues(_handle, *_attributeValuePairSet, timeStamp, tag); + + for (unsigned i = 0; i < numAttributes; ++i) { + setAttributeUpdated(i); + } + + } catch (RTI::ObjectNotKnown& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason); + } catch (RTI::AttributeNotDefined& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason); + } catch (RTI::AttributeNotOwned& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason); + } catch (RTI::InvalidFederationTime& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason); + } catch (RTI::FederateNotExecutionMember& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason); + } catch (RTI::ConcurrentAccessAttempted& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason); + } catch (RTI::SaveInProgress& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason); + } catch (RTI::RestoreInProgress& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason); + } catch (RTI::RTIinternalError& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not delete object instance: " << e._name << " " << e._reason); + } + + // That means clear() + _attributeValuePairSet->empty(); +} + +void +RTI13ObjectInstance::attributesInScope(const RTI::AttributeHandleSet& attributeHandleSet) +{ + RTI::ULong numAttribs = attributeHandleSet.size(); + for (RTI::ULong i = 0; i < numAttribs; ++i) { + RTI::AttributeHandle attributeHandle = attributeHandleSet.getHandle(i); + setAttributeInScope(getAttributeIndex(attributeHandle), true); + } +} + +void +RTI13ObjectInstance::attributesOutOfScope(const RTI::AttributeHandleSet& attributeHandleSet) +{ + RTI::ULong numAttribs = attributeHandleSet.size(); + for (RTI::ULong i = 0; i < numAttribs; ++i) { + RTI::AttributeHandle attributeHandle = attributeHandleSet.getHandle(i); + setAttributeInScope(getAttributeIndex(attributeHandle), false); + } +} + +void +RTI13ObjectInstance::turnUpdatesOnForObjectInstance(const RTI::AttributeHandleSet& attributeHandleSet) +{ + RTI::ULong numAttribs = attributeHandleSet.size(); + for (RTI::ULong i = 0; i < numAttribs; ++i) { + RTI::AttributeHandle attributeHandle = attributeHandleSet.getHandle(i); + setAttributeUpdateEnabled(getAttributeIndex(attributeHandle), true); + } +} + +void +RTI13ObjectInstance::turnUpdatesOffForObjectInstance(const RTI::AttributeHandleSet& attributeHandleSet) +{ + RTI::ULong numAttribs = attributeHandleSet.size(); + for (RTI::ULong i = 0; i < numAttribs; ++i) { + RTI::AttributeHandle attributeHandle = attributeHandleSet.getHandle(i); + setAttributeUpdateEnabled(getAttributeIndex(attributeHandle), false); + } +} + +void +RTI13ObjectInstance::requestAttributeOwnershipAssumption(const RTI::AttributeHandleSet& attributes, const RTIData& tag) +{ +} + +void +RTI13ObjectInstance::attributeOwnershipDivestitureNotification(const RTI::AttributeHandleSet& attributes) +{ +} + +void +RTI13ObjectInstance::attributeOwnershipAcquisitionNotification(const RTI::AttributeHandleSet& attributes) +{ +} + +void +RTI13ObjectInstance::attributeOwnershipUnavailable(const RTI::AttributeHandleSet& attributes) +{ +} + +void +RTI13ObjectInstance::requestAttributeOwnershipRelease(const RTI::AttributeHandleSet& attributes, const RTIData& tag) +{ +} + +void +RTI13ObjectInstance::confirmAttributeOwnershipAcquisitionCancellation(const RTI::AttributeHandleSet& attributes) +{ +} + +void +RTI13ObjectInstance::informAttributeOwnership(RTI::AttributeHandle attributeHandle, RTI::FederateHandle federateHandle) +{ +} + +void +RTI13ObjectInstance::attributeIsNotOwned(RTI::AttributeHandle attributeHandle) +{ +} + +void +RTI13ObjectInstance::attributeOwnedByRTI(RTI::AttributeHandle attributeHandle) +{ +} + +} diff --git a/simgear/hla/RTI13ObjectInstance.hxx b/simgear/hla/RTI13ObjectInstance.hxx new file mode 100644 index 00000000..ed73aa09 --- /dev/null +++ b/simgear/hla/RTI13ObjectInstance.hxx @@ -0,0 +1,106 @@ +// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#ifndef RTI13ObjectInstance_hxx +#define RTI13ObjectInstance_hxx + +#include +#include + +#ifndef RTI_USES_STD_FSTREAM +#define RTI_USES_STD_FSTREAM +#endif + +#include + +#include + +#include "RTIObjectInstance.hxx" +#include "RTI13ObjectClass.hxx" + +namespace simgear { + +class RTI13Ambassador; +class RTI13ObjectClass; + +class RTI13ObjectInstance : public RTIObjectInstance { +public: + RTI13ObjectInstance(const RTI::ObjectHandle& handle, HLAObjectInstance* hlaObjectInstance, const RTI13ObjectClass* objectClass, RTI13Ambassador* ambassador, bool owned); + virtual ~RTI13ObjectInstance(); + + const RTI::ObjectHandle& getHandle() const + { return _handle; } + void setHandle(const RTI::ObjectHandle& handle) + { _handle = handle; } + + virtual const RTIObjectClass* getObjectClass() const; + const RTI13ObjectClass* get13ObjectClass() const; + + unsigned getNumAttributes() const + { return get13ObjectClass()->getNumAttributes(); } + unsigned getAttributeIndex(const std::string& name) const + { return get13ObjectClass()->getAttributeIndex(name); } + unsigned getAttributeIndex(const RTI::AttributeHandle& handle) const + { return get13ObjectClass()->getAttributeIndex(handle); } + RTI::AttributeHandle getAttributeHandle(unsigned index) const + { return get13ObjectClass()->getAttributeHandle(index); } + + virtual std::string getName() const; + + virtual void addToRequestQueue(); + + virtual void deleteObjectInstance(const RTIData& tag); + virtual void deleteObjectInstance(const SGTimeStamp& timeStamp, const RTIData& tag); + virtual void localDeleteObjectInstance(); + + void reflectAttributeValues(const RTI::AttributeHandleValuePairSet& attributeValuePairSet, const RTIData& tag); + void reflectAttributeValues(const RTI::AttributeHandleValuePairSet& attributeValuePairSet, const SGTimeStamp& timeStamp, const RTIData& tag); + virtual void requestObjectAttributeValueUpdate(); + void provideAttributeValueUpdate(const RTI::AttributeHandleSet& attributes); + + virtual void updateAttributeValues(const RTIData& tag); + virtual void updateAttributeValues(const SGTimeStamp& timeStamp, const RTIData& tag); + + void attributesInScope(const RTI::AttributeHandleSet& attributes); + void attributesOutOfScope(const RTI::AttributeHandleSet& attributes); + + void turnUpdatesOnForObjectInstance(const RTI::AttributeHandleSet& attributes); + void turnUpdatesOffForObjectInstance(const RTI::AttributeHandleSet& attributes); + + // Not yet sure what to do here. But the dispatch functions are already there + void requestAttributeOwnershipAssumption(const RTI::AttributeHandleSet& attributes, const RTIData& tag); + void attributeOwnershipDivestitureNotification(const RTI::AttributeHandleSet& attributes); + void attributeOwnershipAcquisitionNotification(const RTI::AttributeHandleSet& attributes); + void attributeOwnershipUnavailable(const RTI::AttributeHandleSet& attributes); + void requestAttributeOwnershipRelease(const RTI::AttributeHandleSet& attributes, const RTIData& tag); + void confirmAttributeOwnershipAcquisitionCancellation(const RTI::AttributeHandleSet& attributes); + void informAttributeOwnership(RTI::AttributeHandle attributeHandle, RTI::FederateHandle federateHandle); + void attributeIsNotOwned(RTI::AttributeHandle attributeHandle); + void attributeOwnedByRTI(RTI::AttributeHandle attributeHandle); + +private: + RTI::ObjectHandle _handle; + SGSharedPtr _objectClass; + SGWeakPtr _ambassador; + + // cached storage for updates + std::auto_ptr _attributeValuePairSet; +}; + +} + +#endif diff --git a/simgear/hla/RTIData.hxx b/simgear/hla/RTIData.hxx new file mode 100644 index 00000000..dff66dbf --- /dev/null +++ b/simgear/hla/RTIData.hxx @@ -0,0 +1,573 @@ +// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#ifndef RTIData_hxx +#define RTIData_hxx + +#include +#include +#include + +namespace simgear { + +/// Sigh, this is std::vector, except that +/// you could feed that with external pointers without copying ... +/// Note on alignment: the c++ standard garantees (5.3.4.10) that +/// new (unsigned) char returns sufficiently aligned memory +/// for all relevant cases +class RTIData { +public: + RTIData() : + _data(0), + _size(0), + _capacity(0) + { } + RTIData(unsigned size) : + _data(0), + _size(0), + _capacity(0) + { resize(size); } + RTIData(char* data, unsigned size) : + _data(data), + _size(size), + _capacity(0) + { } + RTIData(const char* data, unsigned size) : + _data(0), + _size(0), + _capacity(0) + { setData(data, size); } + RTIData(const char* data) : + _data(0), + _size(0), + _capacity(0) + { setData(data); } + RTIData(const RTIData& data) : + _data(0), + _size(0), + _capacity(0) + { + unsigned size = data.size(); + if (size) { + resize(size); + memcpy(_data, data.data(), size); + } + } + ~RTIData() + { + if (_capacity) + delete [] _data; + _data = 0; + } + + const char* data() const + { return _data; } + char* data() + { return _data; } + + unsigned size() const + { return _size; } + + bool empty() const + { return _size == 0; } + + void clear() + { + if (_capacity == 0) { + _data = 0; + _size = 0; + } else + resize(0); + } + + void resize(unsigned size) + { + if (size == _size) + return; + if (_capacity < size) { + unsigned capacity = 2*_capacity; + if (size < capacity) + ensureCapacity(capacity); + else + ensureCapacity(size); + } + _size = size; + } + + void reserve(unsigned capacity) + { + if (capacity <= _capacity) + return; + ensureCapacity(capacity); + } + + void setData(char* data, unsigned size) + { + if (_capacity) + delete [] _data; + _data = data; + _size = size; + _capacity = 0; + } + void setData(const char* data, unsigned size) + { + resize(size); + if (!size) + return; + memcpy(_data, data, size); + } + void setData(const char* data) + { + if (!data) { + setData("", 1); + } else { + size_t size = strlen(data) + 1; + setData(data, size); + } + } + + RTIData& operator=(const RTIData& data) + { + unsigned size = data.size(); + if (size) { + resize(size); + memcpy(_data, data.data(), size); + } + return *this; + } + + void getData8(char data[1], unsigned offset = 0) const + { + data[0] = _data[offset]; + } + + void setData8(const char data[1], unsigned offset = 0) + { + _data[offset] = data[0]; + } + + void getData16LE(char data[2], unsigned offset = 0) const + { + if (hostIsLittleEndian()) { + data[0] = _data[offset]; + data[1] = _data[offset+1]; + } else { + data[1] = _data[offset]; + data[0] = _data[offset+1]; + } + } + void setData16LE(const char data[2], unsigned offset = 0) + { + if (hostIsLittleEndian()) { + _data[offset] = data[0]; + _data[offset+1] = data[1]; + } else { + _data[offset] = data[1]; + _data[offset+1] = data[0]; + } + } + + void getData16BE(char data[2], unsigned offset = 0) const + { + if (hostIsLittleEndian()) { + data[1] = _data[offset]; + data[0] = _data[offset+1]; + } else { + data[0] = _data[offset]; + data[1] = _data[offset+1]; + } + } + void setData16BE(const char data[2], unsigned offset = 0) + { + if (hostIsLittleEndian()) { + _data[offset] = data[1]; + _data[offset+1] = data[0]; + } else { + _data[offset] = data[0]; + _data[offset+1] = data[1]; + } + } + + + void getData32LE(char data[4], unsigned offset = 0) const + { + if (hostIsLittleEndian()) { + data[0] = _data[offset]; + data[1] = _data[offset+1]; + data[2] = _data[offset+2]; + data[3] = _data[offset+3]; + } else { + data[3] = _data[offset]; + data[2] = _data[offset+1]; + data[1] = _data[offset+2]; + data[0] = _data[offset+3]; + } + } + void setData32LE(const char data[4], unsigned offset = 0) + { + if (hostIsLittleEndian()) { + _data[offset] = data[0]; + _data[offset+1] = data[1]; + _data[offset+2] = data[2]; + _data[offset+3] = data[3]; + } else { + _data[offset] = data[3]; + _data[offset+1] = data[2]; + _data[offset+2] = data[1]; + _data[offset+3] = data[0]; + } + } + + void getData32BE(char data[4], unsigned offset = 0) const + { + if (hostIsLittleEndian()) { + data[3] = _data[offset]; + data[2] = _data[offset+1]; + data[1] = _data[offset+2]; + data[0] = _data[offset+3]; + } else { + data[0] = _data[offset]; + data[1] = _data[offset+1]; + data[2] = _data[offset+2]; + data[3] = _data[offset+3]; + } + } + void setData32BE(const char data[4], unsigned offset = 0) + { + if (hostIsLittleEndian()) { + _data[offset] = data[3]; + _data[offset+1] = data[2]; + _data[offset+2] = data[1]; + _data[offset+3] = data[0]; + } else { + _data[offset] = data[0]; + _data[offset+1] = data[1]; + _data[offset+2] = data[2]; + _data[offset+3] = data[3]; + } + } + + + void getData64LE(char data[8], unsigned offset = 0) const + { + if (hostIsLittleEndian()) { + data[0] = _data[offset]; + data[1] = _data[offset+1]; + data[2] = _data[offset+2]; + data[3] = _data[offset+3]; + data[4] = _data[offset+4]; + data[5] = _data[offset+5]; + data[6] = _data[offset+6]; + data[7] = _data[offset+7]; + } else { + data[7] = _data[offset]; + data[6] = _data[offset+1]; + data[5] = _data[offset+2]; + data[4] = _data[offset+3]; + data[3] = _data[offset+4]; + data[2] = _data[offset+5]; + data[1] = _data[offset+6]; + data[0] = _data[offset+7]; + } + } + void setData64LE(const char data[8], unsigned offset = 0) + { + if (hostIsLittleEndian()) { + _data[offset] = data[0]; + _data[offset+1] = data[1]; + _data[offset+2] = data[2]; + _data[offset+3] = data[3]; + _data[offset+4] = data[4]; + _data[offset+5] = data[5]; + _data[offset+6] = data[6]; + _data[offset+7] = data[7]; + } else { + _data[offset] = data[7]; + _data[offset+1] = data[6]; + _data[offset+2] = data[5]; + _data[offset+3] = data[4]; + _data[offset+4] = data[3]; + _data[offset+5] = data[2]; + _data[offset+6] = data[1]; + _data[offset+7] = data[0]; + } + } + + void getData64BE(char data[8], unsigned offset = 0) const + { + if (hostIsLittleEndian()) { + data[7] = _data[offset]; + data[6] = _data[offset+1]; + data[5] = _data[offset+2]; + data[4] = _data[offset+3]; + data[3] = _data[offset+4]; + data[2] = _data[offset+5]; + data[1] = _data[offset+6]; + data[0] = _data[offset+7]; + } else { + data[0] = _data[offset]; + data[1] = _data[offset+1]; + data[2] = _data[offset+2]; + data[3] = _data[offset+3]; + data[4] = _data[offset+4]; + data[5] = _data[offset+5]; + data[6] = _data[offset+6]; + data[7] = _data[offset+7]; + } + } + void setData64BE(const char data[8], unsigned offset = 0) + { + if (hostIsLittleEndian()) { + _data[offset] = data[7]; + _data[offset+1] = data[6]; + _data[offset+2] = data[5]; + _data[offset+3] = data[4]; + _data[offset+4] = data[3]; + _data[offset+5] = data[2]; + _data[offset+6] = data[1]; + _data[offset+7] = data[0]; + } else { + _data[offset] = data[0]; + _data[offset+1] = data[1]; + _data[offset+2] = data[2]; + _data[offset+3] = data[3]; + _data[offset+4] = data[4]; + _data[offset+5] = data[5]; + _data[offset+6] = data[6]; + _data[offset+7] = data[7]; + } + } + + +#define TYPED_GETSET_IMPLEMENTATION(type, base, suffix) \ + type get##base##suffix(unsigned offset = 0) const \ + { \ + union { \ + type t; \ + char u8[sizeof(type)]; \ + } u; \ + getData##suffix(u.u8, offset); \ + return u.t; \ + } \ + void set##base##suffix(type value, unsigned offset = 0) \ + { \ + union { \ + type t; \ + char u8[sizeof(type)]; \ + } u; \ + u.t = value; \ + setData##suffix(u.u8, offset); \ + } + + TYPED_GETSET_IMPLEMENTATION(uint8_t, UInt, 8) + TYPED_GETSET_IMPLEMENTATION(int8_t, Int, 8) + TYPED_GETSET_IMPLEMENTATION(uint16_t, UInt, 16LE) + TYPED_GETSET_IMPLEMENTATION(uint16_t, UInt, 16BE) + TYPED_GETSET_IMPLEMENTATION(int16_t, Int, 16LE) + TYPED_GETSET_IMPLEMENTATION(int16_t, Int, 16BE) + TYPED_GETSET_IMPLEMENTATION(uint32_t, UInt, 32LE) + TYPED_GETSET_IMPLEMENTATION(uint32_t, UInt, 32BE) + TYPED_GETSET_IMPLEMENTATION(int32_t, Int, 32LE) + TYPED_GETSET_IMPLEMENTATION(int32_t, Int, 32BE) + TYPED_GETSET_IMPLEMENTATION(uint64_t, UInt, 64LE) + TYPED_GETSET_IMPLEMENTATION(uint64_t, UInt, 64BE) + TYPED_GETSET_IMPLEMENTATION(int64_t, Int, 64LE) + TYPED_GETSET_IMPLEMENTATION(int64_t, Int, 64BE) + + TYPED_GETSET_IMPLEMENTATION(float, Float, 32LE) + TYPED_GETSET_IMPLEMENTATION(float, Float, 32BE) + TYPED_GETSET_IMPLEMENTATION(double, Float, 64LE) + TYPED_GETSET_IMPLEMENTATION(double, Float, 64BE) + +#undef TYPED_GETSET_IMPLEMENTATION + +private: + static inline bool hostIsLittleEndian() + { + union { + uint16_t u16; + uint8_t u8[2]; + } u; + u.u16 = 1; + return u.u8[0] == 1; + } + + void ensureCapacity(unsigned capacity) + { + if (capacity < 32) + capacity = 32; + char* data = new char[capacity]; + if (_size) + memcpy(data, _data, _size); + if (_capacity) + delete [] _data; + _data = data; + _capacity = capacity; + } + + char* _data; + unsigned _size; + unsigned _capacity; +}; + +// A single attribute/parameter update blob +typedef std::pair RTIIndexDataPair; + +// A complete set of updates we received in one reflect/receive call +typedef std::list RTIIndexDataPairList; + +/// Gets an own header at some time + +class RTIBasicDataStream { +public: + RTIBasicDataStream() : _offset(0) {} + + /// Get aligned offset that aligns to a multiple of size + static inline unsigned getAlignedOffset(unsigned offset, unsigned size) + { + return ((offset + size - 1)/size) * size; + } + +protected: + unsigned _offset; +}; + +class HLADecodeStream : public RTIBasicDataStream { +public: + HLADecodeStream(const RTIData& value) : + _value(value) + { } + + bool alignOffsetForSize(unsigned size) + { + _offset = getAlignedOffset(_offset, size); + return _offset <= _value.size(); + } + + bool skip(unsigned size) + { + _offset += size; + return _offset <= _value.size(); + } + + bool eof() const + { return _value.size() <= _offset; } + + const RTIData& getData() const + { return _value; } + +#define TYPED_READ_IMPLEMENTATION(type, base, suffix) \ + bool decode##base##suffix(type& value) \ + { \ + if (_value.size() < _offset + sizeof(type)) \ + return false; \ + value = _value.get##base##suffix(_offset); \ + _offset += sizeof(type); \ + return true; \ + } + + TYPED_READ_IMPLEMENTATION(uint8_t, UInt, 8) + TYPED_READ_IMPLEMENTATION(int8_t, Int, 8) + TYPED_READ_IMPLEMENTATION(uint16_t, UInt, 16LE) + TYPED_READ_IMPLEMENTATION(uint16_t, UInt, 16BE) + TYPED_READ_IMPLEMENTATION(int16_t, Int, 16LE) + TYPED_READ_IMPLEMENTATION(int16_t, Int, 16BE) + TYPED_READ_IMPLEMENTATION(uint32_t, UInt, 32LE) + TYPED_READ_IMPLEMENTATION(uint32_t, UInt, 32BE) + TYPED_READ_IMPLEMENTATION(int32_t, Int, 32LE) + TYPED_READ_IMPLEMENTATION(int32_t, Int, 32BE) + TYPED_READ_IMPLEMENTATION(uint64_t, UInt, 64LE) + TYPED_READ_IMPLEMENTATION(uint64_t, UInt, 64BE) + TYPED_READ_IMPLEMENTATION(int64_t, Int, 64LE) + TYPED_READ_IMPLEMENTATION(int64_t, Int, 64BE) + + TYPED_READ_IMPLEMENTATION(float, Float, 32LE) + TYPED_READ_IMPLEMENTATION(float, Float, 32BE) + TYPED_READ_IMPLEMENTATION(double, Float, 64LE) + TYPED_READ_IMPLEMENTATION(double, Float, 64BE) + +#undef TYPED_READ_IMPLEMENTATION + +private: + const RTIData& _value; +}; + +class HLAEncodeStream : public RTIBasicDataStream { +public: + HLAEncodeStream(RTIData& value) : + _value(value) + { } + + bool alignOffsetForSize(unsigned size) + { + _offset = getAlignedOffset(_offset, size); + _value.resize(_offset); + return true; + } + + bool skip(unsigned size) + { + _offset += size; + _value.resize(_offset); + return true; + } + + bool eof() const + { return _value.size() <= _offset; } + + void setData(const RTIData& data) + { _value = data; } + +#define TYPED_WRITE_IMPLEMENTATION(type, base, suffix) \ + bool encode##base##suffix(type value) \ + { \ + unsigned nextOffset = _offset + sizeof(type); \ + _value.resize(nextOffset); \ + _value.set##base##suffix(value, _offset); \ + _offset = nextOffset; \ + return true; \ + } + + TYPED_WRITE_IMPLEMENTATION(uint8_t, UInt, 8) + TYPED_WRITE_IMPLEMENTATION(int8_t, Int, 8) + TYPED_WRITE_IMPLEMENTATION(uint16_t, UInt, 16LE) + TYPED_WRITE_IMPLEMENTATION(uint16_t, UInt, 16BE) + TYPED_WRITE_IMPLEMENTATION(int16_t, Int, 16LE) + TYPED_WRITE_IMPLEMENTATION(int16_t, Int, 16BE) + TYPED_WRITE_IMPLEMENTATION(uint32_t, UInt, 32LE) + TYPED_WRITE_IMPLEMENTATION(uint32_t, UInt, 32BE) + TYPED_WRITE_IMPLEMENTATION(int32_t, Int, 32LE) + TYPED_WRITE_IMPLEMENTATION(int32_t, Int, 32BE) + TYPED_WRITE_IMPLEMENTATION(uint64_t, UInt, 64LE) + TYPED_WRITE_IMPLEMENTATION(uint64_t, UInt, 64BE) + TYPED_WRITE_IMPLEMENTATION(int64_t, Int, 64LE) + TYPED_WRITE_IMPLEMENTATION(int64_t, Int, 64BE) + + TYPED_WRITE_IMPLEMENTATION(float, Float, 32LE) + TYPED_WRITE_IMPLEMENTATION(float, Float, 32BE) + TYPED_WRITE_IMPLEMENTATION(double, Float, 64LE) + TYPED_WRITE_IMPLEMENTATION(double, Float, 64BE) + +#undef TYPED_WRITE_IMPLEMENTATION + +private: + RTIData& _value; +}; + +} // namespace simgear + +#endif diff --git a/simgear/hla/RTIFederate.cxx b/simgear/hla/RTIFederate.cxx new file mode 100644 index 00000000..5d754fb2 --- /dev/null +++ b/simgear/hla/RTIFederate.cxx @@ -0,0 +1,30 @@ +// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#include "RTIFederate.hxx" + +namespace simgear { + +RTIFederate::RTIFederate() +{ +} + +RTIFederate::~RTIFederate() +{ +} + +} diff --git a/simgear/hla/RTIFederate.hxx b/simgear/hla/RTIFederate.hxx new file mode 100644 index 00000000..4b5d2d83 --- /dev/null +++ b/simgear/hla/RTIFederate.hxx @@ -0,0 +1,96 @@ +// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#ifndef RTIFederate_hxx +#define RTIFederate_hxx + +#include +#include "simgear/structure/SGWeakReferenced.hxx" +#include "RTIObjectClass.hxx" +#include "RTIObjectInstance.hxx" + +class SGTimeStamp; + +namespace simgear { + +class RTIFederate : public SGWeakReferenced { +public: + RTIFederate(); + virtual ~RTIFederate(); + + /// Get the name of the joined federate/federation + const std::string& getFederateType() const + { return _federateType; } + const std::string& getFederationName() const + { return _federationName; } + + /// Create a federation execution + /// Semantically this methods should be static, + /// but the nonstatic case could reuse the connection to the server + /// FIXME: cannot determine from the return value if we created the execution + virtual bool createFederationExecution(const std::string& federation, const std::string& objectModel) = 0; + virtual bool destroyFederationExecution(const std::string& federation) = 0; + + /// Join with federateName the federation execution federation + virtual bool join(const std::string& federateType, const std::string& federation) = 0; + virtual bool resign() = 0; + + /// Synchronization Point handling + virtual bool registerFederationSynchronizationPoint(const std::string& label, const RTIData& tag) = 0; + virtual bool waitForFederationSynchronizationPointAnnounced(const std::string& label) = 0; + virtual bool synchronizationPointAchieved(const std::string& label) = 0; + virtual bool waitForFederationSynchronized(const std::string& label) = 0; + + /// Time management + virtual bool enableTimeConstrained() = 0; + virtual bool disableTimeConstrained() = 0; + + virtual bool enableTimeRegulation(const SGTimeStamp& lookahead) = 0; + virtual bool disableTimeRegulation() = 0; + + virtual bool timeAdvanceRequestBy(const SGTimeStamp& dt) = 0; + virtual bool timeAdvanceRequest(const SGTimeStamp& fedTime) = 0; + + /// Process messages + virtual bool tick() = 0; + virtual bool tick(const double& minimum, const double& maximum) = 0; + + virtual RTIObjectClass* createObjectClass(const std::string& name, HLAObjectClass* hlaObjectClass) = 0; + // virtual RTIInteractionClass* createInteractionClass(const std::string& name) = 0; + + virtual RTIObjectInstance* getObjectInstance(const std::string& name) = 0; + +protected: + void setFederateType(const std::string& federateType) + { _federateType = federateType; } + void setFederationName(const std::string& federationName) + { _federationName = federationName; } + +private: + RTIFederate(const RTIFederate&); + RTIFederate& operator=(const RTIFederate&); + + /// The federates name + std::string _federateType; + + /// The federation execution name + std::string _federationName; +}; + +} + +#endif diff --git a/simgear/hla/RTIInteractionClass.hxx b/simgear/hla/RTIInteractionClass.hxx new file mode 100644 index 00000000..9cfafbd1 --- /dev/null +++ b/simgear/hla/RTIInteractionClass.hxx @@ -0,0 +1,63 @@ +// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#ifndef RTIInteractionClass_hxx +#define RTIInteractionClass_hxx + +#include +#include +#include +#include "simgear/structure/SGReferenced.hxx" +#include "simgear/structure/SGSharedPtr.hxx" +#include "simgear/structure/SGReferenced.hxx" +#include "RTIData.hxx" + +namespace simgear { + +class RTIInteractionClass : public SGReferenced { +public: + RTIInteractionClass(const std::string& name); + virtual ~RTIInteractionClass(); + + const std::string& getName() const + { return _name; } + + virtual unsigned getNumParameters() const = 0; + virtual unsigned getParameterIndex(const std::string& name) const = 0; + virtual unsigned getOrCreateParameterIndex(const std::string& name) = 0; + + virtual bool publish(const std::set& indexSet) = 0; + virtual bool unpublish() = 0; + + virtual bool subscribe(const std::set& indexSet, bool) = 0; + virtual bool unsubscribe() = 0; + + virtual void send(const RTIData& tag) = 0; + virtual void send(const SGTimeStamp& timeStamp, const RTIData& tag) = 0; + + class ReceiveCallback : public SGReferenced { + public: + virtual ~ReceiveCallback() {} + }; + +private: + std::string _name; +}; + +} + +#endif diff --git a/simgear/hla/RTIObjectClass.cxx b/simgear/hla/RTIObjectClass.cxx new file mode 100644 index 00000000..98618cfc --- /dev/null +++ b/simgear/hla/RTIObjectClass.cxx @@ -0,0 +1,66 @@ +// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#include "RTIObjectClass.hxx" + +#include "RTIObjectInstance.hxx" + +namespace simgear { + +RTIObjectClass::RTIObjectClass(HLAObjectClass* hlaObjectClass) : + _hlaObjectClass(hlaObjectClass) +{ +} + +RTIObjectClass::~RTIObjectClass() +{ +} + +void +RTIObjectClass::discoverInstance(RTIObjectInstance* objectInstance, const RTIData& tag) const +{ + SGSharedPtr hlaObjectClass = _hlaObjectClass.lock(); + if (!hlaObjectClass.valid()) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Invalid hla object class pointer in RTIObjectClass::discoverInstance()."); + return; + } + hlaObjectClass->discoverInstance(objectInstance, tag); +} + +void +RTIObjectClass::startRegistration() const +{ + SGSharedPtr hlaObjectClass = _hlaObjectClass.lock(); + if (!hlaObjectClass.valid()) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Invalid hla object class pointer in RTIObjectClass::startRegstration()."); + return; + } + hlaObjectClass->startRegistrationCallback(); +} + +void +RTIObjectClass::stopRegistration() const +{ + SGSharedPtr hlaObjectClass = _hlaObjectClass.lock(); + if (!hlaObjectClass.valid()) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Invalid hla object class pointer in RTIObjectClass::stopRegistration()."); + return; + } + hlaObjectClass->stopRegistrationCallback(); +} + +} diff --git a/simgear/hla/RTIObjectClass.hxx b/simgear/hla/RTIObjectClass.hxx new file mode 100644 index 00000000..e659b983 --- /dev/null +++ b/simgear/hla/RTIObjectClass.hxx @@ -0,0 +1,122 @@ +// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#ifndef RTIObjectClass_hxx +#define RTIObjectClass_hxx + +#include +#include +#include "simgear/structure/SGReferenced.hxx" +#include "simgear/structure/SGSharedPtr.hxx" +#include "simgear/structure/SGWeakPtr.hxx" +#include "RTIData.hxx" +#include "HLAObjectClass.hxx" + +namespace simgear { + +class RTIObjectInstance; +class HLAObjectClass; + +class RTIObjectClass : public SGReferenced { +public: + RTIObjectClass(HLAObjectClass* hlaObjectClass); + virtual ~RTIObjectClass(); + + virtual std::string getName() const = 0; + + virtual unsigned getNumAttributes() const = 0; + virtual unsigned getAttributeIndex(const std::string& name) const = 0; + virtual unsigned getOrCreateAttributeIndex(const std::string& name) = 0; + + virtual bool publish(const std::set& indexSet) = 0; + virtual bool unpublish() = 0; + + virtual bool subscribe(const std::set& indexSet, bool) = 0; + virtual bool unsubscribe() = 0; + + // Factory to create an object instance that can be used in this current federate + virtual RTIObjectInstance* registerObjectInstance(HLAObjectInstance*) = 0; + + void discoverInstance(RTIObjectInstance* objectInstance, const RTIData& tag) const; + + void startRegistration() const; + void stopRegistration() const; + + void setAttributeDataType(unsigned index, SGSharedPtr dataType) + { + if (_attributeDataVector.size() <= index) + return; + _attributeDataVector[index]._dataType = dataType; + } + const HLADataType* getAttributeDataType(unsigned index) const + { + if (_attributeDataVector.size() <= index) + return 0; + return _attributeDataVector[index]._dataType.get(); + } + + HLAUpdateType getAttributeUpdateType(unsigned index) const + { + if (_attributeDataVector.size() <= index) + return HLAUndefinedUpdate; + return _attributeDataVector[index]._updateType; + } + void setAttributeUpdateType(unsigned index, HLAUpdateType updateType) + { + if (_attributeDataVector.size() <= index) + return; + _attributeDataVector[index]._updateType = updateType; + } + + bool getAttributeSubscribed(unsigned index) const + { + if (_attributeDataVector.size() <= index) + return false; + return _attributeDataVector[index]._subscribed; + } + bool getAttributePublished(unsigned index) const + { + if (_attributeDataVector.size() <= index) + return false; + return _attributeDataVector[index]._published; + } + std::string getAttributeName(unsigned index) const + { + if (_attributeDataVector.size() <= index) + return std::string(); + return _attributeDataVector[index]._name; + } + +protected: + struct AttributeData { + AttributeData(const std::string& name) : _name(name), _subscribed(false), _published(false), _updateType(HLAUndefinedUpdate) {} + std::string _name; + SGSharedPtr _dataType; + bool _subscribed; + bool _published; + HLAUpdateType _updateType; + }; + typedef std::vector AttributeDataVector; + AttributeDataVector _attributeDataVector; + +private: + SGWeakPtr _hlaObjectClass; +}; + +} + +#endif diff --git a/simgear/hla/RTIObjectInstance.cxx b/simgear/hla/RTIObjectInstance.cxx new file mode 100644 index 00000000..74544146 --- /dev/null +++ b/simgear/hla/RTIObjectInstance.cxx @@ -0,0 +1,90 @@ +// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#include "RTIObjectInstance.hxx" +#include "RTIObjectClass.hxx" +#include "HLAObjectInstance.hxx" + +namespace simgear { + +RTIObjectInstance::RTIObjectInstance(HLAObjectInstance* hlaObjectInstance) : + _hlaObjectInstance(hlaObjectInstance), + _pendingAttributeUpdateRequest(false) +{ +} + +RTIObjectInstance::~RTIObjectInstance() +{ +} + +unsigned +RTIObjectInstance::getNumAttributes() const +{ + return getObjectClass()->getNumAttributes(); +} + +unsigned +RTIObjectInstance::getAttributeIndex(const std::string& name) const +{ + return getObjectClass()->getAttributeIndex(name); +} + +std::string +RTIObjectInstance::getAttributeName(unsigned index) const +{ + return getObjectClass()->getAttributeName(index); +} + +void +RTIObjectInstance::removeInstance(const RTIData& tag) +{ + SGSharedPtr hlaObjectInstance = _hlaObjectInstance.lock(); + if (!hlaObjectInstance.valid()) + return; + hlaObjectInstance->removeInstance(tag); +} + +void +RTIObjectInstance::reflectAttributeValues(const RTIIndexDataPairList& dataPairList, const RTIData& tag) +{ + for (RTIIndexDataPairList::const_iterator i = dataPairList.begin(); + i != dataPairList.end(); ++i) { + reflectAttributeValue(i->first, i->second); + } + + SGSharedPtr hlaObjectInstance = _hlaObjectInstance.lock(); + if (!hlaObjectInstance.valid()) + return; + hlaObjectInstance->reflectAttributeValues(dataPairList, tag); +} + +void +RTIObjectInstance::reflectAttributeValues(const RTIIndexDataPairList& dataPairList, + const SGTimeStamp& timeStamp, const RTIData& tag) +{ + for (RTIIndexDataPairList::const_iterator i = dataPairList.begin(); + i != dataPairList.end(); ++i) { + reflectAttributeValue(i->first, i->second); + } + + SGSharedPtr hlaObjectInstance = _hlaObjectInstance.lock(); + if (!hlaObjectInstance.valid()) + return; + hlaObjectInstance->reflectAttributeValues(dataPairList, timeStamp, tag); +} + +} diff --git a/simgear/hla/RTIObjectInstance.hxx b/simgear/hla/RTIObjectInstance.hxx new file mode 100644 index 00000000..fb8f096a --- /dev/null +++ b/simgear/hla/RTIObjectInstance.hxx @@ -0,0 +1,354 @@ +// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#ifndef RTIObjectInstance_hxx +#define RTIObjectInstance_hxx + +#include +#include +#include +#include +#include "simgear/debug/logstream.hxx" +#include "simgear/structure/SGReferenced.hxx" +#include "simgear/structure/SGWeakPtr.hxx" +#include "simgear/timing/timestamp.hxx" +#include "RTIData.hxx" +#include "RTIObjectClass.hxx" +#include "HLADataElement.hxx" + +class SGTimeStamp; + +namespace simgear { + +class RTIObjectClass; +class HLAObjectInstance; + +class RTIObjectInstance : public SGReferenced { +public: + RTIObjectInstance(HLAObjectInstance* hlaObjectInstance); + virtual ~RTIObjectInstance(); + + virtual const RTIObjectClass* getObjectClass() const = 0; + + virtual std::string getName() const = 0; + + unsigned getNumAttributes() const; + unsigned getAttributeIndex(const std::string& name) const; + std::string getAttributeName(unsigned index) const; + + // FIXME: factor out an ambassador base + virtual void addToRequestQueue() = 0; + + virtual void deleteObjectInstance(const RTIData& tag) = 0; + virtual void deleteObjectInstance(const SGTimeStamp& timeStamp, const RTIData& tag) = 0; + virtual void localDeleteObjectInstance() = 0; + + virtual void requestObjectAttributeValueUpdate() = 0; + + virtual void updateAttributeValues(const RTIData& tag) = 0; + virtual void updateAttributeValues(const SGTimeStamp& timeStamp, const RTIData& tag) = 0; + + void removeInstance(const RTIData& tag); + // Call this if you want to roll up the queued timestamed updates + // and reflect that into the attached data elements. + void reflectQueuedAttributeValues(const SGTimeStamp& timeStamp) + { + // replay all updates up to the given timestamp + UpdateListMap::iterator last = _updateListMap.upper_bound(timeStamp); + for (UpdateListMap::iterator i = _updateListMap.begin(); i != last; ++i) { + for (UpdateList::iterator j = i->second.begin(); j != i->second.end(); ++j) { + // FIXME have a variant that takes the timestamp? + reflectAttributeValues(j->_indexDataPairList, j->_tag); + } + putUpdateToPool(i->second); + } + } + void reflectAttributeValues(const RTIIndexDataPairList& dataPairList, const RTIData& tag); + void reflectAttributeValues(const RTIIndexDataPairList& dataPairList, const SGTimeStamp& timeStamp, const RTIData& tag); + void reflectAttributeValue(unsigned i, const RTIData& data) + { + if (_attributeData.size() <= i) + return; + HLADataElement* dataElement = _attributeData[i]._dataElement.get(); + if (!dataElement) + return; + HLADecodeStream stream(data); + dataElement->decode(stream); + } + + const HLADataType* getAttributeDataType(unsigned i) const + { + return getObjectClass()->getAttributeDataType(i); + } + HLAUpdateType getAttributeUpdateType(unsigned i) const + { + return getObjectClass()->getAttributeUpdateType(i); + } + bool getAttributeSubscribed(unsigned i) const + { + return getObjectClass()->getAttributeSubscribed(i); + } + bool getAttributePublished(unsigned i) const + { + return getObjectClass()->getAttributePublished(i); + } + + HLADataElement* getDataElement(unsigned i) + { + if (_attributeData.size() <= i) + return 0; + return _attributeData[i]._dataElement.get(); + } + const HLADataElement* getDataElement(unsigned i) const + { + if (_attributeData.size() <= i) + return 0; + return _attributeData[i]._dataElement.get(); + } + void setDataElement(unsigned i, HLADataElement* dataElement) + { + if (_attributeData.size() <= i) + return; + _attributeData[i]._dataElement = dataElement; + } + + void updateAttributesFromClass(bool owned) + { + // FIXME: rethink that!!! + unsigned numAttributes = getNumAttributes(); + unsigned i = 0; + for (; i < _attributeData.size(); ++i) { + if (getAttributePublished(i)) { + } else { + _attributeData[i].setUpdateEnabled(false); + _attributeData[i].setOwned(false); + } + } + _attributeData.resize(numAttributes); + for (; i < numAttributes; ++i) { + if (getAttributePublished(i)) { + _attributeData[i].setUpdateEnabled(true); + _attributeData[i].setOwned(owned); + } else { + _attributeData[i].setUpdateEnabled(false); + _attributeData[i].setOwned(false); + } + } + } + + void setAttributeForceUpdate(unsigned i) + { + if (_attributeData.size() <= i) + return; + _attributeData[i].setForceUpdate(true); + } + void setAttributeInScope(unsigned i, bool inScope) + { + if (_attributeData.size() <= i) + return; + _attributeData[i].setInScope(inScope); + } + void setAttributeUpdateEnabled(unsigned i, bool enabled) + { + if (_attributeData.size() <= i) + return; + _attributeData[i].setUpdateEnabled(enabled); + } + void setAttributeUpdated(unsigned i) + { + if (_attributeData.size() <= i) + return; + _attributeData[i].setForceUpdate(false); + } + bool getAttributeEffectiveUpdateEnabled(unsigned i) + { + if (_attributeData.size() <= i) + return false; + if (!getAttributePublished(i)) + return false; + if (!_attributeData[i]._updateEnabled) + return false; + if (!_attributeData[i]._inScope) + return false; + if (_attributeData[i]._forceUpdate) + return true; + switch (getAttributeUpdateType(i)) { + case HLAPeriodicUpdate: + return true; + case HLAConditionalUpdate: + return true; // FIXME + case HLAStaticUpdate: + return false; + default: + return false; + } + } + void setRequestAttributeUpdate(bool request) + { + for (unsigned i = 0; i < getNumAttributes(); ++i) { + if (getAttributeUpdateType(i) == HLAPeriodicUpdate) + continue; + setRequestAttributeUpdate(i, request); + } + } + void setRequestAttributeUpdate(unsigned i, bool request) + { + if (_attributeData.size() <= i) + return; + _attributeData[i].setRequestUpdate(request); + if (request) { + if (!_pendingAttributeUpdateRequest) { + _pendingAttributeUpdateRequest = true; + addToRequestQueue(); + } + } + } + bool getRequestAttributeUpdate(unsigned i) const + { + if (_attributeData.size() <= i) + return false; + return _attributeData[i]._requestUpdate; + } + + void flushPendingRequests() + { + if (_pendingAttributeUpdateRequest) { + requestObjectAttributeValueUpdate(); + _pendingAttributeUpdateRequest = false; + } + } + +protected: + // The backward reference to the user visible object + SGWeakPtr _hlaObjectInstance; + + // Is true if we should emit a requestattr + bool _pendingAttributeUpdateRequest; + + // Contains a full update as it came in from the RTI + struct Update { + RTIIndexDataPairList _indexDataPairList; + RTIData _tag; + }; + // A bunch of updates for the same timestamp + typedef std::list UpdateList; + // The timestamp sorted list of updates + typedef std::map UpdateListMap; + + // The timestamped updates sorted by timestamp + UpdateListMap _updateListMap; + + // The pool of unused updates so that we do not need to malloc/free each time + UpdateList _updateList; + + void getUpdateFromPool(UpdateList& updateList) + { + if (_updateList.empty()) + updateList.push_back(Update()); + else + updateList.splice(updateList.end(), _updateList, _updateList.begin()); + } + void putUpdateToPool(UpdateList& updateList) + { + for (UpdateList::iterator i = updateList.begin(); i != updateList.end(); ++i) + putDataToPool(i->_indexDataPairList); + _updateList.splice(_updateList.end(), updateList); + } + + // Appends the updates in the list to the given timestamps updates + void scheduleUpdates(const SGTimeStamp& timeStamp, UpdateList& updateList) + { + UpdateListMap::iterator i = _updateListMap.find(timeStamp); + if (i == _updateListMap.end()) + i = _updateListMap.insert(UpdateListMap::value_type(timeStamp, UpdateList())).first; + i->second.splice(i->second.end(), updateList); + } + + // This adds raw storage for attribute index i to the end of the dataPairList. + void getDataFromPool(unsigned i, RTIIndexDataPairList& dataPairList) + { + if (_attributeData.size() <= i) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Invalid object attribute index!"); + return; + } + + // Nothing left in the pool - so allocate something + if (_attributeData[i]._indexDataPairList.empty()) { + dataPairList.push_back(RTIIndexDataPairList::value_type()); + dataPairList.back().first = i; + return; + } + + // Take one from the pool + dataPairList.splice(dataPairList.end(), + _attributeData[i]._indexDataPairList, + _attributeData[i]._indexDataPairList.begin()); + } + + void putDataToPool(RTIIndexDataPairList& dataPairList) + { + while (!dataPairList.empty()) { + // Put back into the pool + unsigned i = dataPairList.front().first; + if (_attributeData.size() <= i) { + // should not happen!!! + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Invalid object attribute index!"); + dataPairList.pop_front(); + } else { + _attributeData[i]._indexDataPairList.splice(_attributeData[i]._indexDataPairList.begin(), + dataPairList, dataPairList.begin()); + } + } + } + + struct AttributeData { + AttributeData() : _owned(false), _inScope(true), _updateEnabled(true), _forceUpdate(false), _requestUpdate(false) + { } + + // The hla level data element with tha actual local program + // accessible data. + SGSharedPtr _dataElement; + // SGSharedPtr _timeStamp; + + // Pool of already allocated raw data used for reflection of updates + RTIIndexDataPairList _indexDataPairList; + + void setOwned(bool owned) + { _owned = owned; } + void setInScope(bool inScope) + { _inScope = inScope; } + void setUpdateEnabled(bool updateEnabled) + { _updateEnabled = updateEnabled; } + void setForceUpdate(bool forceUpdate) + { _forceUpdate = forceUpdate; } + void setRequestUpdate(bool requestUpdate) + { _requestUpdate = requestUpdate; } + + bool _owned; + bool _inScope; + bool _updateEnabled; + bool _forceUpdate; + bool _requestUpdate; + }; + std::vector _attributeData; + + friend class HLAObjectInstance; +}; + +} + +#endif