matlabmatlab-figurehomogenous-transformation

Why is my Matlab hgtransform matrix invalid?


I am attempting to apply a transform matrix by setting the 'Matrix' property of a matlab hgtransform object. The transform matrix is below:

 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

This particular matrix is intended to represent a translation

(0.5, 0.5, 0)

and rotation around the Z axis of pi/6.

When I try to do this:

% 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 );

I get the error:

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

Why?

EDIT

The code that generated the transform matrix. First you need the following class which constructs orientation (rotation) matrices:

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

Then do:

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 ];

Now there may be an issue with the rotation not actually being what I intend, but as far as I can see it is still a valid transformation matrix?


Solution

  • The answer was that Matlab only accepts non-negative scaling terms, see Transforms Supported by hgtransform