{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# dllModel - Python Runner Notebook\n", "\n", "![](dllModel.png)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Python Setup\n", "\n", "This is the type setup required before running the model.\n", "\n", "For readability the `rtwtypes.h` is converted to [`rtwtypes.py`](https://github.com/dapperfu/python_SimulinkDLL/blob/master/Example1/rtwtypes.py) and in a separate file." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "from rtwtypes import *" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### ```dllModel.h``` in Python\n", "\n", "Using `ctypes.Structure` re-create all of the `dllModel.h` structure." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "class B_dllModel_T(ctypes.Structure):\n", " \"\"\"Simulink.Parameter SimulinkGlobals\"\"\"\n", "\n", " _fields_ = [\n", " (\"SimulationSignal1\", real_T),\n", " (\"SignalOut3\", real32_T),\n", " (\"SignalOut2\", uint16_T),\n", " ]\n", "\n", "\n", "class ExtU_dllModel_T(ctypes.Structure):\n", " \"\"\"SimulinkGlobal Inputs to Model\"\"\"\n", "\n", " _fields_ = [(\"SignalIin2\", uint16_T)]\n", "\n", "\n", "class ExtY_dllModel_T(ctypes.Structure):\n", " \"\"\"SimulinkGlobal Outputs from Model\"\"\"\n", "\n", " _fields_ = [(\"OutputPort2\", real32_T)]\n", "\n", "\n", "class P_dllModel_T(ctypes.Structure):\n", " \"\"\"SimulinkGlobal Parameters\"\"\"\n", "\n", " _fields_ = [(\"K2\", uint16_T)]\n", "\n", "\n", "class Timing(ctypes.Structure):\n", " \"\"\" Timing STructure\"\"\"\n", "\n", " _fields_ = [\n", " (\"clockTick0\", uint32_T),\n", " (\"clockTickH0\", uint32_T),\n", " ]\n", "\n", "\n", "class tag_RTM_dllModel_T(ctypes.Structure):\n", " \"\"\" tag RTM \"\"\"\n", "\n", " _fields_ = [\n", " (\"errorStatus\", ctypes.c_char_p),\n", " (\"Timing\", Timing),\n", " ]" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "import os\n", "\n", "dll_path = os.path.abspath(\"dllModel_win64.dll\")\n", "dll = ctypes.windll.LoadLibrary(dll_path)" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "# Block parameters (default storage)\n", "dllModel_P = P_dllModel_T.in_dll(dll, \"dllModel_P\")\n", "# Block signals (default storage)\n", "dllModel_B = B_dllModel_T.in_dll(dll, \"dllModel_B\")\n", "# External inputs (root inport signals with default storage)\n", "dllModel_U = ExtU_dllModel_T.in_dll(dll, \"dllModel_U\")\n", "# External outputs (root outports fed by signals with default storage)\n", "dllModel_Y = ExtY_dllModel_T.in_dll(dll, \"dllModel_Y\")" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "\"\"\"\n", " * Exported Global Signals\n", " *\n", " * Note: Exported global signals are block signals with an exported global\n", " * storage class designation. Code generation will declare the memory for\n", " * these signals and export their symbols.\n", " \"\"\"\n", "SignalIn = real32_T.in_dll(dll, \"SignalIn\")\n", "SimulationSignal2 = real_T.in_dll(dll, \"SimulationSignal2\")\n", "SignalOut = real32_T.in_dll(dll, \"SignalOut\")\n", "\"\"\"\n", " * Exported Global Parameters\n", " *\n", " * Note: Exported global parameters are tunable parameters with an exported\n", " * global storage class designation. Code generation will declare the memory for\n", " * these parameters and exports their symbols.\n", "\"\"\"\n", "K = real32_T.in_dll(dll, \"K\")\n", "\n", "# Model entry point functions\n", "dllModel_initialize = dll.dllModel_initialize\n", "dllModel_step = dll.dllModel_step\n", "dllModel_terminate = dll.dllModel_terminate\n", "\n", "# Real-time Model object\n", "dllModel_M = ctypes.POINTER(tag_RTM_dllModel_T).in_dll(dll, \"dllModel_M\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Running The Model." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Before running the model you will need to run the model init function." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "dllModel_initialize();" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Take an initial step into the model, function returns the current step number." ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "1" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dllModel_step()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Inspect the simulation time, both in the Block signal structure and in the global variable." ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[0.0, c_double(0.0)]" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "[dllModel_B.SimulationSignal1, SimulationSignal2]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Take another step and inspect the simulation time again.\n", "\n", "0.1s matches the discrete step size specified in the model.\n", "\n", "![](dllModel_solver.png)\n" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[0.1, c_double(0.1)]" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dllModel_step()\n", "[dllModel_B.SimulationSignal1, SimulationSignal2]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Manipulating Signals\n", "\n", "& Reading Outputs\n", "\n", "![](dllModel.png)" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "c_float(0.0)" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "SignalIn.value = float(2)\n", "SignalOut" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "c_float(2.0)" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dllModel_step()\n", "SignalOut" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[0, 2.0, c_float(2.0)]" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "[dllModel_B.SignalOut2, dllModel_B.SignalOut3, SignalOut]" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [], "source": [ "dllModel_U.SignalIin2 = 1" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[2, 4.0, c_float(2.0)]" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dllModel_step()\n", "[dllModel_B.SignalOut2, dllModel_B.SignalOut3, SignalOut]" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "4" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dllModel_M.contents.Timing.clockTick0" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [], "source": [ "step = dllModel_step()\n", "assert dllModel_M.contents.Timing.clockTick0 == step" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.9.1" } }, "nbformat": 4, "nbformat_minor": 4 }