ROS2 2일차(2) launch

2024. 9. 20. 10:11ROS2/기초

https://puzzling-cashew-c4c.notion.site/ROS-2-Launch-launch-file-55c2125808ef4b64bade278852b37d6e

 

ROS 2 Launch, launch file 작성 | Notion

여러 Node들을 한번에 실행할 수 있는 launch와, 실습을 통해 launch 파일의 작성법을 알아보도록 하겠습니다.

puzzling-cashew-c4c.notion.site

참조 문서

 

ros2에서 launch는 아래와 같은 구조

ros2 launch <패키지 이름> <launch 파일이름>

 

그리고 기본적으로 launch파일은 Python문법을 사용해 ros1에서 사용하던 xml 방식과 비교해보면 매우 편리해졌음

 

gcamp_world.launch.py 파일 살펴보기

import os

from ament_index_python.packages import get_package_share_directory
from launch import LaunchDescription
from launch.actions import ExecuteProcess, IncludeLaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSource
from launch.substitutions import LaunchConfiguration

from launch_ros.actions import Node

# this is the function launch  system will look for
def generate_launch_description():
    use_sim_time = LaunchConfiguration('use_sim_time', default='false')

    rviz_file = "skidbot.rviz"
    robot_file = "skidbot.urdf"
    package_name = "gcamp_gazebo"
    world_file_name = "gcamp_world.world"

    # full  path to urdf and world file
    world = os.path.join(
        get_package_share_directory(package_name), "worlds", world_file_name
    )
    urdf = os.path.join(get_package_share_directory(package_name), "urdf", robot_file)
    rviz = os.path.join(get_package_share_directory(package_name), "rviz", rviz_file)

    # read urdf contents because to spawn an entity in
    # gazebo we need to provide entire urdf as string on  command line
    robot_desc = open(urdf, "r").read()

    # double quotes need to be with escape sequence
    xml = robot_desc.replace('"', '\\"')

    # this is argument format for spwan_entity service
    spwan_args = '{name: "skidbot", xml: "' + xml + '" }'

    robot_state_publisher_node = Node(
        package='robot_state_publisher',
        executable='robot_state_publisher',
        parameters=[{'use_sim_time': use_sim_time, 'robot_description': robot_desc}],
        arguments=[urdf],
    )


    # create and return launch description object
    return LaunchDescription(
        [
            # robot state publisher allows robot model spawn in RVIZ
            robot_state_publisher_node,
            # start gazebo, notice we are using libgazebo_ros_factory.so instead of libgazebo_ros_init.so
            # That is because only libgazebo_ros_factory.so contains the service call to /spawn_entity
            ExecuteProcess(
                cmd=["gazebo", "--verbose", world, "-s", "libgazebo_ros_factory.so"],
                output="screen",
            ),
            # tell gazebo to spwan your robot in the world by calling service
            ExecuteProcess(
                cmd=[ "ros2", "service", "call", "/spawn_entity", "gazebo_msgs/SpawnEntity", spwan_args ],
                output="screen",
            ),
            ExecuteProcess(
                cmd=["ros2", "run", "rviz2", "rviz2", "-d", rviz], output="screen"
            ),
        ]
    )

 

여기서 아래 ExecuteProcess 아래 부분은 개별적으로 실행 가능

이 파일을 launch 하면

  1. gazebo 실행
  2. 로봇 생성
  3. rviz 실행

gazebo 실행과 로봇 생성 같은 경우엔 파라미터를 미리 설정해줘야하는데

# full  path to urdf and world file
  world = os.path.join(
      get_package_share_directory(package_name), "worlds", world_file_name
  )
  urdf = os.path.join(get_package_share_directory(package_name), "urdf", robot_file)
  rviz = os.path.join(get_package_share_directory(package_name), "rviz", rviz_file)

여기서 미리 설정하여 코드를 여러번 쓸 필요가 없음

 

launch file을 작성하는 데에는 여러 방식이 있음

첫번째로 ExecuteProcess 방식

rviz만 동작시키는 launch file

cd ~/ch_ws/src/gcamp_ros2_basic/gcamp_gazebo/launch
touch first_launch.launch.py
code first_launch.launch.py

 

first_launch.launch.py

#!/usr/bin/env python3

import os

from launch import LaunchDescription
from launch.actions import ExecuteProcess, IncludeLaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSource
from launch.substitutions import LaunchConfiguration

