본문 바로가기
IT 프로그래밍 관련/ROS

ROS 패키지 생성하기(ServiceServer, ServiceClient, Service사용)

by 지나는행인 2021. 6. 9.
728x90

이번에는 Service 메세지를 이용하여 패키지를 만들어 본다.

 

노드로는 Service Server, Service Client 의 구성이 된다.

 

먼저 무조건 선행되어야할 ... 워크스페이스(catkin_ws)의 src로 이동한다. ( 패키지 생성 디렉토리 )

 

그 다음으로는 패키지 생성 명령어를 입력한다.

 

$ catkin_create_pkg [패키지이름] [의존성패키지1 의존성패키지2 .....]

 

* yh_tuto_service 패키지 생성

이번에도 메세지 파일을 내가 만들어 쓸 것 이기 때문에 message_generation 을 추가하였다.

 

src  하위로 yh_tuto_service 디렉토리가 생성되고 ,

 

하위로 package.xml , CMakeLists.txt 파일,

 

include, src 디렉토리가 생성된다.

 

패키지 디렉토리로 이동하여 작업하자!!!

 

먼저 안해도 상관은 없으나 ,  전에 했던대로 , package.xml 파일을 수정해본다. ( 패키지 정보 파일 )

 

$ gedit package.xml

 

실행 . 에디트가 열리면 내 정보로 수정해준다.

 

* 아래 depend 부분은 내가 쓴 의존성 패키지 관련 확인만한다.

 

다음으로 ,  메시지 디렉토리를 생성해주자.

 

이전에는 topic 메시지를 사용하여서 디렉토리이름을 msg 라고 하였으나 ,

 

이번에는 service 메시지를 사용할 것 이기 때문에 srv 로 한다.

 

디렉토리를 만들고 , 디렉토리로 이동 후 에

 

메시지 파일을 만들어줘야 한다. 메시지 파일까지 만들어 본다. 

 

$ mkdir srv
$ cd srv
$ gedit [서비스파일이름.srv]

** 서비스 파일이름은 yh_srv.srv 로 하였다.

 

서비스파일 에디터에는 topic 때와 다르게 ,  request 부분과 response 부분을 나누어 작업하는데

 

이는 --- 로 나타낸다.

 

작성 방법은 마찬가지로

 

데이터타입   변수명         으로 작성한다.

 

* yh_srv.srv 에디터 화면

 

일단 예제로 간단하게 만들었다.   숫자  두개를 받아서 결과를 숫자로 응답한다는 것이다.

 

그 다음으로 노드를 생성한다.

 

노드는 패키지명디렉토리의 src 디렉토리 하위에 작업한다.  이동해준다.

 

그리고 노드를 두개 ( service server, service client )를 만들어 줘야하는데,

 

먼저 service server 노드를 만들어 주겠다.

 

순서는 아래와 같다.

 

$ cd src
$ gedit [노드이름.cpp]

*** srv_server.cpp 로 만들었다.

 

에디터파일은 아래와 같이 작성한다. 아래는 예제로

 

숫자 두개를 받아 덧셈을 하는 서비스 서버이다.

 

코드예제 ( srv_server.cpp )

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include "ros/ros.h"
#include "yh_tuto_service/yh_srv.h"    //서비스를 사용하니까 서비스 파일.h
 
 
bool calculation(yh_tuto_service::yh_srv::Request &req, yh_tuto_service::yh_srv::Response &res) //req, 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;    // bool형이기때문에 return이 true
}                 // 함수 만들기
 
 
//main 문 만들기
 
int main(int argc, char **argv)
{
    ros::init(argc, argv, "srv_server");  // 초기화
    ros::NodeHandle nh;  // 노드핸들 선언
 
    ros::ServiceServer server = nh.advertiseService("hamburger", calculation);
 
    ROS_INFO("ready srv server!!");
 
    ros::spin();   //요청이 올때까지 기다린다.spin 
 
    return 0;
}
cs

 

 

여기에는 서비스파일 헤더가 들어간다. ( 메시지 파일 )

 

hamburger는 서비스 이름..

 

이렇게 서버를 만들고 , 다음으로 클라이언트 노드를 만든다.

 

클라이언트 노드에서는 메시지파일에 있는 것처럼 , 서버로 숫자 2개를 보내 요청하고 , 응답을 기다린다.

 

 

 

코드예제 ( srv_client.cpp )

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#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_client");
    
    if(argc !=3)   // 요청시 노드이름 , 숫자1 , 숫자2로 요청하기때문에 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;
 
}
 
cs


 

이렇게 까지 하면 노드는 완성 되었다.

 

클라이언트 노드는 메시지 파일 대로 숫자 2개를 요청하고  , 응답받는다.

 

이제 패키지의 CMakeLists.txt 파일을 수정한다.

 

수정은 이전 패키지 때와 같으니 아래를 참고한다.

 

아래를 볼때 수정된 내용, 주석이 풀린내용,   노드 이름등의 확인!!!이 중요하다.

 

 

##############

  Install

##############

 

부분은 건드릴게 없다.

 

이제 끝이다 . 패키지 디렉토리에서 catkin_make 실행해서 빌드시키자!!

 

후에 빌드된 내용을 source devel/setup.bash 명령어로 등록시켜주고,

 

rospack profile  을 실행한다.

 

 

여기까지 다 됐으면, 이제 만든 서비스를 실행시켜본다.

 

먼저 하나의 터미널에서 roscore를 실행시키고 ,

 

다른 하나의 터미널로 서버노드를 실행시킨다.

 

마지막 다른 터미널로 클라이언트 노드를 실행시키는데 , 이때 작성한 코드에 맞게 숫자 두개를 함께 입력해줘야한다.

 

그러면 숫자가 코드에 맞게 덧셈이 되어 나올것이다.

 

확인해보자.

 

실행 명령어도 같이 확인!

 

* ros 실행화면

 

완성!!!

 

서비스 메시지는 클라이언트가 요청하고 응답을 받으면 클라이언트는 연결이 해제 된다!!!!!

댓글