198 lines
5.2 KiB
C++
198 lines
5.2 KiB
C++
/**
|
|
* @file Rot3.h
|
|
* @brief Rotation
|
|
* @author Alireza Fathi
|
|
* @author Christian Potthast
|
|
* @author Frank Dellaert
|
|
*/
|
|
|
|
// \callgraph
|
|
|
|
#pragma once
|
|
|
|
#include "Point3.h"
|
|
#include "Testable.h"
|
|
|
|
namespace gtsam {
|
|
|
|
/* Rotation matrix */
|
|
class Rot3: Testable<Rot3> {
|
|
private:
|
|
/** we store columns ! */
|
|
Point3 r1_, r2_, r3_;
|
|
|
|
public:
|
|
|
|
/** default coonstructor, unit rotation */
|
|
Rot3() : r1_(Point3(1.0,0.0,0.0)),
|
|
r2_(Point3(0.0,1.0,0.0)),
|
|
r3_(Point3(0.0,0.0,1.0)) {
|
|
}
|
|
|
|
/** constructor from columns */
|
|
Rot3(const Point3& r1, const Point3& r2, const Point3& r3) :
|
|
r1_(r1), r2_(r2), r3_(r3) {
|
|
}
|
|
|
|
/** constructor from vector */
|
|
Rot3(const Vector &v) :
|
|
r1_(Point3(v(0),v(1),v(2))),
|
|
r2_(Point3(v(3),v(4),v(5))),
|
|
r3_(Point3(v(6),v(7),v(8)))
|
|
{ }
|
|
|
|
/** constructor from doubles in *row* order !!! */
|
|
Rot3(double R11, double R12, double R13,
|
|
double R21, double R22, double R23,
|
|
double R31, double R32, double R33) :
|
|
r1_(Point3(R11, R21, R31)),
|
|
r2_(Point3(R12, R22, R32)),
|
|
r3_(Point3(R13, R23, R33)) {}
|
|
|
|
/** constructor from matrix */
|
|
Rot3(const Matrix& R):
|
|
r1_(Point3(R(0,0), R(1,0), R(2,0))),
|
|
r2_(Point3(R(0,1), R(1,1), R(2,1))),
|
|
r3_(Point3(R(0,2), R(1,2), R(2,2))) {}
|
|
|
|
/** print */
|
|
void print(const std::string& s="R") const { gtsam::print(matrix(), s);}
|
|
|
|
/** equals with an tolerance */
|
|
bool equals(const Rot3& p, double tol = 1e-9) const;
|
|
|
|
/** return DOF, dimensionality of tangent space */
|
|
size_t dim() const { return 3;}
|
|
|
|
/** Given 3-dim tangent vector, create new rotation */
|
|
Rot3 exmap(const Vector& d) const;
|
|
|
|
/** return vectorized form (column-wise)*/
|
|
Vector vector() const {
|
|
double r[] = { r1_.x(), r1_.y(), r1_.z(),
|
|
r2_.x(), r2_.y(), r2_.z(),
|
|
r3_.x(), r3_.y(), r3_.z() };
|
|
Vector v(9);
|
|
copy(r,r+9,v.begin());
|
|
return v;
|
|
}
|
|
|
|
/** return 3*3 rotation matrix */
|
|
Matrix matrix() const {
|
|
double r[] = { r1_.x(), r2_.x(), r3_.x(),
|
|
r1_.y(), r2_.y(), r3_.y(),
|
|
r1_.z(), r2_.z(), r3_.z() };
|
|
return Matrix_(3,3, r);
|
|
}
|
|
|
|
/** return 3*3 transpose (inverse) rotation matrix */
|
|
Matrix transpose() const {
|
|
double r[] = { r1_.x(), r1_.y(), r1_.z(),
|
|
r2_.x(), r2_.y(), r2_.z(),
|
|
r3_.x(), r3_.y(), r3_.z()};
|
|
return Matrix_(3,3, r);
|
|
}
|
|
|
|
/** returns column vector specified by index */
|
|
Point3 column(int index) const{
|
|
if(index == 3)
|
|
return r3_;
|
|
else if (index == 2)
|
|
return r2_;
|
|
else
|
|
return r1_; // default returns r1
|
|
}
|
|
|
|
/** inverse transformation */
|
|
Rot3 inverse() const {
|
|
return Rot3(
|
|
r1_.x(), r1_.y(), r1_.z(),
|
|
r2_.x(), r2_.y(), r2_.z(),
|
|
r3_.x(), r3_.y(), r3_.z());
|
|
}
|
|
|
|
/** composition */
|
|
inline Rot3 operator*(const Rot3& B) const { return Rot3(matrix()*B.matrix());}
|
|
|
|
/** rotate from rotated to world, syntactic sugar = R*p */
|
|
inline Point3 operator*(const Point3& p) const {
|
|
return r1_ * p.x() + r2_ * p.y() + r3_ * p.z();
|
|
}
|
|
|
|
/** rotate from world to rotated = R'*p */
|
|
Point3 unrotate(const Point3& p) const {
|
|
return Point3(
|
|
r1_.x() * p.x() + r1_.y() * p.y() + r1_.z() * p.z(),
|
|
r2_.x() * p.x() + r2_.y() * p.y() + r2_.z() * p.z(),
|
|
r3_.x() * p.x() + r3_.y() * p.y() + r3_.z() * p.z()
|
|
);
|
|
}
|
|
|
|
/** friends */
|
|
friend Matrix Dunrotate1(const Rot3& R, const Point3& p);
|
|
|
|
private:
|
|
/** Serialization function */
|
|
friend class boost::serialization::access;
|
|
template<class Archive>
|
|
void serialize(Archive & ar, const unsigned int version)
|
|
{
|
|
ar & BOOST_SERIALIZATION_NVP(r1_);
|
|
ar & BOOST_SERIALIZATION_NVP(r2_);
|
|
ar & BOOST_SERIALIZATION_NVP(r3_);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Rodriguez' formula to compute an incremental rotation matrix
|
|
* @param w is the rotation axis, unit length
|
|
* @param theta rotation angle
|
|
* @return incremental rotation matrix
|
|
*/
|
|
Rot3 rodriguez(const Vector& w, double theta);
|
|
|
|
/**
|
|
* Rodriguez' formula to compute an incremental rotation matrix
|
|
* @param wx
|
|
* @param wy
|
|
* @param wz
|
|
* @return incremental rotation matrix
|
|
*/
|
|
Rot3 rodriguez(double wx, double wy, double wz);
|
|
|
|
/**
|
|
* Rodriguez' formula to compute an incremental rotation matrix
|
|
* @param v a vector of incremental roll,pitch,yaw
|
|
* @return incremental rotation matrix
|
|
*/
|
|
Rot3 rodriguez(const Vector& v);
|
|
|
|
/**
|
|
* Update Rotation with incremental rotation
|
|
* @param v a vector of incremental roll,pitch,yaw
|
|
* @param R a rotated frame
|
|
* @return incremental rotation matrix
|
|
*/
|
|
Rot3 exmap(const Rot3& R, const Vector& v);
|
|
|
|
/**
|
|
* rotate point from rotated coordinate frame to
|
|
* world = R*p
|
|
*/
|
|
Point3 rotate(const Rot3& R, const Point3& p);
|
|
Matrix Drotate1(const Rot3& R, const Point3& p);
|
|
Matrix Drotate2(const Rot3& R); // does not depend on p !
|
|
|
|
/**
|
|
* rotate point from world to rotated
|
|
* frame = R'*p
|
|
*/
|
|
Point3 unrotate(const Rot3& R, const Point3& p);
|
|
Matrix Dunrotate1(const Rot3& R, const Point3& p);
|
|
Matrix Dunrotate2(const Rot3& R); // does not depend on p !
|
|
|
|
/** receives a rotation 3 by 3 matrix and returns 3 rotation angles.*/
|
|
Vector RQ(Matrix R);
|
|
|
|
}
|