reading ASCII data from a file from s function
6 ビュー (過去 30 日間)
古いコメントを表示
I would like to read an ASCII data from a file in an s-function. For example, the data in the file is a column array of real numbers like A(100,1) =[1;2;3;..]. I tried to read this data from a file (.dat file) in a s-function using the following code (given in an example by Jarrod Rivituso in Matlab Central file exchange http://www.mathworks.com/matlabcentral/fileexchange/13438:
static void mdlStart(SimStruct *S)
{
void** pwork = ssGetPWork(S);
FILE *datafile;
datafile = fopen("datafile.dat","r");
pwork[0] = datafile;
}
static void mdlOutputs(SimStruct *S, int_T tid)
{
//get pointer to the block's output signal
real_T *y = ssGetOutputPortSignal(S,0);
/*get pointer to array of pointers, where the first element is the address
*of the open file */
void** pwork = ssGetPWork(S);
/*read a floating point number and then the comma delimiter
*store the result in y*/
fscanf(pwork[0],"%f%*c",y);
}
This works fine. But if I try to use the values of in the array y (for example, read the data and assign it to y and then store it in z for o/p):
static void mdlOutputs(SimStruct *S, int_T tid)
{
//get pointer to the block's output signal
int ii;
real_T *z = ssGetOutputPortSignal(S,0);
real_T y[100];
/*get pointer to array of pointers, where the first element is the address
*of the open file */
void** pwork = ssGetPWork(S);
/*read a floating point number and then the comma delimiter
*store the result in y*/
fscanf(pwork[0],"%f%*c",&y);
for (ii=0;ii<100;ii++)
{z[ii]=y[ii];
}
}
Matlab crashes when I execute the corresponding file using mex (mex cfileiosfun.c)
It will be nice if someone can comment on this.
0 件のコメント
回答 (4 件)
MarkB
2011 年 3 月 29 日
I suspect that this is only a subset of the code in the S-function, so it is a little difficult to tell if things are truly missing, or if you just didn't paste them. However, it looks like you are using the "pwork" vector without actually allocating it in the first place.
You can confirm this by either attaching a debugger to the ".mex" file while it's running to see exactly which line is causing the break, or by the low-tech, old-fashioned way of commenting-out almost everything until it works, and then uncommenting things until it breaks again.
You can allocate one with the command "ssSetNumPWork", which can be called in "mdlInitializeSizes" or in "mdlSetWorkWidths". In this case, "mdlInitializeSizes" is probably the "right" place to do it. "mdlSetWorkWidths" is an optional function, which lets you set the size of your work vectors a little later, in case they depend on information that might not be available at "mdlInitializeSizes", such as a port dimensions. In this case, you know how much "pwork" you need, so you might as well do it in "mdlInitializeSizes" and not bother to write another function.
Also, make sure to close the file in "mdlTerminate".
0 件のコメント
Kaustubha Govind
2011 年 3 月 29 日
Assuming that you are using Jarrod's code almost exactly (only with the stated modification to mdlOutputs), I see two issues with your code:
- The following line in the S-function: ssSetOutputPortWidth(S, 0, 1); states that the outport port width is only 1. However, you are trying to access 100 elements, which is causing a segmentation violation since you do not own those adjacent 99 values. If you really want to the output width to be 100, you should use: ssSetOutputPortWidth(S, 0, 100);
- The other issue does not cause the crash, but is something you should consider. The statement: fscanf(pwork[0],"%f%*c",&y); states that only one floating point number is read into the variable 'y' - therefore, the remaining 99 elements in 'y' are never assigned and will hold some arbitrary values.
2 件のコメント
Kaustubha Govind
2011 年 3 月 31 日
Tushar wrote:
-----------------------
1. In the Jarrod's code, he is also using the output port width of 1 (ssSetOutputPortWidth(S, 0, 1))while the data in the file datafile.dat is (1,1000).
2. In the code by Jarrod, he read the data file datafile.dat with (1,1000) size using the fscanf(pwork[0],"%f%*c",&y);
But I cannot use the values in the y array further as done in the modified code. The c file is executed correctly without errors using mex cfileiosfun.c. But when I run the simulink model filetest.mdl, Matlab crashes.
Please comment on this.
Also it will be nice if you tell me how to read a column matrix for example (100 2). How the fscanf statement looks like for data file with column matrix (100 2)?
Kaustubha Govind
2011 年 3 月 31 日
What Jarrod does is read data incrementally from datafile.dat - since the file pointer is opened in mdlStart, each call to fscanf moves the pointer one floating point number down the stream. So, one number is read at _every_ time step. Therefore, the model would have to run through 1000 time-steps to read all the values in the file. (You must be careful about reading past EOF though).
To answer your question about reading a 100x2 matrix - you must first determine, whether you want to read a 1x2 matrix per time-step for 100 time-steps, or 100x2 at each time-step.
To read 1x2 per time-step, you can use:
real_T temp[2];
fscanf(pwork[0], "%f%*c%f%*c", temp, temp+1);
To read 100x2, I would recommend putting a for-loop with 100 iterations around the above statement.
Tushar
2011 年 4 月 1 日
1 件のコメント
Kaustubha Govind
2011 年 4 月 1 日
Could you try debugging your MEX file as described in the documentation: http://www.mathworks.com/help/techdoc/matlab_external/f32489.html. It might be useful to determine the exact line that causes the crash.
Tushar
2011 年 4 月 7 日
1 件のコメント
Kaustubha Govind
2011 年 4 月 7 日
Apologies. I gave you the wrong link for debugging. Here is how you debug S-functions: http://www.mathworks.com/support/tech-notes/1800/1819.html
You need to run the Simulink model which in turn runs the S-function (you cannot call the S-function directly from the MATLAB prompt as you can with MEX-functions).
参考
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!