-
Notifications
You must be signed in to change notification settings - Fork 35
Remove DualQuaternion #92
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Changes from all commits
Commits
Show all changes
22 commits
Select commit
Hold shift + click to select a range
08a3a19
Remove DualQuaternion code
sethaxen 4c546f3
Remove DualQuaternion tests
sethaxen 4e9a303
Remove DualNumbers dependency
sethaxen 05bf42b
Remove dual quaternions from docs
sethaxen 4195f2e
Remove ForwardDiff from extras
sethaxen 4389cd4
Document example of dual quaternions
sethaxen c670e2d
Mark as dev version
sethaxen c94e674
Apply suggestions from code review
sethaxen c871c4f
Merge remote-tracking branch 'upstream/master' into rmdual
sethaxen 4192465
Merge branch 'rmdual' of https://github.com/JuliaGeometry/Quaternions…
sethaxen 42dea68
Update README.md
sethaxen 9fe166b
Rename conj to dualconj
sethaxen 9c4f1ad
Set correct example name
sethaxen 749fd5e
Update docs/src/examples/dual_quaternions.md
sethaxen 2c015c8
Apply suggestions from code review
sethaxen 367a9a4
Merge branch 'master' into rmdual
sethaxen a78df78
Add missing word
sethaxen 5865540
Use repl mode
sethaxen aebd8a7
Move transformation matrix check to that section
sethaxen a13e576
Remove redundant y creation
sethaxen 01cd4b6
Describe affine transformation matrix
sethaxen 620087f
Specify that it's unit
sethaxen File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,19 +1,16 @@ | ||
| name = "Quaternions" | ||
| uuid = "94ee1d12-ae83-5a48-8b1c-48b8ff168ae0" | ||
| version = "0.5.7" | ||
| version = "0.6.0-DEV" | ||
|
|
||
| [deps] | ||
| DualNumbers = "fa6b7ba4-c1ee-5f82-b5fc-ecf0adba8f74" | ||
| LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" | ||
| Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" | ||
|
|
||
| [compat] | ||
| DualNumbers = "0.5, 0.6" | ||
| julia = "1" | ||
|
|
||
| [extras] | ||
| ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210" | ||
| Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" | ||
|
|
||
| [targets] | ||
| test = ["ForwardDiff", "Test"] | ||
| test = ["Test"] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,2 +1,7 @@ | ||
| [deps] | ||
| Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" | ||
| ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210" | ||
| Quaternions = "94ee1d12-ae83-5a48-8b1c-48b8ff168ae0" | ||
|
|
||
| [compat] | ||
| ForwardDiff = "0.10" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -14,6 +14,7 @@ makedocs(; | |
| ), | ||
| pages=[ | ||
| "Home" => "index.md", | ||
| "Examples" => ["examples/dual_quaternions.md"], | ||
| ], | ||
| ) | ||
|
|
||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,175 @@ | ||
| # Dual quaternions | ||
|
|
||
| ## Introduction | ||
|
|
||
| The [dual quaternions](https://en.wikipedia.org/wiki/Dual_quaternion) are an example of "biquaternions." | ||
| They can be represented equivalently either as a [dual number](https://en.wikipedia.org/wiki/Dual_number) where both both the "primal" and "tangent" part are quaternions | ||
|
|
||
| ```math | ||
| d = q_0 + q_e \epsilon = (s_0 + a_0 i + b_0 j + c_0 k) + (s_e + a_e i + b_e j + c_e k) \epsilon | ||
| ``` | ||
|
|
||
| or as a quaternion where the scalar part and three imaginary parts are all dual numbers | ||
|
|
||
| ```math | ||
| d = s + ai + bj + ck = (s_0 + s_e \epsilon) + (a_0 + a_e \epsilon) i + (b_0 + b_e \epsilon) j + (c_0 + c_e \epsilon) k. | ||
| ``` | ||
|
|
||
| Like unit quaternions can compactly representation rotations in 3D space, dual quaternions can compactly represent rigid transformations (rotation with translation). | ||
|
|
||
| Without any special glue code, we can construct a dual quaternion by composing `ForwardDiff.Dual` and [`Quaternion`](@ref); this uses the second representation described above: | ||
|
|
||
| !!! note | ||
| Previously this package contained a specialized `DualQuaternion` type. | ||
| This was removed in v0.6.0 because it offered nothing extra over composing [ForwardDiff](https://github.com/JuliaDiff/ForwardDiff.jl) and Quaternions. | ||
|
|
||
| ## Utility functions | ||
|
|
||
| First let's load the packages: | ||
|
|
||
| ```@example dualquat | ||
| using Quaternions, ForwardDiff, Random | ||
| ``` | ||
|
|
||
| Then we'll create some utility types/functions: | ||
|
|
||
| ```@example dualquat | ||
| const DualQuaternion{T} = Quaternion{ForwardDiff.Dual{Nothing,T,1}} | ||
|
|
||
| purequat(p::AbstractVector) = quat(false, @views(p[begin:begin+2])...) | ||
|
|
||
| dual(x::Real, v::Real) = ForwardDiff.Dual(x, v) | ||
|
|
||
| function dualquat(_q0::Union{Real,Quaternion}, _qe::Union{Real,Quaternion}) | ||
| q0 = quat(_q0) | ||
| qe = quat(_qe) | ||
| Quaternion( | ||
| dual(real(q0), real(qe)), | ||
| dual.(imag_part(q0), imag_part(qe))..., | ||
| ) | ||
| end | ||
|
|
||
| function primal(d::DualQuaternion) | ||
| return Quaternion( | ||
| ForwardDiff.value(real(d)), | ||
| ForwardDiff.value.(imag_part(d))..., | ||
| ) | ||
| end | ||
|
|
||
| function tangent(d::DualQuaternion) | ||
| return Quaternion( | ||
| ForwardDiff.partials(real(d), 1), | ||
| ForwardDiff.partials.(imag_part(d), 1)..., | ||
| ) | ||
| end | ||
|
|
||
| function dualconj(d::DualQuaternion) | ||
| de = tangent(d) | ||
| return dualquat(conj(primal(d)), quat(-real(de), imag_part(de)...)) | ||
| end | ||
|
|
||
| rotation_part(d::DualQuaternion) = primal(d) | ||
|
|
||
| translation_part(d::DualQuaternion) = dualquat(true, conj(rotation_part(d)) * tangent(d)) | ||
|
|
||
| # first=true returns the translation performed before the rotation: R(p+t) | ||
| # first=false returns the translation performed after the rotation: R(p)+t | ||
| function translation(d::DualQuaternion; first::Bool=true) | ||
| v = first ? primal(d)' * tangent(d) : tangent(d) * primal(d)' | ||
| return collect(2 .* imag_part(v)) | ||
| end | ||
|
|
||
| function transform(d::DualQuaternion, p::AbstractVector) | ||
| dp = dualquat(true, purequat(p)) | ||
| dpnew = d * dp * dualconj(d) | ||
| pnew_parts = imag_part(tangent(dpnew)) | ||
| pnew = similar(p, eltype(pnew_parts)) | ||
| pnew .= pnew_parts | ||
| return pnew | ||
| end | ||
|
|
||
| function transformationmatrix(d::DualQuaternion) | ||
| R = rotationmatrix(rotation_part(d)) | ||
| t = translation(d; first=false) | ||
| T = similar(R, 4, 4) | ||
| T[1:3, 1:3] .= R | ||
| T[1:3, 4] .= t | ||
| T[4, 1:3] .= 0 | ||
| T[4, 4] = 1 | ||
| return T | ||
| end | ||
|
|
||
| randdualquat(rng::AbstractRNG,T=Float64) = dualquat(rand(rng, Quaternion{T}), rand(rng, Quaternion{T})) | ||
| randdualquat(T=Float64) = randdualquat(Random.GLOBAL_RNG,T) | ||
| nothing # hide | ||
| ``` | ||
|
|
||
| ## Example: transforming a point | ||
|
|
||
| Now we'll create a unit dual quaternion. | ||
| ```@repl dualquat | ||
| x = sign(randdualquat()) | ||
| ``` | ||
|
|
||
| `sign(q) == q / abs(q)` both normalizes the primal part of the dual quaternion and makes the tangent part perpendicular to it. | ||
|
|
||
| ```@repl dualquat | ||
| abs(primal(x)) ≈ 1 | ||
| isapprox(real(primal(x)' * tangent(x)), 0; atol=1e-10) | ||
| ``` | ||
|
|
||
| Here's how we use dual quaternions to transform a point: | ||
|
|
||
| ```@repl dualquat | ||
| p = randn(3) | ||
| ``` | ||
|
|
||
| ```@repl dualquat | ||
| transform(x, p) | ||
| ``` | ||
|
|
||
| ## Example: homomorphism from unit dual quaternions to the transformation matrices | ||
|
|
||
| Each unit dual quaternion can be mapped to an affine transformation matrix ``T``. | ||
| ``T`` can be used to transform a vector ``p`` like this: | ||
|
|
||
| ```math | ||
| T \begin{pmatrix} p \\ 1\end{pmatrix} = \begin{pmatrix} R & t \\ 0^\mathrm{T} & 1\end{pmatrix} \begin{pmatrix} p \\ 1\end{pmatrix} = \begin{pmatrix} Rp + t \\ 1\end{pmatrix}, | ||
| ``` | ||
| where ``R`` is a rotation matrix, and ``t`` is a translation vector. | ||
| Our helper function `transformationmatrix` maps from a unit dual quaternion to such an affine matrix. | ||
|
|
||
| ```@repl dualquat | ||
| y = sign(randdualquat()) | ||
| ``` | ||
|
|
||
| ```@repl dualquat | ||
| X = transformationmatrix(x) | ||
| Y = transformationmatrix(y) | ||
| XY = transformationmatrix(x*y) | ||
| X*Y ≈ XY | ||
| ``` | ||
|
|
||
| We can check that our transformation using the unit dual quaternion gives the same result as transforming with an affine transformation matrix: | ||
|
|
||
| ```@repl dualquat | ||
| transform(x, p) ≈ (X * vcat(p, 1))[1:3] | ||
| ``` | ||
|
|
||
sethaxen marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| ## Example: motion planning | ||
|
|
||
| For unit quaternions, spherical linear interpolation with [`slerp`](@ref) can be used to interpolate between two rotations with unit quaternions, which can be used to plan motion between two orientations. | ||
| Similarly, we can interpolate between unit dual quaternions to plan motion between two rigid poses. | ||
| Conveniently, we can do this using the exact same `slerp` implementation. | ||
|
|
||
| ```@repl dualquat | ||
| slerp(x, y, 0) ≈ x | ||
| ``` | ||
|
|
||
| ```@repl dualquat | ||
| slerp(x, y, 1) ≈ y | ||
| ``` | ||
|
|
||
| ```@repl dualquat | ||
| slerp(x, y, 0.3) | ||
| ``` | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.