다시 한번 C++ 패키지로 서비스를 만들어보자.
참고한 링크는 다음과 같다.
https://cafe.naver.com/openrt/3044
이것 역시 저번에 생성한 oroca_ros_tutorials 패키지를 그대로 사용하도록 하자. 다만 CMakeLists.txt 파일은 수정해야한다.
oroca_ros_tutorials 패키지 내부에 srv 폴더를 만들고, 그 안에 srvTutorial.srv 라는 파일을 만들어주자. 내부 내용은 다음과 같다.
int64 a
int64 b
---
int64 result
다음 내용을 추가해주자.
add_executable(ros_tutorial_srv_server src/ros_tutorial_srv_server.cpp)
target_link_libraries(ros_tutorial_srv_server ${catkin_LIBRARIES})
add_dependencies(ros_tutorial_srv_server oroca_ros_tutorials_generate_messages_cpp)
add_executable(ros_tutorial_srv_client src/ros_tutorial_srv_client.cpp)
target_link_libraries(ros_tutorial_srv_client ${catkin_LIBRARIES})
add_dependencies(ros_tutorial_srv_client oroca_ros_tutorials_generate_messages_cpp)
add_service_files(
FILES
srvTutorial.srv
)
#include "ros/ros.h"
#include "oroca_ros_tutorials/srvTutorial.h"
bool calculation(oroca_ros_tutorials::srvTutorial::Request &req,
oroca_ros_tutorials::srvTutorial::Response &res){
// 서비스 요청이 있을 경우 이 함수를 사용한다.
res.result = req.a + req.b; // 서비스 요청시 받은 a와 b값을 더해서 저장한다.
ROS_INFO("request: x=%ld, y=%ld", (long int)req.a, (long int)req.b);
ROS_INFO("sending back response: [%ld]", (long int)res.result);
// 서비스 요청에 사용된 a와 b값의 표시 및 서비스 응답에 해당하는 result 값 출력
return true;
}
int main(int argc, char **argv){
ros::init(argc, argv, "ros_tutorial_srv_server");
ros::NodeHandle nh;
ros::ServiceServer ros_tutorial_service_server = nh.advertiseService("ros_tutorial_srv", calculation);
// 서비스 서버를 선언하고, 패키지 내부의 srv 파일을 이용한
// 서비스 서버 ros_tutorial_srv_server를 선언한다.
// 서비스명은 ros_tutorial_srv이며, 서비스 요청이 있을 경우 calculation이라는 함수를 실행한다.
ROS_INFO("ready srv server!");
ros::spin();
}
ros_tutorials_srv_client.cpp라는 이름으로 작성한다.
#include "ros/ros.h" // ROS 기본 헤더파일
#include "oroca_ros_tutorials/srvTutorial.h" // srvTutorial 서비스 파일 헤더 (빌드후 자동 생성됨)
#include <cstdlib> // atoll 함수 사용을 위한 라이브러리
int main(int argc, char **argv) // 노드 메인 함수
{
ros::init(argc, argv, "ros_tutorial_srv_client"); // 노드명 초기화
if (argc != 3) // 입력값 오류 처리
{
ROS_INFO("cmd : rosrun ros_tutorial ros_tutorial_service_client arg0 arg1");
ROS_INFO("arg0: double number, arg1: double number");
return 1;
}
ros::NodeHandle nh; // ROS 시스템과 통신을 위한 노드 핸들 선언
// 서비스 클라이언트 선언, oroca_ros_tutorials 패키지의 srvTutorial 서비스 파일을 이용한
// 서비스 클라이언트 ros_tutorial_service_client 를 작성한다. 서비스명은 "ros_tutorial_srv" 이다
ros::ServiceClient ros_tutorial_service_client = nh.serviceClient<oroca_ros_tutorials::srvTutorial>("ros_tutorial_srv");
// srv 라는 이름으로 srvTutorial 서비스 파일을 이용하는 서비스 파일을 선언한다
oroca_ros_tutorials::srvTutorial srv;
// 서비스 요청 값으로 노드가 실행될 때 입력으로 사용된 매개변수를 각각의 a, b에 저장한다
srv.request.a = atoll(argv[1]);
srv.request.b = atoll(argv[2]);
// 서비스를 요청하고, 요청이 받아들여 졌을 경우, 응답값을 표시한다
if (ros_tutorial_service_client.call(srv))
{
ROS_INFO("send srv, srv.Request.a and b: %ld, %ld", (long int)srv.request.a, (long int)srv.request.b);
ROS_INFO("recieve srv, srv.Response.result: %ld", (long int)srv.response.result);
}
else
{
ROS_ERROR("Failed to call service ros_tutorial_srv");
return 1;
}
return 0;
}
이후에 빌드한 후, 실행하는 것은 이전 포스팅과 동일하다.