28template <
typename F,
typename State,
typename Input,
typename Time>
36 return x + (
k1 +
k2 * 2.0 +
k3 * 2.0 +
k4) * (
dt / 6.0);
123 int numStates,
int numInputs, std::chrono::duration<double> dt,
139 return dynamics(x, u);
163 int numStates,
int numInputs, std::chrono::duration<double> dt,
171 : m_numStates{numStates},
172 m_numInputs{numInputs},
174 m_numSteps{numSteps},
175 m_transcriptionMethod{method},
176 m_dynamicsType{dynamicsType},
177 m_dynamicsFunction{std::move(dynamics)},
178 m_timestepMethod{timestepMethod} {
180 m_U = DecisionVariable(m_numInputs, m_numSteps + 1);
182 if (m_timestepMethod == TimestepMethod::kFixed) {
184 for (
int i = 0; i < numSteps + 1; ++i) {
185 m_DT(0, i) = m_dt.count();
187 }
else if (m_timestepMethod == TimestepMethod::kVariableSingle) {
193 for (
int i = 0; i < numSteps + 1; ++i) {
196 }
else if (m_timestepMethod == TimestepMethod::kVariable) {
197 m_DT = DecisionVariable(1, m_numSteps + 1);
198 for (
int i = 0; i < numSteps + 1; ++i) {
199 m_DT(0, i).SetValue(m_dt.count());
203 if (m_transcriptionMethod == TranscriptionMethod::kDirectTranscription) {
204 m_X = DecisionVariable(m_numStates, m_numSteps + 1);
205 ConstrainDirectTranscription();
206 }
else if (m_transcriptionMethod ==
207 TranscriptionMethod::kDirectCollocation) {
208 m_X = DecisionVariable(m_numStates, m_numSteps + 1);
209 ConstrainDirectCollocation();
210 }
else if (m_transcriptionMethod == TranscriptionMethod::kSingleShooting) {
214 ConstrainSingleShooting();
223 template <
typename T>
226 SubjectTo(InitialState() == initialState);
234 template <
typename T>
237 SubjectTo(FinalState() == finalState);
251 for (
int i = 0; i < m_numSteps + 1; ++i) {
272 for (
int i = 0; i < m_numSteps + 1; ++i) {
275 auto dt = DT()(0, i);
276 callback(time, x, u, dt);
288 template <
typename T>
291 for (
int i = 0; i < m_numSteps + 1; ++i) {
292 SubjectTo(U().Col(i) >= lowerBound);
302 template <
typename T>
305 for (
int i = 0; i < m_numSteps + 1; ++i) {
306 SubjectTo(U().Col(i) <= upperBound);
316 SubjectTo(DT() >= minTimestep.count());
325 SubjectTo(DT() <= maxTimestep.count());
375 void ConstrainDirectCollocation() {
376 Assert(m_dynamicsType == DynamicsType::kExplicitODE);
381 for (
int i = 0; i < m_numSteps; ++i) {
384 auto& f = m_dynamicsFunction;
387 auto t_end = t_begin + h;
389 auto x_begin = X().Col(i);
390 auto x_end = X().Col(i + 1);
392 auto u_begin = U().Col(i);
393 auto u_end = U().Col(i + 1);
395 auto xdot_begin = f(t_begin, x_begin, u_begin, h);
396 auto xdot_end = f(t_end, x_end, u_end, h);
398 -3 / (2 * h) * (x_begin - x_end) - 0.25 * (xdot_begin + xdot_end);
400 auto t_c = t_begin + 0.5 * h;
401 auto x_c = 0.5 * (x_begin + x_end) + h / 8 * (xdot_begin - xdot_end);
402 auto u_c = 0.5 * (u_begin + u_end);
404 SubjectTo(xdot_c == f(t_c, x_c, u_c, h));
410 void ConstrainDirectTranscription() {
413 for (
int i = 0; i < m_numSteps; ++i) {
414 auto x_begin = X().Col(i);
415 auto x_end = X().Col(i + 1);
417 Variable dt = DT()(0, i);
419 if (m_dynamicsType == DynamicsType::kExplicitODE) {
420 SubjectTo(x_end == RK4<
const decltype(m_dynamicsFunction)&,
421 VariableMatrix, VariableMatrix, Variable>(
422 m_dynamicsFunction, x_begin, u, time, dt));
423 }
else if (m_dynamicsType == DynamicsType::kDiscrete) {
424 SubjectTo(x_end == m_dynamicsFunction(time, x_begin, u, dt));
431 void ConstrainSingleShooting() {
434 for (
int i = 0; i < m_numSteps; ++i) {
435 auto x_begin = X().Col(i);
436 auto x_end = X().Col(i + 1);
438 Variable dt = DT()(0, i);
440 if (m_dynamicsType == DynamicsType::kExplicitODE) {
441 x_end =
RK4<
const decltype(m_dynamicsFunction)&, VariableMatrix,
442 VariableMatrix, Variable>(m_dynamicsFunction, x_begin, u,
444 }
else if (m_dynamicsType == DynamicsType::kDiscrete) {
445 x_end = m_dynamicsFunction(time, x_begin, u, dt);
454 std::chrono::duration<double> m_dt;
460 function_ref<VariableMatrix(
const Variable& t,
const VariableMatrix& x,
461 const VariableMatrix& u,
const Variable& dt)>
#define Assert(condition)
Definition Assert.hpp:24
#define SLEIPNIR_DLLEXPORT
Definition SymbolExports.hpp:34
Definition OCPSolver.hpp:103
void ConstrainInitialState(const T &initialState)
Definition OCPSolver.hpp:225
void SetMinTimestep(std::chrono::duration< double > minTimestep)
Definition OCPSolver.hpp:315
VariableMatrix InitialState()
Definition OCPSolver.hpp:365
VariableMatrix & U()
Definition OCPSolver.hpp:347
void SetMaxTimestep(std::chrono::duration< double > maxTimestep)
Definition OCPSolver.hpp:324
void ForEachStep(const function_ref< void(const VariableMatrix &x, const VariableMatrix &u)> callback)
Definition OCPSolver.hpp:248
VariableMatrix & DT()
Definition OCPSolver.hpp:358
void ConstrainFinalState(const T &finalState)
Definition OCPSolver.hpp:236
void SetUpperInputBound(const T &upperBound)
Definition OCPSolver.hpp:304
VariableMatrix FinalState()
Definition OCPSolver.hpp:372
void ForEachStep(const function_ref< void(const Variable &t, const VariableMatrix &x, const VariableMatrix &u, const Variable &dt)> callback)
Definition OCPSolver.hpp:266
void SetLowerInputBound(const T &lowerBound)
Definition OCPSolver.hpp:290
OCPSolver(int numStates, int numInputs, std::chrono::duration< double > dt, int numSteps, function_ref< VariableMatrix(const VariableMatrix &x, const VariableMatrix &u)> dynamics, DynamicsType dynamicsType=DynamicsType::kExplicitODE, TimestepMethod timestepMethod=TimestepMethod::kFixed, TranscriptionMethod method=TranscriptionMethod::kDirectTranscription)
Definition OCPSolver.hpp:122
VariableMatrix & X()
Definition OCPSolver.hpp:336
OCPSolver(int numStates, int numInputs, std::chrono::duration< double > dt, int numSteps, function_ref< VariableMatrix(const Variable &t, const VariableMatrix &x, const VariableMatrix &u, const Variable &dt)> dynamics, DynamicsType dynamicsType=DynamicsType::kExplicitODE, TimestepMethod timestepMethod=TimestepMethod::kFixed, TranscriptionMethod method=TranscriptionMethod::kDirectTranscription)
Definition OCPSolver.hpp:162
Definition OptimizationProblem.hpp:51
Definition VariableMatrix.hpp:28
VariableBlock< VariableMatrix > Col(int col)
Definition VariableMatrix.hpp:505
Definition Variable.hpp:33
void SetValue(double value)
Definition Variable.hpp:92
Definition FunctionRef.hpp:17
Definition Concepts.hpp:28
Definition Concepts.hpp:12
Definition Expression.hpp:18
IntrusiveSharedPtr< T > AllocateIntrusiveShared(Alloc alloc, Args &&... args)
Definition IntrusiveSharedPtr.hpp:275
DynamicsType
Definition OCPSolver.hpp:57
@ kExplicitODE
The dynamics are a function in the form dx/dt = f(t, x, u).
@ kDiscrete
The dynamics are a function in the form xₖ₊₁ = f(t, xₖ, uₖ).
TranscriptionMethod
Definition OCPSolver.hpp:42
TimestepMethod
Definition OCPSolver.hpp:67
@ kFixed
The timestep is a fixed constant.
@ kVariable
The timesteps are allowed to vary as independent decision variables.
State RK4(F &&f, State x, Input u, Time t0, Time dt)
Definition OCPSolver.hpp:29
function_ref(R(*)(Args...)) -> function_ref< R(Args...)>