1. Model Spawn이란?
Model Spawn은 Gazebo 시뮬레이션 월드 안에 로봇 모델을 동적으로 생성하는 작업입니다.
쉽게 말하면 다음과 같습니다.
URDF/Xacro 파일 작성
↓
robot_description 생성
↓
Gazebo 실행
↓
spawn_entity.py 또는 ros_gz_sim create로 로봇 투입
↓
Gazebo 화면에 모바일 로봇 등장
ROS 2에서 Gazebo Classic을 사용할 때는 보통 gazebo_ros spawn_entity.py를 사용하고, 최신 Gazebo Sim 계열에서는 ros_gz_sim create 또는 ros_gz_spawn_model.launch.py를 사용합니다.
2. 실습 목표
이번 실습의 최종 목표는 다음과 같습니다.
my_mobile_robot_description 패키지 생성
↓
2륜 모바일 로봇 URDF/Xacro 작성
↓
robot_state_publisher 실행
↓
Gazebo 실행
↓
로봇 모델 Spawn
↓
Gazebo에서 로봇 위치 확인
완성하면 다음 명령 하나로 Gazebo에 모바일 로봇을 띄울 수 있습니다.
ros2 launch my_mobile_robot_description spawn_robot.launch.py
3. 핵심 개념 이해
1) URDF
URDF는 Unified Robot Description Format의 약자입니다. 로봇의 링크, 조인트, 바퀴, 센서 위치, 충돌 영역, 관성 정보를 XML 형식으로 정의합니다.
모바일 로봇에서는 보통 다음 요소가 들어갑니다.
base_link : 로봇 본체 left_wheel_link : 왼쪽 바퀴 right_wheel_link: 오른쪽 바퀴 caster_link : 보조 바퀴 joint : 본체와 바퀴의 연결 관계 collision : 충돌 계산용 형상 visual : 화면 표시용 형상 inertial : 질량과 관성 정보
2) Xacro
Xacro는 URDF를 더 편하게 작성하기 위한 매크로 도구입니다.
URDF만 쓰면 같은 숫자와 구조를 반복해서 작성해야 합니다. Xacro를 쓰면 변수와 매크로를 사용해 로봇 크기, 바퀴 반지름, 바퀴 간 거리 등을 쉽게 수정할 수 있습니다.
예를 들어 다음처럼 작성할 수 있습니다.
<xacro:property name="wheel_radius" value="0.1"/> <xacro:property name="wheel_width" value="0.05"/>
처음부터 복잡한 메시 파일을 쓰지 말고, box, cylinder, sphere 같은 기본 형상으로 시작하는 것이 좋습니다. 메시 경로 문제 때문에 초보자가 스폰 실패를 자주 겪습니다. 실제 GitHub 이슈에서도 URDF 자체는 스폰되지만 mesh 파일 경로 때문에 일부 링크가 보이지 않는 사례가 보고되어 있습니다.
3) robot_state_publisher
robot_state_publisher는 URDF로 정의된 로봇 구조를 읽어서 TF 정보를 발행하는 노드입니다.
Gazebo 스폰에서는 보통 다음 흐름으로 사용합니다.
robot.urdf.xacro
│
│ xacro 명령으로 변환
▼
URDF XML 문자열
│
│ robot_description 파라미터로 전달
▼
robot_state_publisher
│
├── /robot_description 토픽 발행
├── /tf 발행
└── /tf_static 발행
│
│ spawn_entity.py가
│ /robot_description 토픽 구독
▼
spawn_entity.py
│
│ /spawn_entity 서비스 요청
▼
Gazebo 월드에 로봇 생성
spawn_entity.py는 일반적으로 robot_state_publisher 노드의 파라미터를 직접 읽는 것이 아니라, /robot_description 토픽을 구독해 URDF 문자열을 받습니다.
4. 패키지 생성
cd ~/gazebo_ws/src ros2 pkg create my_robot_description --build-type ament_python

