TransformListener와 lookup_transform

turtle2는 turtle1이 '자기 기준으로' 어디 있는지 어떻게 알아낼까?

두 부품

Listener가 받아 Buffer에 쌓습니다

TransformListener는 /tf와 /tf_static을 구독해서 받은 변환을 Buffer에 넣어 둡니다. 내 코드는 토픽을 직접 듣지 않고 Buffer에 "A 기준 B는?"이라고 묻기만 합니다.

Buffer는 기본으로 최근 10초 치를 들고 있습니다(7편).

준비

Buffer와 Listener를 짝으로 만듭니다

__init__에서 Buffer()를 만들고, 그 Buffer를 채울 TransformListener(self.tf_buffer, self)를 만듭니다. 리스너는 만들어지는 순간부터 받기 시작합니다. 묻는 일은 1초마다 부르는 타이머 콜백 on_timer에서 합니다.

공식 튜토리얼 turtle_tf2_listener.py의 일부입니다.

묻기

누구 기준으로 누구를 묻나

lookup_transform의 첫 인자는 기준이 되는 프레임(target), 둘째는 알고 싶은 프레임(source)입니다. 돌려받는 변환에는 source가 target 기준으로 어디 있는지가 담깁니다. rclpy.time.Time()은 버퍼에 있는 가장 최근 값을 달라는 뜻입니다.

튜토리얼은 프레임 이름을 to_frame_rel, from_frame_rel 변수에 담아 넘깁니다.

없을 수도

변환이 없으면 예외가 납니다

노드를 막 켰을 때는 버퍼가 비어 있거나 turtle2가 아직 생기지 않았습니다. 이때 lookup_transform은 TransformException을 던집니다. 그래서 try로 감싸 로그만 남기고 돌아갑니다. 1초 뒤 타이머가 다시 물어봅니다.

쓰기

받은 값으로 속도를 만듭니다

1편에서 본 따라가기 규칙이 바로 이 몇 줄입니다. 받은 이동 값 (x, y)로 turtle1 쪽 각도만큼 돌고, 떨어진 거리에 비례해 앞으로 갑니다. 이 Twist를 turtle2/cmd_vel로 발행하면 turtle2가 따라붙습니다.

튜토리얼은 1.0과 0.5를 scale_rotation_rate, scale_forward_speed 변수에 담아 씁니다.

주의

리스너는 한 번 만들어 둡니다

Buffer와 Listener를 콜백 안에서 매번 새로 만들면, 막 만든 빈 버퍼에 묻는 셈이라 늘 실패합니다. __init__에서 한 번 만들어 노드가 사는 동안 계속 받게 둡니다.

시각을 now()로 물으면 아직 도착하지 않은 시각이라 실패하기 쉽습니다. 처음에는 Time()을 씁니다.

다음 편

지금까지 숫자로만 본 프레임들, 화면에 띄워 볼 수 있을까요?

9편TF를 눈으로 12강 목록