hla: Use an implementation file for SGLocation.

This commit is contained in:
Mathias Froehlich
2012-11-25 21:08:04 +01:00
parent 420e43d47d
commit 72a0ff706d
3 changed files with 629 additions and 466 deletions

View File

@@ -41,6 +41,7 @@ set(HLA_SOURCES
HLAInteractionClass.cxx
HLAFixedRecordDataElement.cxx
HLAFixedRecordDataType.cxx
HLALocation.cxx
HLAObjectClass.cxx
HLAObjectInstance.cxx
HLAOMTXmlVisitor.cxx

578
simgear/hla/HLALocation.cxx Normal file
View File

@@ -0,0 +1,578 @@
// 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.
//
#ifdef HAVE_CONFIG_H
# include <simgear_config.h>
#endif
#include <simgear/compiler.h>
#include "HLALocation.hxx"
#include "HLAArrayDataElement.hxx"
#include "HLAObjectInstance.hxx"
namespace simgear {
HLAAbstractLocationFactory::~HLAAbstractLocationFactory()
{
}
////////////////////////////////////////////////////////////////////////
HLACartesianLocation::HLACartesianLocation()
{
}
HLACartesianLocation::~HLACartesianLocation()
{
}
SGLocationd
HLACartesianLocation::getLocation() const
{
return SGLocationd(getCartPosition(), getCartOrientation());
}
void
HLACartesianLocation::setLocation(const SGLocationd& location)
{
setCartPosition(location.getPosition());
setCartOrientation(location.getOrientation());
}
SGVec3d
HLACartesianLocation::getCartPosition() const
{
return SGVec3d(_position[0].getValue(), _position[1].getValue(), _position[2].getValue());
}
void
HLACartesianLocation::setCartPosition(const SGVec3d& position)
{
for (unsigned i = 0; i < 3; ++i)
_position[i].setValue(position[i]);
}
SGQuatd
HLACartesianLocation::getCartOrientation() const
{
return SGQuatd::fromPositiveRealImag(SGVec3d(_imag[0].getValue(), _imag[1].getValue(), _imag[2].getValue()));
}
void
HLACartesianLocation::setCartOrientation(const SGQuatd& orientation)
{
SGVec3d imag = orientation.getPositiveRealImag();
for (unsigned i = 0; i < 3; ++i)
_imag[i].setValue(imag[i]);
}
SGVec3d
HLACartesianLocation::getAngularBodyVelocity() const
{
return SGVec3d(_angularVelocity[0].getValue(), _angularVelocity[1].getValue(), _angularVelocity[2].getValue());
}
void
HLACartesianLocation::setAngularBodyVelocity(const SGVec3d& angularVelocity)
{
for (unsigned i = 0; i < 3; ++i)
_angularVelocity[i].setValue(angularVelocity[i]);
}
SGVec3d
HLACartesianLocation::getLinearBodyVelocity() const
{
return SGVec3d(_linearVelocity[0].getValue(), _linearVelocity[1].getValue(), _linearVelocity[2].getValue());
}
void
HLACartesianLocation::setLinearBodyVelocity(const SGVec3d& linearVelocity)
{
for (unsigned i = 0; i < 3; ++i)
_linearVelocity[i].setValue(linearVelocity[i]);
}
double
HLACartesianLocation::getTimeDifference(const SGTimeStamp& timeStamp) const
{
return _position[0].getDataElement()->getTimeDifference(timeStamp);
}
HLADataElement*
HLACartesianLocation::getPositionDataElement()
{
HLAArrayDataElement* arrayDataElement = new HLAArrayDataElement;
for (unsigned i = 0; i < 3; ++i)
arrayDataElement->setElement(i, _position[i].getDataElement());
return arrayDataElement;
}
HLADataElement*
HLACartesianLocation::getPositionDataElement(unsigned i)
{
if (3 <= i)
return 0;
return _position[i].getDataElement();
}
HLADataElement*
HLACartesianLocation::getOrientationDataElement()
{
HLAArrayDataElement* arrayDataElement = new HLAArrayDataElement;
for (unsigned i = 0; i < 3; ++i)
arrayDataElement->setElement(i, _imag[i].getDataElement());
return arrayDataElement;
}
HLADataElement*
HLACartesianLocation::getOrientationDataElement(unsigned i)
{
if (3 <= i)
return 0;
return _imag[i].getDataElement();
}
HLADataElement*
HLACartesianLocation::getAngularVelocityDataElement()
{
HLAArrayDataElement* arrayDataElement = new HLAArrayDataElement;
for (unsigned i = 0; i < 3; ++i)
arrayDataElement->setElement(i, _angularVelocity[i].getDataElement());
return arrayDataElement;
}
HLADataElement*
HLACartesianLocation::getAngularVelocityDataElement(unsigned i)
{
if (3 <= i)
return 0;
return _angularVelocity[i].getDataElement();
}
HLADataElement*
HLACartesianLocation::getLinearVelocityDataElement()
{
HLAArrayDataElement* arrayDataElement = new HLAArrayDataElement;
for (unsigned i = 0; i < 3; ++i)
arrayDataElement->setElement(i, _linearVelocity[i].getDataElement());
return arrayDataElement;
}
HLADataElement*
HLACartesianLocation::getLinearVelocityDataElement(unsigned i)
{
if (3 <= i)
return 0;
return _linearVelocity[i].getDataElement();
}
////////////////////////////////////////////////////////////////////////
HLACartesianLocationFactory::HLACartesianLocationFactory()
{
}
HLACartesianLocationFactory::~HLACartesianLocationFactory()
{
}
HLACartesianLocation*
HLACartesianLocationFactory::createLocation(HLAObjectInstance& objectInstance) const
{
HLACartesianLocation* location = new HLACartesianLocation;
for (unsigned i = 0; i < 3; ++i)
objectInstance.setAttributeDataElement(_positionIndex[i], location->getPositionDataElement(i));
for (unsigned i = 0; i < 3; ++i)
objectInstance.setAttributeDataElement(_orientationIndex[i], location->getOrientationDataElement(i));
for (unsigned i = 0; i < 3; ++i)
objectInstance.setAttributeDataElement(_angularVelocityIndex[i], location->getAngularVelocityDataElement(i));
for (unsigned i = 0; i < 3; ++i)
objectInstance.setAttributeDataElement(_linearVelocityIndex[i], location->getLinearVelocityDataElement(i));
return location;
}
void
HLACartesianLocationFactory::setPositionIndex(const HLADataElementIndex& dataElementIndex)
{
for (unsigned i = 0; i < 3; ++i) {
_positionIndex[i] = dataElementIndex;
_positionIndex[i].push_back(i);
}
}
void
HLACartesianLocationFactory::setPositionIndex(unsigned index, const HLADataElementIndex& dataElementIndex)
{
if (3 <= index)
return;
_positionIndex[index] = dataElementIndex;
}
void
HLACartesianLocationFactory::setOrientationIndex(const HLADataElementIndex& dataElementIndex)
{
for (unsigned i = 0; i < 3; ++i) {
_orientationIndex[i] = dataElementIndex;
_orientationIndex[i].push_back(i);
}
}
void
HLACartesianLocationFactory::setOrientationIndex(unsigned index, const HLADataElementIndex& dataElementIndex)
{
if (3 <= index)
return;
_orientationIndex[index] = dataElementIndex;
}
void
HLACartesianLocationFactory::setAngularVelocityIndex(const HLADataElementIndex& dataElementIndex)
{
for (unsigned i = 0; i < 3; ++i) {
_angularVelocityIndex[i] = dataElementIndex;
_angularVelocityIndex[i].push_back(i);
}
}
void
HLACartesianLocationFactory::setAngularVelocityIndex(unsigned index, const HLADataElementIndex& dataElementIndex)
{
if (3 <= index)
return;
_angularVelocityIndex[index] = dataElementIndex;
}
void
HLACartesianLocationFactory::setLinearVelocityIndex(const HLADataElementIndex& dataElementIndex)
{
for (unsigned i = 0; i < 3; ++i) {
_linearVelocityIndex[i] = dataElementIndex;
_linearVelocityIndex[i].push_back(i);
}
}
void
HLACartesianLocationFactory::setLinearVelocityIndex(unsigned index, const HLADataElementIndex& dataElementIndex)
{
if (3 <= index)
return;
_linearVelocityIndex[index] = dataElementIndex;
}
////////////////////////////////////////////////////////////////////////
class HLAGeodeticLocationFactory::Location : public HLAAbstractLocation {
public:
Location() :
_dirty(true),
_cartPosition(SGVec3d::zeros()),
_cartOrientation(SGQuatd::unit()),
_cartBodyVelocity(SGVec3d::zeros()),
_geodPosition(),
_geodEulerRad(SGVec3d::zeros()),
_groundTrackRad(0),
_groundSpeedMPerSec(0),
_verticalSpeedMPerSec(0)
{
updateCartesianFromGeodetic();
}
virtual ~Location()
{
}
virtual SGLocationd getLocation() const
{
updateCartesianFromGeodetic();
return SGLocationd(_cartPosition, _cartOrientation);
}
virtual void setLocation(const SGLocationd& location)
{
_cartPosition = location.getPosition();
_cartOrientation = location.getOrientation();
_dirty = true;
}
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) \
HLADataElement* get## name ## DataElement() \
{ return new DataElement<&Location::get## name, &Location::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
HLADataElement* getDataElement(Semantic semantic)
{
switch (semantic) {
case LatitudeDeg:
return getLatitudeDegDataElement();
case LatitudeRad:
return getLatitudeRadDataElement();
case LongitudeDeg:
return getLongitudeDegDataElement();
case LongitudeRad:
return getLongitudeRadDataElement();
case ElevationM:
return getElevationMDataElement();
case ElevationFt:
return getElevationFtDataElement();
case HeadingDeg:
return getHeadingDegDataElement();
case HeadingRad:
return getHeadingRadDataElement();
case PitchDeg:
return getPitchDegDataElement();
case PitchRad:
return getPitchRadDataElement();
case RollDeg:
return getRollDegDataElement();
case RollRad:
return getRollRadDataElement();
case GroundTrackDeg:
return getGroundTrackDegDataElement();
case GroundTrackRad:
return getGroundTrackRadDataElement();
case GroundSpeedKnots:
return getGroundSpeedKnotsDataElement();
case GroundSpeedFtPerSec:
return getGroundSpeedFtPerSecDataElement();
case GroundSpeedMPerSec:
return getGroundSpeedMPerSecDataElement();
case VerticalSpeedFtPerSec:
return getVerticalSpeedFtPerSecDataElement();
case VerticalSpeedFtPerMin:
return getVerticalSpeedFtPerMinDataElement();
case VerticalSpeedMPerSec:
return getVerticalSpeedMPerSecDataElement();
default:
return 0;
}
}
private:
template<double (Location::*getter)() const, void (Location::*setter)(double)>
class DataElement : public HLAAbstractDoubleDataElement {
public:
DataElement(Location* data) :
_data(data)
{ }
virtual double getValue() const
{ return (_data->*getter)(); }
virtual void setValue(double value)
{ (_data->*setter)(value); }
private:
SGSharedPtr<Location> _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;
};
HLAGeodeticLocationFactory::HLAGeodeticLocationFactory()
{
}
HLAGeodeticLocationFactory::~HLAGeodeticLocationFactory()
{
}
HLAAbstractLocation*
HLAGeodeticLocationFactory::createLocation(HLAObjectInstance& objectInstance) const
{
Location* location = new Location;
for (IndexSemanticMap::const_iterator i = _indexSemanticMap.begin();
i != _indexSemanticMap.end(); ++i) {
Semantic semantic = i->second;
objectInstance.setAttributeDataElement(i->first, location->getDataElement(semantic));
}
return location;
}
} // namespace simgear

View File

@@ -24,6 +24,8 @@
namespace simgear {
class HLAObjectInstance;
class HLAAbstractLocation : public SGReferenced {
public:
virtual ~HLAAbstractLocation() {}
@@ -57,194 +59,77 @@ public:
class HLACartesianLocation : public HLAAbstractLocation {
public:
HLACartesianLocation() :
_position(SGVec3d::zeros()),
_imag(SGVec3d::zeros()),
_angularVelocity(SGVec3d::zeros()),
_linearVelocity(SGVec3d::zeros())
{ }
HLACartesianLocation();
virtual ~HLACartesianLocation();
virtual SGLocationd getLocation() const
{ return SGLocationd(_position, SGQuatd::fromPositiveRealImag(_imag)); }
virtual void setLocation(const SGLocationd& location)
{
_position = location.getPosition();
_imag = location.getOrientation().getPositiveRealImag();
}
virtual SGLocationd getLocation() const;
virtual void setLocation(const SGLocationd& location);
virtual SGVec3d getCartPosition() const
{ return _position; }
virtual void setCartPosition(const SGVec3d& position)
{ _position = position; }
virtual SGVec3d getCartPosition() const;
virtual void setCartPosition(const SGVec3d& position);
virtual SGQuatd getCartOrientation() const
{ return SGQuatd::fromPositiveRealImag(_imag); }
virtual void setCartOrientation(const SGQuatd& orientation)
{ _imag = orientation.getPositiveRealImag(); }
virtual SGQuatd getCartOrientation() const;
virtual void setCartOrientation(const SGQuatd& orientation);
virtual SGVec3d getAngularBodyVelocity() const
{ return _angularVelocity; }
virtual void setAngularBodyVelocity(const SGVec3d& angularVelocity)
{ _angularVelocity = angularVelocity; }
virtual SGVec3d getAngularBodyVelocity() const;
virtual void setAngularBodyVelocity(const SGVec3d& angularVelocity);
virtual SGVec3d getLinearBodyVelocity() const
{ return _linearVelocity; }
virtual void setLinearBodyVelocity(const SGVec3d& linearVelocity)
{ _linearVelocity = linearVelocity; }
virtual SGVec3d getLinearBodyVelocity() const;
virtual void setLinearBodyVelocity(const SGVec3d& linearVelocity);
HLADataElement* getPositionDataElement(unsigned i)
{
if (3 <= i)
return 0;
return new PositionDataElement(this, i);
}
HLADataElement* getOrientationDataElement(unsigned i)
{
if (3 <= i)
return 0;
return new OrientationDataElement(this, i);
}
virtual double getTimeDifference(const SGTimeStamp& timeStamp) const;
HLADataElement* getAngularVelocityDataElement(unsigned i)
{
if (3 <= i)
return 0;
return new AngularVelocityDataElement(this, i);
}
HLADataElement* getLinearVelocityDataElement(unsigned i)
{
if (3 <= i)
return 0;
return new LinearVelocityDataElement(this, i);
}
HLADataElement* getPositionDataElement();
HLADataElement* getPositionDataElement(unsigned i);
HLADataElement* getOrientationDataElement();
HLADataElement* getOrientationDataElement(unsigned i);
HLADataElement* getAngularVelocityDataElement();
HLADataElement* getAngularVelocityDataElement(unsigned i);
HLADataElement* getLinearVelocityDataElement();
HLADataElement* getLinearVelocityDataElement(unsigned 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; }
HLADoubleData _position[3];
HLADoubleData _imag[3];
private:
SGSharedPtr<HLACartesianLocation> _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<HLACartesianLocation> _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<HLACartesianLocation> _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<HLACartesianLocation> _data;
unsigned _index;
};
SGVec3d _position;
SGVec3d _imag;
SGVec3d _angularVelocity;
SGVec3d _linearVelocity;
HLADoubleData _angularVelocity[3];
HLADoubleData _linearVelocity[3];
};
class HLALocationFactory : public SGReferenced {
class HLAAbstractLocationFactory : public SGReferenced {
public:
virtual ~HLALocationFactory() {}
virtual ~HLAAbstractLocationFactory();
virtual HLAAbstractLocation* createLocation(HLAObjectInstance&) const = 0;
};
class HLACartesianLocationFactory : public HLALocationFactory {
typedef HLAAbstractLocationFactory HLALocationFactory;
class HLACartesianLocationFactory : public HLAAbstractLocationFactory {
public:
virtual HLACartesianLocation* createLocation(HLAObjectInstance& objectInstance) const
{
HLACartesianLocation* location = new HLACartesianLocation;
HLACartesianLocationFactory();
virtual ~HLACartesianLocationFactory();
for (unsigned i = 0; i < 3; ++i)
objectInstance.setAttributeDataElement(_positonIndex[i], location->getPositionDataElement(i));
for (unsigned i = 0; i < 3; ++i)
objectInstance.setAttributeDataElement(_orientationIndex[i], location->getOrientationDataElement(i));
for (unsigned i = 0; i < 3; ++i)
objectInstance.setAttributeDataElement(_angularVelocityIndex[i], location->getAngularVelocityDataElement(i));
for (unsigned i = 0; i < 3; ++i)
objectInstance.setAttributeDataElement(_linearVelocityIndex[i], location->getLinearVelocityDataElement(i));
virtual HLACartesianLocation* createLocation(HLAObjectInstance& objectInstance) const;
return location;
}
void setPositionIndex(const HLADataElementIndex& dataElementIndex);
void setPositionIndex(unsigned index, const HLADataElementIndex& dataElementIndex);
void setOrientationIndex(const HLADataElementIndex& dataElementIndex);
void setOrientationIndex(unsigned index, const HLADataElementIndex& dataElementIndex);
void setPositionIndex(unsigned index, const HLADataElementIndex& dataElementIndex)
{
if (3 <= index)
return;
_positonIndex[index] = dataElementIndex;
}
void setOrientationIndex(unsigned index, const HLADataElementIndex& dataElementIndex)
{
if (3 <= index)
return;
_orientationIndex[index] = dataElementIndex;
}
void setAngularVelocityIndex(unsigned index, const HLADataElementIndex& dataElementIndex)
{
if (3 <= index)
return;
_angularVelocityIndex[index] = dataElementIndex;
}
void setLinearVelocityIndex(unsigned index, const HLADataElementIndex& dataElementIndex)
{
if (3 <= index)
return;
_linearVelocityIndex[index] = dataElementIndex;
}
void setAngularVelocityIndex(const HLADataElementIndex& dataElementIndex);
void setAngularVelocityIndex(unsigned index, const HLADataElementIndex& dataElementIndex);
void setLinearVelocityIndex(const HLADataElementIndex& dataElementIndex);
void setLinearVelocityIndex(unsigned index, const HLADataElementIndex& dataElementIndex);
private:
HLADataElementIndex _positonIndex[3];
HLADataElementIndex _positionIndex[3];
HLADataElementIndex _orientationIndex[3];
HLADataElementIndex _angularVelocityIndex[3];
HLADataElementIndex _linearVelocityIndex[3];
};
class HLAGeodeticLocation : public HLAAbstractLocation {
class HLAGeodeticLocationFactory : public HLAAbstractLocationFactory {
public:
enum Semantic {
LatitudeDeg,
@@ -269,318 +154,17 @@ public:
VerticalSpeedMPerSec
};
HLAGeodeticLocation() :
_dirty(true),
_cartPosition(SGVec3d::zeros()),
_cartOrientation(SGQuatd::unit()),
_cartBodyVelocity(SGVec3d::zeros()),
_geodPosition(),
_geodEulerRad(SGVec3d::zeros()),
_groundTrackRad(0),
_groundSpeedMPerSec(0),
_verticalSpeedMPerSec(0)
{
updateCartesianFromGeodetic();
}
HLAGeodeticLocationFactory();
virtual ~HLAGeodeticLocationFactory();
virtual SGLocationd getLocation() const
{
updateCartesianFromGeodetic();
return SGLocationd(_cartPosition, _cartOrientation);
}
virtual void setLocation(const SGLocationd& location)
{
_cartPosition = location.getPosition();
_cartOrientation = location.getOrientation();
_dirty = true;
}
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) \
HLADataElement* 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
HLADataElement* getDataElement(Semantic semantic)
{
switch (semantic) {
case LatitudeDeg:
return getLatitudeDegDataElement();
case LatitudeRad:
return getLatitudeRadDataElement();
case LongitudeDeg:
return getLongitudeDegDataElement();
case LongitudeRad:
return getLongitudeRadDataElement();
case ElevationM:
return getElevationMDataElement();
case ElevationFt:
return getElevationFtDataElement();
case HeadingDeg:
return getHeadingDegDataElement();
case HeadingRad:
return getHeadingRadDataElement();
case PitchDeg:
return getPitchDegDataElement();
case PitchRad:
return getPitchRadDataElement();
case RollDeg:
return getRollDegDataElement();
case RollRad:
return getRollRadDataElement();
case GroundTrackDeg:
return getGroundTrackDegDataElement();
case GroundTrackRad:
return getGroundTrackRadDataElement();
case GroundSpeedKnots:
return getGroundSpeedKnotsDataElement();
case GroundSpeedFtPerSec:
return getGroundSpeedFtPerSecDataElement();
case GroundSpeedMPerSec:
return getGroundSpeedMPerSecDataElement();
case VerticalSpeedFtPerSec:
return getVerticalSpeedFtPerSecDataElement();
case VerticalSpeedFtPerMin:
return getVerticalSpeedFtPerMinDataElement();
case VerticalSpeedMPerSec:
return getVerticalSpeedMPerSecDataElement();
default:
return 0;
}
}
private:
template<double (HLAGeodeticLocation::*getter)() const,
void (HLAGeodeticLocation::*setter)(double)>
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<HLAGeodeticLocation> _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 = HLAGeodeticLocation::LatitudeDeg,
LatitudeRad = HLAGeodeticLocation::LatitudeRad,
LongitudeDeg = HLAGeodeticLocation::LongitudeDeg,
LongitudeRad = HLAGeodeticLocation::LongitudeRad,
ElevationM = HLAGeodeticLocation::ElevationM,
ElevationFt = HLAGeodeticLocation::ElevationFt,
HeadingDeg = HLAGeodeticLocation::HeadingDeg,
HeadingRad = HLAGeodeticLocation::HeadingRad,
PitchDeg = HLAGeodeticLocation::PitchDeg,
PitchRad = HLAGeodeticLocation::PitchRad,
RollDeg = HLAGeodeticLocation::RollDeg,
RollRad = HLAGeodeticLocation::RollRad,
GroundTrackDeg = HLAGeodeticLocation::GroundTrackDeg,
GroundTrackRad = HLAGeodeticLocation::GroundTrackRad,
GroundSpeedKnots = HLAGeodeticLocation::GroundSpeedKnots,
GroundSpeedFtPerSec = HLAGeodeticLocation::GroundSpeedFtPerSec,
GroundSpeedMPerSec = HLAGeodeticLocation::GroundSpeedMPerSec,
VerticalSpeedFtPerSec = HLAGeodeticLocation::VerticalSpeedFtPerSec,
VerticalSpeedFtPerMin = HLAGeodeticLocation::VerticalSpeedFtPerMin,
VerticalSpeedMPerSec = HLAGeodeticLocation::VerticalSpeedMPerSec
};
virtual HLAGeodeticLocation* createLocation(HLAObjectInstance& objectInstance) const
{
HLAGeodeticLocation* location = new HLAGeodeticLocation;
for (IndexSemanticMap::const_iterator i = _indexSemanticMap.begin();
i != _indexSemanticMap.end(); ++i) {
HLAGeodeticLocation::Semantic semantic = HLAGeodeticLocation::Semantic(i->second);
objectInstance.setAttributeDataElement(i->first, location->getDataElement(semantic));
}
return location;
}
virtual HLAAbstractLocation* createLocation(HLAObjectInstance& objectInstance) const;
void setIndex(Semantic semantic, const HLADataElementIndex& index)
{ _indexSemanticMap[index] = semantic; }
private:
class Location;
typedef std::map<HLADataElementIndex, Semantic> IndexSemanticMap;
IndexSemanticMap _indexSemanticMap;
};