# A QP Solver Implementation for Embedded Systems Applied to Control Allocation

^{*}

## Abstract

**:**

## 1. Introduction

## 2. Description of the EmbQP Algorithm

## 3. EmbQP Implementation Details

**,**only the columns $k$ to $q$ differ from ${\mathit{Z}}_{I}$. The matrix ${\mathit{Z}}_{q-k+1}^{\left(1\right)}$ is multiplied with the same Givens rotations as ${\mathit{R}}_{I}^{\left(22\right)}$. This can again be carried out in parallel and without the need to explicitly determine the matrix ${\mathit{Q}}_{I}^{\left(2\right)}$. With the described approach, the updating of the matrices ${\mathit{Z}}_{I}$ and ${\mathit{R}}_{I}$ can be done efficiently, both when an element is added to the active set $I$ and when an element is removed from it. All required algorithms for these computations, such as the Cholesky decomposition, Givens rotations, or backwards substitution, were implemented in C. The C function for computing plane Givens rotations used within the EmbQP solver is shown in Table A5. As a consequence, the EmbQP algorithm is self-contained, and no external library is needed.

## 4. Application of the EmbQP Solver in a Vehicular Control Allocation Problem

#### 4.1. Control Allocation Problem

#### 4.2. QP Problems in the Control Allocation

## 5. Results of the Simulation

## 6. Outlook: Configuration of a QP-Based Controller Software on an Embedded Platform

## 7. Conclusions

## Author Contributions

## Funding

## Acknowledgments

## Conflicts of Interest

## Appendix A. Code Segments of the EmbQP C Code

int_t* position = &int_workarray[0]; |

int_t* ind_ineq = &int_workarray[m+n+n]; |

int_t* ind_viol_constr = &int_workarray[2 × (m+n+n)]; |

int_t* pos_r_ind = &int_workarray[3 × (m+n+n)]; |

int_t* pivot = &int_workarray[4 × (m+n+n)]; |

**Table A2.**Code segment to set $\mathit{x}$ to a value within the bounds if the problem is infeasible.

if (t_sigmainf == TRUE) {//problem not feasible |

if (bounds_x_l) { |

for (i = 0; i < n; i++) { |

if (x[i] < x_l[i]) { |

x[i] = x_l[i]; |

} |

} |

} |

if (bounds_x_u) { |

for (i = 0; i < n; i++) { |

if (x[i] > x_u[i]) { |

x[i] = x_u[i]; |

} |

} |

} |

*exit = 2; |

} |

int main() { |

//problem data |

int_t m = 3; |

int_t m_e = 3; |

int_t n = 5; |

real_t C[25] = {2.0, −2.0, 0.0, 0.0, 0.0, −2.0, 4.0, 2.0, 0.0, 0.0, 0.0, 2.0, 2.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2.0}; |

real_t d[5] = {0.0, −4.0, −4.0, −2.0, −2.0}; |

real_t A[15] = {1.0, 0.0, 0.0, 3.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, −2.0, −1.0}; |

real_t b[3] = {0.0, 0.0, 0.0}; |

real_t x_l[5] = {−10.0, −10.0, −10.0, −10.0, −10.0}; |

real_t x_u[5] = {10.0, 10.0, 10.0, 10.0, 10.0}; |

real_t EPS = 1.0 × 10^{−12}; |

int_t mode = 1; //a Cholesky decomposition of C needs to be computed internally |

boolean_t bounds_x_l = TRUE; |

boolean_t bounds_x_u = TRUE; |

real_t x[5] = {0.0}; |

real_t f_min = 0.0; |

int_t exit = 0; |

real_t real_workarray[588] = {0.0}; |

int_t int_workarray[57] = {0}; |

EmbQP(m, m_e, n, C, d, A, b, x_l, x_u, EPS, mode, bounds_x_l, bounds_x_u, x, &f_min, &exit, real_workarray, int_workarray); |

return 0; |

} |

//choose the most violated constraint |

test_any = FALSE; |

numb_viol_constr = 0; //number of violated constraints |