폴더 생성:
cd ~/gazebo_ws/src/my_robot_description mkdir urdf launch

5. 간단한 2륜 로봇 URDF 작성
touch urdf/simple_diff_robot.urdf

내용:
<?xml version="1.0"?>
<robot name="simple_diff_robot">
<link name="base_link">
<visual>
<geometry>
<box size="0.4 0.3 0.1"/>
</geometry>
<origin xyz="0 0 0.05"/>
</visual>
<collision>
<geometry>
<box size="0.4 0.3 0.1"/>
</geometry>
<origin xyz="0 0 0.05"/>
</collision>
<inertial>
<mass value="2.0"/>
<origin xyz="0 0 0.05"/>
<inertia ixx="0.02" ixy="0" ixz="0"
iyy="0.02" iyz="0"
izz="0.02"/>
</inertial>
</link>
<link name="left_wheel">
<visual>
<geometry>
<cylinder radius="0.05" length="0.03"/>
</geometry>
<origin rpy="1.5708 0 0"/>
</visual>
<collision>
<geometry>
<cylinder radius="0.05" length="0.03"/>
</geometry>
<origin rpy="1.5708 0 0"/>
</collision>
<inertial>
<mass value="0.2"/>
<inertia ixx="0.001" ixy="0" ixz="0"
iyy="0.001" iyz="0"
izz="0.001"/>
</inertial>
</link>
<link name="right_wheel">
<visual>
<geometry>
<cylinder radius="0.05" length="0.03"/>
</geometry>
<origin rpy="1.5708 0 0"/>
</visual>
<collision>
<geometry>
<cylinder radius="0.05" length="0.03"/>
</geometry>
<origin rpy="1.5708 0 0"/>
</collision>
<inertial>
<mass value="0.2"/>
<inertia ixx="0.001" ixy="0" ixz="0"
iyy="0.001" iyz="0"
izz="0.001"/>
</inertial>
</link>
<joint name="left_wheel_joint" type="continuous">
<parent link="base_link"/>
<child link="left_wheel"/>
<origin xyz="0 0.17 0.05" rpy="0 0 0"/>
<axis xyz="0 1 0"/>
</joint>
<joint name="right_wheel_joint" type="continuous">
<parent link="base_link"/>
<child link="right_wheel"/>
<origin xyz="0 -0.17 0.05" rpy="0 0 0"/>
<axis xyz="0 1 0"/>
</joint>
<gazebo>
<plugin name="diff_drive" filename="libgazebo_ros_diff_drive.so">
<ros>
<namespace>/</namespace>
</ros>
<left_joint>left_wheel_joint</left_joint>
<right_joint>right_wheel_joint</right_joint>
<wheel_separation>0.34</wheel_separation>
<wheel_diameter>0.1</wheel_diameter>
<max_wheel_torque>20</max_wheel_torque>
<max_wheel_acceleration>1.0</max_wheel_acceleration>
<command_topic>cmd_vel</command_topic>
<odometry_topic>odom</odometry_topic>
<odometry_frame>odom</odometry_frame>
<robot_base_frame>base_link</robot_base_frame>
<publish_odom>true</publish_odom>
<publish_odom_tf>true</publish_odom_tf>
<publish_wheel_tf>true</publish_wheel_tf>
</plugin>
</gazebo>
</robot>

