본문으로 바로가기

ROS2 Action Server 만들기 #1

category 강좌/ROS2 2026. 5. 22. 18:37

1. 간단한 Action Server 만들기

 

이제 my_first_package 안에 Action Server 파일을 만듭니다.

my_first_package/
└── my_first_package/
    └── dist_turtle_action_server.py
 

 

먼저 cd ~/ros2_study/src/my_first_package/my_first_package/ 로 이동하여 dist_turtle_action_server.py 파일을 생성합니다.

 

cd ~/ros2_study/src/my_first_package/my_first_package/
touch dist_turtle_action_server.py

 

 

 

기본 구조는 다음과 같습니다. VS Code에서 dist_turtle_action_server.py 파일을 불러와서 아래의 코드를 작성합니다.

 

import rclpy as rp
from rclpy.action import ActionServer
from rclpy.node import Node

from my_first_package_msgs.action import DistTurtle


class DistTurtleServer(Node):

    def __init__(self):
        super().__init__('dist_turtle_action_server')

        self._action_server = ActionServer(
            self,
            DistTurtle,
            'dist_turtle',
            self.execute_callback
        )

    def execute_callback(self, goal_handle):
        goal_handle.succeed()

        result = DistTurtle.Result()
        return result


def main(args=None):
    rp.init(args=args)

    dist_turtle_action_server = DistTurtleServer()
    rp.spin(dist_turtle_action_server)

    dist_turtle_action_server.destroy_node()
    rp.shutdown()


if __name__ == '__main__':
    main()

 

 

 

 

아직 turtlesim을 움직이지는 않고, Action Goal을 받으면 바로 성공 처리 후 빈 Result를 반환하는 구조입니다.

 

이 소스는 다음과 같은 역할을 합니다.

 

Action Client → /dist_turtle로 Goal 전송
Action Server → Goal 수신
Action Server → 성공 처리
Action Server → Result 반환
 

 

즉, 이 코드는 “Action Server가 제대로 실행되고 Goal을 받을 수 있는지” 확인하기 위한 기본 뼈대입니다.

 

 

a. import 부분

 

import rclpy as rp
 

 

ROS 2 Python 라이브러리인 rclpy를 불러옵니다.

여기서는 이름을 짧게 쓰기 위해 rp라는 별칭을 붙였습니다.

 
from rclpy.action import ActionServer
 

 

Action Server를 만들기 위해 필요한 클래스입니다.

ROS 2 Action 통신에서 서버 역할을 하는 객체를 생성할 때 사용합니다.

 
from rclpy.node import Node
 

 

ROS 2에서 노드를 만들기 위한 기본 클래스입니다.
사용자가 직접 노드를 만들 때는 보통 Node를 상속받아 클래스를 작성합니다.

 
from my_first_package_msgs.action import DistTurtle
 

 

직접 만든 Action 정의 파일인 DistTurtle.action을 불러옵니다.

 

예를 들어 DistTurtle.action이 다음 구조라면,

float32 linear_x
float32 angular_z
float32 dist
---
float32 pos_x
float32 pos_y
float32 pos_theta
float32 result_dist
---
float32 remained_dist
 

 

Python에서는 다음 객체들을 사용할 수 있게 됩니다.

 
DistTurtle.Goal
DistTurtle.Result
DistTurtle.Feedback

 

 

b. Action Server 클래스 선언

 
class DistTurtleServer(Node):
 

 

DistTurtleServer라는 클래스를 만듭니다.
이 클래스는 Node를 상속받기 때문에 ROS 2 노드로 동작할 수 있습니다. 즉, 이 클래스 하나가 하나의 ROS 2 노드입니다.

 

 

c. 생성자 함수

 
def __init__(self):
 

클래스 객체가 생성될 때 자동으로 실행되는 함수입니다.

 
super().__init__('dist_turtle_action_server')
 

 

부모 클래스인 Node의 생성자를 호출합니다.
여기서 노드 이름을 지정합니다.

 

노드 이름: dist_turtle_action_server
 

 

실행 후 노드 목록을 확인하면 이 이름으로 보입니다.

 
ros2 node list

 

 

d. ActionServer 생성

 
self._action_server = ActionServer(
    self,
    DistTurtle,
    'dist_turtle',
    self.execute_callback
)
 

 

이 부분이 코드의 핵심입니다. Action Server를 생성합니다.

 

각 인자의 의미는 다음과 같습니다.

 
self
 

 

현재 노드 객체입니다.
즉, 이 Action Server가 DistTurtleServer 노드 안에서 동작한다는 뜻입니다.

 
DistTurtle
 

 

사용할 Action 타입입니다.
앞에서 import한 DistTurtle.action 정의를 사용합니다.

 
'dist_turtle'
 

 

Action 이름입니다.
클라이언트는 이 이름으로 Goal을 보냅니다.

 

실행할 때는 다음처럼 사용합니다.

 
ros2 action send_goal /dist_turtle my_first_package_msgs/action/DistTurtle "{linear_x: 0.0, angular_z: 0.0, dist: 0.0}"
 

 

주의할 점은 코드에서는 'dist_turtle'이라고 쓰지만, 명령어에서는 보통 앞에 /를 붙여 /dist_turtle로 사용합니다.

 
self.execute_callback
 

 

Goal이 들어왔을 때 실행할 함수입니다.
즉, Action Client가 Goal을 보내면 execute_callback() 함수가 호출됩니다.

 

 

e. execute_callback 함수

 
def execute_callback(self, goal_handle):
 

 

Action Server가 Goal을 받으면 실행되는 callback 함수입니다.

여기서 goal_handle은 클라이언트가 보낸 Goal을 관리하는 객체입니다. 일반적으로 goal_handle이라는 이름을 많이 사용하지만 사용자가 다른 이름을 사용해도 됩니다.

 

