How do I get random numbers from a Simulink Coder executable?

7 views (last 30 days)
I have a simple Simulink model that consists of a Random Number block and a To File block that writes the random number to a file. I compile this using Simulink Coder and get an executable. Every time I run the executable I get the same number. I would like to find a way to make it so that every time I run the executable I get a different number.
There was a similar problem asked here which was apparently solved, though the solution was not given. I assume that the seed is being fixed during the compilation, but I can't figure out how to change that.
If anyone has a solution I would appreciate your help. David

Accepted Answer

Kaustubha Govind
Kaustubha Govind on 14 Feb 2013
It looks like the 'Seed' parameter is a non-tunable parameter, so I'm not sure how you would do this, other than manually modify the code and add a wrapper around it to get the Seed value as a command-line parameter, or perhaps compute it based on the system clock or something. (If it were a tunable parameter, you could just declare it as an ImportedExtern parameter that your wrapper code could then define)
However, in general, if you plan to use the generated code in your own application, you would probably generate a DLL from the model, instead of an executable. In case of a DLL, it is initialized once, and then executed multiple times before termination. In this case, since the seed is initialized only once, a different random value should be obtained for each execution.
  3 Comments
David
David on 14 Feb 2013
Hi Kaustubha, thank you for your answer. It is too bad the seeds get fixed. The plan is to generate an executable as a standalone application, so I think I will try hacking the code.
I guess I could also write an sfunction to give me random numbers. Either way it would appear that I'm headed to the unfamiliar world of C.
David
David on 15 Feb 2013
I wrote an sfunction to solve the issue. Now when I compile the Simulink model containing this sfunction, each time I run the executable the output is different. I'm posting the code here in case anyone has the same issue; hopefully this will be of some help. Forgive the formatting, the tool doesn't seem to handle c-code very well.
--------------------------------------------------------------
/* Define S-function a name */
#define S_FUNCTION_NAME cfun_rand_gaus
#define S_FUNCTION_LEVEL 2
/* Include definition files */
#include "simstruc.h"
#include stdlib.h
#include math.h
#include<time.h>
/* Function: mdlInitializeSizes ======================================================= */
static void mdlInitializeSizes(SimStruct *S) {
ssSetNumSFcnParams(S, 0);
if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) {
return; /* Parameter mismatch will be reported by Simulink */
}
ssSetNumContStates(S, 0);
ssSetNumDiscStates(S, 0);
if (!ssSetNumInputPorts(S, 2)) return;
ssSetInputPortWidth(S, 0, 1);
ssSetInputPortDirectFeedThrough(S, 0, 1);
ssSetInputPortWidth(S, 1, 1);
ssSetInputPortDirectFeedThrough(S, 1, 1);
if (!ssSetNumOutputPorts(S,1)) return; ssSetOutputPortWidth(S, 0, 1);
ssSetNumPWork(S,1);
ssSetNumSampleTimes(S, 1);
/* Take care when specifying exception free code - see sfuntmpl.doc */
ssSetOptions(S, SS_OPTION_EXCEPTION_FREE_CODE);
}
static void mdlInitializeSampleTimes(SimStruct *S)
{ ssSetSampleTime(S, 0, INHERITED_SAMPLE_TIME);
ssSetOffsetTime(S, 0, 0.0);
}
#define MDL_START /* Change to #undef to remove function */
#if defined(MDL_START)
/* Function: mdlStart =======================================================
*/
static void mdlStart(SimStruct *S)
{
srand ( time(NULL) );
}
#endif /* MDL_START */
/* Function: mdlOutputs ======================================================= */
static void mdlOutputs(SimStruct *S, int_T tid)
{
InputRealPtrsType xmean = ssGetInputPortRealSignalPtrs(S,0);
InputRealPtrsType xmu = ssGetInputPortRealSignalPtrs(S,1);
real_T *val_rand = ssGetOutputPortRealSignal(S,0);
/* Gaussian RNG based on the method discussed in Knuth and due originally to Marsaglia */
/* -reference code found here: http://c-faq.com/lib/gaussian.html*/
static double v1, v2, rsq;
static int phase = 0;
double gset;
if(phase == 0) {
do {
double ran1 = (double)rand() / RAND_MAX;
double ran2 = (double)rand() / RAND_MAX;
v1 = 2 * ran1 - 1;
v2 = 2 * ran2 - 1;
rsq = v1 * v1 + v2 * v2;
} while(rsq >= 1 rsq == 0);
gset = v1 * sqrt(-2 * log(rsq) / rsq);
} else {
gset = v2 * sqrt(-2 * log(rsq) / rsq);
}
phase = 1 - phase;
val_rand[0] = *xmean[0] + *xmu[0] * gset;
}
/*=============================*
* Required S-function trailer *
*=============================*/
static void mdlTerminate(SimStruct *S){}
#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

Sign in to comment.

More Answers (1)

Azzi Abdelmalek
Azzi Abdelmalek on 14 Feb 2013
Edited: Azzi Abdelmalek on 14 Feb 2013
You create a mat file fic_seed.mat
seedv=1:300
save fic_seed seedv
In model properties-callbacks-Init Fcn write this code
v=load('fic')
v=v.v;
val=v(1);
v(1)=[];
save fic v
set_param('yoursimulinkmodelname/Random Number','seed',num2str(val))
Random Number is the name of your random block, Check if it's the same name in your simulink model.
  1 Comment
Kaustubha Govind
Kaustubha Govind on 14 Feb 2013
Azzi: Since David wants to do this in the generated code, the InitFcn callback won't help unfortunately, since it is only called within the Simulink environment.

Sign in to comment.

Categories

Find more on General Applications in Help Center and File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!