이 포스트는 theconstructsim.com의 ROS BASICS 를 참고하였습니다.
이번 포스트에서 다룰 내용은
- Subscriber가 뭔지 알고, 어떻게 만드는지 알기
- Custom Topic message 만들기
시뮬레이션 모델은 turtlebot3 Waffle 모델을 사용합니다.
waffle 모델을 사용하기 위해서는 환경 변수를 추가하거나, bash shell에 해당 명령을 입력하면 됩니다.
$ export TURTLEBOT3_MODEL=waffle
또는, ~/.bashrc 를 수정하여 맨 밑에 export TURTLEBOT3_MODEL=waffle 를 추가합니다.
Part 2 : Subscriber
우리는 node가 정보를 읽거나 쓸 수 있는 채널을 topic이라고 했습니다. 또한, 예제에서 publisher를 이용해 topic으로 데이터를 쓰기도 했는데, 따라서 이와 비슷하게 topic을 이용해 데이터를 읽을 수도 있습니다. 이렇게 데이터를 쓰는 node는 publisher라고 하고, 읽는 node는 subscriber라고 합니다.
예제를 하나 수행해보겠습니다. ~/catkin_ws/src/my_examples_pkg/scrpits 디렉토리에 NAME_OF_EXAMPLE_SCRIPT.py 라는 파일을 만들고, 다음과 같이 편집합니다.
#! /usr/bin/env python
import rospy
from std_msgs.msg import Int32
def callback(msg):
print msg.data
rospy.init_node('topic_subscriber')
sub = rospy.Subscriber('counter', Int32, callback)
rospy.spin()
실행 권한을 추가하고, 실행해봅니다.
$ sudo chmod +x NAME_OF_EXAMPLE_SCRIPT.py
$ rosrun my_example_pkg NAME_OF_EXAMPLE_SCRIPT.py
실행해봐도, 이전 포스트의 예제처럼 아무런 반응이 없을것입니다. topic을 확인해보기 위해 다음 명령을 실행해봅니다
$ rostopic echo /counter
그래도 아무런 반응이 없을 것인데, 왜냐하면 데이터를 받으려고 하는 node는 있는데 그 데이터를 보내주는 node가 없기 때문에 데이터가 들어올 때 까지 계속 기다리는 것입니다. 데이터를 publish 하기 위해서는 프로그램을 만들 수도 있지만, 다음 명령으로 간단하게 topic을 publish 할 수도 있습니다.
$ rostopic pub <topic_name> <message_type> <value>
그러면 이제 위 명령으로 topic을 하나 publish 해보겠습니다. rostopic echo 명령으로 topic /counter 를 확인하는 상태에서 명령을 입력하세요.
$ rostopic pub /counter std_msgs/Int32 5
실행해보면, 위와 같은 결과가 나오게 됩니다.
이제 코드를 분석해보겠습니다.
#! /usr/bin/env python
import rospy
from std_msgs.msg import Int32
def callback(msg): # Define a function called 'callback' that receives a parameter
# named 'msg'
print msg.data # Print the value 'data' inside the 'msg' parameter
rospy.init_node('topic_subscriber') # Initiate a Node called 'topic_subscriber'
sub = rospy.Subscriber('/counter', Int32, callback) # Create a Subscriber object that will listen to the /counter
# topic and will cal the 'callback' function each time it reads
# something from the topic
rospy.spin() # Create a loop that will keep the program in execution
즉, 우리는 topic /counter를 subscribe하기 위한 node를 만들었습니다. 이 node는 Int32 형식의 topic을 읽을 때마다 callback 함수를 호출하는데, publish된 topic이 없으므로 아무런 반응이 없었던 것입니다. 그리고 나중에 우리가 rostopic pub 명령으로 topic을 publish했기 때문에, 그제서야 rostopic echo 명령으로 데이터를 확인할 수 있었던 것입니다.
예제를 하나 수행해보겠습니다.
- 로봇의 odometry정보는 로봇 시뮬레이션 패키지가 발행하는 topic들 중에서 /odom 이라는 이름의 topic으로 publish됩니다. 이 /odom의 message 구조가 어떻게 생겼는지 확인하고, 이를 subscribe하고 나서 이 데이터를 출력하는 파일을 위 예제를 수정하여 만드세요. 그리고 이 파일을 실행하는 launch 파일까지 만들어 보세요.
답은 아래와 같습니다.
먼저, topic의 정보를 확인해봅니다.
$ rostopic info /odom
위 명령어로 확인해보니 nav_msgs/Odometry 타입이라고 나옵니다. 그러면 이제 rosmsg show 명령어로 메세지의 구조를 확인해봅니다.
$ rosmsg show nav_msgs/Odometry
다음과 같이 python 파일을 수정합니다.
#! /usr/bin/env python
import rospy
from nav_msgs.msg import Odometry
def callback(msg):
print msg #This will print the whole Odometry message
# print msg.header #This will print the header section of the Odometry message
# print msg.pose # #This will print the pose section of the Odometry message
rospy.init_node('topic_subscriber')
sub = rospy.Subscriber('/odom', Odometry, callback)
rospy.spin()
다음과 같이 launch 파일을 만듭니다.
<launch>
<node pkg="my_examples_pkg" type="NAME_OF_EXAMPLE_SCRIPT.py" name="topic_subscriber" output="screen" />
</launch>
실행 시, 다음과 같은 데이터를 볼 수 있습니다.
How to Prepare CMakeLists.txt and package.xml for Custom Topic Message Compilation
만약 Int32 말고 다른 자료형의 데이터를 publish하려고 하면 어떻게 해야할까요? 우리는 ROS에서 정의된 message들을 사용할 수 있습니다(rosmsg list 명령으로 현재 정의된 모든 message들을 확인할 수 있습니다.) 하지만, 지금 우리에게 필요한 자료형이 없다면 직접 만들 수도 있습니다. 새로운 message를 만들기 위해서는 다음 절차를 진행합니다.
1. 패키지 안에 'msg'라는 디렉토리 생성
2. 디렉토리에 Name_of_my_message.msg 파일 편집
3. CMakeLists.txt 파일을 수정 (패키지 안에 있는 CMakeLists.txt입니다. ~/catkin_ws/src에 있는 CMakeLists.txt가 아닙니다.)
4. package.xml 파일을 수정
5. 컴파일
이제 태어난 년도, 월, 일 나타내는 자료형을 가진 message를 만들어보겠습니다.
$ roscd my_examples_pkg
$ mkdir msg
해당 디렉토리에서 Age.msg라는 파일을 만들고, 수정합니다.
$ cd msg
$ atom Age.msg
float32 years
float32 months
float32 days
CMakeLists.txt 파일을 수정할 것인데, 그 파일 내부의 다음 함수들을 수정 할 것입니다.
- find_package()
- add_message_files()
- generate_messages()
- catkin_package()
위 파일을 처음 편집기로 열면, 해당 함수들이 주석 처리되어 있을 것인데, ctrl+f 로 함수를 찾고, 주석처리 된 것을 해제하고 아래와 같이 편집하면 됩니다.
1. find_package()
이 함수는 topics, services, actions(services와 actions는 topics와 같이 데이터를 전송하는 메시지 중 하나 입니다.) 를 컴파일하기 위해 필요한 패키지들이 있는 곳입니다. 여기 있는 패키지들은 나중에 package.xml파일을 수정할 때 build_depend라는 태그 안에도 기술해야 합니다.
find_package(catkin REQUIRED COMPONENTS
rospy
std_msgs
message_generation # Add message_generation here, after the other packages
)
2. add_message_files()
이 함수는 이 패키지에서 사용 할 message 파일이 있는 곳입니다(이 message를 사용하기 위해서는 msg 디렉토리에 있어야 합니다.) 아까 이전에 Age.msg라는 파일을 편집했으므로, 이를 추가해줍니다.
add_message_files(
FILES
Age.msg
)
3. generate_messages()
message들을 컴파일 할 때 필요한 패키지들이 있는 곳입니다. 우리가 Age.msg파일을 편집할 때 사용했던 float32는 std_msgs라는 패키지에 있으므로 이를 추가해줍니다.
generate_messages(
DEPENDENCIES
std_msgs
)
4. catkin_package()
여기에 있는 패키지들은 우리 패키지에서 뭔가를 실행할 때 필요한 패키지들이 있는 곳입니다. 여기에 있는 패키지들은 나중에 package.xml 파일을 수정할 때 exec_depend라는 태그 안에도 기술해야 합니다.
catkin_package(
CATKIN_DEPENDS rospy message_runtime # This will NOT be the only thing here
)
최종적으로, 다음과 같이 편집되어야 합니다.
cmake_minimum_required(VERSION 2.8.3)
project(topic_ex)
find_package(catkin REQUIRED COMPONENTS
std_msgs
message_generation
)
add_message_files(
FILES
Age.msg
)
generate_messages(
DEPENDENCIES
std_msgs
)
catkin_package(
CATKIN_DEPENDS rospy message_runtime
)
include_directories(
${catkin_INCLUDE_DIRS}
)
다음으로, package.xml 파일을 아래와 같이 수정합니다.
$ atom package.xml
<?xml version="1.0"?>
<package format="2">
<name>topic_ex</name>
<version>0.0.0</version>
<description>The topic_ex package</description>
<maintainer email="user@todo.todo">user</maintainer>
<license>TODO</license>
<buildtool_depend>catkin</buildtool_depend>
<build_depend>rospy</build_depend>
<build_depend>std_msgs</build_depend>
<build_depend>message_generation</build_depend>
<build_export_depend>rospy</build_export_depend>
<exec_depend>rospy</exec_depend>
<build_export_depend>std_msgs</build_export_depend>
<exec_depend>std_msgs</exec_depend>
<build_export_depend>message_runtime</build_export_depend>
<exec_depend>message_runtime</exec_depend>
<export>
</export>
</package>
다음으로, 패키지를 컴파일 합니다(이전 포스트처럼 설정을 완료했다면 cm 명령어로도 가능합니다).
$ roscd; cd ..
$ catkin_make
$ source devel/setup.bash
catkin_make 후에는 반드시 devel/setup.bash 명령을 실행해야 새로운 message 파일을 import할 수 있습니다. 컴파일이 제대로 됐는지 확인하기 위해 아래 명령어를 입력해 확인해봅니다.
$ rosmsg show Age
아까 우리가 입력한 대로 message의 구조가 나오면 잘 된것입니다.
'Study > [ROS] ROS Basic' 카테고리의 다른 글
ROS Basics(5. Action, Server and Client) (0) | 2021.08.29 |
---|---|
ROS_Basics(4. Service. Server and Client) (0) | 2020.11.03 |
ROS Basics(2. Topic, Publisher) (0) | 2020.10.31 |
ROS Basics(1) (0) | 2020.10.31 |