/* * Copyright (C) 2009 * Robert Bosch LLC * Research and Technology Center North America * Palo Alto, California * * All rights reserved. * *------------------------------------------------------------------------------ * project ....: Autonomous Technologies * file .......: rtcTransform.h * authors ....: Benjamin Pitzer * organization: Robert Bosch LLC * creation ...: 08/16/2006 * modified ...: $Date: 2009-01-21 18:19:16 -0800 (Wed, 21 Jan 2009) $ * changed by .: $Author: benjaminpitzer $ * revision ...: $Revision: 14 $ */ #ifndef RTC_TRANSFORM_H #define RTC_TRANSFORM_H //== INCLUDES ================================================================== #include "rtcMath.h" #include "rtcRotation.h" #include "rtcEulerAngles.h" #include "rtcQuaternion.h" #include "rtcVec3.h" #include "rtcSMat4.h" //== NAMESPACES ================================================================ namespace rtc { // Forward declarations template class EulerAngles; // Euler angles template class Rotation; // Rotation matrix (3x3) template class Transform; // Rigid tranform matrix (4x4) template class Quaternion; // Quaternion template class Vec3; // 3d Vector /** * The Tranform Matrix Class * * Defines transformation class for rigid body rotations and translations * that knows how to construct itself from several other common rotation * representations, such as quaternions, axis angles, and rotation matrices. */ template class Transform: public SMat4 { public: // Constructors Transform(); Transform(const Mat& m); Transform(const Rotation& rot); Transform(const Vec3& trans); Transform(const Rotation& rot, const Vec3& trans); // Accessors void get( Rotation& rot, Vec3& trans) const; Vec3 getTrans( ) const; Rotation getRot( ) const; // Mutators void set(const Rotation& rot); void set(const Vec3& trans); void set(const Rotation& rot, const Vec3& trans); void rotateX(T theta); void rotateY(T theta); void rotateZ(T theta); void translate(T x, T y, T z); void translate(const Vec3& t); // Helper for applying tranform to points: Transform * Vec Vec operator * (const Vec3& v) const; void apply(Vec3& v) const; Vec3 apply(const Vec3& v) const; //Special inverse that uses the fact this is a rigid transform matrix Transform inverted() const; // calculate a relative transformation inv(referenceFrame)*this Transform relativeTo(const Transform& referenceFrame) const; //TODO: figure out how to make << a friend and make this protected bool verifyTag(std::string got, std::string expected); // Inherited from parent using SMat::set; using SMat::x; using SMat::operator*; }; // Declare a few common typdefs typedef Transform Transformf; typedef Transform Transformd; // ASCII stream IO template std::ostream& operator<<(std::ostream& os, const Transform& trans); template std::istream& operator>>(std::istream& is, Transform& trans); //============================================================================== // Transform //============================================================================== /** Ctor that initializes to no rotation and no translation. */ template inline Transform::Transform() { set(Rotation(),Vec(T(0))); } /** Ctor that initializes to the given rotation and no translation. */ template inline Transform::Transform(const Rotation& r){ set(r,Vec3(T(0))); } /** Ctor that initializes to no rotation and the given translation. */ template inline Transform::Transform(const Vec3& t){ set(Rotation(),t); } /** Ctor that starts with the given rotation and translation. */ template inline Transform::Transform(const Rotation& rot, const Vec3& trans){ set(rot,trans); } /** Ctor that initializes from Mat. */ template inline Transform::Transform(const Mat& m) : SMat4(m) {} // Accessors /** Get the rotation and translation */ template inline void Transform::get(Rotation& r, Vec3& t) const{ r=Rotation(x[0],x[1],x[2], x[4],x[5],x[6], x[8],x[9],x[10]); t=Vec3(x[3],x[7],x[11]); } /** Get the rotation and translation */ template inline Vec3 Transform::getTrans() const{ return Vec3(x[3],x[7],x[11]); } /** Get the rotation and translation */ template inline Rotation Transform::getRot() const{ return Rotation(x[0],x[1],x[2], x[4],x[5],x[6], x[8],x[9],x[10]); } // Mutators /** Set only the rotation portion of the Transform. */ template inline void Transform::set(const Rotation& r) { for (int i=0;i<3;i++) for (int j=0;j<3;j++) (*this)(i,j) = r(i,j); x[12] = 0; x[13] = 0; x[14] = 0; x[15] = 1; } /** Set only the translation portion of the Transform. */ template inline void Transform::set(const Vec3& t) { x[3] = t(0); x[7] = t(1); x[11] = t(2); x[12] = 0; x[13] = 0; x[14] = 0; x[15] = 1; } /** Set to the given rotation and translation */ template inline void Transform::set(const Rotation& r, const Vec3& t) { set(r); set(t); } /** Apply a rotation about the x axis to the transform */ template inline void Transform::rotateX(T theta) { Transform temp; T ctheta = cos(theta), stheta = sin(theta); temp(1,1) = ctheta; temp(1,2) = -stheta; temp(2,1) = stheta; temp(2,2) = ctheta; leftMultiply(temp); } /** Apply a rotation about the y axis to the transform */ template inline void Transform::rotateY(T theta) { Transform temp; T ctheta = cos(theta), stheta = sin(theta); temp(0,0) = ctheta; temp(0,2) = stheta; temp(2,0) = -stheta; temp(2,2) = ctheta; leftMultiply(temp); } /** Apply a rotation about the z axis to the transform */ template inline void Transform::rotateZ(T theta) { Transform temp; T ctheta = cos(theta), stheta = sin(theta); temp(0,0) = ctheta; temp(0,1) = -stheta; temp(1,0) = stheta; temp(1,1) = ctheta; leftMultiply(temp); } /** Apply a translation to the transform */ template inline void Transform::translate(T _x, T _y, T _z) { x[3] += _x; x[7] += _y; x[11] += _z; } /** Apply a translation to the transform */ template inline void Transform::translate(const Vec3& t) { translate(t[0],t[1],t[2]); } /** Helper function that allows a tranform to operate on a point. */ template inline Vec Transform::operator * (const Vec3& v) const{ return (*this)*Vec4(v(0),v(1),v(2),T(1.0)); } /** Helper function that allows a transform to operate on a point. */ template inline void Transform::apply(Vec3& v) const { Vec v1 = (*this)*v; v.set(v1[0],v1[1],v1[2]); } /** Helper function that allows a transform to operate on a point. */ template inline Vec3 Transform::apply(const Vec3& v) const { Vec v1 = (*this)*v; return(Vec3(v1[0],v1[1],v1[2])); } /** Fast inverse of a rigid tranform matrix. * M = [ r t] * [ 0 1] * * inv(M) = [ r' -r'*t] * [ 0 1] */ template inline Transform Transform::inverted() const{ Rotation r(x[0],x[4],x[8], x[1],x[5],x[9], x[2],x[6],x[10]); Vec3 t(-x[3],-x[7],-x[11]); return Transform(r,r*t); } /** Converts to a new coordinate frame @return this transform relative to the provided reference frame */ template inline Transform Transform::relativeTo(const Transform& referenceFrame) const { return SMat4(referenceFrame.inverted()*(*this)); } template inline bool Transform::verifyTag(std::string got, std::string expected) { if (got == expected){ return true; } else{ std::cerr << "ERROR: input stream format error." << std::endl; std::cerr << "Expected: " << expected << " Got: " << got << std::endl; return false; } } /** Write state to stream as formated ASCII */ template std::ostream& operator<<(std::ostream& os, const Transform& trans){ Rotation rot; Vec3 t; trans.get( rot, t); EulerAngles r; r.set(rot); os << "rot " << r << std::endl; os << "trans " << t << std::endl; return os; } /** Restores state data from formated ASCII stream * supports reading old and new formats */ template std::istream& operator>>(std::istream& is, Transform& trans){ using namespace std; Rotation rot; Vec3 t; string buf; is >> buf; //old format (rot as quat) if (trans.verifyTag(buf,"r")){ Quaternion q; if (trans.verifyTag(buf,"r")){ is >> q; } else{ cout << "format error" << endl; exit(0); } is >> buf; if (trans.verifyTag(buf,"t")){ is >> t; } else{ cout << "format error" << endl; exit(0); } rot = Rotation(q); } //new format (rot as euler angles) else{ EulerAngles ea; if (trans.verifyTag(buf,"rot")){ is >> ea; } else{ cout << "format error" << endl; exit(0); } is >> buf; if (trans.verifyTag(buf,"trans")){ is >> t; } else{ cout << "format error" << endl; exit(0); } rot = Rotation(ea); } trans.set(rot,t); return is; } //============================================================================== } // namespace rtc //============================================================================== #endif // RTC_TRANSFORM_H defined //==============================================================================