Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "cartographer/mapping/internal/2d/scan_matching/ceres_scan_matcher_2d.h"
00018
00019 #include <utility>
00020 #include <vector>
00021
00022 #include "Eigen/Core"
00023 #include "cartographer/common/ceres_solver_options.h"
00024 #include "cartographer/common/lua_parameter_dictionary.h"
00025 #include "cartographer/mapping/2d/grid_2d.h"
00026 #include "cartographer/mapping/internal/2d/scan_matching/occupied_space_cost_function_2d.h"
00027 #include "cartographer/mapping/internal/2d/scan_matching/rotation_delta_cost_functor_2d.h"
00028 #include "cartographer/mapping/internal/2d/scan_matching/translation_delta_cost_functor_2d.h"
00029 #include "cartographer/mapping/internal/2d/scan_matching/tsdf_match_cost_function_2d.h"
00030 #include "cartographer/transform/transform.h"
00031 #include "ceres/ceres.h"
00032 #include "glog/logging.h"
00033
00034 namespace cartographer {
00035 namespace mapping {
00036 namespace scan_matching {
00037
00038 proto::CeresScanMatcherOptions2D CreateCeresScanMatcherOptions2D(
00039 common::LuaParameterDictionary* const parameter_dictionary) {
00040 proto::CeresScanMatcherOptions2D options;
00041 options.set_occupied_space_weight(
00042 parameter_dictionary->GetDouble("occupied_space_weight"));
00043 options.set_translation_weight(
00044 parameter_dictionary->GetDouble("translation_weight"));
00045 options.set_rotation_weight(
00046 parameter_dictionary->GetDouble("rotation_weight"));
00047 *options.mutable_ceres_solver_options() =
00048 common::CreateCeresSolverOptionsProto(
00049 parameter_dictionary->GetDictionary("ceres_solver_options").get());
00050 return options;
00051 }
00052
00053 CeresScanMatcher2D::CeresScanMatcher2D(
00054 const proto::CeresScanMatcherOptions2D& options)
00055 : options_(options),
00056 ceres_solver_options_(
00057 common::CreateCeresSolverOptions(options.ceres_solver_options())) {
00058 ceres_solver_options_.linear_solver_type = ceres::DENSE_QR;
00059 }
00060
00061 CeresScanMatcher2D::~CeresScanMatcher2D() {}
00062
00063 void CeresScanMatcher2D::Match(const Eigen::Vector2d& target_translation,
00064 const transform::Rigid2d& initial_pose_estimate,
00065 const sensor::PointCloud& point_cloud,
00066 const Grid2D& grid,
00067 transform::Rigid2d* const pose_estimate,
00068 ceres::Solver::Summary* const summary) const {
00069 double ceres_pose_estimate[3] = {initial_pose_estimate.translation().x(),
00070 initial_pose_estimate.translation().y(),
00071 initial_pose_estimate.rotation().angle()};
00072 ceres::Problem problem;
00073 CHECK_GT(options_.occupied_space_weight(), 0.);
00074 switch (grid.GetGridType()) {
00075 case GridType::PROBABILITY_GRID:
00076 problem.AddResidualBlock(
00077 CreateOccupiedSpaceCostFunction2D(
00078 options_.occupied_space_weight() /
00079 std::sqrt(static_cast<double>(point_cloud.size())),
00080 point_cloud, grid),
00081 nullptr , ceres_pose_estimate);
00082 break;
00083 case GridType::TSDF:
00084 problem.AddResidualBlock(
00085 CreateTSDFMatchCostFunction2D(
00086 options_.occupied_space_weight() /
00087 std::sqrt(static_cast<double>(point_cloud.size())),
00088 point_cloud, static_cast<const TSDF2D&>(grid)),
00089 nullptr , ceres_pose_estimate);
00090 break;
00091 }
00092 CHECK_GT(options_.translation_weight(), 0.);
00093 problem.AddResidualBlock(
00094 TranslationDeltaCostFunctor2D::CreateAutoDiffCostFunction(
00095 options_.translation_weight(), target_translation),
00096 nullptr , ceres_pose_estimate);
00097 CHECK_GT(options_.rotation_weight(), 0.);
00098 problem.AddResidualBlock(
00099 RotationDeltaCostFunctor2D::CreateAutoDiffCostFunction(
00100 options_.rotation_weight(), ceres_pose_estimate[2]),
00101 nullptr , ceres_pose_estimate);
00102
00103 ceres::Solve(ceres_solver_options_, &problem, summary);
00104
00105 *pose_estimate = transform::Rigid2d(
00106 {ceres_pose_estimate[0], ceres_pose_estimate[1]}, ceres_pose_estimate[2]);
00107 }
00108
00109 }
00110 }
00111 }