Featured
- Get link
- X
- Other Apps
What is Rotation Matrix 1 : Rotation Sequence
앞선 포스팅에"DCM 2"에서는 기준 좌표계에서 상대 좌표계로의 회전 관계를 3가지로 나누어 단순화 하고 이를 수식화 해보았다. 그리고 Rotation Matrix는 DCM과 같이 많이 사용되는 회전 행렬이며 DCM과 큰 차이가 없어 혼용되고 있는데 정확히는 DCM 행렬의 Transpose 관계이다. 그러므로 이전에 계산했던 DCM 행렬들의 Transpose가 곧 Rotation Matrix이다.
Rotation Matrix도 마찬가지로 Yaw, Pitch 그리고 Roll을 사용하는데 단순히 원하는 각도를 무작위로 넣어서 곱해주는 걸까? 물론 운이좋으면 원하는 바와 맞는 결과를 얻을 수 있겠지만 이를 규칙있게 잘 표현하기위해 Rotation Sequence라는 것이 존재한다. 다음에 정리된 표는 각 Rotation Sequence에 의한 결과를 정리한 표이다. 이는 Proper Euler Angles 그리고 Tait-Bryan Angles로 나뉜다(둘의 차이는 당장에 중요하지 않아서 나중에 다룰 예정임).
이렇게 표준화 해놓은 이유는 오일러 각의 순서가 일관되어야 하는 이유인데, 이런식으로 선택할 수 있는 시퀀스가 많기 때문에 분야마다 표준이 다르다. 그러므로 세 개의 각도 회전 시퀀스가 선택되면 항상 해당 순서로 변환해야 한다. 그렇지 않으면 올바른 최종 방향을 얻지 못할 수 있다.
그러면 많이 사용되는 3-2-1(Z-Y-X, Yaw-Pitch-Roll) 순서에 대한 Rotation Matrix을 확인해보자.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | clear all; close all; clc; deg2rad = pi/180; rad2deg = 180/pi; x = [1 0 0]'; y = [0 1 0]'; z = [0 0 1]'; Yaw = 10 * deg2rad; Pitch = 20 * deg2rad; Roll = 30 * deg2rad; DCM_mat = angle2dcm(Yaw,Pitch,Roll,'ZYX'); Rot_mat = DCM_mat';% Rotation Matrix와 DCM은 Transpose 관계! b_1 = Rot_mat*x; b_2 = Rot_mat*y; b_3 = Rot_mat*z; figure; quiver3(0,0,0,x(1,1),x(2,1),x(3,1),'k','LineWidth',2); hold on; grid on; quiver3(0,0,0,y(1,1),y(2,1),y(3,1),'k','LineWidth',2); quiver3(0,0,0,z(1,1),z(2,1),z(3,1),'k','LineWidth',2); quiver3(0,0,0,b_1(1,1),b_1(2,1),b_1(3,1),'r','LineWidth',2); quiver3(0,0,0,b_2(1,1),b_2(2,1),b_2(3,1),'g','LineWidth',2); quiver3(0,0,0,b_3(1,1),b_3(2,1),b_3(3,1),'b','LineWidth',2); axis equal; axis([-1 1 -1 1 -1 1]); xlabel('X - base Frame'); ylabel('Y - base Frame'); zlabel('Z - base Frame'); str = sprintf('Yaw:%3.3f[deg],Pitch:%3.3f[deg],Roll:%3.3f[deg]',... Yaw*rad2deg,Pitch*rad2deg,Roll*rad2deg); title(str); legend('X','Y','Z','b_1','b_2','b_3') %%%%%%%%%%%%%% % Result:
% b_1 =
% 0.9254
% 0.1632
% -0.3420
% b_2 =
% 0.0180
% 0.8826
% 0.4698
% b_3 =
% 0.3785
% -0.4410
% 0.8138 %%%%%%%%%%%%%%% | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | close all; clear all; clc; deg2rad = pi/180; rad2deg = 180/pi; z_final_angle = 30*deg2rad; y_final_angle = 20*deg2rad; x_final_angle = 10*deg2rad; z_des_angle = linspace(0, z_final_angle,100)'; y_des_angle = linspace(0, y_final_angle,100)'; x_des_angle = linspace(0, x_final_angle,100)'; zero_z_angle = zeros(length(z_des_angle),1)+z_final_angle; zero_y_angle = zeros(length(y_des_angle),1)+y_final_angle; zero_x_angle = zeros(length(x_des_angle),1)+x_final_angle; des_angle = [ x_des_angle, y_des_angle, z_des_angle; zero_x_angle, zero_y_angle,zero_z_angle ]; z = [0 0 1]'; y = [0 1 0]'; x = [1 0 0]'; dcm_final = angle2dcm(des_angle(length(des_angle),3),des_angle(length(des_angle),2),des_angle(length(des_angle),1),'ZYX'); rot_final = dcm_final'; basis_z_final = rot_final*z; basis_y_final = rot_final*y; basis_x_final = rot_final*x; figure; quiver3(0,0,0,1,0,0,'k'); hold on; grid on; xlabel('X-axis'); ylabel('Y-axis'); zlabel('Z-axis'); quiver3(0,0,0,0,1,0,'k'); quiver3(0,0,0,0,0,1,'k'); axis equal; axis([-1.5 1.5 -1.5 1.5 -1.5 1.5]); view(135,30) % basisX = [1 0 0]'; basisY = [0 1 0]'; basisZ = [0 0 1]'; basisX_handler = quiver3(0,0,0,0,0,0); basisX_handler.Color = 'r'; basisX_handler.LineWidth = 3; basisX_handler.UData = 1; basisX_handler.VData = 0; basisX_handler.WData = 0; basisY_handler = quiver3(0,0,0,0,0,0); basisY_handler.Color = 'g'; basisY_handler.LineWidth = 3; basisY_handler.UData = 0 ; basisY_handler.VData = 1; basisY_handler.WData = 0; basisZ_handler = quiver3(0,0,0,0,0,0); basisZ_handler.Color = 'b'; basisZ_handler.LineWidth = 3; basisZ_handler.UData = 0; basisZ_handler.VData = 0; basisZ_handler.WData = 1; xlabel('X-axis'); ylabel('Y-axis'); zlabel('Z-axis'); quiver3(0,0,0,basis_z_final(1),basis_z_final(2),basis_z_final(3),'k'); quiver3(0,0,0,basis_y_final(1),basis_y_final(2),basis_y_final(3),'k'); quiver3(0,0,0,basis_x_final(1),basis_x_final(2),basis_x_final(3),'k'); pause(10) for i=1:1:length(des_angle) str = sprintf('Roll:%3.3f[deg], Pitch:%3.3f[deg], Yaw:%3.3f[deg]', des_angle(i,1)*rad2deg, des_angle(i,2)*rad2deg, des_angle(i,3)*rad2deg); title(str); dcm = angle2dcm( des_angle(i,3), des_angle(i,2), des_angle(i,1), 'ZYX' ); rot = dcm'; basis_Xr_vec = rot*x; basis_Yr_vec = rot*y; basis_Zr_vec = rot*z; basisX_handler.UData = basis_Xr_vec(1,1); basisX_handler.VData = basis_Xr_vec(2,1); basisX_handler.WData = basis_Xr_vec(3,1); basisY_handler.UData = basis_Yr_vec(1,1); basisY_handler.VData = basis_Yr_vec(2,1); basisY_handler.WData = basis_Yr_vec(3,1); basisZ_handler.UData = basis_Zr_vec(1,1); basisZ_handler.VData = basis_Zr_vec(2,1); basisZ_handler.WData = basis_Zr_vec(3,1); drawnow; pause(0.01); end | cs |
해당 표에서 3-2-1에 해당하는 부분을 살펴보면 다음과 같다.
$$\alpha(:yaw) = arctan\left(\frac{R_{21}}{R_{11}}\right)\;\;eq.1$$
$eq.1$를 보면 $R_{11} = cos\theta sin\psi$이고 $R_{21} = -cos\theta sin\psi$ 이다. 같은 방법으로 $eq.2$, $eq.3$을 확인하면 역탄젠트 안에 있는 분수의 분모가 0이 되는 순간은 Rotation Matrix를 이용하여 각도를 계산 할 수 없는 상황이다. 다음 그림을 통해 확인해보자
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 | close all; clear all; clc; deg2rad = pi/180; rad2deg = 180/pi; z_final_angle = 45*deg2rad; y_final_angle = 180*deg2rad; x_final_angle = 50*deg2rad; z_des_angle = linspace(0, z_final_angle,100)'; % y_des_angle = linspace(0, y_final_angle,100)'; y_des_angle = zeros(1, length(z_des_angle))'+y_final_angle; x_des_angle = linspace(0, x_final_angle,100)'; zero_z_angle = zeros(length(z_des_angle),1)+z_final_angle; zero_y_angle = zeros(length(y_des_angle),1)+y_final_angle; zero_x_angle = zeros(length(x_des_angle),1)+x_final_angle; des_angle = [ x_des_angle, y_des_angle, z_des_angle; zero_x_angle, zero_y_angle,zero_z_angle ]; z = [0 0 1]'; y = [0 1 0]'; x = [1 0 0]'; dcm_final = angle2dcm(des_angle(length(des_angle),3),des_angle(length(des_angle),2),des_angle(length(des_angle),1),'ZYX'); rot_final = dcm_final'; basis_z_final = rot_final*z; basis_y_final = rot_final*y; basis_x_final = rot_final*x; figure; quiver3(0,0,0,1,0,0,'k'); hold on; grid on; xlabel('X-axis'); ylabel('Y-axis'); zlabel('Z-axis'); quiver3(0,0,0,0,1,0,'k'); quiver3(0,0,0,0,0,1,'k'); axis equal; axis([-1.5 1.5 -1.5 1.5 -1.5 1.5]); view(135,30) % basisX = [1 0 0]'; basisY = [0 1 0]'; basisZ = [0 0 1]'; basisX_handler = quiver3(0,0,0,0,0,0); basisX_handler.Color = 'r'; basisX_handler.LineWidth = 3; basisX_handler.UData = 1; basisX_handler.VData = 0; basisX_handler.WData = 0; basisY_handler = quiver3(0,0,0,0,0,0); basisY_handler.Color = 'g'; basisY_handler.LineWidth = 3; basisY_handler.UData = 0 ; basisY_handler.VData = 1; basisY_handler.WData = 0; basisZ_handler = quiver3(0,0,0,0,0,0); basisZ_handler.Color = 'b'; basisZ_handler.LineWidth = 3; basisZ_handler.UData = 0; basisZ_handler.VData = 0; basisZ_handler.WData = 1; xlabel('X-axis'); ylabel('Y-axis'); zlabel('Z-axis'); quiver3(0,0,0,basis_z_final(1),basis_z_final(2),basis_z_final(3),'k'); quiver3(0,0,0,basis_y_final(1),basis_y_final(2),basis_y_final(3),'k'); quiver3(0,0,0,basis_x_final(1),basis_x_final(2),basis_x_final(3),'k'); % pause(10) for i=1:1:length(des_angle) % rot = rot_z(des_angle(i,3))*rot_y(des_angle(i,2))*rot_x(des_angle(i,1)); % [y,p,r] = dcm2angle(rot','ZYX'); % str = sprintf('Rotattion Matrix to Angle\nRoll:%3.3f[deg], Pitch:%3.3f[deg], Yaw:%3.3f[deg]\nTrue Angle\nRoll:%3.3f[deg], Pitch:%3.3f[deg], Yaw:%3.3f[deg]',... % r*rad2deg, p*rad2deg, y*rad2deg, des_angle(i,1)*rad2deg, des_angle(i,2)*rad2deg, des_angle(i,3)*rad2deg); % title(str); dcm = angle2dcm( des_angle(i,3), des_angle(i,2), des_angle(i,1), 'ZYX' ); [yaw,pitch,roll] = dcm2angle(dcm,'ZYX'); rot = dcm'; basis_Xr_vec = rot*x; basis_Yr_vec = rot*y; basis_Zr_vec = rot*z; str = sprintf('Rotation Matrix to Angle\nRoll:%3.3f[deg], Pitch:%3.3f[deg], Yaw:%3.3f[deg]\nTrue Angle\nRoll:%3.3f[deg], Pitch:%3.3f[deg], Yaw:%3.3f[deg]',... roll*rad2deg, pitch*rad2deg, yaw*rad2deg, des_angle(i,1)*rad2deg, des_angle(i,2)*rad2deg, des_angle(i,3)*rad2deg); title(str); basisX_handler.UData = basis_Xr_vec(1,1); basisX_handler.VData = basis_Xr_vec(2,1); basisX_handler.WData = basis_Xr_vec(3,1); basisY_handler.UData = basis_Yr_vec(1,1); basisY_handler.VData = basis_Yr_vec(2,1); basisY_handler.WData = basis_Yr_vec(3,1); basisZ_handler.UData = basis_Zr_vec(1,1); basisZ_handler.VData = basis_Zr_vec(2,1); basisZ_handler.WData = basis_Zr_vec(3,1); drawnow; pause(0.1); end | cs |
[1] https://en.wikipedia.org/wiki/Euler_angles
Popular Posts
Simple MATLAB simulation using Euler rigid body equation and Quaternion kinematics
- Get link
- X
- Other Apps
What is Direction Cosine Matrix 2 - DCM 1
- Get link
- X
- Other Apps
Comments
Post a Comment