Simulation Callbacks for Deployable Applications

With certain functions in Simulink Compiler, you can register callbacks during simulation. The simulink.compiler.setExternalInputsFcn and simulink.compiler.setExternalOutputsFcn functions enable you to set the values at the root inport blocks and to obtain the values at the root outport blocks at every simulation step. With the simulink.compiler.setPostStepFcn function, you can register a callback that is invoked after every simulation step, thus using it to post process the outputs.

The following example uses the simulink.compiler.setExternalOutputsFcn and the simulink.compiler.setPostStepFcn, to provide an ongoing tracing of the simulation outputs.

Deploy an App with Live Simulation Results of Lorenz System

This example shows an app that uses callbacks for simulation inputs and outputs to view the simulation of a Simulink model of Lorenz System, and is then deployed with Simulink Compiler

Open and Examine the Project File

In this example, we use a Simulink Project that contains all the files required to run this example. The project contains a Simulink Model of Lorenz System and A MATLAB App, created in App Designer that simulates the model with different input and output values. To learn more about how to create an app using the App Designer, see Create and Run a Simple App Using App Designer.

simulink.compiler.example.LorenzSystem

App Details

Open the mlapp file. You can view the code written to create this app in Code View section of the app designer. The essential part of this app is the behavior of the Simulate button. It has the following salient parts: creating the SimulationInput object, configureing it for deployment, using simulation callbacks to read the output port data and plot the data at each time step. The following section explains how these three functions are used to see the live results of the simulation in the deployed app

Creating the Simulink.SimulationInput object

In the function createSimulationInput, we define an empty Simulink.SimulationInput object for the model. We use this Simulink.SimulationInput object to set simulation callbacks and variables for the model to simulate with.

The simulation callback functions are used to register the callbacks. The simulink.compiler.setPostStepFcn function registers a callback that is invoked after every simulation step. The simulink.compiler.setExternalOuputsFcn registers a callback that dynamically processes the values for every output port at root level of a model during simulation.

We use the setVariable method of the Simulink.SimulationInput object to provide the parameter values to the app. These values for the simulation are obtained from the edit fields of the UI of the app. To enable deployment of the app, we use the simulink.compiler.configureForDeployment function. (Comment the line of code that calls simulink.compiler.configureForDeployment function for faster debugging)

function simInp = createSimulationInput(app)
            % Create an empty SimulationInput object
            simInp = Simulink.SimulationInput('LorenzSystemModel');
            
            % Specify the simulation callbacks
            simInp = simulink.compiler.setPostStepFcn(simInp, @app.postStepFcn);
            simInp = simulink.compiler.setExternalOutputsFcn(simInp, @app.processOutputs);

            % Load the parameters values from the ui edit fields
            simInp = simInp.setVariable('rho',app.rhoUIC.Value);
            simInp = simInp.setVariable('beta',app.betaUIC.Value);
            simInp = simInp.setVariable('sigma',app.sigmaUIC.Value);
            simInp = simInp.setVariable('x0',app.x0UIC.Value);
            simInp = simInp.setVariable('y0',app.y0UIC.Value);
            simInp = simInp.setVariable('z0',app.z0UIC.Value);
            
            % Configure simInp for deployment
            % DEBUG TIP: Comment out the line below for
            % faster/easier debugging when runnng in MATLAB
            simInp = simulink.compiler.configureForDeployment(simInp);
        end % createSimulationInput

Simulation Callback functions

The simulation callback functions register callbacks to enable you to read values from the output ports and to wrtie values to the root input ports. These functions register callbacks at every simulation time step thus allowing you to view live results of the simulation.

The processOutputs Callback

The simulink.compiler.setExternalOutputsFcn line refers to the function postprocressOuputs. This is a callback function that processes the values for every root output port block of model during simulation. The postprocressOuputs function is called once per port, and per the port's sample time. When postprocressOuputs function is called, it reads the values for every root outport block and caches away those values. The postStepFcn obtains the cached values to update the plot.

  function processOutputs(app, opIdx, ~, data)
            % Called during sim to process the external output port data,
            % will be called once per port per its sample hit.
            switch opIdx
                case 1
                    app.txyzBuffer.x = data;
                case 2
                    app.txyzBuffer.y = data;
                case 3
                    app.txyzBuffer.z = data;
                otherwise
                    error(['Invalid port index: ', num2str(opIdx)]);
            end            
  end

The PostStepFcn Callback

The postStepFcn is a callback function that is invoked after every simulation step. The time argument is the time for the previous simulation step. This function obtains the cached outport block values for every time, and passes those values to the updateTrace function to plot the cached values at simulation time.

function postStepFcn(app, time)
            % Called during sim after each simulation time step
            app.updateSimStats(time);
            if app.status == AppStatus.Starting
                app.switchStatus(AppStatus.Running);
                app.simStats.WallClockTimeAfterFirstStep = tic;
            end
            if app.stopRequested
                app.switchStatus(AppStatus.Stopping);
                stopRequestedID = [mfilename('class'), ':StopRequested'];
                throw(MException(stopRequestedID, 'Stop requested'));
            end
            %--------------------------------------------------------------
            app.txyzBuffer.t = time;
            x = [app.txyzBuffer.x];
            y = [app.txyzBuffer.y];
            z = [app.txyzBuffer.z];
            app.updateTrace(x, y, z);
            app.updateMarker('head', x, y, z);
            %--------------------------------------------------------------
            drawnow limitrate;
        end % postStepFcn

Test Out the Application in App Designer

Before deploying the application, ensure that the app runs in the App Designer. Click Simulate to verify that the application works by simulating the model for different values.

Compile App for Deployment

. You can use the MATLAB App Designer to compile and deploy the app. You can also use deploytool. For more information on compiling and deploying with App Designer, see Develop Apps Using App Designer, Web Apps and Application Compiler.

In this example, we compile the app, with the mcc command followed by the app name.

mcc -m LorenzSystemApp

See Also

| | | | | | | |

Related Topics