質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Matplotlib

MatplotlibはPythonのおよび、NumPy用のグラフ描画ライブラリです。多くの場合、IPythonと連携して使われます。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

4702閲覧

matplotlibのanimationをmp4で保存すると,5秒で終わってしまう.

trami

総合スコア25

Matplotlib

MatplotlibはPythonのおよび、NumPy用のグラフ描画ライブラリです。多くの場合、IPythonと連携して使われます。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2019/08/07 13:52

前提・実現したいこと

matplotlibの公式ドキュメントにある二重振り子のプログラムを少し改造して,
軌跡付きの二重振り子のシミュレーションプログラムを作りました.

↓「二重振り子」の公式ドキュメントのリンク
https://matplotlib.org/2.0.2/examples/animation/double_pendulum_animated.html

そして,その動画をmp4形式で保存しようとすると,保存は出来るのですが,
だいたい1周期20秒なのですが,最初の5秒分しか保存がされません.

1周期(20秒分)保存するにはどうしたらよいのでしょうか?

発生している問題・エラーメッセージ

保存は正しくされ,エラーメッセージは表示されません.

ただ,動画が5秒しか保存されていません.

該当のソースコード

Python

1"""二重振り子をシミュレーションするプログラム""" 2from numpy import sin, cos 3from scipy.integrate import solve_ivp 4from matplotlib.animation import FuncAnimation 5import numpy as np 6import matplotlib.pyplot as plt 7 8G = 9.8 # 重力加速度 [m/s^2] 9L1 = 1.0 # 単振り子1の長さ [m] 10L2 = 1.0 # 単振り子2の長さ [m] 11M1 = 1.0 # おもり1の質量 [kg] 12M2 = 1.0 # おもり2の質量 [kg] 13 14# 運動方程式 15def derivs(t, state): 16 17 dydx = np.zeros_like(state) 18 dydx[0] = state[1] 19 20 delta = state[2] - state[0] 21 den1 = (M1+M2) * L1 - M2 * L1 * cos(delta) * cos(delta) 22 dydx[1] = ((M2 * L1 * state[1] * state[1] * sin(delta) * cos(delta) 23 + M2 * G * sin(state[2]) * cos(delta) 24 + M2 * L2 * state[3] * state[3] * sin(delta) 25 - (M1+M2) * G * sin(state[0])) 26 / den1) 27 28 dydx[2] = state[3] 29 30 den2 = (L2/L1) * den1 31 dydx[3] = ((- M2 * L2 * state[3] * state[3] * sin(delta) * cos(delta) 32 + (M1+M2) * G * sin(state[0]) * cos(delta) 33 - (M1+M2) * L1 * state[1] * state[1] * sin(delta) 34 - (M1+M2) * G * sin(state[2])) 35 / den2) 36 37 return dydx 38 39# 時間生成 40t_span = [0,20] 41dt = 0.05 42t = np.arange(t_span[0], t_span[1], dt) 43 44# 初期条件 45th1 = 120.0 46w1 = 0.0 47th2 = -10.0 48w2 = 0.0 49state = np.radians([th1, w1, th2, w2]) 50 51# 運動方程式を解く 52sol = solve_ivp(derivs, t_span, state, t_eval=t) 53y = sol.y 54 55# ジェネレータ 56def gen(): 57 for tt, th1, th2 in zip(t,y[0,:], y[2,:]): 58 x1 = L1*sin(th1) 59 y1 = -L1*cos(th1) 60 x2 = L2*sin(th2) + x1 61 y2 = -L2*cos(th2) + y1 62 yield tt, x1, y1, x2, y2 63 64fig, ax = plt.subplots() 65ax.set_xlim(-(L1+L2), L1+L2) 66ax.set_ylim(-(L1+L2), L1+L2) 67ax.set_aspect('equal') 68ax.grid() 69 70locus, = ax.plot([], [], 'r-', linewidth=2) 71line, = ax.plot([], [], 'o-', linewidth=2) 72time_template = 'time = %.1fs' 73time_text = ax.text(0.05, 0.9, '', transform=ax.transAxes) 74 75xlocus, ylocus = [], [] 76def animate(data): 77 t, x1, y1, x2, y2 = data 78 xlocus.append(x2) 79 ylocus.append(y2) 80 81 locus.set_data(xlocus, ylocus) 82 line.set_data([0, x1, x2], [0, y1, y2]) 83 time_text.set_text(time_template % (t)) 84 85ani = FuncAnimation(fig, animate, gen, interval=100, repeat=False) 86 87ani.save('double_pendulum.mp4', writer='ffmpeg', fps=5) 88 89plt.show()

試したこと

