Search code examples
matlabvariablessimulinks-function

how to make constant variables being used in s-functions as tunable in matlab


i have written a simple s-function which calls a function inside a c code which models the single track model. i am using constant variables for storing mass,yaw moment of inertia,steering ratio etc. I wanted to know how to make these variables tunable. i want to create a subsystem out of my s-function and then use realtime workshop->generate s-function and select the tunable parameters from the list. but for now am not able to find any tunable parameters since i have not specified anything as tunable

this is my s-function code

#define S_FUNCTION_NAME  single_track
#define S_FUNCTION_LEVEL 2

#include "simstruc.h"


#include "single_track_func.c"


#define MDL_START  /* Change to #undef to remove function */ 
#if defined(MDL_START) 

static void mdlStart(SimStruct *S) 
  { 

    initialization();

  } 
#endif


static void mdlInitializeSizes(SimStruct *S)
{
    ssSetNumSFcnParams(S, 0);


    if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) {
        return; /* Parameter mismatch will be reported by Simulink */
    }

    if (!ssSetNumInputPorts(S, 2)) return;
    ssSetInputPortWidth(S, 0, 1);
    ssSetInputPortDirectFeedThrough(S, 0, 1);
    ssSetInputPortWidth(S, 1, 1);
    ssSetInputPortDirectFeedThrough(S, 1, 1);


    if (!ssSetNumOutputPorts(S,3)) return;
    ssSetOutputPortWidth(S, 0, 1);
    ssSetOutputPortWidth(S, 1, 1);
    ssSetOutputPortWidth(S, 2, 1);
   ssSetNumSampleTimes(S, 1);


    ssSetSimStateCompliance(S, USE_DEFAULT_SIM_STATE);


    ssSetOptions(S,
                 SS_OPTION_WORKS_WITH_CODE_REUSE |
                 SS_OPTION_EXCEPTION_FREE_CODE |
                 SS_OPTION_USE_TLC_WITH_ACCELERATOR);
}

static void mdlInitializeSampleTimes(SimStruct *S)
{
    ssSetSampleTime(S, 0, INHERITED_SAMPLE_TIME);
    ssSetOffsetTime(S, 0, 0.0);
    ssSetModelReferenceSampleTimeDefaultInheritance(S); 
}


static void mdlOutputs(SimStruct *S, int_T tid)
{
    retvale obj_b;

    InputRealPtrsType v_1 = ssGetInputPortRealSignalPtrs(S,0);               //velocity
    InputRealPtrsType delta_1 = ssGetInputPortRealSignalPtrs(S,1);         //steering angle

    real_T            *a_y_1    = ssGetOutputPortRealSignal(S,0);          //lateral acceleration           
    real_T            *psi_dot_1    = ssGetOutputPortRealSignal(S,1);      //yaw velocity   
    real_T            *beta_1    = ssGetOutputPortRealSignal(S,2);         //attitude angle   



                obj_b=singletrack((double)*(*v_1),(double)*(*delta_1));
                *a_y_1    = obj_b.a_y;          //lateral acceleration           
                *psi_dot_1 =obj_b.psi_dot;       //yaw velocity   
                *beta_1    =obj_b.beta;

}

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

and this is the logic file which has the function singletrack()

#include "single_track_func.h"

float a_1_1,a_1_2,a_2_1,a_2_2,b_1_1,b_2_1,psi_dot_prev,beta_prev;
int count;

const int cv=75000;                  //cornering stiffness front      
const int ch=150000;                //cornering stiffness rear axle          
const int m=1550;                                    //mass of the vehicle kg
const int lv=1.344;                 //distance from center of gravity to front wheel
const int lh=1.456;                 //distance from center of gravity to rear wheel  
const int theta=2800;                //yaw moment of inertia      
const int I_s=16;                    //overall steering ratio      
const float dt=0.001;