이 URDF 파일은 Gazebo Classic에서 동작하는 간단한 2륜 차동구동 모바일 로봇을 정의합니다. 로봇은 직육면체 형태의 본체와 좌우 바퀴로 구성되며, gazebo_ros_diff_drive 플러그인을 통해 ROS 2의 cmd_vel 메시지로 움직일 수 있습니다.
로봇 본체
<link name="base_link">
base_link는 로봇의 중심이 되는 기본 링크입니다. 본체 크기는 다음과 같습니다.
<box size="0.4 0.3 0.1"/>
각 값은 X, Y, Z축 방향 크기를 의미합니다.
- 길이: 0.4m
- 폭: 0.3m
- 높이: 0.1m
본체 중심은 지면에서 0.05m 위에 위치합니다.
<origin xyz="0 0 0.05"/>
visual은 화면에 표시되는 모양이고, collision은 Gazebo의 충돌 계산에 사용됩니다. inertial에는 로봇 본체의 질량과 관성값이 설정되어 있습니다.
좌우 바퀴
left_wheel과 right_wheel은 원통형으로 정의되어 있습니다.
<cylinder radius="0.05" length="0.03"/>
바퀴의 반지름은 0.05m이고, 지름은 0.1m입니다. 바퀴 폭은 0.03m입니다.
URDF에서 원통의 기본 축은 Z축이므로, 바퀴가 Y축 방향을 중심으로 회전하도록 X축 방향으로 약 90도 회전시킵니다.
<origin rpy="1.5708 0 0"/>
바퀴 조인트
좌우 바퀴는 continuous 타입의 조인트로 본체에 연결됩니다.
<joint name="left_wheel_joint" type="continuous">
continuous 조인트는 회전 각도 제한 없이 계속 회전할 수 있으므로 바퀴에 적합합니다.
왼쪽 바퀴는 Y축의 양수 방향, 오른쪽 바퀴는 Y축의 음수 방향에 배치됩니다.
<origin xyz="0 0.17 0.05"/>
<origin xyz="0 -0.17 0.05"/>
두 바퀴의 중심 간 거리는 0.34m입니다.
<axis xyz="0 1 0"/>
바퀴의 회전축은 Y축으로 설정되어 있습니다. 로봇의 X축이 전방 방향이므로 바퀴가 회전하면 로봇이 앞뒤로 이동합니다.
차동구동 플러그인
<plugin name="diff_drive"
filename="libgazebo_ros_diff_drive.so">
이 플러그인은 좌우 바퀴의 속도를 제어해 로봇을 전진, 후진, 회전시키는 역할을 합니다.
좌우 바퀴 조인트는 다음과 같이 지정합니다.
<left_joint>left_wheel_joint</left_joint>
<right_joint>right_wheel_joint</right_joint>
바퀴 간 거리와 바퀴 지름은 실제 URDF 구조와 동일하게 설정되어 있습니다.
<wheel_separation>0.34</wheel_separation>
<wheel_diameter>0.1</wheel_diameter>
이 값들이 실제 모델 치수와 다르면 주행 거리나 회전 각도 계산에 오차가 발생할 수 있습니다.
6. 로봇 spawn launch 작성
touch launch/spawn_robot.launch.py

내용:
import os
from ament_index_python.packages import get_package_share_directory
from launch import LaunchDescription
from launch.actions import IncludeLaunchDescription, ExecuteProcess
from launch.launch_description_sources import PythonLaunchDescriptionSource
from launch_ros.actions import Node
def generate_launch_description():
gazebo_ros_pkg = get_package_share_directory('gazebo_ros')
robot_pkg = get_package_share_directory('my_robot_description')
urdf_path = os.path.join(robot_pkg, 'urdf', 'simple_diff_robot.urdf')
with open(urdf_path, 'r') as infp:
robot_description = infp.read()
gazebo = IncludeLaunchDescription(
PythonLaunchDescriptionSource(
os.path.join(gazebo_ros_pkg, 'launch', 'gazebo.launch.py')
)
)
robot_state_publisher = Node(
package='robot_state_publisher',
executable='robot_state_publisher',
parameters=[
{'robot_description': robot_description},
{'use_sim_time': True}
]
)
spawn_entity = Node(
package='gazebo_ros',
executable='spawn_entity.py',
arguments=[
'-topic', 'robot_description',
'-entity', 'simple_diff_robot',
'-x', '0',
'-y', '0',
'-z', '0.1'
],
output='screen'
)
return LaunchDescription([
gazebo,
robot_state_publisher,
spawn_entity
])

