움직이는 로봇 브로드캐스팅

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

지금까지 몇 가지 멋진 트릭을 배웠지만 여전히 정적 프레임을 게시하는 데 어려움을 겪고 있습니다. 로봇이 움직이기를 원합니다! 이 문제를 해결하기 전에 몇 가지 추가 패키지를 설치해야 합니다.

sudo apt install ros-humble-xacro ros-humble-joint-state-publisher-gui

이를 수행하는 첫 번째 단계는 로봇용 URDF 파일이 있는지 확인하는 것입니다. 이것은 크기, 모양, 색상 등과 같은 로봇 구성 요소의 모든 종류의 물리적 특성을 지정할 수 있는 일종의 구성 파일입니다.

URDF에서 로봇은 링크 라고 하는 일련의 견고한 구성 요소로 구성되며 링크는 부모-자식 트리 구조로 함께 연결됩니다. 여기서 서로 다른 링크 간의 관계를 Joint관절 이라고 합니다.

링크/조인트 패턴이 프레임/변환 패턴과 매우 유사한 방식을 보는 것은 그리 어렵지 않습니다. 그것들은 매우 밀접하게 관련되어 있기 때문에 URDF 파일을 가져와 자동으로 모든 변환을 브로드캐스트할 수 있는 ROS 노드 robot_state_publisher가 있습니다 . /robot_description또한 필요한 다른 모든 노드가 동일한 파일을 사용할 수 있도록 URDF 파일의 전체 내용을 토픽에 게시합니다 .

URDF 파일에서 각 조인트는 "Static" 또는 다양한 이동 가능 유형(예: 연속 회전, 제한된 회전, 선형 슬라이딩) 중 하나로 정의될 수 있습니다. 고정된 관절의 경우 robot_state_publisher정적 변환만 게시할 수 있지만 이동하는 관절의 경우 해당 시점에 대한 동적 변환을 계산하기 위해 외부 값(예: 각도 또는 거리)이 필요합니다. 이러한 값을 얻기 위해 JointStat메시지를 포함할 /joint_states이라는 토픽을 구독합니다. 이러한 메시지에는 관절의 위치, 속도 또는 노력에 대한 정보가 포함될 수 있습니다(하지만 지금은 위치만 사용합니다).

갑자기 작업이 훨씬 쉬워졌습니다! 전체 변환을 브로드캐스트하는 대신 JointState메시지를 게시하기만 하면 됩니다. 일반적으로 이 데이터는 인코더 또는 전위차계와 같은 로봇의 액추에이터 피드백 센서에서 나옵니다(시뮬레이션 환경에서는 이러한 센서를 시뮬레이션할 수 있음).

지금은 joint_state_publisher_gui 이라는 도구를 사용하여 관절 상태를 속일 것입니다. 이 노드는 /robot_description에서 게시한 robot_state_publisher항목을 보고 이동할 수 있는 관절을 찾은 다음 해당 관절에 대한 슬라이더를 표시합니다. 이 슬라이더에서 값을 읽고 /joint_states에 게시합니다.

이 모든 것을 실행해 봅시다.

먼저 robot_state_publisher를 실행할 것입니다 . URDF 파일을 전달하는 것이 약간 까다롭기 때문에 처음 실행할 때 약간 혼란스러울 수 있습니다. URDF는 robot_description매개변수에서 가져오므로 명령은 다음과 같습니다.

ros2 run robot_state_publisher robot_state_publisher --ros-args -p robot_description:=(something here)

예제 "example_robot.urdf.xacro" 는 다음과 같습니다.

