콜백을 부르는 반복문

rclpy.spin(node)에서 프로그램은 왜 끝나지 않을까?

콜백

내가 아니라 ROS가 부르는 함수

콜백(callback)은 "이런 일이 생기면 이 함수를 불러 달라"고 미리 맡겨 둔 함수입니다. 그래서 self.timer_callback처럼 괄호 없이 함수 자체를 넘깁니다. 언제 불릴지는 내 코드가 정하지 않습니다.

spin

spin은 콜백을 꺼내 부르는 반복문

rclpy.spin(node)는 반복문입니다. 타이머 시각이 되거나 메시지가 도착하면 그 일을 하나 꺼내 맞는 콜백을 부르고, 다시 기다리기를 Ctrl+C나 rclpy.shutdown()으로 rclpy가 꺼질 때까지 되풀이합니다.

한 바퀴만 도는 것은 rclpy.spin_once(node)입니다. spin은 이것을 계속 되풀이한다고 보면 됩니다.

실행기

반복문의 주인은 실행기

콜백을 꺼내 부르는 반복문을 돌리는 것이 실행기(executor)입니다. rclpy.spin(node)는 기본 실행기인 SingleThreadedExecutor에 노드를 넣고 돌리는 줄임말입니다.

코드로 쓸 때는 from rclpy.executors import SingleThreadedExecutor가 필요합니다(그림에서는 뺐습니다). 실행기는 11강 7편에서 다시 봅니다.

돌아오지 않는다

main은 spin 줄에 머뭅니다

rclpy.spin()은 Ctrl+C나 rclpy.shutdown()으로 rclpy가 꺼질 때까지 돌아오지 않습니다. 그래서 프로그램이 끝나지 않고, main은 spin 줄에 머문 채 콜백만 불립니다. spin 아래에 적은 줄은 반복이 끝나야 실행됩니다.

Ctrl+C를 누르면 Traceback과 KeyboardInterrupt가 찍힙니다. 고장이 아니라 Ctrl+C로 멈췄다는 표시입니다. 이때는 예외로 빠져나가 아래 두 줄은 건너뜁니다.

한 번에 하나

콜백은 하나씩 차례로 불립니다

기본 실행기는 스레드 하나로 콜백을 하나씩 부릅니다. 한 콜백이 오래 걸리면 그동안 도착한 메시지는 기다려야 합니다. 그래서 콜백 안에서는 time.sleep()이나 오래 걸리는 계산을 피합니다.

여러 콜백을 함께 돌리는 방법은 11강 8편에서 맛봅니다.

앞으로

7강, 9강도 이 고리 위에서

서비스의 응답(7강)과 액션의 결과(9강)도 실행기가 꺼내 콜백을 부르는 일입니다. spin이 돌지 않으면 답이 도착해도 받아 줄 쪽이 없습니다. 이 그림을 기억해 두세요.

7강의 spin_until_future_complete는 답이 올 때까지만 도는 spin입니다.

다음 편

"0.5초마다"라는 일은 실행기에 어떻게 맡길까요?

4편일정하게 일하기 6강 목록