OpenOCL.org

View the Project on GitHub

back

API documentation

top

Note that this API docs is for the current development version in branch dev_3-10 and for the future release of OpenOCL v3.10

OclSystem(fhVars, fhEquations)

There are two ways to implement the dynamics of a system. The first way is by implementing functions for defining the system variables and equations, and creating an OclSystem using the function handles/pointers. The second way involves involves implementing the system in an object oriented way as a class that is inherited from OclSystem. The second way is a bit more involved but for complex systems it allows using the capabilities of classes, e.g. defining instance variables.

Using system functions 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 two function handles to the constructor of OclSystem.

By inheriting from OclSystem You need to inherit your class from OclSystem and implement the two methods setupVariables and setupEquations as static methods.

%% Example code for the two ways of implementing
%% system. The two resulting systems sys1 and sys2 are 
%% equivalent.
%%

%% Using system functions
%%
sys1 = 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(sys)
  sys.addState('p');
  sys.addState('v');
  sys.addControl('u');  
end
function sysEq(sys,x,z,u,p)
  sys.setODE('p',(1-x.v^2)*x.p-x.v+u.u); 
  sys.setODE('v',x.p);
end


%% By inheriting from OclSystem
%% 
sys2 = VanDerPolSystem();

% The class definition must be in a separate file.
% Note that the methods are marked as Static!
classdef VanDerPolSystem < OclSystem
  methods (Static)
    function setupVariables(sys)    
      sys.addState('p');
      sys.addState('v');
      sys.addControl('u');      
    end
    function setupEquations(sys,x,z,u,p)     
      sys.setODE('p',(1-x.v^2)*x.p-x.v+u.u); 
      sys.setODE('v',x.p);
    end
  end
end

Arguments:

fhVars (function handle, optional)
Function handle to the function that sets up the variables. The function for the variables must have one input argument, no return values, and thus the following siganture: varFunctionName(sys) where sys is a system handler that allows to add variables and parameters. If no function handle is provided, the system must be implemented by deriving from OclSystem and implementing the abstract methods setupVariables and setupEquations.
fhEquations (function handle, optional)
Function handle to the function that sets up the equations. The function for the variables must have five input argument, no return values, and thus the following signature: eqFunctionName(sys,x,z,u,p) where sys is a system handler that allows to add ODE and DAE equations, x the states, z the algebraic variables, u the control inputs, p the parameters. If no function handle is provided, the system must be implemented by deriving from OclSystem and implementing the abstract methods setupVariables and setupEquations.

Abstract Methods

setupVariables(sh)
Implement this method as a static method to define the system variables. You can create state, control and algebraic variables using the class methods.
Arguments:
sh (OclSystem)
System handler, reference to the system object.
setupEquations(sh, x, z, u, p)
Implement this method as a static method to specify the differential and algebraic equations. It is possible to define only ordinary differential equations (ODE system), or differential and algebraic equations (DAE system).
Arguments:
sh (OclSystem)
System handler, reference to the system object.
x (OclVariable)
State variables
z (OclVariable)
Algebraic Variables
u (OclVariable)
Control variables
p (OclVariable)
Parameters

Methods

