Why is my Matlab hgtransform matrix invalid?

15 次查看(过去 30 天)
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 个评论
Richard Crozier
Richard Crozier 2017-2-22
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.

请先登录,再进行评论。

回答(1 个)

Walter Roberson
Walter Roberson 2017-2-22
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 个评论
Richard Crozier
Richard Crozier 2017-2-22
I edited the question to show my transform matrix appears to do the same as one generated with makehgtform.
Richard Crozier
Richard Crozier 2017-2-22
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.

请先登录,再进行评论。

类别

Help CenterFile Exchange 中查找有关 Graphics Performance 的更多信息

产品

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by