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