for (i = 0; i < m; i++) { |

ind_viol_constr[i] = 0; |

residuum[i] = 0.0; |

} |

for (j = 1; j <= m_e; j++) { // all equality constraints |

sum = 0.0; |

for (i = 0; i < n; i++) { |

sum += A[(j + m × i) − 1] × x[i]; |

} |

if (fabs(sum − b[j − 1]) > EPS) { |

i = 1; |

while (i <= m) { |

if (I_data[i − 1] == j) { |

test_any = TRUE; |

i = m + 1; |

} else { |

test_any = FALSE; |

i++; |

} |

} |

if (test_any == FALSE) {// p must not be an element of I |

numb_viol_constr = numb_viol_constr + 1; |

ind_viol_constr[numb_viol_constr-1] = j; |

residuum[numb_viol_constr-1] = fabs(sum − b[j − 1]); |

} |

} |

} |

for (j = (m_e+1); j <= m; j++) {// all inequality constraints |

sum = 0.0; |

for (i = 0; i < n; i++) { |

sum += A[(j + m × i) − 1] × x[i]; |

} |

if (sum − b[j − 1] < -EPS) { |

i = 1; |

while (i <= m) { |

if (I_data[i − 1] == j) { |

test_any = TRUE; |

i = m + 1; |

} else { |

test_any = FALSE; |

i++; |

} |

} |

if (test_any == FALSE) {// p must not be an element of I |

numb_viol_constr = numb_viol_constr + 1; |

ind_viol_constr[numb_viol_constr-1] = j; |

residuum[numb_viol_constr-1] = fabs(sum − b[j − 1]); |

} |

} |

} |

if (numb_viol_constr == 1) { |

p = ind_viol_constr[0] −1; |

} else if (numb_viol_constr > 1) { |

sum = residuum[0]; |

p = ind_viol_constr[0] −1; |

for (i = 1; i < numb_viol_constr; i++) { |

if (residuum[i] > sum) { |

p = ind_viol_constr[i] −1;//p is the index of the violated constraint with the largest absolute value //of the residual |

sum = residuum[i]; |

} |

} |

} |

void givens_rot(real_t x[2], real_t G[4], real_t y[2]) |

{ |

//an orthogonal matrix G is computed so that: y = G*x with y[1] = 0.0 |

real_t r = 0.0; |

if (fabs(x[1]) > EPS) { |

r = sqrt(fabs(x[0]) × fabs(x[0]) + fabs(x[1]) × fabs(x[1])); |

G[0] = x[0]/r; |

G[1] = −x[1]/r; |

G[2] = x[1]/r; |

G[3] = x[0]/r; |

y[0] = r; |

y[1] = 0.0; |

} else {//G is the identity matrix |

G[0] = 1.0; |

G[1] = 0.0; |

G[2] = 0.0; |

G[3] = 1.0; |

y[0] = x[0]; |

y[1] = x[1]; |

} |

} |

## References

