18 CeresSolver::CeresSolver() :
19 nodes_(new
std::unordered_map<int,
Eigen::Vector3d>()),
20 blocks_(new
std::unordered_map<
std::size_t,
21 ceres::ResidualBlockId>()),
22 problem_(
NULL), was_constant_set_(false)
26 std::string solver_type, preconditioner_type, dogleg_type,
27 trust_strategy, loss_fn, mode;
28 nh.
getParam(
"ceres_linear_solver", solver_type);
29 nh.
getParam(
"ceres_preconditioner", preconditioner_type);
30 nh.
getParam(
"ceres_dogleg_type", dogleg_type);
31 nh.
getParam(
"ceres_trust_strategy", trust_strategy);
32 nh.
getParam(
"ceres_loss_function", loss_fn);
44 if (loss_fn ==
"HuberLoss")
46 ROS_INFO(
"CeresSolver: Using HuberLoss loss function.");
49 else if (loss_fn ==
"CauchyLoss")
51 ROS_INFO(
"CeresSolver: Using CauchyLoss loss function.");
56 options_.linear_solver_type = ceres::SPARSE_NORMAL_CHOLESKY;
57 if (solver_type ==
"SPARSE_SCHUR")
59 ROS_INFO(
"CeresSolver: Using SPARSE_SCHUR solver.");
60 options_.linear_solver_type = ceres::SPARSE_SCHUR;
62 else if (solver_type ==
"ITERATIVE_SCHUR")
64 ROS_INFO(
"CeresSolver: Using ITERATIVE_SCHUR solver.");
65 options_.linear_solver_type = ceres::ITERATIVE_SCHUR;
67 else if (solver_type ==
"CGNR")
69 ROS_INFO(
"CeresSolver: Using CGNR solver.");
70 options_.linear_solver_type = ceres::CGNR;
74 options_.preconditioner_type = ceres::JACOBI;
75 if (preconditioner_type ==
"IDENTITY")
77 ROS_INFO(
"CeresSolver: Using IDENTITY preconditioner.");
78 options_.preconditioner_type = ceres::IDENTITY;
80 else if (preconditioner_type ==
"SCHUR_JACOBI")
82 ROS_INFO(
"CeresSolver: Using SCHUR_JACOBI preconditioner.");
83 options_.preconditioner_type = ceres::SCHUR_JACOBI;
86 if (
options_.preconditioner_type == ceres::CLUSTER_JACOBI ||
87 options_.preconditioner_type == ceres::CLUSTER_TRIDIAGONAL)
91 options_.visibility_clustering_type = ceres::SINGLE_LINKAGE;
95 options_.trust_region_strategy_type = ceres::LEVENBERG_MARQUARDT;
96 if (trust_strategy ==
"DOGLEG")
98 ROS_INFO(
"CeresSolver: Using DOGLEG trust region strategy.");
99 options_.trust_region_strategy_type = ceres::DOGLEG;
103 if(
options_.trust_region_strategy_type == ceres::DOGLEG)
105 options_.dogleg_type = ceres::TRADITIONAL_DOGLEG;
106 if (dogleg_type ==
"SUBSPACE_DOGLEG")
108 ROS_INFO(
"CeresSolver: Using SUBSPACE_DOGLEG dogleg type.");
109 options_.dogleg_type = ceres::SUBSPACE_DOGLEG;
116 options_.parameter_tolerance = 1e-3;
118 options_.sparse_linear_algebra_library_type = ceres::SUITE_SPARSE;
119 options_.max_num_consecutive_invalid_steps = 3;
120 options_.max_consecutive_nonmonotonic_steps =
121 options_.max_num_consecutive_invalid_steps;
123 options_.use_nonmonotonic_steps =
true;
126 options_.min_relative_decrease = 1e-3;
128 options_.initial_trust_region_radius = 1e4;
129 options_.max_trust_region_radius = 1e8;
130 options_.min_trust_region_radius = 1e-16;
135 if(
options_.linear_solver_type == ceres::SPARSE_NORMAL_CHOLESKY)
140 if (mode == std::string(
"localization"))
177 ROS_ERROR(
"CeresSolver: Ceres was called when there are no nodes." 178 " This shouldn't happen.");
185 ROS_DEBUG(
"CeresSolver: Setting first node as a constant pose:" 195 ceres::Solver::Summary summary;
199 std::cout << summary.FullReport() <<
'\n';
202 if (!summary.IsSolutionUsable())
205 "Ceres could not find a usable solution to optimize.");
217 for ( iter; iter !=
nodes_->end(); ++iter )
219 pose.
SetX(iter->second(0));
220 pose.
SetY(iter->second(1));
222 corrections_.push_back(std::make_pair(iter->first, pose));
266 nodes_ =
new std::unordered_map<int, Eigen::Vector3d>();
267 blocks_ =
new std::unordered_map<std::size_t, ceres::ResidualBlockId>();
290 nodes_->insert(std::pair<int,Eigen::Vector3d>(
id,pose2d));
315 if (node1it ==
nodes_->end() ||
316 node2it ==
nodes_->end() || node1it == node2it)
318 ROS_WARN(
"CeresSolver: Failed to add constraint, could not find nodes.");
328 Eigen::Matrix3d sqrt_information;
329 sqrt_information(0,0) = precisionMatrix(0,0);
330 sqrt_information(0,1) = sqrt_information(1,0) = precisionMatrix(0,1);
331 sqrt_information(0,2) = sqrt_information(2,0) = precisionMatrix(0,2);
332 sqrt_information(1,1) = precisionMatrix(1,1);
333 sqrt_information(1,2) = sqrt_information(2,1) = precisionMatrix(1,2);
334 sqrt_information(2,2) = precisionMatrix(2,2);
338 pose2d(1), pose2d(2), sqrt_information);
339 ceres::ResidualBlockId block =
problem_->AddResidualBlock(
341 &node1it->second(0), &node1it->second(1), &node1it->second(2),
342 &node2it->second(0), &node2it->second(1), &node2it->second(2));
343 problem_->SetParameterization(&node1it->second(2),
345 problem_->SetParameterization(&node2it->second(2),
348 blocks_->insert(std::pair<std::size_t, ceres::ResidualBlockId>(
349 GetHash(node1, node2), block));
359 if (nodeit !=
nodes_->end())
365 ROS_ERROR(
"RemoveNode: Failed to find node matching id %i", (
int)
id);
374 std::unordered_map<std::size_t, ceres::ResidualBlockId>::iterator it_a =
376 std::unordered_map<std::size_t, ceres::ResidualBlockId>::iterator it_b =
380 problem_->RemoveResidualBlock(it_a->second);
383 else if (it_b !=
blocks_->end())
385 problem_->RemoveResidualBlock(it_b->second);
390 ROS_ERROR(
"RemoveConstraint: Failed to find residual block for %i %i",
391 (
int)sourceId, (
int)targetId);
403 double yaw_init = it->second(2);
405 it->second(2) += yaw_init;
417 pose = it->second(2);
std::unordered_map< int, Eigen::Vector3d >::iterator first_node_
virtual void AddConstraint(karto::Edge< karto::LocalizedRangeScan > *pEdge)
karto::ScanSolver::IdPoseVector corrections_
virtual void RemoveNode(kt_int32s id)
std::size_t GetHash(const int &x, const int &y)
const Pose2 & GetCorrectedPose() const
std::unordered_map< int, Eigen::Vector3d > * nodes_
ceres::LocalParameterization * angle_local_parameterization_
IMETHOD Vector diff(const Vector &p_w_a, const Vector &p_w_b, double dt=1)
const Matrix3 & GetCovariance()
virtual void RemoveConstraint(kt_int32s sourceId, kt_int32s targetId)
virtual const karto::ScanSolver::IdPoseVector & GetCorrections() const
Vertex< T > * GetTarget() const
virtual std::unordered_map< int, Eigen::Vector3d > * getGraph()
kt_int32s GetUniqueId() const
virtual void ModifyNode(const int &unique_id, Eigen::Vector3d pose)
ceres::LossFunction * loss_function_
bool getParam(const std::string &key, std::string &s) const
static ceres::LocalParameterization * Create()
static ceres::CostFunction * Create(double x_ab, double y_ab, double yaw_ab_radians, const Eigen::Matrix3d &sqrt_information)
ceres::Problem * problem_
ceres::Solver::Options options_
virtual void AddNode(karto::Vertex< karto::LocalizedRangeScan > *pVertex)
Vertex< T > * GetSource() const
virtual void GetNodeOrientation(const int &unique_id, double &pose)
ceres::Problem::Options options_problem_
std::vector< std::pair< kt_int32s, Pose2 > > IdPoseVector
void SetHeading(kt_double heading)
std::unordered_map< size_t, ceres::ResidualBlockId > * blocks_
boost::mutex nodes_mutex_
#define PLUGINLIB_EXPORT_CLASS(class_type, base_class_type)
const Pose2 & GetPoseDifference()
kt_double GetHeading() const