nmpc_ddp
DDPSolver.hpp
Go to the documentation of this file.
1 /* Author: Masaki Murooka */
2 
3 #include <chrono>
4 #include <fstream>
5 #include <iostream>
6 
7 #include <nmpc_ddp/BoxQP.h>
8 
9 namespace
10 {
11 template<class Clock>
12 double calcDuration(const std::chrono::time_point<Clock> & start_time, const std::chrono::time_point<Clock> & end_time)
13 {
14  return 1e3 * std::chrono::duration_cast<std::chrono::duration<double>>(end_time - start_time).count();
15 }
16 } // namespace
17 
18 namespace nmpc_ddp
19 {
20 template<int StateDim, int InputDim>
22 : problem_(problem)
23 {
24 }
25 
26 template<int StateDim, int InputDim>
28  const StateDimVector & current_x,
29  const std::vector<InputDimVector> & initial_u_list)
30 {
31  computation_duration_ = ComputationDuration();
32 
33  auto start_time = std::chrono::system_clock::now();
34 
35  // Initialize variables
36  current_t_ = current_t;
37  lambda_ = config_.initial_lambda;
38  dlambda_ = config_.initial_dlambda;
39 
40  // Check initial_u_list
41  if(static_cast<int>(initial_u_list.size()) != config_.horizon_steps)
42  {
43  throw std::invalid_argument("initial_u_list length should be " + std::to_string(config_.horizon_steps) + " but "
44  + std::to_string(initial_u_list.size()) + ".");
45  }
46  if constexpr(InputDim == Eigen::Dynamic)
47  {
48  for(int i = 0; i < config_.horizon_steps; i++)
49  {
50  double t = current_t_ + i * problem_->dt();
51  if(initial_u_list[i].size() != problem_->inputDim(t))
52  {
53  throw std::runtime_error("initial_u dimension should be " + std::to_string(problem_->inputDim(t)) + " but "
54  + std::to_string(initial_u_list[i].size()) + ". i: " + std::to_string(i)
55  + ", time: " + std::to_string(t));
56  }
57  }
58  }
59 
60  // Resize list
61  candidate_control_data_.x_list.resize(config_.horizon_steps + 1);
62  candidate_control_data_.u_list.resize(config_.horizon_steps);
63  candidate_control_data_.cost_list.resize(config_.horizon_steps + 1);
64  int outer_dim = config_.use_state_eq_second_derivative ? problem_->stateDim() : 0;
65  if constexpr(InputDim == Eigen::Dynamic)
66  {
67  derivative_list_.clear();
68  for(int i = 0; i < config_.horizon_steps; i++)
69  {
70  double t = current_t_ + i * problem_->dt();
71  derivative_list_.push_back(Derivative(problem_->stateDim(), problem_->inputDim(t), outer_dim));
72  }
73  }
74  else
75  {
76  // This assumes that the dimension is fixed, but it is efficient because it preserves existing elements
77  derivative_list_.resize(config_.horizon_steps, Derivative(problem_->stateDim(), problem_->inputDim(), outer_dim));
78  }
79  k_list_.resize(config_.horizon_steps);
80  K_list_.resize(config_.horizon_steps);
81 
82  // Initialize state and cost sequence
83  control_data_.u_list = initial_u_list;
84  control_data_.x_list.resize(config_.horizon_steps + 1);
85  control_data_.cost_list.resize(config_.horizon_steps + 1);
86  control_data_.x_list[0] = current_x;
87  for(int i = 0; i < config_.horizon_steps; i++)
88  {
89  double t = current_t_ + i * problem_->dt();
90  control_data_.x_list[i + 1] = problem_->stateEq(t, control_data_.x_list[i], control_data_.u_list[i]);
91  control_data_.cost_list[i] = problem_->runningCost(t, control_data_.x_list[i], control_data_.u_list[i]);
92  }
93  double terminal_t = current_t_ + config_.horizon_steps * problem_->dt();
94  control_data_.cost_list[config_.horizon_steps] =
95  problem_->terminalCost(terminal_t, control_data_.x_list[config_.horizon_steps]);
96 
97  // Initialize trace data
98  trace_data_list_.clear();
99  TraceData initial_trace_data;
100  initial_trace_data.iter = 0;
101  initial_trace_data.cost = control_data_.cost_list.sum();
102  initial_trace_data.lambda = lambda_;
103  initial_trace_data.dlambda = dlambda_;
104  trace_data_list_.push_back(initial_trace_data);
105 
106  if(config_.print_level >= 3)
107  {
108  std::cout << "[DDP] Initial cost: " << control_data_.cost_list.sum() << std::endl;
109  }
110 
111  auto setup_time = std::chrono::system_clock::now();
112  computation_duration_.setup = calcDuration(start_time, setup_time);
113 
114  // Optimization loop
115  int retval = 0;
116  for(int iter = 1; iter <= config_.max_iter; iter++)
117  {
118  retval = procOnce(iter);
119  if(retval != 0)
120  {
121  break;
122  }
123  }
124 
125  if(config_.print_level >= 3)
126  {
127  std::cout << "[DDP] Final cost: " << control_data_.cost_list.sum() << std::endl;
128  }
129 
130  auto end_time = std::chrono::system_clock::now();
131  computation_duration_.opt = calcDuration(setup_time, end_time);
132  computation_duration_.solve = calcDuration(start_time, end_time);
133 
134  if(config_.print_level >= 3)
135  {
136  std::cout << "[DDP] Setup duration: " << computation_duration_.setup
137  << " [ms], optimization duration: " << computation_duration_.opt << " [ms]." << std::endl;
138  }
139 
140  return retval == 1;
141 }
142 
143 template<int StateDim, int InputDim>
145 {
146  if(config_.print_level >= 3)
147  {
148  std::cout << "[DDP] Start iteration " << iter << std::endl;
149  }
150 
151  // Append trace data
152  trace_data_list_.push_back(TraceData());
153  auto & trace_data = trace_data_list_.back();
154  trace_data.iter = iter;
155 
156  // Step 1: differentiate dynamics and cost along new trajectory
157  {
158  auto start_time = std::chrono::system_clock::now();
159 
160  for(int i = 0; i < config_.horizon_steps; i++)
161  {
162  auto & derivative = derivative_list_[i];
163 
164  double t = current_t_ + i * problem_->dt();
165  const StateDimVector & x = control_data_.x_list[i];
166  const InputDimVector & u = control_data_.u_list[i];
167  if(config_.use_state_eq_second_derivative)
168  {
169  problem_->calcStateEqDeriv(t, x, u, derivative.Fx, derivative.Fu, derivative.Fxx, derivative.Fuu,
170  derivative.Fxu);
171  }
172  else
173  {
174  problem_->calcStateEqDeriv(t, x, u, derivative.Fx, derivative.Fu);
175  }
176  problem_->calcRunningCostDeriv(t, x, u, derivative.Lx, derivative.Lu, derivative.Lxx, derivative.Luu,
177  derivative.Lxu);
178  }
179  double terminal_t = current_t_ + config_.horizon_steps * problem_->dt();
180  problem_->calcTerminalCostDeriv(terminal_t, control_data_.x_list[config_.horizon_steps], last_Vx_, last_Vxx_);
181 
182  double duration_derivative = calcDuration(start_time, std::chrono::system_clock::now());
183  trace_data.duration_derivative = duration_derivative;
184  computation_duration_.derivative += duration_derivative;
185  }
186 
187  // Step 2: backward pass, compute optimal control law and cost-to-go
188  {
189  auto start_time = std::chrono::system_clock::now();
190 
191  while(!backwardPass())
192  {
193  // Increase lambda
194  dlambda_ = std::max(dlambda_ * config_.lambda_factor, config_.lambda_factor);
195  lambda_ = std::max(lambda_ * dlambda_, config_.lambda_min);
196  if(lambda_ > config_.lambda_max)
197  {
198  if(config_.print_level >= 1)
199  {
200  std::cout << "[DDP/Backward] Failure due to large lambda. (time: " << current_t_ << ", iter: " << iter << ")"
201  << std::endl;
202  }
203  return -1; // Failure
204  }
205  if(config_.print_level >= 3)
206  {
207  std::cout << "[DDP/Backward] Increase lambda to " << lambda_ << std::endl;
208  }
209  }
210 
211  double duration_backward = calcDuration(start_time, std::chrono::system_clock::now());
212  trace_data.duration_backward = duration_backward;
213  computation_duration_.backward += duration_backward;
214  }
215 
216  // Check for termination due to small gradient
217  double k_rel_norm = 0;
218  for(int i = 0; i < config_.horizon_steps; i++)
219  {
220  k_rel_norm = std::max(k_rel_norm, k_list_[i].norm() / (control_data_.u_list[i].norm() + 1.0));
221  }
222  trace_data.k_rel_norm = k_rel_norm;
223  if(k_rel_norm < config_.k_rel_norm_thre && lambda_ < config_.lambda_thre)
224  {
225  if(config_.print_level >= 2)
226  {
227  std::cout << "[DDP] Terminate due to small gradient. (time: " << current_t_ << ", iter: " << iter << ")"
228  << std::endl;
229  }
230  return 1; // Terminate
231  }
232 
233  // Step 3: forward pass, line-search to find new control sequence, trajectory, cost
234  bool forward_pass_success = false;
235  double cost_update_actual = 0;
236  {
237  auto start_time = std::chrono::system_clock::now();
238 
239  double alpha = 0;
240  double cost_update_expected = 0;
241  double cost_update_ratio = 0;
242  for(int i = 0; i < config_.alpha_list.size(); i++)
243  {
244  alpha = config_.alpha_list[i];
245 
246  forwardPass(alpha);
247 
248  cost_update_actual = control_data_.cost_list.sum() - candidate_control_data_.cost_list.sum();
249  cost_update_expected = -1 * alpha * (dV_[0] + alpha * dV_[1]);
250  cost_update_ratio = cost_update_actual / cost_update_expected;
251  if(cost_update_expected < 0)
252  {
253  if((!config_.with_input_constraint && config_.print_level >= 0)
254  || (config_.with_input_constraint && config_.print_level >= 2))
255  {
256  std::cout << "[DDP/Forward] Value is not expected to decrease." << std::endl;
257  }
258  cost_update_ratio = (cost_update_actual >= 0 ? 1 : -1);
259  }
260  if(cost_update_ratio > config_.cost_update_ratio_thre)
261  {
262  forward_pass_success = true;
263  break;
264  }
265  }
266  trace_data.alpha = alpha;
267  trace_data.cost_update_actual = cost_update_actual;
268  trace_data.cost_update_expected = cost_update_expected;
269  trace_data.cost_update_ratio = cost_update_ratio;
270 
271  double duration_forward = calcDuration(start_time, std::chrono::system_clock::now());
272  trace_data.duration_forward = duration_forward;
273  computation_duration_.forward += duration_forward;
274  }
275  if(!forward_pass_success && config_.print_level >= 3)
276  {
277  std::cout << "[DDP] Forward pass failed." << std::endl;
278  }
279 
280  // Step 4: accept step (or not)
281  int retval = 0; // Continue
282  if(forward_pass_success)
283  {
284  // Accept changes
285  control_data_.x_list = candidate_control_data_.x_list;
286  control_data_.u_list = candidate_control_data_.u_list;
287  control_data_.cost_list = candidate_control_data_.cost_list;
288 
289  // Check for termination due to small cost update
290  if(cost_update_actual < config_.cost_update_thre)
291  {
292  if(config_.print_level >= 2)
293  {
294  std::cout << "[DDP] Terminate due to small cost update. (time: " << current_t_ << ", iter: " << iter << ")"
295  << std::endl;
296  }
297  retval = 1; // Terminate
298  }
299 
300  // Decrease lambda
301  dlambda_ = std::min(dlambda_ / config_.lambda_factor, 1 / config_.lambda_factor);
302  if(lambda_ >= config_.lambda_min)
303  {
304  lambda_ *= dlambda_;
305  }
306  else
307  {
308  lambda_ = 0;
309  }
310  if(config_.print_level >= 3)
311  {
312  std::cout << "[DDP/Forward] Decrease lambda to " << lambda_ << std::endl;
313  }
314  }
315  else
316  {
317  // Increase lambda
318  dlambda_ = std::max(dlambda_ * config_.lambda_factor, config_.lambda_factor);
319  lambda_ = std::max(lambda_ * dlambda_, config_.lambda_min);
320  if(lambda_ > config_.lambda_max)
321  {
322  if(config_.print_level >= 1)
323  {
324  std::cout << "[DDP/Forward] Failure due to large lambda. (time: " << current_t_ << ", iter: " << iter << ")"
325  << std::endl;
326  }
327  retval = -1; // Failure
328  }
329  if(config_.print_level >= 3)
330  {
331  std::cout << "[DDP/Forward] Increase lambda to " << lambda_ << std::endl;
332  }
333  }
334 
335  trace_data.cost = control_data_.cost_list.sum();
336  trace_data.lambda = lambda_;
337  trace_data.dlambda = dlambda_;
338 
339  return retval;
340 }
341 
342 template<int StateDim, int InputDim>
344 {
345  // To avoid repetitive memory allocation, the vector and matrix variables are created outside of loop
346  StateDimVector Vx = last_Vx_;
347  StateStateDimMatrix Vxx = last_Vxx_;
348  StateStateDimMatrix Vxx_reg;
349  StateStateDimMatrix Vxx_symmetric;
350 
351  InputDimVector Qu;
352  StateDimVector Qx;
356  InputStateDimMatrix Qux_reg;
357  InputInputDimMatrix Quu_F;
358 
359  InputStateDimMatrix VxFux;
360  InputInputDimMatrix VxFuu;
361 
362  InputDimVector k;
364 
365  dV_.setZero();
366 
367  for(int i = config_.horizon_steps - 1; i >= 0; i--)
368  {
369  // Get derivatives
370  double t = current_t_ + i * problem_->dt();
371  const StateStateDimMatrix & Fx = derivative_list_[i].Fx;
372  const StateInputDimMatrix & Fu = derivative_list_[i].Fu;
373  // const std::vector<StateStateDimMatrix> & Fxx = derivative_list_[i].Fxx;
374  // const std::vector<InputInputDimMatrix> & Fuu = derivative_list_[i].Fuu;
375  // const std::vector<StateInputDimMatrix> & Fxu = derivative_list_[i].Fxu;
376  const StateDimVector & Lx = derivative_list_[i].Lx;
377  const InputDimVector & Lu = derivative_list_[i].Lu;
378  const StateStateDimMatrix & Lxx = derivative_list_[i].Lxx;
379  const InputInputDimMatrix & Luu = derivative_list_[i].Luu;
380  const StateInputDimMatrix & Lxu = derivative_list_[i].Lxu;
381  int input_dim = static_cast<int>(Fu.cols());
382 
383  // Calculate Q
384  auto start_time_Q = std::chrono::system_clock::now();
385 
386  Qu.noalias() = Lu + Fu.transpose() * Vx;
387 
388  Qx.noalias() = Lx + Fx.transpose() * Vx;
389 
390  Qux.noalias() = Lxu.transpose() + Fu.transpose() * Vxx * Fx;
391  if(config_.use_state_eq_second_derivative)
392  {
393  throw std::runtime_error("Vector-tensor product is not implemented yet.");
394  // \todo Need operation to compute a matrix by vector and tensor product
395  // VxFux = Vx * Fxu.transpose();
396  // Qux += VxFux
397  }
398 
399  Quu.noalias() = Luu + Fu.transpose() * Vxx * Fu;
400  if(config_.use_state_eq_second_derivative)
401  {
402  throw std::runtime_error("Vector-tensor product is not implemented yet.");
403  // \todo Need operation to compute a matrix by vector and tensor product
404  // VxFuu = Vx * Fuu;
405  // Quu += VxFuu;
406  }
407 
408  Qxx.noalias() = Lxx + Fx.transpose() * Vxx * Fx;
409  if(config_.use_state_eq_second_derivative)
410  {
411  throw std::runtime_error("Vector-tensor product is not implemented yet.");
412  // \todo Need operation to compute a matrix by vector and tensor product
413  // Qxx += Vx * Fxx;
414  }
415 
416  computation_duration_.Q += calcDuration(start_time_Q, std::chrono::system_clock::now());
417 
418  // Calculate regularization
419  auto start_time_reg = std::chrono::system_clock::now();
420 
421  Vxx_reg = Vxx;
422  if(config_.reg_type == 2)
423  {
424  Vxx_reg.diagonal().array() += lambda_;
425  }
426 
427  Qux_reg.noalias() = Lxu.transpose() + Fu.transpose() * Vxx_reg * Fx;
428  if(config_.use_state_eq_second_derivative)
429  {
430  Qux_reg += VxFux;
431  }
432 
433  Quu_F.noalias() = Luu + Fu.transpose() * Vxx_reg * Fu;
434  if(config_.use_state_eq_second_derivative)
435  {
436  Quu_F += VxFuu;
437  }
438  if(config_.reg_type == 1)
439  {
440  Quu_F.diagonal().array() += lambda_;
441  }
442 
443  computation_duration_.reg += calcDuration(start_time_reg, std::chrono::system_clock::now());
444 
445  // Calculate gains
446  auto start_time_gain = std::chrono::system_clock::now();
447 
448  if(input_dim > 0)
449  {
450  if(config_.with_input_constraint)
451  {
452  InputDimVector initial_k;
453  if(i == config_.horizon_steps - 1)
454  {
455  initial_k.setZero(input_dim);
456  }
457  else
458  {
459  if(k_list_[i + 1].size() == input_dim)
460  {
461  initial_k = k_list_[i + 1];
462  }
463  else
464  {
465  initial_k.setZero(input_dim);
466  }
467  }
468 
469  BoxQP<Eigen::Dynamic> qp(static_cast<int>(Quu_F.cols()));
470  const auto & u_limits = input_limits_func_(t);
471  k = qp.solve(Quu_F, Qu, u_limits[0] - control_data_.u_list[i], u_limits[1] - control_data_.u_list[i],
472  initial_k);
473  if(qp.retval_ < 0)
474  {
475  if(config_.print_level >= 1)
476  {
477  std::cout << "[DDP/Backward] Failed BoxQP: " << qp.retstr_.at(qp.retval_) << std::endl;
478  }
479  return false;
480  }
481 
482  const auto & free_idxs = qp.free_idxs_;
483  K.setZero(input_dim, problem_->stateDim());
484  if(free_idxs.size() > 0)
485  {
486  Eigen::MatrixXd Qux_reg_free(free_idxs.size(), problem_->stateDim());
487  for(size_t j = 0; j < free_idxs.size(); j++)
488  {
489  Qux_reg_free.row(j) = Qux_reg.row(free_idxs[j]);
490  }
491  Eigen::MatrixXd K_free = -1 * qp.llt_free_->solve(Qux_reg_free);
492  for(size_t j = 0; j < free_idxs.size(); j++)
493  {
494  K.row(free_idxs[j]) = K_free.row(j);
495  }
496  }
497  }
498  else
499  {
500  Eigen::LLT<InputInputDimMatrix> llt_Quu_F(Quu_F);
501  if(llt_Quu_F.info() == Eigen::NumericalIssue)
502  {
503  if(config_.print_level >= 1)
504  {
505  std::cout << "[DDP/Backward] Quu_F is not positive definite in Cholesky decomposition (LLT)." << std::endl;
506  }
507  return false;
508  }
509  k = -1 * llt_Quu_F.solve(Qu);
510  K = -1 * llt_Quu_F.solve(Qux_reg);
511  }
512  }
513  else
514  {
515  k.setZero(0);
516  K.setZero(0, problem_->stateDim());
517  }
518 
519  computation_duration_.gain += calcDuration(start_time_gain, std::chrono::system_clock::now());
520 
521  // Update cost-to-go approximation
522  dV_ += Eigen::Vector2d(k.dot(Qu), 0.5 * k.dot(Quu * k));
523  Vx.noalias() = Qx + K.transpose() * Quu * k + K.transpose() * Qu + Qux.transpose() * k;
524  Vxx.noalias() = Qxx + K.transpose() * Quu * K + K.transpose() * Qux + Qux.transpose() * K;
525  Vxx_symmetric = 0.5 * (Vxx + Vxx.transpose());
526  Vxx = Vxx_symmetric;
527 
528  // Save gains
529  k_list_[i] = k;
530  K_list_[i] = K;
531  }
532 
533  return true;
534 }
535 
536 template<int StateDim, int InputDim>
538 {
539  // Set initial state
540  candidate_control_data_.x_list[0] = control_data_.x_list[0];
541 
542  for(int i = 0; i < config_.horizon_steps; i++)
543  {
544  // Calculate input
545  candidate_control_data_.u_list[i] = control_data_.u_list[i] + alpha * k_list_[i]
546  + K_list_[i] * (candidate_control_data_.x_list[i] - control_data_.x_list[i]);
547 
548  // \todo Impose constraints on input
549 
550  // Calculate next state and cost
551  double t = current_t_ + i * problem_->dt();
552  candidate_control_data_.x_list[i + 1] =
553  problem_->stateEq(t, candidate_control_data_.x_list[i], candidate_control_data_.u_list[i]);
554  candidate_control_data_.cost_list[i] =
555  problem_->runningCost(t, candidate_control_data_.x_list[i], candidate_control_data_.u_list[i]);
556  }
557  double terminal_t = current_t_ + config_.horizon_steps * problem_->dt();
558  candidate_control_data_.cost_list[config_.horizon_steps] =
559  problem_->terminalCost(terminal_t, candidate_control_data_.x_list[config_.horizon_steps]);
560 }
561 
562 template<int StateDim, int InputDim>
563 void DDPSolver<StateDim, InputDim>::dumpTraceDataList(const std::string & file_path) const
564 {
565  std::ofstream ofs(file_path);
566  // clang-format off
567  ofs << "iter "
568  << "cost "
569  << "lambda "
570  << "dlambda "
571  << "alpha "
572  << "k_rel_norm "
573  << "cost_update_actual "
574  << "cost_update_expected "
575  << "cost_update_ratio "
576  << "duration_derivative "
577  << "duration_backward "
578  << "duration_forward" << std::endl;
579  // clang-format on
580  for(const auto & trace_data : trace_data_list_)
581  {
582  // clang-format off
583  ofs << trace_data.iter << " "
584  << trace_data.cost << " "
585  << trace_data.lambda << " "
586  << trace_data.dlambda << " "
587  << trace_data.alpha << " "
588  << trace_data.k_rel_norm << " "
589  << trace_data.cost_update_actual << " "
590  << trace_data.cost_update_expected << " "
591  << trace_data.cost_update_ratio << " "
592  << trace_data.duration_derivative << " "
593  << trace_data.duration_backward << " "
594  << trace_data.duration_forward
595  << std::endl;
596  // clang-format on
597  }
598 }
599 } // namespace nmpc_ddp
nmpc_ddp::DDPSolver::TraceData
Data to trace optimization loop.
Definition: DDPSolver.h:179
nmpc_ddp::DDPSolver::Derivative
Derivatives of DDP problem.
Definition: DDPSolver.h:126
nmpc_ddp::DDPSolver::forwardPass
void forwardPass(double alpha)
Process forward pass.
Definition: DDPSolver.hpp:537
nmpc_ddp::DDPSolver::StateDimVector
typename DDPProblem< StateDim, InputDim >::StateDimVector StateDimVector
Type of vector of state dimension.
Definition: DDPSolver.h:28
nmpc_ddp::BoxQP::retstr_
const std::unordered_map< int, std::string > retstr_
Return string.
Definition: BoxQP.h:375
nmpc_ddp::DDPSolver::InputInputDimMatrix
typename DDPProblem< StateDim, InputDim >::InputInputDimMatrix InputInputDimMatrix
Type of matrix of input x input dimension.
Definition: DDPSolver.h:37
nmpc_ddp::DDPSolver::InputDimVector
typename DDPProblem< StateDim, InputDim >::InputDimVector InputDimVector
Type of vector of input dimension.
Definition: DDPSolver.h:31
nmpc_ddp::BoxQP::free_idxs_
std::vector< int > free_idxs_
Indices of free dimensions in decision variables.
Definition: BoxQP.h:389
nmpc_ddp::DDPSolver::StateStateDimMatrix
typename DDPProblem< StateDim, InputDim >::StateStateDimMatrix StateStateDimMatrix
Type of matrix of state x state dimension.
Definition: DDPSolver.h:34
nmpc_ddp::DDPSolver::backwardPass
bool backwardPass()
Process backward pass.
Definition: DDPSolver.hpp:343
nmpc_ddp::DDPSolver::TraceData::lambda
double lambda
Regularization coefficient.
Definition: DDPSolver.h:188
nmpc_ddp::DDPSolver::TraceData::dlambda
double dlambda
Scaling factor of regularization coefficient.
Definition: DDPSolver.h:191
nmpc_ddp::BoxQP
Solver for quadratic programming problems with box constraints (i.e., only upper and lower bounds).
Definition: BoxQP.h:19
nmpc_ddp::DDPSolver::procOnce
int procOnce(int iter)
Process one iteration.
Definition: DDPSolver.hpp:144
nmpc_ddp
Definition: BoxQP.h:9
nmpc_ddp::DDPSolver::StateInputDimMatrix
typename DDPProblem< StateDim, InputDim >::StateInputDimMatrix StateInputDimMatrix
Type of matrix of state x input dimension.
Definition: DDPSolver.h:40
nmpc_ddp::DDPSolver::solve
bool solve(double current_t, const StateDimVector &current_x, const std::vector< InputDimVector > &initial_u_list)
Solve optimization.
Definition: DDPSolver.hpp:27
nmpc_ddp::BoxQP::retval_
int retval_
Return value.
Definition: BoxQP.h:372
nmpc_ddp::DDPSolver::TraceData::cost
double cost
Total cost.
Definition: DDPSolver.h:185
BoxQP.h
nmpc_ddp::DDPSolver::ComputationDuration
Data of computation duration.
Definition: DDPSolver.h:219
nmpc_ddp::DDPSolver::InputStateDimMatrix
typename DDPProblem< StateDim, InputDim >::InputStateDimMatrix InputStateDimMatrix
Type of matrix of input x state dimension.
Definition: DDPSolver.h:43
nmpc_ddp::DDPSolver::dumpTraceDataList
void dumpTraceDataList(const std::string &file_path) const
Dump trace data list.
Definition: DDPSolver.hpp:563
nmpc_ddp::DDPSolver::TraceData::iter
int iter
Iteration of optimization loop.
Definition: DDPSolver.h:182
nmpc_ddp::BoxQP::llt_free_
std::unique_ptr< Eigen::LLT< Eigen::MatrixXd > > llt_free_
Cholesky decomposition (LLT) of free block of objective Hessian matrix.
Definition: BoxQP.h:386
nmpc_ddp::DDPProblem
DDP problem.
Definition: DDPProblem.h:16
nmpc_ddp::DDPSolver::DDPSolver
EIGEN_MAKE_ALIGNED_OPERATOR_NEW DDPSolver(const std::shared_ptr< DDPProblem< StateDim, InputDim >> &problem)
Constructor.
Definition: DDPSolver.hpp:21
nmpc_ddp::BoxQP::solve
VarDimVector solve(const VarVarDimMatrix &H, const VarDimVector &g, const VarDimVector &lower, const VarDimVector &upper)
Solve optimization.
Definition: BoxQP.h:126