0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ROS2コマンドとMCAPを試してみた

Last updated at Posted at 2025-05-06

背景・目的

前回、MCAPについて下記の記事で整理しました。

MCAPは、下記の特徴があります。

  • 多様なシリアライズ形式のサポート
  • 高性能な書き込みと読み取り
  • メッセージスキーマやメタデータをファイル内に含む自己完結型の構造を持っています。これにより、外部の依存関係なしにデータの解釈や再生が可能
  • 堅牢性とデータの回復性

今回、ros2とMCAPを操作しながら理解を進めます。

まとめ

ROS2の基本的概念

用語 説明
ノード(node) 処理の単位(例:カメラ、センサ)
1つのプロセス(アプリケーションの単位)
トピック(topic) ノード間で送受信されるメッセージのチャネル
パブリッシャー メッセージを送る側
サブスクライバー メッセージを受け取る側

コマンド

下記にコマンドの特徴をまとめます。

カテゴリ コマンド 概要 補足
トピック ros2 topic list 現在アクティブな トピック名の一覧 を表示する 現在通信中または作成済のトピックが対象
ros2 topic info <トピック> トピックの 型や Publisher/Subscriber 数 を確認する 通信の方向性や型が確認できる
ノード ros2 run <パッケージ名> <ノード> 指定した ROS 2 パッケージに含まれる ノードスクリプトを起動する
(例: Python ノード)
ノードの自作・動作確認に使う
Publisher ros2 topic pub 指定したトピックに 手動でメッセージを Publish(送信)する デバッグや簡易送信に利用
ros2 bag play bag ファイルの内容を 再度トピックに Publish(再生)する 録画データのリプレイ用途
Subscriber ros2 topic echo <トピック> 指定したトピックのメッセージを リアルタイムで表示する データ確認・デバッグに有効
ros2 bag record 指定したトピックのメッセージを ファイル(bag形式)に記録する デバッグ・検証・再利用のために記録
ros2 bag info bag ファイルの メタ情報(トピック名・件数・時間など)を表示する 記録内容の確認用

データフロー

上記のコマンドや概念を整理するとかきのようにあなります。

image.png

概要

MCAPについて

下記にまとめましたので、よろしければご参照ください。

ROS2

下記にまとめましたので、よろしければご参照ください。

あらためて、下記にも記載します。

  • ROS 2は、Robot Operating System 2の略
  • ロボットアプリケーションの開発を支援するためのオープンソースのミドルウェアフレームワーク
  • ROS 1の後継として開発され、リアルタイム性やセキュリティ、マルチプラットフォーム対応などの機能強化が図られている
  • 主な特徴は下記の通り
    • モジュール性:ノード、トピック、サービスなどの概念により、機能を分割して開発・管理できる
    • DDS(Data Distribution Service)ベース:リアルタイム通信やQoS(Quality of Service)の設定が可能
    • マルチプラットフォーム対応:Linux、Windows、macOSなど、複数のOSで動作する
    • セキュリティ強化:通信の暗号化や認証機能が追加されている
    • ROS 2は、ロボットの制御、センサーの統合、データ処理など、ロボティクスアプリケーション全体の開発を支援するための包括的なフレームワーク

MCAPとROS2の関連性

項目 MCAP ROS 2
種類 ファイルフォーマット ミドルウェアフレームワーク
目的 データの記録・保存 ロボットアプリケーションの開発支援
データの扱い タイムスタンプ付きのメッセージの保存 ノード間の通信、センサー統合、制御など
対応データ形式 Protobuf、JSON、ROS 1/2メッセージなど ROSメッセージ(ROS 1/2)
関連性 ROS 2のデータ記録フォーマットとして利用可能 MCAPをデータ記録フォーマットとして利用可能
  • MCAP:ロボティクス分野でのデータ記録・保存に特化したファイルフォーマット
  • ROS 2:ロボットアプリケーション全体の開発を支援するミドルウェアフレームワーク

ROS2の基本的概念

用語 説明
ノード(node) 処理の単位(例:カメラ、センサ)
1つのプロセス(アプリケーションの単位)
トピック(topic) ノード間で送受信されるメッセージのチャネル
パブリッシャー メッセージを送る側
サブスクライバー メッセージを受け取る側

実践

前提

下記を使用しています。

  • Mac
  • UTM

環境の準備

