시뮬링크 상에서 3차원 공간 상의 움직이는 강체의 자세를 보고싶을 때가 있다. 멀티로터 혹은 고정익들은 기체의 크기에 비해 움직이는 공간이 크기 때문에 기체의 스케일을 키우면 이동 궤적이 잘 보이지 않는 문제가 있을 수 있는데, 기체에 초점을 맞추어 그려주면 되지 않을까?
본 글은 Simulink의 'Interpreted MATLAB Fcn'이라는 함수를 통해서 MATLAB 스크립트가 비행체의 자세를 애니메이션으로 표현하는 방법을 소개한다.
결과를 먼저 보면 다음과 같다. 롤 각 45도, 피치각을 -30도, 전방 좌측으로 기울인 후에 일정 속도로 요잉을 하는 움직임이다.
MATLAB 스크립트 작성
MATLAB 함수는 다음과 같이 정의했다. 간단히 말하면 전방 로터를 빨갛게 칠한 쿼드로터의 자세를 표현하고 있다.
입력은 시뮬레이션 시간과 방향 코사인 행렬을 벡터로 변환하여 입력한다. 함수의 출력은 무의미하다.
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
|
function y = view_atti(in)
time = in(1);
CB2N = reshape(in(2:10),3,3);
y = 1;
persistent prev_time_for_view;
if isempty(prev_time_for_view)
prev_time_for_view = time;
end
if time == 0.0
prev_time_for_view = 0.0;
end
dT = 0.1;
if (time < prev_time_for_view + dT)
return;
else
prev_time_for_view = time;
end
figure(1);
t = linspace(0,2*pi,16);
diameter = 0.100;
arm_len = 0.330/2;
lims = diameter*1.5 + arm_len;
arms{1} = (arm_len*[cosd(45) sind(45) 0]);
arms{2} = (arm_len*[cosd(-45) sind(-45) 0]);
arms{3} = (arm_len*[cosd(-135) sind(-135) 0]);
arms{4} = (arm_len*[cosd(135) sind(135) 0]);
Circle_big{1} = CB2N*(diameter*[cos(t') sin(t') zeros(size(t))']+arms{1})';
Circle_big{2} = CB2N*(diameter*[cos(t') sin(t') zeros(size(t))']+arms{2})';
Circle_big{3} = CB2N*(diameter*[cos(t') sin(t') zeros(size(t))']+arms{3})';
Circle_big{4} = CB2N*(diameter*[cos(t') sin(t') zeros(size(t))']+arms{4})';
trans_arms{1} = CB2N*arms{1}';
trans_arms{2} = CB2N*arms{2}';
trans_arms{3} = CB2N*arms{3}';
trans_arms{4} = CB2N*arms{4}';
fill3( Circle_big{1}(2,:), Circle_big{1}(1,:), -Circle_big{1}(3,:),'r',...
Circle_big{2}(2,:), Circle_big{2}(1,:), -Circle_big{2}(3,:),'r',...
Circle_big{3}(2,:), Circle_big{3}(1,:), -Circle_big{3}(3,:),'k',...
Circle_big{4}(2,:), Circle_big{4}(1,:), -Circle_big{4}(3,:),'k'...
); hold on; grid on;
plot3( [0 trans_arms{1}(2)],[0 trans_arms{1}(1)],-[0 trans_arms{1}(3)],'r',...
[0 trans_arms{2}(2)],[0 trans_arms{2}(1)],-[0 trans_arms{2}(3)],'r',...
[0 trans_arms{3}(2)],[0 trans_arms{3}(1)],-[0 trans_arms{3}(3)],'k',...
[0 trans_arms{4}(2)],[0 trans_arms{4}(1)],-[0 trans_arms{4}(3)],'k','LineWidth',2);
hold off;
xlim([-lims lims]); ylim([-lims lims]); zlim([-lims lims]);
grid on;
view(30,30);
title_str = sprintf('Attitude of model @ %.1f s',time);
title(title_str);
xlabel('x'); ylabel('y');
drawnow;
|
cs |
코드의 구조를 간단히 설명하면 (1) 정해진 주기 시간 dt 을 정하여 시간 확인을 통해서 정해진 주기에 그림을 그리도록 한다. (2) 동체 좌표계 상에서 로터 암과 로터 디스크를 정의한 후 동체 좌표계에서 관성 좌표계로 좌표변환행렬인 방향 코사인 행렬을 이용하여 기체의 로터 암과 디스크를 관성 좌표계 상에서 표현한다. (3) 로터 디스크는 fill3 함수로 공간 상의 안을 채운 다각형을, 로터 암은 plot3로 공간상의 선으로 그린다.
하이라이팅이 이상한건 color script가 지원하는 프로그래밍 언어로 MATLAB 혹은 octave 가 없어서 그렇다.
Simulink 블록 작성 예시
Simulink에서의 Aerospace blockset을 이용한 예는 다음과 같다. 그리고 우측의 'Interpreted MATLAB Fcn'에 함수 이름을 넣어주면 된다. 블록 이름은 상관 없다. 아래와 같이 롤, 피치, 요 자세각을 넣어주면 MATLAB 함수로 정의한 그림 함수가 자세를 정해진 주기마다 그려주게 된다.
참고로 위의 방법이 아닌 Aerospace blockset의 '6DoF Animation' 블록을 이용해서도 위와 같이 그림을 그릴 수 있다. 그러나 조금 방법에 차이가 있으며, '6DoF Animation'은 s-function을 이용하는 saeroanim.m을 workspace에 넣고 작업을 해주어야한다. 이 방법은 추후 여유가 있다면 이어서 포스팅을 하고자 한다.
'SW > Others' 카테고리의 다른 글
python으로 사진 파일 이름 바꾸기 (0) | 2022.10.03 |
---|---|
[PYTORCH] conda 환경에서 vscode에서 쓸 때, DLL load failed (0) | 2021.07.22 |
[PYTHON] MATLAB plot처럼 matplotlib 다루기 (1) - 기본 속성 편 (0) | 2021.07.15 |
[PYTHON] MATLAB의 drawnow처럼 움직이는 plot 만들기 (0) | 2021.04.04 |
알고리즘 공부 어떻게 시작할까? (0) | 2021.03.22 |