artivis / manif Goto Github PK
View Code? Open in Web Editor NEWA small C++11 header-only library for Lie theory.
Home Page: https://artivis.github.io/manif
License: MIT License
A small C++11 header-only library for Lie theory.
Home Page: https://artivis.github.io/manif
License: MIT License
Hi, @joansola:
Thanks for your very detailed paper first !
How to calculate the jacobian of
the act
operation my be wrong throughout the library, this need to be double checked.
Moreover it need to be generalized somehow so that an element can act on e.g. point/vector/etc...
The following test is incorrect:
https://github.com/artivis/manif/blob/joss/CMakeLists.txt#L34
This is because this was only allowed by C++14:
https://isocpp.org/files/papers/N3652.html
Both clang and gcc fail this test with -std=c++11
I've posted a question in StackExchange. Can someone help me solve this problem?
Dear all,
I am working on an optimal control library which supports both native Eigen-types and manif-types, as well as optimal control on manifolds.
I am trying to make things as generic as possible, i.e. write my code such that Eigen-types and manif-types are interchangeable where possible.
One of the unfortunate obstacles in the way is that manif does not have a non-const getter for coeffs()
.
Do you see any major obstacles for adding such a feature?
Any thoughts and discussion on this would be highly appreciated.
Best!
We like to have the following API extension:
SO3Tangent::operator * (SO3Tangent, scalar)
as in
SO3Tangentd w;
SO3Tangentd wdt = w * dt;
also for other groups
The cmake
code:
FIND_PACKAGE(manif REQUIRED)
IF(manif_FOUND)
MESSAGE(STATUS "manif Library FOUND!")
MESSAGE(STATUS "manif_INCLUDE_DIRS=" ${manif_INCLUDE_DIRS})
ELSEIF(manif_FOUND)
MESSAGE(STATUS "manif Library NOT FOUND!")
ENDIF(manif_FOUND)
produces
-- manif Library FOUND!
-- manif_INCLUDE_DIRS=/usr/local/include/usr/local/include
where /usr/local/include
is appended twice! Then, the line
TARGET_INCLUDE_DIRECTORIES(${PROJECT_NAME} SYSTEM ${manif_INCLUDE_DIRS})
produces not surprisingly
CMake Error at CMakeLists.txt:529 (TARGET_INCLUDE_DIRECTORIES):
TARGET_INCLUDE_DIRECTORIES called with invalid arguments
I can grasp the basic idea of this passage. But the term "origin" confused me. It is the "origin" of the manifold, or that of the tangent vector space? And what is the "origin" of a manifold?
There's also an "origin" exists in the latter passage, which I assumed to mean "the time instant t = 0". Am I right?
Just out of curiousity: is there a reason why the method .isApprox() in the Tangent Base class does not have a default value for the tolerance?
If not, would it be an option to add a reasonable default tolerance?
I have trouble using Eigen::MatrixXs
as the Jacobians. They are of the correct size, but I guess manif expects these matrices to be of static size?
my example code:
void ProcessorOdom2D::deltaPlusDelta(const Eigen::VectorXs& _delta1, const Eigen::VectorXs& _delta2, const Scalar _Dt2,
Eigen::VectorXs& _delta1_plus_delta2, Eigen::MatrixXs& _jacobian1,
Eigen::MatrixXs& _jacobian2)
{
assert(_delta1.size() == delta_size_ && "Wrong _delta1 vector size");
assert(_delta2.size() == delta_size_ && "Wrong _delta2 vector size");
assert(_delta1_plus_delta2.size() == delta_size_ && "Wrong _delta1_plus_delta2 vector size");
assert(_jacobian1.rows() == delta_cov_size_ && "Wrong _jacobian1 size");
assert(_jacobian1.cols() == delta_cov_size_ && "Wrong _jacobian1 size");
assert(_jacobian2.rows() == delta_cov_size_ && "Wrong _jacobian2 size");
assert(_jacobian2.cols() == delta_cov_size_ && "Wrong _jacobian2 size");
// This is just a frame composition in 2D
SE2s delta1(_delta1(0), _delta1(1), _delta1(2));
SE2s delta2(_delta2(0), _delta2(1), _delta2(2));
// SE2s delta1_plus_delta2 = delta1.compose(delta2, _jacobian1, _jacobian2); // THIS FAILS
SE2s::Jacobian J_D_D1, J_D_D2;
SE2s delta1_plus_delta2 = delta1.compose(delta2, J_D_D1, J_D_D2); // THIS WORKS ...
_jacobian1 = J_D_D1; // ... BUT THEN I NEED A COPY HERE
_jacobian2 = J_D_D2;
_delta1_plus_delta2 << delta1_plus_delta2.x(), delta1_plus_delta2.y(), delta1_plus_delta2.angle();
}
The error msg when failing is:
/Users/jsola/dev/wolf_lib/core/src/processor/processor_odom_2D.cpp:82:38: error: no matching member function for call to 'compose'
SE2s delta1_plus_delta2 = delta1.compose(delta2, _jacobian1, _jacobian2); // THIS FAILS
~~~~~~~^~~~~~~
It might be beneficial to revive CppAD integration in manif
and make sure (tests) that it works fine.
As tangent elements are vectors after all, they should be assignable. This include also vector expressions. The following shoudl work.
Here, t
is a tangent element, u,v
are vectors, and K
is a matrix. Sizes are of course compatible.
// constructors and assignment
t(v);
v(t);
t = v;
v = t;
// unary expressions
t = -v;
v = -t;
// binary expressions
t = u+v;
t = K*v;
t = t + v;
t = K*t;
v = t + v;
v = K*t;
v = K*t+u;
In particular, I had to write this for it to work:
t = (K*v).eval();
which means that t=v
works, but that t=<vector expression>
does not work.
Dear all,
what do you think of introducing an Eigen-style transpose()
call for manif tangent types?
The context of the question is the same as in #137.
So far, I helped myself with introducing the following public method to my personal clone of manifs tangent_base.h
:
auto transpose() const {return coeffs().transpose();}
Note that it in fact returns the transpose of the underlying data type, i.e. the transpose of an Eigen-matrix.
I would like to hear your opinion regarding such a feature, and like to suggest that this could also be helpful for other users?
Best!
At the moment, the act
function treats its input argument as a point and act on it accordingly (e.g. SE2 rotates and translates). It would be great if act
could act appropriately on different objects, likely vectors and points at first.
This calls for a rethinking/redesign of the function with the following options:
enum
)struct assumePoint
)Pro:
Cons:
act
implementation is going to be a big switch
enum
for every new objectPro:
Cons:
Pro:
Cons:
class Point
)Pseudo-code for each options:
act( obj, Ja, Jb, flag )
act< flag >( obj, Ja, Jb )
act( Vector, Ja, Jb )
act( Point, Ja, Jb )
Dear all,
I would like to ask whether you would consider it meaningful to introduce the following operator for manif tangent-types, in order to allow direct access to single elements of the coefficient vector of the tangent objects.
I would suggest something along the lines of this
A trivial way to implement the const-version would be to include the following into tangent_base.h
Scalar operator()(int idx) const {return coeffs()(idx);}
Hi:
Great work. I'm working on optimization problem by using manif so I can solve the problem with Lie group.
But when I worked on autodiff in ceres solver by solving SE3 problem, I can't find the answer about write my own cost function while use your local parameterization functor, because I don't know the correct residual size according to your local parameterization functor.
Can you give me a hint or a sample ? It would be helpful.
Cheers.
This is a low priority issue.
I am wondering: manif could have the option of providing the left-Jacobians instead of the right-Jacobians. This would give extra power to interface it with other tools that might be using left- logic. This means all implementations that regard uncertainties in the global reference.
As a reminder:
For example, Delaert and Drummond typically use left operations. Also Ceres uses left-plus in the local parametrizations they ship with the library.
So Manif could easily adapt to these cases.
The option should be global I guess, something like:
manif::options::setRightJacobians()
or whatsoeverX.inverse(J, manif::LEFT_JAC)
--> ugly in my opinionI am reviewing openjournals/joss-reviews#1371 - couple of suggestions regarding the paper:
"The library is mathematically grounded in (Solà, Deray, & Atchuthan, 2018)" - perhaps better to write "Mathematical foundations of the library are given in" (or "Mathematical background ..." etc).
please fix references to Books and wave_geometry - they are not rendered correctly.
Manif uses random tangent space element and expMap to generate a random Lie group element:
setRandom coeffs_nonconst() = Tangent::Random().exp().coeffs()
This is not a good idea. Because uniform distribution of tangent space may not lead to uniform distribution of Lie group.
I used the following code to test the Random() function in SO(3) by generating 10000 random elements:
// generate_so3_random_elements.cpp
#include "manif/SO3.h"
#include <vector>
#include <iostream>
#include <fstream>
#include <Eigen/Dense>
using namespace manif;
using namespace std;
int main(int /*argc*/, char ** /*argv*/)
{
ofstream file;
file.open("SO3Randomization.txt");
for (int i = 0; i < 10000; ++i)
{
SO3d X = SO3d::Random();
file << X.coeffs().transpose() << endl;
}
file.close();
return 0;
}
and plotted the axis distribution (on a unit sphere) and angle distribution (with a histogram) in Matlab:
%% plot_so3_distribution.m
clear; clc; close all;
qua = importdata('SO3Randomization.txt');
axang_arr = quat2axang(qua);
figure(1)
plot3(axang_arr(:,1), axang_arr(:,2), axang_arr(:,3), '.');
figure(2)
hist(axang_arr(:,4),100);
The Random() function cannot generate uniformly distributed SO3 elements.
Hi guys,
Just to let you know, I think there is a typo in Table 1 in the paper. In the Exp(T) matrix of SE(3), there should be a 1 instead of a 0 in the bottom right side.
Anyway, thanks for this great work!
Cheers
Thanks for this work.
Could you add a bit more explanation to 'a note on jacobians' section in the readme?
For example, how should one use manif with ceres correctly.
Related #33
Dear all,
I am using manif in a catkin (ROS) workspace and encounter the following issue:
When building using catkin build
, manif creates a package.xml file in <path_to_ws>/devel/share/manif
Creating a package.xml in the devel folders leads ROS to "believe" that there is a ROS package in devel with the same package name as the orginal package in the src folder. This triggers errors in some ROS tools, in particular rosdep install
. Normally ROS packages do not have a package.xml in their devel folder after build, which leads me to believe that this is a manif problem.
Is that package.xml in the devel folder used, or maybe just legacy?
Dear all,
I am wondering whether manif should adopt the (anti) aliasing helper functions native to Eigen.
In particular, I believe that Eigens .eval()
and .noalias()
could be relevant and attractive for manif. For instance, in my applications, this helps to greatly reduce the number of temporary expressions and therefore increases speed!
After removing it cmake correctly finds eigen (installed in /usr/local/include)
I want to use it in some application. But I don't how to use Lie theory library. I can write the code. But I have no idea to do it.
Can you help me?
Thanks!
The library is header-only. This means that there is nothing to build at installation time.
The documentation suggests running make
after cmake
, but unless we are building the tests and examples, this is pointless.
Morever, the build instructions do not indicate a make install
step. This is necessary so that manif will be found according to the instructions in the "Use Manif in your project" section of the Readme.
Thanks for this work.
We are considering using manif in our EKF implementation that constantly updates the rotation estimate (SO3) with angular velocity updates stored in Lie algebra. It is working on our own simple LieAlgebra library but it crashes after several iterations when using manif. Minimal code that reproduces the error:
// Identity
manif::SO3d R = manif::SO3d(0, 0, 0, 1.0);
// Some angular velocity
manif::SO3Tangentd Om = Eigen::Vector3d(0.001, 0.0, 0.0);
// New orientation
for (int i = 0 ; i < 1000; i++) {
std::cout << i << std::endl;
R = R.plus(Om);
}
I guess it is related to pull request #72 and I understand your arguments but as for now I think it is necessary to perform R.normalize() after every change to make sure it is still a proper quaternion. Maybe it should be added to the examples concerning EKF/optimization?
lieli
reads lili
- LIE LIbrarylilly
- LIe aLgebra LibrarYlialle
- LIe ALgebra Lirary for state Estimationcerise
- miCro liE algebRa lIbrary for State Estimationmerit
- Micro liE algebRa lIbrary for state esTimationDear all,
I'm an application which takes an "manif" manifold as a template parameter. This works nicely, since the basic interface, accessors and methods are naturally the same for all manifolds.
However, it fails as soon as I want to operate in Euclidean space. What is missing, is essentially a manif-implementation of the must fundamental n-dimensional Euclidean manifold E(n), in which case anything within manif should fall back to the natural Eigen-types and methods.
Is there any plan to add such a feature?
Best, and thanks in advance!
Start with a CI job
This is a first attempt. Derived classes must implement all methods:
template <Size vector_size; Size manifold_size>
class manifold {
typedef Matrix<Scalar, vector_size, 1> VectorType;
typedef Matrix<Scalar, manifold_size, 1> ManifoldType;
typedef Matrix<Scalar, vector_size, vector_size> JacobianType;
// First, a bunch of static methods:
// lift and retract
static VectorType lift(ManifoldType);
static ManifoldType retract(VectorType);
// inverse and compose
static ManifoldType inverse(ManifoldType);
static ManifoldType compose(ManifoldType m1, ManifoldType m2);
static ManifoldType between(ManifoldType m1, ManifoldType m2);
// right plus and minus
static ManifoldType rplus(ManifoldType, VectorType);
static VectorType rminus(Manifoldtype, ManifoldType);
// left plus and minus
static ManifoldType lplus(VectorType, ManifoldType);
static VectorType lminus(Manifoldtype, ManifoldType);
// left and right Jacobians
static JacobianType Jr(VectorType);
static JacobianType Jr_inv(VectorType);
static JacobianType Jl(VectorType);
static JacobianType Jl_inv(VectorType);
// Basic Jacobians
static JacobianType inverse_jac(ManifoldType);
static JacobianType compose_jac_m1(ManifoldType m1, ManifoldType m2);
static JacobianType compose_jac_m2(ManifoldType m1, ManifoldType m2);
// Other Jacobians might be added
// Action of the manifold on vectors
static VectorType operator * (ManifoldType, VectorType)
// other operations might be added
// then actions applied on objects
ManifoldType inverse();
ManifoldType rplus(VectorType);
ManifoldType lplus(VectorType);
VectorType rminus(ManifoldType);
// etc, replicate most of the statics, but using the manifold object as the first input param
First of all, thank you for this great repository!
I would like to make a feature request for adding an additional Lie group
This can be useful in some applications using inertial measurement units. Please see, Associating Uncertainty to Extended Poses for on Lie Group IMU Preintegration with Rotating Earth, where the orientation, position and linear velocity (with the frame located in the origin of the body and the orientation same as the inertial frame) can be packed into a single Lie group.
Similarly. a possible extension could be towards a generic
@artivis Do you think it would be meaningful to have these Lie groups added to the repository?
I've made an initial implementation for
However, there is a missing implementation for the action of this Lie group on a vector, act()
method. It was not clear to me about how this operation might work.
Let me know what you think about this. If you agree, I can maybe open a PR. Thank you!
Hi all, I'm trying to build manif
on VisualStudio2019
. When I configure the cmake project I get the following error:
Selecting Windows SDK version 10.0.18362.0 to target Windows 10.0.17134.
The CXX compiler identification is MSVC 19.26.28806.0
Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Enterprise/VC/Tools/MSVC/14.26.28801/bin/Hostx64/x64/cl.exe
Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio/2019/Enterprise/VC/Tools/MSVC/14.26.28801/bin/Hostx64/x64/cl.exe -- works
Detecting CXX compiler ABI info
Detecting CXX compiler ABI info - done
Detecting CXX compile features
Detecting CXX compile features - done
Performing Test COMPILER_SUPPORTS_CXX11
Performing Test COMPILER_SUPPORTS_CXX11 - Failed
CMake Error at CMakeLists.txt:15 (message):
The compiler C:/Program Files (x86)/Microsoft Visual
Studio/2019/Enterprise/VC/Tools/MSVC/14.26.28801/bin/Hostx64/x64/cl.exe has
no C++11 support. Please use a different C++ compiler.
Configuring incomplete, errors occurred!
See also "C:/Users/gromualdi/robot-code/manif/build/CMakeFiles/CMakeOutput.log".
See also "C:/Users/gromualdi/robot-code/manif/build/CMakeFiles/CMakeError.log".
Associated issue: GiulioRomualdi/lie-group-controllers#1 (comment)
Hi guys,
Thanks for sharing this work!
I just wanted to let you know that there is a typo about V(θ) in Appendix D. The V(θ) (Eq.174) does not match the left Jacobian of SO(3) (Eq. 145), it misses the powers' values on the denominators.
Cheers,
Maxime
Hi, thanks for your work!
In your example se2_sam.cpp
(or se3_sam.cpp
), for the prior measurement, the residual is:
r=poses[0].log()
, so I think the jacobian is:
let t = Log(poses[0])
,
$ J = \partial Log(poses[0]) / \partial poses[0] = J_r^{-1}(t) $
so this line:
J.block<DoF, DoF>(row, col) = MatrixT::Identity();
should be:
J.block<DoF, DoF>(row, col) = poses[0].log().rjacinv();
.
How do you think?
Since manif is based on Eigen, compiling manif programs also require finding Eigen. I recommend that something like the following be added to the README:
find_package (Eigen3 REQUIRED)
target_include_directories(${PROJECT_NAME} SYSTEM PUBLIC ${EIGEN3_INCLUDE_DIRS})
SO2 -> SO2d.
In struct traits<SO2<_Scalar>> in SO2.h
...
using Vector = Eigen::Matrix<Scalar, DoF, 1>;
Should the 'DoF' be 'Dim'?
The DoF of SO2 is 1, but the dimension of the Vector SO2 act on is 2.
In several developments it is handy to consider composite manifolds, such as T3xSO3 instead of SE3, or the IMU implementation using T3xT3xSO3.
In the paper, a notation is introduced so as to be able to define, for composite manifolds, the full family of operators: composition, inverse, exp, log, plus and minus, mainly. It is also possible to produce the Jacobians as a block-concatenation of the jacobians of each individual group.
It'd be very interesting if we could create a (probably variadic templated) way of producing composites of any number of groups, and then have the API ready to manipulate them as a single group.
This is probably not trivial to do.
If I'm reading this right,
https://cmake.org/cmake/help/v3.0/command/target_include_directories.html
this line in the readme
target_include_directories(${PROJECT_NAME} SYSTEM ${manif_INCLUDE_DIRS})
should probably be something like
target_include_directories(${PROJECT_NAME} SYSTEM PUBLIC ${manif_INCLUDE_DIRS})
Without the PUBLIC
directive I get
CMake Error at CMakeLists.txt:7 (target_include_directories):
target_include_directories called with invalid arguments
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.