Skip to content

Commit eadcb8c

Browse files
committed
Pull in docs index.md from README.md
1 parent 2294ce4 commit eadcb8c

File tree

1 file changed

+219
-1
lines changed

1 file changed

+219
-1
lines changed

docs/src/index.md

Lines changed: 219 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,219 @@
1-
# CoordinateTransformations.jl
1+
```@meta
2+
DocTestSetup = quote
3+
using CoordinateTransformations
4+
end
5+
```
6+
# CoordinateTransformations
7+
8+
[![Build Status](https://github.com/JuliaGeometry/CoordinateTransformations.jl/workflows/CI/badge.svg)](https://github.com/JuliaGeometry/CoordinateTransformations.jl/actions?query=workflow%3ACI)
9+
10+
**CoordinateTransformations** is a Julia package to manage simple or complex
11+
networks of coordinate system transformations. Transformations can be easily
12+
applied, inverted, composed, and differentiated (both with respect to the
13+
input coordinates and with respect to transformation parameters such as rotation
14+
angle). Transformations are designed to be light-weight and efficient enough
15+
for, e.g., real-time graphical applications, while support for both explicit
16+
and automatic differentiation makes it easy to perform optimization and
17+
therefore ideal for computer vision applications such as SLAM (simultaneous
18+
localization and mapping).
19+
20+
The package provide two main pieces of functionality
21+
22+
1. Primarily, an interface for defining `Transformation`s and applying
23+
(by calling), inverting (`inv()`), composing (`` or `compose()`) and
24+
differentiating (`transform_deriv()` and `transform_deriv_params()`) them.
25+
26+
2. A small set of built-in, composable, primitive transformations for
27+
transforming 2D and 3D points (optionally leveraging the *StaticArrays*
28+
and *Rotations* packages).
29+
30+
## Quick start
31+
32+
Let's translate a 3D point:
33+
```julia
34+
using CoordinateTransformations, Rotations, StaticArrays
35+
36+
x = SVector(1.0, 2.0, 3.0) # SVector is provided by StaticArrays.jl
37+
trans = Translation(3.5, 1.5, 0.0)
38+
39+
y = trans(x)
40+
```
41+
42+
We can either apply different transformations in turn,
43+
```julia
44+
rot = LinearMap(RotX(0.3)) # Rotate 0.3 radians about X-axis, from Rotations.jl
45+
46+
z = trans(rot(x))
47+
```
48+
or build a composed transformation using the `` operator (accessible at the
49+
REPL by typing `\circ` then tab):
50+
```julia
51+
composed = trans rot # alternatively, use compose(trans, rot)
52+
53+
composed(x) == z
54+
```
55+
A composition of a `Translation` and a `LinearMap` results in an `AffineMap`.
56+
57+
We can invert the transformation:
58+
```julia
59+
composed_inv = inv(composed)
60+
61+
composed_inv(z) == x
62+
```
63+
64+
For any transformation, we can shift the origin to a new point using `recenter`:
65+
```julia
66+
rot_around_x = recenter(rot, x)
67+
```
68+
Now `rot_around_x` is a rotation around the point `x = SVector(1.0, 2.0, 3.0)`.
69+
70+
71+
Finally, we can construct a matrix describing how the components of `z`
72+
differentiates with respect to components of `x`:
73+
```julia
74+
# In general, the transform may be non-linear, and thus we require
75+
# the value of x to compute the derivative
76+
∂z_∂x = transform_deriv(composed, x)
77+
```
78+
79+
Or perhaps we want to know how `y` will change with respect to changes of
80+
to the translation parameters:
81+
```julia
82+
∂y_∂θ = transform_deriv_params(trans, x)
83+
```
84+
85+
## Interface
86+
87+
Transformations are derived from `Transformation`. As an example, we have
88+
`Translation{T} <: Transformation`. A `Translation` will accept and translate
89+
points in a variety of formats, such as `Vector` or `SVector`, but in general
90+
your custom-defined `Transformation`s could transform any Julia object.
91+
92+
Transformations can be reversed using `inv(trans)`. They can be chained
93+
together using the `` operator (`trans1 ∘ trans2`) or `compose` function (`compose(trans1, trans2)`).
94+
In this case, `trans2` is applied first to the data, before `trans1`.
95+
Composition may be intelligent, for instance by precomputing a new `Translation`
96+
by summing the elements of two existing `Translation`s, and yet other
97+
transformations may compose to the `IdentityTransformation`. But by default,
98+
composition will result in a `ComposedTransformation` object which simply
99+
dispatches to apply the transformations in the correct order.
100+
101+
Finally, the matrix describing how differentials propagate through a transform
102+
can be calculated with the `transform_deriv(trans, x)` method. The derivatives
103+
of how the output depends on the transformation parameters is accessed via
104+
`transform_deriv_params(trans, x)`. Users currently have to overload these methods,
105+
as no fall-back automatic differentiation is currently included. Alternatively,
106+
all the built-in types and transformations are compatible with automatic differentiation
107+
techniques, and can be parameterized by *DualNumbers*' `DualNumber` or *ForwardDiff*'s `Dual`.
108+
109+
## Built-in transformations
110+
111+
A small number of 2D and 3D coordinate systems and transformations are included.
112+
We also have `IdentityTransformation` and `ComposedTransformation`, which allows us
113+
to nest together arbitrary transformations to create a complex yet efficient
114+
transformation chain.
115+
116+
### Coordinate types
117+
118+
The package accepts any `AbstractVector` type for Cartesian coordinates. For speed, we recommend
119+
using a statically-sized container such as `SVector{N}` from *StaticArrays*.
120+
121+
We do provide a few specialist coordinate types. The `Polar(r, θ)` type is a 2D
122+
polar representation of a point, and similarly in 3D we have defined
123+
`Spherical(r, θ, ϕ)` and `Cylindrical(r, θ, z)`.
124+
125+
### Coordinate system transformations
126+
127+
Two-dimensional coordinates may be converted using these parameterless (singleton)
128+
transformations:
129+
130+
1. [`PolarFromCartesian()`](@ref)
131+
2. [`CartesianFromPolar()`](@ref)
132+
133+
Three-dimensional coordinates may be converted using these parameterless
134+
transformations:
135+
136+
1. [`SphericalFromCartesian()`](@ref)
137+
2. [`CartesianFromSpherical()`](@ref)
138+
3. [`SphericalFromCylindrical()`](@ref)
139+
4. [`CylindricalFromSpherical()`](@ref)
140+
5. [`CartesianFromCylindrical()`](@ref)
141+
6. [`CylindricalFromCartesian()`](@ref)
142+
143+
However, you may find it simpler to use the convenience constructors like
144+
`Polar(SVector(1.0, 2.0))`.
145+
146+
### Translations
147+
148+
Translations can be be applied to Cartesian coordinates in arbitrary dimensions,
149+
by e.g. `Translation(Δx, Δy)` or `Translation(Δx, Δy, Δz)` in 2D/3D, or by
150+
`Translation(Δv)` in general (with `Δv` an `AbstractVector`). Compositions of
151+
two `Translation`s will intelligently create a new `Translation` by adding the
152+
translation vectors.
153+
154+
### Linear transformations
155+
156+
Linear transformations (a.k.a. linear maps), including rotations, can be
157+
encapsulated in the `LinearMap` type, which is a simple wrapper of an
158+
`AbstractMatrix`.
159+
160+
You are able to provide any matrix of your choosing, but your choice of type
161+
will have a large effect on speed. For instance, if you know the dimensionality
162+
of your points (e.g. 2D or 3D) you might consider a statically sized matrix
163+
like `SMatrix` from *StaticArrays.jl*. We recommend performing 3D rotations
164+
using those from *Rotations.jl* for their speed and flexibility. Scaling will
165+
be efficient with Julia's built-in `UniformScaling`. Also note that compositions
166+
of two `LinearMap`s will intelligently create a new `LinearMap` by multiplying
167+
the transformation matrices.
168+
169+
### Affine maps
170+
171+
An Affine map encapsulates a more general set of transformation which are
172+
defined by a composition of a translation and a linear transformation. An
173+
`AffineMap` is constructed from an `AbstractVector` translation `v` and an
174+
`AbstractMatrix` linear transformation `M`. It will perform the mapping
175+
`x -> M*x + v`, but the order of addition and multiplication will be more obvious
176+
(and controllable) if you construct it from a composition of a linear map
177+
and a translation, e.g. `Translation(v) ∘ LinearMap(v)` (or any combination of
178+
`LinearMap`, `Translation` and `AffineMap`).
179+
180+
`AffineMap`s can be constructed to fit point pairs `from_points => to_points`:
181+
182+
```jldoctest
183+
julia> from_points = [[0, 0], [1, 0], [0, 1]];
184+
185+
julia> to_points = [[1, 1], [3, 1], [1.5, 3]];
186+
187+
julia> AffineMap(from_points => to_points)
188+
AffineMap([1.9999999999999996 0.5; -5.551115123125783e-16 2.0], [0.9999999999999999, 1.0000000000000002])
189+
```
190+
191+
The points can be supplied as a collection of vectors or as a matrix with points as columns.
192+
193+
### Perspective transformations
194+
195+
The perspective transformation maps real-space coordinates to those on a virtual
196+
"screen" of one lesser dimension. For instance, this process is used to render
197+
3D scenes to 2D images in computer generated graphics and games. It is an ideal
198+
model of how a pinhole camera operates and is a good approximation of the modern
199+
photography process.
200+
201+
The `PerspectiveMap()` command creates a `Transformation` to perform the
202+
projective mapping. It can be applied individually, but is particularly
203+
powerful when composed with an `AffineMap` containing the position and
204+
orientation of the camera in your scene. For example, to transfer `points` in 3D
205+
space to 2D `screen_points` giving their projected locations on a virtual camera
206+
image, you might use the following code:
207+
208+
```julia
209+
cam_transform = PerspectiveMap() inv(AffineMap(cam_rotation, cam_position))
210+
screen_points = map(cam_transform, points)
211+
```
212+
213+
There is also a `cameramap()` convenience function that can create a composed
214+
transformation that includes the intrinsic scaling (e.g. focal length and pixel
215+
size) and offset (defining which pixel is labeled `(0,0)`) of an imaging system.
216+
217+
## Acknowledgements
218+
219+
- The [Fugro Roames organization](https://github.com/FugroRoames)

0 commit comments

Comments
 (0)