간만에 ros python 패키지를 만들 일이 생겨서 그 과정을 정리하였다.

1. python 노드가 포함된 패키지를 만들고

2. 서비스를 만들고 호출하는 방법을 설명


1. 패키지 만들기

일단 workspace의 src 디렉토리로 이동한 다음 다음을 입력한다

<패키지이름>은 사용할 패키지 이름이고 Python으로 작성할 예정이므로 rospy 를 추가해준다.

$ catkin_create_pkg <패키지이름> std_msgs rospy

1-1. 노드 python 만들기

이제 ws/src/<패키지이름>/ 디렉토리로 이동하여 python 노드를 하나 추가하기 위해 디렉토리와 노드가 될 파일을 만든다.

일반적으로 /nodes 안에 "<패키지이름>_node.py" 로 작성한다.

반드시!!! .py 파일을 실행파일로 바꾸어준다.

$ cd <패키지이름>
$ mkdir nodes
$ cd nodes
$ touch <패키지이름>_node.py

1-2. setup.py 만들기

파이썬 패키지를 위해서 패키지 디렉토리에 setup.py 파일을 하나 만들고 다음을 추가한다.

"패키지 이름"만 수정하고 나머지는 그대로 둔다.

## ! DO NOT MANUALLY INVOKE THIS setup.py, USE CATKIN INSTEAD

from distutils.core import setup
from catkin_pkg.python_setup import generate_distutils_setup

# fetch values from package.xml
setup_args = generate_distutils_setup(
    packages=['패키지이름'],
    package_dir={'': 'src'}
)

setup(**setup_args)

1.3. package.xml 수정하기

패키지 디렉토리로 이동하여 package.xml 파일을 열고 필요한 부분을 수정한다.

불필요한 것들이 잔뜩 있기때문에 필요한 것만 추가하면 된다.

필요한 메세지나 패키지가 있으면 <depend> </depend> 에 넣으면 된다.

<?xml version="1.0"?>
<package format="2">
  <name>패키지이름</name>
  <version>0.0.0</version>
  <description>The 패키지 package</description>
  <maintainer email="메일@주소">관리자이름</maintainer>
  <license>TODO</license>

  <buildtool_depend>catkin</buildtool_depend>
  
  <depend>rospy</depend>
  <depend>std_msgs</depend>
  <exec_depend>message_runtime</exec_depend>
</package>

 

1.4. CmakeLists.txt 수정하기

cmakelist에는 build를 하기 위한 항목들이 있는데 역시 불필요한 것들이 잔뜩 있으므로 아래와 같이 정리한다.

중요한 부분은 다음과 같다. launch 파일이 있는 경우 해당 디렉토리를 install에 포함시킨다.

  • find_package(catkin REQUIRED COMPONENTS) : 필요한 패키지
  • catkin_package(): catkin에 필요한 패키지들 
  • catkin_install_python(PROGRAMS
      nodes/패키지이름_node.py
      DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION})
  • install(DIRECTORY launch
      DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION})
cmake_minimum_required(VERSION 3.0.2)
project(패키지이름)

## Compile as C++11, supported in ROS Kinetic and newer
add_compile_options(-std=c++11)

################################################################################
# Find catkin packages and libraries for catkin and system dependencies
################################################################################
find_package(catkin REQUIRED COMPONENTS
  rospy
  std_msgs
)

## System dependencies are found with CMake's conventions
# find_package(Boost REQUIRED COMPONENTS system)

catkin_python_setup()

################################################
## Declare ROS messages, services and actions ##
################################################

## Generate services in the 'srv' folder
# add_service_files(
#   FILES
#   Service1.srv
#   Service2.srv
# )

## Generate added messages and services with any dependencies listed here
# generate_messages(
#   DEPENDENCIES
#   nav_msgs#   std_msgs
# )

################################################
## Declare ROS dynamic reconfigure parameters ##
################################################
## Generate dynamic reconfigure parameters in the 'cfg' folder
# generate_dynamic_reconfigure_options(
#   cfg/DynReconf1.cfg
#   cfg/DynReconf2.cfg
# )

###################################
## catkin specific configuration ##
###################################
catkin_package(
  CATKIN_DEPENDS 
  rospy 
  message_runtime
  std_msgs
)

###########
## Build ##
###########

#############
## Install ##
#############
catkin_install_python(PROGRAMS
  nodes/패키지이름_node.py
  DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)

install(DIRECTORY launch
  DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}
)

1.5. 노드 파일 수정하기

이제 노드 역할을 할 파이썬 코드를 작성한다.

다음은 토픽을 읽고 다른 메세지를 publish 하는 노드 템플릿이다.

import rospy
import std_msgs.msg from String, Int32

class 패키지이름Node:
    def __init__(self):
        print('Hello package')
        rospy.Subscriber("Subscribe토픽", Int32, self.메세지콜백, queue_size=10)
        self.pub_msg = rospy.Publisher("Publish토픽", String, queue_size=10)
        rospy.Timer(rospy.Duration(0.1), self.timer_callback)
        
    def timer_callback(self, event):
    	msg = String()
        msg.data = 'Hello'
    	self.pub_msg.publish(msg);
    
    def 메세지콜백(self, msg):
    	int num = int(msg.data)
    	rospy.loginfo('new message! %d', num)
    
    def main(self):
        rospy.spin()

if __name__ == '__main__':
    rospy.init_node('패키지이름_node')
    node = 패키지이름Node()
    node.main()

2. 서비스 추가하기

srv 파일을 추가하면 특정한 작업을 수행하는 서비스를 만들 수 있다.

2.1 서비스파일 만들기

먼저 패키지 안에 srv 디렉토리를 만들고 서비스 이름.srv 파일을 만든다.

$ cd to package
$ mkdir srv
$ cd srv
$ nano 서비스이름.srv

그리고나서 다음 내용을 추가한다. 

srv 파일은 전달할 데이터와 응답 데이터가 "---" 으로 구분된 파일이다.

전달하거나 응답할 데이터가 없으면 그냥 비워두면 된다.

float 설정할변이름1
bool 설정할변수이름2
---
bool 응답할변수이름

2.2 CmakeLists.txt 수정하기

기존 CmakeLists.txt에 다음 내용이 추가되어야 한다.

## Generate added messages and services with any dependencies listed here
generate_messages(
  DEPENDENCIES
  std_msgs
)

 

2.3 터미널에서 실행하기

해당 서비스를 호출하기 위해서는 노드를 띄우고 터미널에 다음과 같이 입력한다.

$ rosservice call /서비스토픽 "{'설정할변수이름1':0.0, '설정할변수이릅2':true}"

+ Recent posts