- Banjac, G.; Stellato, B.; Moehle, N.; Goulart, P.; Bemporad, A.; Boyd, S. Embedded code generation using the OSQP solver. In Proceedings of the 56th Annual Conference on Decision and Control (CDC), Melbourne, Australia, 12–15 December 2017; pp. 1906–1911. [Google Scholar]
- Defraene, B.; Van Waterschoot, T.; Ferreau, H.J.; Diehl, M.; Moonen, M. Real-Time Perception-Based Clipping of Audio Signals Using Convex Optimization. IEEE Trans. Audio Speech Lang. Process.
**2012**, 20, 2657–2671. [Google Scholar] [CrossRef] - Amos, B.; Kolter, J.Z. OptNet: Differentiable Optimization as a Layer in Neural Networks. In Proceedings of the 34th International Conference on Machine Learning, Sydney, Australia, 6–11 August 2017. [Google Scholar]
- Mattingley, J.; Boyd, S. CVXGEN: A code generator for embedded convex optimization. Optim. Eng.
**2011**, 13, 1–27. [Google Scholar] [CrossRef] - Goldfarb, D.; Idnani, A. A numerically stable dual method for solving strictly convex quadratic programs. Math. Program.
**1983**, 27, 1–33. [Google Scholar] [CrossRef] - Di Gaspero, L. QuadProg++, University of Udine, Italy. 2020. Available online: https://github.com/liuq/QuadProgpp (accessed on 25 September 2020).
- Sherikov. qpmad. 2020. Available online: https://github.com/asherikov/qpmad. (accessed on 25 September 2020).
- Barraud. QP a General Convex qpp Solver. 2020. Available online: https://www.mathworks.com/matlabcentral/fileexchange/67864-qp-a-general-convex-qpp-solver. (accessed on 25 September 2020).
- Schittkowski, K. QL: A Fortran Code for Convex Quadratic Programming—User’s Guide. 2011. Available online: http://www.easy-fit.de/QL.pdf. (accessed on 20 August 2020).
- Feldman, S.I. A Fortran to C converter. ACM SIGPLAN Fortran Forum
**1990**, 9, 21–22. [Google Scholar] [CrossRef] - Brembeck, J. Model Based Energy Management and State Estimation for the Robotic Electric Vehicle RoboMObil. Ph.D. Thesis, Technische Universität München, Munchen, Germany, 2018. [Google Scholar]
- Brembeck, J.; Ho, L.M.; Schaub, A.; Satzger, C.; Tobolar, J.; Hirzinger, J.B.u.G. ROMO—The Robotic Electric Vehicle. In Proceedings of the 22nd IAVSD International Symposium on Dynamics of Vehicle on Roads and Tracks, Manchester, UK, 14–19 August 2011. [Google Scholar]
- Powell, M. ZQPCVX, A Fortran Subroutine for Convex Quadratic Programming; University of Cambridge: Camridge, UK, 1983. [Google Scholar]
- Werner, J. Vorlesung über Optimierung. Universität Hamburg. 2007/2008. Available online: https://num.math.uni-goettingen.de/werner/optim.pdf. (accessed on 20 August 2020).
- Liedel, M. Sichere Mehrparteienberechnungen und datenschutzfreundliche Klassifikation auf Basis horizontal partitionierter Datenbanken. Ph.D Thesis, Universität Regensburg, Regensburg, Germany, 2012. [Google Scholar]
- Motor Industry Software Reliability Association. MISRA-C: 2012. 2012. Available online: https://www.misra.org.uk/ (accessed on 26 May 2020).
- Brembeck, J.; Ritzer, P. Energy optimal control of an over actuated Robotic Electric Vehicle using enhanced control allocation approaches. In Proceedings of the IEEE Intelligent Vehicles Symposium, Alacala de Henares, Spain, 3–7 June 2012; pp. 322–327. [Google Scholar]
- Ritzer, P.; Winter, C.; Brembeck, J.; Peter, R. Advanced path following control of an overactuated robotic vehicle. In Proceedings of the IEEE Intelligent Vehicles Symposium (IV), Seoul, Korea, 28 June–1 July 2015; pp. 1120–1125. [Google Scholar] [CrossRef] [Green Version]
- Johansen, T.A.; Fossen, T.I. Control allocation—A survey. Automatica
**2013**, 49, 1087–1103. [Google Scholar] [CrossRef] [Green Version] - Brembeck, J. Nonlinear Constrained Moving Horizon Estimation Applied to Vehicle Position Estimation. Sensors
**2019**, 19, 2276. [Google Scholar] [CrossRef] [PubMed] [Green Version] - Modelica Association. Modelica. 2020. Available online: http://www.modelica.org (accessed on 28 May 2020).
- Brembeck, J. A Physical Model-Based Observer Framework for Nonlinear Constrained State Estimation Applied to Battery State Estimation. Sensors
**2019**, 19, 4402. [Google Scholar] [CrossRef] [PubMed] [Green Version] - Neudorfer, J.; Armugham, S.S.; Peter, M.; Mandipalli, N.; Ramachandran, K.; Bertsch, C.; Corral, I. FMI for Physics-Based Models on AUTOSAR Platforms. SAE Tech. Pap. Ser.
**2017**. [Google Scholar] [CrossRef]

