qpOASES-3.0beta/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-2011 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/SQProblem.hpp>
40 
41 
42 #ifdef __cplusplus
43 extern "C" {
44 #endif
45 
46 
47 #define S_FUNCTION_NAME qpOASES_SQProblem
48 #define S_FUNCTION_LEVEL 2
50 #define MDL_START
52 #include "simstruc.h"
53 
54 
55 /* SETTINGS: */
56 #define SAMPLINGTIME 0.1
57 #define NCONTROLINPUTS 2
58 #define NWSR 10
61 static void mdlInitializeSizes (SimStruct *S) /* Init sizes array */
62 {
63  int nU = NCONTROLINPUTS;
64 
65  /* Specify the number of continuous and discrete states */
66  ssSetNumContStates(S, 0);
67  ssSetNumDiscStates(S, 0);
68 
69  /* Specify the number of intput ports */
70  if ( !ssSetNumInputPorts(S, 7) )
71  return;
72 
73  /* Specify the number of output ports */
74  if ( !ssSetNumOutputPorts(S, 4) )
75  return;
76 
77  /* Specify dimension information for the input ports */
78  ssSetInputPortVectorDimension(S, 0, DYNAMICALLY_SIZED);
79  ssSetInputPortVectorDimension(S, 1, DYNAMICALLY_SIZED);
80  ssSetInputPortVectorDimension(S, 2, DYNAMICALLY_SIZED);
81  ssSetInputPortVectorDimension(S, 3, DYNAMICALLY_SIZED);
82  ssSetInputPortVectorDimension(S, 4, DYNAMICALLY_SIZED);
83  ssSetInputPortVectorDimension(S, 5, DYNAMICALLY_SIZED);
84  ssSetInputPortVectorDimension(S, 6, DYNAMICALLY_SIZED);
85 
86  /* Specify dimension information for the output ports */
87  ssSetOutputPortVectorDimension(S, 0, 1 );
88  ssSetOutputPortVectorDimension(S, 1, nU );
89  ssSetOutputPortVectorDimension(S, 2, 1 );
90  ssSetOutputPortVectorDimension(S, 3, 1 );
91 
92  /* Specify the direct feedthrough status */
93  ssSetInputPortDirectFeedThrough(S, 0, 1);
94  ssSetInputPortDirectFeedThrough(S, 1, 1);
95  ssSetInputPortDirectFeedThrough(S, 2, 1);
96  ssSetInputPortDirectFeedThrough(S, 3, 1);
97  ssSetInputPortDirectFeedThrough(S, 4, 1);
98  ssSetInputPortDirectFeedThrough(S, 5, 1);
99  ssSetInputPortDirectFeedThrough(S, 6, 1);
100 
101  /* One sample time */
102  ssSetNumSampleTimes(S, 1);
103 
104 
105  /* global variables:
106  * 0: problem
107  * 1: H
108  * 2: g
109  * 3: A
110  * 4: lb
111  * 5: ub
112  * 6: lbA
113  * 7: ubA
114  * 8: count
115  */
116 
117  /* Specify the size of the block's pointer work vector */
118  ssSetNumPWork(S, 9);
119 }
120 
121 
122 #if defined(MATLAB_MEX_FILE)
123 
124 #define MDL_SET_INPUT_PORT_DIMENSION_INFO
125 #define MDL_SET_OUTPUT_PORT_DIMENSION_INFO
126 
127 static void mdlSetInputPortDimensionInfo(SimStruct *S, int_T port, const DimsInfo_T *dimsInfo)
128 {
129  if ( !ssSetInputPortDimensionInfo(S, port, dimsInfo) )
130  return;
131 }
132 
133 static void mdlSetOutputPortDimensionInfo(SimStruct *S, int_T port, const DimsInfo_T *dimsInfo)
134 {
135  if ( !ssSetOutputPortDimensionInfo(S, port, dimsInfo) )
136  return;
137 }
138 
139 #endif
140 
141 
142 static void mdlInitializeSampleTimes(SimStruct *S)
143 {
144  ssSetSampleTime(S, 0, SAMPLINGTIME);
145  ssSetOffsetTime(S, 0, 0.0);
146 }
147 
148 
149 static void mdlStart(SimStruct *S)
150 {
151  #ifndef __DSPACE__
152  using namespace qpOASES;
153  #endif
154 
155  int nU = NCONTROLINPUTS;
156  int size_H, size_g, size_A, size_lb, size_ub, size_lbA, size_ubA;
157  int nV, nC;
158 
159  SQProblem* problem;
160  real_t* count;
161 
162 
163  /* get block inputs dimensions */
164  size_H = ssGetInputPortWidth(S, 0);
165  size_g = ssGetInputPortWidth(S, 1);
166  size_A = ssGetInputPortWidth(S, 2);
167  size_lb = ssGetInputPortWidth(S, 3);
168  size_ub = ssGetInputPortWidth(S, 4);
169  size_lbA = ssGetInputPortWidth(S, 5);
170  size_ubA = ssGetInputPortWidth(S, 6);
171 
172 
173  /* dimension checks */
174  nV = size_g;
175  nC = (int) ( ((real_t) size_A) / ((real_t) nV) );
176 
177  if ( nV == 0 )
178  {
179  #ifndef __DSPACE__
180  mexErrMsgTxt( "ERROR (qpOASES): Dimension mismatch!" );
181  #endif
182  return;
183  }
184 
185  if ( size_H != nV*nV )
186  {
187  #ifndef __DSPACE__
188  mexErrMsgTxt( "ERROR (qpOASES): Dimension mismatch!" );
189  #endif
190  return;
191  }
192 
193  if ( nU > nV )
194  {
195  #ifndef __DSPACE__
196  mexErrMsgTxt( "ERROR (qpOASES): Dimension mismatch!" );
197  #endif
198  return;
199  }
200 
201  if ( size_lb != nV )
202  {
203  #ifndef __DSPACE__
204  mexErrMsgTxt( "ERROR (qpOASES): Dimension mismatch!" );
205  #endif
206  return;
207  }
208 
209  if ( size_ub != nV )
210  {
211  #ifndef __DSPACE__
212  mexErrMsgTxt( "ERROR (qpOASES): Dimension mismatch!" );
213  #endif
214  return;
215  }
216 
217  if ( size_lbA != nC )
218  {
219  #ifndef __DSPACE__
220  mexErrMsgTxt( "ERROR (qpOASES): Dimension mismatch!" );
221  #endif
222  return;
223  }
224 
225  if ( size_ubA != nC )
226  {
227  #ifndef __DSPACE__
228  mexErrMsgTxt( "ERROR (qpOASES): Dimension mismatch!" );
229  #endif
230  return;
231  }
232 
233 
234  /* allocate QProblem object */
235  problem = new SQProblem( nV,nC );
236  if ( problem == 0 )
237  {
238  #ifndef __DSPACE__
239  mexErrMsgTxt( "ERROR (qpOASES): Unable to create QProblem object!" );
240  #endif
241  return;
242  }
243 
244  #ifndef __DEBUG__
245  problem->setPrintLevel( PL_LOW );
246  #endif
247  #ifdef __SUPPRESSANYOUTPUT__
248  problem->setPrintLevel( PL_NONE );
249  #endif
250  #ifdef __DSPACE__
251  problem->setPrintLevel( PL_NONE );
252  #endif
253 
254  ssGetPWork(S)[0] = (void *) problem;
255 
256  /* allocate memory for QP data ... */
257  ssGetPWork(S)[1] = (void *) calloc( size_H, sizeof(real_t) ); /* H */
258  ssGetPWork(S)[2] = (void *) calloc( size_g, sizeof(real_t) ); /* g */
259  ssGetPWork(S)[3] = (void *) calloc( size_A, sizeof(real_t) ); /* A */
260  ssGetPWork(S)[4] = (void *) calloc( size_lb, sizeof(real_t) ); /* lb */
261  ssGetPWork(S)[5] = (void *) calloc( size_ub, sizeof(real_t) ); /* ub */
262  ssGetPWork(S)[6] = (void *) calloc( size_lbA, sizeof(real_t) ); /* lbA */
263  ssGetPWork(S)[7] = (void *) calloc( size_ubA, sizeof(real_t) ); /* ubA */
264  ssGetPWork(S)[8] = (void *) calloc( 1, sizeof(real_t) ); /* count */
265 
266  /* reset counter */
267  count = (real_t *) ssGetPWork(S)[8];
268  count[0] = 0.0;
269 }
270 
271 
272 
273 static void mdlOutputs(SimStruct *S, int_T tid)
274 {
275  #ifndef __DSPACE__
276  using namespace qpOASES;
277  #endif
278 
279  int i;
280  int nV, nC, status;
281 
282  int nWSR = NWSR;
283  int nU = NCONTROLINPUTS;
284 
285  InputRealPtrsType in_H, in_g, in_A, in_lb, in_ub, in_lbA, in_ubA;
286 
287  SQProblem* problem;
288  real_t *H, *g, *A, *lb, *ub, *lbA, *ubA, *count;
289 
290  real_t *xOpt;
291 
292  real_T *out_objVal, *out_xOpt, *out_status, *out_nWSR;
293 
294 
295  /* get pointers to block inputs ... */
296  in_H = ssGetInputPortRealSignalPtrs(S, 0);
297  in_g = ssGetInputPortRealSignalPtrs(S, 1);
298  in_A = ssGetInputPortRealSignalPtrs(S, 2);
299  in_lb = ssGetInputPortRealSignalPtrs(S, 3);
300  in_ub = ssGetInputPortRealSignalPtrs(S, 4);
301  in_lbA = ssGetInputPortRealSignalPtrs(S, 5);
302  in_ubA = ssGetInputPortRealSignalPtrs(S, 6);
303 
304 
305  /* ... and to the QP data */
306  problem = (SQProblem *) ssGetPWork(S)[0];
307 
308  H = (real_t *) ssGetPWork(S)[1];
309  g = (real_t *) ssGetPWork(S)[2];
310  A = (real_t *) ssGetPWork(S)[3];
311  lb = (real_t *) ssGetPWork(S)[4];
312  ub = (real_t *) ssGetPWork(S)[5];
313  lbA = (real_t *) ssGetPWork(S)[6];
314  ubA = (real_t *) ssGetPWork(S)[7];
315 
316  count = (real_t *) ssGetPWork(S)[8];
317 
318 
319  /* setup QP data */
320  nV = ssGetInputPortWidth(S, 1); /* nV = size_g */
321  nC = (int) ( ((real_t) ssGetInputPortWidth(S, 2)) / ((real_t) nV) ); /* nC = size_A / size_g */
322 
323  for ( i=0; i<nV*nV; ++i )
324  H[i] = (*in_H)[i];
325 
326  for ( i=0; i<nC*nV; ++i )
327  A[i] = (*in_A)[i];
328 
329  for ( i=0; i<nV; ++i )
330  {
331  g[i] = (*in_g)[i];
332  lb[i] = (*in_lb)[i];
333  ub[i] = (*in_ub)[i];
334  }
335 
336  for ( i=0; i<nC; ++i )
337  {
338  lbA[i] = (*in_lbA)[i];
339  ubA[i] = (*in_ubA)[i];
340  }
341 
342  xOpt = new real_t[nV];
343 
344  if ( count[0] == 0 )
345  {
346  /* initialise and solve first QP */
347  status = problem->init( H,g,A,lb,ub,lbA,ubA, nWSR,0 );
348  ssGetPWork(S)[0] = ( void* ) problem;
349  problem->getPrimalSolution( xOpt );
350  }
351  else
352  {
353  /* solve neighbouring QP using hotstart technique */
354  status = problem->hotstart( H,g,A,lb,ub,lbA,ubA, nWSR,0 );
355  if ( ( status != SUCCESSFUL_RETURN ) && ( status != RET_MAX_NWSR_REACHED ) )
356  {
357  /* if an error occurs, reset problem data structures and initialise again */
358  problem->reset( );
359  problem->init( H,g,A,lb,ub,lbA,ubA, nWSR,0 );
360  }
361  else
362  {
363  /* otherwise obtain optimal solution */
364  problem->getPrimalSolution( xOpt );
365  }
366  }
367 
368  /* generate block output: status information ... */
369  out_objVal = ssGetOutputPortRealSignal(S, 0);
370  out_xOpt = ssGetOutputPortRealSignal(S, 1);
371  out_status = ssGetOutputPortRealSignal(S, 2);
372  out_nWSR = ssGetOutputPortRealSignal(S, 3);
373 
374  out_objVal[0] = ((real_T) problem->getObjVal( ));
375 
376  for ( i=0; i<nU; ++i )
377  out_xOpt[i] = ((real_T) xOpt[i]);
378 
379  switch ( status )
380  {
381  case SUCCESSFUL_RETURN:
382  out_status[0] = 0.0;
383  break;
384 
386  out_status[0] = 1.0;
387  break;
388 
391  out_status[0] = -2.0;
392  break;
393 
396  out_status[0] = -3.0;
397  break;
398 
399  default:
400  out_status[0] = -1.0;
401  break;
402  }
403 
404  out_nWSR[0] = ((real_T) nWSR);
405 
406  /* increase counter */
407  count[0] = count[0] + 1;
408 
409  delete[] xOpt;
410 }
411 
412 
413 static void mdlTerminate(SimStruct *S)
414 {
415  #ifndef __DSPACE__
416  using namespace qpOASES;
417  #endif
418 
419  /* reset global message handler */
421 
422  int i;
423  for ( i=0; i<9; ++i )
424  {
425  if ( ssGetPWork(S)[i] != 0 )
426  free( ssGetPWork(S)[i] );
427  }
428 }
429 
430 
431 #ifdef MATLAB_MEX_FILE
432 #include "simulink.c"
433 #else
434 #include "cg_sfun.h"
435 #endif
436 
437 
438 #ifdef __cplusplus
439 }
440 #endif
441 
442 
443 /*
444  * end of file
445  */
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.
#define PL_NONE
#define PL_LOW
double real_t
Definition: AD_test.c:10
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