addState(id, size, lb, ub)
Adds a state variable to the system.
Arguments:
id (char)
Name of the state variable
size (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 (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 (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, size, lb, ub)
Adds an algebraic variable to the system.
Arguments:
id (char)
Name of the algebraic variable
size (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 (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 (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, size, lb, ub)
Adds an control input to the system.
Arguments:
id (char)
Name of the control variable
size (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 (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 (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, size, v)
Adds a parameter.
Arguments:
id (char)
Name of the parameter
size (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].
v (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.
setODE(id, equation)
Adds a differential equation to the system. Note that for every state variable a differential equation must be specified.
Arguments:
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.
Arguments:
equation (OclVariable or Matlab matrix)
Algebraic equation g in the form g(x,z,u,p)=0

OclOCP(fhPathCosts, fhArrivalCosts, fhPathConstraints, fhBoundaryConditions)

As for OclSystem there are two ways to implement an optimal control problem (OCP): The functional and the object oriented approach. If you do not implemented some of the functions or methods they default to zero cost for the cost functions or an empty constraints array for path constraints and boundary conditions.

Using OCP function You can implement functions for path costs, arrival costs, path constraints, boundary conditions. Pass function handles/pointers to these function to the constructor of OclOCP to create an optimal control problem. For information about the signature of these functions look at the definitions of the abstract methods.

By inheriting from OclOCP The OCP is defined by inheriting from the OclOCP class. In order to specify cost functions and boundary conditions you have to implement the corresponding methods.

%% Example code for the two ways of implementing
%% optimal control problems. The two resulting problems
%% ocp1 and ocp2 are equivalent.
%%

%% Using functions
%%
ocp1 = OclOCP(@ocpPathCosts);

function ocpPathCosts(ch,x,z,u,p)
  self.add( x.p^2 );
  self.add( x.v^2 );
  self.add( u.u^2 );
end

%% Using an OCP class
%%
ocp2 = VanDerPolOCP();

%% Note that the methods are marked as Static!
%% Class definitions must be in a separate file.
classdef VanDerPolOCP < OclOCP
  methods (Static)
    function pathCosts(ch,x,z,u,p)
      ch.add( x.p^2 );
      ch.add( x.v^2 );
      ch.add( u.u^2 );
    end
  end
end

Arguments:

fhPathCosts (function handle, optional)
Function handle to the function that defines the path costs. The signature of the corresponding function can be seen in the abstract methods definition.
fhArrivalCosts (function handle, optional)
Function handle to the function that defines the arrival costs. The signature of the corresponding function can be seen in the abstract methods definition.
fhPathConstraints (function handle, optional)
Function handle to the function that defines the path constraints. The signature of the corresponding function can be seen in the abstract methods definition.
fhBoundaryConditions (function handle, optional)
Function handle to the function that defines the boundary conditions. The signature of the corresponding function can be seen in the abstract methods definition.

Abstract Methods

pathCosts(ch, x, z, u, p)
In this method you can implement the path cost (also called Lagrange cost or intermediate cost) function.
Arguments:
ch (OclCostHandler)
Cost handler, allows you to add cost terms to the optimal control problem using the add method.
x (OclVariable)
State variables
z (OclVariable)
Algebraic Variables
u (OclVariable)
Control variables
p (OclVariable)
Parameters
arrivalCosts(ch, x, p)
In this method you can specify the costs on the final state (also called Mayer terms).
Arguments:
ch (OclCostHandler)
Cost handler, allows you to add cost terms to the optimal control problem using the add method.
x (OclVariable)
State variables
p (OclVariable)
Parameters
pathConstraints(ch, x, p)
Specifies the path constraints.
function pathConstraints(ch,x,p)
  ch.add(x.Fx^2+x.Fy^2,'<=',p.Fmax^2);
end
Arguments:
ch (OclConstraint)
Constraints handler, allows you to add constraints to the optimal control problem using the add method.
x (OclVariable)
State variables
p (OclVariable)
Parameters
boundaryConditions(ch, x0, xf, p)
Specifies the boundary conditions on intial state x0 and final state xf.
function boundaryConditions(ch,x0,xF,p)
  ch.add(x0.p(1)^2+x0.p(2)^2-p.l^2,'==',0);
  ch.add(dot(x0.p,x0.v),'==',0);
end
Arguments:
ch (OclConstraint)
Constraints handler, allows you to add constraints to the optimal control problem using the add method.
x0 (OclVariable)
Initial state variables
xf (OclVariable)
Final state variables
p (OclVariable)
Parameters
discreteCosts(vars)
Specifies cost terms that depend on any variable of the discretized problem which is a non-linear program (NLP).
Arguments:
vars (OclVariable)
Contains all variable of the discretized OCP.

Methods

addPathCost(cost)
Adds a path cost term of the form c_p(x,z,u,p).
Arguments:
cost (OclVariable or Matlab matrix)
Scalar variable containing the cost
addArrivalCost(cost)
Adds an end cost term of the form c_f(x,p).
Arguments:
cost (OclVariable or Matlab matrix)
Scalar variable containing the cost
addPathConstraint(lhs, operator, rhs)
Adds a path constraint of the form c_p_lower(x,u,z,p)<=c_p(x,u,z,p)<=c_p_upper(x,u,z,p) to the optimal control problem.
Arguments:
lhs (OclVariable or Matlab matrix)
Left hand side of the constraint equation
operator (char)
One of the following operators as a string: ‘<=’, ‘==’, ‘>=’
rhs (OclVariable or Matlab matrix)
Right hand side of the constraint equation
addBoundaryCondition(lhs, operator, rhs)
Adds a boundary constraint of the form c_b_lower(x0,xf,p)<=c_b(x0,xf,p)<=c_b_upper(x0,xf,p) that can depend on the initial and final states to the optimal control problem.
Arguments:
lhs (OclVariable or Matlab matrix)
Left hand side of the constraint equation
operator (char)
One of the following operators as a string: ‘<=’, ‘==’, ‘>=’
rhs (OclVariable or Matlab matrix)
Right hand side of the constraint equation
addDiscreteCost(cost)
Adds a cost term that can depend on any variable in the discretized optimal control problem.
Arguments:
cost (OclVariable or Matlab matrix)
Scalar variable containing the cost c_d(v_d)

OclSolver(T, system, ocp, options)

Creates a solver object that discretizes the given system and optimal control problem, and calls the underlying optimizer. Before solving set options, parameters, bounds, and the initial guess:

opt = OclOptions();
opt.nlp.controlIntervals = 30;
ocl = OclSolver(10,VanDerPolSystem,VanDerPolOCP,opt);

ocl.setBounds('p', -0.25, inf);
ocl.setInitialBounds('p', 0);

v0 = ocl.getInitialGuess();
v0.states.p = -0.2;

[v,t] = ocl.solve(v0);

% initial guess, solution and times have
% the following structure:
v.states     % state trajectory
v.controls   % control trajectory
v.algVars    % algebraic variable trajectory
v.integrator % integrator variables
t.states     % time points of states
t.controls   % time points of controls

% plotting of control and state p trajectory:
oclPlot(t.controls,v.controls.u)
oclPlot(t.states,v.states.p)

Arguments:

T (numeric)
The end time/horizon length of the optimal control problem. You can alternatively specify a vector of length(T)==N+1 to set the timepoints at which the optimal control problem is discretized. The default discretizatoin is at times linspace(0,1,N+1)*T. If you pass a vector of length(T)==N, the entries of T are the timesteps of the control interval, e.g. T=linspace(0.1,0.1,N). If you specify T=[], the final time of the optimal control problem is free. The endtime is available in the parameters as p.T. The normalized discretization of the control intervals is available in the controls as u.h_normalized. You can set bounds on T and h_normalized as you can do on any other variable. If your system equatiosn are expressed as function of an independent variable other than time, the same holds just that T represents not the end time but the endpoint of the integration over the independent variable.
system (OclSystem)
The system dynamics
ocp (OclOCP)
The optimal control problem
options (struct)
Options struct, can be created with OclOptions()

Returns:

(OclSolver)
A solver object.

Methods

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.
Returns:
(OclVariable)
Structured variable for setting the initial guess
solve(initialGuess)
Calls the solver and starts doing iterations.
Arguments:
initialGuess (OclVariable)
Provide a good initial guess
Returns:
(OclVariable)
The solution of the OCP
(OclVariable)
Time points of the solution
setBounds(id, lb=lb, ub=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.
Arguments:
id (char)
The variable id
lb=lb (numeric)
The lower bound
ub=ub (numeric,optional)
The upper bound
setInitialBounds(id, lb=lb, ub=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.
Arguments:
id (char)
The variable id
lb=lb (numeric)
The lower bound
ub=ub (numeric,optional)
The upper bound
setEndBounds(id, lb=lb, ub=ub)
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.
Arguments:
id (char)
The variable id
lb=lb (numeric)
The lower bound
ub=ub (numeric)
The upper bound
setParameter(id, lb=lb, ub=ub)
Sets a bound on the parameter with the given name. 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.
Arguments:
id (char)
The parameter name
lb=lb (numeric)
The lower bound
ub=ub (numeric)
The upper bound

OclVariable()

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)

Methods

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
Arguments:
id (char)
Name of the state variable
Returns:
(OclVariable)
the sub-variable of the given variable.
set(value)
Alternative syntax: var = value Sets a value to the variable.
Arguments:
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.
Arguments:
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.
Returns:
(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.
Returns:
(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..]

OclOptions()

Creates an options struct for OclSolver. Check the casadi documentation and the ipopt documentation to see which options are available. These options can be set in ‘opt.nlp.ipopt’. The default values are the following:

opt = struct;
opt.solverInterface   = 'casadi';
opt.system_casadi_mx  = false;
opt.controls_regularization = true;
opt.controls_regularization_value = 1e-6;
opt.nlp = struct;
opt.nlp.discretization         = 'collocation';
opt.nlp.controlIntervals       = 20;
opt.nlp.collocationOrder       = 3;
opt.nlp.solver                 = 'ipopt';
opt.nlp.auto_interpolation     = true;
opt.nlp.casadi = struct;
opt.nlp.ipopt = struct;
opt.nlp.ipopt.linear_solver = 'mumps';
opt.nlp.ipopt.hessian_approximation = 'exact';

Returns:

(struct)
the options struct.

Simulator(system, options)

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);

Arguments:

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

Returns:

(Simulator)
the Simulator object.

Methods

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.
Arguments:
N (int)
Number of control intervals
Returns:
(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.
Returns:
(OclVariable)
The states.
getParameters()
Returns a structured state variable that allows you to set parameters for the simulation. All parameter values default to zero.
Returns:
(OclVariable)
The parameters.
simulate(x0, times, p, uVec)
Simulates the system for the given time interval.
Arguments:
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.
Returns:
(OclVariable)
The state trajectory.
(OclVariable)
The trajectory of algebraic variables.
(OclVariable)
The control inputs applied to the system.