MATLAB Answers

Why is my Matlab hgtransform matrix invalid?

13 views (last 30 days)
Richard Crozier
Richard Crozier on 22 Feb 2017
Commented: Richard Crozier on 22 Feb 2017
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

  1 Comment

Richard Crozier
Richard Crozier on 22 Feb 2017
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.

Sign in to comment.

Answers (1)

Walter Roberson
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

Richard Crozier
Richard Crozier on 22 Feb 2017
Thanks for the fast answer, but yes, as I explain, the rotation is not what I intended (probably because the cross product order is not correct), but the matrix to me still seems like a valid transformation matrix. The question is really why does hgtransform not like what appears to be a valid transformation matrix (irrespective of the fact that it was not what I intended, i.e. gives a rotation in the opposite direction than desired).
Richard Crozier
Richard Crozier on 22 Feb 2017
I edited the question to show my transform matrix appears to do the same as one generated with makehgtform.
Richard Crozier
Richard Crozier on 22 Feb 2017
Actually I see that it is probably due to the -ve scaling coefficient (perhaps this is what you meant?) I've added a comment to the question with a link to the relevant matlab doc.

Sign in to comment.

Sign in to answer this question.