In *OpenOCL* you can solve a large class of optimal control problems including **non-linear**, **continuous-time**, **multi-stage**, and **constrained** problems, which can appear in the context of **trajectory optimization** and model **predictive control**. The types of dynamical systems that are supported are all systems that can be described by **ordinary differential equations** or **differential algebraic equations**.

We introduced some new concepts that should make it as easy as possible for you to model optimal control problems, in particular the notion of *grid*-costs and *grid*-constraints that can be very handy when implementing **tracking problems**. In the following we give a short introduction to the concepts used and introduced in *OpenOCL*.

We support **bounds** that hold along the entire trajectory, and ** grid-constraints** that hold only at specific gridpoints in the discretized trajectory.

For the cost terms you can specify ** path-costs** that are integrated along the trajectory (also known as Lagrange term), and

Performs simulations of the system by integrating the system dynamics.

```
simulator = Simulator(PendulumSystem);
x0 = simulator.getStates();
x0.p = [0;1];
x0.v = [-0.5;-1];
p = simulator.getParameters();
p.m = 1;
p.l = 1.5;
t = linspace(0,4,20);
% apply constant force
uVec = simulator.getControlsVec(20);
uVec.F = 10;
[xVec,zVec,uVec] = simulator.simulate(x0,t,uVec,p);
```

- system (OclSystem)
- The system dynamics
- options (struct, optional)
- Options struct, can be created with Simulator.getOptions(). Defaults to empty struct.

- (Simulator)
- the Simulator object.

- getControlsVec(N)
- Gives you a structured variable that allows you to specify an open-loop control input by setting values to the variable. The default value for all variables is zero.

- N (int)
- Number of control intervals

- (OclVariable)
- The control vector.

- getStates()
- Returns a structured state variable that you can use to pass as the initial state to the simulator. All variable values default to zero.

- (OclVariable)
- The states.

- getParameters()
- Returns a structured state variable that allows you to set parameters for the simulation. All parameter values default to zero.

- (OclVariable)
- The parameters.

- simulate(x0, times, p, uVec)
- Simulates the system for the given time interval.

- x0 (OclVariable)
- The initial state.
- times (numeric)
- Times vector. The system will be evaluated at the given time points.
- p (OclVariable)
- The parameters set to numeric values.
- uVec (OclVariable, optional)
- Controls vector with open-loop controls. Defaults to zero valued controls.

- (OclVariable)
- The state trajectory.
- (OclVariable)
- The trajectory of algebraic variables.
- (OclVariable)
- The control inputs applied to the system.

The constraint handler allows to add constraints to the optimal control problem definition.

- add(lhs, op, rhs)
- Adds a constraint to the optimal control problem.

- lhs (OclVariable or Matlab matrix)
- Left hand side of the constraint equation
- op (char)
- One of the following operators as a string: ‘<=’, ‘==’, ‘>=’
- rhs (OclVariable or Matlab matrix)
- Right hand side of the constraint equation

The cost handler allows to add cost terms in a cost function definition.

- add(cost)
- Adds a cost term.

- cost (OclVariable or Matlab matrix)
- Scalar variable containing the cost

The differential equations handler allows to specify the system equations which can be of ODE and DAE type.

- setODE(id, equation)
- Adds a differential equation to the system. Note that for every state variable defined in the variables function, a differential equation must be specified.

- id (char)
- Name of the state variable for that the differential equation is given.
- equation (OclVariable or Matlab matrix)
- The equation specifies the derivative of a state variable. Right hand side of the differential equation dot(x) = f(x,z,u,p) for state variable x.

- setAlgEquation(equation)
- Adds an algebraic equation to the system. Note that in order to be able to simulate the system, the total number of rows of the algebraic equations needs to be equal to the total number/dimension of algebraic variables.

- equation (OclVariable or Matlab matrix)
- Algebraic equation g in the form g(x,z,u,p)=0

Creates a solver object that discretizes the given optimal control problem, and calls the underlying optimizer.

