관리 메뉴

데이터 과학

ROS 2 구현 예제 - Gazebo에서 TurtleBot3 자동 전진 후 정지 본문

인공지능/피지컬 AI

ROS 2 구현 예제 - Gazebo에서 TurtleBot3 자동 전진 후 정지

티에스윤 2026. 7. 20. 23:55
ROS 2 구현 예제 - Gazebo에서 TurtleBot3 자동 전진 후 정지

ROS 2 구현 예제: Gazebo에서 TurtleBot3 자동 전진 후 정지

ROS 2 Python 노드가 /cmd_vel 토픽으로 속도 명령을 발행하여 TurtleBot3를 5초 동안 전진시킨 뒤 정지시키는 예제

ROS 2 Jazzy Python Gazebo TurtleBot3 Burger

1. 구현 구조

move_robot 노드 ↓ /cmd_vel 토픽 ↓ TwistStamped 메시지 ↓ TurtleBot3 Gazebo 플러그인 ↓ 가상 로봇 이동

프로그램은 다음 순서로 동작합니다.

노드 실행 ↓ 0.1초마다 속도 명령 발행 ↓ 선속도 0.15 m/s로 전진 ↓ 5초 경과 ↓ 속도 0.0 m/s 발행 ↓ 로봇 정지

2. ROS 2 환경 적용

source /opt/ros/jazzy/setup.bash

기존 Workspace가 있다면 다음 명령도 실행합니다.

source ~/ros2_ws/install/setup.bash

3. Workspace로 이동

cd ~/ros2_ws/src

Workspace가 없다면 먼저 생성합니다.

mkdir -p ~/ros2_ws/src
cd ~/ros2_ws/src

4. Python 패키지 생성

ros2 pkg create \
  --build-type ament_python \
  --license Apache-2.0 \
  --node-name move_robot \
  --dependencies rclpy geometry_msgs \
  robot_control

생성되는 주요 폴더 구조는 다음과 같습니다.

ros2_ws/
└── src/
    └── robot_control/
        ├── package.xml
        ├── setup.py
        ├── setup.cfg
        ├── resource/
        └── robot_control/
            ├── __init__.py
            └── move_robot.py

5. Python 코드 작성

다음 파일을 엽니다.

nano ~/ros2_ws/src/robot_control/robot_control/move_robot.py

기존 내용을 지우고 다음 코드를 입력합니다.

#!/usr/bin/env python3

import time

import rclpy
from geometry_msgs.msg import TwistStamped
from rclpy.node import Node


class MoveRobot(Node):
    """TurtleBot3를 일정 시간 전진시킨 후 정지시키는 ROS 2 노드."""

    def __init__(self) -> None:
        super().__init__('move_robot')

        self.publisher = self.create_publisher(
            TwistStamped,
            '/cmd_vel',
            10,
        )

        self.timer = self.create_timer(0.1, self.timer_callback)

        self.start_time = time.monotonic()
        self.duration = 5.0
        self.linear_speed = 0.15
        self.finished = False

        self.get_logger().info(
            f'로봇이 {self.linear_speed:.2f} m/s로 '
            f'{self.duration:.1f}초 동안 전진합니다.'
        )

    def timer_callback(self) -> None:
        if self.finished:
            return

        elapsed_time = time.monotonic() - self.start_time

        message = TwistStamped()
        message.header.stamp = self.get_clock().now().to_msg()
        message.header.frame_id = 'base_link'

        if elapsed_time < self.duration:
            message.twist.linear.x = self.linear_speed
            message.twist.angular.z = 0.0

            self.publisher.publish(message)

            self.get_logger().info(
                f'전진 중: {elapsed_time:.1f} / {self.duration:.1f}초',
                throttle_duration_sec=1.0,
            )
        else:
            message.twist.linear.x = 0.0
            message.twist.angular.z = 0.0

            self.publisher.publish(message)
            self.finished = True
            self.timer.cancel()

            self.get_logger().info(
                '5초 주행이 완료되어 로봇을 정지합니다.'
            )


def main(args=None) -> None:
    rclpy.init(args=args)
    node = MoveRobot()

    try:
        while rclpy.ok() and not node.finished:
            rclpy.spin_once(node, timeout_sec=0.1)
    except KeyboardInterrupt:
        node.get_logger().info(
            '사용자가 프로그램을 중단했습니다.'
        )
    finally:
        stop_message = TwistStamped()
        stop_message.header.stamp = (
            node.get_clock().now().to_msg()
        )
        stop_message.header.frame_id = 'base_link'
        stop_message.twist.linear.x = 0.0
        stop_message.twist.angular.z = 0.0

        node.publisher.publish(stop_message)
        node.destroy_node()

        if rclpy.ok():
            rclpy.shutdown()


