@@ -35,6 +35,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3535
3636#include < ocs2_oc/multiple_shooting/Helpers.h>
3737#include < ocs2_oc/multiple_shooting/Initialization.h>
38+ #include < ocs2_oc/multiple_shooting/MetricsComputation.h>
3839#include < ocs2_oc/multiple_shooting/PerformanceIndexComputation.h>
3940#include < ocs2_oc/multiple_shooting/Transcription.h>
4041#include < ocs2_oc/precondition/Ruzi.h>
@@ -177,6 +178,7 @@ void SlpSolver::runImpl(scalar_t initTime, const vector_t& initState, scalar_t f
177178
178179 // Bookkeeping
179180 performanceIndeces_.clear ();
181+ std::vector<Metrics> metrics;
180182
181183 int iter = 0 ;
182184 slp::Convergence convergence = slp::Convergence::FALSE ;
@@ -186,7 +188,7 @@ void SlpSolver::runImpl(scalar_t initTime, const vector_t& initState, scalar_t f
186188 }
187189 // Make QP approximation
188190 linearQuadraticApproximationTimer_.startTimer ();
189- const auto baselinePerformance = setupQuadraticSubproblem (timeDiscretization, initState, x, u);
191+ const auto baselinePerformance = setupQuadraticSubproblem (timeDiscretization, initState, x, u, metrics );
190192 linearQuadraticApproximationTimer_.endTimer ();
191193
192194 // Solve LP
@@ -197,7 +199,7 @@ void SlpSolver::runImpl(scalar_t initTime, const vector_t& initState, scalar_t f
197199
198200 // Apply step
199201 linesearchTimer_.startTimer ();
200- const auto stepInfo = takeStep (baselinePerformance, timeDiscretization, initState, deltaSolution, x, u);
202+ const auto stepInfo = takeStep (baselinePerformance, timeDiscretization, initState, deltaSolution, x, u, metrics );
201203 performanceIndeces_.push_back (stepInfo.performanceAfterStep );
202204 linesearchTimer_.endTimer ();
203205
@@ -211,6 +213,7 @@ void SlpSolver::runImpl(scalar_t initTime, const vector_t& initState, scalar_t f
211213
212214 computeControllerTimer_.startTimer ();
213215 primalSolution_ = toPrimalSolution (timeDiscretization, std::move (x), std::move (u));
216+ problemMetrics_ = multiple_shooting::toProblemMetrics (timeDiscretization, std::move (metrics));
214217 computeControllerTimer_.endTimer ();
215218
216219 ++numProblems_;
@@ -290,7 +293,7 @@ PrimalSolution SlpSolver::toPrimalSolution(const std::vector<AnnotatedTime>& tim
290293}
291294
292295PerformanceIndex SlpSolver::setupQuadraticSubproblem (const std::vector<AnnotatedTime>& time, const vector_t & initState,
293- const vector_array_t & x, const vector_array_t & u) {
296+ const vector_array_t & x, const vector_array_t & u, std::vector<Metrics>& metrics ) {
294297 // Problem horizon
295298 const int N = static_cast <int >(time.size ()) - 1 ;
296299
@@ -302,6 +305,7 @@ PerformanceIndex SlpSolver::setupQuadraticSubproblem(const std::vector<Annotated
302305 stateInputIneqConstraints_.resize (N);
303306 constraintsProjection_.resize (N);
304307 projectionMultiplierCoefficients_.resize (N);
308+ metrics.resize (N + 1 );
305309
306310 std::atomic_int timeIndex{0 };
307311 auto parallelTask = [&](int workerId) {
@@ -314,6 +318,7 @@ PerformanceIndex SlpSolver::setupQuadraticSubproblem(const std::vector<Annotated
314318 if (time[i].event == AnnotatedTime::Event::PreEvent) {
315319 // Event node
316320 auto result = multiple_shooting::setupEventNode (ocpDefinition, time[i].time , x[i], x[i + 1 ]);
321+ metrics[i] = multiple_shooting::computeMetrics (result);
317322 workerPerformance += multiple_shooting::computePerformanceIndex (result);
318323 cost_[i] = std::move (result.cost );
319324 dynamics_[i] = std::move (result.dynamics );
@@ -327,6 +332,7 @@ PerformanceIndex SlpSolver::setupQuadraticSubproblem(const std::vector<Annotated
327332 const scalar_t ti = getIntervalStart (time[i]);
328333 const scalar_t dt = getIntervalDuration (time[i], time[i + 1 ]);
329334 auto result = multiple_shooting::setupIntermediateNode (ocpDefinition, sensitivityDiscretizer_, ti, dt, x[i], x[i + 1 ], u[i]);
335+ metrics[i] = multiple_shooting::computeMetrics (result);
330336 workerPerformance += multiple_shooting::computePerformanceIndex (result, dt);
331337 multiple_shooting::projectTranscription (result, settings_.extractProjectionMultiplier );
332338 cost_[i] = std::move (result.cost );
@@ -344,6 +350,7 @@ PerformanceIndex SlpSolver::setupQuadraticSubproblem(const std::vector<Annotated
344350 if (i == N) { // Only one worker will execute this
345351 const scalar_t tN = getIntervalStart (time[N]);
346352 auto result = multiple_shooting::setupTerminalNode (ocpDefinition, tN, x[N]);
353+ metrics[i] = multiple_shooting::computeMetrics (result);
347354 workerPerformance += multiple_shooting::computePerformanceIndex (result);
348355 cost_[i] = std::move (result.cost );
349356 stateIneqConstraints_[i] = std::move (result.ineqConstraints );
@@ -365,44 +372,46 @@ PerformanceIndex SlpSolver::setupQuadraticSubproblem(const std::vector<Annotated
365372}
366373
367374PerformanceIndex SlpSolver::computePerformance (const std::vector<AnnotatedTime>& time, const vector_t & initState, const vector_array_t & x,
368- const vector_array_t & u) {
369- // Problem horizon
375+ const vector_array_t & u, std::vector<Metrics>& metrics ) {
376+ // Problem size
370377 const int N = static_cast <int >(time.size ()) - 1 ;
378+ metrics.resize (N + 1 );
371379
372380 std::vector<PerformanceIndex> performance (settings_.nThreads , PerformanceIndex ());
373381 std::atomic_int timeIndex{0 };
374382 auto parallelTask = [&](int workerId) {
375383 // Get worker specific resources
376384 OptimalControlProblem& ocpDefinition = ocpDefinitions_[workerId];
377- PerformanceIndex workerPerformance; // Accumulate performance in local variable
378385
379386 int i = timeIndex++;
380387 while (i < N) {
381388 if (time[i].event == AnnotatedTime::Event::PreEvent) {
382389 // Event node
383- workerPerformance += multiple_shooting::computeEventPerformance (ocpDefinition, time[i].time , x[i], x[i + 1 ]);
390+ metrics[i] = multiple_shooting::computeEventMetrics (ocpDefinition, time[i].time , x[i], x[i + 1 ]);
391+ performance[workerId] += toPerformanceIndex (metrics[i]);
384392 } else {
385393 // Normal, intermediate node
386394 const scalar_t ti = getIntervalStart (time[i]);
387395 const scalar_t dt = getIntervalDuration (time[i], time[i + 1 ]);
388- workerPerformance += multiple_shooting::computeIntermediatePerformance (ocpDefinition, discretizer_, ti, dt, x[i], x[i + 1 ], u[i]);
396+ metrics[i] = multiple_shooting::computeIntermediateMetrics (ocpDefinition, discretizer_, ti, dt, x[i], x[i + 1 ], u[i]);
397+ performance[workerId] += toPerformanceIndex (metrics[i], dt);
389398 }
390399
391400 i = timeIndex++;
392401 }
393402
394403 if (i == N) { // Only one worker will execute this
395404 const scalar_t tN = getIntervalStart (time[N]);
396- workerPerformance += multiple_shooting::computeTerminalPerformance (ocpDefinition, tN, x[N]);
405+ metrics[N] = multiple_shooting::computeTerminalMetrics (ocpDefinition, tN, x[N]);
406+ performance[workerId] += toPerformanceIndex (metrics[N]);
397407 }
398-
399- // Accumulate! Same worker might run multiple tasks
400- performance[workerId] += workerPerformance;
401408 };
402409 runParallel (std::move (parallelTask));
403410
404- // Account for init state in performance
405- performance.front ().dynamicsViolationSSE += (initState - x.front ()).squaredNorm ();
411+ // Account for initial state in performance
412+ const vector_t initDynamicsViolation = initState - x.front ();
413+ metrics.front ().dynamicsViolation += initDynamicsViolation;
414+ performance.front ().dynamicsViolationSSE += initDynamicsViolation.squaredNorm ();
406415
407416 // Sum performance of the threads
408417 PerformanceIndex totalPerformance = std::accumulate (std::next (performance.begin ()), performance.end (), performance.front ());
@@ -412,7 +421,7 @@ PerformanceIndex SlpSolver::computePerformance(const std::vector<AnnotatedTime>&
412421
413422slp::StepInfo SlpSolver::takeStep (const PerformanceIndex& baseline, const std::vector<AnnotatedTime>& timeDiscretization,
414423 const vector_t & initState, const OcpSubproblemSolution& subproblemSolution, vector_array_t & x,
415- vector_array_t & u) {
424+ vector_array_t & u, std::vector<Metrics>& metrics ) {
416425 using StepType = FilterLinesearch::StepType;
417426
418427 /*
@@ -438,13 +447,14 @@ slp::StepInfo SlpSolver::takeStep(const PerformanceIndex& baseline, const std::v
438447 scalar_t alpha = 1.0 ;
439448 vector_array_t xNew (x.size ());
440449 vector_array_t uNew (u.size ());
450+ std::vector<Metrics> metricsNew (metrics.size ());
441451 do {
442452 // Compute step
443453 multiple_shooting::incrementTrajectory (u, du, alpha, uNew);
444454 multiple_shooting::incrementTrajectory (x, dx, alpha, xNew);
445455
446456 // Compute cost and constraints
447- const PerformanceIndex performanceNew = computePerformance (timeDiscretization, initState, xNew, uNew);
457+ const PerformanceIndex performanceNew = computePerformance (timeDiscretization, initState, xNew, uNew, metricsNew );
448458
449459 // Step acceptance and record step type
450460 bool stepAccepted;
@@ -462,6 +472,7 @@ slp::StepInfo SlpSolver::takeStep(const PerformanceIndex& baseline, const std::v
462472 if (stepAccepted) { // Return if step accepted
463473 x = std::move (xNew);
464474 u = std::move (uNew);
475+ metrics = std::move (metricsNew);
465476
466477 // Prepare step info
467478 slp::StepInfo stepInfo;
0 commit comments