42 void BayesianIKSolver::Instantiate(
const BayesianIKSolverInitializer& init)
45 std::string mode = init.SweepMode;
46 if (mode ==
"Forwardly")
47 sweep_mode_ = FORWARD;
48 else if (mode ==
"Symmetric")
49 sweep_mode_ = SYMMETRIC;
50 else if (mode ==
"LocalGaussNewton")
51 sweep_mode_ = LOCAL_GAUSS_NEWTON;
52 else if (mode ==
"LocalGaussNewtonDamped")
53 sweep_mode_ = LOCAL_GAUSS_NEWTON_DAMPED;
56 ThrowNamed(
"Unknown sweep mode '" << init.SweepMode <<
"'");
58 max_backtrack_iterations_ = init.MaxBacktrackIterations;
59 minimum_step_tolerance_ = init.MinStep;
60 step_tolerance_ = init.StepTolerance;
61 function_tolerance_ = init.FunctionTolerance;
62 damping_init_ = init.Damping;
63 use_bwd_msg_ = init.UseBackwardMessage;
64 verbose_ = init.Verbose;
69 if (problem->type() !=
"exotica::UnconstrainedEndPoseProblem")
71 ThrowNamed(
"This solver can't use problem of type '" << problem->type() <<
"'!");
73 MotionSolver::SpecifyProblem(problem);
79 void BayesianIKSolver::Solve(Eigen::MatrixXd& solution)
81 prob_->ResetCostEvolution(GetNumberOfMaxIterations() + 1);
82 prob_->termination_criterion = TerminationCriterion::NotStarted;
85 Eigen::VectorXd q0 = prob_->ApplyStartState();
88 if (verbose_)
ROS_WARN_STREAM(
"BayesianIKSolver: Setting up the solver");
90 damping = damping_init_;
92 iteration_count_ = -1;
99 while (iteration_count_ < GetNumberOfMaxIterations())
102 if (Server::IsRos() && !
ros::ok())
104 if (debug_)
HIGHLIGHT(
"Solving cancelled by user");
105 prob_->termination_criterion = TerminationCriterion::UserDefined;
116 if (sweep_ >= max_backtrack_iterations_)
118 if (debug_)
HIGHLIGHT(
"Maximum backtrack iterations reached, exiting.");
119 prob_->termination_criterion = TerminationCriterion::BacktrackIterationLimit;
124 if (iteration_count_ > 1)
129 if ((damping != 0.0 && sweep_improved_cost_) || !(damping != 0.0))
136 if (d < minimum_step_tolerance_)
138 if (debug_)
HIGHLIGHT(
"Satisfied tolerance\titer=" << iteration_count_ <<
"\td=" << d <<
"\tminimum_step_tolerance=" << minimum_step_tolerance_);
139 prob_->termination_criterion = TerminationCriterion::StepTolerance;
145 if ((cost_prev_ - cost_) <= function_tolerance_ * std::max(1.0, std::abs(cost_)))
147 if (debug_)
HIGHLIGHT(
"Function tolerance achieved: " << (cost_prev_ - cost_) <<
" <= " << function_tolerance_ * std::max(1.0, std::abs(cost_)));
148 prob_->termination_criterion = TerminationCriterion::FunctionTolerance;
157 if (iteration_count_ == GetNumberOfMaxIterations())
159 if (debug_)
HIGHLIGHT(
"Maximum iterations reached");
160 prob_->termination_criterion = TerminationCriterion::IterationLimit;
163 solution.resize(1, prob_->N);
168 void BayesianIKSolver::InitMessages()
170 s = Eigen::VectorXd::Zero(prob_->N);
171 Sinv = Eigen::MatrixXd::Zero(prob_->N, prob_->N);
172 v = Eigen::VectorXd::Zero(prob_->N);
173 Vinv = Eigen::MatrixXd::Zero(prob_->N, prob_->N);
187 b = Eigen::VectorXd::Zero(prob_->N);
188 damping_reference_ = Eigen::VectorXd::Zero(prob_->N);
189 Binv = Eigen::MatrixXd::Zero(prob_->N, prob_->N);
190 r = Eigen::VectorXd::Zero(prob_->N);
191 R = Eigen::MatrixXd::Zero(prob_->N, prob_->N);
193 qhat = Eigen::VectorXd::Zero(prob_->N);
197 void BayesianIKSolver::InitTrajectory(
const Eigen::VectorXd& q_init)
201 damping_reference_ = q_init;
206 Sinv.diagonal().setConstant(damping);
208 Vinv.diagonal().setConstant(damping);
211 if (prob_->W.rows() != prob_->N)
213 ThrowNamed(prob_->W.rows() <<
"!=" << prob_->N);
221 UpdateTaskMessage(b, 0.0);
223 cost_ = EvaluateTrajectory(b,
true);
225 prob_->SetCostEvolution(0, cost_);
226 if (cost_ < 0)
ThrowNamed(
"Invalid cost! " << cost_);
227 if (verbose_)
HIGHLIGHT(
"Initial cost, updates: " << update_count_ <<
", cost: " << cost_);
231 void BayesianIKSolver::UpdateFwdMessage()
233 Eigen::MatrixXd barS(prob_->N, prob_->N), St;
235 s = barS * (Sinv *
s +
r);
240 void BayesianIKSolver::UpdateBwdMessage()
242 Eigen::MatrixXd barV(prob_->N, prob_->N), Vt;
247 Vinv.diagonal().setConstant(1);
252 Vinv = bwd_msg_Vinv_;
256 void BayesianIKSolver::UpdateTaskMessage(
const Eigen::Ref<const Eigen::VectorXd>& qhat_t,
double tolerance,
257 double max_step_size)
259 Eigen::VectorXd
diff = qhat_t - qhat;
260 if ((diff.array().abs().maxCoeff() < tolerance))
return;
261 double nrm = diff.norm();
262 if (max_step_size > 0. && nrm > max_step_size)
264 qhat += diff * (max_step_size / nrm);
277 void BayesianIKSolver::GetTaskCosts()
284 for (
int i = 0; i < prob_->cost.num_tasks; ++i)
286 prec = prob_->cost.rho(i);
289 const int& start = prob_->cost.indexing[i].start_jacobian;
290 const int& len = prob_->cost.indexing[i].length_jacobian;
291 Jt = prob_->cost.jacobian.middleRows(start, len).transpose();
292 R += prec * Jt * prob_->cost.jacobian.middleRows(start, len);
293 r += prec * Jt * (-prob_->cost.ydiff.segment(start, len) + prob_->cost.jacobian.middleRows(start, len) * qhat);
294 rhat += prec * (-prob_->cost.ydiff.segment(start, len) + prob_->cost.jacobian.middleRows(start, len) * qhat).squaredNorm();
299 void BayesianIKSolver::UpdateTimestep(
bool update_fwd,
bool update_bwd,
300 int max_relocation_iterations,
double tolerance,
bool force_relocation,
301 double max_step_size)
303 if (update_fwd) UpdateFwdMessage();
304 if (update_bwd) UpdateBwdMessage();
308 Binv = Sinv + Vinv + R + Eigen::MatrixXd::Identity(prob_->N, prob_->N) * damping;
309 AinvBSymPosDef(b, Binv, Sinv *
s + Vinv * v +
r + damping * damping_reference_);
313 Binv = Sinv + Vinv + R;
317 for (
int k = 0; k < max_relocation_iterations && !(Server::IsRos() && !
ros::ok()); ++k)
319 if (!((!k && force_relocation) || (b - qhat).array().abs().maxCoeff() > tolerance))
break;
321 UpdateTaskMessage(b, 0., max_step_size);
324 if (update_fwd) UpdateFwdMessage();
325 if (update_bwd) UpdateBwdMessage();
329 Binv = Sinv + Vinv + R + Eigen::MatrixXd::Identity(prob_->N, prob_->N) * damping;
330 AinvBSymPosDef(b, Binv, Sinv *
s + Vinv * v +
r + damping * damping_reference_);
334 Binv = Sinv + Vinv + R;
340 void BayesianIKSolver::UpdateTimestepGaussNewton(
bool update_fwd,
341 bool update_bwd,
int max_relocation_iterations,
double tolerance,
342 double max_step_size)
348 double BayesianIKSolver::EvaluateTrajectory(
const Eigen::VectorXd& x,
bool skip_update)
350 if (verbose_)
ROS_WARN_STREAM(
"Evaluating, iteration " << iteration_count_ <<
", sweep_ " << sweep_);
361 return prob_->GetScalarCost();
364 double BayesianIKSolver::Step()
371 UpdateTimestep(
true,
false, 1, minimum_step_tolerance_, !iteration_count_, 1.);
372 UpdateTimestep(
false,
true, 0, minimum_step_tolerance_,
false, 1.);
375 UpdateTimestep(
true,
false, 1, minimum_step_tolerance_, !iteration_count_, 1.);
376 UpdateTimestep(
false,
true, (iteration_count_ ? 1 : 0), minimum_step_tolerance_,
false, 1.);
378 case LOCAL_GAUSS_NEWTON:
382 case LOCAL_GAUSS_NEWTON_DAMPED:
390 b_step_ = std::max((b_old - b).array().
abs().maxCoeff(), 0.0);
391 damping_reference_ = b;
393 cost_ = EvaluateTrajectory(b);
394 if (debug_)
HIGHLIGHT(
"Iteration: " << iteration_count_ <<
", Sweep: " << sweep_ <<
", updates: " << update_count_ <<
", cost: " << cost_ <<
" (dq=" << b_step_ <<
", damping=" << damping <<
")");
395 if (cost_ < 0)
return -1.0;
396 best_sweep_ = sweep_;
399 if (damping != 0.0) PerhapsUndoStep();
402 if (sweep_improved_cost_)
407 prob_->SetCostEvolution(iteration_count_, cost_);
413 void BayesianIKSolver::RememberOldState()
429 best_sweep_old_ = best_sweep_;
430 b_step_old_ = b_step_;
433 void BayesianIKSolver::PerhapsUndoStep()
435 if (cost_ > cost_old_)
437 sweep_improved_cost_ =
false;
452 damping_reference_ = b_old;
453 best_sweep_ = best_sweep_old_;
454 b_step_ = b_step_old_;
455 if (verbose_)
HIGHLIGHT(
"Reverting to previous line-search step (" << best_sweep_ <<
")");
459 sweep_improved_cost_ =
true;
static void AinvBSymPosDef(T1 &x, const T2 &A, const T3 &b)
Computes the solution to the linear problem for symmetric positive definite matrix A...
Solves motion planning problem using Approximate Inference Control method.
IMETHOD Vector diff(const Vector &p_w_a, const Vector &p_w_b, double dt=1)
#define REGISTER_MOTIONSOLVER_TYPE(TYPE, DERIV)
#define ROS_WARN_STREAM(args)
static void inverseSymPosDef(T1 &Ainv, const T2 &A)
Computes an inverse of a symmetric positive definite matrix.
INLINE Rall1d< T, V, S > abs(const Rall1d< T, V, S > &x)
double GetDuration() const
std::shared_ptr< PlanningProblem > PlanningProblemPtr