```
function vanderpol
solver = ocl.Solver(END_TIME, @varsfun, @daefun, @pathcosts, 'N', 30);
solver.setInitialBounds('x', 0);
solver.setInitialBounds('y', 1);
initialGuess = solver.getInitialGuess();
initialGuess.states.x.set(-0.2);
[solution,timepoints] = solver.solve(initialGuess);
% initial guess, solution and times have
% the following structure:
solution.states % state trajectory
solution.integrator % integrator variables trajectory
solution.controls % control trajectory
solution.parameters % parameters
timepoints.states % time points of states
timepoints.controls % time points of controls
% plotting of control and state p trajectory:
oclPlot(timepoints.controls, solution.controls.u)
oclPlot(timepoints.states, solution.states.p)
end
function varsfun(svh)
svh.addState('x', 'lb', -0.25, 'ub', inf);
svh.addState('y');
svh.addControl('F', 'lb', -1, 'ub', 1);
end
function daefun(daeh,x,~,u,~)
daeh.setODE('x', (1-x.y^2)*x.x - x.y + u.F);
daeh.setODE('y', x.x);
end
function pathcosts(ch,x,~,u,~)
ch.add( x.x^2 );
ch.add( x.y^2 );
ch.add( u.F^2 );
end
```

- T (numeric or [])
- The end time/horizon length of the optimal control problem. If your system equations are expressed as function of an independent variable other than time,
`T`

represents not the end time but the endpoint of the integration over the independent variable. If you would like to optimize for time,**time optimal control**, pass the empty list`[]`

- vars = @(vars_handler)[] (@(vars_handler))
- System variables function. Optional, defaults to an empty function handle.
- dae = @(dae_handler,x,z,u,p)[] (@(dae_handler,x,z,u,p))
- DAE (system equations) function. Optional, defaults to an empty function handle.
- pathcosts = @(cost_handler,x,z,u,p) 0 (@(cost_handler,x,z,u,p))
- Path-costs function. Optional, defaults to a function handle returning 0.
- gridcosts = @(cost_handler,k,K,x) 0 (@(cost_handler,k,K,x))
- Grid-costs function. Optional, defaults to a function handle returning 0.
- gridconstraints = @(constraints_handler,k,K,x) [] (@(constraints_handler,k,K,x))
- Grid-constraints function. Optional, defaults to an empty function handle.

- (ocl.Solver)
- A solver object.

- getInitialGuess()
- Use this method to retrieve a first initial guess that is generated from the bounds. You can further modify this initial guess to improve the solver performance.

- (OclVariable)
- Structured variable for setting the initial guess

- solve(initialGuess)
- Calls the solver and starts doing iterations.

- initialGuess (OclVariable)
- Provide a good initial guess

- (OclVariable)
- The solution of the OCP
- (OclVariable)
- Grid points of the solution

- setBounds(id, lb, ub)
- Sets a bound on a variable for the whole trajectory. If only the lower bound is given, it will be
`lb==ub`

. A bound can be either scalar or a vector with`length(lb)==length(ub)==N+1`

for states and`length(lb)==length(ub)==N`

for control variables.

- id (char)
- The variable id
- lb (numeric)
- The lower bound
- ub (numeric,optional)
- The upper bound

- setInitialBounds(id, lb, ub)
- Sets an initial bound on a variable. If only the lower bound is given, it will be
`lb==ub`

. A bound can be either scalar or a vector with`length(lb)==length(ub)==N+1`

for states and`length(lb)==length(ub)==N`

for control variables.

- id (char)
- The variable id
- lb (numeric)
- The lower bound
- ub (numeric,optional)
- The upper bound

- setEndBounds(id, lb, ub,optional)
- Sets an end bound on a variable. If only the lower bound is given, it will be
`lb==ub`

. A bound can be either scalar or a vector with`length(lb)==length(ub)==N+1`

for states and`length(lb)==length(ub)==N`

for control variables.

- id (char)
- The variable id
- lb (numeric)
- The lower bound
- ub,optional (numeric)
- The upper bound

Creates a solver object for multi-stage problems.

```
```

- stages = {} (cell<ocl.Stage>)
- List (cell-array) of stages. Optional, defaults to empty list.
- transitions = {} (cell<ocl.Transition>)
- List (cell-array) of transitions. Optional, defaults to empty list.

- (ocl.Solver)
- A solver object.

- getInitialGuess()
- Use this method to retrieve a first initial guess that is generated from the bounds. You can further modify this initial guess to improve the solver performance.

- (OclVariable)
- Structured variable for setting the initial guess

- solve(initialGuess)
- Calls the solver and starts doing iterations.

- initialGuess (OclVariable)
- Provide a good initial guess

- (OclVariable)
- The solution of the OCP
- (OclVariable)
- Time points of the solution

The definition of a Stage.

```
stage = ocl.Stage([], @vars, @ode, 'N', 10, 'd', 2);
% Function definitions can be in the same file
% (if the main script is wrapped by a function)
% or in separate files:
function vars(sh)
sh.addState('s');
sh.addState('v');
end
function ode(sh,x,~,~,~)
sh.setODE('s', x.v);
sh.setODE('v', -10);
end
```

