@@ -26,53 +26,43 @@ ith_partial{N}(X::SMatrix{9,N}, i) = @SMatrix([X[1,i] X[4,i] X[7,i];
2626 jacobian(::Type{output_param}, R::input_param)
2727Returns the jacobian for transforming from the input rotation parameterization
2828to the output parameterization, centered at the value of R.
29+ Note that
30+ * if `input_param <: QuatRotation`, a unit quaternion is assumed and
31+ the jacobian is with respect to the four parameters of a unit quaternion.
32+ * if `input_param <: Quaternion`, a general (with arbitrary norm)
33+ quaternion is assumed and the jacobian is with respect to a general quaternion
2934
3035 jacobian(R::rotation_type, X::AbstractVector)
3136Returns the jacobian for rotating the vector X by R.
3237"""
33- function jacobian (:: Type{RotMatrix} , q:: QuatRotation )
34- w = real (q. q)
35- x, y, z = imag_part (q. q)
36-
37- # let q = s * qhat where qhat is a unit quaternion and s is a scalar,
38- # then R = RotMatrix(q) = RotMatrix(s * qhat) = s * RotMatrix(qhat)
39-
40- # get R(q)
41- # R = q[:] # FIXME : broken with StaticArrays 0.4.0 due to https://github.com/JuliaArrays/StaticArrays.jl/issues/128
42- R = SVector (Tuple (q))
43-
44- # solve d(s*R)/dQ (because its easy)
45- dsRdQ = @SMatrix [ 2 * w 2 * x - 2 * y - 2 * z ;
46- 2 * z 2 * y 2 * x 2 * w ;
47- - 2 * y 2 * z - 2 * w 2 * x ;
48-
49- - 2 * z 2 * y 2 * x - 2 * w ;
50- 2 * w - 2 * x 2 * y - 2 * z ;
51- 2 * x 2 * w 2 * z 2 * y ;
52-
53- 2 * y 2 * z 2 * w 2 * x ;
54- - 2 * x - 2 * w 2 * z 2 * y ;
55- 2 * w - 2 * x - 2 * y 2 * z ]
56-
57- # get s and dsdQ
58- # s = 1
59- dsdQ = @SVector [2 * w, 2 * x, 2 * y, 2 * z]
60-
61- # now R(q) = (s*R) / s
62- # so dR/dQ = (s * d(s*R)/dQ - (s*R) * ds/dQ) / s^2
63- # = (d(s*R)/dQ - R*ds/dQ) / s
38+ function jacobian (:: Type{RotMatrix} , q:: Quaternion )
39+ s = abs (q)
40+ w = real (q)
41+ x, y, z = imag_part (q)
42+ qhat = SVector {4} (w/ s, x/ s, y/ s, z/ s) # unit quaternion
43+
44+ dRdqhat = _jacobian_unit_quat (qhat)
45+
46+ dqhatdq = (I (4 ) - qhat * qhat' ) / s # jacobian of normalization
47+ dRdqhat * dqhatdq # total jacobian
48+ end
6449
65- # now R(q) = (R(s*q)) / s for scalar s, because RotMatrix(s * q) = s * RotMatrix(q)
66- #
67- # so dR/dQ = (dR(s*q)/dQ*s - R(s*q) * ds/dQ) / s^2
68- # = (dR(s*q)/dQ*s - s*R(q) * ds/dQ) / s^2
69- # = (dR(s*q)/dQ - R(q) * ds/dQ) / s
7050
71- jac = dsRdQ - R * transpose (dsdQ )
51+ jacobian ( :: Type{RotMatrix} , q :: QuatRotation ) = _jacobian_unit_quat ( params (q) )
7252
73- # now reformat for output. TODO : is the the best expression?
74- # return Vec{4,Mat{3,3,T}}(ith_partial(jac, 1), ith_partial(jac, 2), ith_partial(jac, 3), ith_partial(jac, 4))
7553
54+ @inline function _jacobian_unit_quat (qhat:: SVector{4} )
55+ # jacobian of vec(RotMatrix(QuatRotation(qhat, false)))
56+ w, x, y, z = qhat
57+ return @SMatrix [ 2 * w 2 * x - 2 * y - 2 * z ;
58+ 2 * z 2 * y 2 * x 2 * w ;
59+ - 2 * y 2 * z - 2 * w 2 * x ;
60+ - 2 * z 2 * y 2 * x - 2 * w ;
61+ 2 * w - 2 * x 2 * y - 2 * z ;
62+ 2 * x 2 * w 2 * z 2 * y ;
63+ 2 * y 2 * z 2 * w 2 * x ;
64+ - 2 * x - 2 * w 2 * z 2 * y ;
65+ 2 * w - 2 * x - 2 * y 2 * z ]
7666end
7767
7868
0 commit comments