FORCES Pro supports designing customized nonlinear solvers via MATLAB® scripts. Regardless of the language used, a Simulink® block is always created such that you can plug your solver directly into other simulation models, or download it to a real-time target platform. Click here for further details on how to deploy the generated solver on an embedded target.

This high-level interface gives optimization users a familiar easy-to-use way to define an optimization problem. The interface also gives the advanced user full flexibility when importing external C-coded functions to evaluate the quantities involved in the optimization problem. For information on other interfaces click here.

The FORCES NLP solver solves (potentially) non-convex, finite-time nonlinear optimal control problems with horizon length N of the form

$$ \begin{align} \text{minimize} \ \ & \sum_{k=1}^{N-1} f_k(z_k, \color{blue}{p_k}) & & \text{(separable objective)}\\

\text{subject to} \ \ & z_1(\mathcal{I}) = \color{blue}{ z_{\text{init}}} && \text{(initial equality)} \\

& E_k z_{k+1} = c_k(z_k, \color{blue}{p_k}) && \text{(inter-stage equality)}\\

& z_N(\mathcal{N}) = \color{blue}{z_{\text{final}}} && \text{(final equality)} \\

& \underline{z}_k \leq z_k \leq \bar{z}_k && \text{(upper-lower bounds)}\\

& \underline{h}_k \leq h_k(z_k, \color{blue}{p_k}) \leq \bar{h}_k && \text{(nonlinear constraints)}\\

\end{align}$$ for \(k=1,…,N\).
where \(z_k\in\mathbb{R}^{n_k}\) are the optimization variables, for example a collection of inputs, states or outputs in an MPC problem; \(p_k\in\mathbb{R}^{l_k}\) are real-time data, which are not necessarily present in all problems; the functions \( f_k: \mathbb{R}^{n_k}\rightarrow \mathbb{R}\) are stage cost functions; the functions \(c_k: \mathbb{R}^{n_k} \rightarrow \mathbb{R}^{w_k}\) represents (potentially nonlinear) equality constraints, such as a state transition function; the matrices \(E_k\) are used to couple variables from the \((k+1)^{th}\) stage to those of stage \(k\) through the function \(c_k\); and the functions \(h_k: \mathbb{R}^{n_k} \rightarrow \mathbb{R}^{m_k}\) are used to express potentially nonlinear, non-convex inequality constraints. The index sets \(\mathcal{I}\) and \(\mathcal{N}\) are used to determine which variables are fixed to initial and final values, respectively. The initial and final values \(z_{\text{init}}\) and \(z_{\text{final}}\) can also be changed in real-time.

All real-time data is coloured in blue.

To obtain a solver for this optimization problem using the FORCES Pro client, you need to define all functions involved ( \(f_k\), \(c_k\), \(h_k\) ) along with the corresponding dimensions. The following steps will take you through this process. See also Simple MPC Example for a minimalistic example.

**Variations**

Not all elements in the description above have to be necessarily present. Possible variants include problems:

- with
**continuous-time dynamics**, using one of FORCES Pro's integrators for discretization. New - where all functions are fixed at code generation time and do not need extra real-time data \(p\);
- with no lower (upper) bounds for variable \(z_{k,i}\), \(\underline{z}_i \equiv -\infty\) (\(\bar{z}_i \equiv +\infty\));
- without nonlinear inequalities \(h\);
- with N = 1 (single stage problem), then the inter-stage equality can be omitted;
- that optimize over the initial value \(z_{\text{init}}\) and do not include the initial equality;
- that optimize over the final value \(z_{\text{final}}\) final and do not include the final equality.

In the following, we describe how to model a problem of the above form with FORCES Pro. First make sure that the FORCES Pro client is on the MATLAB/Python path. Click here for more details.

In order to define the dimensions of the stage variables \(z_i\), the number of equality and inequality constraints and the number of real-time parameters use the following fields:

nlp.nvar = 6; % number of stage variables

nlp.neq = 4; % number of equality constraints

nlp.nh = 2; % number of nonlinear inequality constraints

nlp.npar = 0; % number of runtime parameters

If the dimensions vary for different stages use arrays of length \(N\).

The high-level interface allows you to define the objective function using a handle to a MATLAB function that evaluates the objective. FORCES Pro will process this information and generate the necessary C code to be included in the solver.

For instance, the MATLAB function could be:

F = z(1);

s = z(2);

y = z(4);

f = -100*y + 0.1*F^2 + 0.01* s^2;

end

If the cost function varies for different stages use a cell array of function handles of length \(N\).

Similarly, one can define a handle to a MATLAB function evaluating \(c\) as shown below. The selection matrix \( E \) that determines which variables are affected by the inter-stage equality must also be filled. For performance reasons, it is recommended to order variables such that the selection matrix has the following structure:

