action server와 client 작성하기(Python)
소개
실습
action server 작성하기
action client 작성하기
action은 ROS내의 비동기 통신
action client가 action server에게 goal request를 전송
action server는 action client에게 goal feedback과 result를 전송
준비
action_tutorials_interfaces package
Fibonacci.action interface
fibonacci_action_server.py 파일 추가하기 (위치 : ~/action_test)
import time
import rclpy
from rclpy .action import ActionServer
from rclpy .node import Node
from action_tutorials_interfaces .action import Fibonacci
class FibonacciActionServer (Node ):
def __init__ (self ):
super ().__init__ ('fibonacci_action_server' )
self ._action_server = ActionServer (
self ,
Fibonacci ,
'fibonacci' ,
self .execute_callback )
def execute_callback (self , goal_handle ):
self .get_logger ().info ('Executing goal...' )
feedback_msg = Fibonacci .Feedback ()
feedback_msg .partial_sequence = [0 , 1 ]
for i in range (1 , goal_handle .request .order ):
feedback_msg .partial_sequence .append (
feedback_msg .partial_sequence [i ] + feedback_msg .partial_sequence [i - 1 ])
self .get_logger ().info ('Feedback: {0}' .format (feedback_msg .partial_sequence ))
goal_handle .publish_feedback (feedback_msg )
time .sleep (1 )
goal_handle .succeed ()
result = Fibonacci .Result ()
result .sequence = feedback_msg .partial_sequence
return result
def main (args = None ):
rclpy .init (args = args )
fibonacci_action_server = FibonacciActionServer ()
rclpy .spin (fibonacci_action_server )
if __name__ == '__main__' :
main ()
python3 fibonacci_action_server.py
ros2 action send_goal fibonacci action_tutorials_interfaces/action/Fibonacci " {order: 5}"
action server 재시작(--feedback 옵션으로 feedback이 publish되고 있는지 확인)
ros2 action send_goal --feedback fibonacci action_tutorials_interfaces/action/Fibonacci " {order: 5}"
fibonacci_action_client.py 파일 생성 및 복사하기
import rclpy
from rclpy .action import ActionClient
from rclpy .node import Node
from action_tutorials_interfaces .action import Fibonacci
class FibonacciActionClient (Node ):
def __init__ (self ):
super ().__init__ ('fibonacci_action_client' )
self ._action_client = ActionClient (self , Fibonacci , 'fibonacci' )
def send_goal (self , order ):
goal_msg = Fibonacci .Goal ()
goal_msg .order = order
self ._action_client .wait_for_server ()
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 )
def goal_response_callback (self , future ):
goal_handle = future .result ()
if not goal_handle .accepted :
self .get_logger ().info ('Goal rejected :(' )
return
self .get_logger ().info ('Goal accepted :)' )
self ._get_result_future = goal_handle .get_result_async ()
self ._get_result_future .add_done_callback (self .get_result_callback )
def get_result_callback (self , future ):
result = future .result ().result
self .get_logger ().info ('Result: {0}' .format (result .sequence ))
rclpy .shutdown ()
def feedback_callback (self , feedback_msg ):
feedback = feedback_msg .feedback
self .get_logger ().info ('Received feedback: {0}' .format (feedback .partial_sequence ))
def main (args = None ):
rclpy .init (args = args )
action_client = FibonacciActionClient ()
action_client .send_goal (10 )
rclpy .spin (action_client )
if __name__ == '__main__' :
main ()
python3 fibonacci_action_server.py
새 터미널에서 action client 실행하기
python3 fibonacci_action_client.py
[INFO] [fibonacci_action_server]: Executing goal...
[INFO] [fibonacci_action_server]: Feedback: array('i', [0, 1, 1])
[INFO] [fibonacci_action_server]: Feedback: array('i', [0, 1, 1, 2])
[INFO] [fibonacci_action_server]: Feedback: array('i', [0, 1, 1, 2, 3])
[INFO] [fibonacci_action_server]: Feedback: array('i', [0, 1, 1, 2, 3, 5])
# etc.