41 # define M_PI 3.14159265358979323846 43 #define NEAR_ZERO 1e-10 130 template <
class Precision=
double>
138 SO3_(
const Precision& X,
const Precision& Y,
const Precision& Z,
const Precision& W)
139 :x(X),y(Y),z(Z),w(W) { }
144 FromAxis(direction,angle);
159 template<
typename Scalar>
166 const Precision squared_w = w*w;
167 const Precision n = sqrt(x*x+y*y+z*z);
180 A_inv = 2./w - 2.*(1.0-squared_w)/(w*squared_w);
184 if (fabs(w)<NEAR_ZERO)
197 A_inv = 2*atan(n/w)/n;
203 template<
typename Scalar>
206 const Scalar theta_sq=r.x*r.x+r.y*r.y+r.z*r.z;
207 const Scalar theta = sqrt(theta_sq);
208 const Scalar half_theta = 0.5*theta;
210 const Scalar W = cos(half_theta);
211 Scalar sin_half_theta;
214 Scalar theta_po4 = theta_sq*theta_sq;
215 sin_half_theta = 0.5-0.0208333*theta_sq+0.000260417*theta_po4;
219 sin_half_theta = sin(half_theta);
220 sin_half_theta = sin_half_theta/theta;
225 sin_half_theta*r.z,W);
228 template <
typename T>
229 static inline T sine(T x) {
232 while (x < -3.14159265)
234 while (x > 3.14159265)
238 sin = 1.27323954 * x + .405284735 * x * x;
240 sin = .225 * (sin * -sin - sin) + sin;
242 sin = .225 * (sin * sin - sin) + sin;
244 sin = 1.27323954 * x - 0.405284735 * x * x;
246 sin = .225 * (sin * -sin - sin) + sin;
248 sin = .225 * (sin * sin - sin) + sin;
253 template <
typename T>
254 static inline T cosine(T x) {
256 return sine(x+1.57079632);
259 template<
typename Scalar>
262 Scalar theta_sq = l.dot(l);
263 Scalar theta = sqrt(theta_sq);
264 Scalar half_theta =
static_cast<Scalar
>(0.5) * theta;
269 if (theta < static_cast<Scalar>(1e-10)) {
270 Scalar theta_po4 = theta_sq * theta_sq;
271 imag_factor =
static_cast<Scalar
>(0.5) -
272 static_cast<Scalar
>(1.0 / 48.0) * theta_sq +
273 static_cast<Scalar
>(1.0 / 3840.0) * theta_po4;
274 real_factor =
static_cast<Scalar
>(1) -
275 static_cast<Scalar>(0.5) * theta_sq +
276 static_cast<Scalar
>(1.0 / 384.0) * theta_po4;
278 Scalar sin_half_theta = sine(half_theta);
279 imag_factor = sin_half_theta / theta;
280 real_factor = cosine(half_theta);
283 return SO3_<Scalar>( imag_factor * l.x, imag_factor * l.y,
284 imag_factor * l.z,real_factor);
303 auto SIGN=[](
const Precision& v){
return v>0?1.:-1.;};
308 const Precision &r11=m[0],&r12=m[1],&r13=m[2],
309 &r21=m[3],&r22=m[4],&r23=m[5],
310 &r31=m[6],&r32=m[7],&r33=m[8];
311 q0 = ( r11 + r22 + r33 + 1.0f) / 4.0f;
312 q1 = ( r11 - r22 - r33 + 1.0f) / 4.0f;
313 q2 = (-r11 + r22 - r33 + 1.0f) / 4.0f;
314 q3 = (-r11 - r22 + r33 + 1.0f) / 4.0f;
315 if(q0 < 0.0f) q0 = 0.0f;
316 if(q1 < 0.0f) q1 = 0.0f;
317 if(q2 < 0.0f) q2 = 0.0f;
318 if(q3 < 0.0f) q3 = 0.0f;
323 if(q0 >= q1 && q0 >= q2 && q0 >= q3) {
325 q1 *= SIGN(r32 - r23);
326 q2 *= SIGN(r13 - r31);
327 q3 *= SIGN(r21 - r12);
328 }
else if(q1 >= q0 && q1 >= q2 && q1 >= q3) {
329 q0 *= SIGN(r32 - r23);
331 q2 *= SIGN(r21 + r12);
332 q3 *= SIGN(r13 + r31);
333 }
else if(q2 >= q0 && q2 >= q1 && q2 >= q3) {
334 q0 *= SIGN(r13 - r31);
335 q1 *= SIGN(r21 + r12);
337 q3 *= SIGN(r32 + r23);
338 }
else if(q3 >= q0 && q3 >= q1 && q3 >= q2) {
339 q0 *= SIGN(r21 - r12);
340 q1 *= SIGN(r31 + r13);
341 q2 *= SIGN(r32 + r23);
344 std::cerr<<
"Unable to construct SO3 from this Matrix.";
346 Precision r = sqrt(q0*q0+q1*q1+q2*q2+q3*q3);
362 Precision x2 = x * x;
363 Precision y2 = y * y;
364 Precision z2 = z * z;
365 Precision xy = x * y;
366 Precision xz = x * z;
367 Precision yz = y * z;
368 Precision wx = w * x;
369 Precision wy = w * y;
370 Precision wz = w * z;
371 m[0]=1.0-2.0*(y2+z2); m[1]=2.0 * ( xy- wz); m[2]= 2.0 * (xz + wy);
372 m[3]=2.0 * (xy + wz); m[4]=1.0-2.0*(x2+z2); m[5]= 2.0 * (yz - wx);
373 m[6]=2.0 * (xz - wy); m[7]=2.0 * ( yz+ wx); m[8]= 1.0-2.0*(x2+y2);
378 SO3_(
const TooN::Matrix<3,3,Precision>& m)
383 bool fromMatrix(
const TooN::Matrix<3,3,Precision>& m)
385 w=0.5*sqrt(m[0][0]+m[1][1]+m[2][2]+1);
386 Precision oneover4w=0.25/w;
387 x=(m[2][1]-m[1][2])*oneover4w;
388 y=(m[0][2]-m[2][0])*oneover4w;
389 z=(m[1][0]-m[0][1])*oneover4w;
390 if(w<0){x*=-1;y*=-1;z*=-1;w*=-1;}
395 TooN::Matrix<3,3,Precision> getMatrixTooN()
const 397 Precision x2 = x * x;
398 Precision y2 = y * y;
399 Precision z2 = z * z;
400 Precision xy = x * y;
401 Precision xz = x * z;
402 Precision yz = y * z;
403 Precision wx = w * x;
404 Precision wy = w * y;
405 Precision wz = w * z;
406 return TooN::Data(1.0-2.0*(y2+z2), 2.0 * ( xy- wz), 2.0 * (xz + wy),
407 2.0 * (xy + wz), 1.0-2.0*(x2+z2), 2.0 * (yz - wx),
408 2.0 * (xz - wy), 2.0 * ( yz+ wx), 1.0-2.0*(x2+y2));
411 operator TooN::SO3<Precision>()
413 return getMatrixTooN();
418 #ifdef SOPHUS_SO3_HPP 419 SO3_(
const Sophus::SO3Group<Precision>& so3)
420 : x(so3.unit_quaternion().coeffs()[0]),
421 y(so3.unit_quaternion().coeffs()[1]),
422 z(so3.unit_quaternion().coeffs()[2]),
423 w(so3.unit_quaternion().coeffs()[3])
426 operator Sophus::SO3Group<Precision>()
428 return Sophus::SO3Group<Precision>(Eigen::Quaternion<Precision>(w,x,y,z));
432 static SO3_ fromPitchYawRollAngle(
const Precision& pitch,
const Precision& yaw,
const Precision& roll)
434 Precision a2r=(3.1415926/180.0);
435 return fromPitchYawRoll(pitch*a2r,yaw*a2r,roll*a2r);
439 return fromPitchYawRoll(pyr.x,pyr.y,pyr.z);
449 Precision piover360=0.5;
450 Precision p = pitch * piover360;
451 Precision y = yaw * piover360;
452 Precision r = roll * piover360;
455 Precision sinp = sin(p);
456 Precision siny = sin(y);
457 Precision sinr = sin(r);
458 Precision cosp = cos(p);
459 Precision cosy = cos(y);
460 Precision cosr = cos(r);
463 Precision rx = sinr * cosp * cosy - cosr * sinp * siny;
464 Precision ry = cosr * sinp * cosy + sinr * cosp * siny;
465 Precision rz = cosr * cosp * siny - sinr * sinp * cosy;
466 Precision rw = cosr * cosp * cosy + sinr * sinp * siny;
468 SO3_ ret(rx,ry,rz,rw);
473 Precision getRoll()
const 475 return atan2(2.0*(w*x+y*z),1.0-2.0*(x*x+y*y));
478 Precision getPitch()
const 480 return asin(2.0*(w*y-z*x));
483 Precision getYaw()
const 485 return atan2(2.0*(w*z+x*y),1.0-2.0*(z*z+y*y));
489 SO3_ operator* (
const SO3_& rq)
const 492 return SO3_( w * rq.x + x * rq.w + y * rq.z - z * rq.y,
493 w * rq.y + y * rq.w + z * rq.x - x * rq.z,
494 w * rq.z + z * rq.w + x * rq.y - y * rq.x,
495 w * rq.w - x * rq.x - y * rq.y - z * rq.z);
511 bool operator ==(
const SO3_& rq)
const{
512 return ((*this).log()-rq.
log()).norm()<1e-6;
518 Precision det=sqrt(p.x*p.x+p.y*p.y+p.z*p.z);
524 Precision p2v=sin(angle)/det;
525 return SO3_(p.x*p2v,p.y*p2v,p.z*p2v,cos(angle));
531 Precision mag2 = w * w + x * x + y * y + z * z;
532 if ( mag2!=0.f && (fabs(mag2 - 1.0f) > 0.001))
534 Precision mag = 1./sqrt(mag2);
546 return SO3_(-x, -y, -z, w);
549 void getValue(Precision& X,Precision& Y,Precision& Z,Precision& W)
const 554 operator std::string()
const 556 std::stringstream sst;sst<<*
this;
return sst.str();
559 Precision getX()
const{
return x;}
560 Precision getY()
const{
return y;}
561 Precision getZ()
const{
return z;}
562 Precision getW()
const{
return w;}
564 void setX(Precision X){x=X;}
565 void setY(Precision Y){y=Y;}
566 void setZ(Precision Z){z=Z;}
567 void setW(Precision W){w=W;}
568 SO3_ mul (
const SO3_& rq)
const{
return (*
this)*rq;}
571 std::string toString()
const{std::stringstream sst;sst<<*
this;
return sst.str();}
583 template <
typename Precision>
584 inline std::ostream& operator << (std::ostream& os,const SO3_<Precision>& so3)
591 so3.getValue(X,Y,Z,W);
592 os<<X<<
" "<<Y<<
" "<<Z<<
" "<<W;
599 template <
typename Precision>
600 inline std::istream& operator >> (std::istream& is,
SO3_<Precision>& so3)
602 is>>so3.x>>so3.y>>so3.z>>so3.w;
609 #endif // GSLAM_CORE_SO3_H SO3_(const Matrix< Precision, 3, 3 > &M)
Construct from a rotation matrix.
Definition: SO3.h:154
SO3_(const Point3_< Precision > &direction, Precision angle)
Construct from a direction and angle in radius.
Definition: SO3.h:142
3D rotation represented by the quaternion.
Definition: SO3.h:131
SO3_()
Default constructor, Idendity Matrix.
Definition: SO3.h:135
void fromMatrix(const Precision *m)
This is an unsafe operation. Please make sure that your pointer is both valid and has an appropriate ...
Definition: SO3.h:301
static SO3_ fromPitchYawRoll(const Precision &pitch, const Precision &yaw, const Precision &roll)
Convert from Euler Angles, Please use "Radian" rather than degree to present angle.
Definition: SO3.h:444
Point3_< Precision > log() const
Definition: SO3.h:164
SO3_(const Precision &X, const Precision &Y, const Precision &Z, const Precision &W)
Construct from Quaternion.
Definition: SO3.h:138
static SO3_< Precision > exp(const Point3_< Scalar > &r)
Construct from lie algebra representation.
Definition: SO3.h:204
void getMatrix(Precision *m) const
return the matrix M
Definition: SO3.h:360
SO3_(const SO3_< Scalar > &r)
Construct from another precision.
Definition: SO3.h:160
SO3_(const Precision *M)
Construct from a rotation matrix data (ColMajor).
Definition: SO3.h:148