ceres_scan_matcher_3d_test.cc
Go to the documentation of this file.
00001 /*
00002  * Copyright 2016 The Cartographer Authors
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *      http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00017 #include "cartographer/mapping/internal/3d/scan_matching/ceres_scan_matcher_3d.h"
00018 
00019 #include <memory>
00020 
00021 #include "Eigen/Core"
00022 #include "cartographer/common/lua_parameter_dictionary_test_helpers.h"
00023 #include "cartographer/mapping/3d/hybrid_grid.h"
00024 #include "cartographer/sensor/point_cloud.h"
00025 #include "cartographer/transform/rigid_transform.h"
00026 #include "cartographer/transform/rigid_transform_test_helpers.h"
00027 #include "gtest/gtest.h"
00028 
00029 namespace cartographer {
00030 namespace mapping {
00031 namespace scan_matching {
00032 namespace {
00033 
00034 class CeresScanMatcher3DTest : public ::testing::Test {
00035  protected:
00036   CeresScanMatcher3DTest()
00037       : hybrid_grid_(1.f),
00038         expected_pose_(
00039             transform::Rigid3d::Translation(Eigen::Vector3d(-1., 0., 0.))) {
00040     for (const Eigen::Vector3f& point :
00041          {Eigen::Vector3f(-3.f, 2.f, 0.f), Eigen::Vector3f(-4.f, 2.f, 0.f),
00042           Eigen::Vector3f(-5.f, 2.f, 0.f), Eigen::Vector3f(-6.f, 2.f, 0.f),
00043           Eigen::Vector3f(-6.f, 3.f, 1.f), Eigen::Vector3f(-6.f, 4.f, 2.f),
00044           Eigen::Vector3f(-7.f, 3.f, 1.f)}) {
00045       point_cloud_.push_back({point});
00046       hybrid_grid_.SetProbability(
00047           hybrid_grid_.GetCellIndex(expected_pose_.cast<float>() * point), 1.);
00048     }
00049 
00050     auto parameter_dictionary = common::MakeDictionary(R"text(
00051         return {
00052           occupied_space_weight_0 = 1.,
00053           translation_weight = 0.01,
00054           rotation_weight = 0.1,
00055           only_optimize_yaw = false,
00056           ceres_solver_options = {
00057             use_nonmonotonic_steps = true,
00058             max_num_iterations = 10,
00059             num_threads = 1,
00060           },
00061         })text");
00062     options_ = CreateCeresScanMatcherOptions3D(parameter_dictionary.get());
00063     ceres_scan_matcher_.reset(new CeresScanMatcher3D(options_));
00064   }
00065 
00066   void TestFromInitialPose(const transform::Rigid3d& initial_pose) {
00067     transform::Rigid3d pose;
00068 
00069     ceres::Solver::Summary summary;
00070     ceres_scan_matcher_->Match(initial_pose.translation(), initial_pose,
00071                                {{&point_cloud_, &hybrid_grid_}}, &pose,
00072                                &summary);
00073     EXPECT_NEAR(0., summary.final_cost, 1e-2) << summary.FullReport();
00074     EXPECT_THAT(pose, transform::IsNearly(expected_pose_, 3e-2));
00075   }
00076 
00077   HybridGrid hybrid_grid_;
00078   transform::Rigid3d expected_pose_;
00079   sensor::PointCloud point_cloud_;
00080   proto::CeresScanMatcherOptions3D options_;
00081   std::unique_ptr<CeresScanMatcher3D> ceres_scan_matcher_;
00082 };
00083 
00084 TEST_F(CeresScanMatcher3DTest, PerfectEstimate) {
00085   TestFromInitialPose(
00086       transform::Rigid3d::Translation(Eigen::Vector3d(-1., 0., 0.)));
00087 }
00088 
00089 TEST_F(CeresScanMatcher3DTest, AlongX) {
00090   ceres_scan_matcher_.reset(new CeresScanMatcher3D(options_));
00091   TestFromInitialPose(
00092       transform::Rigid3d::Translation(Eigen::Vector3d(-0.8, 0., 0.)));
00093 }
00094 
00095 TEST_F(CeresScanMatcher3DTest, AlongZ) {
00096   TestFromInitialPose(
00097       transform::Rigid3d::Translation(Eigen::Vector3d(-1., 0., -0.2)));
00098 }
00099 
00100 TEST_F(CeresScanMatcher3DTest, AlongXYZ) {
00101   TestFromInitialPose(
00102       transform::Rigid3d::Translation(Eigen::Vector3d(-0.9, -0.2, 0.2)));
00103 }
00104 
00105 TEST_F(CeresScanMatcher3DTest, FullPoseCorrection) {
00106   // We try to find the rotation around z...
00107   const auto additional_transform = transform::Rigid3d::Rotation(
00108       Eigen::AngleAxisd(0.05, Eigen::Vector3d(0., 0., 1.)));
00109   point_cloud_ = sensor::TransformPointCloud(
00110       point_cloud_, additional_transform.cast<float>());
00111   expected_pose_ = expected_pose_ * additional_transform.inverse();
00112   // ...starting initially with rotation around x.
00113   TestFromInitialPose(
00114       transform::Rigid3d(Eigen::Vector3d(-0.95, -0.05, 0.05),
00115                          Eigen::AngleAxisd(0.05, Eigen::Vector3d(1., 0., 0.))));
00116 }
00117 
00118 }  // namespace
00119 }  // namespace scan_matching
00120 }  // namespace mapping
00121 }  // namespace cartographer


cartographer
Author(s): The Cartographer Authors
autogenerated on Thu May 9 2019 02:27:35