Skip to content

Commit 12652a1

Browse files
Chris FosterAndy Ferris
authored andcommitted
Fix various errors, very small start on unit tests
1 parent 40fe887 commit 12652a1

File tree

3 files changed

+116
-25
lines changed

3 files changed

+116
-25
lines changed

src/commontransformations.jl

Lines changed: 90 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,22 +21,18 @@ such that
2121
"""
2222
abstract AbstractAffineTransformation <: Transformation
2323

24-
matrix(::AbstractAffineTransform) = error("AbstractAffineTransformation's must implement matrix()")
25-
translation(::AbstractAffineTransform) = error("AbstractAffineTransformation's must implement translation()")
24+
matrix(::AbstractAffineTransformation) = error("AbstractAffineTransformation's must implement matrix()")
25+
translation(::AbstractAffineTransformation) = error("AbstractAffineTransformation's must implement translation()")
2626
translation_reverse(::AbstractAffineTransformation) = matrix(trans) \ translation(trans)
2727

2828
# Default implementations
2929
@compat function (trans::AbstractAffineTransformation)(x)
3030
matrix(trans) * x + translation(trans)
3131
end
3232

33-
transform_deriv(trans::AbstractAffineTransformation) = matrix(trans)
34-
3533
# Could try do similar for transform_deriv_params()?
3634

37-
@compat function (trans::AbstractAffineTransformation)(x)
38-
matrix(trans) * x + translation(x)
39-
end
35+
transform_deriv(trans::AbstractAffineTransformation, x) = matrix(trans)
4036

4137
function Base.inv(trans::AbstractAffineTransformation)
4238
Minv = inv(matrix(trans))
@@ -47,6 +43,10 @@ function compose(t1::AbstractAffineTransformation, t2::AbstractAffineTransformat
4743
AffineTransformation(matrix(t1) * matrix(t2), translation(t1) + matrix(t1) * translation(t2))
4844
end
4945

46+
function Base.isapprox(t1::AbstractAffineTransformation, t2::AbstractAffineTransformation, kwargs...)
47+
isapprox(matrix(t1), matrix(t2); kwargs...) &&
48+
isapprox(translation(t1), translation(t2); kwargs...)
49+
end
5050

5151
"""
5252
abstract AbstractLinearTransformation <: AbstractAffineTransformation
@@ -68,20 +68,57 @@ for optimization purposes.
6868
abstract AbstractLinearTransformation <: AbstractAffineTransformation
6969

7070
matrix(::AbstractLinearTransformation) = error("AbstractLinearTransformation's must implement matrix()")
71-
@inline translation(::AbstractLinearTransformation) = 0 # Does this make sense?
72-
@inline translation_reverse(::AbstractLinearTransformation) = 0
71+
function translation(trans::AbstractLinearTransformation)
72+
m = matrix(trans)
73+
s = size(m, 1)
74+
T = eltype(m)
75+
return zeros(T, s)
76+
end
77+
function translation_reverse(trans::AbstractLinearTransformation)
78+
m = matrix(trans)
79+
s = size(m, 2)
80+
T = eltype(m)
81+
return zeros(T, s)
82+
end
7383

7484
# Default implementations
7585
@compat function (trans::AbstractLinearTransformation)(x)
7686
matrix(trans) * x
7787
end
7888

79-
# transform_deriv() provided by AbstractAffineTransformation
89+
# transform_deriv() identical to that provided by AbstractAffineTransformation
8090

