Skip to content

Commit dfdf20d

Browse files
update after merge
1 parent a6d01ae commit dfdf20d

File tree

8 files changed

+74
-41
lines changed

8 files changed

+74
-41
lines changed

ocs2_ddp/src/DDP_HelperFunctions.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ void computeRolloutMetrics(OptimalControlProblem& problem, const PrimalSolution&
7373
problemMetrics.intermediates.reserve(tTrajectory.size());
7474

7575
auto nextPostEventIndexItr = postEventIndices.begin();
76-
const auto request = Request::Cost + Request::Constraint + Request::SoftConstraint;
76+
constexpr auto request = Request::Cost + Request::Constraint + Request::SoftConstraint;
7777
for (size_t k = 0; k < tTrajectory.size(); k++) {
7878
// intermediate time cost and constraints
7979
problem.preComputationPtr->request(request, tTrajectory[k], xTrajectory[k], uTrajectory[k]);

ocs2_oc/include/ocs2_oc/multiple_shooting/Helpers.h

+10
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3333

3434
#include "ocs2_oc/oc_data/PerformanceIndex.h"
3535
#include "ocs2_oc/oc_data/PrimalSolution.h"
36+
#include "ocs2_oc/oc_data/ProblemMetrics.h"
3637
#include "ocs2_oc/oc_data/TimeDiscretization.h"
3738

3839
namespace ocs2 {
@@ -101,5 +102,14 @@ PrimalSolution toPrimalSolution(const std::vector<AnnotatedTime>& time, ModeSche
101102
PrimalSolution toPrimalSolution(const std::vector<AnnotatedTime>& time, ModeSchedule&& modeSchedule, vector_array_t&& x, vector_array_t&& u,
102103
matrix_array_t&& KMatrices);
103104

105+
/**
106+
* Constructs a ProblemMetrics from an array of metrics.
107+
*
108+
* @param [in] time : The annotated time trajectory
109+
* @param [in] metrics: The metrics array.
110+
* @return The ProblemMetrics.
111+
*/
112+
ProblemMetrics toProblemMetrics(const std::vector<AnnotatedTime>& time, const std::vector<Metrics>& metrics);
113+
104114
} // namespace multiple_shooting
105115
} // namespace ocs2

ocs2_oc/include/ocs2_oc/oc_data/PerformanceIndex.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -115,9 +115,12 @@ inline PerformanceIndex operator*(const scalar_t c, PerformanceIndex rhs) {
115115
/** Swaps performance indices. */
116116
void swap(PerformanceIndex& lhs, PerformanceIndex& rhs);
117117

118-
/** Computes the PerformanceIndex based on a given Metrics. */
118+
/** Computes the PerformanceIndex based on a given continuous-time Metrics. */
119119
PerformanceIndex toPerformanceIndex(const Metrics& m);
120120

121+
/** Computes the PerformanceIndex based on a given discrete-time Metrics. */
122+
PerformanceIndex toPerformanceIndex(const Metrics& m, const scalar_t dt);
123+
121124
/** Overloads the stream insertion operator. */
122125
std::ostream& operator<<(std::ostream& stream, const PerformanceIndex& performanceIndex);
123126

ocs2_oc/src/multiple_shooting/Helpers.cpp

+24
Original file line numberDiff line numberDiff line change
@@ -119,5 +119,29 @@ PrimalSolution toPrimalSolution(const std::vector<AnnotatedTime>& time, ModeSche
119119
return primalSolution;
120120
}
121121

122+
ProblemMetrics toProblemMetrics(const std::vector<AnnotatedTime>& time, const std::vector<Metrics>& metrics) {
123+
assert(time.size() > 1);
124+
assert(metrics.size() == time.size());
125+
126+
// Problem horizon
127+
const int N = static_cast<int>(time.size()) - 1;
128+
129+
// resize
130+
ProblemMetrics problemMetrics;
131+
problemMetrics.intermediates.reserve(N);
132+
problemMetrics.preJumps.reserve(8); // the size is just a guess
133+
problemMetrics.final = metrics.back();
134+
135+
for (int i = 0; i < N; ++i) {
136+
if (time[i].event == AnnotatedTime::Event::PreEvent) {
137+
problemMetrics.preJumps.push_back(metrics[i]);
138+
} else {
139+
problemMetrics.intermediates.push_back(metrics[i]);
140+
}
141+
}
142+
143+
return problemMetrics;
144+
}
145+
122146
} // namespace multiple_shooting
123147
} // namespace ocs2

ocs2_oc/src/multiple_shooting/PerformanceIndexComputation.cpp

+1-6
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,7 @@ PerformanceIndex computeIntermediatePerformance(const Transcription& transcripti
6060
PerformanceIndex computeIntermediatePerformance(OptimalControlProblem& optimalControlProblem, DynamicsDiscretizer& discretizer, scalar_t t,
6161
scalar_t dt, const vector_t& x, const vector_t& x_next, const vector_t& u) {
6262
const auto metrics = computeIntermediateMetrics(optimalControlProblem, discretizer, t, dt, x, x_next, u);
63-
auto performanceIndex = toPerformanceIndex(metrics);
64-
// performanceIndex.cost *= dt no need since it is already considered in multiple_shooting::computeIntermediateMetrics()
65-
performanceIndex.dynamicsViolationSSE *= dt;
66-
performanceIndex.equalityConstraintsSSE *= dt;
67-
performanceIndex.inequalityConstraintsSSE *= dt;
68-
return performanceIndex;
63+
return toPerformanceIndex(metrics, dt);
6964
}
7065

7166
PerformanceIndex computeTerminalPerformance(const TerminalTranscription& transcription) {

ocs2_oc/src/oc_data/PerformanceIndex.cpp

+10
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,16 @@ PerformanceIndex toPerformanceIndex(const Metrics& m) {
9898
return performanceIndex;
9999
}
100100

101+
PerformanceIndex toPerformanceIndex(const Metrics& m, const scalar_t dt) {
102+
auto performanceIndex = toPerformanceIndex(m);
103+
// performanceIndex.cost *= dt no need since it is already considered in multiple_shooting::computeIntermediateMetrics()
104+
performanceIndex.dualFeasibilitiesSSE *= dt;
105+
performanceIndex.dynamicsViolationSSE *= dt;
106+
performanceIndex.equalityConstraintsSSE *= dt;
107+
performanceIndex.inequalityConstraintsSSE *= dt;
108+
return performanceIndex;
109+
}
110+
101111
std::ostream& operator<<(std::ostream& stream, const PerformanceIndex& performanceIndex) {
102112
const size_t tabSpace = 12;
103113
const auto indentation = stream.width();

ocs2_sqp/ocs2_sqp/include/ocs2_sqp/SqpSolver.h

+3-4
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ class SqpSolver : public SolverBase {
125125

126126
/** Computes only the performance metrics at the current {t, x(t), u(t)} */
127127
PerformanceIndex computePerformance(const std::vector<AnnotatedTime>& time, const vector_t& initState, const vector_array_t& x,
128-
const vector_array_t& u, ProblemMetrics& problemMetrics);
128+
const vector_array_t& u, std::vector<Metrics>& metrics);
129129

130130
/** Returns solution of the QP subproblem in delta coordinates: */
131131
struct OcpSubproblemSolution {
@@ -143,7 +143,8 @@ class SqpSolver : public SolverBase {
143143

144144
/** Decides on the step to take and overrides given trajectories {x(t), u(t)} <- {x(t) + a*dx(t), u(t) + a*du(t)} */
145145
sqp::StepInfo takeStep(const PerformanceIndex& baseline, const std::vector<AnnotatedTime>& timeDiscretization, const vector_t& initState,
146-
const OcpSubproblemSolution& subproblemSolution, vector_array_t& x, vector_array_t& u);
146+
const OcpSubproblemSolution& subproblemSolution, vector_array_t& x, vector_array_t& u,
147+
std::vector<Metrics>& metrics);
147148

148149
/** Determine convergence after a step */
149150
sqp::Convergence checkConvergence(int iteration, const PerformanceIndex& baseline, const sqp::StepInfo& stepInfo) const;
@@ -184,8 +185,6 @@ class SqpSolver : public SolverBase {
184185

185186
// The ProblemMetrics associated to primalSolution_
186187
ProblemMetrics problemMetrics_;
187-
// Memory used within the search strategy
188-
ProblemMetrics problemMetricsNew_;
189188

190189
// Benchmarking
191190
size_t numProblems_{0};

ocs2_sqp/ocs2_sqp/src/SqpSolver.cpp

+21-29
Original file line numberDiff line numberDiff line change
@@ -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/oc_problem/OcpSize.h>
@@ -176,6 +177,7 @@ void SqpSolver::runImpl(scalar_t initTime, const vector_t& initState, scalar_t f
176177

177178
// Bookkeeping
178179
performanceIndeces_.clear();
180+
std::vector<Metrics> metrics(timeDiscretization.size());
179181

180182
int iter = 0;
181183
sqp::Convergence convergence = sqp::Convergence::FALSE;
@@ -197,7 +199,7 @@ void SqpSolver::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 SqpSolver::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, metrics);
214217
computeControllerTimer_.endTimer();
215218

216219
++numProblems_;
@@ -362,21 +365,11 @@ PerformanceIndex SqpSolver::setupQuadraticSubproblem(const std::vector<Annotated
362365
}
363366

364367
PerformanceIndex SqpSolver::computePerformance(const std::vector<AnnotatedTime>& time, const vector_t& initState, const vector_array_t& x,
365-
const vector_array_t& u, ProblemMetrics& problemMetrics) {
366-
// Problem horizon
368+
const vector_array_t& u, std::vector<Metrics>& metrics) {
369+
// Problem size
367370
const int N = static_cast<int>(time.size()) - 1;
368-
369-
// extract indices for setting up problemMetrics
370-
int numEvents = 0, numIntermediates = 0;
371-
std::vector<int> indices(N);
372-
for (int i = 0; i < N; ++i) {
373-
indices[i] = (time[i].event == AnnotatedTime::Event::PreEvent) ? numEvents++ : numIntermediates++;
374-
}
375-
376-
// resize
377-
problemMetrics.clear();
378-
problemMetrics.preJumps.resize(numEvents);
379-
problemMetrics.intermediates.resize(numIntermediates);
371+
metrics.clear();
372+
metrics.resize(N + 1);
380373

381374
std::vector<PerformanceIndex> performance(settings_.nThreads, PerformanceIndex());
382375
std::atomic_int timeIndex{0};
@@ -386,34 +379,32 @@ PerformanceIndex SqpSolver::computePerformance(const std::vector<AnnotatedTime>&
386379

387380
int i = timeIndex++;
388381
while (i < N) {
389-
const auto problemMetricsIndex = indices[i];
390382
if (time[i].event == AnnotatedTime::Event::PreEvent) {
391383
// Event node
392-
problemMetrics.preJumps[problemMetricsIndex] = multiple_shooting::computeEventMetrics(ocpDefinition, time[i].time, x[i], x[i + 1]);
393-
performance[workerId] += toPerformanceIndex(problemMetrics.preJumps[problemMetricsIndex]);
384+
metrics[i] = multiple_shooting::computeEventMetrics(ocpDefinition, time[i].time, x[i], x[i + 1]);
385+
performance[workerId] += toPerformanceIndex(metrics[i]);
394386
} else {
395387
// Normal, intermediate node
396388
const scalar_t ti = getIntervalStart(time[i]);
397389
const scalar_t dt = getIntervalDuration(time[i], time[i + 1]);
398-
problemMetrics.intermediates[problemMetricsIndex] =
399-
multiple_shooting::computeIntermediateMetrics(ocpDefinition, discretizer_, ti, dt, x[i], x[i + 1], u[i]);
400-
performance[workerId] += toPerformanceIndex(problemMetrics.intermediates[problemMetricsIndex], dt);
390+
metrics[i] = multiple_shooting::computeIntermediateMetrics(ocpDefinition, discretizer_, ti, dt, x[i], x[i + 1], u[i]);
391+
performance[workerId] += toPerformanceIndex(metrics[i], dt);
401392
}
402393

403394
i = timeIndex++;
404395
}
405396

406397
if (i == N) { // Only one worker will execute this
407398
const scalar_t tN = getIntervalStart(time[N]);
408-
problemMetrics.final = multiple_shooting::computeTerminalMetrics(ocpDefinition, tN, x[N]);
409-
performance[workerId] += toPerformanceIndex(problemMetrics.final);
399+
metrics[N] = multiple_shooting::computeTerminalMetrics(ocpDefinition, tN, x[N]);
400+
performance[workerId] += toPerformanceIndex(metrics[N]);
410401
}
411402
};
412403
runParallel(std::move(parallelTask));
413404

414405
// Account for initial state in performance
415406
const vector_t initDynamicsViolation = initState - x.front();
416-
problemMetrics.intermediates.front().dynamicsViolation += initDynamicsViolation;
407+
metrics.front().dynamicsViolation += initDynamicsViolation;
417408
performance.front().dynamicsViolationSSE += initDynamicsViolation.squaredNorm();
418409

419410
// Sum performance of the threads
@@ -424,7 +415,7 @@ PerformanceIndex SqpSolver::computePerformance(const std::vector<AnnotatedTime>&
424415

425416
sqp::StepInfo SqpSolver::takeStep(const PerformanceIndex& baseline, const std::vector<AnnotatedTime>& timeDiscretization,
426417
const vector_t& initState, const OcpSubproblemSolution& subproblemSolution, vector_array_t& x,
427-
vector_array_t& u) {
418+
vector_array_t& u, std::vector<Metrics>& metrics) {
428419
using StepType = FilterLinesearch::StepType;
429420

430421
/*
@@ -450,13 +441,14 @@ sqp::StepInfo SqpSolver::takeStep(const PerformanceIndex& baseline, const std::v
450441
scalar_t alpha = 1.0;
451442
vector_array_t xNew(x.size());
452443
vector_array_t uNew(u.size());
444+
std::vector<Metrics> metricsNew(x.size());
453445
do {
454446
// Compute step
455447
multiple_shooting::incrementTrajectory(u, du, alpha, uNew);
456448
multiple_shooting::incrementTrajectory(x, dx, alpha, xNew);
457449

458450
// Compute cost and constraints
459-
const PerformanceIndex performanceNew = computePerformance(timeDiscretization, initState, xNew, uNew);
451+
const PerformanceIndex performanceNew = computePerformance(timeDiscretization, initState, xNew, uNew, metricsNew);
460452

461453
// Step acceptance and record step type
462454
bool stepAccepted;
@@ -474,7 +466,7 @@ sqp::StepInfo SqpSolver::takeStep(const PerformanceIndex& baseline, const std::v
474466
if (stepAccepted) { // Return if step accepted
475467
x = std::move(xNew);
476468
u = std::move(uNew);
477-
problemMetrics.swap(problemMetricsNew_);
469+
metrics = std::move(metricsNew);
478470

479471
// Prepare step info
480472
sqp::StepInfo stepInfo;
@@ -508,8 +500,8 @@ sqp::StepInfo SqpSolver::takeStep(const PerformanceIndex& baseline, const std::v
508500
stepInfo.du_norm = 0.0;
509501
stepInfo.performanceAfterStep = baseline;
510502
stepInfo.totalConstraintViolationAfterStep = FilterLinesearch::totalConstraintViolation(baseline);
511-
512-
std::ignore = computePerformance(timeDiscretization, initState, xNew, uNew, problemMetrics);
503+
// compute metrics for the baseline rollout
504+
std::ignore = computePerformance(timeDiscretization, initState, x, u, metrics);
513505

514506
if (settings_.printLinesearch) {
515507
std::cerr << "[Linesearch terminated] Step size: " << stepInfo.stepSize << ", Step Type: " << toString(stepInfo.stepType) << "\n";

0 commit comments

Comments
 (0)