retvale singletrack(double a,double b)
{
    retvale my_obj;



    static float beta_dot=0; 
    static float psi_double_dot=0; 
    static float beta_previous=0; 
    static float psi_dot_previous=0;


    beta_previous       = beta_prev;
    psi_dot_previous    = psi_dot_prev;
    a_1_1               = ((-cv-ch)/((m)*(a)));
    a_1_2               = ((m*(a)*(a))-((ch*lh)-(cv*lv)))/(m*(a)*(a));    
    a_2_1               = (-(ch*lh)+(cv*lv))/theta;
    a_2_2               = ((-ch*lh*lh)-(cv*lv*lv))/(theta*(a));
    b_1_1               = -cv/(m*(a));
    b_2_1               = (cv*lv)/(theta);

    beta_dot            = a_1_1 * beta_previous + a_1_2 * psi_dot_previous - b_1_1*((b)/I_s);
    psi_double_dot      = a_2_1 * beta_previous + a_2_2 * psi_dot_previous + b_2_1*((b)/I_s);                             
    my_obj.beta             = beta_dot          * dt + beta_previous;
    my_obj.psi_dot          = psi_double_dot    * dt + psi_dot_previous;
    my_obj.a_y              = (a*((my_obj.psi_dot)-(beta_dot)));
    beta_prev=my_obj.beta;
    psi_dot_prev=my_obj.psi_dot; 
    return my_obj;

}
void initialization()
{
    psi_dot_prev=0;
    beta_prev=0;
}

and the corresponding .h file

#ifndef _SINGLE_TRACK_FUNC_
#define _SINGLE_TRACK_FUNC_

typedef struct retvale
{
double a_y;
double psi_dot;
double beta;
} retvale;

extern struct retvale singletrack(double a,double b);
extern void initialization();
#endif

I know i have to use ssSetSFcnParamTunable() but even after looking at examples have no idea how to do it!!

update:

i declared the variables as global real_T real_T *m_s,*cv_s,*ch_s,*lv_s,*lh_s,*theta_s,*I_s_s,*dt_s;

and added these lines of codes in my mdlInitializeSizes(). i mex it and everything is fine. but when i use the s-function block and just change the name of the s-function to the mex file the matlab crashes. also i pass these arguments as pointers to my single_track () function

ssSetNumSFcnParams(S, 8);
 m_s=mxGetPr(ssGetSFcnParam(S,0));
 cv_s=mxGetPr(ssGetSFcnParam(S,1));
 ch_s=mxGetPr(ssGetSFcnParam(S,2));
 lv_s=mxGetPr(ssGetSFcnParam(S,3));
 lh_s=mxGetPr(ssGetSFcnParam(S,4));
 theta_s=mxGetPr(ssGetSFcnParam(S,5));
 I_s_s=mxGetPr(ssGetSFcnParam(S,6));
 dt_s=mxGetPr(ssGetSFcnParam(S,7));
 ssSetSFcnParamTunable(S,0,SS_PRM_SIM_ONLY_TUNABLE);
 ssSetSFcnParamTunable(S,1,SS_PRM_SIM_ONLY_TUNABLE);
 ssSetSFcnParamTunable(S,2,SS_PRM_SIM_ONLY_TUNABLE);
 ssSetSFcnParamTunable(S,3,SS_PRM_SIM_ONLY_TUNABLE);
 ssSetSFcnParamTunable(S,4,SS_PRM_SIM_ONLY_TUNABLE);
 ssSetSFcnParamTunable(S,5,SS_PRM_SIM_ONLY_TUNABLE);
 ssSetSFcnParamTunable(S,6,SS_PRM_SIM_ONLY_TUNABLE);
 ssSetSFcnParamTunable(S,7,SS_PRM_SIM_ONLY_TUNABLE);

any idea why there is a crash?


Solution

  • For a parameter to be tunable it must be passed as an input from Simulink to your S-Function.

    This is done by specifying them in the Parameters part of the S-Function block's dialog (as a comma separated list), and using the ssSetNumSFcnParams method within the S-Function itself to tell the S-function how many parameters to expect (you currently have that set to 0).

    Also, within the S-Function you'll need to

    Then you'll need to rewrite your singletrack function so that all of the parameters are passed into it as inputs rather than being hard coded into the file.

    However, looking at the code you've given, it would be far easier to do this all as a MATLAB Function than it would as an S-Function.