@@ -230,8 +230,7 @@ void IpmSolver::runImpl(scalar_t initTime, const vector_t& initState, scalar_t f
230230 const vector_t delta_x0 = initState - x[0 ];
231231 const auto deltaSolution =
232232 getOCPSolution (delta_x0, barrierParam, slackStateIneq, slackStateInputIneq, dualStateIneq, dualStateInputIneq);
233- vector_array_t deltaLmdSol;
234- extractValueFunction (timeDiscretization, x, lmd, deltaSolution.deltaXSol , deltaLmdSol);
233+ extractValueFunction (timeDiscretization, x, lmd, deltaSolution.deltaXSol );
235234 solveQpTimer_.endTimer ();
236235
237236 // Apply step
@@ -243,23 +242,16 @@ void IpmSolver::runImpl(scalar_t initTime, const vector_t& initState, scalar_t f
243242 slackStateInputIneq, metrics);
244243 const scalar_t dualStepSize =
245244 settings_.usePrimalStepSizeForDual ? std::min (stepInfo.stepSize , deltaSolution.maxDualStepSize ) : deltaSolution.maxDualStepSize ;
246- performanceIndeces_.push_back (stepInfo.performanceAfterStep );
247245 if (settings_.computeLagrangeMultipliers ) {
248- multiple_shooting::incrementTrajectory (lmd, deltaLmdSol, stepInfo.stepSize , lmd);
246+ multiple_shooting::incrementTrajectory (lmd, deltaSolution. deltaLmdSol , stepInfo.stepSize , lmd);
249247 if (settings_.projectStateInputEqualityConstraints ) {
250- // Remaining term that depends on the costate
251- auto deltaNuSol = std::move (deltaSolution.deltaNuSol );
252- for (int i = 0 ; i < nu.size (); i++) {
253- if (nu[i].size () > 0 ) {
254- deltaNuSol[i].noalias () += projectionMultiplierCoefficients_[i].dfdcostate * deltaLmdSol[i + 1 ];
255- }
256- }
257- multiple_shooting::incrementTrajectory (nu, deltaNuSol, stepInfo.stepSize , nu);
248+ multiple_shooting::incrementTrajectory (nu, deltaSolution.deltaNuSol , stepInfo.stepSize , nu);
258249 }
259250 }
260251 multiple_shooting::incrementTrajectory (dualStateIneq, deltaSolution.deltaDualStateIneq , stepInfo.stepSize , dualStateIneq);
261252 multiple_shooting::incrementTrajectory (dualStateInputIneq, deltaSolution.deltaDualStateInputIneq , stepInfo.stepSize ,
262253 dualStateInputIneq);
254+ performanceIndeces_.push_back (stepInfo.performanceAfterStep );
263255 linesearchTimer_.endTimer ();
264256
265257 // Check convergence
@@ -393,6 +385,20 @@ IpmSolver::OcpSubproblemSolution IpmSolver::getOCPSolution(const vector_t& delta
393385 // to determine if the solution is a descent direction for the cost: compute gradient(cost)' * [dx; du]
394386 solution.armijoDescentMetric = armijoDescentMetric (lagrangian_, deltaXSol, deltaUSol);
395387
388+ // Extract value function
389+ auto & deltaLmdSol = solution.deltaLmdSol ;
390+ if (settings_.createValueFunction ) {
391+ valueFunction_ = hpipmInterface_.getRiccatiCostToGo (dynamics_[0 ], lagrangian_[0 ]);
392+ // Extract costate directions
393+ if (settings_.computeLagrangeMultipliers ) {
394+ deltaLmdSol.resize (deltaXSol.size ());
395+ for (int i = 0 ; i < deltaXSol.size (); ++i) {
396+ deltaLmdSol[i] = valueFunction_[i].dfdx ;
397+ deltaLmdSol[i].noalias () += valueFunction_[i].dfdxx * deltaXSol[i];
398+ }
399+ }
400+ }
401+
396402 // Problem horizon
397403 const int N = static_cast <int >(deltaXSol.size ()) - 1 ;
398404
@@ -436,6 +442,7 @@ IpmSolver::OcpSubproblemSolution IpmSolver::getOCPSolution(const vector_t& delta
436442 deltaNuSol[i] = projectionMultiplierCoefficients_[i].f ;
437443 deltaNuSol[i].noalias () += projectionMultiplierCoefficients_[i].dfdx * deltaXSol[i];
438444 deltaNuSol[i].noalias () += projectionMultiplierCoefficients_[i].dfdu * deltaUSol[i];
445+ deltaNuSol[i].noalias () += projectionMultiplierCoefficients_[i].dfdcostate * deltaLmdSol[i + 1 ];
439446 }
440447 // Re-map the projected input back to the original space.
441448 tmp.noalias () = constraintsProjection_[i].dfdu * deltaUSol[i];
@@ -465,16 +472,9 @@ IpmSolver::OcpSubproblemSolution IpmSolver::getOCPSolution(const vector_t& delta
465472}
466473
467474void IpmSolver::extractValueFunction (const std::vector<AnnotatedTime>& time, const vector_array_t & x, const vector_array_t & lmd,
468- const vector_array_t & deltaXSol, vector_array_t & deltaLmdSol ) {
475+ const vector_array_t & deltaXSol) {
469476 if (settings_.createValueFunction ) {
470- valueFunction_ = hpipmInterface_.getRiccatiCostToGo (dynamics_[0 ], lagrangian_[0 ]);
471- // Compute costate directions
472- deltaLmdSol.resize (deltaXSol.size ());
473- for (int i = 0 ; i < time.size (); ++i) {
474- deltaLmdSol[i] = valueFunction_[i].dfdx ;
475- deltaLmdSol[i].noalias () += valueFunction_[i].dfdxx * x[i];
476- }
477- // Correct for linearization state
477+ // Correct for linearization state. Naive value function of hpipm is already extracted and stored in valueFunction_ in getOCPSolution().
478478 for (int i = 0 ; i < time.size (); ++i) {
479479 valueFunction_[i].dfdx .noalias () -= valueFunction_[i].dfdxx * x[i];
480480 if (settings_.computeLagrangeMultipliers ) {
0 commit comments