Skip to content

Commit

Permalink
Support for latest Julia master.
Browse files Browse the repository at this point in the history
Base.Test -> Compat.Test.

Comment out showarray for now.

Compat for eye and inv.

transpose instead of .'

Use Compat.LinearAlgebra in runtests.jl

indmax -> argmax

Import srand from Compat.Random.

Import inv and eye from Compat.LinearAlgebra.

Comment out show test for now.

More transpose, adjoint fixes.

Minor fixes.

Make benchmarks keys the same between 0.6 and 0.7.

Fixes for 0.6.

showarray/show
  • Loading branch information
tkoolen committed Mar 23, 2018
1 parent 8a97a9e commit 6720803
Show file tree
Hide file tree
Showing 11 changed files with 104 additions and 58 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ q2 = rand(Quat)
q3 = q * q2

# Take the inverse (equivalent to transpose)
q_inv = q'
q_inv = transpose(q)
q_inv == inv(q)
p q_inv * (q * p)
q4 = q3 / q2 # q4 = q3 * inv(q2)
Expand Down Expand Up @@ -102,7 +102,7 @@ j2 = Rotations.jacobian(q, p) # How does the rotated point q*p change w.r.t. the

4. **Rodrigues Vector** `RodriguesVec{T}`

A 3D rotation encoded by an angle-axis representation as `angle * axis`.
A 3D rotation encoded by an angle-axis representation as `angle * axis`.
This type is used in packages such as [OpenCV](http://docs.opencv.org/2.4/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.html#void%20Rodrigues%28InputArray%20src,%20OutputArray%20dst,%20OutputArray%20jacobian%29).

Note: If you're differentiating a Rodrigues Vector check the result is what
Expand Down
1 change: 1 addition & 0 deletions REQUIRE
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
julia 0.6
StaticArrays 0.6.5
Compat
14 changes: 11 additions & 3 deletions perf/runbenchmarks.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Rotations
using BenchmarkTools
import Base.Iterators: product
import Compat.Random: srand

const T = Float64

Expand All @@ -11,16 +12,23 @@ suite["conversions"] = BenchmarkGroup()
rotationtypes = (RotMatrix3{T}, Quat{T}, SPQuat{T}, AngleAxis{T}, RodriguesVec{T})
for (from, to) in product(rotationtypes, rotationtypes)
if from != to
name = "$(string(from)) -> $(string(to))"
name = if VERSION < v"0.7.0-"
"$(string(from)) -> $(string(to))"
else
"Rotations.$(string(from)) -> Rotations.$(string(to))"
end
# use eval here because of https://github.com/JuliaCI/BenchmarkTools.jl/issues/50#issuecomment-318673288
suite["conversions"][name] = eval(:(@benchmarkable convert($to, rot) setup = rot = rand($from)))
end
end

suite["composition"] = BenchmarkGroup()
suite["composition"]["RotMatrix{3} * RotMatrix{3}"] = @benchmarkable r1 * r2 setup = (r1 = rand(RotMatrix3{T}); r2 = rand(RotMatrix3{T}))
suite["composition"]["RotMatrix{3} * RotMatrix{3}"] = @benchmarkable(
r1 * r2,
setup = (r1 = rand(RotMatrix3{T}); r2 = rand(RotMatrix3{T}))
)

paramspath = joinpath(dirname(@__FILE__), "benchmarkparams.json")
paramspath = joinpath(@__DIR__, "benchmarkparams.json")
if isfile(paramspath)
loadparams!(suite, BenchmarkTools.load(paramspath)[1], :evals, :samples);
else
Expand Down
5 changes: 4 additions & 1 deletion src/Rotations.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@ __precompile__(true)

module Rotations

using Compat
using Compat.LinearAlgebra
using StaticArrays

import Base: convert, eltype, size, length, getindex, inv, *, Tuple, eye
import Base: convert, eltype, size, length, getindex, *, Tuple
import Compat.LinearAlgebra: inv, eye

include("util.jl")
include("core_types.jl")
Expand Down
91 changes: 58 additions & 33 deletions src/core_types.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ abstract type Rotation{N,T} <: StaticMatrix{N,N,T} end
Base.@pure StaticArrays.Size(::Type{Rotation{N}}) where {N} = Size(N,N)
Base.@pure StaticArrays.Size(::Type{Rotation{N,T}}) where {N,T} = Size(N,N)
Base.@pure StaticArrays.Size(::Type{R}) where {R<:Rotation} = Size(supertype(R))
Base.ctranspose(r::Rotation) = inv(r)
Base.transpose(r::Rotation{N,T}) where {N,T<:Real} = inv(r)
Compat.adjoint(r::Rotation) = inv(r)
Compat.transpose(r::Rotation{N,T}) where {N,T<:Real} = inv(r)

# Rotation angles and axes can be obtained by converting to the AngleAxis type
rotation_angle(r::Rotation) = rotation_angle(AngleAxis(r))
Expand Down Expand Up @@ -102,11 +102,11 @@ Base.@propagate_inbounds Base.getindex(r::RotMatrix, i::Int) = r.mat[i]
@inline (::Type{RotMatrix{2,T}})(θ::Real) where {T} = RotMatrix(@SMatrix T[cos(θ) -sin(θ); sin(θ) cos(θ)])

# A rotation is more-or-less defined as being an orthogonal (or unitary) matrix
Base.inv(r::RotMatrix) = RotMatrix(r.mat')
inv(r::RotMatrix) = RotMatrix(r.mat')

# A useful constructor for identity rotation (eye is already provided by StaticArrays, but needs an eltype)
@inline Base.eye(::Type{RotMatrix{N}}) where {N} = RotMatrix((eye(SMatrix{N,N,Float64})))
@inline Base.eye(::Type{RotMatrix{N,T}}) where {N,T} = RotMatrix((eye(SMatrix{N,N,T})))
@inline eye(::Type{RotMatrix{N}}) where {N} = RotMatrix((eye(SMatrix{N,N,Float64})))
@inline eye(::Type{RotMatrix{N,T}}) where {N,T} = RotMatrix((eye(SMatrix{N,N,T})))

# By default, composition of rotations will go through RotMatrix, unless overridden
@inline *(r1::Rotation, r2::Rotation) = RotMatrix(r1) * RotMatrix(r2)
Expand Down Expand Up @@ -150,32 +150,18 @@ function isrotation(r::AbstractMatrix{T}, tol::Real = 1000 * eps(eltype(T))) whe
return d < tol
end


# A simplification and specialization of the Base.showarray() function makes
# everything sensible at the REPL.
function Base.showarray(io::IO, X::Rotation, repr::Bool = true; header = true)
if !haskey(io, :compact)
io = IOContext(io, compact=true)
end
if repr
if isa(X, RotMatrix)
Base.print_matrix_repr(io, X)
else
print(io, typeof(X).name.name)
n_fields = length(fieldnames(typeof(X)))
print(io, "(")
for i = 1:n_fields
print(io, getfield(X, i))
if i < n_fields
print(io, ", ")
end
end
print(io, ")")
@static if VERSION < v"0.7-"
# A simplification and specialization of the Base.showarray() function makes
# everything sensible at the REPL.
function Base.showarray(io::IO, X::Rotation, repr::Bool = true; header = true)
if !haskey(io, :compact)
io = IOContext(io, compact=true)
end
else
if header
print(io, summary(X))
if !isa(X, RotMatrix)
if repr
if isa(X, RotMatrix)
Base.print_matrix_repr(io, X)
else
print(io, typeof(X).name.name)
n_fields = length(fieldnames(typeof(X)))
print(io, "(")
for i = 1:n_fields
Expand All @@ -186,10 +172,49 @@ function Base.showarray(io::IO, X::Rotation, repr::Bool = true; header = true)
end
print(io, ")")
end
println(io, ":")
else
if header
print(io, summary(X))
if !isa(X, RotMatrix)
n_fields = length(fieldnames(typeof(X)))
print(io, "(")
for i = 1:n_fields
print(io, getfield(X, i))
if i < n_fields
print(io, ", ")
end
end
print(io, ")")
end
println(io, ":")
end
punct = (" ", " ", "")
Base.print_matrix(io, X, punct...)
end
end
else
# A simplification and specialization of the Base.show function for AbstractArray makes
# everything sensible at the REPL.
function Base.show(io::IO, ::MIME"text/plain", X::Rotation)
if !haskey(io, :compact)
io = IOContext(io, :compact => true)
end
summary(io, X)
if !isa(X, RotMatrix)
n_fields = length(fieldnames(typeof(X)))
print(io, "(")
for i = 1:n_fields
print(io, getfield(X, i))
if i < n_fields
print(io, ", ")
end
end
print(io, ")")
end
punct = (" ", " ", "")
Base.print_matrix(io, X, punct...)
print(io, ":")
println(io)
io = IOContext(io, :typeinfo => eltype(X))
Base.print_array(io, X)
end
end

Expand Down
4 changes: 2 additions & 2 deletions src/derivatives.jl
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ function jacobian(::Type{RotMatrix}, q::Quat)
# = (dR(s*q)/dQ*s - s*R(q) * ds/dQ) / s^2
# = (dR(s*q)/dQ - R(q) * ds/dQ) / s

jac = dsRdQ - R * dsdQ.'
jac = dsRdQ - R * transpose(dsdQ)

# now reformat for output. TODO: is the the best expression?
# return Vec{4,Mat{3,3,T}}(ith_partial(jac, 1), ith_partial(jac, 2), ith_partial(jac, 3), ith_partial(jac, 4))
Expand Down Expand Up @@ -198,7 +198,7 @@ function jacobian(q::Quat, X::AbstractVector)

# and finalize with the quotient rule
Xo = q * X # N.B. g(x) = s * Xo, with dG/dx = dRdQs
Xom = Xo * dSdQ.'
Xom = Xo * transpose(dSdQ)
return dRdQs - Xom
end

Expand Down
14 changes: 7 additions & 7 deletions src/quaternion_types.jl
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ function (::Type{Q})(t::NTuple{9}) where Q<:Quat
not_orthogonal = randn(3,3)
u,s,v = svd(not_orthogonal)
is_orthogoral = u * diagm([1, 1, sign(det(u * v.'))]) * v.'
is_orthogoral = u * diagm([1, 1, sign(det(u * transpose(v)))]) * transpose(v)
=#

a = 1 + t[1] + t[5] + t[9]
Expand Down Expand Up @@ -188,12 +188,12 @@ function Base.:*(q1::Quat, q2::Quat)
q1.w*q2.z + q1.x*q2.y - q1.y*q2.x + q1.z*q2.w)
end

function Base.inv(q::Quat)
function inv(q::Quat)
Quat(q.w, -q.x, -q.y, -q.z)
end

@inline Base.eye(::Type{Quat}) = Quat(1.0, 0.0, 0.0, 0.0)
@inline Base.eye(::Type{Quat{T}}) where {T} = Quat{T}(one(T), zero(T), zero(T), zero(T))
@inline eye(::Type{Quat}) = Quat(1.0, 0.0, 0.0, 0.0)
@inline eye(::Type{Quat{T}}) where {T} = Quat{T}(one(T), zero(T), zero(T), zero(T))

"""
rotation_between(from, to)
Expand Down Expand Up @@ -274,10 +274,10 @@ end
@inline Base.:*(r::RotMatrix, spq::SPQuat) = r * Quat(spq)
@inline Base.:*(spq1::SPQuat, spq2::SPQuat) = Quat(spq1) * Quat(spq2)

@inline Base.inv(spq::SPQuat) = SPQuat(-spq.x, -spq.y, -spq.z)
@inline inv(spq::SPQuat) = SPQuat(-spq.x, -spq.y, -spq.z)

@inline Base.eye(::Type{SPQuat}) = SPQuat(0.0, 0.0, 0.0)
@inline Base.eye(::Type{SPQuat{T}}) where {T} = SPQuat{T}(zero(T), zero(T), zero(T))
@inline eye(::Type{SPQuat}) = SPQuat(0.0, 0.0, 0.0)
@inline eye(::Type{SPQuat{T}}) where {T} = SPQuat{T}(zero(T), zero(T), zero(T))

# rotation properties
@inline rotation_angle(spq::SPQuat) = rotation_angle(Quat(spq))
Expand Down
4 changes: 2 additions & 2 deletions src/util.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ function perpendicular_vector(vec::SVector{3})

# find indices of the two elements of vec with the largest absolute values:
absvec = abs.(vec)
ind1 = indmax(absvec) # index of largest element
ind1 = argmax(absvec) # index of largest element
@inbounds absvec2 = @SVector [ifelse(i == ind1, typemin(T), absvec[i]) for i = 1 : 3] # set largest element to typemin(T)
ind2 = indmax(absvec2) # index of second-largest element
ind2 = argmax(absvec2) # index of second-largest element

# perp[ind1] = -vec[ind2], perp[ind2] = vec[ind1], set remaining element to zero:
@inbounds perpind1 = -vec[ind2]
Expand Down
11 changes: 8 additions & 3 deletions test/2d.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Rotations, StaticArrays, Base.Test
using Rotations, StaticArrays, Compat.Test

@testset "2d Rotations" begin

Expand Down Expand Up @@ -38,8 +38,8 @@ using Rotations, StaticArrays, Base.Test
for i = 1:repeats
r = rand(R)
@test isrotation(r)
@test inv(r) == r'
@test inv(r) == r.'
@test inv(r) == adjoint(r)
@test inv(r) == transpose(r)
@test inv(r)*r I
@test r*inv(r) I
end
Expand Down Expand Up @@ -119,6 +119,11 @@ using Rotations, StaticArrays, Base.Test
show(io, MIME("text/plain"), r)
str = String(take!(io))
@test startswith(str, "2×2 RotMatrix{Float64}:")

rxyz = RotXYZ(1.0, 2.0, 3.0)
show(io, MIME("text/plain"), rxyz)
str = String(take!(io))
@test startswith(str, "3×3 RotXYZ{Float64}(1.0, 2.0, 3.0):")
end
end

Expand Down
6 changes: 3 additions & 3 deletions test/rotation_tests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,8 @@ all_types = (RotMatrix{3}, Quat, SPQuat, AngleAxis, RodriguesVec,
srand(0)
for i = 1:repeats
r = rand(R)
@test inv(r) == r'
@test inv(r) == r.'
@test inv(r) == adjoint(r)
@test inv(r) == transpose(r)
@test inv(r)*r I
@test r*inv(r) I
end
Expand Down Expand Up @@ -183,7 +183,7 @@ all_types = (RotMatrix{3}, Quat, SPQuat, AngleAxis, RodriguesVec,
#########################################################################
function nearest_orthonormal(not_orthonormal)
u,s,v = svd(not_orthonormal)
return u * diagm([1, 1, sign(det(u * v.'))]) * v.'
return u * diagm([1, 1, sign(det(u * transpose(v)))]) * transpose(v)
end

@testset "DCM to Quat" begin
Expand Down
8 changes: 6 additions & 2 deletions test/runtests.jl
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
using Base.Test
using Compat
using Compat.Test
using Compat.LinearAlgebra
using Rotations
using StaticArrays

import Compat.Random: srand

# Check that there are no ambiguities beyond those present in StaticArrays
ramb = detect_ambiguities(Rotations, Base, Core)
samb = detect_ambiguities(StaticArrays, Base, Core)
Expand All @@ -14,4 +18,4 @@ include("2d.jl")
include("rotation_tests.jl")
include("derivative_tests.jl")

include(joinpath("..", "perf", "runbenchmarks.jl"))
include(joinpath(@__DIR__, "..", "perf", "runbenchmarks.jl"))

0 comments on commit 6720803

Please sign in to comment.