qpOASES-3.2.0/interfaces/simulink/qpOASES_SQProblem.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of qpOASES.
3  *
4  * qpOASES -- An Implementation of the Online Active Set Strategy.
5  * Copyright (C) 2007-2015 by Hans Joachim Ferreau, Andreas Potschka,
6  * Christian Kirches et al. All rights reserved.
7  *
8  * qpOASES is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * qpOASES is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16  * See the GNU Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with qpOASES; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  *
22  */
23 
24 
37 #include <stdlib.h>
38 
39 #include <qpOASES.hpp>
41 
42 
43 #ifdef __cplusplus
44 extern "C" {
45 #endif
46 
47 
48 #define S_FUNCTION_NAME qpOASES_SQProblem
49 #define S_FUNCTION_LEVEL 2
51 #define MDL_START
53 #include "simstruc.h"
54 
55 
56 /* SETTINGS */
57 #define SAMPLINGTIME -1
58 #define NCONTROLINPUTS 2
59 #define MAXITER 100
60 #define HESSIANTYPE HST_UNKNOWN
63 static void mdlInitializeSizes (SimStruct *S) /* Init sizes array */
64 {
65  int nU = NCONTROLINPUTS;
66 
67  /* Specify the number of continuous and discrete states */
68  ssSetNumContStates(S, 0);
69  ssSetNumDiscStates(S, 0);
70 
71  /* Specify the number of parameters */
72  ssSetNumSFcnParams(S, 0);
73  if ( ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S) )
74  return;
75 
76  /* Specify the number of intput ports */
77  if ( !ssSetNumInputPorts(S, 7) )
78  {
79  #ifndef __SUPPRESSANYOUTPUT__
80  mexErrMsgTxt( "ERROR (qpOASES): Invalid number of input ports!" );
81  #endif
82  return;
83  }
84 
85  /* Specify the number of output ports */
86  if ( !ssSetNumOutputPorts(S, 4) )
87  {
88  #ifndef __SUPPRESSANYOUTPUT__
89  mexErrMsgTxt( "ERROR (qpOASES): Invalid number of output ports!" );
90  #endif
91  return;
92  }
93 
94  /* Specify dimension information for the input ports */
95  ssSetInputPortVectorDimension(S, 0, DYNAMICALLY_SIZED); /* H */
96  ssSetInputPortVectorDimension(S, 1, DYNAMICALLY_SIZED); /* g */
97  ssSetInputPortVectorDimension(S, 2, DYNAMICALLY_SIZED); /* A */
98  ssSetInputPortVectorDimension(S, 3, DYNAMICALLY_SIZED); /* lb */
99  ssSetInputPortVectorDimension(S, 4, DYNAMICALLY_SIZED); /* ub */
100  ssSetInputPortVectorDimension(S, 5, DYNAMICALLY_SIZED); /* lbA */
101  ssSetInputPortVectorDimension(S, 6, DYNAMICALLY_SIZED); /* ubA */
102 
103  /* Specify dimension information for the output ports */
104  ssSetOutputPortVectorDimension(S, 0, nU ); /* uOpt */
105  ssSetOutputPortVectorDimension(S, 1, 1 ); /* fval */
106  ssSetOutputPortVectorDimension(S, 2, 1 ); /* exitflag */
107  ssSetOutputPortVectorDimension(S, 3, 1 ); /* iter */
108 
109  /* Specify the direct feedthrough status */
110  ssSetInputPortDirectFeedThrough(S, 0, 1);
111  ssSetInputPortDirectFeedThrough(S, 1, 1);
112  ssSetInputPortDirectFeedThrough(S, 2, 1);
113  ssSetInputPortDirectFeedThrough(S, 3, 1);
114  ssSetInputPortDirectFeedThrough(S, 4, 1);
115  ssSetInputPortDirectFeedThrough(S, 5, 1);
116  ssSetInputPortDirectFeedThrough(S, 6, 1);
117 
118  /* One sample time */
119  ssSetNumSampleTimes(S, 1);
120 
121  /* global variables:
122  * 0: problem
123  * 1: H
124  * 2: g
125  * 3: A
126  * 4: lb
127  * 5: ub
128  * 6: lbA
129  * 7: ubA
130  */
131 
132  /* Specify the size of the block's pointer work vector */
133  ssSetNumPWork(S, 8);
134 }
135 
136 
137 #if defined(MATLAB_MEX_FILE)
138 
139 #define MDL_SET_INPUT_PORT_DIMENSION_INFO
140 #define MDL_SET_OUTPUT_PORT_DIMENSION_INFO
141 
142 static void mdlSetInputPortDimensionInfo(SimStruct *S, int_T port, const DimsInfo_T *dimsInfo)
143 {
144  if ( !ssSetInputPortDimensionInfo(S, port, dimsInfo) )
145  return;
146 }
147 
148 static void mdlSetOutputPortDimensionInfo(SimStruct *S, int_T port, const DimsInfo_T *dimsInfo)
149 {
150  if ( !ssSetOutputPortDimensionInfo(S, port, dimsInfo) )
151  return;
152 }
153 
154 #endif
155 
156 
157 static void mdlInitializeSampleTimes(SimStruct *S)
158 {
159  ssSetSampleTime(S, 0, SAMPLINGTIME);
160  ssSetOffsetTime(S, 0, 0.0);
161 }
162 
163 
164 static void mdlStart(SimStruct *S)
165 {
167 
168  int nU = NCONTROLINPUTS;
169  int size_H, size_g, size_A, size_lb, size_ub, size_lbA, size_ubA;
170  int nV, nC;
171 
172  SQProblem* problem;
173 
174 
175  /* get block inputs dimensions */
176  size_H = ssGetInputPortWidth(S, 0);
177  size_g = ssGetInputPortWidth(S, 1);
178  size_A = ssGetInputPortWidth(S, 2);
179  size_lb = ssGetInputPortWidth(S, 3);
180  size_ub = ssGetInputPortWidth(S, 4);
181  size_lbA = ssGetInputPortWidth(S, 5);
182  size_ubA = ssGetInputPortWidth(S, 6);
183 
184 
185  /* dimension checks */
186  nV = size_g;
187  nC = (int) ( ((real_t) size_A) / ((real_t) nV) );
188 
189  if ( MAXITER < 0 )
190  {
191  #ifndef __SUPPRESSANYOUTPUT__
192  mexErrMsgTxt( "ERROR (qpOASES): Maximum number of iterations must not be negative!" );
193  #endif
194  return;
195  }
196 
197  if ( nV <= 0 )
198  {
199  #ifndef __SUPPRESSANYOUTPUT__
200  mexErrMsgTxt( "ERROR (qpOASES): Dimension mismatch!" );
201  #endif
202  return;
203  }
204 
205  if ( ( size_H != nV*nV ) && ( size_H != 0 ) )
206  {
207  #ifndef __SUPPRESSANYOUTPUT__
208  mexErrMsgTxt( "ERROR (qpOASES): Dimension mismatch in H!" );
209  #endif
210  return;
211  }
212 
213  if ( ( nU < 1 ) || ( nU > nV ) )
214  {
215  #ifndef __SUPPRESSANYOUTPUT__
216  mexErrMsgTxt( "ERROR (qpOASES): Invalid number of control inputs!" );
217  #endif
218  return;
219  }
220 
221  if ( ( size_lb != nV ) && ( size_lb != 0 ) )
222  {
223  #ifndef __SUPPRESSANYOUTPUT__
224  mexErrMsgTxt( "ERROR (qpOASES): Dimension mismatch in lb!" );
225  #endif
226  return;
227  }
228 
229  if ( ( size_ub != nV ) && ( size_ub != 0 ) )
230  {
231  #ifndef __SUPPRESSANYOUTPUT__
232  mexErrMsgTxt( "ERROR (qpOASES): Dimension mismatch in ub!" );
233  #endif
234  return;
235  }
236 
237  if ( ( size_lbA != nC ) && ( size_lbA != 0 ) )
238  {
239  #ifndef __SUPPRESSANYOUTPUT__
240  mexErrMsgTxt( "ERROR (qpOASES): Dimension mismatch in lbA!" );
241  #endif
242  return;
243  }
244 
245  if ( ( size_ubA != nC ) && ( size_ubA != 0 ) )
246  {
247  #ifndef __SUPPRESSANYOUTPUT__
248  mexErrMsgTxt( "ERROR (qpOASES): Dimension mismatch in ubA!" );
249  #endif
250  return;
251  }
252 
253 
254  /* allocate QProblem object */
255  problem = new SQProblem( nV,nC,HESSIANTYPE );
256  if ( problem == 0 )
257  {
258  #ifndef __SUPPRESSANYOUTPUT__
259  mexErrMsgTxt( "ERROR (qpOASES): Unable to create SQProblem object!" );
260  #endif
261  return;
262  }
263 
264  Options problemOptions;
265  problemOptions.setToMPC();
266  problem->setOptions( problemOptions );
267 
268  #ifndef __DEBUG__
269  problem->setPrintLevel( PL_LOW );
270  #endif
271  #ifdef __SUPPRESSANYOUTPUT__
272  problem->setPrintLevel( PL_NONE );
273  #endif
274 
275  ssGetPWork(S)[0] = (void *) problem;
276 
277  /* allocate memory for QP data ... */
278  if ( size_H > 0 )
279  ssGetPWork(S)[1] = (void *) calloc( size_H, sizeof(real_t) ); /* H */
280  else
281  ssGetPWork(S)[1] = 0;
282 
283  ssGetPWork(S)[2] = (void *) calloc( size_g, sizeof(real_t) ); /* g */
284  ssGetPWork(S)[3] = (void *) calloc( size_A, sizeof(real_t) ); /* A */
285 
286  if ( size_lb > 0 )
287  ssGetPWork(S)[4] = (void *) calloc( size_lb, sizeof(real_t) ); /* lb */
288  else
289  ssGetPWork(S)[4] = 0;
290 
291  if ( size_ub > 0 )
292  ssGetPWork(S)[5] = (void *) calloc( size_ub, sizeof(real_t) ); /* ub */
293  else
294  ssGetPWork(S)[5] = 0;
295 
296  if ( size_lbA > 0 )
297  ssGetPWork(S)[6] = (void *) calloc( size_lbA, sizeof(real_t) ); /* lbA */
298  else
299  ssGetPWork(S)[6] = 0;
300 
301  if ( size_ubA > 0 )
302  ssGetPWork(S)[7] = (void *) calloc( size_ubA, sizeof(real_t) ); /* ubA */
303  else
304  ssGetPWork(S)[7] = 0;
305 }
306 
307 
308 
309 static void mdlOutputs(SimStruct *S, int_T tid)
310 {
312 
313  int i;
314  int nV, nC;
315  returnValue status;
316 
317  int_t nWSR = MAXITER;
318  int nU = NCONTROLINPUTS;
319 
320  InputRealPtrsType in_H, in_g, in_A, in_lb, in_ub, in_lbA, in_ubA;
321 
322  SQProblem* problem;
323  real_t *H, *g, *A, *lb, *ub, *lbA, *ubA;
324 
325  real_t *xOpt;
326 
327  real_T *out_uOpt, *out_objVal, *out_status, *out_nWSR;
328 
329 
330  /* get pointers to block inputs ... */
331  in_H = ssGetInputPortRealSignalPtrs(S, 0);
332  in_g = ssGetInputPortRealSignalPtrs(S, 1);
333  in_A = ssGetInputPortRealSignalPtrs(S, 2);
334  in_lb = ssGetInputPortRealSignalPtrs(S, 3);
335  in_ub = ssGetInputPortRealSignalPtrs(S, 4);
336  in_lbA = ssGetInputPortRealSignalPtrs(S, 5);
337  in_ubA = ssGetInputPortRealSignalPtrs(S, 6);
338 
339 
340  /* ... and to the QP data */
341  problem = (SQProblem*) ssGetPWork(S)[0];
342 
343  H = (real_t *) ssGetPWork(S)[1];
344  g = (real_t *) ssGetPWork(S)[2];
345  A = (real_t *) ssGetPWork(S)[3];
346  lb = (real_t *) ssGetPWork(S)[4];
347  ub = (real_t *) ssGetPWork(S)[5];
348  lbA = (real_t *) ssGetPWork(S)[6];
349  ubA = (real_t *) ssGetPWork(S)[7];
350 
351 
352  /* setup QP data */
353  nV = ssGetInputPortWidth(S, 1); /* nV = size_g */
354  nC = (int) ( ((real_t) ssGetInputPortWidth(S, 2)) / ((real_t) nV) ); /* nC = size_A / size_g */
355 
356  if ( H != 0 )
357  {
358  /* no conversion from FORTRAN to C as Hessian is symmetric! */
359  for ( i=0; i<nV*nV; ++i )
360  H[i] = (*in_H)[i];
361  }
362 
363  convertFortranToC( *in_A,nV,nC, A );
364 
365  for ( i=0; i<nV; ++i )
366  g[i] = (*in_g)[i];
367 
368  if ( lb != 0 )
369  {
370  for ( i=0; i<nV; ++i )
371  lb[i] = (*in_lb)[i];
372  }
373 
374  if ( ub != 0 )
375  {
376  for ( i=0; i<nV; ++i )
377  ub[i] = (*in_ub)[i];
378  }
379 
380  if ( lbA != 0 )
381  {
382  for ( i=0; i<nC; ++i )
383  lbA[i] = (*in_lbA)[i];
384  }
385 
386  if ( ubA != 0 )
387  {
388  for ( i=0; i<nC; ++i )
389  ubA[i] = (*in_ubA)[i];
390  }
391 
392  xOpt = new real_t[nV];
393 
394  if ( problem->getCount() == 0 )
395  {
396  /* initialise and solve first QP */
397  status = problem->init( H,g,A,lb,ub,lbA,ubA, nWSR,0 );
398  problem->getPrimalSolution( xOpt );
399  }
400  else
401  {
402  /* solve neighbouring QP using hotstart technique */
403  status = problem->hotstart( H,g,A,lb,ub,lbA,ubA, nWSR,0 );
404  if ( ( status != SUCCESSFUL_RETURN ) && ( status != RET_MAX_NWSR_REACHED ) )
405  {
406  /* if an error occurs, reset problem data structures ... */
407  problem->reset( );
408 
409  /* ... and initialise/solve again with remaining number of iterations. */
410  int_t nWSR_retry = MAXITER - nWSR;
411  status = problem->init( H,g,A,lb,ub,lbA,ubA, nWSR_retry,0 );
412  nWSR += nWSR_retry;
413  }
414 
415  /* obtain optimal solution */
416  problem->getPrimalSolution( xOpt );
417  }
418 
419  /* generate block output: status information ... */
420  out_uOpt = ssGetOutputPortRealSignal(S, 0);
421  out_objVal = ssGetOutputPortRealSignal(S, 1);
422  out_status = ssGetOutputPortRealSignal(S, 2);
423  out_nWSR = ssGetOutputPortRealSignal(S, 3);
424 
425  for ( i=0; i<nU; ++i )
426  out_uOpt[i] = (real_T)(xOpt[i]);
427 
428  out_objVal[0] = (real_T)(problem->getObjVal( ));
429  out_status[0] = (real_t)(getSimpleStatus( status ));
430  out_nWSR[0] = (real_T)(nWSR);
431 
432  removeNaNs( out_uOpt,nU );
433  removeInfs( out_uOpt,nU );
434  removeNaNs( out_objVal,1 );
435  removeInfs( out_objVal,1 );
436 
437  delete[] xOpt;
438 }
439 
440 
441 static void mdlTerminate(SimStruct *S)
442 {
444 
445  int i;
446 
447  /* reset global message handler */
449 
450  if ( ssGetPWork(S)[0] != 0 )
451  delete ((SQProblem*)(ssGetPWork(S)[0]));
452 
453  for ( i=1; i<8; ++i )
454  {
455  if ( ssGetPWork(S)[i] != 0 )
456  free( ssGetPWork(S)[i] );
457  }
458 }
459 
460 
461 #ifdef MATLAB_MEX_FILE
462 #include "simulink.c"
463 #else
464 #include "cg_sfun.h"
465 #endif
466 
467 
468 #ifdef __cplusplus
469 }
470 #endif
471 
472 
473 /*
474  * end of file
475  */
returnValue init(const real_t *const _H, const real_t *const _g, const real_t *const _A, const real_t *const _lb, const real_t *const _ub, const real_t *const _lbA, const real_t *const _ubA, int &nWSR, const real_t *const yOpt=0, real_t *const cputime=0)
Implements the online active set strategy for QPs with varying matrices.
Allows to pass back messages to the calling function.
returnValue convertFortranToC(const real_t *const A_for, int nV, int nC, real_t *const A)
#define PL_NONE
returnValue setOptions(const Options &_options)
Provides a generic way to set and pass user-specified options.
Definition: options.hpp:65
uint_t getCount() const
#define PL_LOW
returnValue setToMPC()
double real_t
Definition: AD_test.c:10
int_t getSimpleStatus(returnValue returnvalue, BooleanType doPrintStatus=BT_FALSE)
returnValue hotstart(const real_t *const H_new, const real_t *const g_new, const real_t *const A_new, const real_t *const lb_new, const real_t *const ub_new, const real_t *const lbA_new, const real_t *const ubA_new, int &nWSR, real_t *const cputime)


acado
Author(s): Milan Vukov, Rien Quirynen
autogenerated on Mon Jun 10 2019 12:35:01