Examples of how to create custom S-functions to interface C++ or C code with the Simulink coder. This allows users to compile their Simulink models with third-party software, which is not possible otherwise.
The code follows typical C++ project structure with an include dir, src dir, and an optional build file. In this example we will use CMake to ease the build process.
├── CMakeLists.txt
├── include
│ └── optical_flow_uav_velocity.hpp
├── include_directories.txt
├── LICENSE
├── link_libraries.txt
├── README.md
├── source_files.txt
├── src
│ ├── matlab_simulink_s_function.cpp
│ └── optical_flow_uav_velocity.cpp
└── test_s_function.slx
- Prepare source and include files for your custom
classand place them in the appropriate directories. - Edit
src/matlab_simulink_s_function.cppand include your custom headers. - Currently there are two ways to instantiate your custom
classobjects and access their methods.- Using persistent memory
- Using static objects
- You should specify this by
#define USE_PERSISTENT_MEMORYstatement in the top of thes_functionfile. - There are
4important functions and1optional function that needs to be implementedmdlInitializeSizes( SimStruct *S)- Here, we specify the number of inputs and outputs and set the sizes of the input and output signals.
- Furthermore, you can also specify the number of discrete sample times this s-function has, and set the number of persistent memory objects
mdlInitializeSampleTimes(SimStruct* S)- In this function, we set the sample time(s) of this s-function. Typically we use inherited sample time via
ssSetSampleTime(S, 0, INHERITED_SAMPLE_TIME);
- In this function, we set the sample time(s) of this s-function. Typically we use inherited sample time via
mdlStart(SimStruct* S)- This very important function allows us to create instances of the custom class and is only executed once ( if
#define MDL_STARTis defined). Here we can create new instances with dynamic storage duration, and store them in the persistent workers or static containers or objects created we created inmdlInitializeSizes.
- This very important function allows us to create instances of the custom class and is only executed once ( if
mdlOutputs(SimStruct* S, int_T tid)- The main function of your s-function. This is executed every simulation step, and within this block we can access ptrs to input signal, output signal, signal size info, parameter info, etc. Example implementation is provided in the
src/matlab_simulink_s_function.cpp
- The main function of your s-function. This is executed every simulation step, and within this block we can access ptrs to input signal, output signal, signal size info, parameter info, etc. Example implementation is provided in the
- (optional)
mdlTerminate(SimStruct* S)- This is the cleanup code and should delete objects created via
newstatement inC++
- This is the cleanup code and should delete objects created via
- The
SimStruct *Sis the window to the Simulink execution state and static parameters. Through theSimStructwe can access pointers to theinputs,outputs, andparameters. - Examples of how to leverage the
SimStructcan be found here simstruct examples - Finally, edit
CMakeLists.txtand modifyset(CUSTOM_PACKAGES OpenCV )with packages required by your source code. For exampleset(CUSTOM_PACKAGES pkg1 pkg2 ... ). Thenset(SRCS ${CMAKE_SOURCE_DIR}/src/matlab_simulink_s_function.cpp ${CMAKE_SOURCE_DIR}/src/optical_flow_uav_velocity.cpp) set(INCLUDE_DIRS "${CMAKE_SOURCE_DIR}/include"). For your source if the name is different, then modify them accordingly. - Create a
builddirectory and runcmake-
mkdir build && cd build cmake .. -DMATLAB_BIN_DIR=/path/to/my/matlab/binary/dir
- If everything is OK the configuration will finish and your s-function can be found in the build directory
-
- To use it in a simulink model, an example file is provided
test_s_function.slx
If you find this repo helpful, please ⭐ star the repo to show your support!