qpOASES-3.2.0/interfaces/simulink/qpOASES_QProblemB.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_QProblemB
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, 1); /* H */
73  if ( ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S) )
74  return;
75 
76  /* Specify the number of intput ports */
77  if ( !ssSetNumInputPorts(S, 3) )
78  return;
79 
80  /* Specify the number of output ports */
81  if ( !ssSetNumOutputPorts(S, 4) )
82  return;
83 
84  /* Specify dimension information for the input ports */
85  ssSetInputPortVectorDimension(S, 0, DYNAMICALLY_SIZED); /* g */
86  ssSetInputPortVectorDimension(S, 1, DYNAMICALLY_SIZED); /* lb */
87  ssSetInputPortVectorDimension(S, 2, DYNAMICALLY_SIZED); /* ub */
88 
89  /* Specify dimension information for the output ports */
90  ssSetOutputPortVectorDimension(S, 0, nU ); /* uOpt */
91  ssSetOutputPortVectorDimension(S, 1, 1 ); /* fval */
92  ssSetOutputPortVectorDimension(S, 2, 1 ); /* exitflag */
93  ssSetOutputPortVectorDimension(S, 3, 1 ); /* iter */
94 
95  /* Specify the direct feedthrough status */
96  ssSetInputPortDirectFeedThrough(S, 0, 1);
97  ssSetInputPortDirectFeedThrough(S, 1, 1);
98  ssSetInputPortDirectFeedThrough(S, 2, 1);
99 
100  /* One sample time */
101  ssSetNumSampleTimes(S, 1);
102 
103  /* global variables:
104  * 0: problem
105  * 1: H
106  * 2: g
107  * 3: lb
108  * 4: ub
109  */
110 
111  /* Specify the size of the block's pointer work vector */
112  ssSetNumPWork(S, 5);
113 }
114 
115 
116 #if defined(MATLAB_MEX_FILE)
117 
118 #define MDL_SET_INPUT_PORT_DIMENSION_INFO
119 #define MDL_SET_OUTPUT_PORT_DIMENSION_INFO
120 
121 static void mdlSetInputPortDimensionInfo(SimStruct *S, int_T port, const DimsInfo_T *dimsInfo)
122 {
123  if ( !ssSetInputPortDimensionInfo(S, port, dimsInfo) )
124  return;
125 }
126 
127 static void mdlSetOutputPortDimensionInfo(SimStruct *S, int_T port, const DimsInfo_T *dimsInfo)
128 {
129  if ( !ssSetOutputPortDimensionInfo(S, port, dimsInfo) )
130  return;
131 }
132 
133 #endif
134 
135 
136 static void mdlInitializeSampleTimes(SimStruct *S)
137 {
138  ssSetSampleTime(S, 0, SAMPLINGTIME);
139  ssSetOffsetTime(S, 0, 0.0);
140 }
141 
142 
143 static void mdlStart(SimStruct *S)
144 {
146 
147  int nU = NCONTROLINPUTS;
148  int size_g, size_lb, size_ub;
149  int size_H, nRows_H, nCols_H;
150  int nV;
151 
152  QProblemB* problem;
153 
154 
155  /* get block inputs dimensions */
156  const mxArray* in_H = ssGetSFcnParam(S, 0);
157 
158  if ( mxIsEmpty(in_H) == 1 )
159  {
160  if ( ( HESSIANTYPE != HST_ZERO ) && ( HESSIANTYPE != HST_IDENTITY ) )
161  {
162  #ifndef __SUPPRESSANYOUTPUT__
163  mexErrMsgTxt( "ERROR (qpOASES): Hessian can only be empty if type is set to HST_ZERO or HST_IDENTITY!" );
164  #endif
165  return;
166  }
167 
168  nRows_H = 0;
169  nCols_H = 0;
170  size_H = 0;
171  }
172  else
173  {
174  nRows_H = (int)mxGetM(in_H);
175  nCols_H = (int)mxGetN(in_H);
176  size_H = nRows_H * nCols_H;
177  }
178 
179  size_g = ssGetInputPortWidth(S, 0);
180  size_lb = ssGetInputPortWidth(S, 1);
181  size_ub = ssGetInputPortWidth(S, 2);
182 
183 
184  /* dimension checks */
185  nV = size_g;
186 
187  if ( MAXITER < 0 )
188  {
189  #ifndef __SUPPRESSANYOUTPUT__
190  mexErrMsgTxt( "ERROR (qpOASES): Maximum number of iterations must not be negative!" );
191  #endif
192  return;
193  }
194 
195  if ( nV <= 0 )
196  {
197  #ifndef __SUPPRESSANYOUTPUT__
198  mexErrMsgTxt( "ERROR (qpOASES): Dimension mismatch!" );
199  #endif
200  return;
201  }
202 
203  if ( ( size_H != nV*nV ) && ( size_H != 0 ) )
204  {
205  #ifndef __SUPPRESSANYOUTPUT__
206  mexErrMsgTxt( "ERROR (qpOASES): Dimension mismatch in H!" );
207  #endif
208  return;
209  }
210 
211  if ( nRows_H != nCols_H )
212  {
213  #ifndef __SUPPRESSANYOUTPUT__
214  mexErrMsgTxt( "ERROR (qpOASES): Hessian matrix must be square matrix!" );
215  #endif
216  return;
217  }
218 
219  if ( ( nU < 1 ) || ( nU > nV ) )
220  {
221  #ifndef __SUPPRESSANYOUTPUT__
222  mexErrMsgTxt( "ERROR (qpOASES): Invalid number of control inputs!" );
223  #endif
224  return;
225  }
226 
227  if ( ( size_lb != nV ) && ( size_lb != 0 ) )
228  {
229  #ifndef __SUPPRESSANYOUTPUT__
230  mexErrMsgTxt( "ERROR (qpOASES): Dimension mismatch in lb!" );
231  #endif
232  return;
233  }
234 
235  if ( ( size_ub != nV ) && ( size_ub != 0 ) )
236  {
237  #ifndef __SUPPRESSANYOUTPUT__
238  mexErrMsgTxt( "ERROR (qpOASES): Dimension mismatch in ub!" );
239  #endif
240  return;
241  }
242 
243 
244  /* allocate QProblemB object */
245  problem = new QProblemB( nV,HESSIANTYPE );
246  if ( problem == 0 )
247  {
248  #ifndef __SUPPRESSANYOUTPUT__
249  mexErrMsgTxt( "ERROR (qpOASES): Unable to create QProblemB object!" );
250  #endif
251  return;
252  }
253 
254  Options problemOptions;
255  problemOptions.setToMPC();
256  problem->setOptions( problemOptions );
257 
258  #ifndef __DEBUG__
259  problem->setPrintLevel( PL_LOW );
260  #endif
261  #ifdef __SUPPRESSANYOUTPUT__
262  problem->setPrintLevel( PL_NONE );
263  #endif
264 
265  ssGetPWork(S)[0] = (void *) problem;
266 
267  /* allocate memory for QP data ... */
268  if ( size_H > 0 )
269  ssGetPWork(S)[1] = (void *) calloc( size_H, sizeof(real_t) ); /* H */
270  else
271  ssGetPWork(S)[1] = 0;
272 
273  ssGetPWork(S)[2] = (void *) calloc( size_g, sizeof(real_t) ); /* g */
274 
275  if ( size_lb > 0 )
276  ssGetPWork(S)[3] = (void *) calloc( size_lb, sizeof(real_t) ); /* lb */
277  else
278  ssGetPWork(S)[3] = 0;
279 
280  if ( size_ub > 0 )
281  ssGetPWork(S)[4] = (void *) calloc( size_ub, sizeof(real_t) ); /* ub */
282  else
283  ssGetPWork(S)[4] = 0;
284 }
285 
286 
287 static void mdlOutputs(SimStruct *S, int_T tid)
288 {
290 
291  int i;
292  int nV;
293  returnValue status;
294 
295  int_t nWSR = MAXITER;
296  int nU = NCONTROLINPUTS;
297 
298  InputRealPtrsType in_g, in_lb, in_ub;
299 
300  QProblemB* problem;
301  real_t *H, *g, *lb, *ub;
302 
303  real_t *xOpt;
304 
305  real_T *out_uOpt, *out_objVal, *out_status, *out_nWSR;
306 
307 
308  /* get pointers to block inputs ... */
309  const mxArray* in_H = ssGetSFcnParam(S, 0);
310  in_g = ssGetInputPortRealSignalPtrs(S, 0);
311  in_lb = ssGetInputPortRealSignalPtrs(S, 1);
312  in_ub = ssGetInputPortRealSignalPtrs(S, 2);
313 
314  /* ... and to the QP data */
315  problem = (QProblemB*) ssGetPWork(S)[0];
316 
317  H = (real_t *) ssGetPWork(S)[1];
318  g = (real_t *) ssGetPWork(S)[2];
319  lb = (real_t *) ssGetPWork(S)[3];
320  ub = (real_t *) ssGetPWork(S)[4];
321 
322 
323  /* setup QP data */
324  nV = ssGetInputPortWidth(S, 1); /* nV = size_g */
325 
326  if ( H != 0 )
327  {
328  /* no conversion from FORTRAN to C as Hessian is symmetric! */
329  for ( i=0; i<nV*nV; ++i )
330  H[i] = (mxGetPr(in_H))[i];
331  }
332 
333  for ( i=0; i<nV; ++i )
334  g[i] = (*in_g)[i];
335 
336  if ( lb != 0 )
337  {
338  for ( i=0; i<nV; ++i )
339  lb[i] = (*in_lb)[i];
340  }
341 
342  if ( ub != 0 )
343  {
344  for ( i=0; i<nV; ++i )
345  ub[i] = (*in_ub)[i];
346  }
347 
348  xOpt = new real_t[nV];
349 
350  if ( problem->getCount() == 0 )
351  {
352  /* initialise and solve first QP */
353  status = problem->init( H,g,lb,ub, nWSR,0 );
354  problem->getPrimalSolution( xOpt );
355  }
356  else
357  {
358  /* solve neighbouring QP using hotstart technique */
359  status = problem->hotstart( g,lb,ub, nWSR,0 );
360  if ( ( status != SUCCESSFUL_RETURN ) && ( status != RET_MAX_NWSR_REACHED ) )
361  {
362  /* if an error occurs, reset problem data structures ... */
363  problem->reset( );
364 
365  /* ... and initialise/solve again with remaining number of iterations. */
366  int_t nWSR_retry = MAXITER - nWSR;
367  status = problem->init( H,g,lb,ub, nWSR_retry,0 );
368  nWSR += nWSR_retry;
369  }
370 
371  /* obtain optimal solution */
372  problem->getPrimalSolution( xOpt );
373  }
374 
375  /* generate block output: status information ... */
376  out_uOpt = ssGetOutputPortRealSignal(S, 0);
377  out_objVal = ssGetOutputPortRealSignal(S, 1);
378  out_status = ssGetOutputPortRealSignal(S, 2);
379  out_nWSR = ssGetOutputPortRealSignal(S, 3);
380 
381  for ( i=0; i<nU; ++i )
382  out_uOpt[i] = (real_T)(xOpt[i]);
383 
384  out_objVal[0] = (real_T)(problem->getObjVal());
385  out_status[0] = (real_t)(getSimpleStatus( status ));
386  out_nWSR[0] = (real_T)(nWSR);
387 
388  removeNaNs( out_uOpt,nU );
389  removeInfs( out_uOpt,nU );
390  removeNaNs( out_objVal,1 );
391  removeInfs( out_objVal,1 );
392 
393  delete[] xOpt;
394 }
395 
396 
397 static void mdlTerminate(SimStruct *S)
398 {
400 
401  int i;
402 
403  /* reset global message handler */
405 
406  if ( ssGetPWork(S)[0] != 0 )
407  delete ((QProblemB*)(ssGetPWork(S)[0]));
408 
409  for ( i=1; i<5; ++i )
410  {
411  if ( ssGetPWork(S)[i] != 0 )
412  free( ssGetPWork(S)[i] );
413  }
414 }
415 
416 
417 #ifdef MATLAB_MEX_FILE
418 #include "simulink.c"
419 #else
420 #include "cg_sfun.h"
421 #endif
422 
423 
424 #ifdef __cplusplus
425 }
426 #endif
427 
428 
429 /*
430  * end of file
431  */
Implements the online active set strategy for box-constrained QPs.
Allows to pass back messages to the calling function.
returnValue init(const real_t *const _H, const real_t *const _g, const real_t *const _lb, const real_t *const _ub, int &nWSR, const real_t *const yOpt=0, real_t *const cputime=0)
#define HST_IDENTITY
#define PL_NONE
returnValue setOptions(const Options &_options)
returnValue hotstart(const real_t *const g_new, const real_t *const lb_new, const real_t *const ub_new, int &nWSR, real_t *const cputime)
Provides a generic way to set and pass user-specified options.
Definition: options.hpp:65
uint_t getCount() const
#define PL_LOW
#define HST_ZERO
returnValue setToMPC()
double real_t
Definition: AD_test.c:10
int_t getSimpleStatus(returnValue returnvalue, BooleanType doPrintStatus=BT_FALSE)


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