Is it possible to put the calling of function into another thread? I tried spmd in the function but i get error saying that
MATLAB cannot determine whether "System" refers to a function or
variable.
tic
Speak('Testing');
toc
...next line of code...
function Speak(text)
spmd
NET.addAssembly('System.Speech');
speak = System.Speech.Synthesis.SpeechSynthesizer;
speak.Volume = 100;
speak.Speak(text);
end
end
I get elapsed time of approximately 2 seconds, which is pretty long for this purpose. I would prefer the speech continuing in the background and proceed to the next line of code in the meantime.
Related
Suppose in func.m we have
function out = func(in)
for i=1:1000
out=i;
end
end
and after entering >> out = func; in the Matlab cmd, the user interrupts the command execution with Ctrl+C.
Instead of having out equal some integer between 1 and 1000, out is not available in the Global Workspace. If out had been defined before calling out = func;, it would not be updated.
Is there a way to make out available in the Global Workspace upon user interruption and during execution of func as long as it is defined within func?
And if there is a way, will the same method work for cases where a function is interrupted because an error is thrown?
(It may seem trivial if the convenience gained is about a single function. After all, writing to and later reading from harddrive is always an option -- though not an efficient one. Over the years, it's been quite a number of functions where such a functionality would be convenient for me and increase my productivity. So I finally asked.)
So here's a solution that allows to interrupt a loop with a press of a button on a message box.... not ctrl-c, but an alternative way to interrupt a loop:
function out=interrupted_loop_example(in)
f = msgbox('break the loop?') ;
%---------- this is a sample loop:
out=in;
while(~breakloop(f))
out=out+1;
end
%--------------------------------
% clean up:
if ishandle(f) ; delete(f) ; end % to kill the msgbox
% helper function
function x = breakloop(f)
drawnow ; % allowing matlab to detect a button was pressed
x = ~ishandle(f) ;
copy the function, run it, e.g. interrupted_loop_example(100) , and see the ans when you press the button, basically deciding when to break the loop. naturally there will be a toll on performance this way, but you didn't mention anything about performance in your question.
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 want to stop solving a differential equation in Matlab if it takes more than a designated amount of time. I tried the following,but it doesn't work...
options = odeset('AbsTol',1e-8,'RelTol',1e-5);
RUNTIME=5;
timerID = tic;
while (toc(timerID) < RUNTIME)
[t_pae,x_th_pae] = ode15s(#prosomoiwsh,[0 t_end],[80*pi/180;0;130*pi/180;0;th_initial(1);th_initial(2);th_initial(3);th_initial(4)],options);
end
How can I solve this?
UPDATE :
I tried what horchler suggested and now my code looks like this :
interupt_time = 20;
outputFun= #(t,y,flag)interuptFun(t,y,flag,interupt_time);
options = odeset('AbsTol',1e-5,'RelTol',1e-5,'OutputFcn',outputFun);
try
[t_pae,x_b_th_pae] = ode15s(#prosomoiwsh,[0 t_end],[0;0;0;th_initial(1);th_initial(2);th_initial(3);th_initial(4);th_initial(5);th_initial(6);th_initial(7);th_initial(8);th_initial(9);th_initial(10);th_initial(11);th_initial(12)],options);
u_pae=compute_input(epsilon,ke,kv,dD,IwF,IwG,IwD,IbF,IbG,IbD,p,m,t_pae,x_b_th_pae);
catch ME
if strcmp(ME.identifier,'interuptFun:Interupt')
disp(ME.message);
input('got caught')
else
rethrow(ME); % It's possible the error was due to something else
end
end
function dx_b_th = prosomoiwsh(t,x_b_th)
...
end
The outputFun is exactly the same as the one horchler suggested. But now it times out every single time,while previously this only happened occasionally. What am I doing wrong?
First, you can't do anything like what you're trying. All that will happen is that ode15s will run for as long as it needs and return it's result as usual. You need a way of interrupting the ODE solver in the middle of its execution when a certain designated amount of time has been exceeded. Unfortunately, you didn't provide runnable code, so I'll have to provide general suggestions that you can adapt to your problem.
One way to do this is via an Output function. This is a function that gets called after every (successful) integration step of a Matlab solver. There are are several examples of Output functions that you can examine the code of to see what you can do: odeplot, odeprint, odephas2, and odephas3. Just type edit odeplot in your command window to see the code.
Below is an example of how you might use this capability using the built-in example function vdp1000 that's referred to in the help for ode15s. You need to create a persistent variable to save the initial time, initialize it, and then check the elapsed time relative to a parameter that you pass in. Then you throw an error to abort ode15s if the elapsed time exceeds the designated value. A try-catch statement can be used to catch the error.
function ode_interupt_demo
tspan = [0 3000]; y0 = [2;0];
interupt_time = 0.05;
outputFun= #(t,y,flag)interuptFun(t,y,flag,interupt_time);
opts = odeset('AbsTol',1e-8,'RelTol',1e-5,'OutputFcn',outputFun);
try
[t,y] = ode15s(#vdp1000,tspan,y0,opts);
catch ME
if strcmp(ME.identifier,'interuptFun:Interupt')
disp(ME.message);
% Do other things
else
rethrow(ME); % It's possible the error was due to something else
end
end
function status = interuptFun(t,y,flag,interupt_time) %#ok<INUSL>
persistent INIT_TIME;
status = 0;
switch(flag)
case 'init'
INIT_TIME = tic;
case 'done'
clear INIT_TIME;
otherwise
elapsed_time = toc(INIT_TIME);
if elapsed_time > interupt_time
clear INIT_TIME;
str = sprintf('%.6f',elapsed_time);
error('interuptFun:Interupt',...
['Interupted integration. Elapsed time is ' str ' seconds.']);
end
end
One disadvantage of this approach is that you will not get a return value from ode15s. This may or may not be desirable in your application. There are likely ways around this, but they'll require more code. One easy thing that you can do is have the error message return the last time and state of the system (when it was interrupted) using the t and y values passed into the output function. It's also possible that Event functions could be used to terminate integration based on elapsed time – those might allow you to still return output from ode15s.
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