@@ -26,53 +26,43 @@ ith_partial{N}(X::SMatrix{9,N}, i) = @SMatrix([X[1,i] X[4,i] X[7,i];
26
26
jacobian(::Type{output_param}, R::input_param)
27
27
Returns the jacobian for transforming from the input rotation parameterization
28
28
to 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
29
34
30
35
jacobian(R::rotation_type, X::AbstractVector)
31
36
Returns the jacobian for rotating the vector X by R.
32
37
"""
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) / s
41
+ x, y, z = imag_part (q) ./ s
42
+ qhat = SVector {4} (w, x, y, z) # unit quaternion
43
+
44
+ dRdqhat = _jacobian_unit_quat (qhat)
45
+
46
+ dqhatdq = (I (4 ) - qhat * qhat' ) ./ s
47
+ dRdqhat * dqhatdq
48
+ end
64
49
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
70
50
71
- jac = dsRdQ - R * transpose (dsdQ )
51
+ jacobian ( :: Type{RotMatrix} , q :: QuatRotation ) = _jacobian_unit_quat ( params (q) )
72
52
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))
75
53
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 ]
76
66
end
77
67
78
68
0 commit comments