if __name__ == '__main__':
    main()
Nano 저장 방법: Ctrl + O → Enter → Ctrl + X

6. setup.py 확인

nano ~/ros2_ws/src/robot_control/setup.py

entry_points 부분을 다음과 같이 확인합니다.

entry_points={
    'console_scripts': [
        'move_robot = robot_control.move_robot:main',
    ],
},

7. 의존성 설치

cd ~/ros2_ws
rosdep install --from-paths src --ignore-src -r -y

8. 패키지 빌드

cd ~/ros2_ws
colcon build --symlink-install --packages-select robot_control

정상적으로 빌드되면 다음과 비슷한 결과가 출력됩니다.

Starting >>> robot_control
Finished <<< robot_control

Summary: 1 package finished

빌드된 Workspace를 적용합니다.

source ~/ros2_ws/install/setup.bash

매번 자동 적용하려면 다음 명령을 한 번만 실행합니다.

echo "source ~/ros2_ws/install/setup.bash" >> ~/.bashrc

9. TurtleBot3 Gazebo 실행

터미널 1

source /opt/ros/jazzy/setup.bash
source ~/ros2_ws/install/setup.bash

export TURTLEBOT3_MODEL=burger
ros2 launch turtlebot3_gazebo empty_world.launch.py
Gazebo 빈 공간에 TurtleBot3 Burger가 나타나면 정상입니다.

10. 토픽 확인

source /opt/ros/jazzy/setup.bash
source ~/ros2_ws/install/setup.bash

ros2 topic list

목록에 다음 토픽이 있는지 확인합니다.

/cmd_vel

메시지 형식을 확인합니다.

ros2 topic type /cmd_vel

정상 결과는 다음과 같습니다.

geometry_msgs/msg/TwistStamped

11. 이동 프로그램 실행

터미널 2

source /opt/ros/jazzy/setup.bash
source ~/ros2_ws/install/setup.bash

ros2 run robot_control move_robot

Gazebo의 TurtleBot3가 약 5초 동안 전진한 뒤 정지합니다.

[INFO] 로봇이 0.15 m/s로 5.0초 동안 전진합니다.
[INFO] 전진 중: 1.0 / 5.0초
[INFO] 전진 중: 2.0 / 5.0초
[INFO] 전진 중: 3.0 / 5.0초
[INFO] 전진 중: 4.0 / 5.0초
[INFO] 5초 주행이 완료되어 로봇을 정지합니다.

12. 코드에서 중요한 부분

Publisher 생성

self.publisher = self.create_publisher(
    TwistStamped,
    '/cmd_vel',
    10,
)

/cmd_vel 토픽으로 로봇의 이동 속도를 발행합니다.

전진 속도 설정

message.twist.linear.x = 0.15
message.twist.angular.z = 0.0
  • linear.x: 전진·후진 속도
  • angular.z: 좌우 회전 속도

정지 명령

message.twist.linear.x = 0.0
message.twist.angular.z = 0.0

13. 동작 변경 방법

10초 동안 전진

self.duration = 10.0

더 빠르게 전진

self.linear_speed = 0.25

후진

self.linear_speed = -0.15

왼쪽으로 회전

message.twist.linear.x = 0.0
message.twist.angular.z = 0.5

원을 그리며 이동

message.twist.linear.x = 0.15
message.twist.angular.z = 0.4

14. 실행되지 않을 때 확인

Package 'robot_control' not found

cd ~/ros2_ws
colcon build --symlink-install
source install/setup.bash

/cmd_vel 토픽이 보이지 않는 경우

ros2 topic list

Gazebo 시뮬레이션이 실행 중인지 확인합니다.

로봇이 움직이지 않는 경우

ros2 topic type /cmd_vel

Jazzy 환경에서는 다음 형식이어야 합니다.

geometry_msgs/msg/TwistStamped

노드와 토픽 연결 상태 확인

ros2 node list
ros2 topic info /cmd_vel --verbose
맨 위로 이동
ROS 2 + Gazebo + TurtleBot3 Python 제어 예제