aico_solver.cpp
Go to the documentation of this file.
1 //
2 // Copyright (c) 2018, University of Edinburgh
3 // All rights reserved.
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are met:
7 //
8 // * Redistributions of source code must retain the above copyright notice,
9 // this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above copyright
11 // notice, this list of conditions and the following disclaimer in the
12 // documentation and/or other materials provided with the distribution.
13 // * Neither the name of nor the names of its contributors may be used to
14 // endorse or promote products derived from this software without specific
15 // prior written permission.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 // POSSIBILITY OF SUCH DAMAGE.
28 //
29 
30 // This code is based on algorithm developed by Marc Toussaint
31 // M. Toussaint: Robot Trajectory Optimization using Approximate Inference. In Proc. of the Int. Conf. on Machine Learning (ICML 2009), 1049-1056, ACM, 2009.
32 // http://ipvs.informatik.uni-stuttgart.de/mlr/papers/09-toussaint-ICML.pdf
33 // Original code available at http://ipvs.informatik.uni-stuttgart.de/mlr/marc/source-code/index.html
34 
37 
39 #include <exotica_core/server.h>
40 
42 
43 namespace exotica
44 {
45 void AICOSolver::Instantiate(const AICOSolverInitializer& init)
46 {
47  std::string mode = init.SweepMode;
48  if (mode == "Forwardly")
50  else if (mode == "Symmetric")
52  else if (mode == "LocalGaussNewton")
54  else if (mode == "LocalGaussNewtonDamped")
56  else
57  {
58  ThrowNamed("Unknown sweep mode '" << init.SweepMode << "'");
59  }
60  max_backtrack_iterations_ = init.MaxBacktrackIterations;
61  minimum_step_tolerance_ = init.MinStep;
62  step_tolerance_ = init.StepTolerance;
63  function_tolerance_ = init.FunctionTolerance;
64  damping_init_ = init.Damping;
65  use_bwd_msg_ = init.UseBackwardMessage;
66  verbose_ = init.Verbose;
67 }
68 
69 AICOSolver::AICOSolver() = default;
70 
71 AICOSolver::~AICOSolver() = default;
72 
74 {
75  if (problem->type() != "exotica::UnconstrainedTimeIndexedProblem")
76  {
77  ThrowNamed("This solver can't use problem of type '" << problem->type() << "'!");
78  }
80  prob_ = std::static_pointer_cast<UnconstrainedTimeIndexedProblem>(problem);
81 
82  InitMessages();
83 }
84 
85 void AICOSolver::Solve(Eigen::MatrixXd& solution)
86 {
87  prob_->PreUpdate();
88  prob_->ResetCostEvolution(GetNumberOfMaxIterations() + 1);
89  prob_->termination_criterion = TerminationCriterion::NotStarted;
90  planning_time_ = -1;
91 
92  Eigen::VectorXd q0 = prob_->ApplyStartState();
93  std::vector<Eigen::VectorXd> q_init = prob_->GetInitialTrajectory();
94 
95  // If the initial value of the initial trajectory does not equal the start
96  // state, assume that no initial guess is provided and fill the trajectory
97  // with the start state
98  if (!q0.isApprox(q_init[0]))
99  {
100  if (verbose_) HIGHLIGHT("AICO::Solve cold-started");
101  q_init.assign(prob_->GetT(), q0);
102  }
103  else
104  {
105  if (verbose_) HIGHLIGHT("AICO::Solve called with initial trajectory guess");
106  }
107 
108  prob_->SetStartState(q_init[0]);
109  prob_->ApplyStartState();
110 
111  // Check if the trajectory length has changed, if so update the messages.
112  if (prob_->GetT() != last_T_) InitMessages();
113 
114  Timer timer;
115  if (verbose_) ROS_WARN_STREAM("AICO: Setting up the solver");
116  update_count_ = 0;
118  double d;
119  if (prob_->GetT() <= 0)
120  {
121  ThrowNamed("Problem has not been initialized properly: T=0!");
122  }
123  iteration_count_ = -1;
124  InitTrajectory(q_init);
125  if (verbose_) ROS_WARN_STREAM("AICO: Solving");
126 
127  // Reset sweep and iteration count
128  sweep_ = 0;
129  iteration_count_ = 0;
131  {
132  // Check whether user interrupted (Ctrl+C)
133  if (Server::IsRos() && !ros::ok())
134  {
135  if (debug_) HIGHLIGHT("Solving cancelled by user");
136  prob_->termination_criterion = TerminationCriterion::UserDefined;
137  break;
138  }
139 
140  d = Step();
141  if (d < 0)
142  {
143  ThrowNamed("Negative step size!");
144  }
145 
146  // 0. Check maximum backtrack iterations
147  if (damping != 0.0 && sweep_ >= max_backtrack_iterations_)
148  {
149  if (debug_) HIGHLIGHT("Maximum backtrack iterations reached, exiting.");
150  prob_->termination_criterion = TerminationCriterion::BacktrackIterationLimit;
151  break;
152  }
153 
154  // Check stopping criteria
155  if (iteration_count_ > 1)
156  {
157  // Check convergence if
158  // a) damping is on and the iteration has concluded (the sweep improved the cost)
159  // b) damping is off [each sweep equals one iteration]
160  if ((damping != 0.0 && sweep_improved_cost_) || !(damping != 0.0))
161  {
162  // 1. Check step tolerance
163  // || x_t-x_t-1 || <= stepTolerance * max(1, || x_t ||)
164  // TODO(#257): TODO(#256): move to Eigen::MatrixXd to make this easier to compute, in the meantime use old check
165  //
166  // TODO(#256): OLD TOLERANCE CHECK - TODO REMOVE
168  {
169  if (debug_) HIGHLIGHT("Satisfied tolerance\titer=" << iteration_count_ << "\td=" << d << "\tminimum_step_tolerance=" << minimum_step_tolerance_);
170  prob_->termination_criterion = TerminationCriterion::StepTolerance;
171  break;
172  }
173 
174  // 2. Check function tolerance
175  // (f_t-1 - f_t) <= functionTolerance * max(1, abs(f_t))
176  if ((cost_prev_ - cost_) <= function_tolerance_ * std::max(1.0, std::abs(cost_)))
177  {
178  if (debug_) HIGHLIGHT("Function tolerance achieved: " << (cost_prev_ - cost_) << " <= " << function_tolerance_ * std::max(1.0, std::abs(cost_)));
179  prob_->termination_criterion = TerminationCriterion::FunctionTolerance;
180  break;
181  }
182  cost_prev_ = cost_;
183  }
184  }
185  }
186 
187  // Check whether maximum iteration count was reached
189  {
190  if (debug_) HIGHLIGHT("Maximum iterations reached");
191  prob_->termination_criterion = TerminationCriterion::IterationLimit;
192  }
193 
194  Eigen::MatrixXd sol(prob_->GetT(), prob_->N);
195  for (int tt = 0; tt < prob_->GetT(); ++tt)
196  {
197  sol.row(tt) = q[tt];
198  }
199  solution = sol;
200  planning_time_ = timer.GetDuration();
201 }
202 
204 {
205  if (prob_ == nullptr) ThrowNamed("Problem definition is a NULL pointer!");
206 
207  if (prob_->N < 1)
208  {
209  ThrowNamed("State dimension is too small: n=" << prob_->N);
210  }
211  if (prob_->GetT() < 2)
212  {
213  ThrowNamed("Number of time steps is too small: T=" << prob_->GetT());
214  }
215 
216  s.assign(prob_->GetT(), Eigen::VectorXd::Zero(prob_->N));
217  Sinv.assign(prob_->GetT(), Eigen::MatrixXd::Zero(prob_->N, prob_->N));
218  Sinv[0].diagonal().setConstant(1e10);
219  v.assign(prob_->GetT(), Eigen::VectorXd::Zero(prob_->N));
220  Vinv.assign(prob_->GetT(), Eigen::MatrixXd::Zero(prob_->N, prob_->N));
221  if (use_bwd_msg_)
222  {
223  if (bwd_msg_v_.rows() == prob_->N && bwd_msg_Vinv_.rows() == prob_->N && bwd_msg_Vinv_.cols() == prob_->N)
224  {
225  v[prob_->GetT() - 1] = bwd_msg_v_;
226  Vinv[prob_->GetT() - 1] = bwd_msg_Vinv_;
227  }
228  else
229  {
230  use_bwd_msg_ = false;
231  WARNING("Backward message initialisation skipped, matrices have incorrect dimensions.");
232  }
233  }
234  b.assign(prob_->GetT(), Eigen::VectorXd::Zero(prob_->N));
235  damping_reference_.assign(prob_->GetT(), Eigen::VectorXd::Zero(prob_->N));
236  Binv.assign(prob_->GetT(), Eigen::MatrixXd::Zero(prob_->N, prob_->N));
237  Binv[0].setIdentity();
238  Binv[0] = Binv[0] * 1e10;
239  r.assign(prob_->GetT(), Eigen::VectorXd::Zero(prob_->N));
240  R.assign(prob_->GetT(), Eigen::MatrixXd::Zero(prob_->N, prob_->N));
241  rhat = Eigen::VectorXd::Zero(prob_->GetT());
242  qhat.assign(prob_->GetT(), Eigen::VectorXd::Zero(prob_->N));
243  q = b;
244 
245  cost_control_.resize(prob_->GetT());
246  cost_control_.setZero();
247  cost_task_.resize(prob_->GetT());
248  cost_task_.setZero();
249 
250  q_stat_.resize(prob_->GetT());
251  for (int t = 0; t < prob_->GetT(); ++t)
252  {
253  q_stat_[t].resize(prob_->N);
254  }
255 
256  // Set last_T_ to the problem T
257  last_T_ = prob_->GetT();
258 }
259 
260 void AICOSolver::InitTrajectory(const std::vector<Eigen::VectorXd>& q_init)
261 {
262  if (q_init.size() != static_cast<std::size_t>(prob_->GetT()))
263  {
264  ThrowNamed("Incorrect number of timesteps provided!");
265  }
266  qhat = q_init;
267  q = q_init;
268  damping_reference_ = q_init;
269  b = q_init;
270  s = q_init;
271  v = q_init;
272  for (int t = 1; t < prob_->GetT(); ++t)
273  {
274  Sinv.at(t).setZero();
275  Sinv.at(t).diagonal().setConstant(damping);
276  }
277  for (int t = 0; t < prob_->GetT(); ++t)
278  {
279  Vinv.at(t).setZero();
280  Vinv.at(t).diagonal().setConstant(damping);
281  }
282  for (int t = 0; t < prob_->GetT(); ++t)
283  {
284  // Compute task message reference
285  UpdateTaskMessage(t, b[t], 0.0);
286  }
287 
288  // W is still writable, check dimension
289  if (prob_->W.rows() != prob_->N)
290  {
291  ThrowNamed(prob_->W.rows() << "!=" << prob_->N);
292  }
293 
294  // Set constant W,Win,H,Hinv
295  W = prob_->W;
296  Winv = W.inverse();
297 
298  cost_ = EvaluateTrajectory(b, true); // The problem will be updated via UpdateTaskMessage, i.e. do not update on this roll-out
299  cost_prev_ = cost_;
300  prob_->SetCostEvolution(0, cost_);
301  if (cost_ < 0) ThrowNamed("Invalid cost! " << cost_);
302  if (debug_) HIGHLIGHT("Initial cost, updates: " << update_count_ << ", cost_(ctrl/task/total): " << cost_control_.sum() << "/" << cost_task_.sum() << "/" << cost_);
304 }
305 
307 {
308  Eigen::MatrixXd barS(prob_->N, prob_->N), St;
309  inverseSymPosDef(barS, Sinv[t - 1] + R[t - 1]);
310  s[t] = barS * (Sinv[t - 1] * s[t - 1] + r[t - 1]);
311  St = Winv + barS;
312  inverseSymPosDef(Sinv[t], St);
313 }
314 
316 {
317  Eigen::MatrixXd barV(prob_->N, prob_->N), Vt;
318  if (t < prob_->GetT() - 1)
319  {
320  inverseSymPosDef(barV, Vinv[t + 1] + R[t + 1]);
321  v[t] = barV * (Vinv[t + 1] * v[t + 1] + r[t + 1]);
322  Vt = Winv + barV;
323  inverseSymPosDef(Vinv[t], Vt);
324  }
325  if (t == prob_->GetT() - 1)
326  {
327  if (!use_bwd_msg_)
328  {
329  v[t] = b[t];
330  Vinv[t].diagonal().setConstant(1);
331  }
332  else
333  {
334  v[prob_->GetT() - 1] = bwd_msg_v_;
335  Vinv[prob_->GetT() - 1] = bwd_msg_Vinv_;
336  }
337  }
338 }
339 
341  const Eigen::Ref<const Eigen::VectorXd>& qhat_t, double tolerance,
342  double max_step_size)
343 {
344  Eigen::VectorXd diff = qhat_t - qhat[t];
345  if ((diff.array().abs().maxCoeff() < tolerance)) return;
346  double nrm = diff.norm();
347  if (max_step_size > 0. && nrm > max_step_size)
348  {
349  qhat[t] += diff * (max_step_size / nrm);
350  }
351  else
352  {
353  qhat[t] = qhat_t;
354  }
355 
356  prob_->Update(qhat[t], t);
357  ++update_count_;
358  double c = GetTaskCosts(t);
359  q_stat_[t].addw(c > 0 ? 1.0 / (1.0 + c) : 1.0, qhat_t);
360 }
361 
363 {
364  double C = 0;
365  Eigen::MatrixXd Jt;
366  double prec;
367  rhat[t] = 0;
368  R[t].setZero();
369  r[t].setZero();
370  for (int i = 0; i < prob_->cost.num_tasks; ++i)
371  {
372  prec = prob_->cost.rho[t](i);
373  if (prec > 0)
374  {
375  int start = prob_->cost.indexing[i].start_jacobian;
376  int len = prob_->cost.indexing[i].length_jacobian;
377  Jt = prob_->cost.jacobian[t].middleRows(start, len).transpose();
378  C += prec * (prob_->cost.ydiff[t].segment(start, len)).squaredNorm();
379  R[t] += prec * Jt * prob_->cost.jacobian[t].middleRows(start, len);
380  r[t] += prec * Jt * (-prob_->cost.ydiff[t].segment(start, len) + prob_->cost.jacobian[t].middleRows(start, len) * qhat[t]);
381  rhat[t] += prec * (-prob_->cost.ydiff[t].segment(start, len) + prob_->cost.jacobian[t].middleRows(start, len) * qhat[t]).squaredNorm();
382  }
383  }
384  return prob_->get_ct() * C;
385 }
386 
387 void AICOSolver::UpdateTimestep(int t, bool update_fwd, bool update_bwd,
388  int max_relocation_iterations, double tolerance, bool force_relocation,
389  double max_step_size)
390 {
391  if (update_fwd) UpdateFwdMessage(t);
392  if (update_bwd) UpdateBwdMessage(t);
393 
394  if (damping != 0.0)
395  {
396  Binv[t] = Sinv[t] + Vinv[t] + R[t] + Eigen::MatrixXd::Identity(prob_->N, prob_->N) * damping;
397  AinvBSymPosDef(b[t], Binv[t], Sinv[t] * s[t] + Vinv[t] * v[t] + r[t] + damping * damping_reference_[t]);
398  }
399  else
400  {
401  Binv[t] = Sinv[t] + Vinv[t] + R[t];
402  AinvBSymPosDef(b[t], Binv[t], Sinv[t] * s[t] + Vinv[t] * v[t] + r[t]);
403  }
404 
405  for (int k = 0; k < max_relocation_iterations && !(Server::IsRos() && !ros::ok()); ++k)
406  {
407  if (!((!k && force_relocation) || (b[t] - qhat[t]).array().abs().maxCoeff() > tolerance)) break;
408 
409  UpdateTaskMessage(t, b.at(t), 0., max_step_size);
410 
411  //optional reUpdate fwd or bwd message (if the Dynamics might have changed...)
412  if (update_fwd) UpdateFwdMessage(t);
413  if (update_bwd) UpdateBwdMessage(t);
414 
415  if (damping != 0.0)
416  {
417  Binv[t] = Sinv[t] + Vinv[t] + R[t] + Eigen::MatrixXd::Identity(prob_->N, prob_->N) * damping;
418  AinvBSymPosDef(b[t], Binv[t], Sinv[t] * s[t] + Vinv[t] * v[t] + r[t] + damping * damping_reference_[t]);
419  }
420  else
421  {
422  Binv[t] = Sinv[t] + Vinv[t] + R[t];
423  AinvBSymPosDef(b[t], Binv[t], Sinv[t] * s[t] + Vinv[t] * v[t] + r[t]);
424  }
425  }
426 }
427 
428 void AICOSolver::UpdateTimestepGaussNewton(int t, bool update_fwd,
429  bool update_bwd, int max_relocation_iterations, double tolerance,
430  double max_step_size)
431 {
432  // TODO: implement UpdateTimestepGaussNewton
433  ThrowNamed("Not implemented yet!");
434 }
435 
436 double AICOSolver::EvaluateTrajectory(const std::vector<Eigen::VectorXd>& x,
437  bool skip_update)
438 {
439  if (verbose_) ROS_WARN_STREAM("Evaluating, iteration " << iteration_count_ << ", sweep " << sweep_);
440  Timer timer;
441 
442  q = x;
443 
444  // Perform update / roll-out
445  if (!skip_update)
446  {
447  for (int t = 0; t < prob_->GetT(); ++t)
448  {
449  ++update_count_;
450  if (!q[t].allFinite())
451  {
452  ThrowNamed("q[" << t << "] is not finite: " << q[t].transpose());
453  }
454  prob_->Update(q[t], t);
455  }
456  }
457  if (verbose_ && !skip_update) HIGHLIGHT("Roll-out took: " << timer.GetDuration());
458 
459  for (int t = 1; t < prob_->GetT(); ++t)
460  {
461  if (Server::IsRos() && !ros::ok()) return -1.0;
462 
463  // Control cost
464  cost_control_(t) = prob_->GetScalarTransitionCost(t);
465 
466  // Task cost
467  cost_task_(t) = prob_->GetScalarTaskCost(t);
468  }
469 
470  cost_ = cost_control_.sum() + cost_task_.sum();
471  return cost_;
472 }
473 
475 {
477  int t;
478  switch (sweep_mode_)
479  {
480  //NOTE: the dependence on (Sweep?..:..) could perhaps be replaced by (DampingReference.N?..:..)
481  case FORWARD:
482  for (t = 1; t < prob_->GetT(); ++t)
483  {
484  UpdateTimestep(t, true, false, 1, minimum_step_tolerance_, !iteration_count_, 1.); //relocate once on fwd Sweep
485  }
486  for (t = prob_->GetT() - 2; t > 0; t--)
487  {
488  UpdateTimestep(t, false, true, 0, minimum_step_tolerance_, false, 1.); //...not on bwd Sweep
489  }
490  break;
491  case SYMMETRIC:
492  // ROS_WARN_STREAM("Updating forward, iteration_count_ "<<iteration_count_);
493  for (t = 1; t < prob_->GetT(); ++t)
494  {
495  UpdateTimestep(t, true, false, 1, minimum_step_tolerance_, !iteration_count_, 1.); //relocate once on fwd & bwd Sweep
496  }
497  // ROS_WARN_STREAM("Updating backward, iteration_count_ "<<iteration_count_);
498  for (t = prob_->GetT() - 2; t > 0; t--)
499  {
500  UpdateTimestep(t, false, true, (iteration_count_ ? 1 : 0), minimum_step_tolerance_, false, 1.);
501  }
502  break;
503  case LOCAL_GAUSS_NEWTON:
504  for (t = 1; t < prob_->GetT(); ++t)
505  {
506  UpdateTimestep(t, true, false, (iteration_count_ ? 5 : 1), minimum_step_tolerance_, !iteration_count_, 1.); //relocate iteratively on
507  }
508  for (t = prob_->GetT() - 2; t > 0; t--)
509  {
510  UpdateTimestep(t, false, true, (iteration_count_ ? 5 : 0), minimum_step_tolerance_, false, 1.); //...fwd & bwd Sweep
511  }
512  break;
514  for (t = 1; t < prob_->GetT(); ++t)
515  {
516  UpdateTimestepGaussNewton(t, true, false, (iteration_count_ ? 5 : 1),
517  minimum_step_tolerance_, 1.); //GaussNewton in fwd & bwd Sweep
518  }
519  for (t = prob_->GetT() - 2; t > 0; t--)
520  {
521  UpdateTimestep(t, false, true, (iteration_count_ ? 5 : 0), minimum_step_tolerance_, false, 1.);
522  }
523  break;
524  default:
525  ThrowNamed("non-existing Sweep mode");
526  }
527  b_step_ = 0.0;
528  for (t = 0; t < static_cast<int>(b.size()); ++t)
529  {
530  b_step_ = std::max((b_old[t] - b[t]).array().abs().maxCoeff(), b_step_);
531  }
533  // q is set inside of EvaluateTrajectory() function
535  if (verbose_)
536  {
537  HIGHLIGHT("Iteration: " << iteration_count_ << ", Sweep: " << sweep_ << ", updates: " << update_count_ << ", cost(ctrl/task/total): " << cost_control_.sum() << "/" << cost_task_.sum() << "/" << cost_ << " (dq=" << b_step_ << ", damping=" << damping << ")");
538  }
539  else if (debug_ && sweep_ == 0)
540  {
541  HIGHLIGHT("Iteration: " << iteration_count_ << ", updates: " << update_count_ << ", cost(ctrl/task/total): " << cost_control_.sum() << "/" << cost_task_.sum() << "/" << cost_ << " (dq=" << b_step_ << ", damping=" << damping << ")");
542  }
543  if (cost_ < 0) return -1.0;
545 
546  // If damping (similar to line-search) is being used, consider reverting this step
547  if (damping != 0.0) PerhapsUndoStep();
548 
549  ++sweep_;
551  {
552  // HIGHLIGHT("Sweep improved cost, increasing iteration count and resetting sweep count");
554  sweep_ = 0;
555  prob_->SetCostEvolution(iteration_count_, cost_);
556  }
557 
558  return b_step_;
559 }
560 
562 {
563  s_old = s;
564  Sinv_old = Sinv;
565  v_old = v;
566  Vinv_old = Vinv;
567  r_old = r;
568  R_old = R;
569  Binv_old = Binv;
570  rhat_old = rhat;
571  b_old = b;
572  r_old = r;
573  q_old = q;
574  qhat_old = qhat;
575  cost_old_ = cost_;
580 }
581 
583 {
584  if (cost_ > cost_old_)
585  {
586  sweep_improved_cost_ = false;
587  damping *= 10.;
588  s = s_old;
589  Sinv = Sinv_old;
590  v = v_old;
591  Vinv = Vinv_old;
592  r = r_old;
593  R = R_old;
594  Binv = Binv_old;
595  rhat = rhat_old;
596  b = b_old;
597  r = r_old;
598  q = q_old;
599  qhat = qhat_old;
600  cost_ = cost_old_;
606  if (verbose_) HIGHLIGHT("Reverting to previous line-search step (" << best_sweep_ << ")");
607  }
608  else
609  {
610  sweep_improved_cost_ = true;
611  damping /= 5.;
612  }
613 }
614 } // namespace exotica
exotica::TerminationCriterion::NotStarted
@ NotStarted
exotica::AICOSolver::cost_task_
Eigen::VectorXd cost_task_
Task cost for each task for each time step.
Definition: aico_solver.h:127
exotica::AICOSolver::cost_control_old_
Eigen::VectorXd cost_control_old_
Control cost for each time step (last most optimal value)
Definition: aico_solver.h:140
exotica::AICOSolver::q
std::vector< Eigen::VectorXd > q
Configuration space trajectory.
Definition: aico_solver.h:124
exotica::AICOSolver::InitTrajectory
void InitTrajectory(const std::vector< Eigen::VectorXd > &q_init)
Initialise AICO messages from an initial trajectory.
Definition: aico_solver.cpp:260
exotica::AICOSolver::bwd_msg_Vinv_
Eigen::MatrixXd bwd_msg_Vinv_
Backward message initialisation covariance.
Definition: aico_solver.h:109
exotica::AICOSolver::UpdateTimestepGaussNewton
void UpdateTimestepGaussNewton(int t, bool update_fwd, bool update_bwd, int max_relocation_iterations, double tolerance, double max_step_size=-1.)
Update messages for given time step using the Gauss Newton method.
Definition: aico_solver.cpp:428
exotica::AICOSolver::EvaluateTrajectory
double EvaluateTrajectory(const std::vector< Eigen::VectorXd > &x, bool skip_update=false)
Computes the cost of the trajectory.
Definition: aico_solver.cpp:436
exotica::AICOSolver::damping_init_
double damping_init_
Damping.
Definition: aico_solver.h:102
exotica::AICOSolver
Solves motion planning problem using Approximate Inference Control method.
Definition: aico_solver.h:72
exotica::AICOSolver::UpdateTaskMessage
void UpdateTaskMessage(int t, const Eigen::Ref< const Eigen::VectorXd > &qhat_t, double tolerance, double max_step_size=-1.)
Definition: aico_solver.cpp:340
exotica::AICOSolver::PerhapsUndoStep
void PerhapsUndoStep()
Reverts back to previous state if the cost of the current state is higher.
Definition: aico_solver.cpp:582
exotica::AICOSolver::cost_task_old_
Eigen::MatrixXd cost_task_old_
Task cost for each task for each time step (last most optimal value)
Definition: aico_solver.h:141
exotica::AICOSolver::Vinv_old
std::vector< Eigen::MatrixXd > Vinv_old
Backward message covariance inverse (last most optimal value)
Definition: aico_solver.h:132
exotica::Timer
exotica::AICOSolver::max_backtrack_iterations_
int max_backtrack_iterations_
Max. number of sweeps without improvement before terminating (= line-search)
Definition: aico_solver.h:106
exotica::AICOSolver::cost_control_
Eigen::VectorXd cost_control_
Control cost for each time step.
Definition: aico_solver.h:126
exotica::AICOSolver::R
std::vector< Eigen::MatrixXd > R
Task message covariance.
Definition: aico_solver.h:120
exotica::TerminationCriterion::BacktrackIterationLimit
@ BacktrackIterationLimit
exotica::AICOSolver::Step
double Step()
Compute one step of the AICO algorithm.
Definition: aico_solver.cpp:474
exotica::AICOSolver::sweep_improved_cost_
bool sweep_improved_cost_
Whether the last sweep improved the cost (for backtrack iterations count)
Definition: aico_solver.h:110
exotica::AICOSolver::Binv
std::vector< Eigen::MatrixXd > Binv
Belief covariance inverse.
Definition: aico_solver.h:123
exotica::AICOSolver::minimum_step_tolerance_
double minimum_step_tolerance_
Update tolerance to stop update of messages if change of maximum coefficient is less than this tolera...
Definition: aico_solver.h:103
exotica
exotica::AICOSolver::W
Eigen::MatrixXd W
Configuration space weight matrix inverse.
Definition: aico_solver.h:150
REGISTER_MOTIONSOLVER_TYPE
#define REGISTER_MOTIONSOLVER_TYPE(TYPE, DERIV)
exotica::AICOSolver::SYMMETRIC
@ SYMMETRIC
Definition: aico_solver.h:161
exotica::AICOSolver::~AICOSolver
virtual ~AICOSolver()
ros::ok
ROSCPP_DECL bool ok()
exotica::AICOSolver::InitMessages
void InitMessages()
Initializes message data.
Definition: aico_solver.cpp:203
exotica::AICOSolver::qhat_old
std::vector< Eigen::VectorXd > qhat_old
Point of linearisation (last most optimal value)
Definition: aico_solver.h:139
exotica::AICOSolver::qhat
std::vector< Eigen::VectorXd > qhat
Point of linearisation.
Definition: aico_solver.h:125
exotica::AICOSolver::b_step_
double b_step_
Squared configuration space step.
Definition: aico_solver.h:147
exotica::AICOSolver::UpdateFwdMessage
void UpdateFwdMessage(int t)
Updates the forward message at time step $t$.
Definition: aico_solver.cpp:306
exotica::AICOSolver::Sinv_old
std::vector< Eigen::MatrixXd > Sinv_old
Forward message covariance inverse (last most optimal value)
Definition: aico_solver.h:130
exotica::AICOSolver::Binv_old
std::vector< Eigen::MatrixXd > Binv_old
Belief covariance inverse (last most optimal value)
Definition: aico_solver.h:137
exotica::AICOSolver::verbose_
bool verbose_
Definition: aico_solver.h:168
ROS_WARN_STREAM
#define ROS_WARN_STREAM(args)
exotica::AICOSolver::cost_old_
double cost_old_
cost of MAP trajectory (last most optimal value)
Definition: aico_solver.h:145
exotica::AICOSolver::Instantiate
void Instantiate(const AICOSolverInitializer &init) override
Definition: aico_solver.cpp:45
exotica::AICOSolver::q_old
std::vector< Eigen::VectorXd > q_old
Configuration space trajectory (last most optimal value)
Definition: aico_solver.h:138
exotica::TerminationCriterion::StepTolerance
@ StepTolerance
exotica::AICOSolver::best_sweep_
int best_sweep_
Definition: aico_solver.h:156
exotica::AICOSolver::AICOSolver
AICOSolver()
HIGHLIGHT
#define HIGHLIGHT(x)
exotica::AICOSolver::sweep_
int sweep_
Sweeps so far.
Definition: aico_solver.h:155
exotica::MotionSolver::GetNumberOfMaxIterations
int GetNumberOfMaxIterations()
exotica::TerminationCriterion::IterationLimit
@ IterationLimit
exotica::AICOSolver::rhat_old
Eigen::VectorXd rhat_old
Task message point of linearisation (last most optimal value)
Definition: aico_solver.h:135
d
d
exotica::AICOSolver::SpecifyProblem
void SpecifyProblem(PlanningProblemPtr pointer) override
Binds the solver to a specific problem which must be pre-initalised.
Definition: aico_solver.cpp:73
exotica::Object::debug_
bool debug_
exotica::AICOSolver::Vinv
std::vector< Eigen::MatrixXd > Vinv
Backward message covariance inverse.
Definition: aico_solver.h:118
exotica::AICOSolver::v_old
std::vector< Eigen::VectorXd > v_old
Backward message mean (last most optimal value)
Definition: aico_solver.h:131
exotica::AICOSolver::bwd_msg_v_
Eigen::VectorXd bwd_msg_v_
Backward message initialisation mean.
Definition: aico_solver.h:108
exotica::AICOSolver::cost_
double cost_
cost of MAP trajectory
Definition: aico_solver.h:144
aico_solver.h
Approximate Inference Control.
exotica::AICOSolver::last_T_
int last_T_
T the last time InitMessages was called.
Definition: aico_solver.h:153
exotica::AICOSolver::b
std::vector< Eigen::VectorXd > b
Belief mean.
Definition: aico_solver.h:122
exotica::AICOSolver::s
std::vector< Eigen::VectorXd > s
Forward message mean.
Definition: aico_solver.h:115
exotica::AICOSolver::iteration_count_
int iteration_count_
Iteration counter.
Definition: aico_solver.h:111
exotica::AICOSolver::cost_prev_
double cost_prev_
previous iteration cost
Definition: aico_solver.h:146
exotica::TerminationCriterion::FunctionTolerance
@ FunctionTolerance
exotica::AICOSolver::Solve
void Solve(Eigen::MatrixXd &solution) override
Solves the problem.
Definition: aico_solver.cpp:85
exotica::AICOSolver::R_old
std::vector< Eigen::MatrixXd > R_old
Task message covariance (last most optimal value)
Definition: aico_solver.h:134
exotica::AICOSolver::prob_
UnconstrainedTimeIndexedProblemPtr prob_
Shared pointer to the planning problem.
Definition: aico_solver.h:100
exotica::AICOSolver::sweep_mode_
int sweep_mode_
Sweep mode.
Definition: aico_solver.h:165
start
ROSCPP_DECL void start()
exotica::AICOSolver::b_step_old_
double b_step_old_
Definition: aico_solver.h:148
exotica::PlanningProblemPtr
std::shared_ptr< PlanningProblem > PlanningProblemPtr
exotica::AICOSolver::v
std::vector< Eigen::VectorXd > v
Backward message mean.
Definition: aico_solver.h:117
exotica::AICOSolver::update_count_
int update_count_
Definition: aico_solver.h:166
exotica::AICOSolver::Winv
Eigen::MatrixXd Winv
Configuration space weight matrix inverse.
Definition: aico_solver.h:151
exotica::AICOSolver::UpdateTimestep
void UpdateTimestep(int t, bool update_fwd, bool update_bwd, int max_relocation_iterations, double tolerance, bool force_relocation, double max_step_size=-1.)
Update messages for given time step.
Definition: aico_solver.cpp:387
exotica::AICOSolver::LOCAL_GAUSS_NEWTON_DAMPED
@ LOCAL_GAUSS_NEWTON_DAMPED
Definition: aico_solver.h:163
exotica::inverseSymPosDef
static void inverseSymPosDef(T1 &Ainv, const T2 &A)
Computes an inverse of a symmetric positive definite matrix.
Definition: math_operations.h:42
exotica::AICOSolver::GetTaskCosts
double GetTaskCosts(int t)
Updates the task cost terms for time step . UnconstrainedTimeIndexedProblem::Update() has to be call...
Definition: aico_solver.cpp:362
exotica::AICOSolver::b_old
std::vector< Eigen::VectorXd > b_old
Belief mean (last most optimal value)
Definition: aico_solver.h:136
WARNING
#define WARNING(x)
exotica::MotionSolver::planning_time_
double planning_time_
exotica::AICOSolver::r
std::vector< Eigen::VectorXd > r
Task message mean.
Definition: aico_solver.h:119
exotica::AICOSolver::rhat
Eigen::VectorXd rhat
Task message point of linearisation.
Definition: aico_solver.h:121
tolerance
S tolerance()
exotica::AICOSolver::q_stat_
std::vector< SinglePassMeanCovariance > q_stat_
Cost weighted normal distribution of configurations across sweeps.
Definition: aico_solver.h:113
exotica::AICOSolver::function_tolerance_
double function_tolerance_
Relative function tolerance/first-order optimality criterion.
Definition: aico_solver.h:105
init
void init(const M_string &remappings)
exotica::TerminationCriterion::UserDefined
@ UserDefined
exotica::AICOSolver::RememberOldState
void RememberOldState()
Stores the previous state.
Definition: aico_solver.cpp:561
x
double x
exotica::AICOSolver::damping
double damping
Damping.
Definition: aico_solver.h:101
exotica::AICOSolver::s_old
std::vector< Eigen::VectorXd > s_old
Forward message mean (last most optimal value)
Definition: aico_solver.h:129
server.h
exotica::AICOSolver::use_bwd_msg_
bool use_bwd_msg_
Flag for using backward message initialisation.
Definition: aico_solver.h:107
exotica::AICOSolver::r_old
std::vector< Eigen::VectorXd > r_old
Task message mean (last most optimal value)
Definition: aico_solver.h:133
exotica::AICOSolver::LOCAL_GAUSS_NEWTON
@ LOCAL_GAUSS_NEWTON
Definition: aico_solver.h:162
exotica::AICOSolver::Sinv
std::vector< Eigen::MatrixXd > Sinv
Forward message covariance inverse.
Definition: aico_solver.h:116
exotica::AICOSolver::FORWARD
@ FORWARD
Definition: aico_solver.h:160
exotica::MotionSolver::SpecifyProblem
virtual void SpecifyProblem(PlanningProblemPtr pointer)
exotica::AICOSolver::best_sweep_old_
int best_sweep_old_
Definition: aico_solver.h:157
exotica::Server::IsRos
static bool IsRos()
exotica::AICOSolver::step_tolerance_
double step_tolerance_
Relative step tolerance (termination criterion)
Definition: aico_solver.h:104
t
geometry_msgs::TransformStamped t
exotica::Timer::GetDuration
double GetDuration() const
exotica::AICOSolver::damping_reference_
std::vector< Eigen::VectorXd > damping_reference_
Damping reference point.
Definition: aico_solver.h:143
ThrowNamed
#define ThrowNamed(m)
exotica::AICOSolver::UpdateBwdMessage
void UpdateBwdMessage(int t)
Updates the backward message at time step $t$.
Definition: aico_solver.cpp:315
exotica::AinvBSymPosDef
static void AinvBSymPosDef(T1 &x, const T2 &A, const T3 &b)
Computes the solution to the linear problem for symmetric positive definite matrix A.
Definition: math_operations.h:49


exotica_aico_solver
Author(s):
autogenerated on Fri Oct 20 2023 03:00:06