**Figure 2.**Solution of EmbQP and QL for QP (23) and QP (24) for the fifth component of the solution vector $\mathsf{\Delta}{\mathit{u}}^{\mathbf{W}}$, that is the torque for the front left wheel; (

**a**) covers the whole simulation and (

**b**) shows a closer look at the first few time steps. Additionally depicted: lower and upper bounds $\mathsf{\Delta}{\underset{\_}{\mathit{u}}}^{\mathbf{W}}$ and $\mathsf{\Delta}{\overline{\mathit{u}}}^{\mathbf{W}}$ for the solution.

**Figure 3.**Solution of EmbQP for quadratic programming problem (QP) (23) and QP (24) for the first (

**a**) and the fifth (

**b**) component of the solution vector $\mathsf{\Delta}{\mathit{u}}^{\mathbf{W}}$, that is the steering angle (

**a**) and torque (

**b**) for the front left wheel. Additionally depicted: the corresponding solution of QL as well as lower and upper bounds $\mathsf{\Delta}{\underset{\_}{\mathit{u}}}^{\mathbf{W}}$ and $\mathsf{\Delta}{\overline{\mathit{u}}}^{\mathbf{W}}$ for the solution and the absolute difference between the two solvers.

**Figure 4.**Objective function values for QP (22) (

**a**) and for QPs (23) and (24) (

**b**) of EmbQP and QL and their respective absolute difference.

● Compute the first solution pair $\left({\mathit{x}}^{0},{I}^{0}\right):=\left(-{\mathit{C}}^{-1}\mathit{d},\varnothing \right)$ |

● $\mathrm{For}k=0,1,\dots $ repeat: |

○ If all constraints are satisfied: ${\mathit{x}}^{k}$ is the optimal solution, STOP |

○ Else: |

■ Choose any of the remaining violated constraints $p\in \left\{1,\dots ,m\right\}\backslash {I}^{k}$ |

■ $\mathrm{If}P\left({I}^{k}{\cup}^{}\left\{p\right\}\right)$ is infeasible: the problem is infeasible, STOP |

■ Else: Compute new solution pair $\left({\mathit{x}}^{k+1},{I}^{k+1}\right)$ where ${I}^{k+1}={\overline{I}}^{k}{\cup}^{}\left\{p\right\}$, ${\overline{I}}^{k}\subset {I}^{k}$ and $f\left({\mathit{x}}^{k+1}\right)f\left({\mathit{x}}^{k}\right)$ |

Inputs: $\mathit{C}$, $\mathit{d}$, $\mathit{A}$, $\mathit{b}$, ${\mathit{x}}_{\mathrm{l}}$, ${\mathit{x}}_{\mathrm{u}}$, $n$, $m$, ${m}_{\mathrm{e}}$ |

1. Compute the minimum of the unconstrained problem: $\mathit{x}=-{\mathit{C}}^{-1}\mathit{d}$, ${f}_{\mathrm{min}}=\frac{1}{2}{\mathit{d}}^{T}\mathit{x}$ |

2. If all constraints are fulfilled: $\mathit{x}$ is the solution, STOP |

Else: Choose a violated constraint $p\in \left\{1,\dots ,m\right\}\backslash I$ |

3. Determine the step directions in the primal and dual space: |

Compute the matrices ${\mathit{N}}_{I}={\left({\mathit{A}}_{I}{\mathit{C}}^{-1}{\mathit{A}}_{I}^{T}\right)}^{-1}{\mathit{A}}_{I}{\mathit{C}}^{-1}$ and ${\mathit{H}}_{I}={\mathit{C}}^{-1}\left(\mathbf{I}-{\mathit{A}}_{I}^{T}{\mathit{N}}_{I}\right)$, and from these, determine the vectors $\mathit{z}={\mathit{H}}_{I}{\mathit{a}}_{p}$ and $\mathit{r}={\mathit{N}}_{I}{\mathit{a}}_{p}$ |

4. Calculate the step length $t$ using ${t}_{1}$ and ${t}_{2}$: |

full step length ${t}_{1}$: minimal step length in the primal space such that the constraint $p$ becomes feasible |

