【问题标题】:Why is my Matlab hgtransform matrix invalid?为什么我的 Matlab hgtransform 矩阵无效?
【发布时间】:2017-02-17 12:51:04
【问题描述】:

我正在尝试通过设置 matlab hgtransform 对象的 'Matrix' 属性来应用变换矩阵。变换矩阵如下:

 866.0254e-003   500.0000e-003   0.0000e+000   500.0000e-003
 500.0000e-003  -866.0254e-003   0.0000e+000   500.0000e-003
 0.0000e+000     0.0000e+000     1.0000e+000     0.0000e+000
 0.0000e+000     0.0000e+000     0.0000e+000     1.0000e+000

这个特定的矩阵旨在表示翻译

(0.5, 0.5, 0)

围绕 pi/6 的 Z 轴旋转。

当我尝试这样做时:

% make a unit box
sx = 1;
sy = 1;
sz = 1;
shapeData.Vertices = [ -sx/2, -sy/2, -sz/2;
                        sx/2, -sy/2, -sz/2;
                        sx/2,  sy/2, -sz/2;
                       -sx/2,  sy/2, -sz/2;
                       -sx/2, -sy/2,  sz/2;
                        sx/2, -sy/2,  sz/2;
                        sx/2,  sy/2,  sz/2;
                       -sx/2,  sy/2,  sz/2; ];

shapeData.Faces = [ 1, 4, 3, 2;
                         1, 5, 6, 2;
                         2, 6, 7, 3;
                         7, 8, 4, 3;
                         8, 5, 1, 4;
                         8, 7, 6, 5 ];

figure;
axes;
transformObject = hgtransform (gca);

patchObject = patch (gca, ...
                    'Faces', shapeData.Faces, ...
                    'Vertices', shapeData.Vertices, ...
                    'FaceColor', 'red', ...
                    'FaceAlpha', 1.0, ...
                    'EdgeColor', 'none',        ...
                    'FaceLighting', 'gouraud',     ...
                    'AmbientStrength', 0.15, ...
                    'Parent', transformObject);

M = [ ...
         866.0254e-003   500.0000e-003   0.0000e+000   500.0000e-003; ...
         500.0000e-003  -866.0254e-003   0.0000e+000   500.0000e-003; ...
         0.0000e+000     0.0000e+000     1.0000e+000     0.0000e+000; ...
         0.0000e+000     0.0000e+000     0.0000e+000     1.0000e+000; ...
        ];

set ( transformObject, 'Matrix', M );

我得到错误:

Error using matlab.graphics.primitive.Transform/set
Invalid value for Matrix property

为什么?

编辑

生成变换矩阵的代码。首先,您需要以下构造方向(旋转)矩阵的类:

