00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifndef __SE3QUAT_H__
00018 #define __SE3QUAT_H__
00019
00020 #include "g2o/stuff/misc.h"
00021 #include "g2o/stuff/macros.h"
00022 #include <Eigen/Core>
00023 #include <Eigen/Geometry>
00024 #include "se3_ops.h"
00025
00026 namespace g2o {
00027 using namespace Eigen;
00028
00029 typedef Matrix<double, 6, 1> Vector6d;
00030 typedef Matrix<double, 7, 1> Vector7d;
00031
00032 class SE3Quat {
00033 public:
00034 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
00035
00036
00037 protected:
00038
00039 Quaterniond _r;
00040 Vector3d _t;
00041
00042
00043 public:
00044 SE3Quat(){
00045 _r.setIdentity();
00046 _t.setZero();
00047 }
00048
00049 SE3Quat(const Matrix3d& R, const Vector3d t):_r(Quaterniond(R)),_t(t){}
00050 SE3Quat(const Quaterniond& q, const Vector3d t):_r(q),_t(t){}
00051
00055 template <typename Derived>
00056 explicit SE3Quat(const MatrixBase<Derived>& v)
00057 {
00058 assert(v.size() == 6);
00059 for (int i=0; i<3; i++){
00060 _t[i]=v[i];
00061 _r.coeffs()(i)=v[i+3];
00062 }
00063 _r.w() = 0.;
00064 if (_r.norm()>1.){
00065 _r.normalize();
00066 } else
00067 _r.w()=sqrt(1.-_r.squaredNorm());
00068 }
00069
00070 inline const Vector3d& translation() const {return _t;}
00071
00072 inline Vector3d& translation() {return _t;}
00073
00074 inline const Quaterniond& rotation() const {return _r;}
00075
00076 inline Quaterniond& rotation() {return _r;}
00077
00078 inline SE3Quat operator * (const SE3Quat& tr2) const{
00079 SE3Quat result(*this);
00080 result._t += _r*tr2._t;
00081 result._r*=tr2._r;
00082 result._r.normalize();
00083 return result;
00084 }
00085
00086 inline SE3Quat& operator *= (const SE3Quat& tr2){
00087 _t+=_r*tr2._t;
00088 _r*=tr2._r;
00089 _r.normalize();
00090 return *this;
00091 }
00092
00093 inline Vector3d operator * (const Vector3d v) const {
00094 return _t+_r*v;
00095 }
00096
00097 inline SE3Quat inverse() const{
00098 SE3Quat ret;
00099 ret._r=_r.conjugate();
00100 ret._t=ret._r*(_t*-1.);
00101 return ret;
00102 }
00103
00104 inline double operator [](int i) const {
00105 assert(i<7);
00106 if (i<3)
00107 return _t[i];
00108 return _r.coeffs()[i-3];
00109 }
00110
00111 inline double& operator [](int i) {
00112 assert(i<7);
00113 if (i<3)
00114 return _t[i];
00115 return _r.coeffs()[i-3];
00116 }
00117
00118
00119 inline Vector7d toVector() const{
00120 Vector7d v;
00121 v[0]=_t(0);
00122 v[1]=_t(1);
00123 v[2]=_t(2);
00124 v[3]=_r.x();
00125 v[4]=_r.y();
00126 v[5]=_r.z();
00127 v[6]=_r.w();
00128 return v;
00129 }
00130
00131 inline void fromVector(const Vector7d& v){
00132 _r=Quaterniond(v[3], v[4], v[5], v[6]);
00133 _t=Vector3d(v[0], v[1], v[2]);
00134 }
00135
00136 inline Vector6d toMinimalVector() const{
00137 Vector6d v;
00138 v[0]=_t(0);
00139 v[1]=_t(1);
00140 v[2]=_t(2);
00141 v[3]=_r.x();
00142 v[4]=_r.y();
00143 v[5]=_r.z();
00144 return v;
00145 }
00146
00147 inline void fromMinimalVector(const Vector6d& v){
00148 double w = 1.-v[3]*v[3]-v[4]*v[4]-v[5]*v[5];
00149 if (w>0){
00150 _r=Quaterniond(v[3], v[4], v[5], w);
00151 } else {
00152 _r=Quaterniond(-v[3], -v[4], -v[5], -w);
00153 }
00154 _t=Vector3d(v[0], v[1], v[2]);
00155 }
00156
00157
00158
00159 Vector6d log() const {
00160 Vector6d res;
00161 Matrix3d _R = _r.toRotationMatrix();
00162 double d = 0.5*(_R(0,0)+_R(1,1)+_R(2,2)-1);
00163 Vector3d omega;
00164 Vector3d upsilon;
00165
00166
00167 Vector3d dR = deltaR(_R);
00168 Matrix3d V_inv;
00169
00170 if (d>0.99999)
00171 {
00172
00173 omega=0.5*dR;
00174 Matrix3d Omega = skew(omega);
00175 V_inv = Matrix3d::Identity()- 0.5*Omega + (1./12.)*(Omega*Omega);
00176 }
00177 else
00178 {
00179 double theta = acos(d);
00180 omega = theta/(2*sqrt(1-d*d))*dR;
00181 Matrix3d Omega = skew(omega);
00182 V_inv = ( Matrix3d::Identity() - 0.5*Omega
00183 + ( 1-theta/(2*tan(theta/2)))/(theta*theta)*(Omega*Omega) );
00184 }
00185
00186 upsilon = V_inv*_t;
00187 for (int i=0; i<3;i++){
00188 res[i]=omega[i];
00189 }
00190 for (int i=0; i<3;i++){
00191 res[i+3]=upsilon[i];
00192 }
00193
00194 return res;
00195
00196 }
00197
00198 Vector3d map(const Vector3d & xyz) const
00199 {
00200 return _r*xyz + _t;
00201 }
00202
00203
00204 static SE3Quat exp(const Vector6d & update)
00205
00206 {
00207
00208 Vector3d omega;
00209 for (int i=0; i<3; i++)
00210 omega[i]=update[i];
00211 Vector3d upsilon;
00212 for (int i=0; i<3; i++)
00213 upsilon[i]=update[i+3];
00214
00215 double theta = omega.norm();
00216 Matrix3d Omega = skew(omega);
00217
00218 Matrix3d R;
00219 Matrix3d V;
00220 if (theta<0.00001)
00221 {
00222
00223 R = (Matrix3d::Identity() + Omega + Omega*Omega);
00224
00225 V = R;
00226 }
00227 else
00228 {
00229 Matrix3d Omega2 = Omega*Omega;
00230
00231 R = (Matrix3d::Identity()
00232 + sin(theta)/theta *Omega
00233 + (1-cos(theta))/(theta*theta)*Omega2);
00234
00235 V = (Matrix3d::Identity()
00236 + (1-cos(theta))/(theta*theta)*Omega
00237 + (theta-sin(theta))/(pow(theta,3))*Omega2);
00238 }
00239 return SE3Quat(Quaterniond(R),V*upsilon);
00240 }
00241
00242 Matrix<double, 6, 6> adj() const
00243 {
00244 Matrix3d R = _r.toRotationMatrix();
00245 Matrix<double, 6, 6> res;
00246 res.block(0,0,3,3) = R;
00247 res.block(3,3,3,3) = R;
00248 res.block(3,0,3,3) = skew(_t)*R;
00249 res.block(0,3,3,3) = Matrix3d::Zero(3,3);
00250 return res;
00251 }
00252
00253 Matrix<double,4,4> to_homogenious_matrix() const
00254 {
00255 Matrix<double,4,4> homogenious_matrix;
00256 homogenious_matrix.setIdentity();
00257 homogenious_matrix.block(0,0,3,3) = _r.toRotationMatrix();
00258 homogenious_matrix.col(3).head(3) = translation();
00259
00260 return homogenious_matrix;
00261 }
00262 };
00263
00264
00265
00266 inline std::ostream& operator <<(std::ostream& out_str,
00267 const SE3Quat& se3)
00268 {
00269 out_str << se3.to_homogenious_matrix() << std::endl;
00270 return out_str;
00271 }
00272
00273 }
00274
00275 #endif