Crocoddyl
callbacks.cpp
1 // BSD 3-Clause License
3 //
4 // Copyright (C) 2019-2023, LAAS-CNRS, University of Edinburgh,
5 // University of Oxford, Heriot-Watt University
6 // Copyright note valid unless otherwise stated in individual files.
7 // All rights reserved.
9 
10 #include "crocoddyl/core/utils/callbacks.hpp"
11 
12 #include "crocoddyl/core/utils/exception.hpp"
13 
14 namespace crocoddyl {
15 
16 CallbackVerbose::CallbackVerbose(VerboseLevel level, int precision)
17  : CallbackAbstract(),
18  level_(level),
19  separator_(" "),
20  separator_short_(" ") {
21  set_precision(precision);
22 }
23 
24 CallbackVerbose::~CallbackVerbose() {}
25 
26 VerboseLevel CallbackVerbose::get_level() const { return level_; }
27 
28 void CallbackVerbose::set_level(VerboseLevel level) {
29  level_ = level;
30  update_header();
31 }
32 
33 int CallbackVerbose::get_precision() const { return precision_; }
34 
35 void CallbackVerbose::set_precision(int precision) {
36  if (precision < 0) throw_pretty("The precision needs to be at least 0.");
37  precision_ = precision;
38  update_header();
39 }
40 
41 void CallbackVerbose::update_header() {
42  auto center_string = [](const std::string& str, int width,
43  bool right_padding = true) {
44  const int padding_size = width - static_cast<int>(str.length());
45  const int padding_left = padding_size > 0 ? padding_size / 2 : 0;
46  const int padding_right =
47  padding_size % 2 != 0
48  ? padding_left + 1
49  : padding_left; // If the padding is odd, add additional space
50  if (right_padding) {
51  return std::string(padding_left, ' ') + str +
52  std::string(padding_right, ' ');
53  } else {
54  return std::string(padding_left, ' ') + str;
55  }
56  };
57 
58  header_.clear();
59  // Scientific mode requires a column width of 6 + precision
60  const int columnwidth = 6 + precision_;
61  header_ += "iter" + separator_;
62  switch (level_) {
63  case _0: {
64  header_ += center_string("cost", columnwidth) + separator_;
65  header_ += center_string("stop", columnwidth) + separator_;
66  header_ += center_string("grad", columnwidth) + separator_;
67  header_ += center_string("preg", columnwidth) + separator_;
68  header_ += center_string("step", 6) + separator_;
69  header_ += center_string("dV-exp", columnwidth) + separator_;
70  header_ += center_string("dV", columnwidth, false);
71  break;
72  }
73  case _1: {
74  header_ += center_string("cost", columnwidth) + separator_;
75  header_ += center_string("merit", columnwidth) + separator_;
76  header_ += center_string("stop", columnwidth) + separator_;
77  header_ += center_string("grad", columnwidth) + separator_;
78  header_ += center_string("preg", columnwidth) + separator_;
79  header_ += center_string("step", 6) + separator_;
80  header_ += center_string("||ffeas||", columnwidth) + separator_;
81  header_ += center_string("dV-exp", columnwidth) + separator_;
82  header_ += center_string("dV", columnwidth, false);
83  break;
84  }
85  case _2: {
86  header_ += center_string("cost", columnwidth) + separator_;
87  header_ += center_string("merit", columnwidth) + separator_;
88  header_ += center_string("stop", columnwidth) + separator_;
89  header_ += center_string("grad", columnwidth) + separator_;
90  header_ += center_string("preg", columnwidth) + separator_;
91  header_ += center_string("dreg", columnwidth) + separator_;
92  header_ += center_string("step", 6) + separator_;
93  header_ += center_string("||ffeas||", columnwidth) + separator_;
94  header_ += center_string("dV-exp", columnwidth) + separator_;
95  header_ += center_string("dV", columnwidth, false);
96  break;
97  }
98  case _3: {
99  header_ += center_string("cost", columnwidth) + separator_;
100  header_ += center_string("merit", columnwidth) + separator_;
101  header_ += center_string("stop", columnwidth) + separator_;
102  header_ += center_string("grad", columnwidth) + separator_;
103  header_ += center_string("preg", columnwidth) + separator_;
104  header_ += center_string("dreg", columnwidth) + separator_;
105  header_ += center_string("step", 6) + separator_;
106  header_ += center_string("||ffeas||", columnwidth) + separator_;
107  header_ += center_string("||gfeas||", columnwidth) + separator_;
108  header_ += center_string("||hfeas||", columnwidth) + separator_;
109  header_ += center_string("dV-exp", columnwidth) + separator_;
110  header_ += center_string("dV", columnwidth, false);
111  break;
112  }
113  case _4: {
114  header_ += center_string("cost", columnwidth) + separator_;
115  header_ += center_string("merit", columnwidth) + separator_;
116  header_ += center_string("stop", columnwidth) + separator_;
117  header_ += center_string("grad", columnwidth) + separator_;
118  header_ += center_string("preg", columnwidth) + separator_;
119  header_ += center_string("dreg", columnwidth) + separator_;
120  header_ += center_string("step", 6) + separator_;
121  header_ += center_string("||ffeas||", columnwidth) + separator_;
122  header_ += center_string("||gfeas||", columnwidth) + separator_;
123  header_ += center_string("||hfeas||", columnwidth) + separator_;
124  header_ += center_string("dV-exp", columnwidth) + separator_;
125  header_ += center_string("dV", columnwidth) + separator_;
126  header_ += center_string("dPhi-exp", columnwidth) + separator_;
127  header_ += center_string("dPhi", columnwidth, false);
128  break;
129  }
130  default: {
131  }
132  }
133 }
134 
135 void CallbackVerbose::operator()(SolverAbstract& solver) {
136  if (solver.get_iter() % 10 == 0) {
137  std::cout << header_ << std::endl;
138  }
139  auto space_sign = [this](const double value) {
140  std::stringstream stream;
141  if (value >= 0.) {
142  stream << " ";
143  } else {
144  stream << "-";
145  }
146  stream << std::scientific << std::setprecision(precision_) << abs(value);
147  return stream.str();
148  };
149 
150  std::cout << std::setw(4) << solver.get_iter() << separator_; // iter
151  switch (level_) {
152  case _0: {
153  std::cout << std::scientific << std::setprecision(precision_)
154  << solver.get_cost() << separator_; // cost
155  std::cout << solver.get_stop() << separator_; // stop
156  std::cout << space_sign(-solver.get_d()[1]) << separator_short_; // grad
157  std::cout << solver.get_preg() << separator_; // preg
158  std::cout << std::fixed << std::setprecision(4) << solver.get_steplength()
159  << separator_short_; // step
160  std::cout << space_sign(solver.get_dVexp()) << separator_short_; // dVexp
161  std::cout << space_sign(solver.get_dV()); // dV
162  break;
163  }
164  case _1: {
165  std::cout << std::scientific << std::setprecision(precision_)
166  << solver.get_cost() << separator_short_; // cost
167  std::cout << space_sign(solver.get_merit()) << separator_; // merit
168  std::cout << solver.get_stop() << separator_short_; // stop
169  std::cout << space_sign(-solver.get_d()[1]) << separator_; // grad
170  std::cout << solver.get_preg() << separator_; // preg
171  std::cout << std::fixed << std::setprecision(4) << solver.get_steplength()
172  << separator_; // step
173  std::cout << std::scientific << std::setprecision(precision_)
174  << solver.get_ffeas() << separator_short_; // ffeas
175  std::cout << space_sign(solver.get_dVexp()) << separator_short_; // dVexp
176  std::cout << space_sign(solver.get_dV()); // dV
177  break;
178  }
179  case _2: {
180  std::cout << std::scientific << std::setprecision(precision_)
181  << solver.get_cost() << separator_short_; // cost
182  std::cout << space_sign(solver.get_merit()) << separator_; // merit
183  std::cout << solver.get_stop() << separator_short_; // stop
184  std::cout << space_sign(-solver.get_d()[1]) << separator_; // grad
185  std::cout << solver.get_preg() << separator_; // preg
186  std::cout << solver.get_dreg() << separator_; // dreg
187  std::cout << std::fixed << std::setprecision(4) << solver.get_steplength()
188  << separator_; // step
189  std::cout << std::scientific << std::setprecision(precision_)
190  << solver.get_ffeas() << separator_short_; // ffeas
191  std::cout << space_sign(solver.get_dVexp()) << separator_short_; // dVexp
192  std::cout << space_sign(solver.get_dV()); // dV
193  break;
194  }
195  case _3: {
196  std::cout << std::scientific << std::setprecision(precision_)
197  << solver.get_cost() << separator_short_; // cost
198  std::cout << space_sign(solver.get_merit()) << separator_; // merit
199  std::cout << solver.get_stop() << separator_short_; // stop
200  std::cout << space_sign(-solver.get_d()[1]) << separator_; // grad
201  std::cout << solver.get_preg() << separator_; // preg
202  std::cout << solver.get_dreg() << separator_; // dreg
203  std::cout << std::fixed << std::setprecision(4) << solver.get_steplength()
204  << separator_; // step
205  std::cout << std::scientific << std::setprecision(precision_)
206  << solver.get_ffeas() << separator_; // ffeas
207  std::cout << solver.get_gfeas() << separator_; // gfeas
208  std::cout << solver.get_hfeas() << separator_short_; // hfeas
209  std::cout << space_sign(solver.get_dVexp()) << separator_short_; // dVexp
210  std::cout << space_sign(solver.get_dV()); // dV
211  break;
212  }
213  case _4: {
214  std::cout << std::scientific << std::setprecision(precision_)
215  << solver.get_cost() << separator_short_; // cost
216  std::cout << space_sign(solver.get_merit()) << separator_; // merit
217  std::cout << solver.get_stop() << separator_short_; // stop
218  std::cout << space_sign(-solver.get_d()[1]) << separator_; // grad
219  std::cout << solver.get_preg() << separator_; // preg
220  std::cout << solver.get_dreg() << separator_; // dreg
221  std::cout << std::fixed << std::setprecision(4) << solver.get_steplength()
222  << separator_; // step
223  std::cout << std::scientific << std::setprecision(precision_)
224  << solver.get_ffeas() << separator_; // ffeas
225  std::cout << solver.get_gfeas() << separator_; // gfeas
226  std::cout << solver.get_hfeas() << separator_short_; // hfeas
227  std::cout << space_sign(solver.get_dVexp()) << separator_short_; // dVexp
228  std::cout << space_sign(solver.get_dV()) << separator_short_; // dV
229  std::cout << space_sign(solver.get_dPhiexp())
230  << separator_short_; // dPhiexp
231  std::cout << space_sign(solver.get_dPhi()); // dPhi
232  break;
233  }
234  default: {
235  }
236  }
237  std::cout << std::endl;
238  std::cout << std::flush;
239 }
240 
241 } // namespace crocoddyl
Abstract class for optimal control solvers.
Definition: solver-base.hpp:61
double get_cost() const
Return the cost for the current guess.
double get_dPhi() const
Return the reduction in the merit function .
std::size_t get_iter() const
Return the number of iterations performed by the solver.
double get_hfeas() const
Return the equality feasibility for the current guess.
double get_dVexp() const
Return the expected reduction in the cost function .
double get_dPhiexp() const
Return the expected reduction in the merit function .
double get_steplength() const
Return the step length .
double get_merit() const
Return the merit for the current guess.
double get_preg() const
Return the primal-variable regularization.
const Eigen::Vector2d & get_d() const
Return the linear and quadratic terms of the expected improvement.
double get_ffeas() const
Return the dynamic feasibility for the current guess.
double get_gfeas() const
Return the inequality feasibility for the current guess.
double get_stop() const
Return the stopping-criteria value computed by stoppingCriteria()
double get_dV() const
Return the reduction in the cost function .
double get_dreg() const
Return the dual-variable regularization.