ケースごとの代表例の紹介.基本的に関係部分のみ抜粋.
Foxy Fitzroyからの変更が多いので,ROS2における変更点: from Eloquent Elusor to Foxy Fitzroyを参照のこと.
Humble Hawksbill以降はこちらを参照のこと.
基本方針として一つのパッケージにすべて(ターゲット・ライブラリ・独自メッセージ)を入れるのではなく,なるべく分割する.
関連するものは,まずワークスペースをつくり,その中に「独自メッセージのパッケージ」「ライブラリとなるnode」「ターゲット」と分ける.
それぞれのパッケージ名を以下のようにすることで分かりやすくする.
- 独自メッセージのパッケージ名
- ***_msgs
- ライブラリとなるパッケージ名
- ***_node
- ターゲットとなるパッケージ名
-
- ***_target
- どっちでも
-
例えば強化学習用のワークスペースだと
- reinforcement_learning_msgs
- reinforcement_learning_node
- reinforcement_learningやreinforcement_learning_target
- 実行形式だけど,テスト用とかなら以下もあり
- reinforcement_learning_test
- 実行形式だけど,テスト用とかなら以下もあり
もちろん独自ルール.
ターゲットの作成
rclcppは通常使用するパッケージ.
それ以外のパッケージを使う場合,例としてパッケージ名:packとして書いておく.packとしては,std_msgsなどROS2が用意しているものもあれば自分で作成した独自メッセージのパッケージやライブラリのパッケージなども考えられる.特になければpackに関係する部分はいらない.
package.xml
<package format="3">
<depend>rclcpp</depend>
<depend>pack</depend>
</package>
dependについて
<package format="3">
<build_depend>rclcpp</build_depend>
<test_depend>rclcpp</test_depend>
<exec_depend>rclcpp</exec_depend>
<build_depend>pack</build_depend>
<test_depend>pack</test_depend>
<exec_depend>pack</exec_depend>
</package>
こちらの方が便利であるが,独自メッセージの作成のようにbuildとexecで異なるパッケージが必要な場合(rosidl_default_generatorsとrosidl_default_runtime)はもちろん別々に記載する.
CMakeLists.txt
二つのターゲット(ここではtarget_name_1とtarget_name_2)を作成する場合.一つの場合や三つ以上の場合は,例のようにadd_executableとament_target_dependenciesおよびinstallの中を追加していく.
自作の共有ライブラリを使わない場合.
find_package(rclcpp REQUIRED)
find_package(pack REQUIRED)
add_executable(target_name_1
src/main.cpp
# ... すべてのcppファイルを記述
)
ament_target_dependencies(target_name_1
rclcpp
pack
)
add_executable(target_name_2
src/main.cpp
# ... すべてのcppファイルを記述
)
ament_target_dependencies(target_name_2
rclcpp
pack
)
install(TARGETS
target_name_1
target_name_2
DESTINATION lib/${PROJECT_NAME}
)
自作の共有ライブラリ(異なるパッケージ)を使う場合.
自作ライブラリのパッケージ名:packとする.
自作ライブラリのパッケージがexportするincludeファイルを読み込むために以下に関する部分を追加.
- target_include_directories
find_package(rclcpp REQUIRED)
find_package(pack REQUIRED)
add_executable(target_name_1
src/main.cpp
# ... すべてのcppファイルを記述
)
ament_target_dependencies(target_name_1
rclcpp
pack
)
target_include_directories(target_name_1
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
)
add_executable(target_name_2
src/main.cpp
# ... すべてのcppファイルを記述
)
ament_target_dependencies(target_name_2
rclcpp
pack
)
target_include_directories(target_name_2
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
)
install(TARGETS
target_name_1
target_name_2
DESTINATION lib/${PROJECT_NAME}
)
自作の共有ライブラリの作成
package.xml
ライブラリのパッケージを作るには,rclcpp_componentsが必要なのでそれを追加.
rclcpp_componentsはコンポーネンツを作成するときに必要で共有ライブラリの作成時にはいらない.
<package format="3">
<depend>rclcpp</depend>
CMakeLists.txt
ライブラリ名:my_libを作成.そのために必要なソースファイルの例をlib1.cppとlib2.cppとする.
ament_export_targetsで指定しているexport_my_libはinstallのEXPORTで名前つけしているもの.EXPORTでどんなものでも大丈夫なようだけど,通常パッケージ名の頭にexport_を付けるみたい.
find_package(rclcpp REQUIRED)
add_library(my_lib SHARED
src/my_lib1.cpp
src/my_lib2.cpp
)
target_compile_definitions(my_lib
PRIVATE "MY_LIBRARY_BUILDING_LIBRARY"
)
target_compile_options(my_lib PUBLIC -Wall)
ament_target_dependencies(my_lib
rclcpp
rclcpp_components
)
target_include_directories(my_lib
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
)
if(NOT WIN32)
ament_environment_hooks(
"${ament_cmake_package_templates_ENVIRONMENT_HOOK_LIBRARY_PATH}"
)
endif()
ament_export_targets(export_${PROJECT_NAME} HAS_LIBRARY_TARGET)
install(
DIRECTORY include/
DESTINATION include
)
install(TARGETS
my_lib
EXPORT export_${PROJECT_NAME}
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib
RUNTIME DESTINATION bin
INCLUDES DESTINATION include
)
Eloquent Elusorまでの場合
同一パッケージでターゲットと共有ライブラリを作成
異なるパッケージの共有ライブラリを使用してターゲットを作成する場合には,共有ライブラリのパッケージをfind_packageで読み込み,target_include_directoriesで指定した.
同一パッケージの場合,add_libraryで名付けたライブラリ名をtarget_include_directoriesで指定するだけ.
package.xml
ライブラリのパッケージを作るには,rclcpp_componentsが必要なのでそれを追加.
rclcpp_componentsはコンポーネンツを作成するときに必要で共有ライブラリの作成時にはいらない.
<package format="3">
<depend>rclcpp</depend>
CMakeLists.txt
find_package(rclcpp REQUIRED)
add_library(my_lib SHARED
src/my_lib1.cpp
src/my_lib2.cpp
)
target_compile_definitions(my_lib
PRIVATE "MY_LIBRARY_BUILDING_LIBRARY"
)
target_compile_options(my_lib PUBLIC -Wall)
ament_target_dependencies(my_lib
rclcpp
rclcpp_components
)
target_include_directories(my_lib
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
)
if(NOT WIN32)
ament_environment_hooks(
"${ament_cmake_package_templates_ENVIRONMENT_HOOK_LIBRARY_PATH}"
)
endif()
ament_export_targets(export_${PROJECT_NAME} HAS_LIBRARY_TARGET)
add_executable(target_name_1
src/main.cpp
# ... すべてのcppファイルを記述
)
ament_target_dependencies(target_name_1
rclcpp
my_lib
)
target_include_directories(target_name_1
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
)
install(
DIRECTORY include/
DESTINATION include
)
install(TARGETS
my_lib
EXPORT export_${PROJECT_NAME}
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib
RUNTIME DESTINATION bin
INCLUDES DESTINATION include
)
install(TARGETS
target_name_1
DESTINATION lib/${PROJECT_NAME}
)
独自メッセージの作成
Foxy Fitzroyから以下の点が変わった?
- rosidl_default_generatorsについて
- タグがbuildtool_dependからbuild_dependに変更
- ament_export_dependencies(rosidl_default_runtime)が不必要
- 自動判別してくれるようになった?
- あってもOK
詳しくはROS2独自メッセージの作成参照のこと.
package.xml
<package format="3">
<build_depend>rosidl_default_generators</build_depend>
<exec_depend>rosidl_default_runtime</exec_depend>
<member_of_group>rosidl_interface_packages</member_of_group>
CMakeLists.txt
メッセージファイルとして以下のものを例として表示
- msg/TwoInts.msg
- srv/CalcTwoFloats.srv
setは中身(複数行可)をラベル付けし${ラベル名}でアクセスしやすくするもの.
setを使わず直接ファイル名をrosidl_generate_interfacesの中に書いてもよい.
find_package(rosidl_default_generators REQUIRED)
set(msg_files
"msg/TwoInts.msg"
)
set(srv_files
"srv/CalcTwoFloats.srv"
)
rosidl_generate_interfaces(${PROJECT_NAME}
${msg_files}
${srv_files}
)
# ament_export_dependencies(rosidl_default_runtime)
同じパッケージでターゲットも作成する場合
例:ターゲット名:my_target
add_executableなどは省略
以上の上,上記のCMakeLists.txtに下記を追加.
get_default_rmw_implementation(rmw_implementation)
find_package("${rmw_implementation}" REQUIRED)
get_rmw_typesupport(typesupport_impls "${rmw_implementation}" LANGUAGE "cpp")
foreach(typesupport_impl ${typesupport_impls})
rosidl_target_interfaces(my_target
${PROJECT_NAME} ${typesupport_impl}
)
endforeach()
同じパッケージでライブラリも作成する場合
同じパッケージでターゲットを作成する場合と同様に...とやらない.
現在エラーを解決できない状態.