Running multiple functions at once in MATLAB App Designer

I am trying to run multiple functions at once in the App Designer, I have tried to use Parfeval, Parpoop, the Parallel Computing Toolbox, etc but nothing seems to be working. My 2 functions are:
function move_image_randomly(app)
% keep repeating function
while true
% Define the initial position of the image
startPos = app.q1ans.Position;
% Define the maximum distance to move in each direction
maxMove = 20;
%Generate random movement in x and y directions
dx = randi([-maxMove, maxMove]);
dy = randi([-maxMove, maxMove]);
% Update the image position
newPos = startPos + [dx, dy, 0, 0];
app.q1ans.Position = newPos;
% Pause briefly to allow the user to see the image
pause(0.5);
% Get the positions of the two images
image1_pos = app.Ball.Position(1);
image2_pos = app.q1ans.Position(1);
image1b_pos = app.Ball.Position(2);
image2b_pos = app.q1ans.Position(2);
% Calculate the distance between the two images using the distance formula
distance = abs(image1_pos - image2_pos);
distanceb = abs(image1b_pos - image2b_pos);
% Check if the distance is within a certain range (e.g., 100 pixels)
if distance <= 5 || distanceb <=5
app.q = app.q + 1;
end
end
end
function countdown(app)
for i = 30:-1:0
app.CountdownLabel.Text = num2str(i);
pause(1);
end
app.TitleSequence.Text = "Game Over!";
end
I want the image to be moving randomly and the countdown to happen at the same time. But it seems MATLAB can only do them one at a time, and not simultaneously. Please help thanks.

Answers (1)

You can get them to run at the same time if you use parfeval()
However !! The background process cannot directly display to the command line, or directly display any graphics.
You should consider using timer

5 Comments

Hi thanks for the response. I have tried to use timer however this does not seem to work. This is the code that I am using:
function run_parallel(app)
% Define the two functions you want to run simultaneously
f1 = @() countdown(app);
f2 = @() move_image_randomly(app);
% Set up two timers to execute each function
t1 = timer('ExecutionMode', 'fixedSpacing', 'Period', 1, 'TimerFcn', f1);
t2 = timer('ExecutionMode', 'fixedSpacing', 'Period', 1, 'TimerFcn', f2);
% Start the timers
start(t1);
start(t2);
end
function run_parallel(app)
runlimit = 30;
% Define the two functions you want to run simultaneously
move_fun = @(varargin) move_image_randomly(app);
count_fun = @(varargin) countdown(app);
app.CountdownLabel.UserData = runlimit;
% Set up two timers to execute each function
t1 = timer('ExecutionMode', 'fixedSpacing', 'Period', 0.5, 'TimerFcn', move_fun);
t2 = timer('ExecutionMode', 'fixedSpacing', 'Period', 1, 'TimerFcn', count_fun, ...
'TasksToExecute', runlimit, ...
'StartFcn', @(varargin) start(t1)), ...
'StopFcn', @(varargin) stop(t1));
% Start the count which will start the movement
start(t2);
end
function count_fun(app)
oldtime = app.CountdownLabel.UserData;
app.CountdownLabel.Text = num2str(oldtime);
app.CountdownLabel.UserData = oldtime - 1;
end
and move_image_randomly should move once each time it runs.
This version of the code does not need any explicit tests for being out of time; it relies on setting the number of times the count timer should fire, with the count timer set to automatically start and stop the movement timer
Thanks for the response. However the two functions do not run at the same time with the code, the countdown must finish first before the move_image_randomly function starts, whereas I need them to run at the same time. I tried this below but I get the same result:
function run_parallel2(app)
% Create the timers
t1 = timer('ExecutionMode', 'fixedRate', 'Period', 1, 'TimerFcn', {@countdown, app});
t2 = timer('ExecutionMode', 'fixedRate', 'Period', 0.5, 'TimerFcn', @(~,~)move_image_randomly(app));
% Start both timers at the same time
startat(t2, datetime + seconds(0.2));
startat(t1, datetime + seconds(0.2));
end
Timer objects cannot literally run at the same time. They are not parallel processing. As I indicated earlier, in all forms of parallel processing that MATLAB provides, only one thread can write to the command window or have a visual affect on graphics.
When timer objects run, they interrupt whatever else is going on, and they get control until they return. So you generally program them so that they do only a little bit of work and then return.
For example in count_fun that I provided earlier, count_fun just updates the label and decrements the count and then returns. Perhaps it should also drawnow() before it returns.
It is not the case that all periods for one timer must be executed before the other timer can do anything at all.
t2 = timer('ExecutionMode', 'fixedRate', 'Period', 0.5, ...
'TimerFcn', @(varargin) disp('timer 2'));
t1 = timer('ExecutionMode', 'fixedRate', 'Period', 1, ...
'TasksToExecute', 10, ...
'TimerFcn', @(varargin) disp('timer 1'), ...
'StartFcn', @(varargin) start(t2), ...
'StopFcn', @(varargin) stop(t2));
start(t1);
%MATLAB only has maximum pause of 2
BEGIN = tic; while toc(BEGIN) < 30; pause(1); end
t1.TasksExecuted
ans = 10
t2.TasksExecuted
ans = 18
You cannot see it here on MATLAB Answers, but if you execute this code you will see repeated stretches of
timer 1
timer 2
timer 2
so timer 2 is being called twice as often as timer1, and starting and stopping of the second timer (t2) is being controlled by the StartFcn and StopFcn callbacks of timer 1 (t1)
The output will not have 10 calls to timer 1 followed by some number of calls to timer 2.

Sign in to comment.

Categories

Asked:

on 19 Apr 2023

Commented:

on 19 Apr 2023

Community Treasure Hunt

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

Start Hunting!