Directory: | ./ |
---|---|
File: | bindings/python/crocoddyl/core/solvers/ddp.cpp |
Date: | 2025-01-16 08:47:40 |
Exec | Total | Coverage | |
---|---|---|---|
Lines: | 96 | 98 | 98.0% |
Branches: | 96 | 192 | 50.0% |
Line | Branch | Exec | Source |
---|---|---|---|
1 | /////////////////////////////////////////////////////////////////////////////// | ||
2 | // BSD 3-Clause License | ||
3 | // | ||
4 | // Copyright (C) 2019-2023, LAAS-CNRS, University of Edinburgh, | ||
5 | // Heriot-Watt University | ||
6 | // Copyright note valid unless otherwise stated in individual files. | ||
7 | // All rights reserved. | ||
8 | /////////////////////////////////////////////////////////////////////////////// | ||
9 | |||
10 | #include "crocoddyl/core/solvers/ddp.hpp" | ||
11 | |||
12 | #include "python/crocoddyl/core/core.hpp" | ||
13 | #include "python/crocoddyl/utils/copyable.hpp" | ||
14 | #include "python/crocoddyl/utils/deprecate.hpp" | ||
15 | |||
16 | namespace crocoddyl { | ||
17 | namespace python { | ||
18 | |||
19 | 32 | BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(SolverDDP_solves, SolverDDP::solve, 0, 5) | |
20 | 18 | BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(SolverDDP_computeDirections, | |
21 | SolverDDP::computeDirection, 0, 1) | ||
22 | 36 | BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(SolverDDP_trySteps, SolverDDP::tryStep, | |
23 | 0, 1) | ||
24 | |||
25 | 10 | void exposeSolverDDP() { | |
26 | 10 | bp::register_ptr_to_python<boost::shared_ptr<SolverDDP> >(); | |
27 | |||
28 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | bp::class_<SolverDDP, bp::bases<SolverAbstract> >( |
29 | "SolverDDP", | ||
30 | "DDP solver.\n\n" | ||
31 | "The DDP solver computes an optimal trajectory and control commands by " | ||
32 | "iterates\n" | ||
33 | "running backward and forward passes. The backward-pass updates locally " | ||
34 | "the\n" | ||
35 | "quadratic approximation of the problem and computes descent direction,\n" | ||
36 | "and the forward-pass rollouts this new policy by integrating the system " | ||
37 | "dynamics\n" | ||
38 | "along a tuple of optimized control commands U*.\n" | ||
39 | ":param shootingProblem: shooting problem (list of action models along " | ||
40 | "trajectory.)", | ||
41 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | bp::init<boost::shared_ptr<ShootingProblem> >( |
42 | 20 | bp::args("self", "problem"), | |
43 | "Initialize the vector dimension.\n\n" | ||
44 | ":param problem: shooting problem.")) | ||
45 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | .def("solve", &SolverDDP::solve, |
46 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | SolverDDP_solves( |
47 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
20 | bp::args("self", "init_xs", "init_us", "maxiter", "is_feasible", |
48 | "init_reg"), | ||
49 | "Compute the optimal trajectory xopt, uopt as lists of T+1 and " | ||
50 | "T terms.\n\n" | ||
51 | "From an initial guess init_xs,init_us (feasible or not), " | ||
52 | "iterate\n" | ||
53 | "over computeDirection and tryStep until stoppingCriteria is " | ||
54 | "below\n" | ||
55 | "threshold. It also describes the globalization strategy used\n" | ||
56 | "during the numerical optimization.\n" | ||
57 | ":param init_xs: initial guess for state trajectory with T+1 " | ||
58 | "elements (default []).\n" | ||
59 | ":param init_us: initial guess for control trajectory with T " | ||
60 | "elements (default []) (default []).\n" | ||
61 | ":param maxiter: maximum allowed number of iterations (default " | ||
62 | "100).\n" | ||
63 | ":param is_feasible: true if the init_xs are obtained from " | ||
64 | "integrating the init_us (rollout)\n" | ||
65 | "(default False).\n" | ||
66 | ":param init_reg: initial guess for the regularization value. " | ||
67 | "Very low values are typical\n" | ||
68 | " used with very good guess points (default " | ||
69 | "1e-9).\n" | ||
70 | ":returns the optimal trajectory xopt, uopt and a boolean that " | ||
71 | "describes if convergence was reached.")) | ||
72 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | .def("computeDirection", &SolverDDP::computeDirection, |
73 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | SolverDDP_computeDirections( |
74 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
20 | bp::args("self", "recalc"), |
75 | "Compute the search direction (dx, du) for the current guess " | ||
76 | "(xs, us).\n\n" | ||
77 | "You must call setCandidate first in order to define the " | ||
78 | "current\n" | ||
79 | "guess. A current guess defines a state and control trajectory\n" | ||
80 | "(xs, us) of T+1 and T elements, respectively.\n" | ||
81 | ":params recalc: true for recalculating the derivatives at " | ||
82 | "current state and control.\n" | ||
83 | ":returns the search direction dx, du and the dual lambdas as " | ||
84 | "lists of T+1, T and T+1 lengths.")) | ||
85 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | .def("tryStep", &SolverDDP::tryStep, |
86 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | SolverDDP_trySteps( |
87 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
20 | bp::args("self", "stepLength"), |
88 | "Rollout the system with a predefined step length.\n\n" | ||
89 | ":param stepLength: step length (default 1)\n" | ||
90 | ":returns the cost improvement.")) | ||
91 |
2/4✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 10 times.
✗ Branch 5 not taken.
|
20 | .def("stoppingCriteria", &SolverDDP::stoppingCriteria, bp::args("self"), |
92 | "Return a sum of positive parameters whose sum quantifies the DDP " | ||
93 | "termination.") | ||
94 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | .def("expectedImprovement", &SolverDDP::expectedImprovement, |
95 | ✗ | bp::return_value_policy<bp::copy_const_reference>(), | |
96 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
20 | bp::args("self"), |
97 | "Return two scalars denoting the quadratic improvement model\n\n" | ||
98 | "For computing the expected improvement, you need to compute first\n" | ||
99 | "the search direction by running computeDirection. The quadratic\n" | ||
100 | "improvement model is described as dV = f_0 - f_+ = d1*a + " | ||
101 | "d2*a**2/2.") | ||
102 |
2/4✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 10 times.
✗ Branch 5 not taken.
|
20 | .def("calcDiff", &SolverDDP::calcDiff, bp::args("self"), |
103 | "Update the Jacobian and Hessian of the optimal control problem\n\n" | ||
104 | "These derivatives are computed around the guess state and control\n" | ||
105 | "trajectory. These trajectory can be set by using setCandidate.\n" | ||
106 | ":return the total cost around the guess trajectory.") | ||
107 |
2/4✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 10 times.
✗ Branch 5 not taken.
|
20 | .def("backwardPass", &SolverDDP::backwardPass, bp::args("self"), |
108 | "Run the backward pass (Riccati sweep)\n\n" | ||
109 | "It assumes that the Jacobian and Hessians of the optimal control " | ||
110 | "problem have been\n" | ||
111 | "compute. These terms are computed by running calc.") | ||
112 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | .def("forwardPass", &SolverDDP::forwardPass, |
113 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
20 | bp::args("self", "stepLength"), |
114 | "Run the forward pass or rollout\n\n" | ||
115 | "It rollouts the action model given the computed policy " | ||
116 | "(feedforward terns and feedback\n" | ||
117 | "gains) by the backwardPass. We can define different step lengths\n" | ||
118 | ":param stepLength: applied step length (<= 1. and >= 0.)") | ||
119 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | .def("computeActionValueFunction", &SolverDDP::computeActionValueFunction, |
120 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
20 | bp::args("self", "t", "model", "data"), |
121 | "Compute the linear-quadratic model of the control Hamiltonian\n\n" | ||
122 | ":param t: time instance\n" | ||
123 | ":param model: action model in the given time instance\n" | ||
124 | ":param data: action data in the given time instance") | ||
125 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | .def("computeValueFunction", &SolverDDP::computeValueFunction, |
126 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
20 | bp::args("self", "t", "model"), |
127 | "Compute the quadratic model of the value function.\n\n" | ||
128 | "This function is called in the backward pass after updating the " | ||
129 | "local Hamiltonian.\n" | ||
130 | ":param t: time instance\n" | ||
131 | ":param model: action model in the given time instance") | ||
132 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | .add_property( |
133 | "Vxx", | ||
134 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | make_function(&SolverDDP::get_Vxx, |
135 | 10 | bp::return_value_policy<bp::copy_const_reference>()), | |
136 | "Vxx") | ||
137 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | .add_property( |
138 | "Vx", | ||
139 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | make_function(&SolverDDP::get_Vx, |
140 | 10 | bp::return_value_policy<bp::copy_const_reference>()), | |
141 | "Vx") | ||
142 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | .add_property( |
143 | "Qxx", | ||
144 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | make_function(&SolverDDP::get_Qxx, |
145 | 10 | bp::return_value_policy<bp::copy_const_reference>()), | |
146 | "Qxx") | ||
147 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | .add_property( |
148 | "Qxu", | ||
149 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | make_function(&SolverDDP::get_Qxu, |
150 | 10 | bp::return_value_policy<bp::copy_const_reference>()), | |
151 | "Qxu") | ||
152 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | .add_property( |
153 | "Quu", | ||
154 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | make_function(&SolverDDP::get_Quu, |
155 | 10 | bp::return_value_policy<bp::copy_const_reference>()), | |
156 | "Quu") | ||
157 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | .add_property( |
158 | "Qx", | ||
159 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | make_function(&SolverDDP::get_Qx, |
160 | 10 | bp::return_value_policy<bp::copy_const_reference>()), | |
161 | "Qx") | ||
162 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | .add_property( |
163 | "Qu", | ||
164 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | make_function(&SolverDDP::get_Qu, |
165 | 10 | bp::return_value_policy<bp::copy_const_reference>()), | |
166 | "Qu") | ||
167 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | .add_property( |
168 | "K", | ||
169 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | make_function(&SolverDDP::get_K, |
170 | 10 | bp::return_value_policy<bp::copy_const_reference>()), | |
171 | "K") | ||
172 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | .add_property( |
173 | "k", | ||
174 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | make_function(&SolverDDP::get_k, |
175 | 10 | bp::return_value_policy<bp::copy_const_reference>()), | |
176 | "k") | ||
177 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | .add_property( |
178 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | "reg_incFactor", bp::make_function(&SolverDDP::get_reg_incfactor), |
179 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
20 | bp::make_function(&SolverDDP::set_reg_incfactor), |
180 | "regularization factor used for increasing the damping value.") | ||
181 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | .add_property( |
182 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | "reg_decFactor", bp::make_function(&SolverDDP::get_reg_decfactor), |
183 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
20 | bp::make_function(&SolverDDP::set_reg_decfactor), |
184 | "regularization factor used for decreasing the damping value.") | ||
185 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | .add_property( |
186 | "regFactor", | ||
187 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | bp::make_function( |
188 | &SolverDDP::get_reg_incfactor, | ||
189 |
2/4✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 10 times.
✗ Branch 6 not taken.
|
20 | deprecated<>("Deprecated. Use reg_incfactor or reg_decfactor")), |
190 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
20 | bp::make_function( |
191 | &SolverDDP::set_reg_incfactor, | ||
192 |
2/4✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 10 times.
✗ Branch 6 not taken.
|
20 | deprecated<>("Deprecated. Use reg_incfactor or reg_decfactor")), |
193 | "regularization factor used for increasing or decreasing the damping " | ||
194 | "value.") | ||
195 |
2/4✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 10 times.
✗ Branch 5 not taken.
|
10 | .add_property("reg_min", bp::make_function(&SolverDDP::get_reg_min), |
196 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
20 | bp::make_function(&SolverDDP::set_reg_min), |
197 | "minimum regularization value.") | ||
198 |
2/4✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 10 times.
✗ Branch 5 not taken.
|
10 | .add_property("reg_max", bp::make_function(&SolverDDP::get_reg_max), |
199 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
20 | bp::make_function(&SolverDDP::set_reg_max), |
200 | "maximum regularization value.") | ||
201 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | .add_property("regMin", |
202 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | bp::make_function(&SolverDDP::get_reg_min, |
203 |
2/4✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 10 times.
✗ Branch 6 not taken.
|
20 | deprecated<>("Deprecated. Use reg_min")), |
204 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
20 | bp::make_function(&SolverDDP::set_reg_min, |
205 |
2/4✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 10 times.
✗ Branch 6 not taken.
|
20 | deprecated<>("Deprecated. Use reg_min")), |
206 | "minimum regularization value.") | ||
207 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | .add_property("regMax", |
208 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | bp::make_function(&SolverDDP::get_reg_max, |
209 |
2/4✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 10 times.
✗ Branch 6 not taken.
|
20 | deprecated<>("Deprecated. Use reg_max")), |
210 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
20 | bp::make_function(&SolverDDP::set_reg_max, |
211 |
2/4✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 10 times.
✗ Branch 6 not taken.
|
20 | deprecated<>("Deprecated. Use reg_max")), |
212 | "maximum regularization value.") | ||
213 |
2/4✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 10 times.
✗ Branch 5 not taken.
|
10 | .add_property("th_stepDec", bp::make_function(&SolverDDP::get_th_stepdec), |
214 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
20 | bp::make_function(&SolverDDP::set_th_stepdec), |
215 | "threshold for decreasing the regularization after " | ||
216 | "approving a step (higher values decreases the " | ||
217 | "regularization)") | ||
218 |
2/4✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 10 times.
✗ Branch 5 not taken.
|
10 | .add_property("th_stepInc", bp::make_function(&SolverDDP::get_th_stepinc), |
219 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
20 | bp::make_function(&SolverDDP::set_th_stepinc), |
220 | "threshold for increasing the regularization after " | ||
221 | "approving a step (higher values decreases the " | ||
222 | "regularization)") | ||
223 |
2/4✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 10 times.
✗ Branch 5 not taken.
|
10 | .add_property("th_grad", bp::make_function(&SolverDDP::get_th_grad), |
224 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
20 | bp::make_function(&SolverDDP::set_th_grad), |
225 | "threshold for accepting step which gradients is lower " | ||
226 | "than this value") | ||
227 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | .add_property( |
228 | "th_gaptol", | ||
229 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | bp::make_function(&SolverDDP::get_th_gaptol, |
230 |
2/4✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 10 times.
✗ Branch 6 not taken.
|
20 | deprecated<>("Deprecated. Use th_gapTol")), |
231 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
20 | bp::make_function(&SolverDDP::set_th_gaptol, |
232 |
2/4✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 10 times.
✗ Branch 6 not taken.
|
20 | deprecated<>("Deprecated. Use th_gapTol")), |
233 | "threshold for accepting a gap as non-zero") | ||
234 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | .add_property("alphas", |
235 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | bp::make_function( |
236 | &SolverDDP::get_alphas, | ||
237 | ✗ | bp::return_value_policy<bp::copy_const_reference>()), | |
238 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
20 | bp::make_function(&SolverDDP::set_alphas), |
239 | "list of step length (alpha) values") | ||
240 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | .def(CopyableVisitor<SolverDDP>()); |
241 | 10 | } | |
242 | |||
243 | } // namespace python | ||
244 | } // namespace crocoddyl | ||
245 |