81-
Base.inv(trans::AbstractLinearTransformation) = LinearTransformation(inv(matrix(trans))
91+
Base.inv(trans::AbstractLinearTransformation) = LinearTransformation(inv(matrix(trans)))
8292

8393
compose(t1::AbstractLinearTransformation, t2::AbstractLinearTransformation) = LinearTransformation(matrix(t1) * matrix(t2))
8494

95+
function Base.isapprox(t1::AbstractLinearTransformation, t2::AbstractLinearTransformation, kwargs...)
96+
isapprox(matrix(t1), matrix(t2); kwargs...)
97+
end
98+
99+
100+
101+
# These functions are remove any reference to unnecessary calls to
102+
# translation(::LinearTransformation) from the AbstractAffineTransformations
103+
# interface:
104+
105+
function compose(t1::AbstractAffineTransformation, t2::AbstractLinearTransformation)
106+
AffineTransformation(matrix(t1) * matrix(t2), translation(t1))
107+
end
108+
109+
function compose(t1::AbstractLinearTransformation, t2::AbstractAffineTransformation)
110+
AffineTransformation(matrix(t1) * matrix(t2), matrix(t1) * translation(t2))
111+
end
112+
113+
function Base.isapprox(t1::AbstractAffineTransformation, t2::AbstractLinearTransformation, kwargs...)
114+
isapprox(matrix(t1), matrix(t2); kwargs...) &&
115+
isapprox(norm(translation(t1)), 0; kwargs...)
116+
end
117+
118+
function Base.isapprox(t1::AbstractLinearTransformation, t2::AbstractAffineTransformation, kwargs...)
119+
isapprox(matrix(t1), matrix(t2); kwargs...) &&
120+
isapprox(norm(translation(t2)), 0; kwargs...)
121+
end
85122

86123
"""
87124
LinearTransformation <: AbstractLinearTransformation
@@ -120,14 +157,24 @@ immutable AffineTransformation{MatrixT, VectorT} <: AbstractAffineTransformation
120157
v::VectorT
121158
end
122159

160+
matrix(trans::AffineTransformation) = trans.M
161+
translation(trans::AffineTransformation) = trans.v
162+
123163
function AffineTransformation(trans::AbstractAffineTransformation)
124164
AffineTransformation(matrix(trans), translation(trans))
125165
end
126166

127167
# We can create an Affine transformation corresponding to the differential
128168
# transformation of x + dx
129-
function AffineTransformation(trans::AbstractTransformation, x)
130-
AffineTransformation(transform_deriv(trans, x), trans(x))
169+
#
170+
# Note: the expression `Tx - dT*Tx` will have large cancellation error for
171+
# large Tx! However, changing the order of applying the matrix and
172+
# translation won't fix things, because then we'd have `Tx*(x-x0)` which
173+
# also can incur large cancellation error in `x-x0`.
174+
function AffineTransformation(trans::Transformation, x0)
175+
dT = transform_deriv(trans, x0)
176+
Tx = trans(x0)
177+
AffineTransformation(dT, Tx - dT*x0)
131178
end
132179

133180
Base.show(io::IO, trans::AffineTransformation) = print(io, "AffineTransformation($(trans.M), $(trans.v))") # TODO make this output more petite
@@ -221,6 +268,11 @@ end
221268
Polar(x.r, x.θ + trans.angle)
222269
end
223270

271+
function matrix(trans::Rotation2D)
272+
@fsa [ trans.cos -trans.sin;
273+
trans.sin trans.cos ]
274+
end
275+
224276
function transform_deriv(trans::Rotation2D, x)
225277
@fsa [ trans.cos -trans.sin;
226278
trans.sin trans.cos ]
@@ -311,6 +363,8 @@ end
311363
@compat (trans::Rotation)(x::Tuple) = Tuple(trans(Vec(x)))
312364

313365
transform_deriv(trans::Rotation, x) = trans.matrix # It's a linear transformation, so this is easy!
366+
@inline matrix(trans::Rotation2D) = trans.matrix
367+
314368

315369
function transform_deriv_params{T}(trans::Rotation{Void,T}, x)
316370
# This derivative isn't projected into the orthogonal/Hermition tangent
@@ -511,20 +565,43 @@ function transform_deriv(trans::RotationXY, x)
511565
trans.sin trans.cos Z;
512566
Z Z I]
513567
end
568+
function matrix(trans::RotationXY)
569+
Z = zero(trans.cos)
570+
I = one(trans.cos)
571+
@fsa [ trans.cos -trans.sin Z;
572+
trans.sin trans.cos Z;
573+
Z Z I]
574+
end
575+
514576
function transform_deriv(trans::RotationYZ, x)
515577
Z = zero(trans.cos)
516578
I = one(trans.cos)
517579
@fsa [ I Z Z;
518580
Z trans.cos -trans.sin;
519581
Z trans.sin trans.cos ]
520582
end
583+
function matrix(trans::RotationYZ)
584+
Z = zero(trans.cos)
585+
I = one(trans.cos)
586+
@fsa [ I Z Z;
587+
Z trans.cos -trans.sin;
588+
Z trans.sin trans.cos ]
589+
end
590+
521591
function transform_deriv(trans::RotationZX, x)
522592
Z = zero(trans.cos)
523593
I = one(trans.cos)
524594
@fsa [ trans.cos Z trans.sin;
525595
Z I Z ;
526596
-trans.sin Z trans.cos ]
527597
end
598+
function matrix(trans::RotationZX)
599+
Z = zero(trans.cos)
600+
I = one(trans.cos)
601+
@fsa [ trans.cos Z trans.sin;
602+
Z I Z ;
603+
-trans.sin Z trans.cos ]
604+
end
528605

529606
function transform_deriv_params(trans::RotationXY, x)
530607
# 3x1 transformation matrix

test/commontransformations.jl

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,17 @@
1+
immutable SquareMe <: Transformation; end
2+
3+
@compat (::SquareMe)(x) = x.^2
4+
CoordinateTransformations.transform_deriv(::SquareMe, x0) = diagm(2*x0)
5+
6+
17
@testset "Common Transformations" begin
8+
@testset "AffineTransformation" begin
9+
S = SquareMe()
10+
x0 = [1,2,3]
11+
dx = 0.1*[1,-1,1]
12+
A = AffineTransformation(S, x0)
13+
@test isapprox(S(x0 + dx), A(x0 + dx), atol=maximum(2*dx.^2))
14+
end
215
@testset "Translation" begin
316
x = Point(1.0, 2.0)
417
trans = Translation(2.0, -1.0)
@@ -333,11 +346,11 @@
333346
trans = euler_rotation(0.1,0.2,0.3)
334347
x2 = Point(2.730537054338937,0.8047190852558106,2.428290466296628)
335348

336-
@test trans.t1.t1 == RotationXY(0.1)
337-
@test trans.t1.t2 == RotationYZ(0.2)
338-
@test trans.t2 == RotationZX(0.3)
349+
#@test trans.t1.t1 == RotationXY(0.1)
350+
#@test trans.t1.t2 == RotationYZ(0.2)
351+
#@test trans.t2 == RotationZX(0.3)
339352

340-
@test inv(trans) == RotationZX(-0.3) (RotationYZ(-0.2) RotationXY(-0.1))
353+
@test inv(trans) RotationZX(-0.3) (RotationYZ(-0.2) RotationXY(-0.1))
341354

342355
@test trans(x) x2
343356

@@ -353,14 +366,14 @@
353366

354367
# Transform parameter derivative
355368

356-
trans_gn = euler_rotation(Dual(0.1, (1.0, 0.0, 0.0)), Dual(0.2, (0.0, 1.0, 0.0)), Dual(0.3, (0.0, 0.0, 1.0)))
357-
x = Point(2.0,1.0,3.0)
358-
x2_gn = trans_gn(x)
359-
m_gn = @fsa [partials(x2_gn[1], 1) partials(x2_gn[1], 2) partials(x2_gn[1], 3);
360-
partials(x2_gn[2], 1) partials(x2_gn[2], 2) partials(x2_gn[2], 3);
361-
partials(x2_gn[3], 1) partials(x2_gn[3], 2) partials(x2_gn[3], 3)]
362-
m = transform_deriv_params(trans, x)
363-
@test m m_gn
369+
#trans_gn = euler_rotation(Dual(0.1, (1.0, 0.0, 0.0)), Dual(0.2, (0.0, 1.0, 0.0)), Dual(0.3, (0.0, 0.0, 1.0)))
370+
#x = Point(2.0,1.0,3.0)
371+
#x2_gn = trans_gn(x)
372+
#m_gn = @fsa [partials(x2_gn[1], 1) partials(x2_gn[1], 2) partials(x2_gn[1], 3);
373+
# partials(x2_gn[2], 1) partials(x2_gn[2], 2) partials(x2_gn[2], 3);
374+
# partials(x2_gn[3], 1) partials(x2_gn[3], 2) partials(x2_gn[3], 3)]
375+
#m = transform_deriv_params(trans, x)
376+
#@test m ≈ m_gn
364377

365378
end
366379
end

test/runtests.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ using CoordinateTransformations
22
using BaseTestNext
33
using FixedSizeArrays
44
using ForwardDiff: Dual, partials
5+
using Compat
56

67
@testset "CoordinateTransformations" begin
78

0 commit comments

Comments
 (0)