Up 視覚NN ストア 作成: 2026-08-24
更新: 2026-09-27

4足歩行ロボット > 自律型> コンピュータ > プログラミング > 視覚NNストア


           ┌────────┐       
       ┌───│  視覚NN  │←──┐   
       │出力 └────────┘ 入力│   
       │      (処理)      │   
    ┌──│────────────────│──┐
    │  ↓   ┌────────┐   │  │
    │┌───┐ │        │ ┌───┐│
    ││IN │→│ アルゴリズ  │→│OUT││
    │└───┘ │        │ └───┘│
       ↑   └────────┘   │  │
    └──│───<視覚NNストア>────│──┘
       │Sub          Pub│   
       │   (データ流通ループ)   │   
    ┌──│────────────────↓──┐
    │カメラストア        歩行脳NNストア│
    │       通信ネットワーク       │
    └──────────────────────┘

    アルゴリズム:
            START
             │
      ┌─────→│←──────┐
      │      ↓       │No
      │ INにサブスクライブが  │
      │   できているか? ───┘
      │      ↓Yes
      │  NNの入力をつくる (→ OUT)
      │    NNに入力
      │      │
      │   NNの出力を受ける (→ IN)
      │   OUT用に成形 (→ OUT)
      │      ↓
      │    パブリッシュ
      │      │
      └──────┘

  • アルゴリズムの周期
      0.01秒 (100 Hz)

  • ROS2 ノード
      ノード名: visual
      publisher:
        visual_publisher (→ 歩行脳NNストア)
        トピック:/visual/status
        データ型:my_robot_msgs/VisualStatus
      subscriber:
        camera_subscriber (← カメラストア)

  • IN・OUT
     IN:
       カメラ画像
        ←(subscribe)─ カメラストア

     OUT:
       カメラ画像の特徴量
        ─(publish)→ 歩行脳NN ストア


  • OUT データの型
      publish の型 VisualStatus であり,
       float32[128] feature : 画像の特徴量ベクトル

  • プログラム ##################################### # Python の ROS2ライブラリ import rclpy # <ユーザ定義のデータ型を使う>用 from rclpy.node import Node # データ型をimport # subscriber のデータ型 from my_robot_msgs.msg import CameraData # publisher のデータ型 from my_robot_msgs.msg import VisualStatus # <チャイルドプロセスで #  NN に入力し,そして出力を受ける>用 import subprocess import json ##################################### # ストアをノード Visual, visual に設定 class Visual(Node):   ############################   # コントラクタ   # (クラスがもつ属性の定義・初期化)   def __init__(self):    super().__init__('visual')    ##################    # NN に対する<入力する・出力を受ける>を    # child process として実行    # NNプロセス起動    self.nn = subprocess.Popen(    ['/usr/bin/visual_nn'],    stdin=subprocess.PIPE,    stdout=subprocess.PIPE,    text=True,    bufsize=1    )    ##################    # subscriber    # subscribe するデータは,CameraData    # CameraData を保持する変数    # None に初期設定    self.camera = None    # subscriber の設定    self.create_subscriber(    CameraData,    '/camera/data',    self.camera_callback,    10    )    ##################    # publisher    # publish するデータは,VisualStatus    # publisher の設定    self.publisher =    # 形式 : (データ型, topic, バッファ)    self.create_publisher(    VisualStatus,    '/visual/status',    10    )    # self.publisher をこのように設定すると,    # self.publisher.publish(msg) で    # msg の publish となる    # (こういう仕組みになっている)    ##################    # タイマー    #    # publish_visual_status    # (NN への入力から publish までの処理)    # に timer を付ける    # NN の処理速度 : 約10Hz (0.1秒周期)    # そこで 「0.1秒」 を publish の周期とする    self.timer =    self.create_timer(    0.1,    self.publish_visual_status    )      ###############################   # サブルーチン      ##########################   # callback   #   # publisher の call に対し,callback する   #  → 新しい画像が届く   def camera_callback(self, msg):    self.camera = msg   ############################   # NN呼び出し   # NN に入力し,出力を受ける(プロセス通信ラッパ)   # publish_visual_status(self) から呼び出される   def visual_nn(self, visual_input):    # 入力を JSON にして送る    input_json = json.dumps(visual_input)    self.nn.stdin.write(      input_json + "\n"    )    self.nn.stdin.flush()    # NN の出力を受け取る    output_json = \      self.nn.stdout.readline()    nn_output = json.loads(output_json)    return nn_output   ############################   # NN 呼び出し → 入力→ 出力→ publish   def publish_visual_status(self):    ############################    # NN の入力を生成して,入力    # IN庫が空 (CameraData 無し) なら,スキップ    if None in (    self.camera    ):    return    # 視覚NN の入力は,    visual_input = {    "height": self.camera.height,    "width": self.camera.width,    "image": self.camera.data    }    # NN に入力して出力を得る    # (出力は画像特徴量ベクトル)    nn_output = self.visual_nn(    visual_input    )    ############################    # VisualStatus メッセージを生成して,publish    msg = VisualStatus()    # VisualStatus のデータ型は,    # float32[128] featur    msg.feature = nn_output    # publish    self.publisher.publish(msg) ##################################### def main(args=None):   rclpy.init(args=args)   # object 化   node = Visual()   rclpy.spin(node)   node.destroy_node()   rclpy.shutdown() if __name__ == '__main__':   main()