classdef orientmat

    properties (GetAccess = public, SetAccess = protected)

        orientationMatrix;
    end

    methods

        function this = orientmat (spectype, spec)
        % orentmat constructor
        %
        % Syntax
        %
        % om = orientmat (spectype, spec)
        %
        % Input
        %
        % 

            switch spectype

                case 'orientation'

                    this.orientationMatrix = spec;

                case 'euler'

                    this.orientationMatrix = SpinCalc('EA123toDCM', rad2deg (spec), eps (), 1);

                case 'euler123'

                    this.orientationMatrix = SpinCalc('EA123toDCM', rad2deg (spec), eps (), 1);

                case 'euler321'

                    this.orientationMatrix = SpinCalc('EA321toDCM', rad2deg (spec), eps (), 1);

                case 'vector'
                    % axis and angle (angle in rad = norm of matrix)
                    wcrs = [ 0         spec(3) -spec(2)
                            -spec(3)        0   spec(1)
                             spec(2)  -spec(1)       0] ;   

                    this.orientationMatrix = expm (wcrs);

                case '2vectors'

                    % normalise the fisr vector
                    spec.vec1 = this.unit (spec.vec1);
                    spec.vec2 = this.unit (spec.vec2);

                    spec.vec3 = cross (spec.vec1, spec.vec2);

                    spec.vec2 = this.unit (cross (this.unit (spec.vec3), spec.vec1));

                    switch spec.vec1axis

                        case 1
                            X = spec.vec1;
                            if spec.vec2axis == 2
                                Y = spec.vec2;
                                Z = spec.vec3;
                            elseif spec.vec2axis == 3
                                Y = spec.vec3;
                                Z = spec.vec2;
                            end

                        case 2
                            Y = spec.vec1;
                            if spec.vec2axis == 1
                                X = spec.vec2;
                                Z = spec.vec3;
                            elseif spec.vec2axis == 3
                                X = spec.vec3;
                                Z = spec.vec2;
                            end

                        case 3
                            Z = spec.vec1;
                            if spec.vec2axis == 2
                                X = spec.vec2;
                                Y = spec.vec3;
                            elseif spec.vec2axis == 3
                                X = spec.vec3;
                                Y = spec.vec2;
                            end

                    end

                    this.orientationMatrix = [ X, Y, Z ];

            end 

        end

    end

    % operator overloading
    methods 

        function om = plus (om1, om2)

            om = mbdyn.pre.orientmat ('orientation', om1.orientationMatrix + om2.orientationMatrix);

        end

        function om = minus (om1, om2)

            om = mbdyn.pre.orientmat ('orientation', om1.orientationMatrix - om2.orientationMatrix);

        end

        function om = times (om1, om2)

            om = mbdyn.pre.orientmat ('orientation', om1.orientationMatrix .* om2.orientationMatrix);

        end

        function om = mtimes (om1, om2)

            om = mbdyn.pre.orientmat ('orientation', om1.orientationMatrix * om2.orientationMatrix);

        end

        function om = double (om1)

            om = om1.orientationMatrix;

        end

        function om = uminus (om1)

            om = mbdyn.pre.orientmat ('orientation', -om1.orientationMatrix);

        end

        function om = uplus (om1)

            om = mbdyn.pre.orientmat ('orientation', +om1.orientationMatrix);

        end

        function om = transpose (om1)

            om = mbdyn.pre.orientmat ('orientation', om1.orientationMatrix.');

        end

        function om = ctranspose (om1)

            om = mbdyn.pre.orientmat ('orientation', om1.orientationMatrix');

        end

    end

    methods (Access = private)

        function out = unit (self, vec)

            out = vec ./ norm (vec);

        end

    end


end

然后做:

om = orientmat ('2vectors', struct ('vec1axis', 1, 'vec1', [cos(pi/6);sin(pi/6);0], 'vec2axis', 3, 'vec2', [0;0;1]));

M = [ om.orientationMatrix, [0.5; 0.5; 0]; 0, 0, 0, 1 ];

现在可能存在一个问题,旋转实际上不是我想要的,但据我所知,它仍然是一个有效的变换矩阵?

【问题讨论】:

  • 能否提供MATLAB版本?此代码在 2014B 上失败
  • 你有生成变换矩阵的代码吗?
  • @AnderBiguri,它是 R2016b,不确定最早的版本是什么。
  • @Suever 我添加了一些代码

标签: matlab matlab-figure homogenous-transformation


【解决方案1】:

答案是 Matlab 只接受非负缩放项,见Transforms Supported by hgtransform

【讨论】:

  • 嗨,你的意思是你的M 有负缩放条款。在我看来,M 只包含旋转和平移。我错过了什么吗?谢谢!
  • diagonal of the matrix is the scaling matrix,所以即使你只打算旋转和平移,如果你在对角线上有术语,你也隐含地有缩放,或者至少,这似乎是 Matlab 的想法。或许更准确地说,Matlab 不喜欢变换矩阵对角线上的非负项。
  • 感谢您的回复。对,我也不认为“矩阵的对角线是缩放矩阵”。考虑具有负对角线的任意旋转矩阵。显然它没有做任何缩放。此外,我观察到在我的警告中,目标 hgtransform 矩阵具有正对角线。您是否可以分享任何其他可能的材料?
猜你喜欢
  • 2019-11-14
  • 2017-06-07
  • 1970-01-01
  • 2014-12-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多