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?

実習ROS 2 ros2 paramを使う2

Last updated at Posted at 2025-03-28

環境

本記事は以下の環境を想定して記述している。

項目
OS Ubuntu 22.04
ROS ROS 2 Humble

概要

この記事ではros2 paramを使う1に続いて、ROS 2のパラメータの処理に関する以下の内容を扱う。

  • 現在のROS 2でサポートされているパラメータ型について
  • yamlファイルからパラメータを渡すプログラムの実装
  • リスト型のパラメータを使用する例

パラメータの型について

ROS 2のパラメータで使用可能な型を以下に示す(参考)。

ROS 1では、辞書型や異なる複数の型をもつパラメータを扱うことができた。しかし、現状のROS 2(Jazzyまで)では扱うことができない。
そのため、扱えるパラメータの制約が大きく、YAMLファイルで表現できる全ての形式のパラメータを扱えないことに注意が必要である。

  • bool
  • int64
  • float64
  • string
  • byte[]
  • bool[]
  • int64[]
  • float64[]
  • string[]

※注
ROS 2のパラメータ型と、C++, Pythonの型との対応は、ROS 2公式ドキュメントに記載がある。

なお、公式ドキュメントに以下のような記述があるので、今後扱える型の種類が増える可能性がある。

Feature parity

Some features of ROS 1 parameters files do not exist in ROS 2:

  • Mixed types in a list is not supported yet (related issue)

  • deg and rad substitutions are not supported

実装

ros2 paramを使う1と同様に、パッケージを作成する。
任意のROS 2ワークスペースに移動したあと、以下のコマンドでパッケージros2_param2を作成する。

ros2 pkg create ros2_param2 --build-type ament_cmake

YAMLファイルでのパラメータの記述

パッケージ内にconfigディレクトリを作成し、params.yamlファイルを作成する。
YAML形式で以下のようにパラメータを定義する。
以下の例では、param_talker_advancedノード用のパラメータを複数定義している。

# config/params.yaml
param_talker_advanced:                        # ノード名をキーとして先頭に置く 
  ros__parameters:                            # 固定名のキー
    integer_param: 10                         # 以下、パラメータ
    string_param: "Hello world"
    boolean_params: [true, true, false, true]
    list_param:                               # キーを階層構造にすることも可能
      double_param : 3.14

先頭のキーはノード名となっている(param_talker_advanced)。そのため、launchファイルやオプションでノード名を変更した際にはYAMLファイルも変更が必要になる。

ノードの実装

用意したYAMLファイルを読み込み、値を確認するためのノードを実装する。
srcディレクトリ中に、param_talker_advanced.cppファイルを作成し、ノードを実装する。

ノードの実装の構造はros2 paramを使う1で説明したものと同様である。
クラスのコンストラクタで各種のパラメータの宣言とタイマの設定を行い、タイマのコールバック関数でパラメータの値を取得、表示する。

#include <chrono>
#include <string>
#include <vector>
#include <sstream>

#include "rclcpp/rclcpp.hpp"

using namespace std::chrono_literals;

class ParamTalkerAdvanced : public rclcpp::Node
{
public:
  ParamTalkerAdvanced()
  : Node("param_talker_advanced")
  {
    // パラメータの宣言
    this->declare_parameter<int64_t>("integer_param", 100);
    this->declare_parameter<std::string>("string_param", "foo");
    this->declare_parameter<std::vector<bool>>("boolean_params", std::vector<bool>{true});
    this->declare_parameter<double>("list_param.double_param", 0.0);

    // タイマの生成
    // 1000msごとに、timer_callback()関数が呼ばれるようにする
    timer_ = this->create_wall_timer(1000ms, std::bind(&ParamTalkerAdvanced::timer_callback, this));
  }

private:
  // タイマによって呼び出される関数
  void timer_callback()
  {
    // 整数型パラメータの取得と表示
    int64_t int_param;
    this->get_parameter("integer_param", int_param);
    RCLCPP_INFO(this->get_logger(), "integer_param: %ld", int_param);

    // 文字列型パラメータの取得と表示
    std::string str_param;
    this->get_parameter("string_param", str_param);
    RCLCPP_INFO(this->get_logger(), "string_param: %s", str_param.c_str());

    // 真偽型パラメータの取得と表示
    std::vector<bool> boolean_params;
    std::stringstream ss;
    std::string del = "";
    this->get_parameter("boolean_params", boolean_params);
    ss << "[";
    for (auto v : boolean_params) {
      ss << del << v;
      del = ", ";
    }
    ss << "]";
    RCLCPP_INFO(this->get_logger(), "boolean_params: %s", ss.str().c_str());

    // 実数型パラメータの取得と表示
    double double_param;
    this->get_parameter("list_param.double_param", double_param);
    RCLCPP_INFO(this->get_logger(), "list_param.double_param: %lf\n", double_param);
  }

  // 一定周期で処理を実行するタイマ
  rclcpp::TimerBase::SharedPtr timer_;
};

int main(int argc, char * argv[])
{
  rclcpp::init(argc, argv);
  rclcpp::spin(std::make_shared<ParamTalkerAdvanced>());
  rclcpp::shutdown();

  return 0;
}

launchファイルの実装

パッケージ内のlaunchフォルダにparam_talker_advanced.launch.pyを作成し、launchファイルを実装する。

launchファイルでは、パラメータが定義されたYAMLファイルのパスを取得し、それをノードに渡す処理を記述する。
以下の実装では、ファイルへの絶対パスを表す文字列config_pathを取得し、それをノードのparameters引数に渡している。
また、config_pathは以下のパスをos.path.join()を用いて結合して得ている。

  • get_package_share_directory()によって得られたインストール先のパッケージの場所
  • configディレクトリ
  • params.yamlファイル
