structure - rkoyama1623-2021/log_plotter GitHub Wiki

layout.yamlの例

path1: path/to/log1
path2: path/to/log2
path: [$(path1), $(path2)] # 特殊扱い

main:
  this is title:
    legends:
      # abstract case
      - { key: <class name>, arg1: xx, arg2: yy}
      # ログのプロット
      - { key: st_q, id: [0-5], path: $(path1)}
      # ログのプロット (pathの省略)
      - { key: st_q, id: [0-5]} # pathを与える
      # targetどうしの演算
      - key: diff,
        targets:
            - { key: st_q, id: [0-5], path: $(path2)}
            - { key: sh_q, id: [0-5], path: $(path1)}
      # 符号の反転
      - { key: inverse, args: {target: st_q, id: [0-5]} }
      # 座標の変換
      - { key: coords2coords, robot: jaxon, input: lhsensor, output: larm-link6, data: off_lhsensor }
      - { key: lhsensor_ee, robot: jaxon} # 特化したtargetを定義した場合

plot_rule.pyの例

# ログをプロットするだけのtarget
class st_q(LoggedTarget): pass
class abc_q(LoggedTarget): pass
# 横軸は時刻で,縦軸はログどうしの演算でプロット
class watt(TimedTarget):
    def get_y_data(self):
        return None
class joint(TimedTarget):
    def get_y_data(self):
        return None
class joint_diff(TimedTarget):
    def get_y_data(self):
        return None
# 複雑な演算
class sin_curve(TargetInterface): pass
class coords2coords(TargetInterface): pass

layout.yamlからプロット用データの生成

layout.yamlの解釈の仕方

path: [path/to/log, path/to/log]

main:
  this is title:
    legends:
      - { key: Name, arg1: xxx, arg2: yyy, ....} # <- 凡例
  1. layout.yamlは少なくとも"path"と"main"のkeyから成る.
  2. mainの中にグラフの並べ方を書く.
  3. legendsの中の一つ一つの辞書が一つの凡例に対応する.
  4. 凡例については,keyを必ず指定する.keyはpythonのクラスの名前である.それ以外の情報は省略できる.
  5. 凡例に関する情報で,key以外は,凡例のクラスのコンストラクタに渡す.
  6. 凡例に関する情報で,pathが省略された場合,使用しているログのパスのリストで補う.ただし,パスと無関係な理論曲線などの凡例クラスは,その情報を受け取るが利用はしない.

class_diagram
↑pylintのpyreverseで作成したクラス構成図

内部処理 (イメージ)

target_manager = log_plotter.TargetManager(path=["path/to/log1", "path/to/log2"]) # 凡例の管理をする.

以下のlayout.yamlをプロットする場合.

path1: path/to/log1
path2: path/to/log2
path: [$(path1), $(path2)] # 特殊扱い

main:
  this is title:
    legends:
      - { key: st_q, id: [0-5]}
      - { key: inverse, args: {target: st_q, id: [0-5]} }
      - { key: coords2coords, robot: jaxon, input: lhsensor, output: larm-link6, data: off_lhsensor }

処理は

info = { "key": "st_q", "id": [0,1,2,3,4,5]}
cls = getatter(plot_rule, info['key'])
kwargs = {"id": [0,1,2,3,4,5]}
kwargs.set_default("path", target_manager.path) # パスが省略されている場合は追加
target1 = target_manager[cls, kwargs] # インスタンス化(すでに存在するインスタンスは辞書から取り出すだけ)
viewer.plot(target1)

のような流れになる.

viewer.plotの内部処理は,

class Graph(object):
    def plot(self, target):
        if hasatter(target, plot):
            target.plot(self.plotItem)
        else:
            self.plotItem.plot(target.get_x_data(), target.get_y_data())
⚠️ **GitHub.com Fallback** ⚠️