partial step length ${t}_{2}$: maximal step length in the dual space such that the dual feasibility is not violated |

5. If no step in the primal or dual space is possible: problem is infeasible, STOP |

6. If step in the dual space: a constraint is removed from the active set $I$, go to 3. |

7. If step in the primal and dual space: Compute ${\mathit{x}}_{\mathrm{new}}=\mathit{x}+t\mathit{z}$ and ${f}_{\mathrm{min},\mathrm{new}}$ and ${I}_{\mathrm{new}}$ |

If a constraint is added to $I$: go to 2. |

If a constraint is removed from $I$: go to 3. |

Outputs: $\mathit{x}$, ${f}_{\mathrm{min}}$ |

Inputs: |

$n$: dimension of the solution vector |

$m$: number of constraints |

${m}_{\mathrm{e}}$: number of equality constraints |

$\mathit{C}\in {\mathbb{R}}^{n\times n}$: matrix in the objective function |

$\mathit{d}\in {\mathbb{R}}^{n}$: vector in the objective function |

$\mathit{A}\in {\mathbb{R}}^{m\times n}$: matrix of the constraints; the first ${m}_{\mathrm{e}}$ rows refer to equality constraints |

$\mathit{b}\in {\mathbb{R}}^{m}$: vector of the constraints |

${\mathit{x}}_{\mathrm{l}}\in {\mathbb{R}}^{n}$$:\mathrm{lower}\mathrm{bounds}\mathrm{for}\mathit{x}$ |

${\mathit{x}}_{\mathrm{u}}\in {\mathbb{R}}^{n}$$:\mathrm{upper}\mathrm{bounds}\mathrm{for}\mathit{x}$ |

$bounds\_\mathit{x}\_l$$\left(\mathrm{boolean}\right):\mathrm{indicates}\mathrm{whether}\mathrm{bounds}{\mathit{x}}_{\mathrm{l}}$ are present |

$bounds\_\mathit{x}\_u$$\left(\mathrm{boolean}\right):\mathrm{indicates}\mathrm{whether}\mathrm{bounds}{\mathit{x}}_{\mathrm{u}}$ are present |

$eps$: desired accuracy |

$mode$: determines whether an initial Cholesky decomposition of $\mathit{C}$ is available |

$real\_workarray$: working memory for temporary float type data (= preallocated memory for internal calculations) |

$int\_workarray$: working memory for temporary integer type data (= preallocated memory for internal calculations) |

Outputs: |

$\mathit{x}\in {\mathbb{R}}^{n}$: solution vector |

${f}_{\mathrm{min}}$: optimal value of the objective function |

$exit$: reports whether the optimization was successful |

internally used variables are set to pointers in the working memory |

if present, the constraints defined by ${\mathit{x}}_{\mathrm{l}}$ and ${\mathit{x}}_{\mathrm{u}}$ are attached to $\mathit{A}$ and $\mathit{b}$ |

compute the Cholesky decomposition $\mathit{C}=\mathit{L}{\mathit{L}}^{T}$, if not provided, and the inverse $\mathit{U}={\mathit{L}}^{-1}$ |

compute $\mathit{x}=-{\mathit{C}}^{-1}\mathit{d}$ and ${f}_{\mathrm{min}}=\frac{1}{2}{\mathit{d}}^{T}\mathit{x}$ |

set $exit1=false$, $add=false$, $remove=false$, $k=0$, $exit=0$, $q=0$ |

while ($exit1==false$) and ($k\le iter\_max$): |

choose a violated constraint $p$ |

if there is no violated constraint: $exit=1,exit1=true$ |

compute $\sigma =\mathrm{sgn}\left({b}_{p}-{\mathit{a}}_{p}^{\mathrm{T}}\mathit{x}\right)$, $\theta =0$ |

set $exit2=false$ |

while ($exit==0$) and ($exit2==false$) |

if $q==0$: compute $\mathit{z}={\mathit{C}}^{-1}{\mathit{a}}_{p}$ |