패키지 경로 가져오기
gazebo_ros_pkg = get_package_share_directory('gazebo_ros')
robot_pkg = get_package_share_directory('my_robot_description')
두 개의 패키지 경로를 가져옵니다.
gazebo_ros_pkg는 Gazebo Classic과 ROS 2를 연결하는 gazebo_ros 패키지 경로입니다.
robot_pkg는 로봇의 URDF 파일이 들어 있는 my_robot_description 패키지 경로입니다.
URDF 파일 경로 설정
urdf_path = os.path.join(
robot_pkg,
'urdf',
'simple_diff_robot.urdf'
)
my_robot_description 패키지 내부의 URDF 파일 경로를 생성합니다.
프로젝트 구조는 다음과 같은 형태를 가정합니다.
my_robot_description/
├── launch/
│ └── gazebo_spawn.launch.py
├── urdf/
│ └── simple_diff_robot.urdf
├── CMakeLists.txt
└── package.xml
URDF 파일 읽기
with open(urdf_path, 'r') as infp:
robot_description = infp.read()
URDF 파일의 전체 내용을 문자열로 읽어 robot_description 변수에 저장합니다.
이 문자열은 이후 robot_state_publisher의 robot_description 파라미터로 전달됩니다.
with open() 문을 사용하면 파일 처리가 끝난 뒤 자동으로 파일이 닫힙니다.
Gazebo Classic 실행
gazebo = IncludeLaunchDescription(
PythonLaunchDescriptionSource(
os.path.join(
gazebo_ros_pkg,
'launch',
'gazebo.launch.py'
)
)
)
gazebo_ros 패키지에 포함된 gazebo.launch.py를 현재 Launch 파일에 포함합니다.
이 Launch 파일은 일반적으로 다음 프로그램을 실행합니다.
gzserver: 물리 시뮬레이션 서버gzclient: Gazebo GUI
별도의 월드 파일을 지정하지 않았기 때문에 Gazebo의 기본 빈 월드가 실행됩니다.
사용자 정의 월드를 실행하려면 world 인자를 전달할 수 있습니다.
gazebo = IncludeLaunchDescription(
PythonLaunchDescriptionSource(
os.path.join(
gazebo_ros_pkg,
'launch',
'gazebo.launch.py'
)
),
launch_arguments={
'world': '/절대/경로/basic_mobile_world.world'
}.items()
)
robot_state_publisher 실행
robot_state_publisher = Node(
package='robot_state_publisher',
executable='robot_state_publisher',
parameters=[
{'robot_description': robot_description},
{'use_sim_time': True}
]
)
robot_state_publisher는 URDF에 정의된 링크와 조인트 관계를 읽고 로봇의 TF 좌표계를 발행하는 노드입니다.
robot_description
{'robot_description': robot_description}
앞에서 읽어 온 URDF 문자열을 robot_description 파라미터로 전달합니다.
robot_state_publisher는 이 정보를 이용해 로봇의 전체 링크 구조를 해석합니다.
use_sim_time
{'use_sim_time': True}
ROS 2 노드가 컴퓨터의 실제 시간 대신 Gazebo의 시뮬레이션 시간을 사용하도록 설정합니다.
Gazebo는 /clock 토픽으로 시뮬레이션 시간을 발행합니다. 시뮬레이션이 일시 정지되면 ROS 2 노드의 시간도 함께 정지합니다.
Gazebo와 연동하는 노드에서는 일반적으로 use_sim_time을 True로 설정합니다.
Gazebo에 로봇 생성
spawn_entity = Node(
package='gazebo_ros',
executable='spawn_entity.py',
arguments=[
'-topic', 'robot_description',
'-entity', 'simple_diff_robot',
'-x', '0',
'-y', '0',
'-z', '0.1'
],
output='screen'
)
spawn_entity.py는 URDF 또는 SDF 모델을 Gazebo 월드에 생성하는 프로그램입니다.
URDF 토픽 지정
'-topic', 'robot_description'
robot_description 토픽 또는 파라미터를 통해 전달되는 URDF 정보를 이용해 로봇을 생성합니다.
이 정보는 앞에서 실행한 robot_state_publisher의 robot_description 파라미터를 기반으로 제공됩니다.
Gazebo 모델 이름
'-entity', 'simple_diff_robot'
Gazebo 월드 안에 생성되는 모델 이름을 simple_diff_robot으로 설정합니다.
같은 이름의 모델이 이미 존재하면 중복 생성 오류가 발생할 수 있습니다.
로봇 생성 위치
'-x', '0',
'-y', '0',
'-z', '0.1'
로봇을 다음 위치에 생성합니다.
X = 0m
Y = 0m
Z = 0.1m
Z축 위치를 지면보다 약간 높은 0.1m로 지정하면 로봇의 충돌 모델이 바닥과 겹쳐 생성되는 문제를 줄일 수 있습니다.
단, 적절한 Z축 높이는 로봇 바퀴 반지름과 URDF의 링크 원점에 따라 달라질 수 있습니다.
터미널 출력
output='screen'
노드의 로그 메시지와 오류 메시지를 현재 터미널 화면에 출력합니다.
로봇이 생성되지 않을 때 원인을 확인하기 위해 유용한 설정입니다.
실행 항목 등록
return LaunchDescription([
gazebo,
robot_state_publisher,
spawn_entity
])
마지막으로 실행할 항목을 LaunchDescription에 등록합니다.
Launch 파일이 실행되면 Gazebo, robot_state_publisher, spawn_entity.py가 함께 시작됩니다.
일반적인 실행 흐름은 다음과 같습니다.
Gazebo Classic 실행
↓
URDF 정보 등록
↓
robot_state_publisher 실행
↓
Gazebo 월드에 로봇 생성
Launch 목록의 작성 순서가 각 프로세스의 완전한 시작 순서를 보장하는 것은 아닙니다. 복잡한 프로젝트에서는 Gazebo 서버가 준비된 뒤 로봇을 생성하도록 이벤트 핸들러나 지연 실행을 적용하기도 합니다.
7. setup.py 수정
import os
from glob import glob
from setuptools import setup
package_name = 'my_robot_description'
setup(
name=package_name,
version='0.0.0',
packages=[package_name],
data_files=[
('share/ament_index/resource_index/packages',
['resource/' + package_name]),
('share/' + package_name, ['package.xml']),
(os.path.join('share', package_name, 'urdf'), glob('urdf/*.urdf')),
(os.path.join('share', package_name, 'launch'), glob('launch/*.launch.py')),
],
install_requires=['setuptools'],
zip_safe=True,
maintainer='user',
maintainer_email='user@example.com',
description='Simple robot description for Gazebo',
license='Apache-2.0',
tests_require=['pytest'],
entry_points={
'console_scripts': [],
},
)

