ActionClient와 두 단계

목표는 한 번 보냈는데, 왜 기다릴 것은 두 번일까?

만들기

타입과 이름을 서버와 맞춥니다

ActionClient에는 붙을 노드, 액션 타입, 액션 이름 세 가지를 넘깁니다. 타입과 이름이 6편 서버와 같아야 서로 이어집니다.

공식 튜토리얼의 FibonacciActionClient 노드(이름 fibonacci_action_client)를 따라갑니다.

보내기

보내면 바로 돌아옵니다

wait_for_server()로 서버를 기다린 뒤 send_goal_async()로 목표를 보냅니다. 피드백을 받을 콜백도 feedback_callback=으로 함께 넘깁니다. 이 함수는 Future를 바로 돌려주니(7강 7편), 답이 오면 부를 콜백을 걸어 둡니다.

공식 예제를 화면 폭에 맞게 줄였습니다. 예제는 Future를 self._send_goal_future에 둡니다.

두 단계

Future가 두 번 옵니다

첫째 Future는 서버가 목표를 받아들였는지 알려 주며 목표 핸들을 담아 옵니다. 수락되었으면 그 핸들로 get_result_async()를 불러 둘째 Future를 받고, 거기에 결과가 담겨 옵니다.

첫째 Future가 끝났다고 일이 끝난 것이 아닙니다. 수락만 된 것입니다.

① 수락 확인

거절됐으면 여기서 끝

첫째 Future가 끝나면 이 콜백이 불립니다. future.result()가 목표 핸들이고, accepted가 거짓이면 서버가 거절한 것이라 결과도 오지 않습니다. 수락됐으면 둘째 Future에 다음 콜백을 겁니다.

공식 예제는 이때 'Goal rejected :(' 또는 'Goal accepted :)' 로그를 찍습니다.

② 결과와 피드백

결과는 한 겹 더 꺼냅니다

future.result()에는 결과와 끝난 상태(status)가 함께 들어 있어서, 결과 메시지는 .result로 한 번 더 꺼냅니다. 피드백은 3장 코드에서 feedback_callback=으로 넘긴 이 콜백으로 받습니다.

누가 부르나

spin이 콜백을 차례로 부릅니다

main은 목표를 보낸 뒤 rclpy.spin()에 들어갑니다. 응답, 피드백, 결과가 도착할 때마다 spin이 맞는 콜백을 꺼내 부릅니다(6강 3편). 결과 콜백이 rclpy.shutdown()을 부르면 spin이 끝납니다.

6편 서버를 띄운 채 python3 fibonacci_action_client.py로 실행합니다. 콜백 안에서 Future를 기다리며 멈추면 안 됩니다(7강 7편).

다음 편

토픽, 서비스, 액션 가운데 무엇을 고를까요?

8편토픽·서비스·액션 고르기 9강 목록