38 if (pointer->type() !=
"exotica::UnconstrainedEndPoseProblem")
40 ThrowNamed(
"This IKSolver can't solve problem of type '" << pointer->type() <<
"'!");
42 MotionSolver::SpecifyProblem(pointer);
45 W_inv_ = prob_->
W.inverse();
48 if (W_inv_.rows() != prob_->N || W_inv_.cols() != prob_->N)
49 ThrowNamed(
"Size of W incorrect: (" << W_inv_.rows() <<
", " << W_inv_.cols() <<
"), when expected: (" << prob_->N <<
", " << prob_->N <<
")");
52 if (parameters_.MaxStep != 0.0 && GetNumberOfMaxIterations() != 1)
53 WARNING_NAMED(
"IKSolver",
"Deprecated configuration detected: MaxStep (given: " << parameters_.MaxStep <<
") only works if MaxIterations == 1 (given: " << GetNumberOfMaxIterations() <<
")");
56 alpha_space_ = Eigen::VectorXd::LinSpaced(10, 1.0, 0.1);
58 lambda_ = parameters_.RegularizationRate;
59 th_stepinc_ = parameters_.ThresholdRegularizationIncrease;
60 th_stepdec_ = parameters_.ThresholdRegularizationDecrease;
61 regmax_ = parameters_.MaximumRegularization;
63 th_stop_ = parameters_.GradientToleranceConvergenceThreshold;
68 yd_.resize(prob_->cost.length_jacobian);
69 cost_jacobian_.resize(prob_->cost.length_jacobian, prob_->N);
70 J_pseudo_inverse_.resize(prob_->N, prob_->cost.length_jacobian);
71 J_tmp_.resize(prob_->cost.length_jacobian, prob_->cost.length_jacobian);
74 void IKSolver::Solve(Eigen::MatrixXd& solution)
76 if (!prob_)
ThrowNamed(
"Solver has not been initialized!");
80 prob_->ResetCostEvolution(GetNumberOfMaxIterations() + 1);
81 lambda_ = parameters_.RegularizationRate;
82 q_ = prob_->ApplyStartState();
84 if (prob_->q_nominal.rows() == prob_->N)
86 WARNING(
"Nominal state regularization is no longer supported - please use a JointPose task-map.");
90 for (i = 0; i < GetNumberOfMaxIterations(); ++i)
93 error_ = prob_->GetScalarCost();
94 prob_->SetCostEvolution(i, error_);
98 if (error_ < parameters_.Tolerance)
100 prob_->termination_criterion = TerminationCriterion::FunctionTolerance;
104 yd_.noalias() = prob_->cost.S * prob_->cost.ydiff;
105 cost_jacobian_.noalias() = prob_->cost.S * prob_->cost.jacobian;
110 bool decomposition_ok =
false;
111 while (!decomposition_ok)
113 J_tmp_.noalias() = cost_jacobian_ * W_inv_ * cost_jacobian_.transpose();
114 J_tmp_.diagonal().array() += lambda_;
115 J_decomposition_.compute(J_tmp_);
116 if (J_decomposition_.info() != Eigen::Success)
118 IncreaseRegularization();
119 if (lambda_ > regmax_)
121 WARNING(
"Divergence in Cholesky decomposition :-(");
122 prob_->termination_criterion = TerminationCriterion::Divergence;
130 decomposition_ok =
true;
133 J_tmp_.noalias() = J_decomposition_.solve(Eigen::MatrixXd::Identity(prob_->cost.length_jacobian, prob_->cost.length_jacobian));
134 J_pseudo_inverse_.noalias() = W_inv_ * cost_jacobian_.transpose() * J_tmp_;
136 qd_.noalias() = J_pseudo_inverse_ * yd_;
139 if (GetNumberOfMaxIterations() == 1 && parameters_.MaxStep != 0.0)
141 ScaleToStepSize(qd_);
147 for (
int ai = 0; ai < alpha_space_.size(); ++ai)
149 steplength_ = alpha_space_(ai);
150 Eigen::VectorXd q_tmp = q_ - steplength_ * qd_;
151 prob_->Update(q_tmp);
152 error_ = prob_->GetScalarCost();
154 if (error_ < error_prev_)
164 step_ = qd_.squaredNorm();
167 stop_ = cost_jacobian_.norm();
170 if (debug_) PrintDebug(i);
173 if (step_ < parameters_.StepToleranceConvergenceThreshold)
175 prob_->termination_criterion = TerminationCriterion::StepTolerance;
180 if (stop_ < parameters_.GradientToleranceConvergenceThreshold)
182 prob_->termination_criterion = TerminationCriterion::GradientTolerance;
187 if (GetNumberOfMaxIterations() == 1 && parameters_.MaxStep == 0.0 && steplength_ > th_stepdec_)
189 DecreaseRegularization();
191 if (GetNumberOfMaxIterations() == 1 && parameters_.MaxStep == 0.0 && steplength_ <= th_stepinc_)
193 IncreaseRegularization();
194 if (lambda_ == regmax_)
196 prob_->termination_criterion = TerminationCriterion::Divergence;
203 if (i == GetNumberOfMaxIterations())
205 prob_->termination_criterion = TerminationCriterion::IterationLimit;
210 switch (prob_->termination_criterion)
212 case TerminationCriterion::GradientTolerance:
213 HIGHLIGHT_NAMED(
"IKSolver",
"Reached convergence (" << std::scientific << stop_ <<
" < " << parameters_.GradientToleranceConvergenceThreshold <<
")");
215 case TerminationCriterion::FunctionTolerance:
216 HIGHLIGHT_NAMED(
"IKSolver",
"Reached absolute function tolerance (" << std::scientific << error_ <<
" < " << parameters_.Tolerance <<
")");
218 case TerminationCriterion::StepTolerance:
219 HIGHLIGHT_NAMED(
"IKSolver",
"Reached step tolerance (" << std::scientific << step_ <<
" < " << parameters_.StepToleranceConvergenceThreshold <<
")");
221 case TerminationCriterion::Divergence:
222 WARNING_NAMED(
"IKSolver",
"Regularization exceeds maximum regularization: " << lambda_ <<
" > " << regmax_);
224 case TerminationCriterion::IterationLimit:
233 solution.resize(1, prob_->N);
234 solution.row(0) = q_.transpose();
240 const double max_vel = xd.cwiseAbs().maxCoeff();
241 if (max_vel > parameters_.MaxStep)
243 xd = xd * parameters_.MaxStep / max_vel;
#define WARNING_NAMED(name, x)
Eigen::Ref< Eigen::VectorXd > VectorXdRef
#define REGISTER_MOTIONSOLVER_TYPE(TYPE, DERIV)
#define HIGHLIGHT_NAMED(name, x)
Weighted and Regularized Pseudo-Inverse Inverse Kinematics Solver The solver solves a weighted and re...
double GetDuration() const
std::shared_ptr< PlanningProblem > PlanningProblemPtr