ROS2

[ROS2] Tutorial Beginner : Client libraries - Using parameter in a class(Python)

씨주 2024. 11. 8. 16:13

Using parameter in a class(Python)

Background

launch file에 parameter를 추가해주곤 해야 하는데 해당 tutorial을 통해 어떻게 parameter를 생성하고 launchfile에 세팅하는지 알아보자.

 

Tasks

Create a package

# ros2_ws/src
ros2 pkg create --build-type ament_python --license Apache-2.0 python_parameters --dependencies rclpy

--dependencies는 package.xml나 CMakeLists.txt에 dependency를 자동으로 추가해준다.

 

package.xml에 description, maintainer, license에 대한 정보는 잊지 말고 추가해주자.

<description>Python parameter tutorial</description>
<maintainer email="you@email.com">Your Name</maintainer>
<license>Apache License 2.0</license>

 

Write the Python node

# ros2_ws/src/python_parameters/python_parameters

import rclpy
import rclpy.node

class MinimalParam(rclpy.node.Node):
    def __init__(self):
        super().__init__('minimal_param_node')

        self.declare_parameter('my_parameter', 'world')

        self.timer = self.create_timer(1, self.timer_callback)

    def timer_callback(self):
        my_param = self.get_parameter('my_parameter').get_parameter_value().string_value

        self.get_logger().info('Hello %s!' % my_param)

        my_new_param = rclpy.parameter.Parameter(
            'my_parameter',
            rclpy.Parameter.Type.STRING,
            'world'
        )
        all_new_parameters = [my_new_param]
        self.set_parameters(all_new_parameters)

def main():
    rclpy.init()
    node = MinimalParam()
    rclpy.spin(node)

if __name__ == '__main__':
    main()

 

코드를 살펴보자면

my_parameter라는 이름의 parameter를 생성하고 default값은 world이다.

parameter타입은 default값으로 정해지고 해당 예시에는 string이 된다.

self.declare_parameter('my_parameter', 'world')

 

timer는 1부터 시작하여 timer_callback이 1초마다 한번 실행된다.

self.timer = self.create_timer(1, self.timer_callback)

 

timer_callback에선 my_parameter를 들고와 my_param에 저장하고

get_logger는 해당 event를 log한다.

set_parameter는 my_parameter를 default string값인 world로 세팅한다. 사용자가 parameter를 외부에서 변경하더라도 항상 원래값으로 재설정된다. 

def timer_callback(self):
    my_param = self.get_parameter('my_parameter').get_parameter_value().string_value

    self.get_logger().info('Hello %s!' % my_param)

    my_new_param = rclpy.parameter.Parameter(
        'my_parameter',
        rclpy.Parameter.Type.STRING,
        'world'
    )
    all_new_parameters = [my_new_param]
    self.set_parameters(all_new_parameters)

 

그다음 MinimalParam class의 instance가 구성되며 rclpy.spin이 데이터처리를 시작한다.

 

Add an entry point

setup.py에서 package.xml에서 변경해주었던 maintainer, description, license를 맞춰준다.

# ros2_ws/src/python_parameters/setup.py

maintainer='YourName',
maintainer_email='you@email.com',
description='Python parameter tutorial',
license='Apache License 2.0',

 

console_scriptes도 추가해준다.

entry_points={
    'console_scripts': [
        'minimal_param_node = python_parameters.python_parameters_node:main',
    ],
},

 

Build and run

rosdep을 이용해 dependency를 확인하고

rosdep install -i --from-path src --rosdistro humble -y

 

build해보자.

colcon build --packages-select python_parameters
source install/setup.bash

 

실행해보면 parameter의 default값으로 출력이 되는 것을 확인할 수 있다!

ros2 run python_parameters minimal_param_node

 

Change via the console

python_parameters를 실행하며 param list를 확인해보면 아래와 같이 출력됨을 확인할 수 있다.

ros2 param list

 

이 때 parameter를 변경해주면

ros2 param set /minimal_param_node my_parameter earth

 

Change via a launch file

parameter를 laucn file로도 설정할 수 있다.

먼저 launch directory를 만들고 python_parameters_launch.py를 만들어 아래의 코드를 넣는다.

# ros2_ws/src/python_parameters/launch/python_parameters_launch.py
from launch import LaunchDescription
from launch_ros.actions import Node

def generate_launch_description():
    return LaunchDescription([
        Node(
            package='python_parameters',
            executable='minimal_param_node',
            name='custom_minimal_param_node',
            output='screen',
            emulate_tty=True,
            parameters=[
                {'my_parameter': 'earth'}
            ]
        )
    ])

 

parameter_node가 시작될 때 my_parameter를 earth로 설정했다.

아래 2줄을 추가함으로써 output이 console에 출력되도록 할 수 있다.

output='screen',
emulate_tty=True,

 

setup.py를 아래와 같이 수정함으로써 os, glob를 import하여 모든 launch파일을 data_files에 추가한다.

import os
from glob import glob
# ...

setup(
  # ...
  data_files=[
      # ...
      (os.path.join('share', package_name), glob('launch/*launch.[pxy][yma]*')),
    ]
  )

 

build, source해서 test 해보면 parameter가 earth로 바뀐 것을 알 수 있다.

colcon build --packages-select python_parameters
source install/setup.bash

 

 

그런데 tutorial에서는 매번 'Hello earth!'로 return된다고 말하지만 출력은 그렇지 않다.

 

node 코드를 보면 callback함수에서 계속 my_parameter를 self.set_parameters가 매번 my_parameter를 설정하기 때문인 것 같다. 

그래서 해당 구문을 주석처리하고 test해봤을 때 매번 earth로 출력되는 것을 확인할 수 있었다.

# ros2_ws/src/python_parameters/python_parameters/python_parameters_node.py

class MinimalParam(rclpy.node.Node):
    def __init__(self):
        super().__init__('minimal_param_node')

        self.declare_parameter('my_parameter', 'world')

        self.timer = self.create_timer(1, self.timer_callback)
    def timer_callback(self):
            my_param = self.get_parameter('my_parameter').get_parameter_value().string_value

            self.get_logger().info('Hello %s!' % my_param)

            my_new_param = rclpy.parameter.Parameter(
                'my_parameter',
                rclpy.Parameter.Type.STRING,
                'world'
            )
            all_new_parameters = [my_new_param]
            # self.set_parameters(all_new_parameters)

 

 

 

ROS2_Humble Documentation : https://docs.ros.org/en/humble/Tutorials/Beginner-Client-Libraries.html