00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #ifndef TOON_INCLUDE_SO3_H
00031 #define TOON_INCLUDE_SO3_H
00032
00033 #include <TooN/TooN.h>
00034 #include <TooN/helpers.h>
00035 #include <cassert>
00036
00037 namespace TooN {
00038
00039 template <typename Precision> class SO3;
00040 template <typename Precision> class SE3;
00041
00042 template<class Precision> inline std::istream & operator>>(std::istream &, SO3<Precision> & );
00043 template<class Precision> inline std::istream & operator>>(std::istream &, SE3<Precision> & );
00044
00052 template <typename Precision = double>
00053 class SO3 {
00054 public:
00055 friend std::istream& operator>> <Precision> (std::istream& is, SO3<Precision> & rhs);
00056 friend std::istream& operator>> <Precision> (std::istream& is, SE3<Precision> & rhs);
00057 friend class SE3<Precision>;
00058
00060 SO3() : my_matrix(Identity) {}
00061
00063 template <int S, typename P, typename A>
00064 SO3(const Vector<S, P, A> & v) { *this = exp(v); }
00065
00067 template <int R, int C, typename P, typename A>
00068 SO3(const Matrix<R,C,P,A>& rhs) { *this = rhs; }
00069
00075 template <int S1, int S2, typename P1, typename P2, typename A1, typename A2>
00076 SO3(const Vector<S1, P1, A1> & a, const Vector<S2, P2, A2> & b ){
00077 SizeMismatch<3,S1>::test(3, a.size());
00078 SizeMismatch<3,S2>::test(3, b.size());
00079 Vector<3, Precision> n = a ^ b;
00080 if(norm_sq(n) == 0) {
00081
00082
00083 assert(a*b>=0);
00084 my_matrix = Identity;
00085 return;
00086 }
00087 n = unit(n);
00088 Matrix<3> R1;
00089 R1.T()[0] = unit(a);
00090 R1.T()[1] = n;
00091 R1.T()[2] = n ^ R1.T()[0];
00092 my_matrix.T()[0] = unit(b);
00093 my_matrix.T()[1] = n;
00094 my_matrix.T()[2] = n ^ my_matrix.T()[0];
00095 my_matrix = my_matrix * R1.T();
00096 }
00097
00100 template <int R, int C, typename P, typename A>
00101 SO3& operator=(const Matrix<R,C,P,A> & rhs) {
00102 my_matrix = rhs;
00103 coerce();
00104 return *this;
00105 }
00106
00108 void coerce() {
00109 my_matrix[0] = unit(my_matrix[0]);
00110 my_matrix[1] -= my_matrix[0] * (my_matrix[0]*my_matrix[1]);
00111 my_matrix[1] = unit(my_matrix[1]);
00112 my_matrix[2] -= my_matrix[0] * (my_matrix[0]*my_matrix[2]);
00113 my_matrix[2] -= my_matrix[1] * (my_matrix[1]*my_matrix[2]);
00114 my_matrix[2] = unit(my_matrix[2]);
00115
00116 assert( (my_matrix[0] ^ my_matrix[1]) * my_matrix[2] > 0 );
00117 }
00118
00121 template<int S, typename VP, typename A> inline static SO3 exp(const Vector<S,VP,A>& vect);
00122
00125 inline Vector<3, Precision> ln() const;
00126
00128 SO3 inverse() const { return SO3(*this, Invert()); }
00129
00131 SO3& operator *=(const SO3& rhs) {
00132 *this = *this * rhs;
00133 return *this;
00134 }
00135
00137 SO3 operator *(const SO3& rhs) const { return SO3(*this,rhs); }
00138
00140 const Matrix<3,3, Precision> & get_matrix() const {return my_matrix;}
00141
00146 inline static Matrix<3,3, Precision> generator(int i){
00147 Matrix<3,3,Precision> result(Zeros);
00148 result[(i+1)%3][(i+2)%3] = -1;
00149 result[(i+2)%3][(i+1)%3] = 1;
00150 return result;
00151 }
00152
00154 template<typename Base>
00155 inline static Vector<3,Precision> generator_field(int i, const Vector<3, Precision, Base>& pos)
00156 {
00157 Vector<3, Precision> result;
00158 result[i]=0;
00159 result[(i+1)%3] = - pos[(i+2)%3];
00160 result[(i+2)%3] = pos[(i+1)%3];
00161 return result;
00162 }
00163
00168 template <int S, typename A>
00169 inline Vector<3, Precision> adjoint(const Vector<S, Precision, A>& vect) const
00170 {
00171 SizeMismatch<3, S>::test(3, vect.size());
00172 return *this * vect;
00173 }
00174
00175 private:
00176 struct Invert {};
00177 inline SO3(const SO3& so3, const Invert&) : my_matrix(so3.my_matrix.T()) {}
00178 inline SO3(const SO3& a, const SO3& b) : my_matrix(a.my_matrix*b.my_matrix) {}
00179
00180 Matrix<3,3, Precision> my_matrix;
00181 };
00182
00185 template <typename Precision>
00186 inline std::ostream& operator<< (std::ostream& os, const SO3<Precision>& rhs){
00187 return os << rhs.get_matrix();
00188 }
00189
00192 template <typename Precision>
00193 inline std::istream& operator>>(std::istream& is, SO3<Precision>& rhs){
00194 return is >> rhs.my_matrix;
00195 rhs.coerce();
00196 }
00197
00209 template <typename Precision, typename VP, typename VA, typename MA>
00210 inline void rodrigues_so3_exp(const Vector<3,VP, VA>& w, const Precision A, const Precision B, Matrix<3,3,Precision,MA>& R){
00211 {
00212 const Precision wx2 = (Precision)w[0]*w[0];
00213 const Precision wy2 = (Precision)w[1]*w[1];
00214 const Precision wz2 = (Precision)w[2]*w[2];
00215
00216 R[0][0] = 1.0 - B*(wy2 + wz2);
00217 R[1][1] = 1.0 - B*(wx2 + wz2);
00218 R[2][2] = 1.0 - B*(wx2 + wy2);
00219 }
00220 {
00221 const Precision a = A*w[2];
00222 const Precision b = B*(w[0]*w[1]);
00223 R[0][1] = b - a;
00224 R[1][0] = b + a;
00225 }
00226 {
00227 const Precision a = A*w[1];
00228 const Precision b = B*(w[0]*w[2]);
00229 R[0][2] = b + a;
00230 R[2][0] = b - a;
00231 }
00232 {
00233 const Precision a = A*w[0];
00234 const Precision b = B*(w[1]*w[2]);
00235 R[1][2] = b - a;
00236 R[2][1] = b + a;
00237 }
00238 }
00239
00242 template <typename Precision>
00243 template<int S, typename VP, typename VA>
00244 inline SO3<Precision> SO3<Precision>::exp(const Vector<S,VP,VA>& w){
00245 using std::sqrt;
00246 using std::sin;
00247 using std::cos;
00248 SizeMismatch<3,S>::test(3, w.size());
00249
00250 static const Precision one_6th = 1.0/6.0;
00251 static const Precision one_20th = 1.0/20.0;
00252
00253 SO3<Precision> result;
00254
00255 const Precision theta_sq = w*w;
00256 const Precision theta = sqrt(theta_sq);
00257 Precision A, B;
00258
00259
00260 if (theta_sq < 1e-8) {
00261 A = 1.0 - one_6th * theta_sq;
00262 B = 0.5;
00263 } else {
00264 if (theta_sq < 1e-6) {
00265 B = 0.5 - 0.25 * one_6th * theta_sq;
00266 A = 1.0 - theta_sq * one_6th*(1.0 - one_20th * theta_sq);
00267 } else {
00268 const Precision inv_theta = 1.0/theta;
00269 A = sin(theta) * inv_theta;
00270 B = (1 - cos(theta)) * (inv_theta * inv_theta);
00271 }
00272 }
00273 rodrigues_so3_exp(w, A, B, result.my_matrix);
00274 return result;
00275 }
00276
00277 template <typename Precision>
00278 inline Vector<3, Precision> SO3<Precision>::ln() const{
00279 Vector<3, Precision> result;
00280
00281 const Precision cos_angle = (my_matrix[0][0] + my_matrix[1][1] + my_matrix[2][2] - 1.0) * 0.5;
00282 result[0] = (my_matrix[2][1]-my_matrix[1][2])/2;
00283 result[1] = (my_matrix[0][2]-my_matrix[2][0])/2;
00284 result[2] = (my_matrix[1][0]-my_matrix[0][1])/2;
00285
00286 Precision sin_angle_abs = sqrt(result*result);
00287 if (cos_angle > M_SQRT1_2) {
00288 if(sin_angle_abs > 0){
00289 result *= asin(sin_angle_abs) / sin_angle_abs;
00290 }
00291 } else if( cos_angle > -M_SQRT1_2) {
00292 double angle = acos(cos_angle);
00293 result *= angle / sin_angle_abs;
00294 } else {
00295
00296 const Precision angle = M_PI - asin(sin_angle_abs);
00297 const Precision d0 = my_matrix[0][0] - cos_angle,
00298 d1 = my_matrix[1][1] - cos_angle,
00299 d2 = my_matrix[2][2] - cos_angle;
00300 TooN::Vector<3> r2;
00301 if(fabs(d0) > fabs(d1) && fabs(d0) > fabs(d2)){
00302 r2[0] = d0;
00303 r2[1] = (my_matrix[1][0]+my_matrix[0][1])/2;
00304 r2[2] = (my_matrix[0][2]+my_matrix[2][0])/2;
00305 } else if(fabs(d1) > fabs(d2)) {
00306 r2[0] = (my_matrix[1][0]+my_matrix[0][1])/2;
00307 r2[1] = d1;
00308 r2[2] = (my_matrix[2][1]+my_matrix[1][2])/2;
00309 } else {
00310 r2[0] = (my_matrix[0][2]+my_matrix[2][0])/2;
00311 r2[1] = (my_matrix[2][1]+my_matrix[1][2])/2;
00312 r2[2] = d2;
00313 }
00314
00315 if(r2 * result < 0)
00316 r2 *= -1;
00317 r2 = unit(r2);
00318 result = angle * r2;
00319 }
00320 return result;
00321 }
00322
00325 template<int S, typename P, typename PV, typename A> inline
00326 Vector<3, typename Internal::MultiplyType<P, PV>::type> operator*(const SO3<P>& lhs, const Vector<S, PV, A>& rhs){
00327 return lhs.get_matrix() * rhs;
00328 }
00329
00332 template<int S, typename P, typename PV, typename A> inline
00333 Vector<3, typename Internal::MultiplyType<PV, P>::type> operator*(const Vector<S, PV, A>& lhs, const SO3<P>& rhs){
00334 return lhs * rhs.get_matrix();
00335 }
00336
00339 template<int R, int C, typename P, typename PM, typename A> inline
00340 Matrix<3, C, typename Internal::MultiplyType<P, PM>::type> operator*(const SO3<P>& lhs, const Matrix<R, C, PM, A>& rhs){
00341 return lhs.get_matrix() * rhs;
00342 }
00343
00346 template<int R, int C, typename P, typename PM, typename A> inline
00347 Matrix<R, 3, typename Internal::MultiplyType<PM, P>::type> operator*(const Matrix<R, C, PM, A>& lhs, const SO3<P>& rhs){
00348 return lhs * rhs.get_matrix();
00349 }
00350
00351 #if 0 // will be moved to another header file ?
00352
00353 template <class A> inline
00354 Vector<3> transform(const SO3& pose, const FixedVector<3,A>& x) { return pose*x; }
00355
00356 template <class A1, class A2> inline
00357 Vector<3> transform(const SO3& pose, const FixedVector<3,A1>& x, FixedMatrix<3,3,A2>& J_x)
00358 {
00359 J_x = pose.get_matrix();
00360 return pose * x;
00361 }
00362
00363 template <class A1, class A2, class A3> inline
00364 Vector<3> transform(const SO3& pose, const FixedVector<3,A1>& x, FixedMatrix<3,3,A2>& J_x, FixedMatrix<3,3,A3>& J_pose)
00365 {
00366 J_x = pose.get_matrix();
00367 const Vector<3> cx = pose * x;
00368 J_pose[0][0] = J_pose[1][1] = J_pose[2][2] = 0;
00369 J_pose[1][0] = -(J_pose[0][1] = cx[2]);
00370 J_pose[0][2] = -(J_pose[2][0] = cx[1]);
00371 J_pose[2][1] = -(J_pose[1][2] = cx[0]);
00372 return cx;
00373 }
00374
00375 template <class A1, class A2, class A3> inline
00376 Vector<2> project_transformed_point(const SO3& pose, const FixedVector<3,A1>& in_frame, FixedMatrix<2,3,A2>& J_x, FixedMatrix<2,3,A3>& J_pose)
00377 {
00378 const double z_inv = 1.0/in_frame[2];
00379 const double x_z_inv = in_frame[0]*z_inv;
00380 const double y_z_inv = in_frame[1]*z_inv;
00381 const double cross = x_z_inv * y_z_inv;
00382 J_pose[0][0] = -cross;
00383 J_pose[0][1] = 1 + x_z_inv*x_z_inv;
00384 J_pose[0][2] = -y_z_inv;
00385 J_pose[1][0] = -1 - y_z_inv*y_z_inv;
00386 J_pose[1][1] = cross;
00387 J_pose[1][2] = x_z_inv;
00388
00389 const TooN::Matrix<3>& R = pose.get_matrix();
00390 J_x[0][0] = z_inv*(R[0][0] - x_z_inv * R[2][0]);
00391 J_x[0][1] = z_inv*(R[0][1] - x_z_inv * R[2][1]);
00392 J_x[0][2] = z_inv*(R[0][2] - x_z_inv * R[2][2]);
00393 J_x[1][0] = z_inv*(R[1][0] - y_z_inv * R[2][0]);
00394 J_x[1][1] = z_inv*(R[1][1] - y_z_inv * R[2][1]);
00395 J_x[1][2] = z_inv*(R[1][2] - y_z_inv * R[2][2]);
00396
00397 return makeVector(x_z_inv, y_z_inv);
00398 }
00399
00400
00401 template <class A1> inline
00402 Vector<2> transform_and_project(const SO3& pose, const FixedVector<3,A1>& x)
00403 {
00404 return project(transform(pose,x));
00405 }
00406
00407 template <class A1, class A2, class A3> inline
00408 Vector<2> transform_and_project(const SO3& pose, const FixedVector<3,A1>& x, FixedMatrix<2,3,A2>& J_x, FixedMatrix<2,3,A3>& J_pose)
00409 {
00410 return project_transformed_point(pose, transform(pose,x), J_x, J_pose);
00411 }
00412
00413 #endif
00414
00415 }
00416
00417 #endif