I'm starting to think that the reason is the -ve coefficient on the diagonal of my matrix, as according to Transforms Supported by hgtransform no non-negative scaling terms are allowed. So even though the scaling here is 1 the negative term makes it invalid.
Why is my Matlab hgtransform matrix invalid?
    7 views (last 30 days)
  
       Show older comments
    
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 (although actually I think it results in a rotation of -pi/6, more on this below).
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?
To generate this transform matrix I used the following class I created which constructs orientation (rotation) matrices in various ways:
    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 did:
    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 ];
This constructs an orientation matrix from two vectors which define a plane.
Now there may be an issue with the rotation not actually being what I intend (I think the order of the cross products is wrong so the rotation ends up in the wrong direction), but as far as I can see it is still a valid transformation matrix. So why does hgtransform not like it?
EDIT
As explained earlier, there is actually an issue with the transform not doing what I intend (actually produces a rotation in the wrong direction), but the matrix seems valid, for example it produces the same result as hgtransform:
>> M
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
>> pos = [1,0,0,0]
pos =
       1.0000e+000     0.0000e+000     0.0000e+000     0.0000e+000
>> pos * M
ans =
     866.0254e-003   500.0000e-003     0.0000e+000   500.0000e-003
>> Mhgt = makehgtform('translate', [0.5 0.5 0], 'zrotate', -pi/6)
Mhgt =
     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
>> pos * Mhgt
ans =
     866.0254e-003   500.0000e-003     0.0000e+000   500.0000e-003
Answers (1)
  Walter Roberson
      
      
 on 22 Feb 2017
        You appear to have the wrong sign on one of your coefficients.
M = makehgtform('translate', [0.5 0.5 0], 'zrotate', -pi/6)
or +pi/6 when you figure out which you want.
3 Comments
See Also
Categories
				Find more on Object Containers in Help Center and File Exchange
			
	Products
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!
