ROS2のTutorialsをやります。暫くはTutorialsそのままをやります。
Service通信をC++で実装します。
Writing a simple service and client (C++)
srvは前の記事で作成したものを使います。
ROS2 4
環境はUbuntu 22.04です。ROS2 Humbleです。
Services
Servicesについてはこちらが公式の情報。
Services : 即座に完了する処理をさせる。
例1. nodeの状態を問合せする
例2. ロボットハンドへの指示(ロボットハンドがユーザーに対してサービスをする、という解釈)
長時間の処理の呼び出しには絶対に使うな。
Packageをつくろう !!
$ cd ~/ros2_study
$ cd service_cpp_ws
$ cd src
packageの名前を決めます。
server=svとします。client=clとします。
packageの名前をservice_sv_clとします。
ここで公式の説明に--dependencies
が出てきます。
$ ros2 pkg create service_sv_cl --build-type ament_cmake --node-name add_two_ints_server --dependencies rclcpp
example_interfacesは/opt/ros/humble/share/の下にあります。
公式の説明にあるとおり--dependencies
を使うとCMakeLists.txtにfind_package()
が追加され、
package.xmlに<depend>
が追加されます。
package.xml
--dependencies
を使ったから、自動で設定されるけど、ライセンスなんかの情報はきっちり書きましょうという話し。
$ cd service_sv_cl (cd ~/ros2_study/service_cpp_ws/src/service_sv_cl)
$ vi package.xml
下記についてfillしろ、と書いてあります。
description tag
maintainer tag / email attribute
license tag
Service Serverをつくろう !!
$ cd src (cd ~/ros2_study/service_cpp_ws/src/service_sv_cl/src)
$ vi add_two_ints_server.cpp
公式のソースコードをCopy & Pasteします。wgetじゃないんかい。
生成させたadd_two_ints_server.cppの内容を全て消して公式のソースコードで上書きします。
srvを自作したので、example_interfaces
をadd_msg
に書き換えます。
srvを自作したので、AddTwoInts
をMyAddTwoInts
に書き換えます。
add_two_ints_server.cpp
#include "rclcpp/rclcpp.hpp"
#include "add_msg/srv/my_add_two_ints.hpp"
#include <memory>
void add(const std::shared_ptr<add_msg::srv::MyAddTwoInts::Request> request,
std::shared_ptr<add_msg::srv::MyAddTwoInts::Response> response)
{
response->sum = request->a + request->b;
RCLCPP_INFO(rclcpp::get_logger("rclcpp"), "Incoming request\na: %ld" " b: %ld",
request->a, request->b);
RCLCPP_INFO(rclcpp::get_logger("rclcpp"), "sending back response: [%ld]", (long int)response->sum);
}
int main(int argc, char **argv)
{
rclcpp::init(argc, argv);
std::shared_ptr<rclcpp::Node> node = rclcpp::Node::make_shared("add_two_ints_server");
rclcpp::Service<add_msg::srv::MyAddTwoInts>::SharedPtr service =
node->create_service<add_msg::srv::MyAddTwoInts>("add_two_ints", &add);
RCLCPP_INFO(rclcpp::get_logger("rclcpp"), "Ready to add two ints.");
rclcpp::spin(node);
rclcpp::shutdown();
}
例なので「足し算サービス」をしてくれるサーバーです。
service clientがrequestの中に2つの整数を入れて渡すと、
service serverが足し算の結果をresponseの中に入れて返してくれるというサービスをしてくれます。
CMakeLists.txt
下記を記述します。
installのところはCMakeLists.txtの最後の方かつament_package()の前に書いてください。
add_executable(server src/add_two_ints_server.cpp)
ament_target_dependencies(server rclcpp add_msg)
install(TARGETS
server
DESTINATION lib/${PROJECT_NAME})
完成品。clientはまだ。
cmake_minimum_required(VERSION 3.8)
project(service_sv_cl)
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(add_msg REQUIRED)
add_executable(server src/add_two_ints_server.cpp)
target_compile_features(server PUBLIC c_std_99 cxx_std_17) # Require C99 and C++17
ament_target_dependencies(
server
rclcpp
add_msg
)
install(TARGETS
server
DESTINATION lib/${PROJECT_NAME})
ament_package()
colcon build
Tutorialとして、ここで普通はcolcon buildすると思うのですが、公式は簡単すぎると判断しているのかcolcon buildはclientを作ったあとです。
$ cd ../.. (cd ~/ros2_study/service_cpp_ws)
$ colcon build --packages-select service_sv_cl
勿論、公式に従ってcolcon buildを後回しにしても構いません。
Service Clientをつくろう !!
$ cd src (cd ~/ros2_study/service_cpp_ws/src/service_sv_cl/src)
$ vi add_two_ints_client.cpp
公式のソースコードをCopy & Pasteします。wgetじゃないんかい。
ros2 pkg create --node-name
で複数のnodeを作る方法を探しましたが、簡単に調べた範囲では見つかりませんでした。
だから公式では--node-name
を使わない例を先に示しているのかな ?
srvを自作したので、example_interfaces
をadd_msg
に書き換えます。
srvを自作したので、AddTwoInts
をMyAddTwoInts
に書き換えます。
add_two_ints_client.cpp
#include "rclcpp/rclcpp.hpp"
#include "rclcpp/rclcpp.hpp"
#include "add_msg/srv/my_add_two_ints.hpp"
#include <chrono>
#include <cstdlib>
#include <memory>
using namespace std::chrono_literals;
int main(int argc, char **argv)
{
rclcpp::init(argc, argv);
if (argc != 3) {
RCLCPP_INFO(rclcpp::get_logger("rclcpp"), "usage: add_two_ints_client X Y");
return 1;
}
std::shared_ptr<rclcpp::Node> node = rclcpp::Node::make_shared("add_two_ints_client");
rclcpp::Client<add_msg::srv::MyAddTwoInts>::SharedPtr client =
node->create_client<add_msg::srv::MyAddTwoInts>("add_two_ints");
auto request = std::make_shared<add_msg::srv::MyAddTwoInts::Request>();
request->a = atoll(argv[1]);
request->b = atoll(argv[2]);
while (!client->wait_for_service(1s)) {
if (!rclcpp::ok()) {
RCLCPP_ERROR(rclcpp::get_logger("rclcpp"), "Interrupted while waiting for the service. Exiting.");
return 0;
}
RCLCPP_INFO(rclcpp::get_logger("rclcpp"), "service not available, waiting again...");
}
auto result = client->async_send_request(request);
// Wait for the result.
if (rclcpp::spin_until_future_complete(node, result) == rclcpp::FutureReturnCode::SUCCESS)
{
RCLCPP_INFO(rclcpp::get_logger("rclcpp"), "Sum: %ld", result.get()->sum);
} else {
RCLCPP_ERROR(rclcpp::get_logger("rclcpp"), "Failed to call service add_two_ints");
}
rclcpp::shutdown();
return 0;
}
CMakeLists.txt
完成品です。
cmake_minimum_required(VERSION 3.8)
project(service_sv_cl)
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(add_msg REQUIRED)
add_executable( server src/add_two_ints_server.cpp )
ament_target_dependencies( server rclcpp add_msg )
add_executable( client src/add_two_ints_client.cpp )
ament_target_dependencies( client rclcpp add_msg )
target_compile_features(server PUBLIC c_std_99 cxx_std_17) # Require C99 and C++17
install(TARGETS
server
client
DESTINATION lib/${PROJECT_NAME})
ament_package()
colcon build
$ cd ../.. (cd ~/ros2_study/service_cpp_ws)
$ colcon build --packages-select service_sv_cl
run
serverを起動しておきます。
ターミナルを立ち上げます。Ctrl-Alt-t。
$ cd ~/ros2_study/service_cpp_ws
$ . install/setup.bash
$ ros2 run service_sv_cl server
clientを起動します。
別のターミナルを立ち上げます。Ctrl-Alt-t。
$ cd ~/ros2_study/service_cpp_ws
$ . install/setup.bash
$ ros2 run service_sv_cl client 1 2
1と2の和の3が返ってきます。
広告
IT開発関連書とビジネス書が豊富な翔泳社の通販『SEshop』さくらのレンタルサーバ
ムームードメイン
Oisix(おいしっくす)
らでぃっしゅぼーや
珈琲きゃろっと
エプソムソルト