Skip to content
This repository was archived by the owner on May 31, 2025. It is now read-only.

Commit 182a7ee

Browse files
committed
Add Eigen buffer transform tests
1 parent c73b593 commit 182a7ee

3 files changed

Lines changed: 134 additions & 2 deletions

File tree

tf2_eigen/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ find_package(catkin REQUIRED COMPONENTS
55
cmake_modules
66
geometry_msgs
77
tf2
8+
tf2_ros
89
)
910

1011
# Finding Eigen is somewhat complicated because of our need to support Ubuntu

tf2_eigen/package.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
<depend>geometry_msgs</depend>
1313
<depend>tf2</depend>
14+
<depend>tf2_ros</depend>
1415

1516
<build_depend>cmake_modules</build_depend>
1617
<build_depend>eigen</build_depend>

tf2_eigen/test/tf2_eigen-test.cpp

Lines changed: 132 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,25 @@
2626

2727
/** \author Wim Meeussen */
2828

29+
// To get M_PI, especially on Windows.
30+
31+
#ifdef _MSC_VER
32+
#ifndef _USE_MATH_DEFINES
33+
#define _USE_MATH_DEFINES
34+
#endif
35+
#endif
36+
37+
#include <math.h>
38+
2939

30-
#include <tf2_eigen/tf2_eigen.h>
3140
#include <gtest/gtest.h>
3241
#include <tf2/convert.h>
42+
#include <tf2_eigen/tf2_eigen.h>
43+
#include <tf2_ros/buffer.h>
44+
#include <tf2_ros/transform_listener.h>
45+
46+
47+
#include <memory>
3348

3449
TEST(TfEigen, ConvertVector3dStamped)
3550
{
@@ -204,9 +219,124 @@ TEST(TfEigen, ConvertTransform)
204219
EXPECT_TRUE(tm.isApprox(Iback.matrix()));
205220
}
206221

222+
struct EigenTransform : public ::testing::Test
223+
{
224+
static void SetUpTestSuite()
225+
{
226+
geometry_msgs::TransformStamped t;
227+
transform.transform.translation.x = 10;
228+
transform.transform.translation.y = 20;
229+
transform.transform.translation.z = 30;
230+
transform.transform.rotation.w = 0;
231+
transform.transform.rotation.x = 1;
232+
transform.transform.rotation.y = 0;
233+
transform.transform.rotation.z = 0;
234+
transform.header.stamp = ros::Time(2.0);
235+
transform.header.frame_id = "A";
236+
transform.child_frame_id = "B";
237+
}
238+
239+
template<int mode>
240+
void testEigenTransform();
241+
242+
::testing::AssertionResult doTestEigenQuaternion(
243+
const Eigen::Quaterniond & parameter, const Eigen::Quaterniond & expected);
244+
245+
static geometry_msgs::TransformStamped transform;
246+
static constexpr double EPS = 1e-3;
247+
};
248+
249+
geometry_msgs::TransformStamped EigenTransform::transform;
250+
251+
template<int mode>
252+
void EigenTransform::testEigenTransform()
253+
{
254+
using T = Eigen::Transform<double, 3, mode>;
255+
using stampedT = tf2::Stamped<T>;
256+
257+
const stampedT i1{
258+
T{Eigen::Translation3d{1, 2, 3} *Eigen::Quaterniond{0, 1, 0, 0}}, ros::Time(2), "A"};
259+
260+
stampedT i_simple;
261+
tf2::doTransform(i1, i_simple, transform);
262+
263+
EXPECT_NEAR(i_simple.translation().x(), 11, EPS);
264+
EXPECT_NEAR(i_simple.translation().y(), 18, EPS);
265+
EXPECT_NEAR(i_simple.translation().z(), 27, EPS);
266+
const auto q1 = Eigen::Quaterniond(i_simple.linear());
267+
EXPECT_NEAR(q1.x(), 0.0, EPS);
268+
EXPECT_NEAR(q1.y(), 0.0, EPS);
269+
EXPECT_NEAR(q1.z(), 0.0, EPS);
270+
EXPECT_NEAR(q1.w(), 1.0, EPS);
271+
}
272+
273+
TEST_F(EigenTransform, Affine3d) {
274+
testEigenTransform<Eigen::Affine>();
275+
}
276+
277+
TEST_F(EigenTransform, Isometry3d) {
278+
testEigenTransform<Eigen::Isometry>();
279+
}
280+
281+
TEST_F(EigenTransform, Vector)
282+
{
283+
const tf2::Stamped<Eigen::Vector3d> v1{{1, 2, 3}, ros::Time(2), "A"};
207284

285+
// simple api
286+
tf2::Stamped<Eigen::Vector3d> v_simple;
287+
tf2::doTransform(v1, v_simple, transform);
208288

209-
int main(int argc, char **argv){
289+
EXPECT_NEAR(v_simple.x(), 11, EPS);
290+
EXPECT_NEAR(v_simple.y(), 18, EPS);
291+
EXPECT_NEAR(v_simple.z(), 27, EPS);
292+
}
293+
294+
// helper method for Quaternion tests
295+
::testing::AssertionResult EigenTransform::doTestEigenQuaternion(
296+
const Eigen::Quaterniond & parameter, const Eigen::Quaterniond & expected)
297+
{
298+
const tf2::Stamped<Eigen::Quaterniond> q1{parameter, ros::Time(2), "A"};
299+
// avoid linking error
300+
const double eps = EPS;
301+
302+
// simple api
303+
tf2::Stamped<Eigen::Quaterniond> q_simple;
304+
tf2::doTransform(q1, q_simple, transform);
305+
// compare rotation matrices, as the quaternions can be ambigous
306+
EXPECT_TRUE(q_simple.toRotationMatrix().isApprox(expected.toRotationMatrix(), eps));
307+
308+
return ::testing::AssertionSuccess();
309+
}
310+
311+
TEST_F(EigenTransform, QuaternionRotY)
312+
{
313+
// rotated by -90° around y
314+
// 0, 0, -1
315+
// 0, 1, 0,
316+
// 1, 0, 0
317+
const Eigen::Quaterniond param{Eigen::AngleAxisd(-1 * M_PI_2, Eigen::Vector3d::UnitY())};
318+
const Eigen::Quaterniond expected{0, M_SQRT1_2, 0, -1 * M_SQRT1_2};
319+
EXPECT_TRUE(doTestEigenQuaternion(param, expected));
320+
}
321+
322+
TEST_F(EigenTransform, QuaternionRotX)
323+
{
324+
// rotated by 90° around y
325+
const Eigen::Quaterniond param{Eigen::AngleAxisd(M_PI_2, Eigen::Vector3d::UnitX())};
326+
const Eigen::Quaterniond expected{Eigen::AngleAxisd(-1 * M_PI_2, Eigen::Vector3d::UnitX())};
327+
EXPECT_TRUE(doTestEigenQuaternion(param, expected));
328+
}
329+
330+
TEST_F(EigenTransform, QuaternionRotZ)
331+
{
332+
// rotated by 180° around z
333+
const Eigen::Quaterniond param{Eigen::AngleAxisd(M_PI, Eigen::Vector3d::UnitZ())};
334+
const Eigen::Quaterniond expected{Eigen::AngleAxisd(M_PI, Eigen::Vector3d::UnitY())};
335+
EXPECT_TRUE(doTestEigenQuaternion(param, expected));
336+
}
337+
338+
int main(int argc, char ** argv)
339+
{
210340
testing::InitGoogleTest(&argc, argv);
211341

212342
return RUN_ALL_TESTS();

0 commit comments

Comments
 (0)