ROS 설치하기 몹시 초보용을 실습[바로가기]한 후 또 여기 저기 자료를 뒤적거리며 따라하기 중인데요. 이번에는 좋은 자료 하나를 소개하면서 또 그걸 따라해볼까 합니다. 물론 표윤석 박사님의 책[바로가기]에도 나와 있지만, slideshare,net에 표윤석 박사님이 자신의 교재에 있는 내용보다 더 좋은 내용(^^)으로 공개하셨더라구요. 참 대단한 오픈마이드죠... ^^ 아무튼 그 slideshare에 ROS의 메세징 방법인 topic, service에 대해 다루는 기초 자료가 있습니다.[바로가기] 오늘은 저도 이 자료를 그대로 따라하려고 합니다^^.
먼저 catkin_create_pkg
명령으로 std_msgs와 roscpp를 사용하는 oroca_ros_tutorials라는 이름의 패키지를 생성합니다. 따라한다는 것을 이미 고백했으니 팩키지 이름도 똑같이 하는 거죠^^.
저는 sublime text를 좋아하니까... subl
명령으로 일단 package.xml을 편집합니다.
이 부분도 수정하고...
더 중요한 이 부분도...
이렇게.. message_generation
과 message_runtime
을 build_depend
와 run_depend
에 각각 추가합니다. package.xml 전체는 아래와 같습니다.
<?xml version="1.0"?> <package> <name>oroca_ros_tutorials</name> <version>0.0.0</version> <description>The oroca_ros_tutorials package</description> <!-- One maintainer tag required, multiple allowed, one person per tag --> <!-- Example: --> <!-- <maintainer email="jane.doe@example.com">Jane Doe</maintainer> --> <maintainer email="pinkwink@todo.todo">pinkwink</maintainer> <!-- One license tag required, multiple allowed, one license per tag --> <!-- Commonly used license strings: --> <!-- BSD, MIT, Boost Software License, GPLv2, GPLv3, LGPLv2.1, LGPLv3 --> <license>TODO</license> <!-- Url tags are optional, but mutiple are allowed, one per tag --> <!-- Optional attribute type can be: website, bugtracker, or repository --> <!-- Example: --> <!-- <url type="website">http://wiki.ros.org/oroca_ros_tutorials</url> --> <!-- Author tags are optional, mutiple are allowed, one per tag --> <!-- Authors do not have to be maintianers, but could be --> <!-- Example: --> <!-- <author email="jane.doe@example.com">Jane Doe</author> --> <!-- The *_depend tags are used to specify dependencies --> <!-- Dependencies can be catkin packages or system dependencies --> <!-- Examples: --> <!-- Use build_depend for packages you need at compile time: --> <!-- <build_depend>message_generation</build_depend> --> <!-- Use buildtool_depend for build tool packages: --> <!-- <buildtool_depend>catkin</buildtool_depend> --> <!-- Use run_depend for packages you need at runtime: --> <!-- <run_depend>message_runtime</run_depend> --> <!-- Use test_depend for packages you need only for testing: --> <!-- <test_depend>gtest</test_depend> --> <buildtool_depend>catkin</buildtool_depend> <build_depend>roscpp</build_depend> <build_depend>std_msgs</build_depend> <build_depend>message_generation</build_depend> <run_depend>roscpp</run_depend> <run_depend>std_msgs</run_depend> <run_depend>message_runtime</run_depend> <!-- The export tag contains other, unspecified, tags --> <export> <!-- Other tools can request additional information be placed here --> </export> </package>
이제 CMakeList.txt도 수정해 주어야 합니다. 아참.. sublime text에서 CMake 파일에 문법을 강조하는 글을 올린적이 있어요.. 한번 보세요~~[바로가기] 아무튼...
역시.. find_package
부분에서 message_generation
을 추가하고..
위 코드처럼 ros_tutorial_msg_pulisher
와 subscriber
를 추가합니다...
그리고 만들어진 팩키지 폴더에서....
msg폴더를 만들어 둡니다.
이제... 토픽에서 publisher를 할 ros_tutorial_msg_publisher.cpp
를 만듭니다.
위 코드를 예제에서 사용합니다. 코드는
#include "ros/ros.h" #include "oroca_ros_tutorials/msgTutorial.h" int main(int argc, char **argv) { ros::init(argc, argv, "ros_tutorial_msg_publisher"); ros::NodeHandle nh; ros::Publisher ros_tutorial_pub = nh.advertise<oroca_ros_tutorials::msgTutorial>("ros_tutorial_msg", 100); ros::Rate loop_rate(10); int count = 0; while (ros::ok()) { oroca_ros_tutorials::msgTutorial msg; msg.data = count; ROS_INFO("send msg = %d", count); ros_tutorial_pub.publish(msg); loop_rate.sleep(); ++count; } return 0; }
입니다. 이 정도 기초적이고 작은 양의 코드는 지금 바로 설명하고 싶지만.. 현재 저는 메세지(토픽과 서비스)의 구동을 따라하기 중이라 어설프게 설명하는 것보다 그냥 넘어가죠^^. 다시 멋지게 공부할 수 있을 겁니다. 그렇게 되어야 또 다음 단계를 넘어가니까요.
이제.. publisher를 만들었으니 subscriber.cpp
를 만듭니다. ROS에서는 메세지의 한 종류인 토픽(topic)의 경우 일방적으로 말하는 publisher와 듣는 subscriber가 있는데 지금 그걸 학습중입니다.^^
코드는...
#include "ros/ros.h" #include "oroca_ros_tutorials/msgTutorial.h" void msgCallback(const oroca_ros_tutorials::msgTutorial::ConstPtr& msg) { ROS_INFO("recieve msg: %d", msg->data); } int main(int argc, char **argv) { ros::init(argc, argv, "ros_tutorial_msg_subscriber"); ros::NodeHandle nh; ros::Subscriber ros_tutorial_sub = nh.subscribe("ros_tutorial_msg", 10, msgCallback); ros::spin(); return 0; }
입니다.
이제 catkin_ws폴더에서 catkin_make
명령으로 빌드하면 됩니다.
그리고 roscore
를 실행하고 다른 터미널에서 rosrun oroca_ros_tutorials ros_tutorial_msg_publisher
라고 하면... 위 그림처럼 메세지를 찍습니다.
rostopic list
로 확인하면 ros_tutorial_msg가 있다는 것을 알 수 있죠.
토픽의 echo 옵션으로 확인할 수 있습니다.
이제 subscriber
를 실행해 보죠. 그러면 받은 메세지를 또 확인할 수 있습니다.
rqt_graph
로 현태 토픽의 상태와 노드의 상태를 확인해 볼 수 있습니다.
같이 보면, publisher가 보낸 메세지와 이를 수신하고 있는 subscriber의 메세지와 상태를 확인할 수 있네요.
이제 서비스를 실습해 보도록 하겠습니다. 일단 CMake.txt를 좀 더 수정하도록 하죠... 위 그림의 아까 코드에서...
srv_server
와 srv_client
를 추가합니다. 최종적인 CMake.txt파일은
cmake_minimum_required(VERSION 2.8.3) project(oroca_ros_tutorials) find_package(catkin REQUIRED COMPONENTS roscpp std_msgs message_generation ) add_message_files(FILES msgTutorial.msg) add_service_files(FILES srvTutorial.srv) generate_messages(DEPENDENCIES std_msgs) catkin_package( #INCLUDE_DIRS include LIBRARIES oroca_ros_tutorials CATKIN_DEPENDS roscpp std_msgs DEPENDS system_lib ) include_directories(include ${catkin_INCLUDE_DIRS}) #ros_tutorial_msg_publisher add_executable(ros_tutorial_msg_publisher src/ros_tutorial_msg_publisher.cpp) target_link_libraries(ros_tutorial_msg_publisher ${catkin_LIBRARIES}) add_dependencies(ros_tutorial_msg_publisher oroca_ros_tutorials_generate_messages_cpp) #ros_tutorial_msg_subscriber add_executable(ros_tutorial_msg_subscriber src/ros_tutorial_msg_subscriber.cpp) target_link_libraries(ros_tutorial_msg_subscriber ${catkin_LIBRARIES}) add_dependencies(ros_tutorial_msg_subscriber oroca_ros_tutorials_generate_messages_cpp) #ros_tutorial_srv_server 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) #ros_tutorial_srv_client 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)
입니다.
그리고 srv
라는 폴더안에 srvTutorial.srv
를 만들죠~
위와 같이 편집합니다. ---기호 위는 요청(request), 아래는 응답(response)입니다.
그리고 server.cpp
를 또 만들어야죠.
#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; ROS_INFO("request: x=%1d, y=%1d", (long int)req.a, (long int)req.b); ROS_INFO("sending back response: [%1d]", (long int)res.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); ROS_INFO("ready srv server!"); ros::spin(); return 0; }
이렇게 단순히 두 값을 더하는 예제이지만... srv를 작성하고...
또.. client를
#include "ros/ros.h" #include "oroca_ros_tutorials/srvTutorial.h" #include <cstdlib> 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::ServiceClient ros_tutorial_service_client = nh.serviceClient<oroca_ros_tutorials::srvTutorial>("ros_tutorial_srv"); oroca_ros_tutorials::srvTutorial srv; 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 : %1d, %1d", (long int)srv.request.a, (long int)srv.request.b); ROS_INFO("recieve srv, srv.Response.result : %1d", (long int)srv.response.result); } else { ROS_ERROR("Failed to call service ros_tutorial_srv"); return 1; } return 0; }
이제...
다시 빌드하고~~~
oroca_tutorials
팩키지안에 ros_tutorial_srv_server
를 실행한 다음... ros_tutorial_srv_client
를 2, 3으로 옵션을 줘서 실행하면.. 더한 5라는 값을 얻을 수 있네요^^
뭐 rosservice call
로 확인 가능하구요...
rqt
를 실행해서...
service caller
를 불러서 역시 같은 방법으로 확인할 수 있습니다.^^ 기초스러운 것을 또 그대~~~~로 따라해 봤네요.. 이제 저도 뭔가 좀 ROS 공부하는 분들께 도움이 되면서 저 스스로에게도 동기를 부여할 수 있는 뭔가를 해야하는데 말이죠.ㅠㅠ. 뭐 아무튼 이렇게 기초스러운 것으로도 ROS를 하고 있다는 기쁨이 더 큽니다^^ 마지막으로...
를 추가합니다.^^
'Robot > Robot Program - ROS' 카테고리의 다른 글
유니티(Unity) UI의 Toggle Button과 아두이노의 Push Button 연동하기 (4) | 2016.06.22 |
---|---|
ROS의 RViz로 세계적인 수술용 로봇 daVinci 다빈치를 만나보자 (2) | 2016.06.21 |
ROS 3D 시각화 툴 RViz 쉽게 쉽게 처음 시작해보기 (17) | 2016.06.16 |
유니티에서 ARDUnity를 이용하여 아두이노에 연결된 서보모터 움직여 보기 (2) | 2016.06.14 |
ROS 팩키지 만들기 따라하기 (4) | 2016.06.08 |
아두이노 푸시버튼으로 아두니티(ARDUnity)를 이용해서 유니티에서 폭파 효과 주기 (14) | 2016.06.03 |
Robot Operating System을 처음 접근하려는 분들께 추천할 책 - ROS 로봇 프로그래밍 - 표윤석 지음 (6) | 2016.06.01 |