2016-01-18 33 views
0

我知道有可能編寫Level-2 MATLAB具有可變大小信號的S函數。 是否也可以在C MEX S函數中做到這一點?在C MEX S函數中可以使用可變尺寸信號嗎?

我的數據在每個時間步有不同的大小。這個要求源於一個壓縮塊,它獲得一個固定大小的信號(2D)作爲其輸入。然而,輸出信號(1D/Vector)在每個mdlOutput()更改其大小。

+1

http://www.mathworks.com/help/simulink/ug/s-functions-using-variable-size-signals.html – Daniel

+0

一般情況下,該怎麼辦使用C-mex完成S函數是用其他語言(包括m代碼)編寫的S函數可以完成的超級集合。所以是的,這是可能的。 @丹尼爾的鏈接是一個很好的起點。 –

+0

非常感謝。起點非常好! –

回答

1

該問題的意見已經回答了: 是的,這是可能的!

這裏我舉的例子:

// Required S-Function header 
#define S_FUNCTION_LEVEL 2 
#define S_FUNCTION_NAME sfunc_varsignal 

#include "simstruc.h" 

enum {INPUT_PORT = 0, NUM_INPUT_PORTS}; 
enum {OUTPUT_PORT = 0, NUM_OUPUT_PORTS};  

/** 
* "Specify the number of inputs, outputs, states, parameters, and other 
* characteristics of the C MEX S-function" 
*/ 
static void mdlInitializeSizes(SimStruct* S) 
{ 
    boolean_T boolret; 
    int_T intret; 

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

    // Input port 
    boolret = ssSetNumInputPorts(S, NUM_INPUT_PORTS); 
    if (boolret == 0) 
    { 
     return; 
    }  
    ssSetInputPortDirectFeedThrough(S, INPUT_PORT, 1);  
    intret = ssSetInputPortDimensionInfo(S, INPUT_PORT, DYNAMIC_DIMENSION); 
    if (intret == 0) 
    { 
     ssWarning(S, "Input dimensions could not be set."); 
    } 
    _ssSetInputPortNumDimensions(S, INPUT_PORT, 1);  

    // Output port 
    boolret = ssSetNumOutputPorts(S, NUM_OUPUT_PORTS); 
    if (boolret == 0) 
    { 
     return; 
    } 

    intret = ssSetOutputPortDimensionInfo(S, OUTPUT_PORT, DYNAMIC_DIMENSION); 

    if (intret == 0) 
    { 
     ssWarning(S, "Output dimensions could not be set."); 
    } 
    _ssSetOutputPortNumDimensions(S, OUTPUT_PORT, 1); 


    // Sample Times 
    ssSetNumSampleTimes(S, 1); 

    // Dimension Modes of the Ports 
    ssSetInputPortDimensionsMode(S, INPUT_PORT, INHERIT_DIMS_MODE); 
    ssSetOutputPortDimensionsMode(S, OUTPUT_PORT, INHERIT_DIMS_MODE); 
    // This is required for any kind of variable size signal: 
    ssSetInputPortRequiredContiguous(S, INPUT_PORT, true); 

    ssSetOptions(S, 0); 

    // Note: In the doc of ssSetOutputPortWidth it is wriiten: 
    // "If the width is dynamically sized, the S-function must provide 
    // mdlSetOutputPortDimensionInfo and mdlSetDefaultPortDimensionInfo 
    // methods to enable the signal dimensions to be set correctly 
    // during signal propagation." 
    // However in the example sfun_varsize_concat1D this methods are 
    // not present. The function _ssSetOutputPortNumDimensions() may be sufficient 
    // This usgae of this function is copied from the example sfcndemo_varsize  
} 

#if defined(MATLAB_MEX_FILE)  
/** 
* "Set the width of an input port that accepts 1-D (vector) signals" 
*/ 
#define MDL_SET_INPUT_PORT_WIDTH 
static void mdlSetInputPortWidth(SimStruct* S, int_T port, int_T width) 
{ 
    // Set to the sugessted width (e.g. the output width 
    // from the connected block) 
    ssSetInputPortWidth(S, port, width); 

    // Check if the setting was sucessful 
    if (ssGetInputPortWidth(S, INPUT_PORT) != DYNAMICALLY_SIZED) 
    { 
     ssSetOutputPortWidth(S, OUTPUT_PORT, width); 
    } 
    return; 
}  

/** 
* "Set the width of an output port that outputs 1-D (vector) signals" 
*/ 
#define MDL_SET_OUTPUT_PORT_WIDTH 
static void mdlSetOutputPortWidth(SimStruct* S, int_T port, int_T width) 
{ 
    // Nothing here, but its required since the output port is set as 
    // dynamically sized. But its size is set in mdlSetInputPortWidth() 
    UNUSED_ARG(S); 
    UNUSED_ARG(port); 
    UNUSED_ARG(width); 
    return; 
}  
#endif //defined(MATLAB_MEX_FILE) 

/** 
* "Specify the sample rates at which this C MEX S-function operates" 
*/ 
static void mdlInitializeSampleTimes(SimStruct* S) 
{ 
    ssSetSampleTime(S, 0, INHERITED_SAMPLE_TIME); 
    ssSetOffsetTime(S, 0, 0.0); 
    ssSetModelReferenceSampleTimeDefaultInheritance(S); 
} 

/** 
* "Compute the signals that this block emits." 
*/ 
static void mdlOutputs(SimStruct* S, int_T tid) 
{ 
    UNUSED_ARG(tid); 

    const real_T* insignal = ssGetInputPortRealSignal(S, INPUT_PORT); 
    auto width = static_cast<const int>(insignal[0]); 
    // This function does the trick: 
    ssSetCurrentOutputPortDimensions(S, OUTPUT_PORT, 0, width); 
    // newWidth should be width 
    int_T newWidth = ssGetCurrentOutputPortDimensions(S, OUTPUT_PORT, 0 /* dimension ID */); 

    real_T* outsignal = ssGetOutputPortRealSignal(S, OUTPUT_PORT); 

    for (int i = 0; i < newWidth; i++) 
    { 
     *outsignal++ = i+1; 
    } 
} 

/** 
* "Perform any actions required at termination of the simulation" 
*/ 
static void mdlTerminate(SimStruct* S) 
{ 
    UNUSED_ARG(S); 
} 

// 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 
相關問題