빌드:
cd ~/gazebo_ws colcon build source install/setup.bash

실행:
ros2 launch my_robot_description spawn_robot.launch.py

8. /cmd_vel로 로봇 움직이기
로봇이 Gazebo에 뜬 상태에서 새 터미널을 엽니다.
source /opt/ros/humble/setup.bash source ~/gazebo_ws/install/setup.bash
전진 명령:
ros2 topic pub /cmd_vel geometry_msgs/msg/Twist \
"{linear: {x: 0.2, y: 0.0, z: 0.0}, angular: {x: 0.0, y: 0.0, z: 0.0}}" --once

회전 명령:
ros2 topic pub /cmd_vel geometry_msgs/msg/Twist \
"{linear: {x: 0.0, y: 0.0, z: 0.0}, angular: {x: 0.0, y: 0.0, z: 0.5}}" --once

정지:
ros2 topic pub --once /cmd_vel geometry_msgs/msg/Twist \
"{linear: {x: 0.0, y: 0.0, z: 0.0}, angular: {x: 0.0, y: 0.0, z: 0.0}}" --once

토픽 확인:
ros2 topic list

예상 토픽:
/cmd_vel /odom /tf /tf_static /clock /robot_description
9. RViz2로 Gazebo 로봇 확인하기
rviz2
RViz2에서 설정합니다.
설정값
| Fixed Frame | odom |
| Display | RobotModel |
| Display | TF |
| Display | Odometry |

