For example if there is a MATLAB program as follows:
duration = 1 % minute
i=1
while i<1000
[X,Y] = ginput(1)
i = i+1;
end
Is there any way to terminate the execution of this program or getting out of the loop when it reaches to the assigned amount of time (1 minute in this case) in such a situation in which continuation of the loop needs the user intervention (in this case clicking on any point on the plotted figure)?
If you want to do a process within your loop for a minimum of a minute, you can do it like this:
start = now
while now - start < 60/60/24
%do something for a minute
end
As a commenter above said, ginput will wait indefinitely so don't plan on that working.
Related
This question already has an answer here:
Matlab time limit for function execution
(1 answer)
Closed 5 years ago.
I run a matlab script multiple times per day and a lot of times it takes too long to execute. What I want to do is set off a timer that keeps track of how long the script has been running for and stops the script when it takes longer than a specified number of seconds
I have tested this principle on a simple script:
waittime = 5;
t = timer('TimerFcn','error(''Process ended because it took too long'')',waittime);
start(t)
pause(10);
What I would expect to happen is that this function waits for 5 seconds and afterwards it will execute the stop function which is the error('Process ended because it took too long') command.
When running this, the stop command will execute, however it does not stop the main script from running.
In my command window I see
Error while evaluating TimerFcn for timer 'timer-20'
Process ended because it took too long
Afterwards the script is not stopped, and keeps running for the full 10 seconds
I don't want this error to be cast over the TimerFcn function, I want this error to be cast over the running script such that it stops running.
Is there any way I can control the script/function over which the error is cast?
If you have access to the the script and can periodically check for the time inside the script, you can do something like this
waittime = 3;
endt=true;
t = timer('TimerFcn','endt=false; disp(''Timer!'')','StartDelay',waittime);
start(t);
i=1;
while endt==true
a=exp(i);
i=i+1;
pause(0.1);
end
If you do not have any bits that are periodic or do not have access to the script, I think your best bet is described here
Matlab: implementing what CTRL+C does, but in the code
Hope this is helpful
I agree with Ander Biguri that I don't think this is possible. What you can do is make the TimerFcn do something that causes an error somehwere else.
waittime = 5;
d=1;go=1;
t = timer('TimerFcn','clear d','StartDelay',waittime);
start(t)
while go
pause(0.1)
1/d;
end
Given this previous question, you'll probably have to resort to some Java tricks to do this, since throwing an error message doesn't interrupt the pause statement. However, if the script you're running can periodically break computation and perform checks on the state, you can incorporate a timer as follows:
% Initialization:
maxRunTime = 5;
tObj = timer('TimerFcn', #(~, ~) disp('Time''s up!'), 'StartDelay', maxRunTime);
% Script:
start(tObj);
while strcmp(get(tObj, 'Running'), 'on')
% Do some computations
end
delete(tObj);
This checks the running state of the timer to determine if the loop continues, so the timer function doesn't have to modify any variables or throw any errors.
Using timer objects gets too complicated especially when you have to use more than one timer so I was trying to think of alternative approaches.
I want to avoid using pause, since it stops other functions from executing. I thought of using the tic toc functions to measure elapsed time but the code I have written below does not work as I expect.
time=tic;
if(abs(toc(time)))==3 %% if 3 second past
my function
end
How can I modify this code so that it executes the command after 3 seconds?
TLDR;
A tic/toc pair and a while loop is literally no different than using pause since they both block execution of any other functions. You have to use timer objects.
A More Detailed Explanation
In order to make this work, you'd need to use a while loop to monitor if the required amount of time has passed. Also, you'll want to use < to check if the time has elapsed because the loop condition isn't guaranteed to be evaluated every femtosecond and therefore it's never going to be exact.
function wait(time_in_sec)
tic
while toc < time_in_sec
end
% Do thing after 3 seconds
fprintf('Has been %d seconds!\n', time_in_sec)
end
The unfortunate thing about a while loop approach is that it prevents you from running multiple "timers" at once. For example, in the following case, it will wait 3 seconds for the first task and then wait 5 seconds for the second task requiring a total time or 8 seconds.
wait(3)
wait(5)
Also, while the while loop is running, nothing else will be able to execute within MATLAB.
A much better approach is to setup multiple timer objects and configure them with callbacks so that they can run at the same time and they will not block any operations within MATLAB while they run. When you need multiple timer objects (which you consider to be a pain) is exactly when you have to use timer objects.
If it's really that cumbersome, write your own function which does all of the boilerplate stuff for you
function tmr = wait(time_in_sec)
tmr = timer('StartDelay', time_in_sec, ...
'ExecutionMode', 'SingleShot', ...
'TimerFcn', #(s,e)status(time_in_sec));
tmr.start()
function status(t)
fprintf('Has been %d seconds!\n', t);
end
end
wait(3)
wait(5) % Both will execute after 5 seconds
Also since the timers are non-blocking (when the callback isn't running), I can execute commands immediately after starting the timers
wait(3)
disp('Started 3 second timer')
wait(5)
disp('Started 5 second timer')
If you try this with your while loop, you'll see the while loop's blocking behavior.
you need a while loop or something to wait for time to be 3 seconds.
something like this
time=tic;
while 1
if(abs(toc(time)))==3 %% if 3 second past
my function
break;
end
end
If you want to call my function every 3 seconds, then you should do something like this:
time=tic;
while 1
if mod((abs(toc(time))),3) == 0 %% if 3 second past
my function
end
end
Please make sure that you have some way of telling once you are done and then break the while loop.
You could set it to >= instead of ==. That will catch it if it misses the exact value.
I am working with a script that takes user input. I want the user to answer on the input within 4 seconds otherwise the code shall do something (right now without using a GUI). What I have done so far is to start a tic and prompt a input testInput = input('Enter the number: '); Meanwhile the prompt is open (waiting for input) I am checking if time has not runed out:
elapsed_time = toc;
if elapsed_time > 4
%do something
end
To the problem:
From what I have learned, there's no way to programmatically terminate a running command in MATLAB, or even let the code do something while the prompt is open. Therefore I can not check if 4 sec has passed before the user inputs something. I've read (here) that this might be possible to solve by using a GUI. I have although no idea how to implement this, since I am totally new.
So, would this be possible with a GUI? Because with the command window it is not.
I would really appreciate to see how something simple like this could look like as a GUI (just something very simple, a window with a input box):
%Start a time ticker
tic;
testInput = input('Enter the number: ');
elapsed_time = toc;
if elapsed_time > 4
%do something
end
Here is a small example of a custom GUI where the user should enter a number before a maximum time is reached. Please read some about callbacks, handles, figure options and uicontrol to better understand it.
Note that you might need to do som more fault handling of the input string (check that number is valid)
function EnterNumber()
% Create figure
inDlg = figure('NumberTitle','off','MenuBar','none','ToolBar','none');
% Create timer, set it to run TimerFcn after 4 s
maxTime = 4;
tH = timer('TimerFcn', {#closeFig inDlg}, 'StartDelay', maxTime);
% Create text and input box for number in figure
uicontrol(inDlg,...
'Style','Text','FontSize',14, ...
'String',sprintf('Please enter a number within %d seconds:', maxTime),...
'Units','Normalized','Position',[0.1 0.6 0.8 0.2]);
editBox = uicontrol(inDlg,...
'Style','Edit','Units','Normalized','Position',[0.1 0.5 0.8 0.2], ...
'FontSize',14,'Callback',#returnEditValue);
% Start timer
start(tH);
% Set focus on the edit box so a number could be entered instantly
uicontrol(editBox)
% Wait for figure to be closed (in any way)
waitfor(inDlg)
fprintf('Moving on ...\n');
% Callback function to save number
function returnEditValue(hObject,~)
% Get the number
number = str2double(get(hObject,'String'));
% Example of how to display the number
fprintf('The entered number is %d\n', number);
% Example of saving the number to workspace
assignin('base','number', number);
% Close figure
close(get(hObject,'Parent'));
% Calback function for timer timeout
function closeFig(~,~,figH)
% If figure exist, close it
if ishandle(figH)
close(figH)
fprintf('Too slow!\n')
end
I am an amateur Matlab User who is attempting to write a code to run a specific function call every 10ms for a time span of 1 second. I am having trouble trying to get something to run for the exact amount of time; I have tried to use Tic and Toc but that's in seconds (I need millisecond precision). Here is some very basic code I have been playing with to try and get readings using a function called getvelocity. Any help would be appreciated, thanks!
function [ velocity ] = Vel()
i=1;
timerID=tic;
while (toc(timerID) <=2);
[v(i)]=vpx_GetTotalVelocity;
disp (v(i));
i=i+1;
end
velocity=mean(v);
end
The code above runs for two seconds; however, I want to run in ms precision.
Assuming the function you have is fast enough (not a trivial assumption) you can achieve it like so:
tic
for t = 0.01:0.01:1 %If you want the first function call to start right away you can change this to 0:0.01:0.99
while toc < t
end
t %Put your function call here.
end
Note that 0.01 sec is 10 ms
As stated in title.
I want to have a certain interval time for each loop, say 60 seconds.
My problem is I have a code inside a loop to perform measurement with a external device.
This measurement takes 5-10 seconds.
So I cannot simply use pause(60) inside the loop because the interval time depends on how long each measurement takes.
Is there any way to fix the time interval of loop?
Sounds like you'd be able to use parallel threading to achieve what you want. One thread kicks off the measurement every sixty seconds, using a worker thread so that the measurement doesn't block up the time interval.
Perhaps try the batch function with something like this:
while(True)
hBatch = batch(#doMeasurement);
pause(60);
measurement = fetchOutputs(hBatch){1}
end
Better would be to use the timer function:
t = timer('TimerFcn', #doMeasurement, 'Period', 60.0);
start(t)
You want something like this:
k=1; % or any value except 0
time1=clock;
while ~(k==0)
time2=clock;
k=etime(time2,time1);
% your statements
loop