interpolated_tsdf_2d.h
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 #ifndef CARTOGRAPHER_MAPPING_INTERNAL_2D_SCAN_MATCHING_TSDF_INTERPOLATED_TSDF_2D_H_
00018 #define CARTOGRAPHER_MAPPING_INTERNAL_2D_SCAN_MATCHING_TSDF_INTERPOLATED_TSDF_2D_H_
00019 
00020 #include <cmath>
00021 
00022 #include "cartographer/mapping/2d/tsdf_2d.h"
00023 
00024 namespace cartographer {
00025 namespace mapping {
00026 namespace scan_matching {
00027 
00028 // Interpolates between TSDF2D pixels with bilinear interpolation.
00029 //
00030 // This class is templated to work with Ceres autodiff.
00031 class InterpolatedTSDF2D {
00032  public:
00033   explicit InterpolatedTSDF2D(const TSDF2D& grid) : tsdf_(grid) {}
00034 
00035   InterpolatedTSDF2D(const InterpolatedTSDF2D&) = delete;
00036   InterpolatedTSDF2D& operator=(const InterpolatedTSDF2D&) = delete;
00037 
00038   // Returns the interpolated correspondence cost at (x,y). Cells with at least
00039   // one 'unknown' interpolation point result in "MaxCorrespondenceCost()" with
00040   // zero gradient.
00041   template <typename T>
00042   T GetCorrespondenceCost(const T& x, const T& y) const {
00043     float x1, y1, x2, y2;
00044     ComputeInterpolationDataPoints(x, y, &x1, &y1, &x2, &y2);
00045 
00046     const Eigen::Array2i index1 =
00047         tsdf_.limits().GetCellIndex(Eigen::Vector2f(x1, y1));
00048 
00049     const float w11 = tsdf_.GetWeight(index1);
00050     const float w12 = tsdf_.GetWeight(index1 + Eigen::Array2i(-1, 0));
00051     const float w21 = tsdf_.GetWeight(index1 + Eigen::Array2i(0, -1));
00052     const float w22 = tsdf_.GetWeight(index1 + Eigen::Array2i(-1, -1));
00053     if (w11 == 0.0 || w12 == 0.0 || w21 == 0.0 || w22 == 0.0) {
00054       return T(tsdf_.GetMaxCorrespondenceCost());
00055     }
00056 
00057     const float q11 = tsdf_.GetCorrespondenceCost(index1);
00058     const float q12 =
00059         tsdf_.GetCorrespondenceCost(index1 + Eigen::Array2i(-1, 0));
00060     const float q21 =
00061         tsdf_.GetCorrespondenceCost(index1 + Eigen::Array2i(0, -1));
00062     const float q22 =
00063         tsdf_.GetCorrespondenceCost(index1 + Eigen::Array2i(-1, -1));
00064 
00065     return InterpolateBilinear(x, y, x1, y1, x2, y2, q11, q12, q21, q22);
00066   }
00067 
00068   // Returns the interpolated weight at (x,y).
00069   template <typename T>
00070   T GetWeight(const T& x, const T& y) const {
00071     float x1, y1, x2, y2;
00072     ComputeInterpolationDataPoints(x, y, &x1, &y1, &x2, &y2);
00073 
00074     const Eigen::Array2i index1 =
00075         tsdf_.limits().GetCellIndex(Eigen::Vector2f(x1, y1));
00076     const float q11 = tsdf_.GetWeight(index1);
00077     const float q12 = tsdf_.GetWeight(index1 + Eigen::Array2i(-1, 0));
00078     const float q21 = tsdf_.GetWeight(index1 + Eigen::Array2i(0, -1));
00079     const float q22 = tsdf_.GetWeight(index1 + Eigen::Array2i(-1, -1));
00080 
00081     return InterpolateBilinear(x, y, x1, y1, x2, y2, q11, q12, q21, q22);
00082   }
00083 
00084  private:
00085   template <typename T>
00086   void ComputeInterpolationDataPoints(const T& x, const T& y, float* x1,
00087                                       float* y1, float* x2, float* y2) const {
00088     const Eigen::Vector2f lower = CenterOfLowerPixel(x, y);
00089     *x1 = lower.x();
00090     *y1 = lower.y();
00091     *x2 = lower.x() + static_cast<float>(tsdf_.limits().resolution());
00092     *y2 = lower.y() + static_cast<float>(tsdf_.limits().resolution());
00093   }
00094 
00095   template <typename T>
00096   T InterpolateBilinear(const T& x, const T& y, float x1, float y1, float x2,
00097                         float y2, float q11, float q12, float q21,
00098                         float q22) const {
00099     const T normalized_x = (x - T(x1)) / T(x2 - x1);
00100     const T normalized_y = (y - T(y1)) / T(y2 - y1);
00101     const T q1 = T(q12 - q11) * normalized_y + T(q11);
00102     const T q2 = T(q22 - q21) * normalized_y + T(q21);
00103     return T(q2 - q1) * normalized_x + T(q1);
00104   }
00105 
00106   // Center of the next lower pixel, i.e., not necessarily the pixel containing
00107   // (x, y). For each dimension, the largest pixel index so that the
00108   // corresponding center is at most the given coordinate.
00109   Eigen::Vector2f CenterOfLowerPixel(double x, double y) const {
00110     // Center of the cell containing (x, y).
00111     Eigen::Vector2f center = tsdf_.limits().GetCellCenter(
00112         tsdf_.limits().GetCellIndex(Eigen::Vector2f(x, y)));
00113     // Move to the next lower pixel center.
00114     if (center.x() > x) {
00115       center.x() -= tsdf_.limits().resolution();
00116     }
00117     if (center.y() > y) {
00118       center.y() -= tsdf_.limits().resolution();
00119     }
00120     return center;
00121   }
00122 
00123   // Uses the scalar part of a Ceres Jet.
00124   template <typename T>
00125   Eigen::Vector2f CenterOfLowerPixel(const T& jet_x, const T& jet_y) const {
00126     return CenterOfLowerPixel(jet_x.a, jet_y.a);
00127   }
00128 
00129   const TSDF2D& tsdf_;
00130 };
00131 
00132 }  // namespace scan_matching
00133 }  // namespace mapping
00134 }  // namespace cartographer
00135 
00136 #endif  // CARTOGRAPHER_MAPPING_INTERNAL_2D_SCAN_MATCHING_TSDF_INTERPOLATED_TSDF_2D_H_


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