-
Notifications
You must be signed in to change notification settings - Fork 0
/
gcomp_example.cpp
280 lines (214 loc) · 9.21 KB
/
gcomp_example.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
/* Copyright 2003-2014 The MathWorks, Inc. */
// *******************************************************************
// **** To build this mex function use: mex sfun_cppcount_cpp.cpp ****
// *******************************************************************
#define S_FUNCTION_LEVEL 2
#define S_FUNCTION_NAME gcomp_example
// Need to include simstruc.h for the definition of the SimStruct and
// its associated macro definitions.
#include "simstruc.h"
#include <XBotInterface/RobotInterface.h>
#define IS_PARAM_DOUBLE(pVal) (mxIsNumeric(pVal) && !mxIsLogical(pVal) &&\
!mxIsEmpty(pVal) && !mxIsSparse(pVal) && !mxIsComplex(pVal) && mxIsDouble(pVal))
// Function: mdlInitializeSizes ===============================================
// Abstract:
// The sizes information is used by Simulink to determine the S-function
// block's characteristics (number of inputs, outputs, states, etc.).
static void mdlInitializeSizes(SimStruct *S)
{
int model_size = 45;
// No expected parameters
ssSetNumSFcnParams(S, 0);
// Parameter mismatch will be reported by Simulink
if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) {
return;
}
// Specify I/O
if (!ssSetNumInputPorts(S, 1)) return;
ssSetInputPortWidth(S, 0, model_size);
ssSetInputPortDirectFeedThrough(S, 0, 1);
if (!ssSetNumOutputPorts(S,1)) return;
ssSetOutputPortWidth(S, 0, model_size);
ssSetNumSampleTimes(S, 1);
// Reserve place for C++ object
ssSetNumPWork(S, 1);
ssSetSimStateCompliance(S, USE_CUSTOM_SIM_STATE);
ssSetOptions(S,
SS_OPTION_WORKS_WITH_CODE_REUSE |
SS_OPTION_EXCEPTION_FREE_CODE |
SS_OPTION_DISALLOW_CONSTANT_SAMPLE_TIME);
}
// Function: mdlInitializeSampleTimes =========================================
// Abstract:
// This function is used to specify the sample time(s) for your
// S-function. You must register the same number of sample times as
// specified in ssSetNumSampleTimes.
static void mdlInitializeSampleTimes(SimStruct *S)
{
ssSetSampleTime(S, 0, INHERITED_SAMPLE_TIME);
ssSetOffsetTime(S, 0, 0.0);
ssSetModelReferenceSampleTimeDefaultInheritance(S);
}
// Function: mdlStart =======================================================
// Abstract:
// This function is called once at start of model execution. If you
// have states that should be initialized once, this is the place
// to do it.
#define MDL_START
static void mdlStart(SimStruct *S)
{
// Store new C++ object in the pointers vector
static auto robot = XBot::ModelInterface::getModel("/home/arturo/Code/advr-superbuild/configs/ADVR_shared/centauro/configs/config_centauro_full_body_wheels.yaml");
ssGetPWork(S)[0] = (void *) robot.get();
}
#if defined(MATLAB_MEX_FILE)
#define MDL_SET_INPUT_PORT_DIMENSION_INFO
/* Function: mdlSetInputPortDimensionInfo ====================================
* Abstract:
* This routine is called with the candidate dimensions for an input port
* with unknown dimensions. If the proposed dimensions are acceptable, the
* routine should go ahead and set the actual port dimensions.
* If they are unacceptable an error should be generated via
* ssSetErrorStatus.
* Note that any other input or output ports whose dimensions are
* implicitly defined by virtue of knowing the dimensions of the given port
* can also have their dimensions set.
*/
static void mdlSetInputPortDimensionInfo(SimStruct *S,
int_T port,
const DimsInfo_T *dimsInfo)
{
// Retrieve C++ object from the pointers vector
XBot::ModelInterface * robot = static_cast<XBot::ModelInterface *>(ssGetPWork(S)[0]);
int_T uNumDims = dimsInfo->numDims;
int_T uWidth = dimsInfo->width;
int32_T *uDims = dimsInfo->dims;
boolean_T isOk = true;
/* Set input port dimension */
if(!ssSetInputPortDimensionInfo(S, port, dimsInfo)) return;
/*
* The block only accepts 2-D or higher signals. Check number of dimensions.
* If the parameter and the input signal are non-scalar, their dimensions
* must be the same.
*/
isOk = (uNumDims == 1) && (uWidth == robot->getJointNum());
if(!isOk){
ssSetErrorStatus(S, "Invalid input port dimensions. The input signal must be"
"equal to the model dof count!!");
return;
}
} /* end mdlSetInputPortDimensionInfo */
# define MDL_SET_OUTPUT_PORT_DIMENSION_INFO
/* Function: mdlSetOutputPortDimensionInfo ===================================
* Abstract:
* This routine is called with the candidate dimensions for an output port
* with unknown dimensions. If the proposed dimensions are acceptable, the
* routine should go ahead and set the actual port dimensions.
* If they are unacceptable an error should be generated via
* ssSetErrorStatus.
* Note that any other input or output ports whose dimensions are
* implicitly defined by virtue of knowing the dimensions of the given
* port can also have their dimensions set.
*/
static void mdlSetOutputPortDimensionInfo(SimStruct *S,
int_T port,
const DimsInfo_T *dimsInfo)
{
// Retrieve C++ object from the pointers vector
XBot::ModelInterface * robot = static_cast<XBot::ModelInterface *>(ssGetPWork(S)[0]);
int_T uNumDims = dimsInfo->numDims;
int_T uWidth = dimsInfo->width;
int32_T *uDims = dimsInfo->dims;
boolean_T isOk = true;
/* Set input port dimension */
if(!ssSetOutputPortDimensionInfo(S, port, dimsInfo)) return;
/*
* The block only accepts 2-D or higher signals. Check number of dimensions.
* If the parameter and the input signal are non-scalar, their dimensions
* must be the same.
*/
isOk = (uNumDims == 1) && (uWidth == robot->getJointNum());
if(!isOk){
ssSetErrorStatus(S, "Invalid input port dimensions. The input signal must be"
"equal to the model dof count!!");
return;
}
} /* end mdlSetOutputPortDimensionInfo */
# define MDL_SET_DEFAULT_PORT_DIMENSION_INFO
/* Function: mdlSetDefaultPortDimensionInfo ====================================
* This routine is called when Simulink is not able to find dimension
* candidates for ports with unknown dimensions. This function must set the
* dimensions of all ports with unknown dimensions.
*/
static void mdlSetDefaultPortDimensionInfo(SimStruct *S)
{
int_T outWidth = ssGetOutputPortWidth(S, 0);
/* Input port dimension must be unknown. Set it to scalar. */
if(!ssSetInputPortMatrixDimensions(S, 0, 1, 1)) return;
if(outWidth == DYNAMICALLY_SIZED){
/* Output dimensions are unknown. Set it to scalar. */
if(!ssSetOutputPortMatrixDimensions(S, 0, 1, 1)) return;
}
} /* end mdlSetDefaultPortDimensionInfo */
#endif
// Function: mdlOutputs =======================================================
// Abstract:
// In this function, you compute the outputs of your S-function
// block.
static void mdlOutputs(SimStruct *S, int_T tid)
{
// Retrieve C++ object from the pointers vector
XBot::ModelInterface * robot = static_cast<XBot::ModelInterface *>(ssGetPWork(S)[0]);
// Get data addresses of I/O
InputRealPtrsType u = ssGetInputPortRealSignalPtrs(S,0);
real_T *y = ssGetOutputPortRealSignal(S, 0);
int_T u_size = ssGetInputPortWidth(S, 0);
Eigen::Map<Eigen::VectorXd> q((double *)u, robot->getJointNum());
std::cout << q.transpose() << std::endl;
robot->setJointPosition(q);
robot->update();
Eigen::Map<Eigen::VectorXd> y_map((double *)y, robot->getJointNum());
Eigen::VectorXd gcomp;
robot->computeGravityCompensation(gcomp);
y_map = gcomp;
// Call AddTo method and return peak value
// y[0] = q(0);
}
/* Define to indicate that this S-Function has the mdlG[S]etSimState methods */
#define MDL_SIM_STATE
/* Function: mdlGetSimState =====================================================
* Abstract:
*
*/
static mxArray* mdlGetSimState(SimStruct* S)
{
// Retrieve C++ object from the pointers vector
return mxCreateDoubleScalar(.1);
}
/* Function: mdlGetSimState =====================================================
* Abstract:
*
*/
static void mdlSetSimState(SimStruct* S, const mxArray* ma)
{
// Retrieve C++ object from the pointers vector
// DoubleAdder *da = /*static_cast<DoubleAdder*>(ssGetPWork(S)[0]);
// da->SetPeak(mxGetP*/r(ma)[0]);
}
// Function: mdlTerminate =====================================================
// Abstract:
// In this function, you should perform any actions that are necessary
// at the termination of a simulation. For example, if memory was
// allocated in mdlStart, this is the place to free it.
static void mdlTerminate(SimStruct *S)
{
// Retrieve and destroy C++ object
// HelloWorld *da = static_cast<HelloWorld *>(ssGetPWork(S)[0]);
// delete da;
}
// Required S-function trailer
#ifdef MATLAB_MEX_FILE /* Is this file being compiled as a MEX-file? */
#include "simulink.c" /* MEX-file interface mechanism */
#else
#include "cg_sfun.h" /* Code generation registration function */
#endif