Skip to content

Commit 7b64ec3

Browse files
author
MASAHIRO KUBOTA
committed
make simulation movie
1 parent 49dbe4d commit 7b64ec3

9 files changed

+1066
-34
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
movie/

README.md

+4
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,12 @@ coil_FT.mで,色んな姿勢パターンでコイルに加わる力とトル
99

1010
test3.mでトルクがほぼ0になる値をプロット
1111
test8.mで地球の磁場を計算
12+
test9.mはchatGPTで生成したコード.matlabで動画を生成し,保存するためのコード.
1213

1314
coil_FT.mでいろんな相対姿勢でビオサバールとアンペールで電磁力とトルクを計算する.
1415
plot_magnetic_field_FT2.mで決められた相対姿勢,電流で発生る電磁力とトルクを計算する.
1516

1617
dynamics2record.mで任意の場所から10^-5Nの上限でレコード盤軌道にもって行く制御
18+
19+
dynamic2record_movie.mで1つの衛星がレコード盤軌道に投入されるシミュレーション動画.dynamics2record.mを改造.
20+

draw_coil.m

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
function draw_coil(x, q, a)
2+
%UNTITLED6 Summary of this function goes here
3+
% Detailed explanation goes here
4+
%quat2 = quaternion([p2, q2, l2],'euler','XYZ','point');
5+
t = linspace(0,2*pi,100);
6+
x0 = x(1);
7+
y0 = x(2);
8+
z0 = x(3);
9+
coil2_x = rotatepoint(q,[zeros(1,100); a*sin(t); a*cos(t)].').';
10+
coil2_y = rotatepoint(q,[a*sin(t); zeros(1,100); a*cos(t)].').';
11+
coil2_z = rotatepoint(q,[a*sin(t); a*cos(t); zeros(1,100)].').';
12+
plot3(coil2_x(1,:) + x0, coil2_x(2,:) + y0, coil2_x(3,:) + z0)
13+
hold on
14+
plot3(coil2_y(1,:) + x0, coil2_y(2,:) + y0, coil2_y(3,:) + z0)
15+
plot3(coil2_z(1,:) + x0, coil2_z(2,:) + y0, coil2_z(3,:) + z0)
16+
end

dynamic2record_movie.asv

+300
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,300 @@
1+
%レコード盤軌道再現
2+
%オイラー近似で離散化.後々,CW解によって求まるものを使えるようにしておきたい.
3+
4+
5+
%衛星姿勢
6+
p1 = 0;
7+
q1 = 0;
8+
l1 = 0;
9+
p2 = 0;
10+
q2 = 0;
11+
l2 = 0;
12+
quat2 = quaternion([p2, q2, l2],'euler','XYZ','point');
13+
14+
%コイル半径(m)
15+
a = 0.015;
16+
17+
%衛星質量(kg)
18+
m = 1;
19+
20+
%重力定数
21+
myu = 3.986*10^14;
22+
23+
%地球半径
24+
earth_radius = 6378.140*10^3;
25+
26+
%高度
27+
altitude = 500*10^3;
28+
29+
%地心からの距離
30+
r_star = earth_radius + altitude;
31+
32+
%地球を周回する衛星の角速度
33+
n = sqrt(myu/r_star^3);
34+
35+
%軌道周期
36+
%disp(2*pi/(n*60))
37+
38+
%サンプリングタイム
39+
T = 1;
40+
41+
%シミュレーション時間
42+
N = 60*90;
43+
44+
%Hill方程式によって作られるオイラー近似離散状態方程式の係数
45+
A = [0, 0, 0, 1, 0, 0;
46+
0, 0, 0, 0, 1, 0;
47+
0, 0, 0, 0, 0, 1;
48+
0, 0, 0, 0, 0, 2*n;
49+
0, -n^2, 0, 0, 0, 0;
50+
0, 0, 3*n^2, -2*n, 0, 0];
51+
52+
%Hill方程式によって作られるオイラー近似離散状態方程式の係数
53+
B = [0, 0, 0;
54+
0, 0, 0;
55+
0, 0, 0;
56+
1/m, 0, 0;
57+
0, 1/m, 0;
58+
0, 0, 1/m];
59+
60+
%係数を計算するための基本的な計算
61+
c = cos(n*T);
62+
tau = n*T;
63+
s = sin(n*T);
64+
65+
%{
66+
%微分方程式の解を利用した差分方程式の係数
67+
A_d = [1, 0, 6*(tau-s), (4*s-3*tau)/n, 0, 2*(1-c)/n;
68+
0, c, 0, 0, s/n, 0;
69+
0, 0, 4-3*c, 2*(c-1)/n, 0, s/n;
70+
0, 0, 6*n*(1-c), 4*c-3, 0, 2*s;
71+
0, -n*s, 0, 0, c, 0;
72+
0, 0, 3*n*s, -2*s, 0, c];
73+
74+
%B_dの近似が怪しいため要検証
75+
B_d = [(4*s-3*tau)/n, 0, 2*(1-c)/n;
76+
0, s/n, 0;
77+
2*(c-1)/n, 0, s/n;
78+
4*c-3, 0, 2*s;
79+
0, c, 0;
80+
-2*s, 0, c];%差分方程式の係数
81+
%}
82+
83+
%オイラー近似を利用した差分方程式の係数
84+
A_d = eye(6) + T*A;
85+
86+
%オイラー近似を利用した差分方程式の係数
87+
B_d = T*B;
88+
89+
%重み行列
90+
%Q = diag([1, 1, 1, 0, 0, 0]);
91+
%R = diag([10^3, 10^3, 10^3]); とても収束性が良い.その代わり振動する.
92+
93+
%Q = diag([1, 1, 100, 0, 0, 0]);
94+
%R = diag([10^7, 10^3, 10^7]); エネルギーが少なくて済む=振動が少ない
95+
%この値はランデブの軌道制御における予見ファジィ制御と最適制御の比較から持ってきてる.
96+
97+
Q = diag([1, 1, 1, 0, 0, 0]);
98+
R = diag([10^3, 10^3, 10^3]);
99+
100+
%リッカチ方程式を解いて最適ゲインを求める
101+
[~,K,~] = icare(A,B,Q,R,[],[],[]);
102+
103+
%状態配列
104+
X = zeros(N, 6);
105+
106+
%初期状態量代入
107+
X(1,:) = 0.05/2*[1, 1, 1, 0, 0, 0];
108+
109+
%最初からレコード盤に乗っている初期状態量
110+
%X(1,:) = 0.05/2*[0, sqrt(3), 1, 2*n, 0, 0];
111+
112+
%ランデブーを想定した目標値
113+
%x_d = @(t) 0.05*[-1,0,0,0,0,0].';
114+
115+
%各時間での状態量目標値
116+
x_d = @(t) 0.05/2*[2*sin(n*(t-1)), sqrt(3)*cos(n*(t-1)), cos(n*(t-1)), 2*n*cos(n*(t-1)), -sqrt(3)*n*sin(n*(t-1)), -n*sin(n*(t-1))].';
117+
v_d = @(t) 0.05/2*[2*n*cos(n*(t-1)), -sqrt(3)*n*sin(n*(t-1)), -n*sin(n*(t-1)), -2*n^2*sin(n*(t-1)), -sqrt(3)*n^2*cos(n*(t-1)), -n^2*cos(n*(t-1))].';
118+
119+
%変位あり状態方程式の入力変位を設定するための係数
120+
B_sharp = (B.'*B)\B.';
121+
122+
%グラフを作るためのデータ配列
123+
u_data = zeros(N,3);
124+
norm_data = zeros(N,1);
125+
x_tilda_data = zeros(N,1);
126+
x_d_data = zeros(N,3);
127+
128+
129+
tic
130+
i = 0;
131+
j =0;
132+
while i < N %時刻i*T
133+
i = i + 1;
134+
xd = x_d(i*T);
135+
136+
%フィードバック系を0に収束させるために入力変位を設定
137+
u_d = B_sharp*(v_d(i*T) - A_d*xd);
138+
139+
%目標値と現在地のずれ
140+
x_tilda = X(i, :).' - xd;
141+
142+
%x_tildaを0にするためのフィードバック
143+
u_tilda = -K*x_tilda;
144+
145+
%元の状態方程式の入力
146+
u = u_tilda + u_d;
147+
148+
%所望の力が上限を超えた場合,方向そのままで大きさを小さくする.
149+
if norm(u)>10^-5
150+
u = u*10^-5/norm(u);
151+
u_tilda = u - u_d;
152+
end
153+
154+
155+
%離散状態方程式
156+
X(i+1, :) = A_d*X(i, :).' + B_d*u;
157+
158+
%目標値までの距離を格納
159+
x_tilda_data(i) = norm(X(i, :).' - xd);
160+
161+
%電磁力ベクトルを格納
162+
u_data(i,:) = u;
163+
164+
%目標軌道
165+
x_d_data(i,:) = xd(1:3,1).';
166+
167+
end
168+
toc
169+
170+
171+
172+
173+
174+
175+
%各時刻での電磁力の大きさをグラフ化
176+
figure
177+
plot((1:N)/60, u_data)
178+
xlabel('時間(min)');
179+
ylabel('力(N)');
180+
title(append('電磁力',str));
181+
legend('u');
182+
183+
%各時刻での位置変位をグラフ化
184+
figure
185+
plot((1:N)/60, x_tilda_data)
186+
xlabel('時間(min)');
187+
ylabel('位置変位(m)');
188+
title(append('位置変位',str));
189+
legend('x-tilda');
190+
191+
192+
figure
193+
t = linspace(0,2*pi,100);
194+
axis_norm = 0.2;
195+
196+
197+
%コイルを表示
198+
draw_coil(X(1,1:3), quat2, a)
199+
200+
%原点を表示
201+
plot3(0,0,0,'ro');
202+
203+
axis([-axis_norm,axis_norm,-axis_norm,axis_norm,-axis_norm,axis_norm])
204+
axis square
205+
grid on
206+
xlabel('X(m)')
207+
ylabel('Y(m)')
208+
set(gca,'YDir','reverse')
209+
set(gca,'ZDir','reverse')
210+
zlabel('Z(m)')
211+
%quiver3(X,Y,Z,B_x,B_y,B_z, 1/(20 * norm([B_x B_y B_z])))
212+
213+
%軌跡を描画
214+
plot3(X(:,1), X(:,2), X(:,3),'c')
215+
216+
%目標軌道を描画
217+
%plot3(x_d_data(:,1), x_d_data(:,2), x_d_data(:,3), 'r')
218+
219+
220+
221+
222+
223+
224+
225+
226+
227+
% ファイル名に含める日時のフォーマットを指定
228+
dateformat = 'yyyy-MM-dd-HH-mm-ss';
229+
230+
% 日時をファイル名に追加
231+
filename = sprintf('movie/dynamics2record_%s.avi', datetime('now','Format', dateformat));
232+
233+
%フレームレート
234+
Fs = 30;
235+
236+
%表示間引き数 (表示間引き数×フレームレート×サンプリングタイム)=n倍速となる
237+
Th = 10;
238+
239+
% 動画の準備
240+
vidObj = VideoWriter(filename); % 動画ファイル名
241+
vidObj.Quality = 100; % 画質
242+
vidObj.FrameRate = Fs; % フレームレート
243+
open(vidObj);
244+
245+
% グラフの見た目を設定
246+
lw1 = 2; % 線幅1
247+
lw2 = 1; % 線幅2
248+
fs1 = 14; % フォントサイズ1
249+
fs2 = 12; % フォントサイズ2
250+
figcolor = [1 1 1]; % グラフの背景色
251+
252+
253+
% 描画
254+
figure('color',figcolor);
255+
for i = 1:Th:N
256+
disp(i)
257+
258+
% 軌跡を描画
259+
plot3(X(1:i,1),X(1:i,2),X(1:i,3),'LineWidth',1,'Color',[0.7 0.7 0.7]);
260+
hold on;
261+
262+
%コイルを描画
263+
draw_coil([X(i,1:3)], quat2, a)
264+
265+
%発生する力の向きを描画
266+
quiver3(X(i,1),X(i,2),X(i,3),u_data(i,1)*10^4,u_data(i,2)*10^4,u_data(i,3)*10^4)
267+
268+
%目標軌道を描画
269+
plot3(x_d_data(:,1), x_d_data(:,2), x_d_data(:,3), 'r')
270+
271+
%目標ポイントを描画
272+
plot3(x_d_data(i,1),x_d_data(i,2),x_d_data(i,3),'o','MarkerSize',5,'MarkerFaceColor','r');
273+
274+
axis_norm = 0.2;
275+
axis([-axis_norm,axis_norm,-axis_norm,axis_norm,-axis_norm,axis_norm])
276+
axis square
277+
grid on
278+
xlabel('X(m)(進行方向)');
279+
ylabel('Y(m)(面外方向)');
280+
zlabel('Z(m)(地心方向)');
281+
set(gca,'YDir','reverse')
282+
set(gca,'ZDir','reverse')
283+
str = append('(', string(T*Fs*Th), ' times speed)');
284+
title(append('Satellite Relative Motion with Trajectory ',str));
285+
legend('satellite trajectory in LVLH','Circle');
286+
legend('Circle');
287+
legend('target orbit')
288+
dim = [.2 .7 .3 .3];
289+
drawnow;
290+
frame = getframe(gcf);
291+
writeVideo(vidObj,frame);
292+
hold off;
293+
end
294+
295+
% 動画を閉じる
296+
close(vidObj);
297+
298+
299+
hold off
300+

0 commit comments

Comments
 (0)