author | comments | layout | mathjax | slug | title |
---|---|---|---|---|---|
Alok Singh |
true |
post |
true |
noncommutative-3d-rotations |
Exploring Non-Commutative 3D Rotations with Grassmann Algebra |
People find rotation hard because when we try to visualize something, often we project it onto a 2D plane. But for rotations, this loses the plot because 2D rotations DO commute. In this post, we will (symbolically) explore this non-commutative nature of 3D rotations using Grassmann algebra in Julia. We'll use the Grassmann
package to define rotors and demonstrate how the order of rotations matters in three-dimensional space.
I'll set up our 3D space and define a function to create rotors:
using Grassmann
@basis 3 # Define a 3D space
# Function to create a rotor from a bivector and an angle
function rotor(bivector, angle)
return exp(-angle/2 * bivector)
end
Next, we'll create two different rotations:
# Create two different rotations
rotation_xy = rotor(v12, π/4) # Rotation in xy-plane by π/4
rotation_yz = rotor(v23, π/3) # Rotation in yz-plane by π/3
Now, let's compute the composition of rotations in different orders:
# Compute the composition of rotations in different orders
rotor_ab = rotation_yz * rotation_xy
rotor_ba = rotation_xy * rotation_yz
# Demonstrate that squaring rotation_xy results in a π/2 rotation
rotation_xy_squared = rotation_xy * rotation_xy
We'll also create a π/2 rotation in the xy-plane for comparison:
# Create a π/2 rotation in the xy-plane for comparison
rotation_xy_pi_half = rotor(v12, π/2)
Let's print out the results:
println("\nRotation XY squared:")
println(rotation_xy_squared)
println("\nRotation XY by π/2:")
println(rotation_xy_pi_half)
println("\nAre they equal?")
println(rotation_xy_squared ≈ rotation_xy_pi_half)
Optional: Apply to a test vector for visual confirmation:
# Optional: Apply to a test vector for visual confirmation
test_vector_xy = v1 + v2
result_squared = rotation_xy_squared * test_vector_xy * ~rotation_xy_squared
result_pi_half = rotation_xy_pi_half * test_vector_xy * ~rotation_xy_pi_half
println("\nApplied to test vector (1,1,0):")
println("Result of squared rotation:", result_squared)
println("Result of π/2 rotation:", result_pi_half)
println("Are the results equal?", result_squared ≈ result_pi_half)
Now, let's print out the rotors:
println("Rotor XY then YZ:")
println(rotor_ab)
println("\nRotor YZ then XY:")
println(rotor_ba)
println("\nAre the rotors equal?")
println(rotor_ab ≈ rotor_ba)
Optional: Verify the non-commutativity by applying to a test vector:
test_vector = v1 + v2 + v3
result_ab = rotor_ab * test_vector * ~rotor_ab
result_ba = rotor_ba * test_vector * ~rotor_ba
println("\nApplied to test vector (1,1,1):")
println("Result AB:", result_ab)
println("Result BA:", result_ba)
println("Are the results equal?", result_ab ≈ result_ba)
println("\n--- Demonstrating 2D Rotation Commutativity ---")
z = complex(rand(), rand()) println("Random complex number z: ", z)
θ1, θ2 = 2π * rand(), 2π * rand() println("Random angles: θ1 = ", θ1, ", θ2 = ", θ2)
rotation1 = exp(im * θ1) * exp(im * θ2) * z rotation2 = exp(im * θ2) * exp(im * θ1) * z
println("\nRotation 1 (θ1 then θ2): ", rotation1) println("Rotation 2 (θ2 then θ1): ", rotation2) println("Are the results equal? ", isapprox(rotation1, rotation2, atol=1e-10))
function complex_to_grassmann(z::Complex) return real(z) + imag(z) * v12 end
z_grassmann = complex_to_grassmann(z) rotation1_grassmann = rotor(v12, θ1) * rotor(v12, θ2) * z_grassmann * ~rotor(v12, θ2) * ~rotor(v12, θ1) rotation2_grassmann = rotor(v12, θ2) * rotor(v12, θ1) * z_grassmann * ~rotor(v12, θ1) * ~rotor(v12, θ2)
println("\nGrassmann Rotation 1 (θ1 then θ2): ", rotation1_grassmann) println("Grassmann Rotation 2 (θ2 then θ1): ", rotation2_grassmann) println("Are the Grassmann results equal? ", rotation1_grassmann ≈ rotation2_grassmann)
Results:
# Rotation XY squared:
0.7071067811865475 - 0.7071067811865476v₁₂
# Rotation XY by π/2:
0.7071067811865476 - 0.7071067811865475v₁₂
# Are they equal?
true
# Applied to test vector (1,1,0):
# Result of squared rotation:
-1.0v₁ + 1.0v₂ + 0.0v₃ + 0.0v₁₂₃
# Result of π/2 rotation:
-1.0v₁ + 1.0v₂ + 0.0v₃ + 0.0v₁₂₃
# Are the results equal?
true
# Rotor XY then YZ:
0.800103 - 0.331414v₁₂ - 0.191342v₁₃ - 0.46194v₂₃
# Rotor YZ then XY:
0.800103 - 0.331414v₁₂ + 0.191342v₁₃ - 0.46194v₂₃
# Are the rotors equal?
false
# Applied to test vector (1,1,1):
# AB:
-5.55112e-17v₁ - 0.158919v₂ + 1.72474v₃ + 0.0v₁₂₃
# BA:
0.965926v₁ + 0.448288v₂ + 1.36603v₃ + 0.0v₁₂₃
# Are the results equal?
false
# Random complex number z: 0.5 + 0.5im
# Random angles: θ1 = 3.141592653589793, θ2 = 1.5707963267948966
# Rotation 1 (θ1 then θ2): 0.5 - 0.5im
# Rotation 2 (θ2 then θ1): 0.5 - 0.5im
# Are the results equal? true
# Grassmann Rotation 1 (θ1 then θ2): 0.5 - 0.5v₁₂
# Grassmann Rotation 2 (θ2 then θ1): 0.5 - 0.5v₁₂
# Are the Grassmann results equal? true