Home > リソース > MBDynチュートリアル > 12.アニメーション作成の基礎
MBDynチュートリアル

12.アニメーション作成の基礎

アニメーションの原理と、MBDynの出力データから剛体の運動のアニメーションを作成する方法について説明します。

移動する点のアニメーション

まず、1次元の簡単なケースでアニメーションの原理を説明します。

ある点が時間とともにx軸上を移動するとします。一定時間間隔の点位置 x のデータが x = x1, x2, x3, ... と与えられている時、点の動きを表すアニメーションは次の1〜3を循環(ループ)させることによって作成することができます。ただし、点は小さな円で表示することとします。(図1参照)

  1. 前の円を消去
  2. x = x i の位置に円を描画
  3. i = i + 1

animation_concept

図1: 移動する点のアニメーション(1次元)

コード1に、移動する点のアニメーションを作成するMATLABスクリプトの例を示します。また、このスクリプトを実行して得られるアニメーションを動画1に示します。

animation_point.m
% animation_point.m

clear; close all;

% Create data
t = 0:0.001:1;   % Time data
x = sin(2*pi*t); % Position data

% Draw initial figure
figure(1);
set(gcf,'Renderer','OpenGL'); 
h = plot(x(1),0,'o','MarkerSize',20,'MarkerFaceColor','b');
set(h,'EraseMode','normal');
xlim([-1.5,1.5]);
ylim([-1.5,1.5]);

% Animation Loop
i = 1;
while i<=length(x)
    set(h,'XData',x(i));
    drawnow;
    i = i+1;
end
コード1: 移動する点のアニメーションを作成するMATLABスクリプトの例



動画1: 移動する点のアニメーション

運動する剛体のアニメーション

剛体のアニメーションも、点のアニメーションと原理は全く同じです。剛体の場合、描画と消去の対象が3次元形状になるという違いがあるだけです。ただし、MBDynは剛体の運動をnodeという代表点の運動で記述するので、nodeのデータを3次元形状のデータに変換する手続きが必要になります。

例として、図2のように剛体の形状がブロックの場合を考えてみましょう。まず、初期時刻におけるブロックの頂点を定義します(図2左)。ブロックの形状はnodeに張り付いて動くので、任意の時刻における頂点の座標は、nodeの位置と姿勢から図2右のように求めることができます。頂点の座標が求まれば、ブロックの形状を描画できます。このようにして、nodeの位置と姿勢のデータから各時刻におけるブロックの頂点の座標を求め、ブロックの形状に対して描画と消去のループを回せば、ブロックのアニメーションを表示することができます。


animation_rigidbody

図2: 任意時刻におけるブロックの頂点の座標

MATLABでは、一般の3次元形状を作成するのに“パッチpatch)”が利用できます。パッチとは、3つ以上の点で定義される多角形の面です。パッチを組み合わせれば、任意の多面体を作ることができます。例えばブロック形状は、6個の四角形パッチを組み合わせて作ることができます。

さて、下のコード2は、例題2の自由回転するブロックの解析で出力されるmovファイルを読み込んで、ブロックの最上面のパッチのみをアニメーション表示するMATLABスクリプトです。動画2にこのスクリプトを実行して得られるアニメーションを示します。このようなパッチのアニメーションをブロックの6面全部について組み合わせれば、ブロックのアニメーションが完成します。

animation_patch.m
% animation_patch.m

clear; close all;

% Define Geometry Points (Vertices for the top surface of the block)
Lx = 0.15; %[m]
Ly = 0.05; %[m]
Lz = 0.30; %[m]

p1 = [  Lx/2,  Ly/2, Lz/2 ];
p2 = [  Lx/2, -Ly/2, Lz/2 ];
p3 = [ -Lx/2, -Ly/2, Lz/2 ];
p4 = [ -Lx/2,  Ly/2, Lz/2 ];

% Load Data
[LABEL,DATA] = MBDynLoad('free_rotating_block.mov');

r = DATA(:,[2:4],LABEL==1);        % Node Position [m]
A = DATA(:,[5:7],LABEL==1)*pi/180; % Node Orientation [rad] (x-y-z Euler angle)

n = size(r,1); % Data Length

% Euler Angle -> Orientation Matrix
for i=1:n
    a1 = A(i,1);
    a2 = A(i,2);
    a3 = A(i,3);
    
    R1 = [1, 0, 0;
        0, cos(a1), -sin(a1);
        0, sin(a1), cos(a1)];
    
    R2 = [cos(a2), 0, sin(a2);
        0, 1, 0;
        -sin(a2), 0, cos(a2)];
    
    R3 = [cos(a3), -sin(a3), 0;
        sin(a3), cos(a3), 0;
        0, 0, 1];
    
    R(:,:,i) = R1*R2*R3;
end

% Compute Propagation of Geometry Points
for i=1:n 
    r1(i,:) = r(i,:) + p1*R(:,:,1)*R(:,:,i)';
    r2(i,:) = r(i,:) + p2*R(:,:,1)*R(:,:,i)';
    r3(i,:) = r(i,:) + p3*R(:,:,1)*R(:,:,i)';
    r4(i,:) = r(i,:) + p4*R(:,:,1)*R(:,:,i)';
end

% Compile Data for Drawing Patch
PatchData_X = [r1(:,1),r2(:,1),r3(:,1),r4(:,1)];
PatchData_Y = [r1(:,2),r2(:,2),r3(:,2),r4(:,2)];
PatchData_Z = [r1(:,3),r2(:,3),r3(:,3),r4(:,3)];

% Draw Initial Figure
figure(1);
set(gcf,'Renderer','OpenGL');
h = patch(PatchData_X(1,:),PatchData_Y(1,:),PatchData_Z(1,:),'y');
set(h,'EraseMode','normal');
axis vis3d equal;
view([-37.5,30]);
camlight;
grid on;
xlim([-0.2,0.2]);
ylim([-0.2,0.2]);
zlim([-0.2,0.2]);

% Animation Loop
for i=1:n
    set(h,'XData',PatchData_X(i,:)');
    set(h,'YData',PatchData_Y(i,:)');
    set(h,'ZData',PatchData_Z(i,:)');
    drawnow;
end
コード2: 例題2のブロックの最上面パッチのみをアニメーション表示するMATLABスクリプト



動画2: 例題2のブロックの最上面パッチのみのアニメーション (Wx0=5., Wy0=0.02, Wz0=0.)