nlp.E = [zeros(4,2), eye(2)]; % selection matrix

If the equality constraint function varies for different stages use a cell array of function handles of length \(N-1\), and similarly for \(E_k\).

nlp.xfinalidx = 5:6; % indices affected by final condition

The MATLAB function evaluating the nonlinear inequalities can be provided in a similar way. The simple bounds and the nonlinear inequality bounds can have `inf` and `-inf` elements, but must be the same length as the field `nvar` and `nh`, respectively.

nlp.hu = [9, +inf]; % upper bound for nonlinear constraints

nlp.hl = [1, 0.95^2]; % lower bound for nonlinear constraints

nlp.ub = [+5, +1, 0, 3, 2, +pi]; % simple upper bounds

nlp.lb = [-5, -1, -3, -inf, 0, 0]; % simple lower bounds

If the constraints vary for different stages, use cell arrays of length \(N\) for any of the quantities defined above.

All the functions in the problem formulation can be changed in real-time by adding a second argument to the MATLAB function describing it. For instance to be able to change the terms in the cost function during runtime one can define the objective function in MATLAB as:

F = z(1);

s = z(2);

y = z(4);

f = -100*y + p(1)*F^2 + p(2)* s^2;

end

Please check the obstacle avoidance example in the 'examples' folder that comes with your client for an illustration of how to use real-time parameters in the high-level interface.

This approach allows the user to integrate existing efficient C implementations to evaluate the required functions and their derivatives with respect to the stage variable. This gives the user full flexibility in defining the optimization problem. In this case, the functions do not necessarily have to be differentiable, although the convergence of the algorithm is not guaranteed if they are not. When following this route the user does not have to provide MATLAB code to evaluate the objective or constraint functions. However, the user is responsible for making sure that the provided derivatives and function evaluations are coherent. The FORCES NLP code generator will not check this.

The FORCES NLP solver will automatically call the following function, which is implemented by the user, to obtain the necessary information:

double *x, /* primal vars */

double *y, /* eq. constraint multiplers */

double *l, /* ineq . constraint multipliers */

double *p, /* runtime parameters */

double *f, /* objective function ( incremented in this function ) */

double *nabla_f , /* gradient of objective function */

double *c, /* dynamics */

double *nabla_c , /* Jacobian of the dynamics ( column major ) */

double *h, /* inequality constraints */

double *nabla_h , /* Jacobian of inequality constraints ( column major ) */

double *H, /* Hessian ( column major ) */

int stage /* stage number (0 indexed ) */

)

The name of the function can be changed but it should have the same name as the C file containing it, i.e. in this case this function should be included in `myfunctions.c`.

To let the code generator know about the path to the top-level C file implementing the necessary function evaluations use

The contents of the function have to follow certain rules. We will use the following example to illustrate them:

`
/* cost */
if (f)
{ /* notice the increment of f */
(*f) += -100*x[3] + 0.1* x[0]*x[0] + 0.01*x [1]*x [1];
}
/* gradient - only nonzero elements have to be filled in */
if ( nabla_f )
{
nabla_f [0] = 0.2*x[0];
nabla_f [1] = 0.02*x[1];
nabla_f [3] = -100;
}
`

if (c)

{

vehicle_dyanmics (x, c);

}

/* jacobian equalities ( column major ) */

if ( nabla_c )

{

vehicle_dyanmics_jacobian (x, nabla_c );

}

if (h)

{

h[0] = x [2]*x[2] + x[3]*x [3];

h[1] = (x[2]+2)*(x[2]+2) + (x[3] -2.5)*(x[3] -2.5);

}

/* jacobian inequalities ( column major )

- only non - zero elements to be filled in */

if ( nabla_h )

{

/* column 3 */

nabla_h [4] = 2*x [2];

nabla_h [5] = 2*x[2] + 4;

/* column 4 */

nabla_h [6] = 2*x [3];

nabla_h [7] = 2*x[3] - 5;

}

Notice that every function evaluation is only carried out if the corresponding pointer is not null. This is used by the FORCES NLP solver to call the same interface with different pointers depending on the functions that it requires.

**Matrix format**

Matrices are assumed to be stored in dense column major format. However, only the non-zero components need to be populated, as FORCES NLP makes sure that the arrays are initialized to zero before calling this interface.

**Multiple source files**

The use of multiple C files is also supported. In the example above, the functions `dynamics` and `dynamics_jacobian` are defined in another file and included as external functions using:

extern void dynamics_jacobian ( double *x, double *J);

To let the code generator know about the location of these other files use a string with spaces separating the different files.

**Stage-dependent functions**

Whenever the cost function in one of the stages is different from the standard cost function \(f\), one can make use of the argument `stage` to evaluate different functions
depending on the stage number. The same applies to all other quantities.