【ROS2関係トップページへ】
【前:ROS2の共有ライブラリを使用したプログラムの作成】
【次:ROS2のコンポーネントの利用】
共有ライブラリに更に手を加えてコンポーネントを作成する.
ROS2における共有ライブラリで作成したものを例にコマンド類の説明をする.
- パッケージ名
- minimal_comp
- 共有ライブラリで使用できる機能・クラスを収めたソースファイル
- minimal_comp_node1.hppと.cpp
- クラス名:MinimalCompNode1
- minimal_comp_node1.hppと.cpp
- パッケージ共通のnamespace
- minimal_comp
なぜにコンポーネント?
- 共有ライブラリとしても使える
- ひと手間加えるだけで共有ライブラリとしてもコンポーネントとしても使える.
- ノード単体で起動可能である
- ターゲットを作成しなくてもよい
特に2点目について説明する.
ROS2の共有ライブラリを使用したプログラムの作成の共有ライブラリを使用したプログラムにあるプログラムを再掲する.
#include <rclcpp/rclcpp.hpp>
#include "minimal_comp/minimal_comp_node1.hpp"
int main(int argc, char * argv[]){
rclcpp::init(argc,argv);
rclcpp::spin(std::make_shared<minimal_comp::MinimalCompNode1>());
rclcpp::shutdown();
return 0;
}
このように共有ライブラリを単に起動するだけのターゲットを考えると,どんな共有ライブラリでも同じプログラムになるけど一々作成しなければならず面倒である.
こんな起動の仕方ならノードを直接起動しても良くない?→それコンポーネント,のイメージである(個人的見解).
コンポーネントの作り方
dependencies
依存関係としてrclcpp_componentsを指定する.
例えば以下のようになる.
コンポーネントはrclcpp::Nodeから継承するので,当然rclcppも必要.
$ ros2 pkg create minimal_comp --build-type ament_cmake --dependencies rclcpp rclcpp_components
パッケージ作成時にdependenciesを付けない場合,以下を手動で書き込む.
<package format="3">
<depend>rclcpp</depend>
<depend>rclcpp_components</depend>
find_package(rclcpp REQUIRED)
find_package(rclcpp_components REQUIRED)
CMakeLists.txt
以下は関係する部分を抜き出したものとなる.詳しくはROS2における共有ライブラリのCMakeLists.txtを参照のこと.
add_library(minimal_comp_node SHARED
src/minimal_comp_node1.cpp
)
rclcpp_components_register_nodes(minimal_comp_node "minimal_comp::MinimalCompNode1")
target_compile_definitions(minimal_comp_node
PRIVATE "MY_LIBRARY_BUILDING_LIBRARY"
)
target_compile_options(minimal_comp_node PUBLIC -Wall)
ament_target_dependencies(minimal_comp_node
rclcpp
rclcpp_components
)
説明
重要となるのは,4行目と11行目(下から2行目)である.
4行目:rclcpp_components_register_nodesによりノードを登録.
11行目:依存関係があるので,ament_target_dependenciesにrclcpp_componentsを追加.
rclcpp_components_register_nodesの使い方は以下の通り.
rclcpp_components_register_nodes([target名] "namespace::クラス名")
ソースファイル
ノードの実装をしている.cppファイル(例だとminimal_comp_node1.cpp)に以下を追記する.
- #include "rclcpp_components/register_node_macro.hpp"
- RCLCPP_COMPONENTS_REGISTER_NODE(namespace::クラス名)
- 一番下,namespaceの定義外に以下を追加
- 例の場合以下のようになる
- RCLCPP_COMPONENTS_REGISTER_NODE(minimal_comp::MinimalCompNode1)
注意点
コンポーネントにするノードのコンストラクタは引数としてrclcpp::NodeOptionsの一つしか持てない.
よってROS2における共有ライブラリの共有ライブラリ化する二つのクラスのような以下のクラスだとエラーが起きる.
#include <rclcpp/rclcpp.hpp>
#include "minimal_comp/visibility.h" // 同一ディレクトリなら#include "visibility.h"でもok
namespace minimal_comp {
class MinimalCompNode1 : public rclcpp::Node{
public:
MINIMAL_COMP_PUBLIC
MinimalCompNode1(
const std::string &name_space="",
const rclcpp::NodeOptions& options=rclcpp::NodeOptions()
);
};
}
解決方法
解決方法は簡単で引数がrclcpp::NodeOptionsの一つとなるコンストラクタを作ってやればよい.
以下の二つ目のコンストラクタで,name_spaceにデフォルト引数を与えないように注意.
これで,name_spaceを引数にとれる共有ライブラリとしてもコンポーネントとしても使用可となる.
#include <rclcpp/rclcpp.hpp>
#include "minimal_comp/visibility.h" // 同一ディレクトリなら#include "visibility.h"でもok
namespace minimal_comp {
class MinimalCompNode1 : public rclcpp::Node{
public:
MINIMAL_COMP_PUBLIC
MinimalCompNode1(
const rclcpp::NodeOptions& options=rclcpp::NodeOptions()
);
MINIMAL_COMP_PUBLIC
MinimalCompNode1(
const std::string& name_space,
const rclcpp::NodeOptions& options=rclcpp::NodeOptions()
);
};
}
これを使ってコンポーネント用に作り替えると以下のようになる.
2行目と22行目がコンポーネント登録となる.
#include <rclcpp/rclcpp.hpp>
#include "rclcpp_components/register_node_macro.hpp"
#include "minimal_comp/minimal_comp_node1.hpp"
namespace minimal_comp {
MinimalCompNode1::MinimalCompNode1(
const rclcpp::NodeOptions& options
): MinimalCompNode1("", options)
{}
MinimalCompNode1::MinimalCompNode1(
const std::string& name_space,
const rclcpp::NodeOptions& options
): Node("minimal_comp1", name_space, options)
{
RCLCPP_INFO(this->get_logger(),"minimal comp 1 test");
}
}
RCLCPP_COMPONENTS_REGISTER_NODE(minimal_comp::MinimalCompNode1)