Gazebo는 물리 시뮬레이션을 담당하고, RViz2는 ROS 데이터를 시각화하는 도구입니다. 둘은 역할이 다릅니다.
도구역할
| Gazebo | 실제 세계처럼 물리 계산 |
| RViz2 | ROS 토픽, TF, 센서 데이터 시각화 |
10. Gazebo와 ROS 2 통신 구조
Gazebo Classic에서 ROS 2와 연결되는 대표 플러그인은 다음과 같습니다.
목적플러그인 예
| Differential Drive | libgazebo_ros_diff_drive.so |
| Camera | libgazebo_ros_camera.so |
| Ray/LiDAR | libgazebo_ros_ray_sensor.so |
| IMU | libgazebo_ros_imu_sensor.so |
| Joint State | libgazebo_ros_joint_state_publisher.so |
| Factory Spawn | spawn_entity.py |
Gazebo Classic은 독립 실행 프로그램이고, ROS 연동은 gazebo_ros_pkgs 계열 패키지를 통해 이루어집니다.
11. Gazebo Sim 설치와 ros_gz 기본 개념
ROS 2 Humble에서 공식적으로 권장되는 Gazebo 조합은 다음과 같습니다.
Ubuntu 22.04 Jammy
ROS 2 Humble Hawksbill
Gazebo Fortress LTS
ros_gz
Gazebo Fortress는 ROS 2 Humble과 공식적으로 통합·시험된 조합입니다. Gazebo 공식 호환성 표에서도 Humble과 Fortress를 권장 조합으로 분류합니다. Fortress는 2027년 5월까지 지원되는 LTS 배포판입니다.
여기서 주의해야 할 부분은 실행 명령어입니다.
Gazebo Fortress → ign gazebo
Gazebo Harmonic → gz sim
Fortress도 제품명은 Gazebo Sim이지만, 이름이 Ignition에서 Gazebo로 완전히 변경되기 전에 출시되었기 때문에 직접 실행할 때는 gz sim이 아니라 다음 명령을 사용합니다.
ign gazebo
다만 ROS 2 패키지명과 Launch 파일 이름은 이미 ros_gz, gz_sim.launch.py 형태로 변경되어 있습니다. 즉, Humble에서는 ign gazebo와 ros_gz라는 두 이름이 함께 사용됩니다.
설치:
sudo apt update
sudo apt install -y ros-humble-ros-gz
sudo apt install ignition-tools -y
ros_gz는 ROS와 Gazebo를 통합하는 메타 패키지입니다.


Gazebo Sim 실행 예:
ign gazebo
빈 월드 실행:
ign gazebo shapes.sdf