<?xml version="1.0"?>
<robot xmlns:xacro="http://www.ros.org/wiki/xacro"  name="robot">

    <material name="grey">
        <color rgba="0.2 0.2 0.2 1"/>
    </material>

    <material name="white">
        <color rgba="1 1 1 1"/>
    </material>

    <material name="orange">
        <color rgba="1 0.3 0.1 1"/>
    </material>

    <material name="blue">
        <color rgba="0 0 1 1"/>
    </material>


    <link name="world"></link>

    <joint name="world_to_base" type="fixed">
        <parent link="world" />
        <child link="base" />
        <origin  rpy="1.57 0 0" xyz="0 0 0" />
    </joint>

    <link name="base">
        <visual>
            <origin xyz="2 0 0" rpy="0 0 0"/>
            <geometry>
                <box size="5 0.1 3" />
            </geometry>
            <material name="grey" />
        </visual>
    </link>


    <joint name="base_to_l3" type="revolute">
        <parent link="base" />
        <child link="l3" />
        <origin  rpy="0 0 0" xyz="0 0.25 0" />
        <axis rpy="0 0 0" xyz="0 0 1" />
        <limit effort="0.1" lower="-3.1" upper="3.1" velocity="0.2"/>
    </joint>


    <link name="l3">
        <visual>
            <origin xyz="0.75 0 0" rpy="0 1.57 0"/>
            <geometry>
                <cylinder length="1.5" radius="0.04" />
            </geometry>
            <material name="orange" />
        </visual>
    </link>

    <joint name="l3_to_l2" type="revolute">
        <parent link="l3" />
        <child link="l2" />
        <!-- <origin xyz="1 0 0" /> -->
        <origin rpy="0 0 0" xyz="1.5 0 0" />
        <axis rpy="0 0 0" xyz="0 0 1" />
        <limit effort="0.1" lower="-3.1" upper="3.1" velocity="0.2"/>
    </joint>


    <link name="l2">
        <visual>
            <origin xyz="0.75 0 0" rpy="0 1.57 0"/>
            <geometry>
                
                <cylinder length="1.5" radius="0.04" />
            </geometry>
            <material name="orange" />
        </visual>
    </link>

    <joint name="l2_to_l1" type="revolute">
        <parent link="l2" />
        <child link="l1" />
        <origin rpy="0 0 0" xyz="1.5 0 0" />
        <axis rpy="0 0 0" xyz="0 0 1" />
        <limit effort="0.1" lower="-3.1" upper="3.1" velocity="0.2"/>
    </joint>


    <link name="l1">
        <visual>
            <origin xyz="0.5 0 0" rpy="0 1.57 0"/>
            <geometry>
                
                <cylinder length="1" radius="0.04" />
            </geometry>
            <material name="orange" />
        </visual>
    </link>


    <joint name="l1_to_grip" type="revolute">
        <parent link="l1" />
        <child link="grip" />
        <origin rpy="0 0 0" xyz="1 0 0" />
        <axis rpy="0 0 0" xyz="0 0 1" />
        <limit effort="0.1" lower="-3.1" upper="3.1" velocity="0.2"/>
    </joint>


    <link name="grip">
        <visual>
            <origin xyz="0.25 0 0"/>
            <geometry>
                <box size="0.5 0.5 0.05" />
            </geometry>
            <material name="white" />
        </visual>
    </link>



    <joint name="world_to_camera" type="fixed">
        <parent link="world" />
        <child link="camera" />
        <origin  rpy="-2 0 2.5" xyz="4 1 2" />
    </joint>

    <link name="camera">
        <visual>
            <origin xyz="0 0 -0.2"/>
            <geometry>
                <box size="0.2 0.2 0.4" />
            </geometry>
            <material name="blue" />
        </visual>
    </link>


</robot>

파일을 저장한 다음 Joint 상태를 게시하기 위해 다음을 실행할 수 있습니다.

ros2 run robot_state_publisher robot_state_publisher --ros-args -p robot_description:="$(xacro example_robot.urdf.xacro)"

다음은 joint_state_publisher_gui 를 실행 합니다.

ros2 run joint_state_publisher_gui joint_state_publisher_gui

마지막으로 RViz를 다시 시작하고 TF 시각화를 추가하고 슬라이더를 조정할 때 프레임이 움직이는 것을 볼 수 있습니다.

RViz에서 "RobotModel" 시각화를 추가할 수도 있습니다.

옵션을 사용하여 /robot_description항목을 선택하면 링크의 시각적 표현이 나타납니다.

Rviz

tf2_tools

위의 예가 제대로 작동했으면 좋겠지만 때때로 우리가 변환 작업을 할 때 제대로 작동하지 않는 경우가 있으며 그 이유를 알아내야 합니다.

앞서 언급했듯이 변환 데이터는 두 가지 주제 /tf/tf_static에 게시됩니다 . ros2 topic echo를 사용하여 이러한 주제를 직접 들을 수 있지만 때때로 해석하기 까다로울 수 있습니다. 도움을 주기 위해 ROS에는 변환 트리를 시각화할 수 있는 도구(tf2_tools)view_frames함께 브로드캐스팅 방법에 대한 정보가 함께 제공됩니다.

참고로, ROS 1에는 이 작업을 정확히 수행하지만 번거로움은 덜한 유용한 도구rqt_tf_tree가 있었습니다 . 그러나 작성 당시에는 ROS2로 포팅되지 않았으므로 view_frames을대신 사용해야 합니다.

이 도구는 실제로 몇 초 동안 변환을 수신한 다음 스크립트가 실행될 때 터미널이 있던 디렉터리에 frames.pd fframes.gv 라는 파일을 생성하는 Python 스크립트입니다(새 터미널의 경우 홈 디렉터리가 됨).

스크립트는 tf2_tools패키지의 일부이므로 다음을 실행하기만 하면 됩니다.

ros2 run tf2_tools view_frames.py

결과 파일을 보면(파일 브라우저에서 열거나 로 터미널에서 열 때 atril frames.pdf) 시각화된 트리를 볼 수 있습니다. 여기의 화살표는 RViz와 비교하여 반대입니다(소개에서와 동일함). 지금은 표시되는 나머지 정보에 대해 너무 걱정하지 않을 것입니다.

익숙하지 않다면 "16314… Unix Time(일명 Epoch Time)에 대한 자세한 내용은 Epoch Converter를 확인하십시오 . 시뮬레이션을 실행할 때 Gazebo는 자체 시간 소스를 생성하며 숫자는 Gazebo가 시작된 이후 초 단위입니다.

Last updated