| 773 | } |
| 774 | |
| 775 | bool RotationAveragingSolver::SolveIRLS(RotationAveragingProblem& problem) { |
| 776 | SparseCholeskyWithFallbackSolver solver; |
| 777 | bool pattern_analyzed = false; |
| 778 | |
| 779 | const double sigma = DegToRad(options_.irls_loss_parameter_sigma); |
| 780 | |
| 781 | Eigen::SparseMatrix<double> at_weight; |
| 782 | Eigen::SparseMatrix<double> at_weight_a; |
| 783 | Eigen::VectorXd step(problem.NumParameters()); |
| 784 | |
| 785 | int iteration = 0; |
| 786 | for (iteration = 0; iteration < options_.max_num_irls_iterations; |
| 787 | iteration++) { |
| 788 | problem.ComputeResiduals(); |
| 789 | |
| 790 | auto weights_irls = ComputeIRLSWeights(problem, sigma); |
| 791 | if (!weights_irls) { |
| 792 | return false; |
| 793 | } |
| 794 | |
| 795 | // Optionally add a small Tikhonov ridge to stabilize poorly conditioned |
| 796 | // but mathematically PD systems. When zero (default), no regularization |
| 797 | // is added. |
| 798 | at_weight = |
| 799 | problem.ConstraintMatrix().transpose() * weights_irls->asDiagonal(); |
| 800 | at_weight_a = at_weight * problem.ConstraintMatrix(); |
| 801 | if (options_.ridge_regularization > 0) { |
| 802 | for (int i = 0; i < at_weight_a.cols(); ++i) { |
| 803 | at_weight_a.coeffRef(i, i) += options_.ridge_regularization; |
| 804 | } |
| 805 | } |
| 806 | |
| 807 | if (!pattern_analyzed) { |
| 808 | solver.AnalyzePattern(at_weight_a); |
| 809 | pattern_analyzed = true; |
| 810 | } |
| 811 | if (!solver.Factorize(at_weight_a)) { |
| 812 | LOG(ERROR) << "IRLS Cholesky factorization failed (iteration " |
| 813 | << iteration << ")"; |
| 814 | return false; |
| 815 | } |
| 816 | |
| 817 | if (!solver.Solve(at_weight * problem.Residuals(), &step) || |
| 818 | step.array().isNaN().any()) { |
| 819 | LOG(ERROR) << "IRLS solve failed (iteration " << iteration << ")"; |
| 820 | return false; |
| 821 | } |
| 822 | problem.UpdateState(step); |
| 823 | |
| 824 | const double avg_step = problem.AverageStepSize(step); |
| 825 | VLOG(2) << "IRLS iteration " << iteration << ", average step: " << avg_step; |
| 826 | |
| 827 | if (avg_step < options_.irls_step_convergence_threshold) { |
| 828 | iteration++; |
| 829 | break; |
| 830 | } |
| 831 | } |
| 832 | VLOG(2) << "IRLS total iteration: " << iteration; |
nothing calls this directly
no test coverage detected