总结工程实践常用的Eigen库应用,持续更新…
1. Combining multiple transformations in Eigen into one transformation matrix
Q: I have several transformations in Eigen, in the form of translations (Eigen::Vector3f
) and rotations (Eigen::Quaternionf
). I would like to combine all these transformations, in an order of my choosing, into a 4x4 transformation matrix Eigen::Matrix4f
.
For example, I would like to apply the following transformations in the order A, B, C, D, E:
1 | Eigen::Vector3f translation_A; |
A:
1 | Eigen::Vector3f trans_vec_A; |
Note that
1 | combined = A*B*C*D*E |
so combined
applied to a vector v
is
1 | combined*v = A*B*C*D*E*v = A*(B*(C*(D*(E*v)))) |
that is, E
is applied first, then D
, and so on. In my mind, this is the correct order, but that may be a matter of taste.
then apply pcl::transformPointCloud(*src_pointcloud, *dst_pointcloud, combined);
2. Cast Eigen::MatrixXd to Eigen::MatrixXf
*Q: *I am using Eigen on a C++ program.
I wonder if there is a way to cast from Eigen::MatrixXd
to Eigen::MatrixXf
.static_cast <Eigen::MatrixXf>
doesn’t seem to work and neither A.cast<MatrixXf>
(this is the cast method from Eigen).
Any solution for this type of cast?
*A: *Try this:
1 | Eigen::MatrixXd d; // Matrix of doubles. |
3. template function casting
*Q: *I’m having trouble multiplying two matrices using the Eigen library. I have the following function. Here is a small example of what I would like to do :
Program name: testMatOp.cpp
1 |
|
I would like to pass Matrix A and Vector B to multiply. I understand that Eigen does not do automatic promotion and that B needs to be casted as a float vector in order for the multiplication to happen. When I compile, I get the following compilation error among others
1 | testMatOp.cpp:34:44: error: expected primary-expression before 'float' |
What might I be doing wrong. I did take a look at this post : Cast Eigen::MatrixXd to Eigen::MatrixXfwhich correctly describes how to cast, but I’m unable to make it work for this example.
*A: *B
is a dependent name. To access its template member cast
, you have to write
1 | B.template cast |
C++ is context-sensitive. When encountering a <
, it tries to figure out if it is operator<
or angle bracket.
1 | // std::vector is a template, so < is an angle bracket |
However, the type of B
is const Eigen::ArrayBase<DerivedB>&
, which depends on the template parameter DerivedB
. C++ cannot decide if B.cast
is a template. When this happens, C++ always guess that it is not a template and interprets the following <
as operator<
.
Why C++ is so stupid that it cannot recognize previously declared template ArrayBase::cast
? Well, someone may specialize ArrayBase<int>
.
1 | template<> |
Therefore one cannot deduce that B.cast
is a template.
4. Using an aligned allocator
STL containers take an optional template parameter, the allocator type. When using STL containers on fixed-size vectorizable Eigen types, you need tell the container to use an allocator that will always allocate memory at 16-byte-aligned locations. Fortunately, Eigen does provide such an allocator: Eigen::aligned_allocator.
For example, instead of
1 | std::map<int, Eigen::Vector4f> |
you need to use
1 | std::map<int, Eigen::Vector4f, std::less<int>, Eigen::aligned_allocator > > |
Note that the third parameter “std::less