-
Notifications
You must be signed in to change notification settings - Fork 157
Description
今月本を買って勉強し始めたばかりです。
大変わかりやすく、感謝しております。
ideal_robot5.ipynbについて1点お聞きしたいことがあります。
第3章のロボットのモデル化、3.2.5エージェントの実装のp72最後から4行目で
「描写の後にone_stepを実行するのは,初期状態がアニメーションの最初に描かれるようにするためです.」
と述べていますが、
self.ani = anm.FuncAnimation(fig, self.one_step, fargs=(elems, ax), frames=1, interval=1000, repeat=False)上のようにmatplotlib.animationのFuncAnimationでframes=1としても、私の環境ですと、
下図のように左上は「t=0」と表示されていても、ロボットの動作自体は⊿tつまりtime_interval分時刻が進んでしまい初期状態は描写されません。

そこで、
ideal_robot5.ipynbのセル2の
def one_step(self, i, elems, ax): ### fig:one_step_add_one_step
while elems: elems.pop().remove()を
def one_step(self, i, elems, ax): ### fig:one_step_add_one_step
print("one_step {}回目呼び出し".format(self.one_step_num))
print("i = {}".format(i))
while elems: elems.pop().remove()として、jupyter notebook上ではなくコマンドラインで実行し、frames=5として、world.one_step()自体が何回呼び出されているか調べたところ、下図のようになりました。

どうやらmatplotlib.animation.FuncAnimationはまず最初にi=0として1回one_step()を呼び出し、
その後i=0,1,...とone_step()をframes回呼び出すようです。
なのでこのままですと、最初に描写されるのは、左上に「t=0」と描かれているのにも関わらず、1ステップ時刻が進んだ状態になってしまい、t=0以降のアニメーションもロボットの動作と時刻が⊿tずれてしまうと思われます。
そこで最初の一回のworld.one_step()の呼び出しではobject.draw()は呼び出すが、object.one_step()は呼び出さないようにすればいいと思うので、少し不細工な実装になってしまうんですが、
class World:
def __init__(self, debug=False):
self.objects = []
self.debug = debug
#....中略
def one_step(self, i, elems, ax):
while elems: elems.pop().remove()
elems.append(ax.text(-4.4, 4.5, "t = "+str(i), fontsize=10))
for obj in self.objects:
obj.draw(ax, elems)
if hasattr(obj, "one_step"): obj.one_step(1.0) ↓
class World:
def __init__(self, debug=False):
self.objects = []
self.debug = debug
self.first_frame=True # そのフレームが1番最初のフレームかどうかのフラグ
#....中略
def one_step(self, i, elems, ax):
while elems: elems.pop().remove()
elems.append(ax.text(-4.4, 4.5, "t = "+str(i), fontsize=10))
if not self.first_frame:
for obj in self.objects:
obj.draw(ax,elems)
if hasattr(obj,"one_step"):
obj.one_step(1.0)
else: # そのフレームが1番最初のフレームだったら、obj.one_step()は実行しない
self.first_frame = False
for obj in self.objects:
obj.draw(ax,elems)となり、t=0の初期状態が描写されるようになります。t=0以降もロボットの動作と時刻がずれることもなくなると思います。
長々と説明してしまいましたが、この時刻がずれてしまう問題、もっといい実装があるとは思いますがいかがでしょうか?
