ROS2のYAMLファイルを使ったパラメータ設定でパラメータ宣言をせずにパラメータを取得する
TL;DR
一々パラメータの宣言せずに、yamlに書いたパラメータをget_parameter
で取得したい!って場合。
- ノードのオプションを設定し、コンストラクタに渡す。
- rclcpp::NodeOptions
の変数を作り、以下を追加
- allow_undeclared_parameters(true)
- automatically_declare_parameters_from_overrides(true)
- (use_intra_process_comms(true)
などプロセス内通信を行う他のオプションも必要あれば追加しておく)
- コンストラクタ内で継承したノードに渡したオプションで初期化する。
test_node:
ros__parameters:
param1: 100
# 以下、必要に応じてパラメータが続く
int main(int argc, char *argv[])
{
rclcpp::init(argc, argv);
// ノードオプションの設定
rclcpp::NodeOptions node_options;
node_options.allow_undeclared_parameters(true);
node_options.automatically_declare_parameters_from_overrides(true);
// node_options.use_intra_process_comms(true);
std::shared_ptr<TestNode> test_node = nullptr;
test_node = std::make_shared<TestNode>("test_topic", "test_node", node_options);
...
}
TestNode::TestNode(const std::string& topic_name, const std::string& node_name, const rclcpp::NodeOptions &options)
:Node(node_name, options)
{
// declareしなくても指定のパラメーターが取得できる
auto param1 = this->get_parameter("param1").as_string();
// 以下PublisherやSubscriberの設定が続く
}
#include<TestNode.hpp>
std::shared_ptr<TestNode> test_node = nullptr;
test_node = std::make_shared<TestNode>("test_topic", "test_node");
// 上記同様declareしなくても指定のパラメーターが取得できる
auto param1 = test_node->get_parameter("param1").as_string();
// 以下executor等が続く
ros2 run test test_exec --ros-args --params-file config.yaml
はじめに
ROS2ではros2 run
実行時に--ros-args --params-file
を付与することで、yamlファイルからパラメータを呼び出すことができ、非常に便利です。
以下の記事を参考になると思います。
YAMLファイルによるROS2のパラメータ設定
ただ、コンストラクタ内、もしくはノードのメンバ関数declare_parameter("パラメータ名", 引数)
を使ってパラメータを宣言したあとに、get_parameter("パラメータ名")
でパラメータを取得する必要が有ります。
例
test_node:
ros__parameters:
param1: 100
# 以下、必要に応じてパラメータが続く
TestNode::TestNode(const std::string& topic_name, const std::string& node_name): Node(node_name)
{
this->declare_parameter("param1", "test")
auto param1 = this->get_parameter("param1").as_string();
// 以下PublisherやSubscriberの設定が続く
}
#include<TestNode.hpp>
std::shared_ptr<TestNode> test_node = nullptr;
test_node = std::make_shared<TestNode>("test_topic", "test_node");
test_node->declare_parameter("param1", "test");
auto param1 = test_node->get_parameter("param1").as_string();
// 以下executor等が続く
declare_parameter
を忘れてしまい、あれ、取得できない、、、なんてこともしばしば起こります。
("param1" is not declared みたいなエラーが出てROS2実行できません)
パラメータが増えれば増えるほど、declareするパラメータも増えるので辛いです。
Nodeのオプションを指定
Nodeのコンストラクタ内でオプションを渡すだけで、簡単にパラメータを宣言する必要が無くなります。
プロセス内通信を利用している方はコンストラクタにおいてrclcpp::NodeOptions().use_intra_process_comms(true)
でNodeのオプションを初期化しているのをお目にしているのではないでしょうか?そう、それです。
今回は以下のオプションを利用します。
allow_undeclared_parameters(true)
automatically_declare_parameters_from_overrides(true)
上記オプションのAPI Referenceは
になります。
allow_undeclared_parameters
で宣言していないパラメータの使用を許可し、もし、オーバーライドしたパラメータがあればautomatically_declare_parameters_from_overrides
でそれも含めて暗黙的に宣言します。
Referenceにも書いてある通り、allow_undeclared_parameters
だけだと、オーバーライドしたパラメータはノード上には現れません。
ただ、今回の例はautomatically_declare_parameters_from_overrides
が要らなさそうですね(今更ながら)。
具体的には、実行ファイルとなるmain関数でNodeを生成する際に以下のようにオプションを渡すだけでOKです。
(もちろん、Nodeのヘッダーファイルとソースファイルで引数を受け取れるようにしておく必要が有ります。)
int main(int argc, char *argv[])
{
rclcpp::init(argc, argv);
// ノードオプションの設定
rclcpp::NodeOptions node_options;
node_options.allow_undeclared_parameters(true);
node_options.automatically_declare_parameters_from_overrides(true);
// node_options.use_intra_process_comms(true);
std::shared_ptr<TestNode> test_node = nullptr;
test_node = std::make_shared<TestNode>("test_topic", "test_node", node_options);
...
}
TestNode::TestNode(const std::string& topic_name, const std::string& node_name, const rclcpp::NodeOptions &options)
:Node(node_name, options)
// ↑初期化
{
// これでdeclareしなくても指定のパラメーターが取得できる
auto param1 = this->get_parameter("param1").as_string();
// 以下PublisherやSubscriberの設定が続く
}
// ... Nodeの変数生成等
// 上記同様declareしなくても指定のパラメーターが取得できる
auto param1 = test_node->get_parameter("param1").as_string();
// 以下executor等が続く
as_stringやas_intを付けたくない
パラメータによっては、stringだったりintだったり型が異なる場合が有ります。
パラメータ取得の際に毎回as_string()
, as_int()
等付けることは余計なミスが増える原因になります。
その場合は以下のようにテンプレートを用いましょう。
// テンプレート関数を実装
template <class T>
void SetParameter(const std::weak_ptr<rclcpp::Node>& node, std::string parameter_name, T& out)
{
// std::weak_ptrでNodeを受け取り、lock()することでshared_ptrを得る
if (auto node_handle = node.lock()){
node_handle->get_parameter(parameter_name, out);
} else {
throw std::runtime_error("ERROR");
}
}
int main(int argc, char *argv[])
{
rclcpp::init(argc, argv);
// ノードオプションの設定
rclcpp::NodeOptions node_options;
node_options.allow_undeclared_parameters(true);
node_options.automatically_declare_parameters_from_overrides(true);
// node_options.use_intra_process_comms(true);
std::shared_ptr<TestNode> test_node = nullptr;
test_node = std::make_shared<TestNode>("test_topic", "test_node", node_options);
// パラメータ用の変数
int width;
std::string save_dir;
SetParameter(test_node, "camera_width", width);
SetParameter(test_node, "save_dir_name", save_dir);
}
参考
Author And Source
この問題について(ROS2のYAMLファイルを使ったパラメータ設定でパラメータ宣言をせずにパラメータを取得する), 我々は、より多くの情報をここで見つけました https://qiita.com/bigface00/items/1810c6de4d115cc052d8著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .