Function ';无效的句柄对象';在MatLab函数中使用计时器时

Function ';无效的句柄对象';在MatLab函数中使用计时器时,function,matlab,timer,Function,Matlab,Timer,我正在使用MatLab中的一个脚本,它本身运行得非常好,但我需要从中生成一个函数。 该脚本读取一个.csv文件,提取所有值,启动计时器,并在每个刻度处显示从.csv中提取的相应坐标,从而生成我的图形的三维动画。 我想给它一个.csv的位置,这样它就可以开始显示这个csv的图形 以下是我的想法: function handFig(fileLoc) csv=csvread(fileLoc,1,0); both = csv(:,2:19); ax=axes; set(ax,'NextPlot'

我正在使用MatLab中的一个脚本,它本身运行得非常好,但我需要从中生成一个函数。 该脚本读取一个.csv文件,提取所有值,启动计时器,并在每个刻度处显示从.csv中提取的相应坐标,从而生成我的图形的三维动画。 我想给它一个.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
函数k=doPlot(hp1、hp2、hp3、hp4、hp5、hp6、L1、L2、L3、L4、L5、pos、t1、k)
k=k+1;

如果k我认为这是因为当你第一次在计时器中调用
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');
注意
doPlot
调用中缺少的
t1

或者在创建计时器之前初始化您的
t1
,使其具有要传递的值


更新(作为旁白,您是否可以在循环中使用
暂停(Dct)
?似乎更容易) 事实上,现在我认为这是一个范围问题。 要做到这一点需要一些挖掘,但查看Matlab文档,它说:

当MATLAB计算函数句柄时,变量的作用域与创建函数句柄时相同。(相反,指定为字符串的回调在基本工作区中计算。)

您当前将
TimerFcn
参数作为字符串提供,因此
k=doPlot(…)
将在基本工作区中进行计算。如果要转到matlab提示符,运行
handFig
,然后键入
h1
,您会得到一个错误,因为
h1
在全局工作区中不可用--它隐藏在
handFig

这就是你遇到的问题

但是,解决方法是将函数指定为函数句柄而不是字符串(它表示函数句柄是在创建它们的范围内计算的,即在
handFig

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

除了这两个必需的输入参数之外,回调函数 函数可以接受特定于应用程序的参数。收到这些 输入参数时,在指定 函数作为回调属性的值。更多 有关详细信息,请参见指定回调函数属性的值

它通过一个例子说明了你必须做些什么才能让它工作。比如:

% 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
您需要从
doPlot
中获取(timer\u obj,'UserData')

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); 
我认为这是正确的做法——玩玩它。我也强烈推荐mathworks论坛做这类事情,那些人都是天才

来自mathworks论坛是我开始学习的原因,可能会对你有所帮助


祝你好运

谢谢,这是有道理的,事实上,我做到了,错误改变了!总是一种进步;)现在为计时器'timer-15'未定义的函数或变量'hp1'计算TimerFcn时出错了。“我现在不明白,因为hp1(和下面的hp)都是在计时器之前定义的。我知道了它是什么——这是一个范围问题。当您将回调(TimerFcn)定义为字符串时,它将在基本Matlab工作区中进行计算。您必须创建一个函数句柄,以便从另一个函数中调用
计时器
。更新了我的答案。哦,魔术来了!我很难让它工作,因为我天真地将“UserData”更改为“UserTime”,直到我明白“UserData”不是您选择的随机名称,而是实际的计时器属性。。。无论如何,非常感谢您的快速和有用的帮助!