下記を基に環境を作ります。

  1. UTMを起動します
  2. 「ubuntu-24.04.2-live-server-amd64.iso」を基にインストールします
  3. インストールできました
    ~$ ros2 --help
    usage: ros2 [-h] [--use-python-default-buffering] Call `ros2 <command> -h` for more detailed usage. ...
    
    ros2 is an extensible command-line tool for ROS 2.
    
    options:
      -h, --help            show this help message and exit
      --use-python-default-buffering
                            Do not force line buffering in stdout and instead use the python default buffering, which might be affected by PYTHONUNBUFFERED/-u and depends on whatever stdout is interactive or not
    
    Commands:
      action     Various action related sub-commands
      bag        Various rosbag related sub-commands
      component  Various component related sub-commands
      daemon     Various daemon related sub-commands
      doctor     Check ROS setup and other potential issues
      interface  Show information about ROS interfaces
      launch     Run a launch file
      lifecycle  Various lifecycle related sub-commands
      multicast  Various multicast related sub-commands
      node       Various node related sub-commands
      param      Various param related sub-commands
      pkg        Various package related sub-commands
      run        Run a package specific executable
      security   Various security related sub-commands
      service    Various service related sub-commands
      topic      Various topic related sub-commands
      wtf        Use `wtf` as alias to `doctor`
    
      Call `ros2 <command> -h` for more detailed usage.
    :~$ 
    

トピックの確認と送受信

  1. トピック一覧の確認をします。parameter_eventsとresoutがありました(デフォルトのようです)
    $ ros2 topic list
    /parameter_events
    /rosout
    $ 
    
  2. ターミナルを2つ起動します(ここではターミナルAとターミナルBと呼びます)

送信(ターミナルA)

  1. 下記のコマンドでパブリッシュします
    ros2 topic pub /hello_std_msgs std_msgs/String "data: 'Hello ROS 2'"
    
    publishing #1: std_msgs.msg.String(data='Hello ROS 2')
    
    publishing #2: std_msgs.msg.String(data='Hello ROS 2')
    
    publishing #3: std_msgs.msg.String(data='Hello ROS 2')
    
    publishing #4: std_msgs.msg.String(data='Hello ROS 2')
    
    publishing #5: std_msgs.msg.String(data='Hello ROS 2')
    
    ・・・・
    

※ パラメータは下記のとおりです。

  • 特に引数を指定しない場合、送信し続けます
    • topic:
      • topic関連のコマンド
    • pub:
      • publish.指定したトピックにメッセージを送る
    • /hello_std_msgs:
      • 宛先とするトピック名(任意)
    • std_msgs/Strings
      • 送信するメッセージの型
      • 標準の文字列型を指定
    • "data: 'Hello ROS 2'"
      • 送信するメッセージのbody
      • dataフィールドに'Hello ROS2'を入れている

受信(ターミナルB)

  1. 下記のコマンドでサブスクライブします
    ros2 topic echo /hello_std_msgs
    
    data: Hello ROS 2
    ---
    data: Hello ROS 2
    ---
    data: Hello ROS 2
    ---
    data: Hello ROS 2
    ---
    data: Hello ROS 2
    ---
    
    ・・・
    
    

※ echoにより、リアルタイムに出力されていることが確認できます

トピックの確認

  1. ターミナルAで送信中に、ターミナルBでリストします。/hello_std_msgsトピックが表示されました

    $ ros2 topic list
    /hello_std_msgs
    /parameter_events
    /rosout
    $ 
    
  2. ターミナルAからの送信を止めます。(Ctrl+Cで抜けます)

  3. ターミナルBで再びリストします。先ほど見えていた /hello_std_msgsトピック は消えました

    ubuntu@ubuntu:~$ ros2 topic list
    /parameter_events
    /rosout
    ubuntu@ubuntu:~$ 
    

※ 一時的なトピックのため、送信を止めると消えるようです。Publisherである自分自身がノードを作っているようです。トピックを維持しているノードがいないと消えるようです。
/parameter_events/rosoutなどは、ROS2が管理しており常に存在しているようです

ノードの操作

Pythonでノードを作成

