ROS2をC++で開発する3回目です。前回、publisher、今回はもう一方のTopicを受けるsubscriberを作ります。
yoshi@yoshi:~/ros2_ws$ tree
.
└── works
├── CMakeLists.txt
├── include
│ └── works
├── package.xml
└── src
├── exec_sample
│ └── main.c
└── pub
└── pub.cpp
環境
- Raspberry Pi 5 8GB
- 追加ボード;NVMe Base for Raspberry Pi 5 (NVMe Base by Pimoroni)
- Crucial クルーシャル P2シリーズ 500GB 3D NAND NVMe PCIe M.2 SSD CT500P2SSD8
- 初期;RaspberryPi OS Desktop 64bit (Debian version: 12 (bookworm) Release date: March 15th 2024)
- 現在;Ubuntu Desktop 24.04LTS(64-bit)
- ROS2 HumbleではなくJazzy
Windows10で、検索窓にcmdと入れ、コマンドプロンプトを起動します。
sshでログインします(第1回参照)。必要ならupdateします。
C:\Users\yoshi>ssh yoshi.local
ros2が実行できるようにします。
$ source /opt/ros/jazzy/setup.bash
$ cd ros2_ws
subscribeするプログラムを作る
ソースは、pub.cppの入っているpubディレクトリの中に記述します(失敗する)。
#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp"
#include <stdio.h>
rclcpp::Node::SharedPtr g_node = nullptr;
void callback(const std_msgs::msg::String::SharedPtr msg)
{
RCLCPP_INFO(g_node->get_logger(), "%s", msg->data.c_str());
}
int main(int argc, char **argv)
{
printf("start subscribe test\n");
rclcpp::init(argc, argv);
g_node = rclcpp::Node::make_shared("my_subscriber");
auto subscriber = g_node->create_subscription<std_msgs::msg::String>("greeting", 1, callback);
rclcpp::spin(g_node);
g_node = nullptr;
rclcpp::shutdown();
return 0;
}
CMakeLists.txtに、pub.cppを追加した時のようにsub.cppの記述を追加します。
cmake_minimum_required(VERSION 3.8)
project(works)
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
add_compile_options(-Wall -Wextra -Wpedantic)
endif()
# find dependencies
find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)
find_package(rclcpp_components REQUIRED)
find_package(std_msgs REQUIRED)
add_executable(exec_sample
src/exec_sample/main.c)
install(
TARGETS exec_sample
DESTINATION lib/${PROJECT_NAME}
)
add_executable(pub src/pub/pub.cpp)
ament_target_dependencies(pub rclcpp std_msgs)
install(
TARGETS pub
DESTINATION lib/${PROJECT_NAME}
)
add_executable(sub src/pub/sub.cpp)
ament_target_dependencies(sub rclcpp std_msgs)
install(
TARGETS sub
DESTINATION lib/${PROJECT_NAME}
)
if(BUILD_TESTING)
find_package(ament_lint_auto REQUIRED)
# the following line skips the linter which checks for copyrights
# comment the line when a copyright and license is added to all source files
set(ament_cmake_copyright_FOUND TRUE)
# the following line skips cpplint (only works in a git repo)
# comment the line when this package is in a git repo and when
# a copyright and license is added to all source files
set(ament_cmake_cpplint_FOUND TRUE)
ament_lint_auto_find_test_dependencies()
endif()
ament_package()
ビルドします。
yoshi@yoshi:~/ros2_ws$ colcon build
Starting >>> works
--- stderr: works
Traceback (most recent call last):
File "/opt/ros/jazzy/share/ament_cmake_core/cmake/package_templates/templates_2_cmake.py", line 21, in <module>
from ament_package.templates import get_environment_hook_template_path
ModuleNotFoundError: No module named 'ament_package'
CMake Error at /opt/ros/jazzy/share/ament_cmake_core/cmake/ament_cmake_package_templates-extras.cmake:41 (message):
execute_process(/usr/bin/python3
/opt/ros/jazzy/share/ament_cmake_core/cmake/package_templates/templates_2_cmake.py
/home/yoshi/ros2_ws/build/works/ament_cmake_package_templates/templates.cmake)
returned error code 1
Call Stack (most recent call first):
/opt/ros/jazzy/share/ament_cmake_core/cmake/ament_cmake_coreConfig.cmake:41 (include)
/opt/ros/jazzy/share/ament_cmake/cmake/ament_cmake_export_dependencies-extras.cmake:15 (find_package)
/opt/ros/jazzy/share/ament_cmake/cmake/ament_cmakeConfig.cmake:41 (include)
CMakeLists.txt:9 (find_package)
...
エラーが出ました。一つのディレクトリ、ここではpubの中に複数のソースがある場合のCMakeLists.txtの書き方が正しくないのかもしれません。
$ source /opt/ros/jazzy/setup.bash
忘れていたようです(二日目の作業でsshを起動しなおしたから)。
yoshi@yoshi:~/ros2_ws$ colcon build
Starting >>> works
--- stderr: works
/usr/bin/ld: CMakeFiles/pub.dir/src/pub/sub.cpp.o: in function `main':
sub.cpp:(.text+0x2f4): multiple definition of `main'; CMakeFiles/pub.dir/src/pub/pub.cpp.o:pub.cpp:(.text+0x88): first defined here
複数のmainがあるよと言っているようです。同じディレクトリに複数のアプリを書くような書き方ではなく、分割して記述するときに使われるようです。例えば、pub.hとmain.cとpub_123.cとか。
これらのエラー情報から、worksの下に最初に作ったsrc/exec_sample/main.c、前回作ったsrc/pub/pub.cppに加えて、新規に、src/subフォルダを作り、sub.cppを移動します。
yoshi@yoshi:~/ros2_ws$ mkdir works/src/sub
yoshi@yoshi:~/ros2_ws$ mv works/src/pub/sub.cpp works/src/sub
└── works
├── CMakeLists.txt
├── include
│ └── works
├── package.xml
└── src
├── exec_sample
│ └── main.c
├── pub
│ └── pub.cpp
└── sub
└── sub.cpp
CMakeLists.txtを修正します。
cmake_minimum_required(VERSION 3.8)
project(works)
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
add_compile_options(-Wall -Wextra -Wpedantic)
endif()
# find dependencies
find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)
find_package(rclcpp_components REQUIRED)
find_package(std_msgs REQUIRED)
add_executable(exec_sample src/exec_sample/main.c)
install(
TARGETS exec_sample
DESTINATION lib/${PROJECT_NAME}
)
add_executable(pub src/pub/pub.cpp)
ament_target_dependencies(pub rclcpp std_msgs)
install(
TARGETS pub
DESTINATION lib/${PROJECT_NAME}
)
add_executable(sub src/sub/sub.cpp)
ament_target_dependencies(sub rclcpp std_msgs)
install(
TARGETS sub
DESTINATION lib/${PROJECT_NAME}
)
if(BUILD_TESTING)
find_package(ament_lint_auto REQUIRED)
# the following line skips the linter which checks for copyrights
# comment the line when a copyright and license is added to all source files
set(ament_cmake_copyright_FOUND TRUE)
# the following line skips cpplint (only works in a git repo)
# comment the line when this package is in a git repo and when
# a copyright and license is added to all source files
set(ament_cmake_cpplint_FOUND TRUE)
ament_lint_auto_find_test_dependencies()
endif()
ament_package()
ビルドします。
yoshi@yoshi:~/ros2_ws$ colcon build
エラーなく終了しました。約15秒かかっています。
ラズパイ(画面)では、前回動かした可視化ツールrqt_graphが動いています。
ビルドしたものを登録します。subscriberのsubを起動します。
yoshi@yoshi:~/ros2_ws$ source ~/ros2_ws/install/setup.bash
yoshi@yoshi:~/ros2_ws$ ros2 run works sub
もう一つターミナルを立ち上げます。publisherのpubを起動します。
ssh yoshi.local
yoshi@yoshi:~/ros2_ws$ source ~/ros2_ws/install/setup.bash
yoshi@yoshi:~/ros2_ws$ ros2 run works pub
start publish test
最初のターミナルの様子です。
yoshi@yoshi:~/ros2_ws$ ros2 run works sub
start subscribe test
[INFO] [1722076131.778617869] [yoshi_subscriber]: Hello, world 0
[INFO] [1722076132.778774857] [yoshi_subscriber]: Hello, world 1
[INFO] [1722076133.778717550] [yoshi_subscriber]: Hello, world 2
[INFO] [1722076134.778719985] [yoshi_subscriber]: Hello, world 3
[INFO] [1722076135.778789254] [yoshi_subscriber]: Hello, world 4
[INFO] [1722076136.778799579] [yoshi_subscriber]: Hello, world 5
[INFO] [1722076137.778784072] [yoshi_subscriber]: Hello, world 6
[INFO] [1722076138.778818511] [yoshi_subscriber]: Hello, world 7
[INFO] [1722076139.778783895] [yoshi_subscriber]: Hello, world 8
[INFO] [1722076140.778757076] [yoshi_subscriber]: Hello, world 9
[INFO] [1722076141.778729184] [yoshi_subscriber]: Hello, world 10
[INFO] [1722076142.778748571] [yoshi_subscriber]: Hello, world 11
ラズパイで動いているrqt_graphの左上にあるアイコンを押してリフレッシュします。
動作の確認ができました。
(※)参考にさせていただいたサイト
備忘録 ラズパイ5 ROS2
① ハードの用意とUbuntu Desktop 24.04LTS
② Ubuntu Desktop 24.04LTSでROS2環境 rqt_graphとturtlesim
③ Ubuntu Desktop 24.04LTSでROS2環境 Python その1 responder(セットアップ)
④ Ubuntu Desktop 24.04LTSでROS2環境 Pythonその2responder(コーディングと実行;失敗)
⑤ Ubuntu Desktop 24.04LTSでROS2環境 C++ その1 セットアップ main.c
⑥ Ubuntu Desktop 24.04LTSでROS2環境 C++ その2 セットアップ pub.cpp rqt_graph
⑦ Ubuntu Desktop 24.04LTSでROS2環境 C++ その3 セットアップ sub.cpp rqt_graph
⑧ Ubuntu Desktop 24.04LTSでROS2環境 C++ その4 bme280.cpp 温度
⑨ Ubuntu Desktop 24.04LTSでROS2環境 C++ その5 bme280_3.cpp 温度、湿度、気圧
⑩ Ubuntu Desktop 24.04LTSでROS2環境 C++ その6 VL53L1X.cpp 距離センサ