- 1. 概要
- 2. 初期状態
- 3. 終了させる
1. 概要
「ROS2」の「Tutorials」のページのまま、サービスのパッケージを作成すると、サーバ側を終わらせる方法がわからない。
どうやって終わらせるかを、「python」のソースで、自分なりにやってみた結果です。
本ページは、下記のサイトを参考にさせていただきました。
「Writing a simple service and client (Python) 」
2. 初期状態
初期状態の、サーバ側プログラム(処理の本質的なところは省略しています、以下同文)。
from my_interface.srv import MyInstruction
import rclpy # type: ignore
from rclpy.node import Node # type: ignore
class MinimalService(Node):
def __init__(self):
super().__init__('minimal_service')
self.srv = self.create_service(MyInstruction, 'MyInstruction', self.my_callback)
def my_callback(self, request, response):
self.get_logger().info('coming code[0x%02X]' % (request.code))
・・・ 処理 ・・・
return response
def main(args=None):
rclpy.init(args=args)
minimal_service = MinimalService()
rclpy.spin(minimal_service)
rclpy.shutdown()
if __name__ == '__main__':
main()
クライアント側プログラム。
from my_interface.srv import MyInstruction
import rclpy # type: ignore
from rclpy.node import Node # type: ignore
class MinimalClientAsync(Node):
def __init__(self):
super().__init__('minimal_client_async')
self.cli = self.create_client(MyInstruction, 'MyInstruction')
while not self.cli.wait_for_service(timeout_sec=1.0):
self.get_logger().info('service not available, waiting again...')
self.req = MyInstruction.Request()
def send_request(self, code):
self.get_logger().info('send [0x%02X]' % (code))
self.req.code = code
self.future = self.cli.call_async(self.req)
rclpy.spin_until_future_complete(self, self.future)
return self.future.result()
def main(args=None):
# import pdb; pdb.set_trace()
rclpy.init(args=args)
client = MinimalClientAsync()
while True:
print("0:exit")
print("Please input: ", end='')
str = input()
if str == '0':
break
response = client.send_request(int(str))
client.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()
実際には、0 以外の入力があれば、何らかの処理を行っているわけで・・・。
クライアント側は、0 を入力すれば、終了できますが、サーバ側は、Ctrl+C で止めないと終わらないことになっております。
3. 終了させる
サーバ側。
from my_interface.srv import MyInstruction
import rclpy # type: ignore
from rclpy.node import Node # type: ignore
class MinimalService(Node):
def __init__(self):
super().__init__('minimal_service')
self.serial = serial
self.srv = self.create_service(MyInstruction, 'MyInstruction', self.my_callback)
def my_callback(self, request, response):
self.get_logger().info('coming code[0x%02X]' % (request.code))
if request.code == 0:
exit()
・・・ 処理 ・・・
return response
def main(args=None):
rclpy.init(args=args)
minimal_service = MinimalService(serial)
rclpy.spin(minimal_service)
rclpy.shutdown()
if __name__ == '__main__':
main()
17、18行で、0 がクライアント側からはいってきたら、終了するようにしています。
クライアント側。
from my_interface.srv import MyInstruction
import rclpy # type: ignore
from rclpy.node import Node # type: ignore
class MinimalClientAsync(Node):
def __init__(self):
super().__init__('minimal_client_async')
self.cli = self.create_client(MyInstruction, 'MyInstruction')
while not self.cli.wait_for_service(timeout_sec=1.0):
self.get_logger().info('service not available, waiting again...')
self.req = MyInstruction.Request()
def send_request(self, code):
self.get_logger().info('send [0x%02X]' % (code))
self.req.code = code
self.future = self.cli.call_async(self.req)
if code == 0:
rclpy.spin_until_future_complete(self, self.future, None, 0)
return
rclpy.spin_until_future_complete(self, self.future)
return self.future.result()
def main(args=None):
# import pdb; pdb.set_trace()
rclpy.init(args=args)
client = MinimalClientAsync()
while True:
print("0:exit")
print("Please input: ", end='')
str = input()
response = client.send_request(int(str))
if str == '0':
break
client.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()
22~24行を加えています。
'0' が入力されたら、サーバにリクエストを送ったうえで、タイムアウト付きの待ち処理を行います。
待ち処理がないと、送った後に止まります。
待ち処理は、当然タイムアウトしますので、終了することができます。
|