SlideShare a Scribd company logo
2
7
@atsukiyokota
@AtsukiYokota
• R 2 O
7
• R
• R
S S
• 2 1 1
• 3
• 2
• 4 7
• 25
2
1
• RT PIO
RI 2 T A O SI
• t mo i mn m
• c t n eA c p
• S O T PTC 1
I
m
p ct
l
6 2
5 5 11 2
26 5
fm
R
r
g OSa nP
l m
• m w r 2 A c
C R
• :i i B t
• Op ro f i e
K
OR S
A
PP I
2 2
y
SR a
5 I f cn A
•
• ::
• :
• C
•
• . . . .
• 2 2
• 2 2
•
• 3 3
• + #-
.
.
2
3 2
• 3 ) Ot h r c
$ ros2 pkg create –build-type ament_python YOUR_AWESOME_PACKAGE
u lnkc / 2 ) / g ws_rt c
• 2 ) .32uo_ k c nkkx t mP u
• r a u
• ( yu .32 t r / le snk
(SRt cs s s .32 rgp (
from setuptools import setup
package_name = 'examples_rclpy_topics'
setup(
name=package_name, # パッケージ名
version='0.6.3', # バージョン番号
packages=[package_name], # ソースコードのディレクトリ
data_files=[ # ソースコード以外のファイル
('share/ament_index/resource_index/packages', ['resource/’ +
package_name]),
('share/' + package_name, ['package.xml']),
],
install_requires=['setuptools'], # 依存Python3モジュール
zip_safe=True,
author='Mikael Arguedas',
author_email='mikael@osrfoundation.org',
maintainer='Atsuki Yokota',
maintainer_email='atsuki.yokota@gmail.com',
keywords=['ROS'],
classifiers=[ # PyPIの分類情報
'Intended Audience :: Developers',
'License :: OSI Approved :: Apache Software License',
'Programming Language :: Python',
'Topic :: Software Development',
],
description='Examples of publishers/subscribers using rclpy.',
license='Apache License, Version 2.0',
tests_require=['pytest'], # テストフレームワーク名
entry_points={ # 実行コマンド名とその呼び出し先
'console_scripts': [
'publisher = ' + package_name + '.publisher:main',
'subscriber = ' + package_name + '.subscriber:main',
],
},
)
; =fR
• 2 2 m si a 2 . S _
R S Rc a
• 2 S d_ . . o ld O
• . 3 2 P b a R3 3 prl ba
$ ros2 run examples_rclpy_topics publisher
• O
• c e u“ fys m =;2 c _b a
• c ; p s e “ lays m ai t m _a
=;2 c . . / . ; ; 2 S
• ha ys fr mP S ai
1 ld
,
• h . 2 v x i , egkm 2h
O rs PChy o n o
• _h . ,. , e h x O rs a oLR y h
o n v xo n e MSe
find_package(std_msgs REQUIRED)
find_package(action_msgs REQUIRED)
find_package(rosidl_default_generators REQUIRED)
rosidl_generate_interfaces(${PROJECT_NAME}
"srv/SetMessage.srv"
"action/Fibonacci.action"
DEPENDENCIES std_msgs action_msgs
)
ament_export_dependencies(rosidl_default_runtime)
ament_package()
,
3
import rclpy
from rclpy.node import Node
from std_msgs.msg import String
class MinimalPublisher(Node):
def __init__(self):
super().__init__('minimal_publisher')
self.publisher = self.create_publisher(String, 'chatter')
self.timer = self.create_timer(0.5, self.timer_callback)
def timer_callback(self):
msg = String()
msg.data = 'Hello World!'
self.publisher.publish(msg)
self.get_logger().info(msg.data)
_e
.
c
. dea
R . .
R N
. R
.
R _e
R
def main(args=None):
rclpy.init(args=args)
minimal_publisher = MinimalPublisher()
rclpy.spin(minimal_publisher)
rclpy.shutdown()
if __name__ == '__main__':
main()
. 1
.
= 2
import rclpy
from rclpy.node import Node
from std_msgs.msg import String
class MinimalSubscriber(Node):
def __init__(self):
super().__init__('minimal_subscriber')
self.subscription = self.create_subscription(
String, 'chatter', self.listener_callback)
def listener_callback(self, msg):
self.get_logger().info(msg.data)
def main(args=None):
rclpy.init(args=args)
minimal_subscriber = MinimalSubscriber()
rclpy.spin(minimal_subscriber)
rclpy.shutdown()
if __name__ == '__main__':
main()
4
from example_interfaces.srv import AddTwoInts
import rclpy
from rclpy.node import Node
class MinimalService(Node):
def __init__(self):
super().__init__('minimal_service')
self.srv = self.create_service(
AddTwoInts, 'add_two_ints', self.add_two_ints_callback)
def add_two_ints_callback(self, request, response):
response.sum = request.a + request.b
self.get_logger().info('{} + {} = {}'.format(request.a, request.b,
response.sum))
return response
H
,
1
def main(args=None):
rclpy.init(args=args)
minimal_service = MinimalService()
rclpy.spin(minimal_service)
rclpy.shutdown()
if __name__ == '__main__':
main()
from example_interfaces.srv import AddTwoInts
import rclpy
from rclpy.node import Node
class MinimalClient(Node):
def __init__(self):
super().__init__('minimal_client')
self.client = self.create_client(AddTwoInts, 'add_two_ints')
while not self.client.wait_for_service(timeout_sec=1.0):
self.get_logger().info('waiting...')
self.request = AddTwoInts.Request()
def call_async(self):
self.request.a = 1
self.request.b = 2
return self.client.call_async(self.request)
1 1
def main(args=None):
rclpy.init(args=args)
minimal_client = MinimalClient()
future = minimal_client.call_async()
rclpy.spin_until_future_complete(minimal_client, future)
if future.done() and future.result() is not None:
response = future.result()
minimal_client.get_logger().info('{} + {} = {}'.format(
minimal_client.request.a, minimal_client.request.b,
response.sum))
rclpy.shutdown()
F
F
5
import time
from example_interfaces.action import Fibonacci
import rclpy
from rclpy.action import ActionServer, CancelResponse, GoalResponse
from rclpy.callback_groups import ReentrantCallbackGroup
from rclpy.executors import MultiThreadedExecutor
from rclpy.node import Node
class MinimalActionServer(Node):
def __init__(self):
super().__init__('minimal_action_server')
self._action_server = ActionServer(
self, Fibonacci, 'fibonacci',
execute_callback=self.execute_callback,
callback_group=ReentrantCallbackGroup())
_e _
b ec
b aec
def destroy(self):
self._action_server.destroy()
super().destroy_node()
async def execute_callback(self, goal_handle):
self.get_logger().info('executing...')
msg = Fibonacci.Feedback()
msg.sequence = [0, 1]
for i in range(1, goal_handle.request.order):
if goal_handle.is_cancel_requested:
goal_handle.canceled()
self.get_logger().info('goal_canceled')
return Fibonacci.Result()
msg.sequence.append(msg.sequence[i] + msg.sequence[i-1])
self.get_logger().info('feedback:{}'.format(msg.sequence))
goal_handle.publish_feedback(msg)
time.sleep(1) # dummy job
. /
/ PdI
c
w sn i
f a h f
. i
f f
t t Oe
5 3
Pd
f f
t
f f
goal_handle.set_succeeded()
result = Fibonacci.Result()
result.sequence = msg.sequence
self.get_logger().info('result:{}'.format(result.sequence))
return result
def main(args=None):
rclpy.init(args=args)
minimal_action_server = MinimalActionServer()
executor = MultiThreadedExecutor()
rclpy.spin(minimal_action_server, executor=executor)
minimal_action_server.destroy()
rclpy.shutdown()
if __name__ == '__main__':
main()
E
E
from action_msgs.msg import GoalStatus
from example_interfaces.action import Fibonacci
import rclpy
from rclpy.action import ActionClient
from rclpy.node import Node
class MinimalActionClient(Node):
def __init__(self):
super().__init__('minimal_action_client')
self._action_client = ActionClient(self, Fibonacci, 'fibonacci')
def goal_response_callback(self, future):
goal_handle = future.result()
if not goal_handle.accepted:
self.get_logger().info('goal rejected')
return
self._get_result_future = goal_handle.get_result_async()
self._get_result_future.add_done_callback(self.get_result_callback)
def feedback_callback(self, feedback):
self.get_logger().info('feedback:{}'.format(
feedback.feedback.sequence))
def get_result_callback(self, future):
status = future.result().action_status
if status == GoalStatus.STATUS_SUCCEEDED:
self.get_logger().info('result:{}'.format(
future.result().requence))
rclpy.shutdown()
def send_goal(self):
self.get_logger().info('waiting...')
self._action_client.wait_for_server()
goal_msg = Fibonacci.Goal()
goal_msg.order = 10
self._send_goal_future = self._action_client.send_goal_async(
goal_msg, feedback_callback=self.feedback_callback)
self._send_goal_future.add_done_callback(
self.goal_response_callback)
ca _
b
b 3
b c
b
def main(args=None):
rclpy.init(args=args)
action_client = MinimalActionClient()
action_client.send_goal()
rclpy.spin(action_client)
action_client.destroy_node()
if __name__ == '__main__':
main()
D

More Related Content

PDF
tf,tf2完全理解
PDF
NDTスキャンマッチング 第1回3D勉強会@PFN 2018年5月27日
PPTX
DockerコンテナでGitを使う
PDF
【DL輪読会】マルチエージェント強化学習における近年の 協調的方策学習アルゴリズムの発展
PDF
03 第3.6節-第3.8節 ROS2の基本機能(2/2)
PDF
LiDAR-SLAM チュートリアル資料
PDF
マルチコアを用いた画像処理
PDF
いまさら聞けないarmを使ったNEONの基礎と活用事例
tf,tf2完全理解
NDTスキャンマッチング 第1回3D勉強会@PFN 2018年5月27日
DockerコンテナでGitを使う
【DL輪読会】マルチエージェント強化学習における近年の 協調的方策学習アルゴリズムの発展
03 第3.6節-第3.8節 ROS2の基本機能(2/2)
LiDAR-SLAM チュートリアル資料
マルチコアを用いた画像処理
いまさら聞けないarmを使ったNEONの基礎と活用事例

What's hot (20)

PDF
02 第3.1節-第3.5節 ROS2の基本機能(1/2) ROS2勉強合宿 @別府温泉
PDF
大域マッチングコスト最小化とLiDAR-IMUタイトカップリングに基づく三次元地図生成
PDF
SSII2022 [TS2] 自律移動ロボットのためのロボットビジョン〜 オープンソースの自動運転ソフトAutowareを解説 〜
PDF
ROS を用いた自律移動ロボットのシステム構築
PDF
ROS2勉強会 4章前半
PDF
06 第5.1節-第5.7節 ROS2に対応したツール/パッケージ
PPTX
SLAM勉強会(3) LSD-SLAM
PPTX
畳み込みニューラルネットワークの高精度化と高速化
PDF
オープンソース SLAM の分類
PDF
工学系大学4年生のための論文の読み方
PPTX
Slurmのジョブスケジューリングと実装
PDF
Rustに触れて私のPythonはどう変わったか
PDF
Jetson活用セミナー ROS2自律走行実現に向けて
PDF
ARM CPUにおけるSIMDを用いた高速計算入門
PDF
SLAM入門 第2章 SLAMの基礎
PDF
Visual slam
PPTX
画像処理AIを用いた異常検知
PDF
semantic segmentation サーベイ
PDF
POMDP下での強化学習の基礎と応用
02 第3.1節-第3.5節 ROS2の基本機能(1/2) ROS2勉強合宿 @別府温泉
大域マッチングコスト最小化とLiDAR-IMUタイトカップリングに基づく三次元地図生成
SSII2022 [TS2] 自律移動ロボットのためのロボットビジョン〜 オープンソースの自動運転ソフトAutowareを解説 〜
ROS を用いた自律移動ロボットのシステム構築
ROS2勉強会 4章前半
06 第5.1節-第5.7節 ROS2に対応したツール/パッケージ
SLAM勉強会(3) LSD-SLAM
畳み込みニューラルネットワークの高精度化と高速化
オープンソース SLAM の分類
工学系大学4年生のための論文の読み方
Slurmのジョブスケジューリングと実装
Rustに触れて私のPythonはどう変わったか
Jetson活用セミナー ROS2自律走行実現に向けて
ARM CPUにおけるSIMDを用いた高速計算入門
SLAM入門 第2章 SLAMの基礎
Visual slam
画像処理AIを用いた異常検知
semantic segmentation サーベイ
POMDP下での強化学習の基礎と応用
Ad

Similar to ROS2勉強会@別府 第7章Pythonクライアントライブラリrclpy (11)

PDF
服务框架: Thrift & PasteScript
PDF
Python na Infraestrutura 
MySQL do Facebook

PDF
Python lecture 11
ODP
OpenStack Oslo Messaging RPC API Tutorial Demo Call, Cast and Fanout
PPTX
Python at Facebook
PDF
Everybody Polyglot! - Cross-Language RPC with Erlang
DOCX
Rpc mechanism
PDF
Open source projects with python
KEY
Polyglot parallelism
PDF
обзор Python
PDF
Python concurrency: libraries overview
服务框架: Thrift & PasteScript
Python na Infraestrutura 
MySQL do Facebook

Python lecture 11
OpenStack Oslo Messaging RPC API Tutorial Demo Call, Cast and Fanout
Python at Facebook
Everybody Polyglot! - Cross-Language RPC with Erlang
Rpc mechanism
Open source projects with python
Polyglot parallelism
обзор Python
Python concurrency: libraries overview
Ad

Recently uploaded (20)

PDF
July 2025 - Top 10 Read Articles in International Journal of Software Enginee...
PPTX
Engineering Ethics, Safety and Environment [Autosaved] (1).pptx
PDF
BMEC211 - INTRODUCTION TO MECHATRONICS-1.pdf
PPTX
Geodesy 1.pptx...............................................
PPTX
UNIT 4 Total Quality Management .pptx
PPTX
Foundation to blockchain - A guide to Blockchain Tech
PDF
Digital Logic Computer Design lecture notes
PPTX
CARTOGRAPHY AND GEOINFORMATION VISUALIZATION chapter1 NPTE (2).pptx
PPTX
Construction Project Organization Group 2.pptx
PDF
Well-logging-methods_new................
PPTX
Internet of Things (IOT) - A guide to understanding
PDF
composite construction of structures.pdf
PDF
Automation-in-Manufacturing-Chapter-Introduction.pdf
PDF
TFEC-4-2020-Design-Guide-for-Timber-Roof-Trusses.pdf
PDF
Enhancing Cyber Defense Against Zero-Day Attacks using Ensemble Neural Networks
PPTX
IOT PPTs Week 10 Lecture Material.pptx of NPTEL Smart Cities contd
DOCX
ASol_English-Language-Literature-Set-1-27-02-2023-converted.docx
PDF
Mitigating Risks through Effective Management for Enhancing Organizational Pe...
PPTX
additive manufacturing of ss316l using mig welding
PPTX
OOP with Java - Java Introduction (Basics)
July 2025 - Top 10 Read Articles in International Journal of Software Enginee...
Engineering Ethics, Safety and Environment [Autosaved] (1).pptx
BMEC211 - INTRODUCTION TO MECHATRONICS-1.pdf
Geodesy 1.pptx...............................................
UNIT 4 Total Quality Management .pptx
Foundation to blockchain - A guide to Blockchain Tech
Digital Logic Computer Design lecture notes
CARTOGRAPHY AND GEOINFORMATION VISUALIZATION chapter1 NPTE (2).pptx
Construction Project Organization Group 2.pptx
Well-logging-methods_new................
Internet of Things (IOT) - A guide to understanding
composite construction of structures.pdf
Automation-in-Manufacturing-Chapter-Introduction.pdf
TFEC-4-2020-Design-Guide-for-Timber-Roof-Trusses.pdf
Enhancing Cyber Defense Against Zero-Day Attacks using Ensemble Neural Networks
IOT PPTs Week 10 Lecture Material.pptx of NPTEL Smart Cities contd
ASol_English-Language-Literature-Set-1-27-02-2023-converted.docx
Mitigating Risks through Effective Management for Enhancing Organizational Pe...
additive manufacturing of ss316l using mig welding
OOP with Java - Java Introduction (Basics)

ROS2勉強会@別府 第7章Pythonクライアントライブラリrclpy

  • 1. 2 7
  • 3. • R 2 O 7 • R • R S S
  • 4. • 2 1 1 • 3 • 2 • 4 7 • 25
  • 5. 2 1
  • 6. • RT PIO RI 2 T A O SI • t mo i mn m • c t n eA c p • S O T PTC 1 I m p ct l 6 2 5 5 11 2 26 5 fm R r g OSa nP
  • 7. l m • m w r 2 A c C R • :i i B t • Op ro f i e K OR S A PP I 2 2 y SR a 5 I f cn A
  • 8. • • :: • : • C • • . . . . • 2 2 • 2 2 • • 3 3 • + #-
  • 10. 3 2 • 3 ) Ot h r c $ ros2 pkg create –build-type ament_python YOUR_AWESOME_PACKAGE u lnkc / 2 ) / g ws_rt c • 2 ) .32uo_ k c nkkx t mP u • r a u • ( yu .32 t r / le snk (SRt cs s s .32 rgp (
  • 11. from setuptools import setup package_name = 'examples_rclpy_topics' setup( name=package_name, # パッケージ名 version='0.6.3', # バージョン番号 packages=[package_name], # ソースコードのディレクトリ data_files=[ # ソースコード以外のファイル ('share/ament_index/resource_index/packages', ['resource/’ + package_name]), ('share/' + package_name, ['package.xml']), ], install_requires=['setuptools'], # 依存Python3モジュール zip_safe=True, author='Mikael Arguedas', author_email='mikael@osrfoundation.org', maintainer='Atsuki Yokota', maintainer_email='atsuki.yokota@gmail.com',
  • 12. keywords=['ROS'], classifiers=[ # PyPIの分類情報 'Intended Audience :: Developers', 'License :: OSI Approved :: Apache Software License', 'Programming Language :: Python', 'Topic :: Software Development', ], description='Examples of publishers/subscribers using rclpy.', license='Apache License, Version 2.0', tests_require=['pytest'], # テストフレームワーク名 entry_points={ # 実行コマンド名とその呼び出し先 'console_scripts': [ 'publisher = ' + package_name + '.publisher:main', 'subscriber = ' + package_name + '.subscriber:main', ], }, )
  • 13. ; =fR • 2 2 m si a 2 . S _ R S Rc a • 2 S d_ . . o ld O • . 3 2 P b a R3 3 prl ba $ ros2 run examples_rclpy_topics publisher • O • c e u“ fys m =;2 c _b a • c ; p s e “ lays m ai t m _a =;2 c . . / . ; ; 2 S • ha ys fr mP S ai 1 ld
  • 14. , • h . 2 v x i , egkm 2h O rs PChy o n o • _h . ,. , e h x O rs a oLR y h o n v xo n e MSe find_package(std_msgs REQUIRED) find_package(action_msgs REQUIRED) find_package(rosidl_default_generators REQUIRED) rosidl_generate_interfaces(${PROJECT_NAME} "srv/SetMessage.srv" "action/Fibonacci.action" DEPENDENCIES std_msgs action_msgs ) ament_export_dependencies(rosidl_default_runtime) ament_package() ,
  • 15. 3
  • 16. import rclpy from rclpy.node import Node from std_msgs.msg import String class MinimalPublisher(Node): def __init__(self): super().__init__('minimal_publisher') self.publisher = self.create_publisher(String, 'chatter') self.timer = self.create_timer(0.5, self.timer_callback) def timer_callback(self): msg = String() msg.data = 'Hello World!' self.publisher.publish(msg) self.get_logger().info(msg.data) _e . c . dea R . . R N . R . R _e R
  • 17. def main(args=None): rclpy.init(args=args) minimal_publisher = MinimalPublisher() rclpy.spin(minimal_publisher) rclpy.shutdown() if __name__ == '__main__': main() . 1 . = 2
  • 18. import rclpy from rclpy.node import Node from std_msgs.msg import String class MinimalSubscriber(Node): def __init__(self): super().__init__('minimal_subscriber') self.subscription = self.create_subscription( String, 'chatter', self.listener_callback) def listener_callback(self, msg): self.get_logger().info(msg.data)
  • 19. def main(args=None): rclpy.init(args=args) minimal_subscriber = MinimalSubscriber() rclpy.spin(minimal_subscriber) rclpy.shutdown() if __name__ == '__main__': main()
  • 20. 4
  • 21. from example_interfaces.srv import AddTwoInts import rclpy from rclpy.node import Node class MinimalService(Node): def __init__(self): super().__init__('minimal_service') self.srv = self.create_service( AddTwoInts, 'add_two_ints', self.add_two_ints_callback) def add_two_ints_callback(self, request, response): response.sum = request.a + request.b self.get_logger().info('{} + {} = {}'.format(request.a, request.b, response.sum)) return response H , 1
  • 22. def main(args=None): rclpy.init(args=args) minimal_service = MinimalService() rclpy.spin(minimal_service) rclpy.shutdown() if __name__ == '__main__': main()
  • 23. from example_interfaces.srv import AddTwoInts import rclpy from rclpy.node import Node class MinimalClient(Node): def __init__(self): super().__init__('minimal_client') self.client = self.create_client(AddTwoInts, 'add_two_ints') while not self.client.wait_for_service(timeout_sec=1.0): self.get_logger().info('waiting...') self.request = AddTwoInts.Request() def call_async(self): self.request.a = 1 self.request.b = 2 return self.client.call_async(self.request) 1 1
  • 24. def main(args=None): rclpy.init(args=args) minimal_client = MinimalClient() future = minimal_client.call_async() rclpy.spin_until_future_complete(minimal_client, future) if future.done() and future.result() is not None: response = future.result() minimal_client.get_logger().info('{} + {} = {}'.format( minimal_client.request.a, minimal_client.request.b, response.sum)) rclpy.shutdown() F F
  • 25. 5
  • 26. import time from example_interfaces.action import Fibonacci import rclpy from rclpy.action import ActionServer, CancelResponse, GoalResponse from rclpy.callback_groups import ReentrantCallbackGroup from rclpy.executors import MultiThreadedExecutor from rclpy.node import Node class MinimalActionServer(Node): def __init__(self): super().__init__('minimal_action_server') self._action_server = ActionServer( self, Fibonacci, 'fibonacci', execute_callback=self.execute_callback, callback_group=ReentrantCallbackGroup()) _e _ b ec b aec
  • 27. def destroy(self): self._action_server.destroy() super().destroy_node() async def execute_callback(self, goal_handle): self.get_logger().info('executing...') msg = Fibonacci.Feedback() msg.sequence = [0, 1] for i in range(1, goal_handle.request.order): if goal_handle.is_cancel_requested: goal_handle.canceled() self.get_logger().info('goal_canceled') return Fibonacci.Result() msg.sequence.append(msg.sequence[i] + msg.sequence[i-1]) self.get_logger().info('feedback:{}'.format(msg.sequence)) goal_handle.publish_feedback(msg) time.sleep(1) # dummy job . / / PdI c w sn i f a h f . i f f t t Oe 5 3 Pd f f t f f
  • 28. goal_handle.set_succeeded() result = Fibonacci.Result() result.sequence = msg.sequence self.get_logger().info('result:{}'.format(result.sequence)) return result def main(args=None): rclpy.init(args=args) minimal_action_server = MinimalActionServer() executor = MultiThreadedExecutor() rclpy.spin(minimal_action_server, executor=executor) minimal_action_server.destroy() rclpy.shutdown() if __name__ == '__main__': main() E E
  • 29. from action_msgs.msg import GoalStatus from example_interfaces.action import Fibonacci import rclpy from rclpy.action import ActionClient from rclpy.node import Node class MinimalActionClient(Node): def __init__(self): super().__init__('minimal_action_client') self._action_client = ActionClient(self, Fibonacci, 'fibonacci')
  • 30. def goal_response_callback(self, future): goal_handle = future.result() if not goal_handle.accepted: self.get_logger().info('goal rejected') return self._get_result_future = goal_handle.get_result_async() self._get_result_future.add_done_callback(self.get_result_callback) def feedback_callback(self, feedback): self.get_logger().info('feedback:{}'.format( feedback.feedback.sequence))
  • 31. def get_result_callback(self, future): status = future.result().action_status if status == GoalStatus.STATUS_SUCCEEDED: self.get_logger().info('result:{}'.format( future.result().requence)) rclpy.shutdown() def send_goal(self): self.get_logger().info('waiting...') self._action_client.wait_for_server() goal_msg = Fibonacci.Goal() goal_msg.order = 10 self._send_goal_future = self._action_client.send_goal_async( goal_msg, feedback_callback=self.feedback_callback) self._send_goal_future.add_done_callback( self.goal_response_callback) ca _ b b 3 b c b
  • 32. def main(args=None): rclpy.init(args=args) action_client = MinimalActionClient() action_client.send_goal() rclpy.spin(action_client) action_client.destroy_node() if __name__ == '__main__': main() D