ROS 2와 Gazebo Sim 사이의 토픽 연결에는 ros_gz_bridge를 사용합니다. 이 패키지는 ROS와 Gazebo Transport 사이에서 메시지를 교환할 수 있게 해주는 bridge입니다.
예:
ros2 run ros_gz_bridge parameter_bridge \ /clock@rosgraph_msgs/msg/Clock[gz.msgs.Clock
LaserScan bridge 예:
ros2 run ros_gz_bridge parameter_bridge \ /scan@sensor_msgs/msg/LaserScan[gz.msgs.LaserScan
Twist bridge 예:
ros2 run ros_gz_bridge parameter_bridge \ /cmd_vel@geometry_msgs/msg/Twist]gz.msgs.Twist
방향 기호 의미:
기호의미
| @ | 양방향 |
| [ | Gazebo → ROS |
| ] | ROS → Gazebo |
12. 공개 로봇 시뮬레이션 예제 1: TurtleBot3
TurtleBot3는 ROS 2 Gazebo 학습에서 가장 대표적인 공개 로봇입니다. ROBOTIS e-Manual은 ROS 2 Humble과 TurtleBot3 Gazebo Simulation 절차를 제공합니다.
13. 공개 로봇 시뮬레이션 예제 2: Universal Robots UR 로봇
Universal Robots는 ROS 2 드라이버와 Gazebo 시뮬레이션 관련 공개 저장소를 제공합니다. UR 공식 ROS 2 드라이버 문서에서는 실제 로봇 외에도 mock hardware, URSim, Gazebo Classic/GZ Sim 사용 가능성을 언급합니다.
Gazebo Classic 기반 UR 시뮬레이션 저장소도 공개되어 있으며, 해당 저장소는 Gazebo Classic이 ROS 2 Jazzy부터 지원되지 않는 문제 때문에 Humble 중심으로 설명합니다.
ROS 2 Humble용 UR 메타 패키지를 설치하십시오.
sudo apt update
sudo apt install ros-humble-ur -y


공식 UR 문서도 바이너리 설치 방법으로 다음 패키지를 권장합니다.
다음을 실행합니다.
mkdir -p ~/ur_ws/src
cd ~/ur_ws/src
git clone -b humble https://github.com/UniversalRobots/Universal_Robots_ROS2_Gazebo_Simulation.git

의존성 설치:
cd ~/ur_ws rosdep update rosdep install --ignore-src --from-paths src -y -r


빌드:
colcon build --symlink-install source install/setup.bash

실행 방식은 저장소 버전별로 달라질 수 있으므로 README의 launch 명령을 확인하셔야 합니다.
UR 계열 실습에서 핵심은 다음입니다.
항목설명
| ros2_control | 조인트 제어 |
| Joint Trajectory Controller | 로봇 팔 궤적 제어 |
| MoveIt 2 | 경로 계획 |
| Gazebo | 물리 시뮬레이션 |
| RViz2 | 로봇 상태 및 계획 시각화 |
시뮬레이션 실행
ros2 launch ur_simulation_gazebo ur_sim_control.launch.py



테스트 궤적을 실행합니다.
ros2 launch ur_robot_driver test_joint_trajectory_controller.launch.py



14. 공개 로봇 시뮬레이션 예제 3: PX4 드론 + Gazebo
PX4는 드론 개발에서 많이 사용하는 오픈소스 오토파일럿입니다. PX4 문서는 ROS 2와 PX4의 구조를 설명하며, PX4 v1.14부터 ROS 2 연동에 uXRCE-DDS를 사용한다고 안내합니다.
PX4의 Gazebo 문서에서는 Gazebo가 오픈소스 로봇 시뮬레이터이며, 기존 Gazebo Classic을 대체한다고 설명합니다.
대표 흐름:
mkdir -p drone_ws/src
cd drone_ws/src
git clone https://github.com/PX4/PX4-Autopilot.git --recursive
cd PX4-Autopilot
의존성 설치:
bash ./Tools/setup/ubuntu.sh
시뮬레이션 실행 예:
make px4_sitl gz_x500
ROS 2와 연결하려면 보통 다음 구성이 필요합니다.
구성역할
| PX4 SITL | 비행제어기 시뮬레이션 |
| Gazebo | 드론 물리/센서 시뮬레이션 |
| Micro XRCE-DDS Agent | PX4 uORB와 ROS 2 DDS 연결 |
| ROS 2 Node | Offboard 제어, 미션 제어 |
| QGroundControl | 상태 확인 및 수동 조작 |
드론 개발자는 Gazebo 사용법을 단순히 모델 띄우기로 끝내면 안 됩니다. 반드시 /clock, 센서 토픽, 좌표계, PX4 모드 전환, Offboard heartbeat 구조까지 함께 보셔야 합니다.




15.