fast_correlative_scan_matcher_2d.h
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 // This is an implementation of the algorithm described in "Real-Time
00018 // Correlative Scan Matching" by Olson.
00019 //
00020 // It is similar to the RealTimeCorrelativeScanMatcher but has a different
00021 // trade-off: Scan matching is faster because more effort is put into the
00022 // precomputation done for a given map. However, this map is immutable after
00023 // construction.
00024 
00025 #ifndef CARTOGRAPHER_MAPPING_INTERNAL_2D_SCAN_MATCHING_FAST_CORRELATIVE_SCAN_MATCHER_2D_H_
00026 #define CARTOGRAPHER_MAPPING_INTERNAL_2D_SCAN_MATCHING_FAST_CORRELATIVE_SCAN_MATCHER_2D_H_
00027 
00028 #include <memory>
00029 #include <vector>
00030 
00031 #include "Eigen/Core"
00032 #include "cartographer/common/port.h"
00033 #include "cartographer/mapping/2d/grid_2d.h"
00034 #include "cartographer/mapping/internal/2d/scan_matching/correlative_scan_matcher_2d.h"
00035 #include "cartographer/mapping/proto/scan_matching/fast_correlative_scan_matcher_options_2d.pb.h"
00036 #include "cartographer/sensor/point_cloud.h"
00037 
00038 namespace cartographer {
00039 namespace mapping {
00040 namespace scan_matching {
00041 
00042 proto::FastCorrelativeScanMatcherOptions2D
00043 CreateFastCorrelativeScanMatcherOptions2D(
00044     common::LuaParameterDictionary* parameter_dictionary);
00045 
00046 // A precomputed grid that contains in each cell (x0, y0) the maximum
00047 // probability in the width x width area defined by x0 <= x < x0 + width and
00048 // y0 <= y < y0.
00049 class PrecomputationGrid2D {
00050  public:
00051   PrecomputationGrid2D(const Grid2D& grid, const CellLimits& limits, int width,
00052                        std::vector<float>* reusable_intermediate_grid);
00053 
00054   // Returns a value between 0 and 255 to represent probabilities between
00055   // min_score and max_score.
00056   int GetValue(const Eigen::Array2i& xy_index) const {
00057     const Eigen::Array2i local_xy_index = xy_index - offset_;
00058     // The static_cast<unsigned> is for performance to check with 2 comparisons
00059     // xy_index.x() < offset_.x() || xy_index.y() < offset_.y() ||
00060     // local_xy_index.x() >= wide_limits_.num_x_cells ||
00061     // local_xy_index.y() >= wide_limits_.num_y_cells
00062     // instead of using 4 comparisons.
00063     if (static_cast<unsigned>(local_xy_index.x()) >=
00064             static_cast<unsigned>(wide_limits_.num_x_cells) ||
00065         static_cast<unsigned>(local_xy_index.y()) >=
00066             static_cast<unsigned>(wide_limits_.num_y_cells)) {
00067       return 0;
00068     }
00069     const int stride = wide_limits_.num_x_cells;
00070     return cells_[local_xy_index.x() + local_xy_index.y() * stride];
00071   }
00072 
00073   // Maps values from [0, 255] to [min_score, max_score].
00074   float ToScore(float value) const {
00075     return min_score_ + value * ((max_score_ - min_score_) / 255.f);
00076   }
00077 
00078  private:
00079   uint8 ComputeCellValue(float probability) const;
00080 
00081   // Offset of the precomputation grid in relation to the 'grid'
00082   // including the additional 'width' - 1 cells.
00083   const Eigen::Array2i offset_;
00084 
00085   // Size of the precomputation grid.
00086   const CellLimits wide_limits_;
00087 
00088   const float min_score_;
00089   const float max_score_;
00090 
00091   // Probabilites mapped to 0 to 255.
00092   std::vector<uint8> cells_;
00093 };
00094 
00095 class PrecomputationGridStack2D {
00096  public:
00097   PrecomputationGridStack2D(
00098       const Grid2D& grid,
00099       const proto::FastCorrelativeScanMatcherOptions2D& options);
00100 
00101   const PrecomputationGrid2D& Get(int index) {
00102     return precomputation_grids_[index];
00103   }
00104 
00105   int max_depth() const { return precomputation_grids_.size() - 1; }
00106 
00107  private:
00108   std::vector<PrecomputationGrid2D> precomputation_grids_;
00109 };
00110 
00111 // An implementation of "Real-Time Correlative Scan Matching" by Olson.
00112 class FastCorrelativeScanMatcher2D {
00113  public:
00114   FastCorrelativeScanMatcher2D(
00115       const Grid2D& grid,
00116       const proto::FastCorrelativeScanMatcherOptions2D& options);
00117   ~FastCorrelativeScanMatcher2D();
00118 
00119   FastCorrelativeScanMatcher2D(const FastCorrelativeScanMatcher2D&) = delete;
00120   FastCorrelativeScanMatcher2D& operator=(const FastCorrelativeScanMatcher2D&) =
00121       delete;
00122 
00123   // Aligns 'point_cloud' within the 'grid' given an
00124   // 'initial_pose_estimate'. If a score above 'min_score' (excluding equality)
00125   // is possible, true is returned, and 'score' and 'pose_estimate' are updated
00126   // with the result.
00127   bool Match(const transform::Rigid2d& initial_pose_estimate,
00128              const sensor::PointCloud& point_cloud, float min_score,
00129              float* score, transform::Rigid2d* pose_estimate) const;
00130 
00131   // Aligns 'point_cloud' within the full 'grid', i.e., not
00132   // restricted to the configured search window. If a score above 'min_score'
00133   // (excluding equality) is possible, true is returned, and 'score' and
00134   // 'pose_estimate' are updated with the result.
00135   bool MatchFullSubmap(const sensor::PointCloud& point_cloud, float min_score,
00136                        float* score, transform::Rigid2d* pose_estimate) const;
00137 
00138  private:
00139   // The actual implementation of the scan matcher, called by Match() and
00140   // MatchFullSubmap() with appropriate 'initial_pose_estimate' and
00141   // 'search_parameters'.
00142   bool MatchWithSearchParameters(
00143       SearchParameters search_parameters,
00144       const transform::Rigid2d& initial_pose_estimate,
00145       const sensor::PointCloud& point_cloud, float min_score, float* score,
00146       transform::Rigid2d* pose_estimate) const;
00147   std::vector<Candidate2D> ComputeLowestResolutionCandidates(
00148       const std::vector<DiscreteScan2D>& discrete_scans,
00149       const SearchParameters& search_parameters) const;
00150   std::vector<Candidate2D> GenerateLowestResolutionCandidates(
00151       const SearchParameters& search_parameters) const;
00152   void ScoreCandidates(const PrecomputationGrid2D& precomputation_grid,
00153                        const std::vector<DiscreteScan2D>& discrete_scans,
00154                        const SearchParameters& search_parameters,
00155                        std::vector<Candidate2D>* const candidates) const;
00156   Candidate2D BranchAndBound(const std::vector<DiscreteScan2D>& discrete_scans,
00157                              const SearchParameters& search_parameters,
00158                              const std::vector<Candidate2D>& candidates,
00159                              int candidate_depth, float min_score) const;
00160 
00161   const proto::FastCorrelativeScanMatcherOptions2D options_;
00162   MapLimits limits_;
00163   std::unique_ptr<PrecomputationGridStack2D> precomputation_grid_stack_;
00164 };
00165 
00166 }  // namespace scan_matching
00167 }  // namespace mapping
00168 }  // namespace cartographer
00169 
00170 #endif  // CARTOGRAPHER_MAPPING_INTERNAL_2D_SCAN_MATCHING_FAST_CORRELATIVE_SCAN_MATCHER_2D_H_


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