occupied_space_cost_function_2d.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/2d/scan_matching/occupied_space_cost_function_2d.h"
00018 
00019 #include "cartographer/mapping/probability_values.h"
00020 #include "ceres/cubic_interpolation.h"
00021 
00022 namespace cartographer {
00023 namespace mapping {
00024 namespace scan_matching {
00025 namespace {
00026 
00027 // Computes a cost for matching the 'point_cloud' to the 'grid' with
00028 // a 'pose'. The cost increases with poorer correspondence of the grid and the
00029 // point observation (e.g. points falling into less occupied space).
00030 class OccupiedSpaceCostFunction2D {
00031  public:
00032   OccupiedSpaceCostFunction2D(const double scaling_factor,
00033                               const sensor::PointCloud& point_cloud,
00034                               const Grid2D& grid)
00035       : scaling_factor_(scaling_factor),
00036         point_cloud_(point_cloud),
00037         grid_(grid) {}
00038 
00039   template <typename T>
00040   bool operator()(const T* const pose, T* residual) const {
00041     Eigen::Matrix<T, 2, 1> translation(pose[0], pose[1]);
00042     Eigen::Rotation2D<T> rotation(pose[2]);
00043     Eigen::Matrix<T, 2, 2> rotation_matrix = rotation.toRotationMatrix();
00044     Eigen::Matrix<T, 3, 3> transform;
00045     transform << rotation_matrix, translation, T(0.), T(0.), T(1.);
00046 
00047     const GridArrayAdapter adapter(grid_);
00048     ceres::BiCubicInterpolator<GridArrayAdapter> interpolator(adapter);
00049     const MapLimits& limits = grid_.limits();
00050 
00051     for (size_t i = 0; i < point_cloud_.size(); ++i) {
00052       // Note that this is a 2D point. The third component is a scaling factor.
00053       const Eigen::Matrix<T, 3, 1> point((T(point_cloud_[i].position.x())),
00054                                          (T(point_cloud_[i].position.y())),
00055                                          T(1.));
00056       const Eigen::Matrix<T, 3, 1> world = transform * point;
00057       interpolator.Evaluate(
00058           (limits.max().x() - world[0]) / limits.resolution() - 0.5 +
00059               static_cast<double>(kPadding),
00060           (limits.max().y() - world[1]) / limits.resolution() - 0.5 +
00061               static_cast<double>(kPadding),
00062           &residual[i]);
00063       residual[i] = scaling_factor_ * residual[i];
00064     }
00065     return true;
00066   }
00067 
00068  private:
00069   static constexpr int kPadding = INT_MAX / 4;
00070   class GridArrayAdapter {
00071    public:
00072     enum { DATA_DIMENSION = 1 };
00073 
00074     explicit GridArrayAdapter(const Grid2D& grid) : grid_(grid) {}
00075 
00076     void GetValue(const int row, const int column, double* const value) const {
00077       if (row < kPadding || column < kPadding || row >= NumRows() - kPadding ||
00078           column >= NumCols() - kPadding) {
00079         *value = kMaxCorrespondenceCost;
00080       } else {
00081         *value = static_cast<double>(grid_.GetCorrespondenceCost(
00082             Eigen::Array2i(column - kPadding, row - kPadding)));
00083       }
00084     }
00085 
00086     int NumRows() const {
00087       return grid_.limits().cell_limits().num_y_cells + 2 * kPadding;
00088     }
00089 
00090     int NumCols() const {
00091       return grid_.limits().cell_limits().num_x_cells + 2 * kPadding;
00092     }
00093 
00094    private:
00095     const Grid2D& grid_;
00096   };
00097 
00098   OccupiedSpaceCostFunction2D(const OccupiedSpaceCostFunction2D&) = delete;
00099   OccupiedSpaceCostFunction2D& operator=(const OccupiedSpaceCostFunction2D&) =
00100       delete;
00101 
00102   const double scaling_factor_;
00103   const sensor::PointCloud& point_cloud_;
00104   const Grid2D& grid_;
00105 };
00106 
00107 }  // namespace
00108 
00109 ceres::CostFunction* CreateOccupiedSpaceCostFunction2D(
00110     const double scaling_factor, const sensor::PointCloud& point_cloud,
00111     const Grid2D& grid) {
00112   return new ceres::AutoDiffCostFunction<OccupiedSpaceCostFunction2D,
00113                                          ceres::DYNAMIC /* residuals */,
00114                                          3 /* pose variables */>(
00115       new OccupiedSpaceCostFunction2D(scaling_factor, point_cloud, grid),
00116       point_cloud.size());
00117 }
00118 
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