00001 #include "transform_graph/graph.h"
00002
00003 #include <string>
00004
00005 #include "Eigen/Dense"
00006 #include "geometry_msgs/Point.h"
00007 #include "geometry_msgs/Pose.h"
00008 #include "gtest/gtest.h"
00009
00010 namespace transform_graph {
00011
00012 TEST(TestGraph, InitiallyEmpty) {
00013 Graph graph;
00014 EXPECT_FALSE(graph.CanTransform("A", "B"));
00015 EXPECT_FALSE(graph.CanTransform("foo", "foo bar"));
00016 }
00017
00018 TEST(TestGraph, SimpleConnection) {
00019 Graph graph;
00020 graph.Add("tool", RefFrame("base link"), Transform());
00021 EXPECT_FALSE(graph.CanTransform("tool", "asdf"));
00022 EXPECT_TRUE(graph.CanTransform("tool", "base link"));
00023 EXPECT_TRUE(graph.CanTransform("base link", "tool"));
00024 }
00025
00026 TEST(TestGraph, SelfTarget) {
00027 Graph graph;
00028 graph.Add("tool", RefFrame("base link"), Transform());
00029 EXPECT_TRUE(graph.CanTransform("tool", "tool"));
00030 }
00031
00032 TEST(TestGraph, LinkedList) {
00033 Graph graph;
00034 graph.Add("B", RefFrame("A"), Transform());
00035 graph.Add("C", RefFrame("B"), Transform());
00036 EXPECT_TRUE(graph.CanTransform("A", "C"));
00037 EXPECT_TRUE(graph.CanTransform("C", "A"));
00038 }
00039
00040 TEST(TestGraph, DisconnectedSuccess) {
00041 Graph graph;
00042 graph.Add("B", RefFrame("A"), Transform());
00043 graph.Add("C", RefFrame("D"), Transform());
00044 EXPECT_TRUE(graph.CanTransform("A", "B"));
00045 }
00046
00047 TEST(TestGraph, DisconnectedFail) {
00048 Graph graph;
00049 graph.Add("B", RefFrame("A"), Transform());
00050 graph.Add("C", RefFrame("D"), Transform());
00051 EXPECT_FALSE(graph.CanTransform("A", "C"));
00052 }
00053
00054 TEST(TestGraph, SelfTargetIsIdentity) {
00055 Graph graph;
00056 Eigen::Vector3d translation(1, 2, 3);
00057 graph.Add("tool", RefFrame("base_link"),
00058 Transform(translation, Orientation()));
00059
00060 Eigen::Matrix4d expected;
00061
00062 expected << 1, 0, 0, 0,
00063 0, 1, 0, 0,
00064 0, 0, 1, 0,
00065 0, 0, 0, 1;
00066
00067 Transform actual;
00068 bool success =
00069 graph.ComputeDescription(LocalFrame("tool"), RefFrame("tool"), &actual);
00070 EXPECT_TRUE(success);
00071
00072 EXPECT_TRUE(expected.isApprox(actual.matrix(), 0.000001));
00073 }
00074
00075
00076 TEST(TestGraph, SimpleTranslationDescription) {
00077 Graph graph;
00078 Eigen::Vector3d translation(1, 2, 3);
00079 Orientation rotation;
00080 graph.Add("some link", RefFrame("base link"),
00081 Transform(translation, rotation));
00082
00083 Eigen::Matrix4d expected;
00084
00085 expected << 1, 0, 0, 1,
00086 0, 1, 0, 2,
00087 0, 0, 1, 3,
00088 0, 0, 0, 1;
00089
00090 Transform actual;
00091 bool success =
00092 graph.ComputeDescription("some link", RefFrame("base link"), &actual);
00093 EXPECT_TRUE(success);
00094 EXPECT_TRUE(expected.isApprox(actual.matrix(), 0.000001));
00095
00096
00097 expected(0, 3) = -1;
00098 expected(1, 3) = -2;
00099 expected(2, 3) = -3;
00100 graph.ComputeDescription("base link", RefFrame("some link"), &actual);
00101 EXPECT_TRUE(expected.isApprox(actual.matrix(), 0.000001));
00102 }
00103
00104 TEST(TestGraph, SimpleOrientationDescription) {
00105 Graph graph;
00106 Position translation;
00107 Eigen::Matrix3d rot_matrix;
00108
00109 rot_matrix << 0.866, -0.5, 0,
00110 0.5, 0.866, 0,
00111 0, 0, 1;
00112
00113
00114 graph.Add("some link", RefFrame("base link"),
00115 Transform(translation, rot_matrix));
00116
00117 Eigen::Matrix4d expected;
00118
00119 expected << 0.866, -0.5, 0, 0,
00120 0.5, 0.866, 0, 0,
00121 0, 0, 1, 0,
00122 0, 0, 0, 1;
00123
00124 Transform actual;
00125 bool success =
00126 graph.ComputeDescription("some link", RefFrame("base link"), &actual);
00127 EXPECT_TRUE(success);
00128 EXPECT_TRUE(expected.isApprox(actual.matrix(), 0.000001));
00129
00130
00131 expected.topLeftCorner(3, 3).transposeInPlace();
00132 graph.ComputeDescription("base link", RefFrame("some link"), &actual);
00133 EXPECT_TRUE(expected.isApprox(actual.matrix(), 0.0001));
00134 }
00135
00136 TEST(TestGraph, TranslationChainDescription) {
00137 Graph graph;
00138 Eigen::Vector3d base_torso(0, 0, 3);
00139 Eigen::Vector3d torso_tool(0.1, 0.2, 0.3);
00140 Orientation identity_rot;
00141 graph.Add("torso", RefFrame("base"), Transform(base_torso, identity_rot));
00142 graph.Add("tool", RefFrame("torso"), Transform(torso_tool, identity_rot));
00143
00144 Eigen::Matrix4d expected;
00145
00146 expected << 1, 0, 0, 0.1,
00147 0, 1, 0, 0.2,
00148 0, 0, 1, 3.3,
00149 0, 0, 0, 1;
00150
00151 Transform actual;
00152 bool success = graph.ComputeDescription("tool", RefFrame("base"), &actual);
00153 EXPECT_TRUE(success);
00154 EXPECT_TRUE(expected.isApprox(actual.matrix(), 0.000001));
00155
00156
00157 expected(0, 3) = -0.1;
00158 expected(1, 3) = -0.2;
00159 expected(2, 3) = -3.3;
00160 graph.ComputeDescription("base", RefFrame("tool"), &actual);
00161 EXPECT_TRUE(expected.isApprox(actual.matrix(), 0.000001));
00162 }
00163
00164 TEST(TestGraph, OrientationChainDescription) {
00165 Graph graph;
00166 Position identity;
00167 Eigen::Matrix3d ori12;
00168 Eigen::Matrix3d ori23;
00169
00170 ori12 << 0.866, -0.5, 0,
00171 0.5, 0.866, 0,
00172 0, 0, 1;
00173 ori23 << 1, 0, 0,
00174 0, 0.866, 0.5,
00175 0, 0.5, 0.866;
00176
00177
00178 graph.Add("link1", RefFrame("base"), Transform(identity, ori12));
00179 graph.Add("link2", RefFrame("link1"), Transform(identity, ori23));
00180
00181 Eigen::Matrix3d ori13 = ori12 * ori23;
00182 Eigen::Affine3d affine13(ori13);
00183 Eigen::Matrix3d ori31 = ori23.inverse() * ori12.inverse();
00184 Eigen::Affine3d affine31(ori31);
00185
00186 Transform actual;
00187 bool success = graph.ComputeDescription("link2", RefFrame("base"), &actual);
00188 EXPECT_TRUE(success);
00189 EXPECT_TRUE(affine13.matrix().isApprox(actual.matrix(), 0.000001));
00190
00191
00192 graph.ComputeDescription("base", RefFrame("link2"), &actual);
00193 EXPECT_TRUE(affine31.matrix().isApprox(actual.matrix(), 0.000001));
00194 }
00195
00196 TEST(TestGraph, InverseDescription) {
00197 Graph graph;
00198 Eigen::Matrix4d matrix;
00199
00200 matrix << 0.866, -0.5, 0, 4,
00201 0.5, 0.866, 0, 3,
00202 0, 0, 1, 0,
00203 0, 0, 0, 1;
00204
00205 Eigen::Matrix4d expected;
00206
00207 expected << 0.866, 0.5, 0, -4.964,
00208 -0.5, 0.866, 0, -0.598,
00209 0, 0, 1, 0,
00210 0, 0, 0, 1;
00211
00212
00213 graph.Add("B", RefFrame("A"), matrix);
00214
00215 Transform actual;
00216 bool success = graph.ComputeDescription("A", RefFrame("B"), &actual);
00217 EXPECT_TRUE(success);
00218 EXPECT_TRUE(expected.isApprox(actual.matrix(), 0.0001));
00219 }
00220
00221 TEST(TestGraph, DescribePoint) {
00222 Graph graph;
00223 Eigen::Matrix4d b_matrix;
00224
00225 b_matrix << 0.866, -0.5, 0, 10,
00226 0.5, 0.866, 0, 5,
00227 0, 0, 1, 0,
00228 0, 0, 0, 1;
00229
00230 graph.Add("B", RefFrame("A"), b_matrix);
00231
00232 geometry_msgs::Point pt_in_b;
00233 pt_in_b.x = 3;
00234 pt_in_b.y = 7;
00235 pt_in_b.z = 0;
00236
00237 Eigen::Vector3d expected(9.098, 12.562, 0);
00238
00239 Position actual;
00240 bool success =
00241 graph.DescribePosition(pt_in_b, Source("B"), Target("A"), &actual);
00242 EXPECT_TRUE(success);
00243 EXPECT_TRUE(expected.isApprox(actual.vector(), 0.000001));
00244 }
00245
00246 TEST(TestGraph, DescribePose) {
00247 Graph graph;
00248 Eigen::Matrix4d tool_in_base;
00249
00250 tool_in_base << 0.866, -0.5, 0, 10,
00251 0.5, 0.866, 0, 5,
00252 0, 0, 1, 0,
00253 0, 0, 0, 1;
00254
00255
00256 graph.Add("tool", RefFrame("base"), tool_in_base);
00257
00258 geometry_msgs::Pose pose_in_tool;
00259 pose_in_tool.orientation.w = 1;
00260 pose_in_tool.position.x = 3;
00261 pose_in_tool.position.y = 7;
00262 pose_in_tool.position.z = 0;
00263
00264 Eigen::Matrix4d expected;
00265
00266 expected << 0.866, -0.5, 0, 9.098,
00267 0.5, 0.866, 0, 12.562,
00268 0, 0, 1, 0,
00269 0, 0, 0, 1;
00270
00271
00272 Transform actual;
00273 bool success =
00274 graph.DescribePose(pose_in_tool, Source("tool"), Target("base"), &actual);
00275 EXPECT_TRUE(success);
00276 EXPECT_TRUE(expected.isApprox(actual.matrix(), 0.000001));
00277 }
00278
00279
00280 TEST(TestGraph, ComputeSimpleMapping) {
00281 Graph graph;
00282 Eigen::Vector3d left_hand(0, 0.5, 0);
00283 Eigen::Vector3d right_hand(0, -0.5, 0);
00284 Orientation identity;
00285
00286 graph.Add("left_hand", RefFrame("base"), Transform(left_hand, identity));
00287 graph.Add("right_hand", RefFrame("base"), Transform(right_hand, identity));
00288
00289 Transform actual;
00290 bool success =
00291 graph.ComputeMapping(From("left_hand"), To("right_hand"), &actual);
00292 Eigen::Vector3d expected(0, -1, 0);
00293 EXPECT_TRUE(success);
00294 EXPECT_TRUE(
00295 expected.isApprox(actual.matrix().topRightCorner(3, 1), 0.000001));
00296
00297
00298 success = graph.ComputeMapping(From("right_hand"), To("left_hand"), &actual);
00299 expected.y() = 1;
00300 EXPECT_TRUE(success);
00301 EXPECT_TRUE(
00302 expected.isApprox(actual.matrix().topRightCorner(3, 1), 0.000001));
00303 }
00304
00305 TEST(TestGraph, SimpleMapPosition) {
00306 Graph graph;
00307 Eigen::Vector3d left_hand(0, 0.5, 0);
00308 Eigen::Vector3d right_hand(0, -0.5, 0);
00309 Orientation identity;
00310
00311 graph.Add("left_hand", RefFrame("base"), Transform(left_hand, identity));
00312 graph.Add("right_hand", RefFrame("base"), Transform(right_hand, identity));
00313
00314 Position actual;
00315 geometry_msgs::Point pt;
00316 pt.x = 1;
00317 pt.y = 0;
00318 pt.z = 0;
00319 bool success =
00320 graph.MapPosition(pt, From("left_hand"), To("right_hand"), &actual);
00321 Eigen::Vector3d expected(1, -1, 0);
00322 EXPECT_TRUE(success);
00323 EXPECT_TRUE(expected.isApprox(actual.vector(), 0.000001));
00324
00325
00326 success = graph.MapPosition(pt, From("right_hand"), To("left_hand"), &actual);
00327 expected.y() = 1;
00328 EXPECT_TRUE(success);
00329 EXPECT_TRUE(expected.isApprox(actual.vector(), 0.000001));
00330 }
00331
00332 TEST(TestGraph, MapPose) {
00333 Graph graph;
00334 Eigen::Vector3d left_hand(0, 1, 0);
00335 Eigen::Vector3d right_hand(0, -1, 0);
00336 Orientation identity;
00337
00338 graph.Add("left_hand", RefFrame("base"), Transform(left_hand, identity));
00339 graph.Add("right_hand", RefFrame("base"), Transform(right_hand, identity));
00340
00341 Eigen::Matrix3d rotation(
00342 Eigen::AngleAxisd(M_PI / 4, Eigen::Vector3d(0, 0, 1)));
00343 Eigen::Quaterniond quaternion(rotation.matrix());
00344
00345 Transform actual;
00346 geometry_msgs::Pose pose;
00347 pose.position.x = 1;
00348 pose.position.y = 0;
00349 pose.position.z = 0;
00350 pose.orientation.w = quaternion.w();
00351 pose.orientation.x = quaternion.x();
00352 pose.orientation.y = quaternion.y();
00353 pose.orientation.z = quaternion.z();
00354 bool success =
00355 graph.MapPose(pose, From("left_hand"), To("right_hand"), &actual);
00356
00357 Eigen::Matrix4d expected;
00358
00359 expected << 0.707107, -0.707107, 0, 1,
00360 0.707107, 0.707107, 0, -2,
00361 0, 0, 1, 0,
00362 0, 0, 0, 1;
00363
00364
00365 EXPECT_TRUE(success);
00366 EXPECT_TRUE(expected.matrix().isApprox(actual.matrix(), 0.000001));
00367 }
00368
00369 TEST(TestGraph, ComputeMappingBetweenRotatedFrames) {
00370 Graph graph;
00371 Eigen::Vector3d left_hand(0, 0.5, 0);
00372 Eigen::Vector3d right_hand(0, -0.5, 0);
00373 Orientation identity;
00374
00375 Eigen::Matrix3d rotation(
00376 Eigen::AngleAxisd(M_PI / 4, Eigen::Vector3d(0, 0, 1)));
00377 graph.Add("left_hand", RefFrame("base"), Transform(left_hand, identity));
00378 graph.Add("right_hand", RefFrame("base"), Transform(right_hand, rotation));
00379
00380 geometry_msgs::Point point;
00381 point.x = sqrt(2);
00382 point.y = 0;
00383 point.z = 0;
00384 Eigen::Vector4d eigen_point;
00385 eigen_point << point.x, point.y, point.z, 1;
00386
00387 Eigen::Vector3d expected;
00388 expected << 1, 0, 0;
00389
00390 transform_graph::Transform left_to_right;
00391 bool success =
00392 graph.ComputeMapping(From("left_hand"), To("right_hand"), &left_to_right);
00393 Eigen::Vector3d compute_actual =
00394 (left_to_right.matrix() * eigen_point).head<3>();
00395 EXPECT_TRUE(success);
00396 EXPECT_TRUE(expected.isApprox(compute_actual, 0.000001));
00397 }
00398
00399 TEST(TestGraph, MapPositionBetweenRotatedFrames) {
00400 Graph graph;
00401 Eigen::Vector3d left_hand(0, 0.5, 0);
00402 Eigen::Vector3d right_hand(0, -0.5, 0);
00403 Orientation identity;
00404
00405 Eigen::Matrix3d rotation(
00406 Eigen::AngleAxisd(M_PI / 4, Eigen::Vector3d(0, 0, 1)));
00407 graph.Add("left_hand", RefFrame("base"), Transform(left_hand, identity));
00408 graph.Add("right_hand", RefFrame("base"), Transform(right_hand, rotation));
00409
00410 geometry_msgs::Point point;
00411 point.x = sqrt(2);
00412 point.y = 0;
00413 point.z = 0;
00414 Eigen::Vector4d eigen_point;
00415 eigen_point << point.x, point.y, point.z, 1;
00416
00417 Eigen::Vector3d expected;
00418 expected << 1, 0, 0;
00419
00420 Position actual;
00421 bool success =
00422 graph.MapPosition(point, From("left_hand"), To("right_hand"), &actual);
00423
00424 EXPECT_TRUE(success);
00425 EXPECT_TRUE(expected.isApprox(actual.vector(), 0.000001));
00426 }
00427 }
00428
00429 int main(int argc, char **argv) {
00430 testing::InitGoogleTest(&argc, argv);
00431 return RUN_ALL_TESTS();
00432 }