고정 프레임 추가

저작권: 쿼드(QUAD) 드론연구소 https://smartstore.naver.com/maponarooo / Updated : 2024-10-11

TF2 트리

tf2는 프레임의 트리 구조를 구축하므로 프레임 구조에서 닫힌 루프를 허용하지 않습니다. 즉, 프레임은 하나의 부모만 가지지만 여러 자식을 가질 수 있습니다. 현재 tf2 트리에는 세 개의 프레임, world, turtle1turtle2가 있습니다. 두 개의 turtle 프레임은 world프레임의 자식입니다. tf2에 새 프레임을 추가하려면 기존 프레임 세 개 중 하나가 부모 프레임이어야 하며 새 프레임이 자식 프레임이 됩니다.

1. 고정 프레임 브로드캐스터 작성

거북이 예제에서 우리는 새로운 carrot1 프레임을 추가할 것입니다. 이것은 turtle1의 자식이 될 것입니다. 이 프레임은 두 번째 거북이의 목표 역할을 할 것입니다.

먼저 소스 파일을 만들어 보겠습니다. 이전 튜토리얼에서 만든 learning_tf2_py패키지로 이동합니다. src/learning_tf2_py/learning_tf2_py디렉토리 내부에서 다음 명령을 입력하여 고정 프레임 브로드캐스터 코드를 다운로드합니다.

wget https://raw.githubusercontent.com/ros/geometry_tutorials/ros2/turtle_tf2_py/turtle_tf2_py/fixed_frame_tf2_broadcaster.py

이제 fixed_frame_tf2_broadcaster.py 파일을 엽니다.

from geometry_msgs.msg import TransformStamped

import rclpy
from rclpy.node import Node

from tf2_ros import TransformBroadcaster


class FixedFrameBroadcaster(Node):

   def __init__(self):
       super().__init__('fixed_frame_tf2_broadcaster')
       self.tf_broadcaster = TransformBroadcaster(self)
       self.timer = self.create_timer(0.1, self.broadcast_timer_callback)

   def broadcast_timer_callback(self):
       t = TransformStamped()

       t.header.stamp = self.get_clock().now().to_msg()
       t.header.frame_id = 'turtle1'
       t.child_frame_id = 'carrot1'
       t.transform.translation.x = 0.0
       t.transform.translation.y = 2.0
       t.transform.translation.z = 0.0
       t.transform.rotation.x = 0.0
       t.transform.rotation.y = 0.0
       t.transform.rotation.z = 0.0
       t.transform.rotation.w = 1.0

       self.tf_broadcaster.sendTransform(t)


def main():
    rclpy.init()
    node = FixedFrameBroadcaster()
    try:
        rclpy.spin(node)
    except KeyboardInterrupt:
        pass

    rclpy.shutdown()

이 코드는 tf2 브로드캐스터 튜토리얼 예제와 매우 유사하며 유일한 차이점은 여기의 변환이 시간이 지나도 바뀌지 않는다는 것입니다.

1.1 코드 검토

이 코드의 핵심 줄을 살펴보겠습니다. 여기서 부모에서 turtle1새 자식으로 새 변환 carrot1을 만듭니다. carrot1프레임은 turtle1프레임을 기준으로 y축으로 2미터 오프셋됩니다.

t = TransformStamped()

t.header.stamp = self.get_clock().now().to_msg()
t.header.frame_id = 'turtle1'
t.child_frame_id = 'carrot1'
t.transform.translation.x = 0.0
t.transform.translation.y = 2.0
t.transform.translation.z = 0.0

1.2 진입점 추가

명령이 노드를 실행하도록 하려면 ( 디렉토리에 있는)에 진입점을 추가해야 합니다.ros2 runsetup.pysrc/learning_tf2_py

다음 줄을 'console_scripts':괄호 안에 추가하세요.

'fixed_frame_tf2_broadcaster = learning_tf2_py.fixed_frame_tf2_broadcaster:main',

1.3 launch 파일

이제 이 예제에 대한 실행 파일을 만들어 보겠습니다. 텍스트 편집기를 사용하여 src/learning_tf2_py/launch디렉토리에 새 turtle_tf2_fixed_frame_demo.launch.py파일을 만들고 다음 줄을 추가합니다.

import os

from ament_index_python.packages import get_package_share_directory

from launch import LaunchDescription
from launch.actions import IncludeLaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSource

from launch_ros.actions import Node


def generate_launch_description():
    demo_nodes = IncludeLaunchDescription(
        PythonLaunchDescriptionSource([os.path.join(
            get_package_share_directory('learning_tf2_py'), 'launch'),
            '/turtle_tf2_demo.launch.py']),
        )

    return LaunchDescription([
        demo_nodes,
        Node(
            package='learning_tf2_py',
            executable='fixed_frame_tf2_broadcaster',
            name='fixed_broadcaster',
        ),
    ])

이 실행 파일은 필요한 패키지를 가져온 다음 이전 튜토리얼의 실행 파일에서 만든 노드를 저장할 demo_nodes변수를 만듭니다.

코드의 마지막 부분은 fixed_frame_tf2_broadcaster노드를 사용하여 터틀심 세계에 고정된 carrot1프레임을 추가합니다.

Node(
    package='learning_tf2_py',
    executable='fixed_frame_tf2_broadcaster',
    name='fixed_broadcaster',
),

1.4 빌드

작업 공간 루트에서 rosdep 실행하여 누락된 종속성을 확인합니다.

cd ~/ros2_ws
rosdep install -i --from-path src --rosdistro humble -y

새 터미널을 열고 작업 공간 루트로 이동한 후 설치 파일을 소싱합니다.

. install/setup.bash

1.5 실행

이제 거북이 방송자 데모를 시작할 수 있습니다.

ros2 launch learning_tf2_py turtle_tf2_fixed_frame_demo.launch.py

변형 트리에 새로운 carrot1프레임이 나타난 것을 확인할 수 있습니다 .

첫 번째 거북이를 운전해 보면, 새로운 프레임을 추가했음에도 불구하고 이전 튜토리얼에서 동작이 바뀌지 않았다는 것을 알 수 있습니다. 그 이유는 추가 프레임을 추가해도 다른 프레임에 영향을 미치지 않고 리스너는 여전히 이전에 정의된 프레임을 사용하고 있기 때문입니다.

따라서 두 번째 거북이가 첫 번째 거북이 대신 당근을 따르게 하려면 target_frame의 값을 변경해야 합니다 . 이는 두 가지 방법으로 수행할 수 있습니다. 한 가지 방법은 콘솔에서 직접 실행 파일에 target_frame인수를 전달하는 것입니다.

ros2 launch learning_tf2_py turtle_tf2_fixed_frame_demo.launch.py target_frame:=carrot1

두 번째 방법은 실행 파일을 업데이트하는 것입니다. 그러려면 파일을 열고 'target_frame':'carrot1'인수를 launch_arguments를통해 매개변수를 turtle_tf2_fixed_frame_demo.launch.py에추가합니다.

def generate_launch_description():
    demo_nodes = IncludeLaunchDescription(
        ...,
        launch_arguments={'target_frame': 'carrot1'}.items(),
        )

이제 패키지를 다시 빌드하고, 를 재시작하면 turtle_tf2_fixed_frame_demo.launch.py첫 번째 거북이 대신 당근 다음에 두 번째 거북이가 나타나는 것을 볼 수 있습니다!

Last updated