为了调试,我在Simulink中的嵌入式matlab函数中绘制了一些向量图。在Matlab R2013b之前,使用以下最小示例代码,一切都可以正常工作:
function fcn
%#minimum example for plot within for-loop of embedded matlab function
coder.extrinsic('delete');
coder.extrinsic('quiver');
coder.extrinsic('gobjects');
numSteps=4;
persistent hFig;
persistent hVector;
if isempty(hFig)
hFig = figure;
hold on;
hVector=zeros(numSteps,1);
hVector=gobjects(numSteps,1);
for i=1:numSteps
hVector(i) = quiver(0,0,0,0);
end
end
set(0, 'CurrentFigure', hFig);
delete(hVector);
for i=1:numSteps
startInc=[1 1;1 1].*i;
endInc=[2 3;2 -3].*i;
hVector(i) = quiver(startInc(1,:),startInc(2,:),endInc(1,:),endInc(2,:));
end
对于句柄数组hVector
,由于它在for
-循环中使用,因此初始化是必要的。然而,对于图形句柄对象的初始化,需要函数gobjects
,而zeros(numSteps,1)
的双重初始化则变得必要,因为matlab无法正确确定外部函数输出的数据类型。正如我所说,如果将此代码片段复制到simulink中的嵌入式matlab函数块中,而模型中没有任何其他内容,则此代码片段可以正常工作。
我的问题是:Mathworks更改了R2014a中的许多绘图函数,其中一个更改是图形句柄的数据类型,对于我的箭袋绘图来说,它不是quiver
类型。因此,使用zeros(numSteps,1)
的初始化会初始化句柄数组的错误数据类型。然而,由于上述问题,将其排除在外仍然不起作用。init循环或任何类似的编译都不会出错。
如果能在这个问题上得到任何帮助,我将不胜感激。
您可以尝试删除gobject
初始化,并使用double()
包装对任何matlab图形对象的调用。例如:
hVector(i) = double( quiver(startInc(1,:),startInc(2,:),endInc(1,:),endInc(2,:)) ) ;
我建议阅读Loren关于切换到HG2版本的Matlab时可能出现的兼容性问题的文章。
它的快速报价更适用于您的问题:
图形函数返回对象,而不是数字句柄
在R2014b之前,可以存储图形对象的一组句柄在数组中,然后向该数组添加一些数字数据。在R2014b中,这将导致错误
[…]
如果你发现自己真的被卡住了,就有可能抛出对象使用double
函数将句柄转换为数字句柄。那你就可以了使用handle
函数将数字强制转换回对象句柄。我们不要建议将此作为长期解决方案。请注意,我们可能选择在未来版本的MATLAB中删除此功能。如果我们这样做,我们会提前通知你的。
现在,如果您真的必须使用此解决方案,请注意,这两个函数都适用于单个元素,也适用于数组。所以
hVector_HG = handle( hVector_Num ) ; %// works if "hVector_Num" is an array of numeric handles
%// and ...
hVector_Num = double( hVector_HG ) ; %// works if "hVector_HG" is an array of HG2 graphic handles
如果经常需要的话,这可能会简化一种或另一种格式之间的往返。
编辑:
我暂时把这个放在帖子的底部,因为开头已经被接受了,但请尝试下面的内容,并让我知道它是否有效。它可能会以更好(更经得起未来考验)的方式解决你的问题。
初始化给定图形对象句柄数组的另一种方法是创建一个(空的就足够了)并复制它
hqNaN = quiver(NaN,NaN) ; %// create an empty quiver
hVector = repmat( hqNaN , numSteps , 1 ) ; %// replicate it in an array
将为您提供一个包含numSteps
HG2图形对象句柄的数组hVector
。在这一点上,它们都指向同一个对象,但用相同类型的句柄覆盖每个元素是完全合法的。所以稍后:
hVector(i) = quiver( ... , etc ... ) ; %// overwrite handle "i" with a new quiver plot handle
将(应该)正常工作。
这种方法需要注意的几件事:
空的箭袋将在哪里产生
你可能已经有了一个"当前"数字,你不希望它被搞砸。如果没有,将创建一个新的空绘图。因此,为了确保空的箭袋不会引起问题(只是屏幕上的闪烁),你可以这样包装:figure ; hqNaN = quiver(NaN,NaN) ; close(gcf) ;
或者你也可以把它放在一个图形中(无论如何它都是不可见的),以防你需要重复使用这种类型的句柄进行其他数组初始化。只是不要忘记,一旦关闭它所在的图形,或者删除图形对象,hqNaN
变量仍然存在,但它不再是同一类型的句柄(因此,如果您确实想要这种类型,则复制它没有用处)。
- 如果不覆盖所有初始句柄数组,该怎么办
记住数组的所有初始句柄都指向同一图形对象。因此,如果您的数组包含12个元素,但假设您错误地只覆盖了其中的10个,那么2个元素将是指向同一对象的句柄(您可能已经删除了该对象)。这意味着呼叫:delete(hVector)
会让你感到讨厌:Error using handle.handle/delete. Invalid or deleted object.
gna-gna-gna。。。幸运的是,您可以通过防御性编程并使用来轻松地做好准备:delete( hVector(ishandle(hVector)) )
Matlab将自动进行检查,并且只删除正确的句柄