Skip to content

第3章の「ロボットのモデル化」で、ロボットの動作と左上の時刻がずれる #5

@SolKul

Description

@SolKul

今月本を買って勉強し始めたばかりです。
大変わかりやすく、感謝しております。

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.animationFuncAnimationframes=1としても、私の環境ですと、
下図のように左上は「t=0」と表示されていても、ロボットの動作自体は⊿tつまりtime_interval分時刻が進んでしまい初期状態は描写されません。
t_0

そこで、
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()自体が何回呼び出されているか調べたところ、下図のようになりました。
debug

どうやら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)

とすれば、frames=1とした場合のアニメーションは
t_0_mod

となり、t=0の初期状態が描写されるようになります。t=0以降もロボットの動作と時刻がずれることもなくなると思います。

長々と説明してしまいましたが、この時刻がずれてしまう問題、もっといい実装があるとは思いますがいかがでしょうか?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions