在MatLab中的函数内使用计时器时,“无效的句柄对象”

时间:2012-01-24 04:42:43

标签: function matlab timer

我在MatLab中使用的脚本本身完美无缺,但我需要用它来创建一个函数。 该脚本读取.csv文件,提取所有值,启动计时器,并在每个刻度显示从.csv中提取的相应坐标,从而生成我的图形的3D动画。 我想要的是给它.csv的位置,以便它开始显示这个csv的图形。

以下是我的想法:

function handFig(fileLoc)

csv=csvread(fileLoc,1,0);  
both = csv(:,2:19);

ax=axes;
set(ax,'NextPlot','replacechildren');

Dt=0.1; %sampling period in secs

k=1;
hp1=text(both(k,1),both(k,2),both(k,3),'thumb'); %get handle to dot object
hold on;
hp2=text(both(k,4),both(k,5),both(k,6),'index');
hp3=text(both(k,7),both(k,8),both(k,9),'middle');
hp4=text(both(k,10),both(k,11),both(k,12),'ring');
hp5=text(both(k,13),both(k,14),both(k,15),'pinky');
hp6=text(both(k,16),both(k,17),both(k,18),'HAND');
L1=plot3([both(k,1),both(k,16)],[both(k,2),both(k,17)],[both(k,3),both(k,18)]);
L2=plot3([both(k,4),both(k,16)],[both(k,5),both(k,17)],[both(k,6),both(k,18)]);
L3=plot3([both(k,7),both(k,16)],[both(k,8),both(k,17)],[both(k,9),both(k,18)]);
L4=plot3([both(k,10),both(k,16)],[both(k,11),both(k,17)],[both(k,12),both(k,18)]);
L5=plot3([both(k,13),both(k,16)],[both(k,14),both(k,17)],[both(k,15),both(k,18)]);
hold off;

t1=timer('TimerFcn','k=doPlot(hp1,hp2,hp3,hp4,hp5,hp6,L1,L2,L3,L4,L5,both,t1,k)','Period', Dt,'ExecutionMode','fixedRate');
start(t1);

end

使用了doplot函数:

function k=doPlot(hp1,hp2,hp3,hp4,hp5,hp6,L1,L2,L3,L4,L5,pos,t1,k)

k=k+1;
if k<5000%length(pos)
set(hp1,'pos',[pos(k,1),pos(k,2),pos(k,3)]);
axis([0 255 0 255 0 255]);
set(hp2,'pos',[pos(k,4),pos(k,5),pos(k,6)]);
set(hp3,'pos',[pos(k,7),pos(k,8),pos(k,9)]);
set(hp4,'pos',[pos(k,10),pos(k,11),pos(k,12)]);
set(hp5,'pos',[pos(k,13),pos(k,14),pos(k,15)]);
set(hp6,'pos',[pos(k,16),pos(k,17),pos(k,18)]);
set(L1,'XData',[pos(k,1),pos(k,16)],'YData',[pos(k,2),pos(k,17)],'ZData',[pos(k,3),pos(k,18)]);
set(L2,'XData',[pos(k,4),pos(k,16)],'YData',[pos(k,5),pos(k,17)],'ZData',[pos(k,6),pos(k,18)]);
set(L3,'XData',[pos(k,7),pos(k,16)],'YData',[pos(k,8),pos(k,17)],'ZData',[pos(k,9),pos(k,18)]);
set(L4,'XData',[pos(k,10),pos(k,16)],'YData',[pos(k,11),pos(k,17)],'ZData',[pos(k,12),pos(k,18)]);
set(L5,'XData',[pos(k,13),pos(k,16)],'YData',[pos(k,14),pos(k,17)],'ZData',[pos(k,15),pos(k,18)]);

else
k=1;
set(hp1,'pos',[pos(k,1),pos(k,2),pos(k,3)]);
axis([0 255 0 255 0 255]);
set(hp2,'pos',[pos(k,4),pos(k,5),pos(k,6)]);
set(hp3,'pos',[pos(k,7),pos(k,8),pos(k,9)]);
set(hp4,'pos',[pos(k,10),pos(k,11),pos(k,12)]);
set(hp5,'pos',[pos(k,13),pos(k,14),pos(k,15)]);
set(hp6,'pos',[pos(k,16),pos(k,17),pos(k,18)]);
end

但是,当我运行handFig('fileName.csv')时,我每次都会收到同样的错误:

  

???在计算定时器'timer-7'的TimerFcn时出错

     

无效的句柄对象。

我认为它可能来自试图每次创建一个新的'csv'和'both'的函数,所以我尝试删除它们,直接向函数提供数据,但没有结果。

究竟是什么问题?有解决方案吗?

非常感谢!

1 个答案:

答案 0 :(得分:2)

我认为这是因为当您第一次在计时器中调用doPlot时,您传入t1作为参数,并且第一次可能不存在。

doPlot是否需要t1?我建议修改它以便它不被使用,然后你打电话给:

t1=timer('TimerFcn','k=doPlot(hp1,hp2,hp3,hp4,hp5,hp6,L1,L2,L3,L4,L5,both,k)','Period', Dt,'ExecutionMode','fixedRate');

请注意t1来电中遗失的doPlot

要么在创建计时器之前初始化t1,要么它有一些值可以传入。


更新(顺便说一句,你可以在循环中使用pause(Dct)吗?似乎更容易)

实际上,现在我认为这是一个范围问题。 我们需要花一点时间来解决这个问题,但是看一下function callbacks的Matlab文档,它说:

  

当MATLAB评估函数句柄时,相同的变量在范围内,就像创建函数句柄时一样。 (相反,指定为字符串的回调在基础工作区中进行评估。)

您目前将TimerFcn参数作为字符串,因此在 base 工作区中评估k=doPlot(...)。如果您要转到matlab提示符,运行handFig,然后键入h1,则会收到错误,因为h1在全局工作空间中不可用 - 它隐藏在内部handFig

这就是你遇到的问题。

但是,解决方法是将您的函数指定为函数句柄而不是字符串(它表示函数句柄在创建它们的范围内进行评估,即在handFig内)。

TimerFcn的函数句柄必须有两个参数objevent(请参阅Creating Callback Functions)。此外,该帮助文件表示您必须将doPlot放在其自己的m文件中,以使其不在基本Matlab工作区中进行评估。

  

除了这两个必需的输入参数外,还有你的回调   function可以接受特定于应用程序的参数。收到这些   输入参数,在指定名称时必须使用单元格数组   函数作为回调属性的值。更多   信息,请参阅指定回调函数属性的值。

它通过一个示例来说明如何使其工作。类似的东西:

% create timer
t = timer('Period', Dt,'ExecutionMode','fixedRate');
% attach `k` to t so it can be accessed within doPlot
set(t,'UserData',k);
% specify TimerFcn and its extra arguments:
t.TimerFcn = { @doPlot, hp1, hp2, hp3, ...., both };
start(t)

注意 - 在k中设置UserData的原因是因为需要在调用doPlot之间以某种方式保存和修改。

然后修改你的doPlot以在开头有两个参数(未使用),不接受 k参数。要从k

中提取get(timer_obj,'UserData'),您需要执行doPlot
function k=doPlot(timer_obj, event, hp1,hp2,hp3,.....)
    k = get(timer_obj,'UserData');
    .... % rest of code here.
    % save back k so it's changed for next time!
    set(timer_obj,'UserData',k); 

我认为这是正确的轨道 - 玩弄它。我强烈推荐数学论坛来做这类事情,那些人都是高手。

来自数学工作论坛的

This thread让我开始并可能对你有所帮助。

祝你好运!