spa_cost_function_2d_test.cc
Go to the documentation of this file.
00001 /*
00002  * Copyright 2018 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/optimization/cost_functions/spa_cost_function_2d.h"
00018 
00019 #include <memory>
00020 
00021 #include "cartographer/transform/rigid_transform.h"
00022 #include "gmock/gmock.h"
00023 #include "gtest/gtest.h"
00024 
00025 namespace cartographer {
00026 namespace mapping {
00027 namespace optimization {
00028 namespace {
00029 
00030 using ::testing::ElementsAre;
00031 
00032 constexpr int kPoseDimension = 3;
00033 constexpr int kResidualsCount = 3;
00034 constexpr int kParameterBlocksCount = 2;
00035 constexpr int kJacobianColDimension = kResidualsCount * kPoseDimension;
00036 
00037 using ResidualType = std::array<double, kResidualsCount>;
00038 using JacobianType = std::array<std::array<double, kJacobianColDimension>,
00039                                 kParameterBlocksCount>;
00040 
00041 ::testing::Matcher<double> Near(double expected, double precision = 1e-05) {
00042   return testing::DoubleNear(expected, precision);
00043 }
00044 
00045 class SpaCostFunction2DTest : public ::testing::Test {
00046  public:
00047   SpaCostFunction2DTest()
00048       : constraint_(PoseGraphInterface::Constraint::Pose{
00049             transform::Rigid3d(Eigen::Vector3d(1., 1., 1.),
00050                                Eigen::Quaterniond(1., 1., -1., -1.)),
00051             1, 10}),
00052         auto_diff_cost_(CreateAutoDiffSpaCostFunction(constraint_)),
00053         analytical_cost_(CreateAnalyticalSpaCostFunction(constraint_)) {
00054     for (int i = 0; i < kParameterBlocksCount; ++i) {
00055       jacobian_ptrs_[i] = jacobian_[i].data();
00056     }
00057   }
00058 
00059   std::pair<const ResidualType&, const JacobianType&> EvaluateAnalyticalCost(
00060       const std::array<const double*, 2>& parameter_blocks) {
00061     return Evaluate(parameter_blocks, analytical_cost_);
00062   }
00063 
00064   std::pair<const ResidualType&, const JacobianType&> EvaluateAutoDiffCost(
00065       const std::array<const double*, 2>& parameter_blocks) {
00066     return Evaluate(parameter_blocks, auto_diff_cost_);
00067   }
00068 
00069  private:
00070   std::pair<const ResidualType&, const JacobianType&> Evaluate(
00071       const std::array<const double*, 2>& parameter_blocks,
00072       const std::unique_ptr<ceres::CostFunction>& cost_function) {
00073     cost_function->Evaluate(parameter_blocks.data(), residuals_.data(),
00074                             jacobian_ptrs_.data());
00075     return std::make_pair(std::cref(residuals_), std::cref(jacobian_));
00076   }
00077 
00078   ResidualType residuals_;
00079   JacobianType jacobian_;
00080   std::array<double*, kParameterBlocksCount> jacobian_ptrs_;
00081   PoseGraphInterface::Constraint::Pose constraint_;
00082   std::unique_ptr<ceres::CostFunction> auto_diff_cost_;
00083   std::unique_ptr<ceres::CostFunction> analytical_cost_;
00084 };
00085 
00086 TEST_F(SpaCostFunction2DTest, CompareAutoDiffAndAnalytical) {
00087   std::array<double, 3> start_pose{{1., 1., 1.}};
00088   std::array<double, 3> end_pose{{10., 1., 100.}};
00089   std::array<const double*, 2> parameter_blocks{
00090       {start_pose.data(), end_pose.data()}};
00091 
00092   ResidualType auto_diff_residual, analytical_residual;
00093   JacobianType auto_diff_jacobian, analytical_jacobian;
00094   std::tie(auto_diff_residual, auto_diff_jacobian) =
00095       EvaluateAutoDiffCost(parameter_blocks);
00096   std::tie(analytical_residual, analytical_jacobian) =
00097       EvaluateAnalyticalCost(parameter_blocks);
00098 
00099   for (int i = 0; i < kResidualsCount; ++i) {
00100     EXPECT_THAT(auto_diff_residual[i], Near(analytical_residual[i]));
00101   }
00102   for (int i = 0; i < kParameterBlocksCount; ++i) {
00103     for (int j = 0; j < kJacobianColDimension; ++j) {
00104       EXPECT_THAT(auto_diff_jacobian[i][j], Near(analytical_jacobian[i][j]));
00105     }
00106   }
00107 }
00108 
00109 TEST_F(SpaCostFunction2DTest, EvaluateAnalyticalCost) {
00110   std::array<double, 3> start_pose{{1., 1., 1.}};
00111   std::array<double, 3> end_pose{{10., 1., 100.}};
00112   std::array<const double*, 2> parameter_blocks{
00113       {start_pose.data(), end_pose.data()}};
00114 
00115   auto residuals_and_jacobian = EvaluateAnalyticalCost(parameter_blocks);
00116   EXPECT_THAT(residuals_and_jacobian.first,
00117               ElementsAre(Near(-3.86272), Near(8.57324), Near(-6.83333)));
00118   EXPECT_THAT(
00119       residuals_and_jacobian.second,
00120       ElementsAre(
00121           ElementsAre(Near(0.540302), Near(0.841471), Near(7.57324),
00122                       Near(-0.841471), Near(0.540302), Near(4.86272), Near(0),
00123                       Near(0), Near(10)),
00124           ElementsAre(Near(-0.540302), Near(-0.841471), Near(0), Near(0.841471),
00125                       Near(-0.540302), Near(0), Near(0), Near(0), Near(-10))));
00126 }
00127 
00128 TEST_F(SpaCostFunction2DTest, EvaluateAutoDiffCost) {
00129   std::array<double, 3> start_pose{{1., 1., 1.}};
00130   std::array<double, 3> end_pose{{10., 1., 100.}};
00131   std::array<const double*, 2> parameter_blocks{
00132       {start_pose.data(), end_pose.data()}};
00133 
00134   auto residuals_and_jacobian = EvaluateAutoDiffCost(parameter_blocks);
00135   EXPECT_THAT(residuals_and_jacobian.first,
00136               ElementsAre(Near(-3.86272), Near(8.57324), Near(-6.83333)));
00137   EXPECT_THAT(
00138       residuals_and_jacobian.second,
00139       ElementsAre(
00140           ElementsAre(Near(0.540302), Near(0.841471), Near(7.57324),
00141                       Near(-0.841471), Near(0.540302), Near(4.86272), Near(0),
00142                       Near(0), Near(10)),
00143           ElementsAre(Near(-0.540302), Near(-0.841471), Near(0), Near(0.841471),
00144                       Near(-0.540302), Near(0), Near(0), Near(0), Near(-10))));
00145 }
00146 
00147 }  // namespace
00148 }  // namespace optimization
00149 }  // namespace mapping
00150 }  // namespace cartographer


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