公式ドキュメントにあるソースコードで動画を保存すると,確かに20秒分保存されるので,
それと比較して,intervalを変えてみたり,init()を定義してみたりしました.

結果的に,動画の長さは長く出来たときもあったのですが,タイマーは5秒まで
つまりスローモーションになっただけでした.

補足情報(FW/ツールのバージョンなど)

公式ドキュメントの動画は,きちんと保存できたのでffmpegのダウンロードはうまくいっていると思います.

公式ドキュメントと変更した点は主に後半で,

・微分方程式を解く関数をodeint()からslve_ivp()にしたこと.
・軌跡を描画するためにジェネレータを定義したこと.

の2点です.あとはそれに伴う細かな調整をしました.

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

ジェネレーターを指定した場合、デフォルトでは100フレームしか呼ばれないようです。
save_count=len(t) として総フレーム数を指定してみてください。

FuncAnimation with generator defaults to arbitrary save_count=100 · Issue #8278 · matplotlib/matplotlib · GitHub

python

1"""二重振り子をシミュレーションするプログラム""" 2from numpy import sin, cos 3from scipy.integrate import solve_ivp 4from matplotlib.animation import FuncAnimation 5import numpy as np 6import matplotlib.pyplot as plt 7 8G = 9.8 # 重力加速度 [m/s^2] 9L1 = 1.0 # 単振り子1の長さ [m] 10L2 = 1.0 # 単振り子2の長さ [m] 11M1 = 1.0 # おもり1の質量 [kg] 12M2 = 1.0 # おもり2の質量 [kg] 13 14# 運動方程式 15def derivs(t, state): 16 17 dydx = np.zeros_like(state) 18 dydx[0] = state[1] 19 20 delta = state[2] - state[0] 21 den1 = (M1 + M2) * L1 - M2 * L1 * cos(delta) * cos(delta) 22 dydx[1] = ( 23 M2 * L1 * state[1] * state[1] * sin(delta) * cos(delta) 24 + M2 * G * sin(state[2]) * cos(delta) 25 + M2 * L2 * state[3] * state[3] * sin(delta) 26 - (M1 + M2) * G * sin(state[0]) 27 ) / den1 28 29 dydx[2] = state[3] 30 31 den2 = (L2 / L1) * den1 32 dydx[3] = ( 33 -M2 * L2 * state[3] * state[3] * sin(delta) * cos(delta) 34 + (M1 + M2) * G * sin(state[0]) * cos(delta) 35 - (M1 + M2) * L1 * state[1] * state[1] * sin(delta) 36 - (M1 + M2) * G * sin(state[2]) 37 ) / den2 38 39 return dydx 40 41 42# 時間生成 43t_span = [0, 20] 44dt = 0.05 45t = np.arange(t_span[0], t_span[1], dt) 46 47# 初期条件 48th1 = 120.0 49w1 = 0.0 50th2 = -10.0 51w2 = 0.0 52state = np.radians([th1, w1, th2, w2]) 53 54# 運動方程式を解く 55sol = solve_ivp(derivs, t_span, state, t_eval=t) 56y = sol.y 57 58# ジェネレータ 59def gen(): 60 for tt, th1, th2 in zip(t, y[0, :], y[2, :]): 61 x1 = L1 * sin(th1) 62 y1 = -L1 * cos(th1) 63 x2 = L2 * sin(th2) + x1 64 y2 = -L2 * cos(th2) + y1 65 yield tt, x1, y1, x2, y2 66 67 68fig, ax = plt.subplots() 69ax.set_xlim(-(L1 + L2), L1 + L2) 70ax.set_ylim(-(L1 + L2), L1 + L2) 71ax.set_aspect("equal") 72ax.grid() 73 74locus, = ax.plot([], [], "r-", linewidth=2) 75line, = ax.plot([], [], "o-", linewidth=2) 76time_template = "time = %.1fs" 77time_text = ax.text(0.05, 0.9, "", transform=ax.transAxes) 78 79xlocus, ylocus = [], [] 80 81 82def animate(data): 83 t, x1, y1, x2, y2 = data 84 xlocus.append(x2) 85 ylocus.append(y2) 86 87 locus.set_data(xlocus, ylocus) 88 line.set_data([0, x1, x2], [0, y1, y2]) 89 time_text.set_text(time_template % (t)) 90 91 92ani = FuncAnimation(fig, animate, gen, interval=100, repeat=False, save_count=len(t)) 93 94ani.save("double_pendulum.gif", writer="pillow", fps=30) 95 96plt.show()

投稿2019/08/07 14:14

tiitoi

総合スコア21954

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

trami

2019/08/08 01:24

できました!ありがとうございます! 公式ドキュメントには載っていたのですね…
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問