from launch_ros.actions import Node

# this is the function launch  system will look for
def generate_launch_description():

    # create and return launch description object
    return LaunchDescription(
        [
            ExecuteProcess(
                cmd=["ros2", "run", "rviz2", "rviz2"], output="screen"
            ),
        ]
    )

 

cd ~/ch_ws
source install/setup.bash
ros2 launch gcamp_gazebo/first_launch.launch.py

 

  • generate_launch_description : ros2 launch 커멘드를 통해 launch file을 실행시키면, 이 이름을 가진 함수를 찾아들어갑니다. 그래서 모든 launch file에는 빠지지 않고 제일 먼저 등장하는 함수입니다.
  • LaunchDescription : 이 부분에서는 말 그대로, 어떤 Node들을 실행시킬지 기술해둔 Description을 작성합니다. 다만 특정한 규칙으로 실행시킨 Node에 대한 옵션을 지정해주어야 하며, 여러 Node들의 실행이 필요할 수 있기에, 기본적으로 list의 구조를 가짐을 파악할 수 있습니다.
  • ExecuteProcess : 프로세스 하나를 실행시킨다는 구분의 개념으로 생각하시면 좋습니다.
    • cmd : 앞에서 살펴본 바와 같이 터미널에서 입력하는 커멘드를 그대로 실행하고자 할 시에 사용 됩니다. 입력은 list 형태로 주어지며, space를 기점으로 나누어 주면 됩니다.
    • output : Error log 등의 output이 출력되는 수단을 입력합니다.

 

두번째 node 방식

ros2 run turtlesim turtlesim_node
ros2 run turtlesim draw_square

 

이렇게 따로 실행시켜야 하는 두 노드를 하나의 launch file로 만들어보기

cd ~/ch_ws/src/gcamp_ros2_basic/gcamp_gazebo/launch
touch second_launch.launch.py
code second_launch.launch.py

 

second_launch.launch.py

#!/usr/bin/env python3

import os

from launch import LaunchDescription
from launch.actions import ExecuteProcess, IncludeLaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSource
from launch.substitutions import LaunchConfiguration

from launch_ros.actions import Node

# this is the function launch  system will look for
def generate_launch_description():

    turtlesim_node = Node(
        package='turtlesim',
        executable='turtlesim_node',
        parameters=[],
        arguments=[],
        output="screen",
    )

    turtlesim_teleop_node = Node(
        package='turtlesim',
        executable='draw_square',
        parameters=[],
        arguments=[],
        output="screen",
    )

    # create and return launch description object
    return LaunchDescription(
        [
            turtlesim_node,
            turtlesim_teleop_node,
        ]
    )

 

cd ~/ch_ws
source install/setup.bash
ros2 launch gcamp_gazebo/second_launch.launch.py

그러면 거북이가 켜지는 것과 사각형으로 움직이는 것이 한번에 실행되는 것을 볼 수 있다.

 

  • Node : Node 하나를 실행시킬 수 있는 옵션입니다.
    • package : 실행시킬 Node가 포함된 package를 선택해줍니다.
    • executable : c++ Node의 경우, colcon build를 하면 실행 가능한 프로그램이 생성됩니다. python의 경우도 추가 작업이 필요한데요, 우선 지금은 기존 커멘드의 마지막 인자라고 생각하시면 좋습니다.
    • parameters : 실행시킬 Node의 추가 매개변수가 있다면 여기 추가됩니다.
    • arguments , name, remappings 등 여러 옵션들이 있다

https://github.com/mit-racecar/racecar/blob/master/racecar/config/racecar-v2/vesc.yaml

 

racecar/racecar/config/racecar-v2/vesc.yaml at master · mit-racecar/racecar

Contribute to mit-racecar/racecar development by creating an account on GitHub.

github.com

위와 같이 매개변수들을 .yaml 파일로 생성 후 launch 할 때 import 할 수 있다.

'ROS2 > 기초' 카테고리의 다른 글

ROS2 2일차(5) tf2  (0) 2024.09.20
ROS2 2일차(4) topic 프로그래밍  (0) 2024.09.20
ROS2 2일차(3) topic  (0) 2024.09.20
ROS2 2일차(1) node  (0) 2024.09.20
ROS2 1일차 Gazebo 월드 생성 및 모델  (0) 2024.09.19