#include #include "tests.hpp" #include namespace Sophus { namespace experimental { template bool tests_linear_velocities() { bool passed = true; std::vector, Eigen::aligned_allocator>> bar_Ts_baz; for (size_t i = 0; i < 10; ++i) { bar_Ts_baz.push_back(SE3::rotX(i * 0.001) * SE3::rotY(i * 0.001) * SE3::transX(0.01 * i)); } SE3 foo_T_bar = SE3::rotX(0.5) * SE3::rotZ(0.2) * SE3::transY(2); std::vector, Eigen::aligned_allocator>> foo_Ts_baz; for (auto const& bar_T_baz : bar_Ts_baz) { foo_Ts_baz.push_back(foo_T_bar * bar_T_baz); } auto gen_linear_vels = [](std::vector, Eigen::aligned_allocator>> const& a_Ts_b) { std::vector, Eigen::aligned_allocator>> linearVels_a; for (size_t i = 0; i < a_Ts_b.size() - 1; ++i) { linearVels_a.push_back(a_Ts_b[i + 1].translation() - a_Ts_b[i].translation()); } return linearVels_a; }; // linear velocities in frame bar std::vector, Eigen::aligned_allocator>> linearVels_bar = gen_linear_vels(bar_Ts_baz); // linear velocities in frame foo std::vector, Eigen::aligned_allocator>> linearVels_foo = gen_linear_vels(foo_Ts_baz); for (size_t i = 0; i < linearVels_bar.size(); ++i) { SOPHUS_TEST_APPROX(passed, linearVels_foo[i], transformVelocity(foo_T_bar, linearVels_bar[i]), sqrt(Constants::epsilon())); } return passed; } template bool tests_rotational_velocities() { bool passed = true; SE3 foo_T_bar = SE3::rotX(0.5) * SE3::rotZ(0.2) * SE3::transY(2); // One parameter subgroup of SE3, motion through space given time t. auto bar_T_baz = [](Scalar t) -> SE3 { return SE3::rotX(t * Scalar(0.01)) * SE3::rotY(t * Scalar(0.0001)) * SE3::transX(t * Scalar(0.0001)); }; std::vector ts = {Scalar(0), Scalar(0.3), Scalar(1)}; Scalar h = Constants::epsilon(); for (Scalar t : ts) { // finite difference approximiation of instantanious velocity in frame bar Vector3 rotVel_in_frame_bar = finiteDifferenceRotationalVelocity(bar_T_baz, t, h); // finite difference approximiation of instantanious velocity in frame foo Vector3 rotVel_in_frame_foo = finiteDifferenceRotationalVelocity( [&foo_T_bar, bar_T_baz](Scalar t) -> SE3 { return foo_T_bar * bar_T_baz(t); }, t, h); Vector3 rotVel_in_frame_bar2 = transformVelocity(foo_T_bar.inverse(), rotVel_in_frame_foo); SOPHUS_TEST_APPROX( passed, rotVel_in_frame_bar, rotVel_in_frame_bar2, // not too tight threshold, because of finit difference approximation std::sqrt(Constants::epsilon())); // The rotational velocities rotVel_in_frame_foo and rotVel_in_frame_bar // should not be equal since they are in different frames (foo != bar). SOPHUS_TEST_NOT_APPROX(passed, rotVel_in_frame_foo, rotVel_in_frame_bar, Scalar(1e-3)); // Expect same result when using adjoint instead since: // vee(bar_R_foo * hat(vel_foo) * bar_R_foo^T = bar_R_foo 8 vel_foo. SOPHUS_TEST_APPROX( passed, transformVelocity(foo_T_bar.inverse(), rotVel_in_frame_foo), SO3::vee(foo_T_bar.so3().inverse().matrix() * SO3::hat(rotVel_in_frame_foo) * foo_T_bar.so3().matrix()), Constants::epsilon()); } return passed; } int test_velocities() { using std::cerr; using std::endl; cerr << "Test Velocities" << endl << endl; cerr << "Double tests: " << endl; bool passed = tests_linear_velocities(); passed &= tests_rotational_velocities(); processTestResult(passed); cerr << "Float tests: " << endl; passed = tests_linear_velocities(); passed &= tests_rotational_velocities(); processTestResult(passed); return 0; } } // namespace experimental } // namespace Sophus int main() { return Sophus::experimental::test_velocities(); }