Calculate 3 x 3 rotation matrices from 3 x n matrix

21 views (last 30 days)
Thomas
Thomas on 9 Oct 2012
I am using the following code to open a .csv file, index columns of interest (euler rotations around x, y, z axes) as single column arrays, and then sequentially order these as a 3 x n matrix:
%Imports geometric camera parameters from phtosynth output .csv in the
%current directory and orders columns as seperate 1 x n matrices
if exist('PARAMETERS_0.csv', 'file') == 2
disp('file found')
[PX PY PZ RX RY RZ] = csvimport('PARAMETERS_0.csv', 'columns', {' PositionX', ' PositionY', ' PositionY', ' RotationX', ' RotationY', ' RotationZ'});
else
disp('camera parameters input file not found')
end
% Sequentially indexes RX RY RZ into a 3 x n matrix where columns are euler
% angles around x y z axes
for i=1:length(RX)
MRV(:,i)=[RX(i);RY(i);RZ(i)];
end
The resulting 3 x n matrix looks like this:
[0.5053 0.5300 0.3820 -0.1594 -0.1289 -0.1107 -1.1684
1.4532 1.4258 1.1240 1.2185 1.2424 1.2131 0.9390
1.4532 1.4258 1.1240 1.2185 1.2424 1.2131 0.9390]
Where individual columns represent euler rotations around x, y z axis (in descending order), describing the orientation of a camera:
e.g.
POV1 =
0.5053
1.4532
1.4532
My problem is that I need to use the euler rotations represented as column vectors in the matrix (MRV) as inputs to calculate a 3 x 3 rotation matrix for each camera position (POV1,..,POVn). The functions to achieve this in the command console would be as follows (example using column 1):
Rx1 = [1 0 0; 0 cosd(MPV(1,1)) -sind(MPV(1,1)); 0 sind(MPV(1,1)) cosd(MPV(1,1))];
Ry1 = [cosd(MPV(2,1)) 0 sind(MPV(2,1)); 0 1 0; -sind(MPV(2,1)) 0 cosd(MPV(2,1))];
Rz1 = [cosd(MPV(3,1)) -sind(MPV(3,1)) 0; sind(MPV(3,1)) cosd(MPV(3,1)) 0; 0 0 1];
RM1 = Rz1*Ry1*Rx1
This function would need to be applied sequentially to each column to give an output rotation matrix of the form:
r11 r12 r13
r21 r22 r23
r31 r32 r33
I know that the code needed would be a for loop of some description but am a bit stuck on the nature of the syntax needed. Any help would be greatly appreciated. Note that I need also to concatenate this rotation matrix with a column vector from an equivalent 3 x n matrix to MRV (x y z position) and a single row array (0 0 0 1) to produce a 4 x 4 matrix (homogeneous coordinates) of the form:
r11 r12 r13 x
r21 r22 r23 y
r31 r32 r33 z
0 0 0 1
So any solution would have to be compatible with next stage in the analysis

Accepted Answer

Julien
Julien on 9 Oct 2012
Edited: Julien on 9 Oct 2012
Ok I found an other way, more properly, to store you resulting matrices. You will store them inside a structure and create dynamics fieldnames.
the final code will looks like this :
euler=struct();
for k=1:size(MPV,2)
Rxk = [1 0 0; 0 cosd(MPV(1,k)) -sind(MPV(1,k)); 0 sind(MPV(1,k)) cosd(MPV(1,k))];
Ryk = [cosd(MPV(2,k)) 0 sind(MPV(2,k)); 0 1 0; -sind(MPV(2,k)) 0 cosd(MPV(2,k))];
Rzk = [cosd(MPV(3,k)) -sind(MPV(3,k)) 0; sind(MPV(3,k)) cosd(MPV(3,k)) 0; 0 0 1];
RMk = Rzk*Ryk*Rxk;
euler.(['PV' num2str(k)])=RMk;
end
then to acces one specific matrix, you have to enter euler.PVi. For example, if you want to access PV1, type euler.PV1
  2 Comments
Julien
Julien on 9 Oct 2012
you're welcome ;) in fact concatenation is really simple. for example with PV 1: example:
PV1=[PV1 [x y z]';[0 0 0 1]];
using brackets, when you let a space, that indicates you will add columns, and puting a semilcon indicates that you put lines.
so in my code, I first add the x y z column (I use transpose to show you several way to do this. You could also put
[x;y;z]
then I added the line
[0 0 0 1]

Sign in to comment.

More Answers (1)

Julien
Julien on 9 Oct 2012
Edited: Julien on 9 Oct 2012
Hi Thomas,
The code is not hard to write. When you want to make sequential calculations, you have first to write it for one specified point (as you did with your first column), and then convert it for any column (by setting indexes).
So if i re-write your code for a column k :
Rxk = [1 0 0; 0 cosd(MPV(1,k)) -sind(MPV(1,k)); 0 sind(MPV(1,k)) cosd(MPV(1,k))];
Ryk = [cosd(MPV(2,k)) 0 sind(MPV(2,k)); 0 1 0; -sind(MPV(2,k)) 0 cosd(MPV(2,k))];
Rzk = [cosd(MPV(3,k)) -sind(MPV(3,k)) 0; sind(MPV(3,k)) cosd(MPV(3,k)) 0; 0 0 1];
RMk = Rzk*Ryk*Rxk
Then, you only need to vary k from 1 to the number of column you have to calculate, that means :
for k=1:size(MPV,2)
Rxk = [1 0 0; 0 cosd(MPV(1,k)) -sind(MPV(1,k)); 0 sind(MPV(1,k)) cosd(MPV(1,k))];
Ryk = [cosd(MPV(2,k)) 0 sind(MPV(2,k)); 0 1 0; -sind(MPV(2,k)) 0 cosd(MPV(2,k))];
Rzk = [cosd(MPV(3,k)) -sind(MPV(3,k)) 0; sind(MPV(3,k)) cosd(MPV(3,k)) 0; 0 0 1];
RMk = Rzk*Ryk*Rxk
end
But if you let it like this, your RMk matrix will be replaced at each iteration. So the question is, how do you want to store each matrix .
EDIT :
You can store each matrix in separated variables using assigning function, so replace
RMk = Rzk*Ryk*Rxk
by
assignin('base',['RM' num2str(k)],Rzk*Ryk*Rxk)
  4 Comments
Julien
Julien on 9 Oct 2012
yes sure it works but it is not the best solution. I think it depends on the complexity of your code (same as using global variables, eval function ... ) Matlab provides certainly more subtle solutions, for optimization considerations.

Sign in to comment.

Community Treasure Hunt

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

Start Hunting!