test_sim3.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. #include <iostream>
  2. #include <unsupported/Eigen/MatrixFunctions>
  3. #include <sophus/sim3.hpp>
  4. #include "tests.hpp"
  5. // Explicit instantiate all class templates so that all member methods
  6. // get compiled and for code coverage analysis.
  7. namespace Eigen {
  8. template class Map<Sophus::Sim3<double>>;
  9. template class Map<Sophus::Sim3<double> const>;
  10. } // namespace Eigen
  11. namespace Sophus {
  12. template class Sim3<double, Eigen::AutoAlign>;
  13. template class Sim3<float, Eigen::DontAlign>;
  14. #if SOPHUS_CERES
  15. template class Sim3<ceres::Jet<double, 3>>;
  16. #endif
  17. template <class Scalar>
  18. class Tests {
  19. public:
  20. using Sim3Type = Sim3<Scalar>;
  21. using RxSO3Type = RxSO3<Scalar>;
  22. using Point = typename Sim3<Scalar>::Point;
  23. using Vector4Type = Vector4<Scalar>;
  24. using Tangent = typename Sim3<Scalar>::Tangent;
  25. Scalar const kPi = Constants<Scalar>::pi();
  26. Tests() {
  27. sim3_vec_.push_back(
  28. Sim3Type(RxSO3Type::exp(Vector4Type(Scalar(0.2), Scalar(0.5),
  29. Scalar(0.0), Scalar(1.))),
  30. Point(Scalar(0), Scalar(0), Scalar(0))));
  31. sim3_vec_.push_back(
  32. Sim3Type(RxSO3Type::exp(Vector4Type(Scalar(0.2), Scalar(0.5),
  33. Scalar(-1.0), Scalar(1.1))),
  34. Point(Scalar(10), Scalar(0), Scalar(0))));
  35. sim3_vec_.push_back(
  36. Sim3Type(RxSO3Type::exp(Vector4Type(Scalar(0.), Scalar(0.), Scalar(0.),
  37. Scalar(0.))),
  38. Point(Scalar(0), Scalar(10), Scalar(5))));
  39. sim3_vec_.push_back(
  40. Sim3Type(RxSO3Type::exp(Vector4Type(Scalar(0.), Scalar(0.), Scalar(0.),
  41. Scalar(1.1))),
  42. Point(Scalar(0), Scalar(10), Scalar(5))));
  43. sim3_vec_.push_back(
  44. Sim3Type(RxSO3Type::exp(Vector4Type(Scalar(0.), Scalar(0.),
  45. Scalar(0.00001), Scalar(0.))),
  46. Point(Scalar(0), Scalar(0), Scalar(0))));
  47. sim3_vec_.push_back(Sim3Type(
  48. RxSO3Type::exp(Vector4Type(Scalar(0.), Scalar(0.), Scalar(0.00001),
  49. Scalar(0.0000001))),
  50. Point(Scalar(1), Scalar(-1.00000001), Scalar(2.0000000001))));
  51. sim3_vec_.push_back(
  52. Sim3Type(RxSO3Type::exp(Vector4Type(Scalar(0.), Scalar(0.),
  53. Scalar(0.00001), Scalar(0))),
  54. Point(Scalar(0.01), Scalar(0), Scalar(0))));
  55. sim3_vec_.push_back(Sim3Type(
  56. RxSO3Type::exp(Vector4Type(kPi, Scalar(0), Scalar(0), Scalar(0.9))),
  57. Point(Scalar(4), Scalar(-5), Scalar(0))));
  58. sim3_vec_.push_back(
  59. Sim3Type(RxSO3Type::exp(Vector4Type(Scalar(0.2), Scalar(0.5),
  60. Scalar(0.0), Scalar(0))),
  61. Point(Scalar(0), Scalar(0), Scalar(0))) *
  62. Sim3Type(
  63. RxSO3Type::exp(Vector4Type(kPi, Scalar(0), Scalar(0), Scalar(0))),
  64. Point(Scalar(0), Scalar(0), Scalar(0))) *
  65. Sim3Type(RxSO3Type::exp(Vector4Type(Scalar(-0.2), Scalar(-0.5),
  66. Scalar(-0.0), Scalar(0))),
  67. Point(Scalar(0), Scalar(0), Scalar(0))));
  68. sim3_vec_.push_back(
  69. Sim3Type(RxSO3Type::exp(Vector4Type(Scalar(0.3), Scalar(0.5),
  70. Scalar(0.1), Scalar(0))),
  71. Point(Scalar(2), Scalar(0), Scalar(-7))) *
  72. Sim3Type(
  73. RxSO3Type::exp(Vector4Type(kPi, Scalar(0), Scalar(0), Scalar(0))),
  74. Point(Scalar(0), Scalar(0), Scalar(0))) *
  75. Sim3Type(RxSO3Type::exp(Vector4Type(Scalar(-0.3), Scalar(-0.5),
  76. Scalar(-0.1), Scalar(0))),
  77. Point(Scalar(0), Scalar(6), Scalar(0))));
  78. Tangent tmp;
  79. tmp << Scalar(0), Scalar(0), Scalar(0), Scalar(0), Scalar(0), Scalar(0),
  80. Scalar(0);
  81. tangent_vec_.push_back(tmp);
  82. tmp << Scalar(1), Scalar(0), Scalar(0), Scalar(0), Scalar(0), Scalar(0),
  83. Scalar(0);
  84. tangent_vec_.push_back(tmp);
  85. tmp << Scalar(0), Scalar(1), Scalar(0), Scalar(1), Scalar(0), Scalar(0),
  86. Scalar(0.1);
  87. tangent_vec_.push_back(tmp);
  88. tmp << Scalar(0), Scalar(0), Scalar(1), Scalar(0), Scalar(1), Scalar(0),
  89. Scalar(0.1);
  90. tangent_vec_.push_back(tmp);
  91. tmp << Scalar(-1), Scalar(1), Scalar(0), Scalar(0), Scalar(0), Scalar(1),
  92. Scalar(-0.1);
  93. tangent_vec_.push_back(tmp);
  94. tmp << Scalar(20), Scalar(-1), Scalar(0), Scalar(-1), Scalar(1), Scalar(0),
  95. Scalar(-0.1);
  96. tangent_vec_.push_back(tmp);
  97. tmp << Scalar(30), Scalar(5), Scalar(-1), Scalar(20), Scalar(-1), Scalar(0),
  98. Scalar(1.5);
  99. tangent_vec_.push_back(tmp);
  100. point_vec_.push_back(Point(Scalar(1), Scalar(2), Scalar(4)));
  101. point_vec_.push_back(Point(Scalar(1), Scalar(-3), Scalar(0.5)));
  102. }
  103. void runAll() {
  104. bool passed = testLieProperties();
  105. passed &= testRawDataAcces();
  106. passed &= testConstructors();
  107. processTestResult(passed);
  108. }
  109. private:
  110. bool testLieProperties() {
  111. LieGroupTests<Sim3Type> tests(sim3_vec_, tangent_vec_, point_vec_);
  112. return tests.doAllTestsPass();
  113. }
  114. bool testRawDataAcces() {
  115. bool passed = true;
  116. Eigen::Matrix<Scalar, 7, 1> raw;
  117. raw << Scalar(0), Scalar(1), Scalar(0), Scalar(0), Scalar(1), Scalar(3),
  118. Scalar(2);
  119. Eigen::Map<Sim3Type const> map_of_const_sim3(raw.data());
  120. SOPHUS_TEST_APPROX(passed, map_of_const_sim3.quaternion().coeffs().eval(),
  121. raw.template head<4>().eval(),
  122. Constants<Scalar>::epsilon());
  123. SOPHUS_TEST_APPROX(passed, map_of_const_sim3.translation().eval(),
  124. raw.template tail<3>().eval(),
  125. Constants<Scalar>::epsilon());
  126. SOPHUS_TEST_EQUAL(passed, map_of_const_sim3.quaternion().coeffs().data(),
  127. raw.data());
  128. SOPHUS_TEST_EQUAL(passed, map_of_const_sim3.translation().data(),
  129. raw.data() + 4);
  130. Eigen::Map<Sim3Type const> const_shallow_copy = map_of_const_sim3;
  131. SOPHUS_TEST_EQUAL(passed, const_shallow_copy.quaternion().coeffs().eval(),
  132. map_of_const_sim3.quaternion().coeffs().eval());
  133. SOPHUS_TEST_EQUAL(passed, const_shallow_copy.translation().eval(),
  134. map_of_const_sim3.translation().eval());
  135. Eigen::Matrix<Scalar, 7, 1> raw2;
  136. raw2 << Scalar(1), Scalar(0), Scalar(0), Scalar(0), Scalar(3), Scalar(2),
  137. Scalar(1);
  138. Eigen::Map<Sim3Type> map_of_sim3(raw.data());
  139. Eigen::Quaternion<Scalar> quat;
  140. quat.coeffs() = raw2.template head<4>();
  141. map_of_sim3.setQuaternion(quat);
  142. map_of_sim3.translation() = raw2.template tail<3>();
  143. SOPHUS_TEST_APPROX(passed, map_of_sim3.quaternion().coeffs().eval(),
  144. raw2.template head<4>().eval(),
  145. Constants<Scalar>::epsilon());
  146. SOPHUS_TEST_APPROX(passed, map_of_sim3.translation().eval(),
  147. raw2.template tail<3>().eval(),
  148. Constants<Scalar>::epsilon());
  149. SOPHUS_TEST_EQUAL(passed, map_of_sim3.quaternion().coeffs().data(),
  150. raw.data());
  151. SOPHUS_TEST_EQUAL(passed, map_of_sim3.translation().data(), raw.data() + 4);
  152. SOPHUS_TEST_NEQ(passed, map_of_sim3.quaternion().coeffs().data(),
  153. quat.coeffs().data());
  154. Eigen::Map<Sim3Type> shallow_copy = map_of_sim3;
  155. SOPHUS_TEST_EQUAL(passed, shallow_copy.quaternion().coeffs().eval(),
  156. map_of_sim3.quaternion().coeffs().eval());
  157. SOPHUS_TEST_EQUAL(passed, shallow_copy.translation().eval(),
  158. map_of_sim3.translation().eval());
  159. Eigen::Map<Sim3Type> const const_map_of_sim3 = map_of_sim3;
  160. SOPHUS_TEST_EQUAL(passed, const_map_of_sim3.quaternion().coeffs().eval(),
  161. map_of_sim3.quaternion().coeffs().eval());
  162. SOPHUS_TEST_EQUAL(passed, const_map_of_sim3.translation().eval(),
  163. map_of_sim3.translation().eval());
  164. Sim3Type const const_sim3(quat, raw2.template tail<3>().eval());
  165. for (int i = 0; i < 7; ++i) {
  166. SOPHUS_TEST_EQUAL(passed, const_sim3.data()[i], raw2.data()[i]);
  167. }
  168. Sim3Type se3(quat, raw2.template tail<3>().eval());
  169. for (int i = 0; i < 7; ++i) {
  170. SOPHUS_TEST_EQUAL(passed, se3.data()[i], raw2.data()[i]);
  171. }
  172. for (int i = 0; i < 7; ++i) {
  173. SOPHUS_TEST_EQUAL(passed, se3.data()[i], raw.data()[i]);
  174. }
  175. Eigen::Matrix<Scalar, 7, 1> data1, data2;
  176. data1 << Scalar(0), Scalar(2), Scalar(0), Scalar(0),
  177. Scalar(1), Scalar(2), Scalar(3);
  178. data2 << Scalar(0), Scalar(0), Scalar(2), Scalar(0),
  179. Scalar(3), Scalar(2), Scalar(1);
  180. Eigen::Map<Sim3Type> map1(data1.data()), map2(data2.data());
  181. // map -> map assignment
  182. map2 = map1;
  183. SOPHUS_TEST_EQUAL(passed, map1.matrix(), map2.matrix());
  184. // map -> type assignment
  185. Sim3Type copy;
  186. copy = map1;
  187. SOPHUS_TEST_EQUAL(passed, map1.matrix(), copy.matrix());
  188. // type -> map assignment
  189. copy = Sim3Type(RxSO3Type::exp(Vector4Type(Scalar(0.2), Scalar(0.5),
  190. Scalar(-1.0), Scalar(1.1))),
  191. Point(Scalar(10), Scalar(0), Scalar(0)));
  192. map1 = copy;
  193. SOPHUS_TEST_EQUAL(passed, map1.matrix(), copy.matrix());
  194. return passed;
  195. }
  196. bool testConstructors() {
  197. bool passed = true;
  198. Eigen::Matrix<Scalar, 4, 4> I = Eigen::Matrix<Scalar, 4, 4>::Identity();
  199. SOPHUS_TEST_EQUAL(passed, Sim3Type().matrix(), I);
  200. Sim3Type sim3 = sim3_vec_.front();
  201. Point translation = sim3.translation();
  202. RxSO3Type rxso3 = sim3.rxso3();
  203. SOPHUS_TEST_APPROX(passed, Sim3Type(rxso3, translation).matrix(),
  204. sim3.matrix(), Constants<Scalar>::epsilon());
  205. SOPHUS_TEST_APPROX(passed,
  206. Sim3Type(rxso3.quaternion(), translation).matrix(),
  207. sim3.matrix(), Constants<Scalar>::epsilon());
  208. SOPHUS_TEST_APPROX(passed, Sim3Type(sim3.matrix()).matrix(), sim3.matrix(),
  209. Constants<Scalar>::epsilon());
  210. Scalar scale(1.2);
  211. sim3.setScale(scale);
  212. SOPHUS_TEST_APPROX(passed, scale, sim3.scale(),
  213. Constants<Scalar>::epsilon(), "setScale");
  214. sim3.setQuaternion(sim3_vec_[0].rxso3().quaternion());
  215. SOPHUS_TEST_APPROX(passed, sim3_vec_[0].rxso3().quaternion().coeffs(),
  216. sim3_vec_[0].rxso3().quaternion().coeffs(),
  217. Constants<Scalar>::epsilon(), "setQuaternion");
  218. return passed;
  219. }
  220. std::vector<Sim3Type, Eigen::aligned_allocator<Sim3Type>> sim3_vec_;
  221. std::vector<Tangent, Eigen::aligned_allocator<Tangent>> tangent_vec_;
  222. std::vector<Point, Eigen::aligned_allocator<Point>> point_vec_;
  223. };
  224. int test_sim3() {
  225. using std::cerr;
  226. using std::endl;
  227. cerr << "Test Sim3" << endl << endl;
  228. cerr << "Double tests: " << endl;
  229. Tests<double>().runAll();
  230. cerr << "Float tests: " << endl;
  231. Tests<float>().runAll();
  232. #if SOPHUS_CERES
  233. cerr << "ceres::Jet<double, 3> tests: " << endl;
  234. Tests<ceres::Jet<double, 3>>().runAll();
  235. #endif
  236. return 0;
  237. }
  238. } // namespace Sophus
  239. int main() { return Sophus::test_sim3(); }