else if $add==true$: compute ${\mathit{N}}_{I}={\left({\mathit{A}}_{I}{\mathit{C}}^{-1}{\mathit{A}}_{I}^{T}\right)}^{-1}{\mathit{A}}_{I}{\mathit{C}}^{-1}$, ${\mathit{H}}_{I}={\mathit{C}}^{-1}\left(\mathit{I}-{\mathit{A}}_{I}^{T}{\mathit{N}}_{I}\right)$, |

$\mathit{z}={\mathit{H}}_{I}{\mathit{a}}_{p}$, $\mathit{r}={\mathit{N}}_{I}{\mathit{a}}_{p}$, $add=false$ |

else if $remove==true$: compute ${\mathit{N}}_{I}={\left({\mathit{A}}_{I}{\mathit{C}}^{-1}{\mathit{A}}_{I}^{T}\right)}^{-1}{\mathit{A}}_{I}{\mathit{C}}^{-1}$, |

${\mathit{H}}_{I}={\mathit{C}}^{-1}\left(I-{\mathit{A}}_{I}^{T}{\mathit{N}}_{I}\right)$, $\mathit{z}={\mathit{H}}_{I}{\mathit{a}}_{p}$, $\mathit{r}={\mathit{N}}_{I}{\mathit{a}}_{p}$, $remove=false$ |

end if |

if $\mathit{z}\ne 0$: compute ${t}_{1}=\frac{{b}_{p}-{\mathit{a}}_{p}^{T}\mathit{x}}{{\mathit{a}}_{p}^{T}\mathit{z}}$ |

if $q>0$ and $\mathit{\sigma}$ · ${r}^{i}>0$ for $i\in I\cap \left\{{m}_{\mathrm{e}}+1,\dots ,m\right\}$: compute ${t}_{2}$ with |

${t}_{2}=\mathrm{min}\left\{\frac{{y}_{i}}{{r}_{i}}:i\in I\cap \left\{{m}_{\mathrm{e}}+1,\dots ,m\right\},{\mathit{r}}_{i}0\right\}$, if $\sigma ==1$, and |

${t}_{2}=\mathrm{max}\left\{\frac{{y}_{i}}{{r}_{i}}:i\in I\cap \left\{{m}_{\mathrm{e}}+1,\dots ,m\right\},{\mathit{r}}_{i}0\right\}$, if $\sigma ==-1$ |

if $\mathit{z}=0$ and ($q==0$ or $\sigma \cdot {r}_{i}\le 0$ for $i\in I\cap \left\{{m}_{\mathrm{e}}+1,\dots ,m\right\}$): problem is infeasible, |

$exit=2$ |

compute $t$ with $t=\mathrm{min}\left({t}_{1},{t}_{2}\right)$, if $\sigma ==1$, and $t=\mathrm{max}\left({t}_{1},{t}_{2}\right)$, if $\sigma ==-1$ |

if $\mathit{z}=0$: dual step, compute $\theta =\theta +t$, ${I}_{\mathrm{new}}$, ${\mathit{y}}_{\mathrm{new}}$, $q=q-1$, $remove=true$ |

if $\mathit{z}\ne 0$: primal and dual step, compute $\mathit{x}=\mathit{x}+t\mathit{z}$, ${f}_{\mathrm{min}}$, $\theta =\theta +t$ |

if $t={t}_{1}$: compute ${I}_{\mathrm{new}}$, ${\mathit{y}}_{\mathrm{new}}$, $q=q+1$, $add=true$, $exit2=true$ |

else: compute ${I}_{\mathrm{new}}$, ${\mathit{y}}_{\mathrm{new}}$, $q=q-1$, $remove=true$ |

end while |

if $exit==2$: make sure that $\mathit{x}$ is within the limits ${\mathit{x}}_{\mathrm{l}}$ and ${\mathit{x}}_{\mathrm{u}}$, $exit1=true$ |

set $k=k+1$ |

end while |

if $kiter\_max$: make sure that $\mathit{x}$ is within the limits ${\mathit{x}}_{\mathrm{l}}$ and ${\mathit{x}}_{\mathrm{u}}$, $exit=3$ |

