🏄

ROS2: 別のpythonファイルからインポートしてノードをつくる手順

2022/10/20に公開

海洋ロボコンをやってた人です。
今回は、pythonでROS2ノードをつくるときに、別のPythonファイルからクラスや関数をインポートするときの記述方法について知見をまとめておきます。

経緯としては、pythonで書かれたROS2プログラムに、別のpythonファイルの関数を読み込む方法が記事にまとまっておらず、わからないという意見を頂いたためです。

なお、本記事はROS2でpythonを使ったプログラムを書く必要性がある方を対象としており、C++でのプログラムで良い場合は依存関係の観点からも、C++での記述が良いと思います。

この記事が皆様のお力添えになれば幸いです。


※2023/02/26追記: 本記事の「ROS2」表記、正しくは「ROS 2」です。

別のpythonファイルからインポートしてROS2ノードをつくる

今回は、以下のようなpython-ROS2パッケージを想定しており、robot_controlパッケージのrobot_control/control_modules/flapping_driver.pyrobot_control/wing_motion_node.pyにインポートする方法を参考例として紹介していきます。

robot_control/
  ├ package.xml
  ├ setup.cfg
  ├ setup.py
  ├ test/
  ├ launch/
  ├ resource/
  ├ robot_control/
      ├ __init__.py
      ├ wing_motion_node.py
      ├ control_modules/
          ├ __init__.py
	  ├ flapping_driver.py

そのため、インポートしたい外部のpythonファイルは任意のフォルダ下に配置してください。
*ここでは"robot_control/control_modules/フォルダのこと

外部pythonファイルのクラス化とROS側でのインポート記述

まずは、python-ROS2プログラムにインポートしたい外部のpythonファイルでクラスを定義していきます。

flapping_driver.py
import math


class Flapping(object):
    def __init__(
        self, period=None, down_freq=None, \
    ):
        self.period = period

    def create_flapping_angle():

上記では、Flappingというクラスを定義しました。


続いて、ROS2側のpythonプログラムで外部のpythonプログラムをインポートしていきます。

wing_motion_node.py
import rclpy
from rclpy.node import Node

from sensor_msgs.msg import Joy
from sensor_msgs.msg import JointState

from .control_modules.flapping_driver import *
import time
import math

class WingMotionParam():
    def __init__(self):    

        # Create the motion of the flapping wing
        flapping = Flapping(period=2.5, down_freq=0.43) 

python-ROS2側では、

  • from .control_modules.flapping_driver import *

と記述することで、control_modules下のflapping_driverのクラスや関数をインポートすることができます。

なお、ここでは"import *"という表記ですが、クラスが単一の場合は"import Flapping"という表記でも問題ありません。

setup.pyにsubmodulesとしてパッケージを追加する

外部のpythonファイルのインポート記述ができたら、setup.pyにsubmodulesとしてパッケージの依存関係を追加します。

ros2_pkg_createでパッケージを作るとpackage_nameという宣言があるので、その下にsubmodulesという形で外部のpythonファイルディレクトリを宣言します。

その後、setup部分でpackagesのリスト部分に"submodules"を追加すれば完了です。

ここの情報がかなり乏しいようですね。

setup.py
from setuptools import setup
from glob import glob

import os

package_name = 'robot_control'
+ submodules = 'robot_control/control_modules'

setup(
    name=package_name,
    version='0.0.0',
+    packages=[package_name, submodules],
    data_files=[
        ('share/ament_index/resource_index/packages',
            ['resource/' + package_name]),
        ('share/' + package_name, ['package.xml']),
        (os.path.join('share',package_name), glob('launch/*.py'))
    ],
    install_requires=['setuptools'],
    zip_safe=True,
    maintainer='',
    maintainer_email='',
    description='',
    license='',
    tests_require=['pytest'],
    entry_points={
        'console_scripts': [

        ],
    },
)

これで、別のpythonファイルから、プログラムをインポートして使えるようになるはずです。

この記事が少しでも、皆様のお役に立てば幸いです。
また、"いいね"をいただけますと、非常にモチベーションに繋がります(´・ω・`)
以上。

Discussion