テンプレート作成

  1. srcディレクトリを作成します

    ~$ mkdir -p ~/ros2_ws/src
    ~$ cd ~/ros2_ws/src/
    ~/ros2_ws/src$ 
    
  2. サンプルノードを作成します

    ros2 pkg create --build-type ament_python my_py_node --dependencies rclpy std_msgs
    
    ===
    $ ros2 pkg create --build-type ament_python my_py_node --dependencies rclpy std_msgs
    going to create a new package
    package name: my_py_node
    destination directory: /home/ubuntu/ros2_ws/src
    package format: 3
    version: 0.0.0
    description: TODO: Package description
    maintainer: ['ubuntu <ubuntu@todo.todo>']
    licenses: ['TODO: License declaration']
    build type: ament_python
    dependencies: ['rclpy', 'std_msgs']
    creating folder ./my_py_node
    creating ./my_py_node/package.xml
    creating source folder
    creating folder ./my_py_node/my_py_node
    creating ./my_py_node/setup.py
    creating ./my_py_node/setup.cfg
    creating folder ./my_py_node/resource
    creating ./my_py_node/resource/my_py_node
    creating ./my_py_node/my_py_node/__init__.py
    creating folder ./my_py_node/test
    creating ./my_py_node/test/test_copyright.py
    creating ./my_py_node/test/test_flake8.py
    creating ./my_py_node/test/test_pep257.py
    
    [WARNING]: Unknown license 'TODO: License declaration'.  This has been set in the package.xml, but no LICENSE file has been created.
    It is recommended to use one of the ament license identifiers:
    Apache-2.0
    BSL-1.0
    BSD-2.0
    BSD-2-Clause
    BSD-3-Clause
    GPL-3.0-only
    LGPL-3.0-only
    MIT
    MIT-0
    $ 
    
    
    • ros2 pkg create : ROS2パッケージを新規作成
    • --build-type ament_python: Python を使ってビルドされることを指定
    • my_py_node:パッケージ名
    • --dependencies rclpy std_msgs:パッケージが依存しているライブラリを指定
      • rclpy:ROS 2 の Pythonクライアントライブラリ
      • std_msgs:標準のメッセージ型(String, Int32など)
  3. 以下の構成ができました

    $ tree 
    .
    └── my_py_node
        ├── my_py_node
        │   └── __init__.py
        ├── package.xml
        ├── resource
        │   └── my_py_node
        ├── setup.cfg
        ├── setup.py
        └── test
            ├── test_copyright.py
            ├── test_flake8.py
            └── test_pep257.py
    
    5 directories, 8 files
    $ 
    

ソースを作成

  1. my_py_node/my_py_node/talker.py を以下の内容で作成します
    import rclpy
    from rclpy.node import Node
    from std_msgs.msg import String
    
    class TalkerNode(Node):
        def __init__(self):
            super().__init__('talker')
            self.publisher_ = self.create_publisher(String, 'hello', 10)
            self.timer = self.create_timer(0.5, self.timer_callback)
            self.count = 0
    
        def timer_callback(self):
            msg = String()
            msg.data = f'Hello ROS 2: {self.count}'
            self.publisher_.publish(msg)
            self.get_logger().info(f'Publishing: "{msg.data}"')
            self.count += 1
    
    def main(args=None):
        rclpy.init(args=args)
        node = TalkerNode()
        rclpy.spin(node)
        rclpy.shutdown()
    
    if __name__ == '__main__':
        main()
    
  • ノード名 talker で起動
  • トピック /hello に、0.5秒ごとに Hello ROS 2: 0, Hello ROS 2: 1, ... のようなメッセージが送信される
    • 0.5秒ごとに、timer_callback()を呼び出し、メッセージを出力している
    • rclpy.spin(node)により、timer_callback()が定期的に呼び出される

setup.pyにエントリーポイントを追記

  1. my_py_node.talker:mainを追記します

    entry_points={
        'console_scripts': [
            'talker = my_py_node.talker:main',
        ],
    },
    
  2. 全体像は下記のとおりです

    $ cat my_py_node/setup.py 
    from setuptools import find_packages, setup
    
    package_name = 'my_py_node'
    
    setup(
        name=package_name,
        version='0.0.0',
        packages=find_packages(exclude=['test']),
        data_files=[
            ('share/ament_index/resource_index/packages',
                ['resource/' + package_name]),
            ('share/' + package_name, ['package.xml']),
        ],
        install_requires=['setuptools'],
        zip_safe=True,
        maintainer='ubuntu',
        maintainer_email='ubuntu@todo.todo',
        description='TODO: Package description',
        license='TODO: License declaration',
        tests_require=['pytest'],
        entry_points={
            'console_scripts': [
                'talker = my_py_node.talker:main',
            ],
        },
    )
    $ 
    

