| Hosted by CoCalc | Download
# Adapted from http://www.wstein.org/edu/2010/414/projects/hoon_kwon.pdf N.<A_w,A_x,A_y,A_z,B_w,B_x,B_y,B_z> = QQ[] # Yields variables i,j,k that comprise the Hamiltonian quaternion basis. H.<i,j,k> = QuaternionAlgebra(Frac(N),-1,-1) quatA = A_w + A_x*i + A_y*j + A_z*k quatB = B_w + B_x*i + B_y*j + B_z*k # This is a neat trick, but I can't seem to do much else with these QuaternionAlgebra[Element] types. quatA * quatB
A_w*B_w - A_x*B_x - A_y*B_y - A_z*B_z + (A_x*B_w + A_w*B_x - A_z*B_y + A_y*B_z)*i + (A_y*B_w + A_z*B_x + A_w*B_y - A_x*B_z)*j + (A_z*B_w - A_y*B_x + A_x*B_y + A_w*B_z)*k
# Constructs a unit quaternion using Euler parameters. def QuatFromAxisAngle(vec, thetaRad): (axisX, axisY, axisZ) = (vec[0], vec[1], vec[2]) halfTheta = thetaRad / 2 w = cos(halfTheta) x = axisX * sin(halfTheta) y = axisY * sin(halfTheta) z = axisZ * sin(halfTheta) return vector([w, x, y, z]) def AxisAngleFromQuat(quat): theta = 2 * arccos(quat[0]) axis = vector([quat[1], quat[2], quat[3]]) axis /= sqrt(1 - (quat[0] * quat[0])) return vector([theta, axis[0], axis[1], axis[2]]) show( AxisAngleFromQuat(vector([0,0,1,0])) )
(π,0,1,0)\displaystyle \left(\pi,\,0,\,1,\,0\right)
xAxis = vector([1, 0, 0]) yAxis = vector([0, 1, 0]) zAxis = vector([0, 0, 1]) qx90 = QuatFromAxisAngle(xAxis, pi / 2) qy90 = QuatFromAxisAngle(yAxis, pi / 2) qz90 = QuatFromAxisAngle(zAxis, pi / 2) halfSqrt2 = sqrt(2) / 2 assert qx90 == vector([halfSqrt2, halfSqrt2, 0, 0]) assert qy90 == vector([halfSqrt2, 0, halfSqrt2, 0]) assert qz90 == vector([halfSqrt2, 0, 0, halfSqrt2]) show('$x(90^{\circ})$', column_matrix(qx90), '$y(90^{\circ})$', column_matrix(qy90), '$z(90^{\circ})$', column_matrix(qz90))
x(90)x(90^{\circ}) (12212200)\displaystyle \left(\begin{array}{r} \frac{1}{2} \, \sqrt{2} \\ \frac{1}{2} \, \sqrt{2} \\ 0 \\ 0 \end{array}\right) y(90)y(90^{\circ}) (12201220)\displaystyle \left(\begin{array}{r} \frac{1}{2} \, \sqrt{2} \\ 0 \\ \frac{1}{2} \, \sqrt{2} \\ 0 \end{array}\right) z(90)z(90^{\circ}) (12200122)\displaystyle \left(\begin{array}{r} \frac{1}{2} \, \sqrt{2} \\ 0 \\ 0 \\ \frac{1}{2} \, \sqrt{2} \end{array}\right)
# The Hamilton product of two quaternions. def quat_product(lhs, rhs): (r1, v1) = (lhs[0], lhs[1:4]) (r2, v2) = (rhs[0], rhs[1:4]) scalarProduct = r1 * r2 dotProduct = v1.dot_product(v2) crossProduct = v1.cross_product(v2) resultScalar = scalarProduct - dotProduct resultVector = (r1 * v2) + (r2 * v1) + crossProduct return vector([resultScalar, resultVector[0], resultVector[1], resultVector[2]]) # Yields the rotation corresponding to the combination of the entire input list of rotation quaternions. def compose_quats(quat_list): return reduce(quat_product, quat_list, vector([1, 0, 0, 0])) qidentity = vector([1, 0, 0, 0]) assert quat_product(qidentity, qidentity) == qidentity assert compose_quats([]) == qidentity assert compose_quats([qidentity]) == qidentity assert compose_quats([qidentity, qidentity]) == qidentity
(theta_x, theta_y, theta_z) = var('theta_x, theta_y, theta_z') qx = QuatFromAxisAngle(xAxis, theta_x) qy = QuatFromAxisAngle(yAxis, theta_y) qz = QuatFromAxisAngle(zAxis, theta_z) show(column_matrix(qx), column_matrix(qy), column_matrix(qz)) show(column_matrix(qx.subs(theta_x == pi / 2)), column_matrix(qy.subs(theta_y == pi / 2)), column_matrix(qz.subs(theta_z == pi / 2)))
(cos(12θx)sin(12θx)00)\displaystyle \left(\begin{array}{r} \cos\left(\frac{1}{2} \, \theta_{x}\right) \\ \sin\left(\frac{1}{2} \, \theta_{x}\right) \\ 0 \\ 0 \end{array}\right) (cos(12θy)0sin(12θy)0)\displaystyle \left(\begin{array}{r} \cos\left(\frac{1}{2} \, \theta_{y}\right) \\ 0 \\ \sin\left(\frac{1}{2} \, \theta_{y}\right) \\ 0 \end{array}\right) (cos(12θz)00sin(12θz))\displaystyle \left(\begin{array}{r} \cos\left(\frac{1}{2} \, \theta_{z}\right) \\ 0 \\ 0 \\ \sin\left(\frac{1}{2} \, \theta_{z}\right) \end{array}\right)
(12212200)\displaystyle \left(\begin{array}{r} \frac{1}{2} \, \sqrt{2} \\ \frac{1}{2} \, \sqrt{2} \\ 0 \\ 0 \end{array}\right) (12201220)\displaystyle \left(\begin{array}{r} \frac{1}{2} \, \sqrt{2} \\ 0 \\ \frac{1}{2} \, \sqrt{2} \\ 0 \end{array}\right) (12200122)\displaystyle \left(\begin{array}{r} \frac{1}{2} \, \sqrt{2} \\ 0 \\ 0 \\ \frac{1}{2} \, \sqrt{2} \end{array}\right)
qxyz = compose_quats([qx, qy, qz]) show(column_matrix(qxyz))
(cos(12θx)cos(12θy)cos(12θz)sin(12θx)sin(12θy)sin(12θz)cos(12θy)cos(12θz)sin(12θx)+cos(12θx)sin(12θy)sin(12θz)cos(12θx)cos(12θz)sin(12θy)cos(12θy)sin(12θx)sin(12θz)cos(12θz)sin(12θx)sin(12θy)+cos(12θx)cos(12θy)sin(12θz))\displaystyle \left(\begin{array}{r} \cos\left(\frac{1}{2} \, \theta_{x}\right) \cos\left(\frac{1}{2} \, \theta_{y}\right) \cos\left(\frac{1}{2} \, \theta_{z}\right) - \sin\left(\frac{1}{2} \, \theta_{x}\right) \sin\left(\frac{1}{2} \, \theta_{y}\right) \sin\left(\frac{1}{2} \, \theta_{z}\right) \\ \cos\left(\frac{1}{2} \, \theta_{y}\right) \cos\left(\frac{1}{2} \, \theta_{z}\right) \sin\left(\frac{1}{2} \, \theta_{x}\right) + \cos\left(\frac{1}{2} \, \theta_{x}\right) \sin\left(\frac{1}{2} \, \theta_{y}\right) \sin\left(\frac{1}{2} \, \theta_{z}\right) \\ \cos\left(\frac{1}{2} \, \theta_{x}\right) \cos\left(\frac{1}{2} \, \theta_{z}\right) \sin\left(\frac{1}{2} \, \theta_{y}\right) - \cos\left(\frac{1}{2} \, \theta_{y}\right) \sin\left(\frac{1}{2} \, \theta_{x}\right) \sin\left(\frac{1}{2} \, \theta_{z}\right) \\ \cos\left(\frac{1}{2} \, \theta_{z}\right) \sin\left(\frac{1}{2} \, \theta_{x}\right) \sin\left(\frac{1}{2} \, \theta_{y}\right) + \cos\left(\frac{1}{2} \, \theta_{x}\right) \cos\left(\frac{1}{2} \, \theta_{y}\right) \sin\left(\frac{1}{2} \, \theta_{z}\right) \end{array}\right)
qzxy = compose_quats([qz, qx, qy]) show(column_matrix(qzxy))
(cos(12θx)cos(12θy)cos(12θz)sin(12θx)sin(12θy)sin(12θz)cos(12θy)cos(12θz)sin(12θx)cos(12θx)sin(12θy)sin(12θz)cos(12θx)cos(12θz)sin(12θy)+cos(12θy)sin(12θx)sin(12θz)cos(12θz)sin(12θx)sin(12θy)+cos(12θx)cos(12θy)sin(12θz))\displaystyle \left(\begin{array}{r} \cos\left(\frac{1}{2} \, \theta_{x}\right) \cos\left(\frac{1}{2} \, \theta_{y}\right) \cos\left(\frac{1}{2} \, \theta_{z}\right) - \sin\left(\frac{1}{2} \, \theta_{x}\right) \sin\left(\frac{1}{2} \, \theta_{y}\right) \sin\left(\frac{1}{2} \, \theta_{z}\right) \\ \cos\left(\frac{1}{2} \, \theta_{y}\right) \cos\left(\frac{1}{2} \, \theta_{z}\right) \sin\left(\frac{1}{2} \, \theta_{x}\right) - \cos\left(\frac{1}{2} \, \theta_{x}\right) \sin\left(\frac{1}{2} \, \theta_{y}\right) \sin\left(\frac{1}{2} \, \theta_{z}\right) \\ \cos\left(\frac{1}{2} \, \theta_{x}\right) \cos\left(\frac{1}{2} \, \theta_{z}\right) \sin\left(\frac{1}{2} \, \theta_{y}\right) + \cos\left(\frac{1}{2} \, \theta_{y}\right) \sin\left(\frac{1}{2} \, \theta_{x}\right) \sin\left(\frac{1}{2} \, \theta_{z}\right) \\ \cos\left(\frac{1}{2} \, \theta_{z}\right) \sin\left(\frac{1}{2} \, \theta_{x}\right) \sin\left(\frac{1}{2} \, \theta_{y}\right) + \cos\left(\frac{1}{2} \, \theta_{x}\right) \cos\left(\frac{1}{2} \, \theta_{y}\right) \sin\left(\frac{1}{2} \, \theta_{z}\right) \end{array}\right)
qzyx = compose_quats([qz, qy, qx]) show(column_matrix(qzyx))
(cos(12θx)cos(12θy)cos(12θz)+sin(12θx)sin(12θy)sin(12θz)cos(12θy)cos(12θz)sin(12θx)cos(12θx)sin(12θy)sin(12θz)cos(12θx)cos(12θz)sin(12θy)+cos(12θy)sin(12θx)sin(12θz)cos(12θz)sin(12θx)sin(12θy)+cos(12θx)cos(12θy)sin(12θz))\displaystyle \left(\begin{array}{r} \cos\left(\frac{1}{2} \, \theta_{x}\right) \cos\left(\frac{1}{2} \, \theta_{y}\right) \cos\left(\frac{1}{2} \, \theta_{z}\right) + \sin\left(\frac{1}{2} \, \theta_{x}\right) \sin\left(\frac{1}{2} \, \theta_{y}\right) \sin\left(\frac{1}{2} \, \theta_{z}\right) \\ \cos\left(\frac{1}{2} \, \theta_{y}\right) \cos\left(\frac{1}{2} \, \theta_{z}\right) \sin\left(\frac{1}{2} \, \theta_{x}\right) - \cos\left(\frac{1}{2} \, \theta_{x}\right) \sin\left(\frac{1}{2} \, \theta_{y}\right) \sin\left(\frac{1}{2} \, \theta_{z}\right) \\ \cos\left(\frac{1}{2} \, \theta_{x}\right) \cos\left(\frac{1}{2} \, \theta_{z}\right) \sin\left(\frac{1}{2} \, \theta_{y}\right) + \cos\left(\frac{1}{2} \, \theta_{y}\right) \sin\left(\frac{1}{2} \, \theta_{x}\right) \sin\left(\frac{1}{2} \, \theta_{z}\right) \\ -\cos\left(\frac{1}{2} \, \theta_{z}\right) \sin\left(\frac{1}{2} \, \theta_{x}\right) \sin\left(\frac{1}{2} \, \theta_{y}\right) + \cos\left(\frac{1}{2} \, \theta_{x}\right) \cos\left(\frac{1}{2} \, \theta_{y}\right) \sin\left(\frac{1}{2} \, \theta_{z}\right) \end{array}\right)
# This is a whole bunch of me trying to figure out how to reorder the terms so the theta variables always appear in the order x,y,z # See also: http://ask.sagemath.org/question/10641/can-sage-stop-ordering-terms/?answer=15600#post-id-15600 assert qxyz[0].operator() == sage.symbolic.operators.add_vararg assert qxyz[0].operands()[0].operator() == sage.symbolic.operators.mul_vararg assert qxyz[0].operands()[0].operands()[0].operator() == cos assert qxyz[0].operands()[0].operands()[0].operands()[0].operator() == sage.symbolic.operators.mul_vararg #qxyz[0].operands()[0].operands()[0].operands()[0].operands()[0] == theta_x #qxyz[0].operands()[0].operands()[0].operands()[0].operands()[1] == 1/2 #qxyz[0].operands()[0].operands()[0].variables()[0] == theta_x