- T (numeric or [])
- The end time/horizon length of the optimal control problem. If your system equations are expressed as function of an independent variable other than time,
`T`

represents not the end time but the endpoint of the integration over the independent variable. If you would like to optimize for time,**time optimal control**, pass the empty list`[]`

- vars = @(vars_handler)[] (@(vars_handler))
- System variables function. Optional, defaults to an empty function handle.
- dae = @(dae_handler,x,z,u,p)[] (@(dae_handler,x,z,u,p))
- DAE (system equations) function. Optional, defaults to an empty function handle.
- pathcosts = @(cost_handler,x,z,u,p) 0 (@(cost_handler,x,z,u,p))
- Path-costs function. Optional, defaults to a function handle returning 0.
- gridcosts = @(cost_handler,k,K,x) 0 (@(cost_handler,k,K,x))
- Grid-costs function. Optional, defaults to a function handle returning 0.
- gridconstraints = @(constraints_handler,k,K,x) [] (@(constraints_handler,k,K,x))
- Grid-constraints function. Optional, defaults to an empty function handle.

A dynamical system is defined by implementing functions for the system variables and equations, and creating an OclSystem passing the function pointers. You need to implement two functions, one for defining the system variables, and a second one for defining the system equations. The system is created by passing the handles of the two functions to the constructor of OclSystem. A system can be used width an ocl.Simulator.

```
sys = OclSystem(@sysVars,@sysEq);
% Function definitions can be in the same file
% (if the main script is wrapped by a function)
% or in separate files:
function sysVars(svh)
svh.addState('p');
svh.addState('v');
svh.addControl('u');
end
function sysEq(seh,x,z,u,p)
seh.setODE('p',(1-x.v^2)*x.p-x.v+u.u);
seh.setODE('v',x.p);
end
```

- vars = @(vars_handler)[] (@(vars_handler))
- System variables function. Optional, defaults to an empty function handle.
- dae = @(dae_handler,x,z,u,p)[] (@(dae_handler,x,z,u,p))
- DAE (system equations) function. Optional, defaults to an empty function handle.

The OclVariable type(or CasadiVariable in the CasADi backend) is the basic structure to retrieve, store, modify structured optimization variables. You can access subvariables by their name like the state trajectory or the control variables.

```
% v is a solution of an OCP
% p=[px;py;pz] is of size 3x1
% p trajectory is of size 3x1x(N+1)
% F trajectory is of size 1x1xN
% with N control intervals
p = v.states.p; % get state p trajectory
F = v.controls.F; % get control F trajectory
% set all 3x1 p states to the same value
v.states.p = [3;2;1];
% set p states 4 and 5 in the trajectory
v.states.p(:,:,4:5) = [1,2,3;4,5,6].';
% or (with the same result)
v.states.p(:,:,4:5) = {[1;2;3],[4;5;6]};
% or even
v.states.p(:,:,4:5) = {[1,2,3],[4,5,6]};
% set all px values of p in state trajectory
v.states.p(1,:,:) = 4;
% plotting of state p trajectory:
plot(t.states.value,v.states.p.value)
```

- get(id)
- Alternative syntax: var.id Gets a sub-variable of a variable. You can use the shorthand notation with the dot operator, e.g.: solution.states.x

- id (char)
- Name of the state variable

- (OclVariable)
- the sub-variable of the given variable.

- set(value)
- Alternative syntax: var = value Sets a value to the variable.

- value (numeric)
- The value to be set. The value either has to be of the same dimension as the variable or if possible it will be repeated in some dimensions to fit the variable. Scalar values will be set to all entries of the variable. You can use the shorthand notation, e.g. initialGuess.states.x = [1,2,3]

- slice(dim1, dim2, dim3)
- Alternative syntax: var(dim1,dim2,dim3) Gets a slice of a variable. You can slice a variable the same way as you would index a matrix in Matlab/Octave which means linear indexing is also possible.

- dim1 (int, :, end)
- indizes for the first dimension. The indizes can be scalar, integer arrays, or you can use : or end.
- dim2 (int, :, end, optional)
- indizes for the second dimension. The indizes can be scalar, integer arrays, or you can use : or end.
- dim3 (int, :, end, optional)
- indizes for the third dimension. The indizes can be scalar, integer arrays, or you can use : or end.

- (OclVariable)
- the sliced variable.

- value()
- Get the value of the variable. This is particularly useful if you want to plot the numeric values of the variable, for example for the solution. In system and OCP definition this gives you the underlying symbolic values.