lateral and longitudinal controller compute $\mathsf{\Delta}{\mathit{v}}^{\mathbf{C}}$ |

set $\mathit{G}=diag\left(userdefinedtuningvalues\right)$ |

determine weighting matrices ${\mathit{W}}_{\nu}$ and ${\mathit{W}}_{u}$ |

when (sample Trigger) |

calculate the control limits $\mathsf{\Delta}{\underset{\_}{\mathit{u}}}^{\mathbf{W}}$ and $\mathsf{\Delta}{\overline{\mathit{u}}}^{\mathbf{W}}$ in one time step using physical parameters |

compute the control-efficiency matrix $\mathit{B}$ |

compute $\mathit{H}$ and $\mathit{f}$ |

compute $\mathsf{\Delta}{\mathit{u}}_{\mathrm{d}}^{\mathbf{W}}$, $\mathit{E}$, $\mathit{e}$ for the energy-optimal objective function |

$\mathsf{\Delta}{\mathit{u}}^{\mathbf{W}}$ = EmbQP(8, 0, 0, $\mathit{H}$, $\mathit{f}$, $\mathsf{\Delta}{\underset{\_}{\mathit{u}}}^{\mathbf{W}}$, $\mathsf{\Delta}{\overline{\mathit{u}}}^{\mathbf{W}}$) |

check whether a nullspace for optimization is available ${v}_{\mathrm{diff}}=abs\left(\mathit{B}\cdot \mathsf{\Delta}{\mathit{u}}^{\mathbf{W}}-\mathsf{\Delta}{\mathit{v}}^{\mathbf{C}}\right)$ |

if ${\mathit{v}}_{\mathrm{diff}}<0.001$ |

$\mathsf{\Delta}{\mathit{u}}^{\mathbf{W}}$ = EmbQP(8, 3, 3, $\mathit{E}$, $\mathit{e}$,$\mathit{B}$, $-\mathsf{\Delta}{\mathit{v}}^{\mathbf{C}}$, $\mathsf{\Delta}{\underset{\_}{\mathit{u}}}^{\mathbf{W}}$, $\mathsf{\Delta}{\overline{\mathit{u}}}^{\mathbf{W}}$) |

else |

$\mathsf{\Delta}{\mathit{u}}^{\mathbf{W}}$ = EmbQP(8, 0, 0, $\left(2\cdot {\mathit{B}}^{T}\mathit{B}+\mathit{G}\right)$, $\left(-2\cdot {\mathit{B}}^{T}\mathsf{\Delta}{\mathit{v}}^{\mathbf{C}}\right)$, $\mathsf{\Delta}{\underset{\_}{\mathit{u}}}^{\mathbf{W}}$, $\mathsf{\Delta}{\overline{\mathit{u}}}^{\mathbf{W}}$) |

end if |

check the limits: $\Delta {\mathit{u}}^{\mathit{W}}=\mathrm{min}\left(\mathrm{max}\left(\Delta {\mathit{u}}^{\mathit{W}},\Delta {\underset{\_}{\mathit{u}}}^{\mathit{W}}\right),\Delta {\overline{\mathit{u}}}^{\mathit{W}}\right)$ |

end when |

© 2020 by the authors. Licensee MDPI, Basel, Switzerland. This article is an open access article distributed under the terms and conditions of the Creative Commons Attribution (CC BY) license (http://creativecommons.org/licenses/by/4.0/).

## Share and Cite

**MDPI and ACS Style**

Schreppel, C.; Brembeck, J.
A QP Solver Implementation for Embedded Systems Applied to Control Allocation. *Computation* **2020**, *8*, 88.
https://doi.org/10.3390/computation8040088

**AMA Style**

Schreppel C, Brembeck J.
A QP Solver Implementation for Embedded Systems Applied to Control Allocation. *Computation*. 2020; 8(4):88.
https://doi.org/10.3390/computation8040088

**Chicago/Turabian Style**

Schreppel, Christina, and Jonathan Brembeck.
2020. "A QP Solver Implementation for Embedded Systems Applied to Control Allocation" *Computation* 8, no. 4: 88.
https://doi.org/10.3390/computation8040088