2021.06.07 - [분류 전체보기] - [ROS] Service, Service server, Service client
토픽으로 먼저 진행을 하니 이해하기 조금 더 쉬워졌다.
1. 패키지 만들기
2. 메세지 형식 만들기
3. 노드 만들기 (server, client)
4. CMakeLists.txt 수정
5. catkin make
6. 실행
$ cd catkin_ws/src
$ catkin_create_pkg yh_tuto_service message_generation std_msgs roscpp
$ mkdir srv
$ cd srv
$ gedit {메세지 이름}.srv
Int64 a // server 용
Int64 b
---
Int64 result //client 용
$ 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;
}
$ 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;
}
$ 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}
)
$ cd catkin_ws && catkin make
$ 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;
}
성공할 수 있었다.
[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 |