Help building standalone exe from slx model that uses TCP/IP Receive Block from Instrument Control Toolbox

22 views (last 30 days)

High level question up front:

Should I be using the TCP/IP Receive block from the Instrument Control Toolbox when building a standalone app from a Simulink model to communicate over ‘localhost’ (127.0.0.1) with another app built in C#/Unity or are there other alternatives I should consider? I only need my Simulink app to act as the TCP client and receive data only.

Details:

I’ve run into a confusing issue when trying to build a standalone app from a Simulink model that uses the TCP/IP Receive block from the Instrument Control Toolbox. I have successfully built a standalone executable using the “mcc” command and I can run the executable without issue on my (first) PC which has a full Matlab R2023a licensed install plus Matlab runtime installed. Now, the issue comes when I try to run the executable on another (second) PC that has the correct Matlab runtime version R2023a (9.14) but does not have matlab installed. I have been able to run standalone executables on the second PC (that don’t have the TCP/IP Receive block) with the same setup for a few months now so I’m confident the issue is with trying to run a standalone executable containing the TCP/IP Receive block.

On the second PC, I get the error when trying to run the executable as shown in the attached image. I tried to capture the error with a try/catch ME statement and print the ME text and got the text shown in the second attached image.

I inspected the C/C++ Code Generation documentation for the TCP/IP Receive block which states the following:

C/C++ Code Generation Generate C and C++ code using Simulink® Coder™. This block generates platform-specific code for the host machine's platform only (Windows®, macOS, Linux®). Set the Device vendor and Device type in Model Settings > Hardware Implementation. You must also select Support long long under Device details. You can only use a single conversion specifier for the ASCII format string parameter.

I didn’t know how to properly set the Device vendor and Device type but did try selecting “Support long long” but that didn’t fix the issue.

I’m also wondering if the second PC had a full matlab install if the executable would work? But why wouldn’t it work with just Matlab Runtime?

Lastly, I was trying to implement in Simulink a Matlab function block that calls tcpclient but was running into an error that “The current BuildConfig has not been set”.

  1 Comment
Brad
Brad on 8 Dec 2023
For more context...
I am required by my employer to produce a standalone executable that acts as a TCP/IP client that receives data packets from a TCP/IP server sent as a uint8 vector from an external app built in C#/Unity. Both my simulink app executable and the C#/Unity app need to both run at the same time on a windows PC where they communicate over address 127.0.0.1 or localhost. The combined software package needs to be distributed to multiple customers around the globe. The C#/Unity app runs fine when users just drag and drop that package into the target windows PC I assume because it includes all required packages/libraries.
For more context we are designing a flight simulator where the aero/flight physics equations are done in simulink and we already have it setup to communicate with the C#/Unity app (which handles visualization of an aircraft) over UDP connection in a way where it works as a standalone app. The feature we are trying to add is to handle user triggered “events” over TCP such as when the user starts a session, pauses, resumes, restarts, and exits a session. I think as a workaround we can handle events over udp but in the long term for our system to be distributed to many customers and have a reliable event system, we would prefer to use TCP driven events.
I had also looked into using a matlab function block that calls the ‘tcpclient’ function but got an error when trying to run my model in simulink that states “The current BuildConfig has not been set”. Any idea how to address that?

Sign in to comment.

Answers (1)

akshatsood
akshatsood on 8 Jan 2024
Edited: akshatsood on 8 Jan 2024
Hi @Brad,
I understand that you are facing issues in executing the standalone application on your system. Prior to reflecting thoughts on the high-level question "Should I be using the TCP/IP Receive block from the Instrument Control Toolbox ...", it would be beneficial to address the message "Rapid accelerator process crashed while simulating the model" when trying to execute the standalone app on your second PC.
Debugging "Rapid accelerator process crashed while simulating the model"
First take on this message would be disabling the anti-virus software on your system to check whether it is blocking the process or not. Depending upon the anti-virus software in your system, you can either put it off and run the executable or add the executable to its permission list (if any for your anti-virus software) so that it is not excluded.
In reference to the screeshot attached, in where you are catching the MException, the "stack" property of "MException" object captures the Stack Trace information which if you could please share would be helpful in having a more clear view on the issue.
Selecting Device Type and Device Vendor
In respose to your confusion pertaining to selecting the appropraite Device Type and Device Vendo, please refer to the following documentation pages for a brief overview on the available options.
Will installing MATLAB fix the issue?
The documentaiton page attached below clearly states that "MATLAB® Runtime contains the libraries needed to run compiled MATLAB applications on a target system without a licensed copy of MATLAB." Hence, installing MATLAB might not be the one-shot solution to the problem.
“The current BuildConfig has not been set” in MATLAB Function block
When you attempt to extract output from the MATLAB Function block, it participates in size and type propagation during which it does not provide the "BuildConfig", which includes settings that are sometimes crucial for code generation for "tcpclient", hence the error.
A possible workaround which might help address this could be by assigning all the output variables with their appropriate types before calling "tcpclient". For instance, if you have two ouptuts 'A' and 'B' from the MATLAB Function block, then before initiating a call to "tcpclient", make sure to define 'A' and 'B' with the appropriate data types. An example code snippet is as follows
% earlier implementation
function y = fcn()
persistent client
if isempty(client)
client = tcpclient("127.0.0.1", 4000);
end
y=1;
end
% proposed implementation
function y = fcn()
y = 0; % defining the correct type
persistent client
if isempty(client)
client = tcpclient("127.0.0.1", 4000);
end
y=1;
end
I hope this helps.
  16 Comments