ビルド

  1. ビルドします
    $ colcon build --symlink-install
    [0.488s] WARNING:colcon.colcon_ros.prefix_path.ament:The path '/home/ubuntu/ros2_ws/install/my_py_node' in the environment variable AMENT_PREFIX_PATH doesn't exist
    [0.488s] WARNING:colcon.colcon_ros.prefix_path.ament:The path '/home/ubuntu/ros2_ws/install' in the environment variable AMENT_PREFIX_PATH doesn't contain any 'local_setup.*' files.
    Starting >>> my_py_node
    Finished <<< my_py_node [3.55s]          
    
    Summary: 1 package finished [3.95s]
    $ 
    

publish(ターミナルA)

  1. メッセージを送信します
    $ ros2 run my_py_node talker
    [INFO] [1746423555.971515959] [talker]: Publishing: "Hello ROS 2: 0"
    [INFO] [1746423556.434968269] [talker]: Publishing: "Hello ROS 2: 1"
    [INFO] [1746423556.936578724] [talker]: Publishing: "Hello ROS 2: 2"
    [INFO] [1746423557.437360531] [talker]: Publishing: "Hello ROS 2: 3"
    [INFO] [1746423557.936618063] [talker]: Publishing: "Hello ROS 2: 4"
    [INFO] [1746423558.436830477] [talker]: Publishing: "Hello ROS 2: 5"
    [INFO] [1746423558.938511280] [talker]: Publishing: "Hello ROS 2: 6"
    [INFO] [1746423559.437847548] [talker]: Publishing: "Hello ROS 2: 7"
    [INFO] [1746423559.935977189] [talker]: Publishing: "Hello ROS 2: 8"
    [INFO] [1746423560.437838697] [talker]: Publishing: "Hello ROS 2: 9"
    [INFO] [1746423560.938195209] [talker]: Publishing: "Hello ROS 2: 10"
    [INFO] [1746423561.437847674] [talker]: Publishing: "Hello ROS 2: 11"
    ・・・
    

subscribe(ターミナルB)

  1. トピックを確認します
    $ ros2 topic list
    /hello
    /parameter_events
    /rosout
    $ 
    
  2. echoで表示します。受信できました!
    $ ros2 topic echo /hello
    2025-05-05 05:42:53.997 [XMLPARSER Error] getcwd failed No such file or directory -> Function loadDefaultXMLFile
    data: 'Hello ROS 2: 438'
    ---
    data: 'Hello ROS 2: 439'
    ---
    data: 'Hello ROS 2: 440'
    