- (numeric or casadi.SX or casadi.MX or sym)
- the underlying value of the variable. The value can be either numeric (for initial guess and solution) or symbolic (in system/ocp definitions).

- disp()
- Display function of OclVariable. It shows the size of the variable, the names of the children variables, and a part of the value. The output of an OCP initial guess variable looks similar to:

```
Variable:
Size: [3681 1]
Type: OclStructure
Children: states, integrator, controls, parameters, time
Value: [100;2;1;0;0;0;0;0;0;0;0;0;0;0;0..]
```

The variables handler allows to specify the system variables, its dimensions and bounds.

- addState(id, s, lb=-inf, ub=inf)
- Adds a state variable to the system.

- id (char)
- Name of the state variable
- s (int, optional)
- Size of the state variable. Scalar, vector, and matrix valued variables are allowed. If a scalar value s is given, the size of the variable will be [s,1]. Defaults to [1,1].
- lb=-inf (numeric, optional)
- Lower bound on the variable. This value can be overwritten when you specify bounds for OclSolver with solver.setBound. Defaults to -inf.
- ub=inf (numeric, optional)
- Upper bound on the variable. This value can be overwritten when you specify bounds for OclSolver with solver.setBound. Defaults to inf.

- addAlgVar(id, s, lb=-inf, ub=inf)
- Adds an algebraic variable to the system.

- id (char)
- Name of the algebraic variable
- s (int, optional)
- Size of the algebraic variable. Scalar, vector, and matrix valued variables are allowed. If a scalar value s is given, the size of the variable will be [s,1]. Defaults to [1,1].
- lb=-inf (numeric, optional)
- Lower bound on the variable. This value can be overwritten when you specify bounds for OclSolver with solver.setBound. Defaults to -inf.
- ub=inf (numeric, optional)
- Upper bound on the variable. This value can be overwritten when you specify bounds for OclSolver with solver.setBound. Defaults to inf.

- addControl(id, s, lb=-inf, ub=inf)
- Adds an control input to the system.

- id (char)
- Name of the control variable
- s (int, optional)
- Size of the control variable. Scalar, vector, and matrix valued variables are allowed. If a scalar value s is given, the size of the variable will be [s,1]. Defaults to [1,1].
- lb=-inf (numeric, optional)
- Lower bound on the variable. This value can be overwritten when you specify bounds for OclSolver with solver.setBound. Defaults to -inf.
- ub=inf (numeric, optional)
- Upper bound on the variable. This value can be overwritten when you specify bounds for OclSolver with solver.setBound. Defaults to inf.

- addParameter(id, s, default=[])
- Adds a parameter.

- id (char)
- Name of the parameter
- s (int, optional)
- Size of the control variable. Scalar, vector, and matrix valued variables are allowed. If a scalar value s is given, the size of the variable will be [s,1]. Defaults to [1,1].
- default=[] (numeric, optional)
- Default value for the parameter. This value can be overwritten when you specify the parameter for OclSolver with solver.setParameter. Defaults to unbounded.

Function handle signature for point constraints function.

- constraints_handler (ocl.Constraint)
- Constraints handler
- k (int)
- current grid point index
- K (int)
- last grid point index
- X (OclVariable)
- State variable

Function handle signature for point cost function.

- cost_handler (ocl.Cost)
- cost_handler handler
- k (int)
- current grid point index
- K (int)
- last grid point index
- X (OclVariable)
- State variable

Function handle signature for the path cost function.

- cost_handler (ocl.Cost)
- Cost handler
- x (OclVariable)
- State variables
- z (OclVariable)
- Algebraic states
- u (OclVariable)
- Controls
- p (OclVariable)
- Parameters

Function handle signature for DAE function.

- dae_handler (ocl.DaeHandler)
- DAE handler
- x (OclVariable)
- State variables
- z (OclVariable)
- Algebraic states
- u (OclVariable)
- Controls
- p (OclVariable)
- Parameters

Function handle signature for system variables function.

- vars_handler (ocl.VarsHandler)
- Variables handler

Creates an options struct for ocl.Solver. Check the casadi documentation and the ipopt documentation to see which options are available. The `ipopt`

options can be set in ‘casadi_options.ipopt’. The default values are the following:

```
casadi_options = struct;
casadi_options.ipopt = struct;
casadi_options.ipopt.linear_solver = 'mumps';
casadi_options.ipopt.hessian_approximation = 'exact';
```

- (struct)
- the options struct.