📄 scsb_sfun.c~
字号:
} } /* If there is a clock pulse, update controller state and output. */ z_and_u = ssGetDiscStates(S); use_sd = ssGetIWorkValue(S,IWORK_USE_SD); if (use_sd) { nz = (int_T) *mxGetPr(ssGetSFcnParam(S,PARAM_NZ)); nup = (int_T) *mxGetPr(ssGetSFcnParam(S,PARAM_NUP)); sd_port = ssGetIWorkValue(S,IWORK_SD_PORT); clock_value = (int_T) **ssGetInputPortRealSignalPtrs(S,sd_port); if ((ssGetIWorkValue(S,IWORK_LAST_SD) < .5)&&(clock_value > .5)) { /* If the clock signal goes hi, update the controller. */ ssSetIWorkValue(S,IWORK_LAST_SD,clock_value); computeDerivativeAndReset(S); memcpy(z_and_u,ssGetPWorkValue(S,PWORK_Z),nz*sizeof(real_T)); memcpy(&z_and_u[nz],ssGetPWorkValue(S,PWORK_U_OUT),nup*sizeof(real_T)); /* Update block output since state has changed. */ mdlOutputs(S,tid); } else if ((ssGetIWorkValue(S,IWORK_LAST_SD) > .5)&&(clock_value < .5)) { ssSetIWorkValue(S,IWORK_LAST_SD,clock_value); } } /* Check if simulation should be stopped. */ mxCI = ssGetSFcnParam(S,PARAM_AR_CI); if (!mxIsEmpty(mxCI)) { nAR = mxGetM(mxCI); CI = mxGetPr(mxCI); dI = mxGetPr(ssGetSFcnParam(S,PARAM_AR_DI)); /* Compute product CI*x for analysis region. */ for (i = 0; i < nAR; i++) { /* Multiply ith row of CI with x */ prod_i = 0; /* If sampled-data analysis is to be performed, analysis region includes controller state dimensions. */ if (use_sd) { for (j = 0; j < nx-1; j++) { prod_i += CI[j*nAR+i]*x[j]; } for (j = nx-1; j < nx-1+nz;j++) { prod_i += CI[j*nAR+i]*z_and_u[j-(nx-1)]; } } else { for (j = 0; j < nx-1; j++) { prod_i += CI[j*nAR+i]*x[j]; } } /* if CIi*x > dIi, then state is out of analysis region. */ if (prod_i > dI[i]) { /* Stop simulation if state is outside of analysis region. */ ssSetStopRequested(S,1); ssWarning(S,"System has left the user-defined Analysis Region. Simulation halted."); ssSetErrorStatus(S,"System has left the user-defined Analysis Region. Simulation halted. "); } } }}#endif /* MDL_UPDATE */#define MDL_DERIVATIVES/* Function: mdlDerivatives ================================================= * Abstract: * In this function, you compute the S-function block's derivatives. * The derivatives are placed in the derivative vector, ssGetdX(S). */static void mdlDerivatives(SimStruct *S){ /* Call the SCSB wrapper function to compute state derivative and state reset vectors. */ int_T nx; nx = (int_T) *mxGetPr(ssGetSFcnParam(S,PARAM_NX)); computeDerivativeAndReset(S); /* Copy the derivative computed above from pointer work vector. */ memcpy(ssGetdX(S),ssGetPWorkValue(S,PWORK_X_DOT), (nx+1)*sizeof(real_T));}#define MDL_ZERO_CROSSINGS/* Function: mdlZeroCrossings =============================================== * Abstract: * If your S-function has registered CONTINUOUS_SAMPLE_TIME and there * are signals entering the S-function or internally generated signals * which have discontinuities, you can use this method to locate the * discontinuities. When called, this method must update the * ssGetNonsampleZCs(S) vector. */static void mdlZeroCrossings(SimStruct *S){ real_T *zcSignals; int_T use_reset,use_sd,reset_value,reset_port,sd_port,sd_value; use_reset = ssGetIWorkValue(S,IWORK_USE_RESET); use_sd = ssGetIWorkValue(S,IWORK_USE_SD); if (use_reset) { reset_port = ssGetIWorkValue(S,IWORK_RESET_PORT); /* Assume that the reset signal changes between discrete values of 0 and 1. Thus, we set the zero crossing detection at 0.5 */ reset_value = (int_T) **ssGetInputPortRealSignalPtrs(S,reset_port); zcSignals = ssGetNonsampledZCs(S); zcSignals[0] = (real_T) reset_value - 0.5; if (use_sd) { sd_port = ssGetIWorkValue(S,IWORK_SD_PORT); /* Assume that the SD signal changes between discrete values of 0 and 1. Thus, we set the zero crossing detection at 0.5 */ sd_value = (int_T) **ssGetInputPortRealSignalPtrs(S,sd_port); zcSignals = ssGetNonsampledZCs(S); zcSignals[1] = (real_T) sd_value - 0.5; } } else if (use_sd) { sd_port = ssGetIWorkValue(S,IWORK_SD_PORT); /* Assume that the SD signal changes between discrete values of 0 and 1. Thus, we set the zero crossing detection at 0.5 */ sd_value = (int_T) **ssGetInputPortRealSignalPtrs(S,sd_port); zcSignals = ssGetNonsampledZCs(S); zcSignals[0] = (real_T) sd_value - 0.5; }}/* 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. * * Suppose your S-function allocates a few few chunks of memory in mdlStart * and saves them in PWork. The following code fragment would free this * memory. * { * int i; * for (i = 0; i<ssGetNumPWork(S); i++) { * if (ssGetPWorkValue(S,i) != NULL) { * free(ssGetPWorkValue(S,i)); * } * } * } */static void mdlTerminate(SimStruct *S){ /* Free mxArrays and other arrays that we allocated in mdlStart. */ free(ssGetPWorkValue(S,PWORK_X_DOT)); free(ssGetPWorkValue(S,PWORK_X_RESET)); free(ssGetPWorkValue(S,PWORK_Z)); free(ssGetPWorkValue(S,PWORK_U_OUT));}/*========================* * Other helper functions * *========================*//* Function: mxIsVector ======================================================= * Abstract: * Return 1 if the given mxArray is a vector of length L, i.e. the * mxArray has the size of 1 in one dimension and the size L in the * other dimension. Return 0 otherwise. */int_T mxIsVector(mxArray *A,int_T L){ int_T m,n,st; m = mxGetM(A); n = mxGetN(A); st = ((m == 1) && (n == L)) || ((m == L) && (n == 1)); return st;}/* Function: controller_state_update ========================================== Abstract: Use the difference equations specified in the user-defined m-file to update the state of the discrete-time controller.*/ /* Function: computeDerivativeAndReset ======================================== * Abstract: * Call the SCSB wrapper function, which, in turn, calls the * use-defined switching function to compute the state derivative * and reset vectors given the current state x and discrete input * u. The results are stored in memory allocated inside the pointer * work vector. */void computeDerivativeAndReset(SimStruct *S){ mxArray *ArgIn[9]; mxArray *ArgOut[2]; mxArray *x_dot_temp; int_T i,nx,nz,nu,nup,u_port,use_sd,use_reset,buflen; real_T *mxUPr,*z_and_u,*u,*z_idx,one,*u_idx,*x_in,*timer,*x_dot; InputRealPtrsType uPtrs; use_reset = ssGetIWorkValue(S,IWORK_USE_RESET); use_sd = ssGetIWorkValue(S,IWORK_USE_SD); ArgIn[0] = ssGetSFcnParam(S,PARAM_SWFUNC); /* Copy x vector to mxArray to be used as an argument to the wrapper function. */ nx = ssGetNumContStates(S); if (use_sd) { nz = (int_T) *mxGetPr(ssGetSFcnParam(S,PARAM_NZ)); ArgIn[1] = mxCreateDoubleMatrix(nx-1+nz,1,mxREAL); x_in = mxGetPr(ArgIn[1]); memcpy(x_in,ssGetContStates(S),(nx-1)*sizeof(real_T)); memcpy(&x_in[nx-1],ssGetDiscStates(S),nz*sizeof(real_T)); } else { nz = 0; ArgIn[1] = mxCreateDoubleMatrix(nx-1,1,mxREAL); x_in = mxGetPr(ArgIn[1]); memcpy(x_in,ssGetContStates(S),(nx-1)*sizeof(real_T)); } /* Copy u vector to mxArray to be used as an argument to the wrapper function. */ nu = (int_T) *mxGetPr(ssGetSFcnParam(S,PARAM_NU)); ArgIn[2] = mxCreateDoubleMatrix(nu,1,mxREAL); if (nu > 0) { u_port = ssGetIWorkValue(S,IWORK_U_PORT); uPtrs = ssGetInputPortRealSignalPtrs(S,u_port); mxUPr = mxGetPr(ArgIn[2]); for (i = 0; i < nu; i++) { mxUPr[i] = *uPtrs[i]; } } ArgIn[3] = ssGetSFcnParam(S,PARAM_P0); ArgIn[4] = ssGetSFcnParam(S,PARAM_USE_RESET); ArgIn[5] = ssGetSFcnParam(S,PARAM_USE_PARAM); ArgIn[6] = ssGetSFcnParam(S,PARAM_USE_SD); if (use_sd) { nup = (int_T) *mxGetPr(ssGetSFcnParam(S,PARAM_NUP)); z_and_u = ssGetDiscStates(S); u = &z_and_u[nz]; ArgIn[7] = mxCreateDoubleMatrix(nup,1,mxREAL); memcpy(mxGetPr(ArgIn[7]),u,nup*sizeof(real_T)); } else { ArgIn[7] = mxCreateDoubleMatrix(1,1,mxREAL); } /* Pass the simulation time to the user-defined m-file. This will allow the simulation of time varying systems.*/ ArgIn[8] = mxCreateDoubleMatrix(1,1,mxREAL); timer = mxGetPr(ArgIn[8]); memcpy(timer,&ssGetContStates(S)[nx-1],(1)*sizeof(real_T)); /* Call the SCSB wrapper function, which calls the switching function to return the derivative and the reset vectors. [msg,x_dot,x_reset] = swfunc_wrapper(swfunc,x,u,p0,use_reset,use_param) */ mexCallMATLAB(2,ArgOut,9,ArgIn,"scsb_wrapper"); mxDestroyArray(ArgIn[1]); mxDestroyArray(ArgIn[2]); mxDestroyArray(ArgIn[7]); mxDestroyArray(ArgIn[8]); /* Perform error checking to check data integrity and prevent possible segmentation fault error. */ /* Check if derivative is a vector of class 'double' and of appropriate length. */ if (!mxIsDouble(ArgOut[0])) { ssSetErrorStatus(S,"Switching function must return derivative vector of class 'double'. "); mxDestroyArray(ArgOut[0]); mxDestroyArray(ArgOut[1]); return; } if (use_sd) { if (!mxIsVector(ArgOut[0],nx-1+nz+nup)) { ssSetErrorStatus(S,"Switching function must return derivative vector with appropriate length. "); mxDestroyArray(ArgOut[0]); mxDestroyArray(ArgOut[1]); return; } } if (!use_sd) { if (!mxIsVector(ArgOut[0],nx-1)) { ssSetErrorStatus(S,"Switching function must return derivative vector with appropriate length. "); mxDestroyArray(ArgOut[0]); mxDestroyArray(ArgOut[1]); return; } } if (use_reset) { /* Check if reset is a vector of class 'double' and of appropriate length. */ if (!mxIsDouble(ArgOut[1])) { ssSetErrorStatus(S,"Switching function must return reset vector of class 'double'. "); mxDestroyArray(ArgOut[0]); mxDestroyArray(ArgOut[1]); return; } if (!mxIsVector(ArgOut[1],nx-1)) { ssSetErrorStatus(S,"Switching function must return reset vector with appropriate length. "); mxDestroyArray(ArgOut[0]); mxDestroyArray(ArgOut[1]); return; } } /* If everything checks out, copy output arguments into memory allocated in the pointer work vector. */ buflen = nx*sizeof(real_T); x_dot_temp = mxCreateDoubleMatrix(nx,1,mxREAL); x_dot = mxGetPr(x_dot_temp); memcpy(x_dot,mxGetPr(ArgOut[0]),(nx-1)*sizeof(real_T)); one = 1; memcpy(&x_dot[nx-1],&one,sizeof(real_T)); memcpy(ssGetPWorkValue(S,PWORK_X_DOT),mxGetPr(x_dot_temp),buflen); if (use_reset) { memcpy(ssGetPWorkValue(S,PWORK_X_RESET),mxGetPr(ArgOut[1]),(nx-1)*sizeof(real_T)); } mxDestroyArray(x_dot_temp); if (use_sd) { z_idx = mxGetPr(ArgOut[0]); z_idx = &z_idx[nx-1]; u_idx = mxGetPr(ArgOut[0]); u_idx = &u_idx[nx-1+nz]; memcpy(ssGetPWorkValue(S,PWORK_Z),z_idx,nz*sizeof(real_T)); memcpy(ssGetPWorkValue(S,PWORK_U_OUT),u_idx,nup*sizeof(real_T)); } /* Free the mxArrays returned by the above MATLAB function call. */ mxDestroyArray(ArgOut[0]); mxDestroyArray(ArgOut[1]); return;}#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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -