Why does my 3 axes system coordinate orientation change x with y values? - matlab

I am using Matlab and Euler Angles in order to reorient a 3axes coordinate system. Specifically,
Rz = [cos(ψ) sin(ψ) 0;-sin(ψ) cos(ψ) 0;0 0 1];
Ry = [cos(φ) 0 -sin(φ);0 1 0;sin(φ) 0 cos(φ)];
Rx = [1 0 0;0 cos(θ) -sin(θ);0 sin(θ) cos(θ)];
Rtotal = Rz*Ry*Rz
Then I loop through my old system coordinates (x,y,z) and make a vector coord_old. Then I get the reoriented system with (xn,yn,zn)
for i=1:size(num,1)
coord_old = [x(i,1);y(i,1);z(i,1)];
coord_new = Rtotal*coord_old;
xn(i,1) = coord_new(1,1);
yn(i,1) = coord_new(2,1);
zn(i,1) = coord_new(3,1);
end
My issue is that when θ,φ,ψ≃0 then x->-y and y->x and when θ,φ≃0 and ψ=90 then x and y will not rotate! That means that when x,y should rotate they don't and when they shouldn't rotate they stay as they were!
--EDIT--
For example, when ψ=20.0871, φ=0.0580 and θ=0.0088 I get these results
See that x->-y and y->x while z doesn't change at all!
Any thoughts?

Ok, I see two main problems here:
Rtotal = Rz*Ry*Rz is probably not what you want since Rz is multiplied twice. I think you mean Rtotal = Rz*Ry*Rx.
Your rotation matrix seems to be incorrect. Check this Wikipedia artice to get the correct signs.
Here a corrected rotation matrix:
Rz = [cos(psi) -sin(psi) 0; sin(psi) cos(psi) 0; 0 0 1];
Ry = [cos(phi) 0 sin(phi); 0 1 0; -sin(phi) 0 cos(phi)];
Rx = [1 0 0; 0 cos(theta) -sin(theta); 0 sin(theta) cos(theta)];
Rtotal = Rz*Ry*Rx;
With this matrix I get the correct results:
x=1; y=2; z=3;
psi=0; phi=0; theta=0;
[xn,yn,zn] >> 1 2 3
x=1; y=2; z=3;
psi=90/180*pi; phi=0; theta=0;
[xn,yn,zn] >> -2 1 3
And here a full graphical example of a cube in 3d-space:
% Create cube (not in origin)
DVert = [0 0 0; 0 1 0; 1 1 0; 1 0 0 ; ...
0 0 1; 0 1 1; 1 1 1; 1 0 1];
DSide = [1 2 3 4; 2 6 7 3; 4 3 7 8; ...
1 5 8 4; 1 2 6 5; 5 6 7 8];
DCol = [0 0 1; 0 0.33 1; 0 0.66 1; ...
0 1 0.33; 0 1 0.66; 0 1 1];
% Rotation angles
psi = 20 /180*pi; % Z
phi = 45 /180*pi; % Y
theta = 0 /180*pi; % X
% Rotation matrix
Rz = [cos(psi) -sin(psi) 0; sin(psi) cos(psi) 0; 0 0 1];
Ry = [cos(phi) 0 sin(phi); 0 1 0; -sin(phi) 0 cos(phi)];
Rx = [1 0 0; 0 cos(theta) -sin(theta); 0 sin(theta) cos(theta)];
Rtotal = Rz*Ry*Rz;
% Apply rotation
DVertNew = Rtotal * DVert';
% Plot cubes
figure;
patch('Faces',DSide,'Vertices',DVert,'FaceColor','flat','FaceVertexCData',DCol);
patch('Faces',DSide,'Vertices',DVertNew','FaceColor','flat','FaceVertexCData',DCol);
% Customize view
grid on;
axis equal;
view(30,30);

When I use your code and insert 0 for all angles, I get Rtotal:
Rtotal =
1 0 0
0 1 0
0 0 1
This is the identity matrix and will not change your values.
You have an error in your matrix multiplication. I think you should multiply: Rtotal*coord_old. I think you are missing the _old. depending on what is in you coordvariable, this may be the bug.
When I run:
for i=1:size(1,1)
coord_old = [1;2;3];
coord_new = Rtotal*coord_old;
xn(i,1) = coord_new(1,1);
yn(i,1) = coord_new(2,1);
zn(i,1) = coord_new(3,1);
end
I get the correct result:
coord_new =
1
2
3

Thank you both #Steffen and #Matt. Unfortunately, my reputation is not high enough to vote Up your answers!
The problem was not with Rtotal as #Matt correctly stated. It should be as it was Rz*Ry*Rx. However, both your ideas helped me test my code with simple examples (5 sets of coordinates and right hand rule), and realize where my (amateur) mistake was.
I had forgotten I had erased parts of codes where I was expressing my angles to degrees... I should be using sind & cosd instead of sin and cos.

Related

Make a one simple code from several similar code

Hello everybody I have a very simple problem, I have too many data y, p and r. So I want to calculate it in a single code.
This an example of my code if I breakdown into separate code
y1=45
y2=56
y3=67
p1=34
p2=45
p3=56
r1=23
r2=34
r3=45
Ryaw1=[cosd(y1) -sind(y1) 0;
sind(y1) cosd(y1) 0;
0 0 1]
Rpitch1=[cosd(p1) 0 sind(p1);
0 1 0;
-sind(p1) 0 cos(p1)]
Rroll1=[1 0 0;
0 cosd(r1) -sind(r1);
0 sind(r1) cosd(r1)]
R1=Ryaw1*Rpitch1*Rroll1
Coordinate1=R1*X0
Ryaw2=[cosd(y2) -sind(y2) 0;
sind(y2) cosd(y2) 0;
0 0 1]
Rpitch2=[cosd(p2) 0 sind(p2);
0 1 0;
-sind(p2) 0 cos(p2)]
Rroll2=[1 0 0;
0 cosd(r2) -sind(r2);
0 sind(r2) cosd(r2)]
R2=Ryaw2*Rpitch2*Rroll2
Coordinate2=R2*X0
Ryaw3=[cosd(y3) -sind(y3) 0;
sind(y3) cosd(y3) 0;
0 0 1]
Rpitch3=[cosd(p3) 0 sind(p3);
0 1 0;
-sind(p3) 0 cos(p3)]
Rroll3=[1 0 0;
0 cosd(r3) -sind(r3);
0 sind(r3) cosd(r3)]
R3=Ryaw3*Rpitch3*Rroll3
Coordinate3=R3*X0
Coordinate=[Cooedinate1 Coordinate2 Coordinate3]
The goals is to find "Coordinate" (in matrix - combined from Coordinate1, Coordinate2, Coordinate3, .... ,Coordinate..) from every y, p and r data with the same "X0" as a single primary data for calculation.
Sorry for my bad english,
Thanks :)
Use vectors and matrices instead of individual scalars. These are indexed in almost the same way as you had before, i.e. y1 becomes y(1).
Then you can easily loop over the code 3 times and save the repetition.
See my commented code below.
% Define some X0. This should be a column vector.
X0 = [1; 2; 3];
% Make y,p,r into 3 element vectors
y = [45 56 67];
p = [34 45 56];
r = [23 34 45];
% Make R, Ryaw, Rpitch and Rroll 3x3x3 matrices
R = zeros(3,3,3);
Ryaw = zeros(3,3,3);
Rpitch = zeros(3,3,3);
Rroll = zeros(3,3,3);
% Make Coordinate a 3x3 matrix
Coordinate = zeros(3,3);
% Loop k from 1 to 3
% For each 3x3x3 matrix, the kth 3x3 matrix is equivalent to your Ryawk, Rpitchk, Rrollk, Rk
for k = 1:3
Ryaw(:,:,k) = [cosd(y(k)) -sind(y(k)) 0
sind(y(k)) cosd(y(k)) 0
0 0 1];
Rpitch(:,:,k)= [cosd(p(k)) 0 sind(p(k))
0 1 0
-sind(p(k)) 0 cos(p(k))];
Rroll(:,:,k) = [1 0 0
0 cosd(r(k)) -sind(r(k))
0 sind(r(k)) cosd(r(k))];
R(:,:,k) = Ryaw(:,:,k)*Rpitch(:,:,k)*Rroll(:,:,k);
Coordinate(:,k) = R(:,:,k)*X0;
end
disp(Coordinate)

Homographic image transformation issue for sattelite images

I want to apply homography to the satellite images. I found this post quite helpful. So I decided to use the same Matlab code.
im = imread('cameraman.tif');
n = [0;0;-1];
d = Inf
theta = 60*pi/180;
R = [ 1 0 0 ;
0 cos(theta) -sin(theta);
0 sin(theta) cos(theta)];
t = [0;0;0];
K=[300 0 0;
0 300 0;
0 0 1];
H=K*R/K-1/d*K*t*n'*K;
img=imagehomog(im,H','c');
figure;imshow(img)
but the output is just the small box.
I am using MATLAB 2015b
EDIT
Homography using imtransform and maketform
n = [0;0;-1];
d = Inf;
im = imread('cameraman.tif');
theta = 60*pi/180;
R = [ 1 0 0 ;
0 cos(theta) -sin(theta);
0 sin(theta) cos(theta)];
t = [0;0;0];
K=[300 0 0;
0 300 0;
0 0 1];
H=K*R/K-1/d*K*t*n'*K;
tform = maketform('projective',H');
imT = imtransform(im,tform);
imshow(imT)
Output
How can I do it from the center. Something like this

Generating a 3D binary mask of geometric shapes in Matlab

I would like to generate a 3D binary mask which represents an ellipsoid with centers xc,yc,zc and radiuces xr,yr,zr.
I noticed that the function ellipsoid generates a mesh of points given these parameters. However, I want the data to be represented by a binary matrix (in my case, of size [100,100,100]), and not a mesh.
My Parameters are:
mask = zeros(100,100,100);
xc = 50; yc = 50; zc = 50;
xr = 15; yr = 15; zr = 15;
Thanks in advance!
To generate a binary mask of shapes which can use an equation you can follow the steps:
Generate a mesh (with ndgrid). Make sure the domain limits includes the volume/surface mask, and choose the mesh resolution according to your needs.
Use the volume/surface equation to generate a binary mask, by doing a simple logical comparison of the coordinates with the equation.
Simple 2D example:
Let's define a simple ellipse (in 2D).
%% // Simple 2D example
xc = 5 ; yc = 6 ; %// ellipse center = (5,6)
xr = 3 ; yr = 2 ; %// ellipse radiuses
xbase = linspace(0,10,11) ; %// temporary variable used to send to "ndgrid"
[xm,ym] = ndgrid( xbase , xbase ) ; %// generate base mesh
mask = ( ((xm-xc).^2/(xr.^2)) + ((ym-yc).^2/(yr.^2)) <= 1 ) %// get binary mask
Gives you the binary mask:
mask =
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 0 0 0 0
0 0 0 0 0 1 1 1 0 0 0
0 0 0 0 0 1 1 1 0 0 0
0 0 0 0 1 1 1 1 1 0 0
0 0 0 0 0 1 1 1 0 0 0
0 0 0 0 0 1 1 1 0 0 0
0 0 0 0 0 0 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
Granted you can hardly recognise an ellipse in the mask but I kept the resolution low to be able to display it as text. You can easily increase the resolution by defining a finer mesh.
3D Ellipsoid:
Well, it's exactly the same method, except we are going to add one dimension to the mesh, and use the 3D equation of the ellipsoid. So for your precise case:
%% // 3D ellipsoid
xc = 50; yc = 50; zc = 50;
xr = 15; yr = 15; zr = 15;
xbase = linspace(1,100,100) ;
[xm,ym,zm] = ndgrid( xbase , xbase , xbase) ;
mask = ( ((xm-xc).^2/(xr.^2)) + ((ym-yc).^2/(yr.^2)) + ((zm-zc).^2/(zr.^2)) <= 1 ) ;
I cannot show you a text output with these kind of 3D arrays, but your mask is now a 3D logical array containing true inside the ellipsoid and false elsewhere.
If I understood your question correctly, this should work:
mask = zeros(100, 100, 100);
%//your ellipsoid properties
xc = 50; yc = 50; zc = 50;
xr = 15; yr = 15; zr = 15;
for x=1:100
for y=1:100
for z=1:100
if ( ((x-xc)/xr)*((x-xc)/xr) + ((y-yc)/yr)*((y-yc)/yr) + ((z-zc)/zr)*((z-zc)/zr) < 1 )
mask(x,y,z) = 1; %//set elements within ellipsoid to 1
end
end
end
end
You can do this with Heaviside functions, this probably needs a bit more thought to get exactly what you want but as a start,
close all
clear all
%Setup Domain
maxdomain = 100;
mindomain = 0.;
step = 1.0;
X = mindomain:step:maxdomain;
Y = mindomain:step:maxdomain;
Z = mindomain:step:maxdomain;
[x,y,z] = meshgrid(X,Y,Z);
xc = 50; yc = 50; zc = 50;
xr = 15; yr = 15; zr = 15;
r2 = xr/2;
r = sqrt((x-xc).^2/xr + (y-yc).^2/yr + (z-zc).^2/zr);
u = heaviside(r-r2);
%Plot Surface of sphere
p = patch(isosurface(x,y,z,u));
isonormals(x,y,z,u,p)
set(p,'FaceColor','red','EdgeColor','none');
camlight ; alpha(0.6);
xlabel('x'); ylabel('y'); zlabel('z');
daspect([1,1,1]); view(3);
axis tight; camlight; camlight(-80,-10);
lighting gouraud;
which for your values above looks like,
and forxr = 15; yr = 45; zr = 15;,
The Heaviside function can be defined using,
function [out]=heaviside(x)
out=0.5.*(sign(x)+1.0);
end
if the Symbolic Math Toolbox is not available.

Debugging 24 symmetric operators

I have written the following code to calculate the disorientation between two points in a large dataset using 24 crystal symmetry operators. The code seems to work fine though the end result is not right. I have a huge dataset containing the euler angles for each points. I find the misorientation between 1st point and 2nd point and then between 2 and 3rd and so on.
I want the end result to contain the corresponding misorientaion angles for each two data points. Following is the full code for your better understanding of my requirement.
LA=[phi1 phi phi2];
function gi=get_gi(pvec)
%pvec is a 1x3 vector of [phi1 phi phi2]
g_11=((cosd(pvec(1)).*cosd(pvec(3)))-(sind(pvec(1)).*sind(pvec(3)).*cosd(pvec(2))));
g_12=((sind(pvec(1)).*cosd(pvec(3)))+(cosd(pvec(1)).*sind(pvec(3)).*cosd(pvec(2))));
g_13= (sind(pvec(3)).*sind(pvec(2)));
g_21 =((-cosd(pvec(1)).*sind(pvec(3)))-(sind(pvec(1)).*cos(pvec(3)).*cos(pvec(2))));
g_22 = ((-sin(pvec(1)).*sind(pvec(3)))+(cosd(pvec(1)).*cosd(pvec(3)).*cosd(pvec(2))));
g_23 = (cosd(pvec(3)).*sind(pvec(2)));
g_31 = (sind(pvec(1)).* sind(pvec(2)));
g_32 = -cosd(pvec(1)).* sind(pvec(2));
g_33 = cosd(pvec(2));
gi =[g_11 g_12 g_13;g_21 g_22 g_23;g_31 g_32 g_33];
f = [1 1 1 -1 1 -1 -1 -1 1 1 -1 -1];
l= [1 1 1];
for i=1:3:10
l1= [f(i) 0 0;0 f(i+1) 0;0 0 f(i+2)];
l2= [0 f(i) 0;0 0 f(i+1);f(i+2) 0 0];
l3= [0 0 f(i);f(i+1) 0 0;0 f(i+2) 0];
l4= -[0 0 f(i);0 f(i+1) 0;f(i+2) 0 0];
l5= -[0 f(i) 0;f(i+1) 0 0;0 0 f(i+2)];
l6= -[f(i) 0 0;0 0 f(i+1);0 f(i+2) 0];
l=[l;l1;l2;l3;l4;l5;l6];
end
k=1;
t=1;
for m=1:(length(a)-1)
for i=2:3:71
for j=2:3:71
g_r= (get_gi(LA(m,:)*l(i:i+2,1:3))*(inv(get_gi(LA(m+1,:)))*inv(l(j:j+2,1:3))));
tr(k)= g_r(1,1) + g_r(2,2) +g_r(3,3);
angle(k) = real(acosd((tr(k)-1)/2));
k=k+1;
end
angle(angle==0)=360;
del_theta=min(angle)
del(t)=del_theta;
t=t+1;
end

Projection matrix sign confusion (edited title)

Down I have edited my question.
I am projecting Wxyz to image(u,v) and getting some wrong result. I can't figure out where is mistake. Please help some one to figure out.
Given:
Wxyzz =
386.06 197.02 -1821.8 1
407.32 -108 -1859.1 1
4.9764 290.92 -1531.2 1
103.39 -233.07 -1643.2 1
189.7 320.19 -1667.9 1
76.279 147.9 -1597.2 1
47.798 -319.51 -1605.8 1
164.74 -223.1 -1688.6 1
482.06 -251.66 -1921.2 1
226.42 -213.27 -1733.6 1
Wxyz=Wxyz' %';
%# intrinsic
fu = 2640; fv =2640; uo= 1514; vo = 994;
A= [ fu 0 uo 0
0 fv vo 0
0 0 1 0
0 0 0 1];
Exterior=[-6.6861,12.6118,-8.0660,[-0.4467,-0.3168,0.2380]*pi/180];%# deg 2 rad
%#data
X0=Exterior(1);
Y0=Exterior(2);
Z0=Exterior(3);
ax=Exterior(4);
by=Exterior(5);
cz=Exterior(6);
%#Rotation in X
Rx = [1 0 0
0 cos(ax) -sin(ax)
0 sin(ax) cos(ax)];
%#Rotation in Y
Ry = [cos(by) 0 sin(by)
0 1 0
-sin(by) 0 cos(by)];
%#Rotation in Z
Rz = [cos(cz) -sin(cz) 0
sin(cz) cos(cz) 0
0 0 1];
R=Rx*Ry*Rz;
T=[X0;Y0;Z0];
Extrinsic= R';
Extrinsic(:,4) = -(R')* (T);
Extrinsic(4,:) = [0 0 0 1]
PImage = A* Extrinsic* Wxyz;
%#Obtain the X's
PImage(1 ,:) = PImage(1 ,:) ./ PImage(3 ,:);
%#Obtain the Y's
PImage(2 ,:) = PImage(2 ,:) ./ PImage(3 ,:);
I am getting
PImage =
955.93 707.43 -1814.4 1
939.75 1147.6 -1854.2 1
1506.3 490.36 -1521 1
1352.7 1370.2 -1637.6 1
1213.9 485.04 -1658.4 1
1389.7 749.08 -1588.5 1
1440.9 1521.6 -1600.6 1
1261.2 1344.2 -1683.2 1
857.22 1340 -1917.8 1
1173.9 1319.9 -1728.5 1
I supposed to get( real 2 D points)
img =
2072.8 706.69
2088.9 1146.9
1522.6 489.6
1676.1 1369.5
1814.9 484.3
1639.2 748.35
1587.9 1520.9
1767.6 1343.5
2171.4 1339.3
1854.9 1319.2
If I use
A= [ -fu 0 uo 0
0 fv vo 0
0 0 1 0
0 0 0 1];
I get corect answer.
I can't figure out where is mistake in rotation or translation; Why Pimage(:,1) is not identical with img(:,1).
Any help will be grateful.
You've done the rotation, and you've done the transformation.
What you need to do is the projection! Now I don't know what exactly you're trying to accomplish, but I don't see a projection matrix anywhere. So that's the first thing you need to fix.
Remember that doing a projection is a R4 -> R4 operation. If you're trying to get an R2 vector, you're trying to do something else (more).
see more at wikipedia.
if you really want to learn the details, you can watch and learn courtesy of YouTube