Brad
Brad on 29 Jan 2024
Edited: Brad on 29 Jan 2024
Alright I figured out how to pass simTime into setExternalInputsFcn and getExternalInputs. See my modified code below:
% clear; close all; clc
function tcp_app()
dt = 0.005;
model = 'tcpClient_model';
% creating a SimulationInput object for your model
simIn = Simulink.SimulationInput(model);
% configuring for deployment
simulink.compiler.configureForDeployment(simIn);
% set rapid accel mode
simIn = simIn.setModelParameter('SimulationMode', 'Rapid');
simIn = simIn.setModelParameter('RapidAcceleratorUpToDateCheck', 'off');
% Set pacing rate and stop time
simIn = simIn.setModelParameter('EnablePacing', 'on');
simIn = simIn.setModelParameter('PacingRate', 1.04);
simIn = simIn.setModelParameter('StopTime','0.1');
% establish the TCP client connection on port 8200
tcpipClient = tcpclient('localhost', 8200);
% Drive external inputs to model with function
simIn = simulink.compiler.setExternalInputsFcn(simIn, @(pn, simTime) getExternalInputs(pn, simTime));
% Simulate model
simOut = sim(simIn);
save("simOut")
figure(1);
for ii = 1:2
subplot(2,1,ii)
plot(simOut.logsout{ii}.Values)
grid minor
end
saveas(figure(1), 'plotOut', 'fig')
% define the external input function
function extInputs = getExternalInputs(~, simTime)
if tcpipClient.NumBytesAvailable > 0
% reading 22 bytes of data from the TCP client
data = read(tcpipClient, 22, 'uint8');
% processing the data using typecast
Var_1 = typecast(data(1), 'int8');
Var_2 = typecast(data(2:5),'int32');
Var_3 = typecast(data(6:9),'int32');
Var_4 = typecast(data(10:13),'int32');
Var_5 = typecast(data(14:21),'double');
Var_6 = typecast(data(22),'int8');
else
Var_1 = int8(0);
Var_2 = int32(0);
Var_3 = int32(0);
Var_4 = int32(0);
Var_5 = double(0);
Var_6 = int8(0);
end
% passing the processed variables into the model
% extInputs = {Var_1, Var_2, Var_3, Var_4, Var_5, Var_6};
% extInputs = [Var_1, Var_6];
extInputs = Var_3;
% disp(extInputs)
end
end
I'm just having extInputs be of size 1 for now.
Compiling with "mcc", the exe runs and I can push data through the one input (see screenshot for simplified model) but it's clearly waiting to step the entire model until it receives a TCP packet of data (which the Python script is pushing every 1 second of real-time). This means the TCP client is running in "blocking mode" still.
Oh and we can tell my sim is running much slower than clock time because I set in my script:
simIn = simIn.setModelParameter('StopTime','0.1');
This means my sim runs for 0.1 seconds of simulation time but the printout of the following property of the simOut object indicates it's taking 2.3 seconds of "ExecutionElapsedWallTime" to actually compute 0.1 seconds of simulation time:
>> simOut.SimulationMetadata.TimingInfo
ans =
struct with fields:
WallClockTimestampStart: '2024-1-29 13:18:57'
WallClockTimestampStop: '2024-1-29 13:18:59'
InitializationElapsedWallTime: 0.3040
ExecutionElapsedWallTime: 2.3270
TerminationElapsedWallTime: 0.0090
TotalElapsedWallTime: 2.6400
Brad
Brad on 29 Jan 2024
Now, trying with multiple inputs, I changed extInputs to be:
extInputs = {Var_1, Var_2, Var_3, Var_4, Var_5, Var_6};
with model looking like:
Running mcc, then running exe throws error:
Error using tcp_app
The dimensions, data type or complexity of the return value from the ExternalInputsFcn for port 1 are incorrect.
SimulinkExecution:SimulationService:InvalidDataFromExternalInputs
Changing it to be defined as an array throws the same error but complains about port 2:
extInputs = [Var_1, Var_2, Var_3, Var_4, Var_5, Var_6];
error:
Error using tcp_app
The dimensions, data type or complexity of the return value from the ExternalInputsFcn for port 2 are incorrect.
SimulinkExecution:SimulationService:InvalidDataFromExternalInputs
I had received a separate email from Mathworks support that provided a script example of using simulink.compiler.setExternalInputsFcn and their example recommended each input be set to a fixed Execution -> Sample time so I double clicked on each input and changed that setting like shown below:
Didn't seem to resolve the issue though...

Sign in to comment.

Categories

Find more on Instrument Control Toolbox in Help Center and File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!