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?
15 vues (au cours des 30 derniers jours)
Afficher commentaires plus anciens
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
Réponses (1)
Walter Roberson
le 22 Fév 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 commentaires
Voir également
Catégories
En savoir plus sur Graphics Performance dans Help Center et File Exchange
Produits
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!