import os

from ament_index_python.packages import get_package_share_directory

from launch import LaunchDescription
from launch_ros.actions import Node


def generate_launch_description():
    ld = LaunchDescription()

    # yamlファイルのパスを取得
    config_path = os.path.join(
        get_package_share_directory('ros2_param2'),
        'config',
        'params.yaml'
    )

    # パラメータを指定してノードを起動
    param_talker_node = Node(
        package='ros2_param2',
        executable='param_talker_advanced',
        parameters=[config_path]
    )

    ld.add_action(param_talker_node)

    return ld

ビルド

package.xmlをこれまでの記事(例:Pub&Sub通信)と同様に編集し、パッケージ情報を適切に記載する。

CMakeLists.txtもこれまでとほとんど同様に記述するが、configディレクトリをインストールするように追記することが必要になる。
これまでの記述と異なる部分を強調して以下に示す。

  # find dependencies
  find_package(ament_cmake REQUIRED)
  find_package(rclcpp REQUIRED)
  
  add_executable(param_talker_advanced
    src/param_talker_advanced.cpp
  )
  
  ament_target_dependencies(param_talker_advanced
    rclcpp
  )
  
  install(TARGETS
    param_talker_advanced
    DESTINATION lib/${PROJECT_NAME}
  )
  
  install(
    DIRECTORY
    launch
+   config    # パラメータファイルがインストールされるように追加
    DESTINATION share/${PROJECT_NAME}/
  )

その後、ROS 2ワークスペースのトップディレクトリで、このパッケージをビルドする。

colcon build --packages-up-to ros2_param2

実行結果

ワークスペースのセットアップスクリプトを実行した後、launchファイルを実行する。

実行例を以下に示す。ソースコード中で記述したパラメータではなく、YAMLファイルで与えたパラメータが表示されていることが分かる。

$ ros2 launch ros2_param2 param_talker_advanced.launch.py 
[INFO] [launch]: Default logging verbosity is set to INFO
[INFO] [param_talker_advanced-1]: process started with pid [66559]
[param_talker_advanced-1] [INFO] [1665106045.274766294] [param_talker_advanced]: integer_param: 10
[param_talker_advanced-1] [INFO] [1665106045.274852845] [param_talker_advanced]: string_param: Hello world
[param_talker_advanced-1] [INFO] [1665106045.274866644] [param_talker_advanced]: boolean_params: [1, 1, 0, 1]
[param_talker_advanced-1] [INFO] [1665106045.274870401] [param_talker_advanced]: list_param.double_param: 3.140000
[param_talker_advanced-1] 
[param_talker_advanced-1] [INFO] [1665106046.274758208] [param_talker_advanced]: integer_param: 10
[param_talker_advanced-1] [INFO] [1665106046.274799771] [param_talker_advanced]: string_param: Hello world
[param_talker_advanced-1] [INFO] [1665106046.274812689] [param_talker_advanced]: boolean_params: [1, 1, 0, 1]
[param_talker_advanced-1] [INFO] [1665106046.274816286] [param_talker_advanced]: list_param.double_param: 3.140000
[param_talker_advanced-1] 
[param_talker_advanced-1] [INFO] [1665106047.274758962] [param_talker_advanced]: integer_param: 10
[param_talker_advanced-1] [INFO] [1665106047.274784315] [param_talker_advanced]: string_param: Hello world
[param_talker_advanced-1] [INFO] [1665106047.274805575] [param_talker_advanced]: boolean_params: [1, 1, 0, 1]
[param_talker_advanced-1] [INFO] [1665106047.274808884] [param_talker_advanced]: list_param.double_param: 3.140000
[param_talker_advanced-1] 
[param_talker_advanced-1] [INFO] [1665106048.274807719] [param_talker_advanced]: integer_param: 10
[param_talker_advanced-1] [INFO] [1665106048.274853121] [param_talker_advanced]: string_param: Hello world
[param_talker_advanced-1] [INFO] [1665106048.274863529] [param_talker_advanced]: boolean_params: [1, 1, 0, 1]
[param_talker_advanced-1] [INFO] [1665106048.274866921] [param_talker_advanced]: list_param.double_param: 3.140000
[param_talker_advanced-1] 

また、ros2 runコマンドでノードを実行するときにも、パスを直接渡すことでパラメータファイルを与えることができる。
例えば、params.yamlファイルがホームディレクトリ直下にある場合(~/params.yaml)、以下のように実行できる。

$ ros2 run ros2_param2 param_talker_advanced --ros-args --params-file ~/params.yaml 
[INFO] [1665106154.940694528] [param_talker_advanced]: integer_param: 10
[INFO] [1665106154.940796499] [param_talker_advanced]: string_param: Hello world
[INFO] [1665106154.940811320] [param_talker_advanced]: boolean_params: [1, 1, 0, 1]
[INFO] [1665106154.940815548] [param_talker_advanced]: list_param.double_param: 3.140000

[INFO] [1665106155.940690462] [param_talker_advanced]: integer_param: 10
[INFO] [1665106155.940753139] [param_talker_advanced]: string_param: Hello world
[INFO] [1665106155.940766110] [param_talker_advanced]: boolean_params: [1, 1, 0, 1]
[INFO] [1665106155.940772962] [param_talker_advanced]: list_param.double_param: 3.140000

[INFO] [1665106156.940687680] [param_talker_advanced]: integer_param: 10
[INFO] [1665106156.940746077] [param_talker_advanced]: string_param: Hello world
[INFO] [1665106156.940755667] [param_talker_advanced]: boolean_params: [1, 1, 0, 1]
[INFO] [1665106156.940760453] [param_talker_advanced]: list_param.double_param: 3.140000

参考

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?