Skip to content

Commit eabc2ae

Browse files
committed
Add README.md
1 parent 76ae770 commit eabc2ae

File tree

1 file changed

+167
-0
lines changed

1 file changed

+167
-0
lines changed

README.md

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
2+
# A manifold geometry library for robotics
3+
4+
**wave_geometry** is a header-only C++ library for working with rotations and transformations in robotics and computer vision applications. It differs from similar libraries by offering:
5+
6+
* Fast operations using expression templates
7+
* Fast on-manifold automatic differentiation
8+
* Compile-time coordinate frame semantics checking
9+
10+
The code is available under the [MIT License](LICENSE).
11+
12+
## Features
13+
14+
### Manifold operations
15+
16+
`wave_geometry` includes operations on SO(3), the Lie group of 3D rotations, and SE(3), the group of 3D rigid transformations.
17+
18+
#### Supported operations
19+
20+
| Operation | | Code |
21+
| :--- | :---: | :---: |
22+
| Sum | <img src="https://latex.codecogs.com/png.latex?\mathbf{v}&plus;\mathbf{v}" title="\mathbf{v}+\mathbf{v}" /> | `v + v` |
23+
| Difference | <img src="https://latex.codecogs.com/png.latex?\mathbf{v}-\mathbf{v}" title="\mathbf{v}-\mathbf{v}" /> | `v - v` |
24+
| Negative | <img src="https://latex.codecogs.com/png.latex?-\mathbf&space;v" title="-\mathbf v" /> | `-v` |
25+
| Composition | <img src="https://latex.codecogs.com/png.latex?\mathbf&space;\Phi&space;\circ&space;\mathbf&space;\Phi" title="\mathbf \Phi \circ \mathbf \Phi" /> | `R * R` |
26+
| Inverse | <img src="https://latex.codecogs.com/png.latex?\mathbf&space;\Phi^{-1}" title="\mathbf \Phi^{-1}" /> | `inverse(R)` |
27+
| Coordinate map | <img src="https://latex.codecogs.com/png.latex?\mathbf&space;\Phi&space;(\mathbf&space;p)" title="\mathbf \Phi (\mathbf p)" /> | `R * p` |
28+
| Exponential map | <img src="https://latex.codecogs.com/png.latex?\exp(\mathbf\varphi)" title="\exp(\mathbf \varphi)" /> | `exp(w)` |
29+
| Logarithmic map | <img src="https://latex.codecogs.com/png.latex?\log(\mathbf&space;\Phi)" title="\log(\mathbf \Phi)" /> | `log(R)` |
30+
| Manifold plus | <img src="https://latex.codecogs.com/png.latex?\mathbf\Phi\boxplus\mathbf\varphi=\exp(\mathbf\varphi)\circ\mathbf\Phi" title="\mathbf\Phi \boxplus \mathbf\varphi = \exp(\mathbf\varphi) \circ \mathbf\Phi" /> | `R + w` |
31+
| Manifold minus | <img src="https://latex.codecogs.com/png.latex?\mathbf\Phi_1\boxminus\mathbf\Phi_2=\log(\mathbf\Phi_1\circ\mathbf\Phi_2^{-1})" title="\mathbf\Phi_1 \boxminus \mathbf\Phi_2 = \log(\mathbf\Phi_1 \circ \mathbf\Phi_2^{-1})" /> | `R - R` |
32+
33+
Above, <img src="https://latex.codecogs.com/png.latex?\mathbf\Phi" alt="Phi" /> or `R` represents a Lie group element, <img src="https://latex.codecogs.com/png.latex?\mathbf\varphi" alt="small phi" /> or `w` represents a Lie algebra element, <img src="https://latex.codecogs.com/png.latex?\mathbf{p}" alt="p" /> or `p` represents a translation, and <img src="https://latex.codecogs.com/png.latex?\mathbf{v}" alt="v" /> or `v` represents any element of R^3, so(3) or se(3).
34+
35+
### Automatic differentiation
36+
37+
Any expression can be differentiated with respect to its variables:
38+
39+
```cpp
40+
wave::RotationMd R = wave::RotationMd::Random();
41+
wave::Translationd p1 = wave::Translationd::Random();
42+
wave::Translationd p2 = R * p1;
43+
Eigen::Matrix3d J_p2_wrt_R = (R * p1).jacobian(R);
44+
```
45+
46+
Above, `J_p2_wrt_R` is the 3x3 Jacobian of `p2 = R * p1` with respect to small changes in `R`. `wave_geometry` computes *local Jacobians*, which are independent of the choice of parametrization for `R` (e.g., rotation matrix or quaternion), and are useful for on-manifold parametrization.
47+
48+
It is possible (and more efficient) to combine evaluation and multiple Jacobian calculations:
49+
50+
```cpp
51+
// Using C++17
52+
auto [p2, J_p2_wrt_R, J_p2_wrt_p1] = (R * p1).evalWithJacobians(R, p1);
53+
54+
// Or, using C++11
55+
wave::Translationd p2;
56+
Eigen::Matrix3d J_p2_wrt_R, J_p2_wrt_p1;
57+
std::tie(p2, J_p2_wrt_R, J_p2_wrt_p1) = (R * p1).evalWithJacobians(R, p1);
58+
```
59+
60+
We can also get all Jacobians at once by providing no arguments:
61+
62+
```cpp
63+
auto [p2, J_p2_wrt_R, J_p2_wrt_p1] = (R * p1).evalWithJacobians();
64+
```
65+
66+
Currently, the call `.evalWithJacobians(R, p1)` uses forward-mode automatic differentiation while `.evalWithJacobians()` uses reverse mode; however, future versions of `wave_geometry` may simply choose the fastest mode for the arguments given.
67+
68+
`wave_geometry`'s expression template-based autodiff algorithm produces efficient code which runs nearly as fast as (or in some cases, just as fast as) hand-optimized code for manually-derived derivatives.
69+
70+
## Coordinate frame semantics
71+
72+
Representing poses without confusion is notoriously difficult, and mistakes such as using a quantity expressed in the wrong coordinate frame have bogged down many a robotics project. `wave_geometry` provides built-in coordinate frame semantics checking. It extends [Furgale's recommended notation](http://paulfurgale.info/news/2014/6/9/representing-robot-pose-the-good-the-bad-and-the-ugly) by putting semantic information into the language type system.
73+
74+
Some examples:
75+
76+
| In math | In English | In wave_geometry |
77+
| :--- | :--- | :--- |
78+
| <img src="https://latex.codecogs.com/png.latex?{}_A\mathbf{p}_{BC}" title="{}_A\mathbf{p}_{BC}" /> | The vector from frame B to frame C, expressed in frame A | `Framed<Translationd, A, B, C>` or `TranslationFd<A, B, C>`|
79+
| <img src="https://latex.codecogs.com/png.latex?{}_A\mathbf\omega_{BC}" title="{}_A\mathbf\omega_{BC}" /> | The angular velocity of frame C with respect to frame B, expressed in frame A | `Framed<RelativeRotatiod, A, B, C> ` or `RelativeRotationFd<A, B, C>` |
80+
| <img src="https://latex.codecogs.com/png.latex?\mathbf{R}_{AB}" title="\mathbf{R}_{AB}" /> | The rotation between frame A and frame B, such that <img src="https://latex.codecogs.com/png.latex?{}_A\mathbf{p}_{BC}={}\mathbf{R}_{AB}({}_B\mathbf{p}_{BC})" title="{}_A\mathbf{p}_{BC}={}\mathbf{R}_{AB}({}_B\mathbf{p}_{BC})" /> | `Framed<RotationMd, A, B>` or `RotationMFd<A, B>` |
81+
82+
Here, `A`, `B` and `C` are types which do nothing but represent a coordinate frame; more descriptive names can be used if desired.
83+
84+
Coordinate frame semantics checking can detect invalid operations *at compile time*. Consider this code:
85+
```cpp
86+
struct BodyFrame;
87+
struct CameraFrame;
88+
struct WorldFrame;
89+
90+
wave::RotationMFd<WorldFrame, BodyFrame> r1;
91+
wave::RotationMFd<CameraFrame, WorldFrame> r2;
92+
93+
// Let's get the rotation between World and Camera (maybe)
94+
wave::RotationMFd<WorldFrame, CameraFrame> result = r1 * r2;
95+
```
96+
This code has a mistake, but is saved by semantics checking. When we try to compile it, we get the following error message (from clang 5, not showing colours):
97+
```
98+
In file included from /.../example.cpp:1:
99+
In file included from /.../wave/geometry/geometry.hpp:45:
100+
/.../wave/geometry/src/geometry/op/Compose.hpp:22:5: error: static_assert failed "Adjacent frames do not match"
101+
static_assert(std::is_same<RightFrameOf<Lhs>, LeftFrameOf<Rhs>>(),
102+
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
103+
/.../example.cpp:31:60: note: in instantiation of template class 'wave::Compose<wave::Framed<wave::MatrixRotation<Eigen::Matrix<double, 3, 3, 0, 3, 3> >, WorldFrame, BodyFrame>, wave::Framed<wave::MatrixRotation<Eigen::Matrix<double, 3, 3, 0, 3, 3> >, CameraFrame, WorldFrame> >' requested here
104+
wave::RotationMFd<WorldFrame, CameraFrame> result = r1 * r2;
105+
^
106+
```
107+
108+
The corrected code compiles successfully.
109+
```
110+
// Let's get the rotation between World and Camera (fixed)
111+
wave::RotationMFd<WorldFrame, CameraFrame> result = r1 * inverse(r2);
112+
```
113+
114+
In addition to making code safer and more readable, using coordinate frame semantics actually makes `wave_geometry`'s autodiff faster by providing extra type information.
115+
116+
117+
### Supported parametrizations
118+
| Group | Parametrization | Class template | Alias for `double` as scalar |
119+
| :--- | :--- | :--- | :--- |
120+
| SO(3) rotation | 3x3 Matrix | `MatrixRotation<T>` | `RotationMd` |
121+
| | Quaternion | `QuaternionRotation<T>` | `RotationQd` |
122+
| | Angle-axis | `AngleAxisRotation<T>` | `RotationAd` |
123+
| SE(3) transformation | 4x4 homogeneous matrix |`MatrixRigidTransform<T>`| `RigidTransformMd` |
124+
| | 7-vector (quaternion + translation) | `CompactRigidTransform` | `RigidTransformQd` |
125+
| R^3 translation | 3-vector | `Translation<T>` | `Translationd` |
126+
| so(3) diff. rotation | 3-vector | `RelativeRotation<T>` | `RelativeRotationd` |
127+
| se(3) diff. transformation | 6-vector (angular + linear) | `Twist<T>` | `Twistd` |
128+
129+
Note the template parameter `<T>` is not a scalar type, but the full type of the underlying Eigen class (for example, `Eigen::Vector3d` or `Map<Matrix<double, 3, 3, RowMajor>>`). Thus `wave_geometry` classes easily work with arbitrary Eigen Maps, memory layouts, and block expressions.
130+
131+
Quaternions use the conventions of `Eigen::Quaternion`: Hamilton product, storage order `x,y,z,w` (despite different order in the constructor), and homomorphic quaternion-matrix conversion: `C(q1)*C(q2) = C(q1*q2)`.
132+
133+
134+
## How to install
135+
136+
`wave_geometry` is a header-only library, meaning no compilation is required to use it in your project. Put the `include` directory into your compiler's search path, and write
137+
138+
```
139+
#include <wave/geometry/geometry.hpp>
140+
```
141+
142+
CMake install and link commands will be added soon.
143+
144+
### Dependencies
145+
146+
`wave_geometry` requires:
147+
* an existing installation of [Eigen](http://eigen.tuxfamily.org) 3.3-beta2 or above
148+
* an existing installation of Boost (only the header-only Optional library is used)
149+
* a compiler supporting C++11
150+
151+
### Development status
152+
153+
`wave_geometry` is in the initial development stage and the API may change at any time.
154+
155+
156+
## More information
157+
The library is described in a conference paper:
158+
```
159+
@inproceedings{koppel2018manifold,
160+
title={Manifold Geometry with Fast Automatic Derivatives and Coordinate Frame Semantics Checking in {C++}},
161+
author={Koppel, Leonid and Waslander, Steven L.},
162+
booktitle={15th Conference on Computer and Robot Vision (CRV)},
163+
year={2018},
164+
note = {to be published}
165+
}
166+
```
167+

0 commit comments

Comments
 (0)