28template <
typename F,
typename State,
typename Input,
typename Time>
29State
rk4(F&& f, State x, Input u, Time t0, Time dt) {
30 auto halfdt = dt * 0.5;
31 State k1 = f(t0, x, u, dt);
32 State k2 = f(t0 + halfdt, x + k1 * halfdt, u, dt);
33 State k3 = f(t0 + halfdt, x + k2 * halfdt, u, dt);
34 State k4 = f(t0 + dt, x + k3 * dt, u, dt);
36 return x + (k1 + k2 * 2.0 + k3 * 2.0 + k4) * (dt / 6.0);
122 OCP(
int num_states,
int num_inputs, std::chrono::duration<double> dt,
127 DynamicsType dynamics_type = DynamicsType::EXPLICIT_ODE,
138 return dynamics(x, u);
161 OCP(
int num_states,
int num_inputs, std::chrono::duration<double> dt,
166 DynamicsType dynamics_type = DynamicsType::EXPLICIT_ODE,
169 : m_num_states{num_states},
170 m_num_inputs{num_inputs},
172 m_num_steps{num_steps},
173 m_transcription_method{method},
174 m_dynamics_type{dynamics_type},
175 m_dynamics_function{
std::move(dynamics)},
176 m_timestep_method{timestep_method} {
178 m_U = decision_variable(m_num_inputs, m_num_steps + 1);
180 if (m_timestep_method == TimestepMethod::FIXED) {
182 for (
int i = 0; i < num_steps + 1; ++i) {
183 m_DT(0, i) = m_dt.count();
185 }
else if (m_timestep_method == TimestepMethod::VARIABLE_SINGLE) {
191 for (
int i = 0; i < num_steps + 1; ++i) {
194 }
else if (m_timestep_method == TimestepMethod::VARIABLE) {
195 m_DT = decision_variable(1, m_num_steps + 1);
196 for (
int i = 0; i < num_steps + 1; ++i) {
197 m_DT(0, i).set_value(m_dt.count());
201 if (m_transcription_method == TranscriptionMethod::DIRECT_TRANSCRIPTION) {
202 m_X = decision_variable(m_num_states, m_num_steps + 1);
203 constrain_direct_transcription();
204 }
else if (m_transcription_method ==
205 TranscriptionMethod::DIRECT_COLLOCATION) {
206 m_X = decision_variable(m_num_states, m_num_steps + 1);
207 constrain_direct_collocation();
208 }
else if (m_transcription_method == TranscriptionMethod::SINGLE_SHOOTING) {
212 constrain_single_shooting();
221 template <
typename T>
224 subject_to(this->initial_state() == initial_state);
232 template <
typename T>
235 subject_to(this->final_state() == final_state);
249 for (
int i = 0; i < m_num_steps + 1; ++i) {
270 for (
int i = 0; i < m_num_steps + 1; ++i) {
273 auto dt = this->dt()(0, i);
274 callback(time, x, u, dt);
286 template <
typename T>
289 for (
int i = 0; i < m_num_steps + 1; ++i) {
290 subject_to(U().col(i) >= lower_bound);
300 template <
typename T>
303 for (
int i = 0; i < m_num_steps + 1; ++i) {
304 subject_to(U().col(i) <= upper_bound);
314 subject_to(dt() >= min_timestep.count());
323 subject_to(dt() <= max_timestep.count());
373 void constrain_direct_collocation() {
374 slp_assert(m_dynamics_type == DynamicsType::EXPLICIT_ODE);
379 for (
int i = 0; i < m_num_steps; ++i) {
382 auto& f = m_dynamics_function;
385 auto t_end = t_begin + h;
387 auto x_begin = X().col(i);
388 auto x_end = X().col(i + 1);
390 auto u_begin = U().col(i);
391 auto u_end = U().col(i + 1);
393 auto xdot_begin = f(t_begin, x_begin, u_begin, h);
394 auto xdot_end = f(t_end, x_end, u_end, h);
396 -3 / (2 * h) * (x_begin - x_end) - 0.25 * (xdot_begin + xdot_end);
398 auto t_c = t_begin + 0.5 * h;
399 auto x_c = 0.5 * (x_begin + x_end) + h / 8 * (xdot_begin - xdot_end);
400 auto u_c = 0.5 * (u_begin + u_end);
402 subject_to(xdot_c == f(t_c, x_c, u_c, h));
408 void constrain_direct_transcription() {
411 for (
int i = 0; i < m_num_steps; ++i) {
412 auto x_begin = X().col(i);
413 auto x_end = X().col(i + 1);
415 Variable dt = this->dt()(0, i);
417 if (m_dynamics_type == DynamicsType::EXPLICIT_ODE) {
418 subject_to(x_end == rk4<
const decltype(m_dynamics_function)&,
419 VariableMatrix, VariableMatrix, Variable>(
420 m_dynamics_function, x_begin, u, time, dt));
421 }
else if (m_dynamics_type == DynamicsType::DISCRETE) {
422 subject_to(x_end == m_dynamics_function(time, x_begin, u, dt));
429 void constrain_single_shooting() {
432 for (
int i = 0; i < m_num_steps; ++i) {
433 auto x_begin = X().col(i);
434 auto x_end = X().col(i + 1);
436 Variable dt = this->dt()(0, i);
438 if (m_dynamics_type == DynamicsType::EXPLICIT_ODE) {
439 x_end =
rk4<
const decltype(m_dynamics_function)&, VariableMatrix,
440 VariableMatrix, Variable>(m_dynamics_function, x_begin, u,
442 }
else if (m_dynamics_type == DynamicsType::DISCRETE) {
443 x_end = m_dynamics_function(time, x_begin, u, dt);
452 std::chrono::duration<double> m_dt;
458 function_ref<VariableMatrix(
const Variable& t,
const VariableMatrix& x,
459 const VariableMatrix& u,
const Variable& dt)>
#define slp_assert(condition)
Abort in C++.
Definition assert.hpp:26
This class allows the user to pose and solve a constrained optimal control problem (OCP) in a variety...
Definition ocp.hpp:103
OCP(int num_states, int num_inputs, std::chrono::duration< double > dt, int num_steps, function_ref< VariableMatrix(const Variable &t, const VariableMatrix &x, const VariableMatrix &u, const Variable &dt)> dynamics, DynamicsType dynamics_type=DynamicsType::EXPLICIT_ODE, TimestepMethod timestep_method=TimestepMethod::FIXED, TranscriptionMethod method=TranscriptionMethod::DIRECT_TRANSCRIPTION)
Build an optimization problem using a system evolution function (explicit ODE or discrete state trans...
Definition ocp.hpp:161
VariableMatrix & U()
Get the input variables.
Definition ocp.hpp:345
void constrain_initial_state(const T &initial_state)
Utility function to constrain the initial state.
Definition ocp.hpp:223
void for_each_step(const function_ref< void(const Variable &t, const VariableMatrix &x, const VariableMatrix &u, const Variable &dt)> callback)
Set the constraint evaluation function.
Definition ocp.hpp:264
VariableMatrix & dt()
Get the timestep variables.
Definition ocp.hpp:356
VariableMatrix & X()
Get the state variables.
Definition ocp.hpp:334
void set_min_timestep(std::chrono::duration< double > min_timestep)
Convenience function to set a lower bound on the timestep.
Definition ocp.hpp:313
VariableMatrix initial_state()
Convenience function to get the initial state in the trajectory.
Definition ocp.hpp:363
void set_upper_input_bound(const T &upper_bound)
Convenience function to set an upper bound on the input.
Definition ocp.hpp:302
void for_each_step(const function_ref< void(const VariableMatrix &x, const VariableMatrix &u)> callback)
Set the constraint evaluation function.
Definition ocp.hpp:246
void set_lower_input_bound(const T &lower_bound)
Convenience function to set a lower bound on the input.
Definition ocp.hpp:288
VariableMatrix final_state()
Convenience function to get the final state in the trajectory.
Definition ocp.hpp:370
OCP(int num_states, int num_inputs, std::chrono::duration< double > dt, int num_steps, function_ref< VariableMatrix(const VariableMatrix &x, const VariableMatrix &u)> dynamics, DynamicsType dynamics_type=DynamicsType::EXPLICIT_ODE, TimestepMethod timestep_method=TimestepMethod::FIXED, TranscriptionMethod method=TranscriptionMethod::DIRECT_TRANSCRIPTION)
Build an optimization problem using a system evolution function (explicit ODE or discrete state trans...
Definition ocp.hpp:122
void set_max_timestep(std::chrono::duration< double > max_timestep)
Convenience function to set an upper bound on the timestep.
Definition ocp.hpp:322
void constrain_final_state(const T &final_state)
Utility function to constrain the final state.
Definition ocp.hpp:234
This class allows the user to pose a constrained nonlinear optimization problem in natural mathematic...
Definition problem.hpp:47
An autodiff variable pointing to an expression node.
Definition variable.hpp:40
void set_value(double value)
Sets Variable's internal value.
Definition variable.hpp:99
A matrix of autodiff variables.
Definition variable_matrix.hpp:29
VariableBlock< VariableMatrix > col(int col)
Returns a column slice of the variable matrix.
Definition variable_matrix.hpp:546
Definition function_ref.hpp:13
Definition concepts.hpp:40
Definition concepts.hpp:13
Definition expression_graph.hpp:11
State rk4(F &&f, State x, Input u, Time t0, Time dt)
Performs 4th order Runge-Kutta integration of dx/dt = f(t, x, u) for dt.
Definition ocp.hpp:29
TimestepMethod
Enum describing the type of system timestep.
Definition ocp.hpp:67
@ VARIABLE_SINGLE
The timesteps are equal length but allowed to vary as a single decision variable.
@ FIXED
The timestep is a fixed constant.
@ VARIABLE
The timesteps are allowed to vary as independent decision variables.
DynamicsType
Enum describing a type of system dynamics constraints.
Definition ocp.hpp:57
@ DISCRETE
The dynamics are a function in the form xₖ₊₁ = f(t, xₖ, uₖ).
@ EXPLICIT_ODE
The dynamics are a function in the form dx/dt = f(t, x, u).
function_ref(R(*)(Args...)) -> function_ref< R(Args...)>
TranscriptionMethod
Enum describing an OCP transcription method.
Definition ocp.hpp:42
@ DIRECT_COLLOCATION
The trajectory is modeled as a series of cubic polynomials where the centerpoint slope is constrained...
@ SINGLE_SHOOTING
States depend explicitly as a function of all previous states and all previous inputs.
@ DIRECT_TRANSCRIPTION
Each state is a decision variable constrained to the integrated dynamics of the previous state.
Definition PointerIntPair.h:280
#define SLEIPNIR_DLLEXPORT
Definition symbol_exports.hpp:34