상세 컨텐츠

본문 제목

[ROS]Service 통신 실습

coding/ROS

by golduny_zoo 2021. 6. 9. 12:13

본문

728x90

2021.06.07 - [분류 전체보기] - [ROS] Service, Service server, Service client

 

[ROS] Service, Service server, Service client

Service 요청 / 응답은 한 쌍의 메시지로 정의되는 서비스 를 통해 수행됩니다 . 하나는 요청 용이고 다른 하나는 응답 용입니다. 제공하는 ROS 노드 는 문자열 이름 으로 서비스를 제공 하

golduny.tistory.com

Service 통신 실습 

토픽으로 먼저 진행을 하니 이해하기 조금 더 쉬워졌다.

 

과정 

1. 패키지 만들기

2. 메세지 형식 만들기

3. 노드 만들기 (server, client)

4. CMakeLists.txt 수정

5. catkin make

6. 실행 

 

 

1. 패키지 만들기

$ cd catkin_ws/src
$ catkin_create_pkg yh_tuto_service message_generation std_msgs roscpp

2. 메세지 형식 만들기

$ mkdir srv 
$ cd srv
$ gedit {메세지 이름}.srv

Int64 a // server 용 
Int64 b
---
Int64 result //client 용

3. 노드 만들기 (server, client)

server

$ cd ../src/
$ gedit {서버노드이름}.cpp
#include "ros/ros.h"
#include "yh_tuto_service/yh_srv.h"


bool calculation(yh_tuto_service::yh_srv::Request &req, yh_tuto_service::yh_srv::Response &res)
{
	res.result = req.a + req.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);
	return true;
}

int main(int argc, char **argv)
{

	ros::init(argc, argv, "srv_server");
	ros::NodeHandle nh;

	ros::ServiceServer server = nh.advertiseService("hamburger", calculation);//hamburger는 서비스 명
	
	ROS_INFO("ready srv server!!");
	ros::spin();
	return 0;

}

client

$ gedit {클라이언트노드이름}.cpp
#include "ros/ros.h"
#include "yh_tuto_service/yh_srv.h"
#include <cstdlib> //atoll 이라는 함수를 쓰기 위해 

int main(int argc, char **argv)
{
	ros::init(argc, argv, "srv_server"); 
	if(argc != 3)//입력값이 3개가 들어오지 않을때 
	{
		ROS_INFO("cmd : rosrun yh_tuto_service srv_client arg0 arg1");
		ROS_INFO("arg0 : double number, arg1 : double number");
		return 1;
	}
	ros::NodeHandle nh;
	
	ros::ServiceClient client = nh.serviceClient<yh_tuto_service::yh_srv>("hamburger");

	yh_tuto_service::yh_srv srv;
	
	srv.request.a = atoll(argv[1]); //atoll 입력값을 분리해서 넣는 함수 
	srv.request.b = atoll(argv[2]);

	if(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("receive srv, srv.Response.result : %ld", (long int)srv.response.result);
	}
	else
	{
		ROS_ERROR("failed to call service");
		return 1;
	}
	return 0;
}

4. CMakeLists.txt 수정

$ cd .. 
$ gedit CMakeLists.txt 
cmake_minimum_required(VERSION 3.0.2)
project(yh_tuto_service)

## Find catkin macros and libraries
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
## is used, also find other catkin packages
find_package(catkin REQUIRED COMPONENTS
  message_generation
  roscpp
  std_msgs
)


## Generate services in the 'srv' folder
 add_service_files(
   FILES
   yh_srv.srv
 )


## Generate added messages and services with any dependencies listed here
 generate_messages(
   DEPENDENCIES
   std_msgs
 )

catkin_package(
#  INCLUDE_DIRS include
  LIBRARIES yh_tuto_service
  CATKIN_DEPENDS roscpp std_msgs
#  DEPENDS system_lib
)


include_directories(
# include
  ${catkin_INCLUDE_DIRS}
)

## Declare a C++ executable
## With catkin_make all packages are built within a single CMake context
## The recommended prefix ensures that target names across packages don't collide
 add_executable(srv_server src/srv_server.cpp)
 add_executable(srv_client src/srv_client.cpp)

## Add cmake target dependencies of the executable
## same as for the library above
 add_dependencies(srv_server ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
 add_dependencies(srv_client ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
## Specify libraries to link a library or executable target against
 target_link_libraries(srv_server
   ${catkin_LIBRARIES}
 )
 target_link_libraries(srv_client
   ${catkin_LIBRARIES}
 )

5. catkin make

$ cd catkin_ws && catkin make

6. 실행

$ roscore 
$ rosrun {패키지명} {서버노드명}
$ rosrun {패키지명} {클라이언트노드명}

잘 들어왔고!

하지만 ?!

에러가 뜨면서

서버가 닫히는 현상이 발생 문제를 확인해보니 

클라이언트노드에서 초기화 명이 server노드의 초기화 명이랑 같아서 에러 발생

초기명을 변경해주고, 다시 catkin make 해주면 

#include "ros/ros.h"
#include "yh_tuto_service/yh_srv.h"
#include <cstdlib> //atoll 이라는 함수를 쓰기 위해 

int main(int argc, char **argv)
{
	ros::init(argc, argv, "srv_server"-->”srv_client”); //server노드와 초기화 이름이 같아 에러 발생
	if(argc != 3)//입력값이 3개가 들어오지 않을때 
	{
		ROS_INFO("cmd : rosrun yh_tuto_service srv_client arg0 arg1");
		ROS_INFO("arg0 : double number, arg1 : double number");
		return 1;
	}
	ros::NodeHandle nh;
	
	ros::ServiceClient client = nh.serviceClient<yh_tuto_service::yh_srv>("hamburger");

	yh_tuto_service::yh_srv srv;
	
	srv.request.a = atoll(argv[1]); //atoll 입력값을 분리해서 넣는 함수 
	srv.request.b = atoll(argv[2]);

	if(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("receive srv, srv.Response.result : %ld", (long int)srv.response.result);
	}
	else
	{
		ROS_ERROR("failed to call service");
		return 1;
	}
	return 0;
}

성공할 수 있었다.

'coding > ROS' 카테고리의 다른 글

[ROS]Topic 통신 실습  (0) 2021.06.08
[ROS]Package 생성  (0) 2021.06.08
[ROS] ROS 용어 정리  (0) 2021.06.07
[ROS] Action, Action server, Action client  (0) 2021.06.07
[ROS] Service, Service server, Service client  (0) 2021.06.07

관련글 더보기