Goal 요청값 확인, 성공 처리, 실패 처리, Feedback 발행 등을 할 수 있습니다.

 

예를 들어 사용자가 보낸 값을 확인하려면 다음처럼 접근할 수 있습니다.

 
goal_handle.request.linear_x
goal_handle.request.angular_z
goal_handle.request.dist
 

 

현재 코드에서는 요청값을 사용하지 않고 바로 성공 처리합니다.

 

 

f. Goal 성공 처리

 
goal_handle.succeed()
 

 

현재 Goal을 성공 상태로 바꿉니다.

 

Action은 단순히 Result만 반환하는 것이 아니라, Goal의 상태도 함께 관리합니다.

 

대표 상태는 다음과 같습니다.

                        상태                                                                   의미
succeed() Goal이 성공적으로 완료됨
abort() Goal 수행 실패
canceled() Goal이 취소됨

 

현재 코드는 아무 작업도 하지 않고 바로 성공 처리하므로, 클라이언트에서는 SUCCEEDED 상태를 받게 됩니다.

 

 

g. Result 객체 생성

 
result = DistTurtle.Result()
 

 

Action 결과를 담을 객체를 생성합니다.

 

만약 DistTurtle.action의 Result가 다음과 같다면,

float32 pos_x
float32 pos_y
float32 pos_theta
float32 result_dist
 

 

원래는 아래처럼 값을 넣어주는 것이 맞습니다.

 
result.pos_x = 0.0
result.pos_y = 0.0
result.pos_theta = 0.0
result.result_dist = 0.0
 

 

하지만 현재 코드에서는 값을 넣지 않았습니다.

 

그래도 기본값 0.0으로 반환됩니다.

 

 

h. Result 반환

 
return result
 

 

Action Client에게 Result를 반환합니다.

 

즉, 전체 callback 흐름은 다음과 같습니다.

Goal 수신
→ 성공 처리
→ Result 객체 생성
→ Result 반환

 

 

i. main 함수

 
def main(args=None):
 

ROS 2 노드를 실행하기 위한 진입 함수입니다.

 
rp.init(args=args)
 

 

ROS 2 Python 시스템을 초기화합니다.
노드를 만들기 전에 반드시 실행해야 합니다.

 
dist_turtle_action_server = DistTurtleServer()
 

 

앞에서 만든 Action Server 노드를 생성합니다.
이 순간 __init__()이 실행되고, Action Server도 함께 생성됩니다.

 
rp.spin(dist_turtle_action_server)
 

 

노드를 계속 실행 상태로 유지합니다.
이 코드가 있어야 Action Client의 Goal 요청을 기다릴 수 있습니다.

 

쉽게 말하면 다음 상태가 됩니다.

서버 실행 중...
Goal 들어오면 execute_callback 실행
 
 
dist_turtle_action_server.destroy_node()
 

 

노드를 종료할 때 리소스를 정리합니다.

 
rp.shutdown()
 

 

ROS 2 Python 시스템을 종료합니다.

 

 

j. Python 실행 진입점

 
if __name__ == '__main__':
    main()
 

이 파일을 직접 실행했을 때 main() 함수를 호출합니다.

 

예를 들어 다음처럼 직접 실행하면,

 
python3 dist_turtle_action_server.py
 

 

main()이 실행됩니다. 직접 실행도 가능합니다.

 

서버를 빌드합니다.

 

cd ~/ros2_study
colcon build
source install/setup.bash

또는 

sl

ros2 run my_first_package dist_turtle_action_server

 

 

 

다른 터미널에서 Feedback 옵션을 붙여 Goal을 보냅니다.

 

ros2 action send_goal --feedback /dist_turtle my_first_package_msgs/action/DistTurtle "{linear_x: 0, angular_z: 0, dist: 0}"

 

 

실행결과를 확인합니다.

 

 

 

ROS 2에서는 보통 setup.py에 entry point를 등록한 뒤 아래처럼 실행합니다.

 
ros2 run my_first_package dist_turtle_action_server

 

 

ROS 2에서 Python 노드를 ros2 run으로 실행하려면 setup.py의 entry_points에 등록해야 합니다.

 

entry_points={
    'console_scripts': [
        'dist_turtle_action_server = my_first_package.dist_turtle_action_server:main',
    ],
},

 

 

 

등록 후 다시 빌드합니다. 그리고 환경을 다시 적용합니다.

 

cd ~/ros2_study
colcon build
source install/setup.bash

또는

sl

 

 

 

서버를 실행합니다.

 

ros2 run my_first_package dist_turtle_action_server

 

 

 


새 터미널을 열고 같은 ROS 2 환경을 적용한 뒤 Action Goal을 보냅니다.

 

ros2 action send_goal /dist_turtle my_first_package_msgs/action/DistTurtle "{linear_x: 0, angular_z: 0, dist: 0}"

 

 

정상 동작하면 Goal이 수락되고 Result가 출력됩니다.

 

 

여기까지 성공했다면 Action Server의 기본 연결은 완료된 것입니다.

 

 

 

파일 압축 명령 예 :

tar zcvf ros2_study_260522.tar.gz src


파일 압축 해제 명령 예 :

tar zxvf ros2_study_260522.tar.gz

 

 

 

2026년 5얼 22일까지 작업한 파일 :

ros2_study_260522.tar.gz
0.01MB

728x90
728x90

'강좌 > ROS2' 카테고리의 다른 글

2일차 강의  (0) 2026.05.23
1일차 강의  (0) 2026.05.22
로봇 개발자를 위한 Python 기초 교육 #1  (0) 2026.05.22
4일차 강의  (0) 2026.05.21
서비스 서버 만들기  (0) 2026.05.21