타이머 콜백

0.5초마다 일하려면 while과 sleep을 쓰면 될까?

while은 곤란

직접 돌리면 spin이 못 돕니다

main에서 while True:와 time.sleep()으로 직접 돌리면, 프로그램이 그 안에 갇혀 rclpy.spin()에 닿지 못합니다. 그러면 메시지가 와도 콜백을 불러 줄 실행기가 돌지 않습니다.

work는 예시로 붙인 메서드 이름입니다.

create_timer

주기와 콜백을 맡겨 둡니다

노드의 create_timer(주기, 콜백)은 타이머를 만들어 실행기에 맡깁니다. 주기는 초 단위입니다. 이 줄은 기다리지 않고 바로 다음 줄로 넘어가고, 콜백은 spin이 돌 때 불립니다.

만든 타이머는 self.timer처럼 노드에 붙여 둡니다. 멈추려면 self.timer.cancel()을 부릅니다.

시간 축

0.5초마다 실행기가 불러 줍니다

타이머 시각이 될 때마다 실행기가 timer_callback을 부릅니다. 콜백이 끝나면 다시 기다립니다. 첫 호출은 타이머를 만든 즉시가 아니라 한 주기가 지난 뒤입니다.

전체 코드

숫자를 세는 Counter 노드

생성자에서 카운터와 타이머를 만들고, 콜백에서 숫자를 로그로 남긴 뒤 하나 올립니다. 숫자는 self.i에 있으니 콜백이 불릴 때마다 이어서 셉니다.

맨 위 import 두 줄은 1편과 같고, main은 2편과 같되 HelloNode() 자리에 Counter()를 씁니다.

따라 하기

이번에는 계속 살아 있습니다

setup.py에 counter 명령을 더하고 빌드한 뒤 ros2 run my_package counter를 실행합니다. 0.5초마다 한 줄씩 찍힙니다. 다른 터미널의 ros2 node list에도 /counter가 계속 보입니다.

실제 출력의 시각 부분은 줄였습니다. 끝낼 때는 Ctrl+C를 누릅니다.

콜백은 짧게

콜백이 길면 박자가 밀립니다

콜백이 주기보다 오래 걸리면 다음 호출이 늦어집니다. 실행기는 콜백을 하나씩 부르니(3편), 앞 콜백이 끝나야 다음 타이머 콜백도 불립니다. 콜백 안에서는 짧은 일만 합니다.

그림의 0.8초는 예시입니다.

다음 편

세는 숫자를 로그 대신 토픽으로 보내려면?

5편말하는 노드 6강 목록