R2014a或更新版本的Simulink中嵌入式matlab函数中的图形对象句柄数组

时间:2015-04-27 10:33:34

标签: matlab function graphics simulink handle

为了进行调试,我在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)初始化为double,因为matlab无法正确确定外部输出的数据类型功能。 正如我所说,如果在simulink中复制到嵌入式matlab功能块而没有模型中的任何其他内容,则此代码段工作正常。

我的问题:Mathworks改变了R2014a中的许多绘图功能,其中一个变化是图形句柄的数据类型,对于我的箭头图,它不是quiver类型。因此,使用zeros(numSteps,1)初始化初始化句柄数组的错误数据类型。然而,由于上述问题,将其遗漏仍然不起作用。 init循环或任何类似的编译都没有错误。

我非常感谢有关该问题的任何帮助。

1 个答案:

答案 0 :(得分:3)

您可以尝试删除gobject初始化并使用double()将您的调用包装到任何matlab图形对象。例如:

hVector(i) = double( quiver(startInc(1,:),startInc(2,:),endInc(1,:),endInc(2,:)) ) ;

我建议阅读Loren's article关于切换到Matlab的HG2版本时可能出现的兼容性问题。

快速引用它可以更适用于您的问题:

  

图形函数返回对象,而不是数字句柄

     

在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

将为您提供包含hVector HG2图形对象句柄的数组numSteps。此时它们都指向同一个对象,但用相同类型的句柄覆盖每个元素是完全合法的。所以后来:

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会自动进行检查,只删除正确的句柄。