-
Oliver Sander authored
[[Imported from SVN: r6750]]
Oliver Sander authored[[Imported from SVN: r6750]]
rigidbodymotion.hh 4.84 KiB
#ifndef RIGID_BODY_MOTION_HH
#define RIGID_BODY_MOTION_HH
#include <dune/common/fvector.hh>
#include "rotation.hh"
/** \brief A rigid-body motion in, R^d, i.e., a member of SE(d) */
template <int dim, class T=double>
struct RigidBodyMotion
{
/** \brief Global coordinates wrt an isometric embedding function are available */
static const bool globalIsometricCoordinates = Rotation<dim,T>::globalIsometricCoordinates;
/** \brief Type of an infinitesimal rigid body motion */
typedef Dune::FieldVector<T, dim + Rotation<dim,T>::TangentVector::size> TangentVector;
/** \brief Type of an infinitesimal rigid body motion */
typedef Dune::FieldVector<T, dim + Rotation<dim,T>::EmbeddedTangentVector::size> EmbeddedTangentVector;
/** \brief The type used for coordinates */
typedef T ctype;
/** \brief Default constructor */
RigidBodyMotion()
{}
/** \brief Constructor from a translation and a rotation */
RigidBodyMotion(const Dune::FieldVector<ctype, dim>& translation,
const Rotation<dim,ctype>& rotation)
: r(translation), q(rotation)
{}
/** \brief The exponential map from a given point $p \in SE(d)$.
Why the template parameter? Well, it should work with both TangentVector and EmbeddedTangentVector.
In general these differ and we could just have two exp methods. However in 2d they do _not_ differ,
and then the compiler complains about having two methods with the same signature.
*/
template <class TVector>
static RigidBodyMotion<dim,ctype> exp(const RigidBodyMotion<dim,ctype>& p, const TVector& v) {
RigidBodyMotion<dim,ctype> result;
// Add translational correction
for (int i=0; i<dim; i++)
result.r[i] = p.r[i] + v[i];
// Add rotational correction
typedef typename Dune::SelectType<Dune::is_same<TVector,TangentVector>::value,
typename Rotation<dim,ctype>::TangentVector,
typename Rotation<dim,ctype>::EmbeddedTangentVector>::Type RotationTangentVector;
RotationTangentVector qCorr;
for (int i=0; i<RotationTangentVector::size; i++)
qCorr[i] = v[dim+i];
result.q = Rotation<dim,ctype>::exp(p.q, qCorr);
return result;
}
/** \brief Compute geodesic distance from a to b */
static T distance(const RigidBodyMotion<dim,ctype>& a, const RigidBodyMotion<dim,ctype>& b) {
T euclideanDistanceSquared = (a.r - b.r).two_norm2();
T rotationDistance = Rotation<dim,ctype>::distance(a.q, b.q);
return std::sqrt(euclideanDistanceSquared + rotationDistance*rotationDistance);
}
/** \brief Compute difference vector from a to b on the tangent space of a */
static TangentVector difference(const RigidBodyMotion<dim,ctype>& a,
const RigidBodyMotion<dim,ctype>& b) {
TangentVector result;
// Usual linear difference
for (int i=0; i<dim; i++)
result[i] = a.r[i] - b.r[i];
// Subtract orientations on the tangent space of 'a'
typename Rotation<dim,ctype>::TangentVector v = Rotation<dim,ctype>::difference(a.q, b.q);
// Compute difference on T_a SO(3)
for (int i=0; i<Rotation<dim,ctype>::TangentVector::size; i++)
result[i+dim] = v[i];
return result;
}
static EmbeddedTangentVector derivativeOfDistanceSquaredWRTSecondArgument(const RigidBodyMotion<dim,ctype>& a,
const RigidBodyMotion<dim,ctype>& b) {
// linear part
Dune::FieldVector<ctype,dim> linearDerivative = a.r;
linearDerivative -= b.r;
linearDerivative *= -2;
// rotation part
typename Rotation<dim,ctype>::EmbeddedTangentVector rotationDerivative
= Rotation<dim,ctype>::derivativeOfDistanceSquaredWRTSecondArgument(a.q, b.q);
return concat(linearDerivative, rotationDerivative);
}
// Translational part
Dune::FieldVector<ctype, dim> r;
// Rotational part
Rotation<dim,ctype> q;
private:
/** \brief Concatenate two FieldVectors */
template <int N, int M>
static Dune::FieldVector<ctype,N+M> concat(const Dune::FieldVector<ctype,N>& a,
const Dune::FieldVector<ctype,M>& b)
{
Dune::FieldVector<ctype,N+M> result;
for (int i=0; i<N; i++)
result[i] = a[i];
for (int i=0; i<M; i++)
result[i+N] = b[i];
return result;
}
};
//! Send configuration to output stream
template <int dim, class ctype>
std::ostream& operator<< (std::ostream& s, const RigidBodyMotion<dim,ctype>& c)
{
s << "(" << c.r << ") (" << c.q << ")";
return s;
}
#endif