이번에는 Service 메세지를 이용하여 패키지를 만들어 본다.
노드로는 Service Server, Service Client 의 구성이 된다.
먼저 무조건 선행되어야할 ... 워크스페이스(catkin_ws)의 src로 이동한다. ( 패키지 생성 디렉토리 )
그 다음으로는 패키지 생성 명령어를 입력한다.
$ catkin_create_pkg [패키지이름] [의존성패키지1 의존성패키지2 .....]
이번에도 메세지 파일을 내가 만들어 쓸 것 이기 때문에 message_generation 을 추가하였다.
src 하위로 yh_tuto_service 디렉토리가 생성되고 ,
하위로 package.xml , CMakeLists.txt 파일,
include, src 디렉토리가 생성된다.
패키지 디렉토리로 이동하여 작업하자!!!
먼저 안해도 상관은 없으나 , 전에 했던대로 , package.xml 파일을 수정해본다. ( 패키지 정보 파일 )
$ gedit package.xml
실행 . 에디트가 열리면 내 정보로 수정해준다.
다음으로 , 메시지 디렉토리를 생성해주자.
이전에는 topic 메시지를 사용하여서 디렉토리이름을 msg 라고 하였으나 ,
이번에는 service 메시지를 사용할 것 이기 때문에 srv 로 한다.
디렉토리를 만들고 , 디렉토리로 이동 후 에
메시지 파일을 만들어줘야 한다. 메시지 파일까지 만들어 본다.
$ mkdir srv
$ cd srv
$ gedit [서비스파일이름.srv]
** 서비스 파일이름은 yh_srv.srv 로 하였다.
서비스파일 에디터에는 topic 때와 다르게 , request 부분과 response 부분을 나누어 작업하는데
이는 --- 로 나타낸다.
작성 방법은 마찬가지로
데이터타입 변수명 으로 작성한다.
일단 예제로 간단하게 만들었다. 숫자 두개를 받아서 결과를 숫자로 응답한다는 것이다.
그 다음으로 노드를 생성한다.
노드는 패키지명디렉토리의 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를 실행시키고 ,
다른 하나의 터미널로 서버노드를 실행시킨다.
마지막 다른 터미널로 클라이언트 노드를 실행시키는데 , 이때 작성한 코드에 맞게 숫자 두개를 함께 입력해줘야한다.
그러면 숫자가 코드에 맞게 덧셈이 되어 나올것이다.
확인해보자.
실행 명령어도 같이 확인!
완성!!!
서비스 메시지는 클라이언트가 요청하고 응답을 받으면 클라이언트는 연결이 해제 된다!!!!!
'IT 프로그래밍 관련 > ROS' 카테고리의 다른 글
ROS launch 파일 만들기 (0) | 2021.06.11 |
---|---|
ROS 분석하는 방법(자주 쓰이는 분석 명령어...) (0) | 2021.06.11 |
ROS 패키지 생성하기(Publisher, Subscriber, Topic사용) (0) | 2021.06.08 |
ROS 패키지 디렉토리 (0) | 2021.06.08 |
ROS 관련 기본 용어 (0) | 2021.06.07 |
댓글