MCAP形式で記録する

  1. 下記のコマンドを実行します

    $ ros2 bag record -o my_bag --storage mcap /hello
    [INFO] [1746455410.390757527] [rosbag2_recorder]: Press SPACE for pausing/resuming
    [INFO] [1746455410.422411606] [rosbag2_recorder]: Listening for topics...
    [INFO] [1746455410.422631740] [rosbag2_recorder]: Event publisher thread: Starting
    [INFO] [1746455410.423877678] [rosbag2_recorder]: Recording...
    [INFO] [1746455801.472895556] [rosbag2_recorder]: Pausing recording.
    [INFO] [1746455801.480338694] [rosbag2_cpp]: Writing remaining messages from cache to the bag. It may take a while
    [INFO] [1746455801.489244086] [rosbag2_recorder]: Event publisher thread: Exiting
    [INFO] [1746455801.490517203] [rosbag2_recorder]: Recording stopped
    [INFO] [1746455801.571788548] [rclcpp]: signal_handler(signum=2)
    $ 
    
    • -o my_bag: 保存先フォルダ名
    • --storage mcap:MCAP形式で記録
    • /hello: 記録対象のトピック名
  2. 別ターミナルで確認します。my_bagフォルダができています

    $ ls -l
    total 24
    drwxrwxr-x 3 XXX XXX 4096 May  5 05:37 build
    drwxrwxr-x 2 XXX XXX 4096 May  5 14:39 hello_bag
    drwxrwxr-x 3 XXX XXX 4096 May  5 05:37 install
    drwxrwxr-x 3 XXX XXX 4096 May  5 05:37 log
    drwxrwxr-x 2 XXX XXX 4096 May  5 14:39 my_bag
    drwxrwxr-x 3 XXX XXX 4096 May  5 05:32 src
    $ 
    
  3. 中身は、空でした

    $ ls -l my_bag/
    total 0
    -rw-rw-r-- 1 XXX XXX 0 May  5 14:39 my_bag_0.mcap
    $ cat my_bag/my_bag_0.mcap 
    $ 
    
  4. 下記のコマンドでメッセージを送信します

    ubuntu@ubuntu:~/ros2_ws$ ros2 run my_py_node talker
    [INFO] [1746456624.855327989] [talker]: Publishing: "Hello ROS 2: 0"
    [INFO] [1746456625.321653404] [talker]: Publishing: "Hello ROS 2: 1"
    [INFO] [1746456625.817827820] [talker]: Publishing: "Hello ROS 2: 2"
    [INFO] [1746456626.317045072] [talker]: Publishing: "Hello ROS 2: 3"
    [INFO] [1746456626.818447231] [talker]: Publishing: "Hello ROS 2: 4"
    [INFO] [1746456627.319625612] [talker]: Publishing: "Hello ROS 2: 5"
    [INFO] [1746456627.819363865] [talker]: Publishing: "Hello ROS 2: 6"
    [INFO] [1746456628.317733225] [talker]: Publishing: "Hello ROS 2: 7"
    [INFO] [1746456628.813893643] [talker]: Publishing: "Hello ROS 2: 8"
    [INFO] [1746456629.312155996] [talker]: Publishing: "Hello ROS 2: 9"
    [INFO] [1746456629.811090218] [talker]: Publishing: "Hello ROS 2: 10"
    [INFO] [1746456630.314374421] [talker]: Publishing: "Hello ROS 2: 11"
    [INFO] [1746456630.819625907] [talker]: Publishing: "Hello ROS 2: 12"
    [INFO] [1746456631.314952955] [talker]: Publishing: "Hello ROS 2: 13"
    [INFO] [1746456631.810452367] [talker]: Publishing: "Hello ROS 2: 14"
    [INFO] [1746456632.312873593] [talker]: Publishing: "Hello ROS 2: 15"
    [INFO] [1746456632.810239991] [talker]: Publishing: "Hello ROS 2: 16"
    [INFO] [1746456633.320642098] [talker]: Publishing: "Hello ROS 2: 17"
    [INFO] [1746456633.819014478] [talker]: Publishing: "Hello ROS 2: 18"
    [INFO] [1746456634.311467673] [talker]: Publishing: "Hello ROS 2: 19"
    [INFO] [1746456634.818081860] [talker]: Publishing: "Hello ROS 2: 20"
    [INFO] [1746456635.313023067] [talker]: Publishing: "Hello ROS 2: 21"
    [INFO] [1746456635.811034489] [talker]: Publishing: "Hello ROS 2: 22"
    
  5. Ctrl+Cをします

  6. ファイルの内容を確認します

    $ ros2 bag info my_bag
    
    Files:             my_bag_0.mcap
    Bag size:          36.0 KiB
    Storage id:        mcap
    ROS Distro:        jazzy
    Duration:          214.495901362s
    Start:             May  5 2025 14:50:24.818789035 (1746456624.818789035)
    End:               May  5 2025 14:53:59.314690397 (1746456839.314690397)
    Messages:          430
    Topic information: Topic: /hello | Type: std_msgs/msg/String | Count: 430 | Serialization Format: cdr
    Service:           0
    Service information: 
    $ 
    
    • Files:使用されているバッグファイル
    • Bag size:データ全体のファイルサイズ
    • Storage id:記録形式(mcap)
    • ROS Distro:使用されたROS 2ディストリビューション(例: jazzy)
    • Duration:記録された時間の長さ(開始から終了までの合計時間)
    • Start / End:記録の開始時刻と終了時刻
    • Messages:430
    • Topic information :トピックごとの詳細(トピック名、型、件数など)
  7. 再生します

    $ ros2 bag play my_bag
    [INFO] [1746457477.260023213] [rosbag2_player]: Set rate to 1
    [INFO] [1746457477.666327399] [rosbag2_player]: Adding keyboard callbacks.
    [INFO] [1746457477.666606203] [rosbag2_player]: Press SPACE for Pause/Resume
    [INFO] [1746457477.666824385] [rosbag2_player]: Press CURSOR_RIGHT for Play Next Message
    [INFO] [1746457477.667502398] [rosbag2_player]: Press CURSOR_UP for Increase Rate 10%
    [INFO] [1746457477.667742370] [rosbag2_player]: Press CURSOR_DOWN for Decrease Rate 10%
    [INFO] [1746457477.668139344] [rosbag2_player]: Playback until timestamp: -1
    $ 
    
    • ros2 bag record:記録したROSメッセージを再度Publishする

考察

今回、ROS2とMCAPについて簡単に試してみました。
次回は、ツールを使用してMCAPファイルのかしkを試してみます。

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?