액션(Acion) 메시지 통신은 요청 처리 후 응답까지 오랜 시간이 걸리고 중간 결괏값이 필요한 경우에 사용되는 메시지 통신 방식이다. 이는 서비스와 많이 비슷한데 요청과 응답에 해당하는 목표(goal)와 결과(result)가 있다. 여기서 피드백(feedback)이 추가되었다.
액션(action)은 아래그림의 Node A - Node B
처럼 비동기식+동기식 양방향 메시지 송수신 방식으로 액션 목표 (goal)를 지정하는 Action Client과 액션 목표를 받아 특정 태스크를 수행하면서 중간 결괏값에 해당되는 액션 피드백(feedback)과 최종 결괏값에 해당되는 액션 결과(result)를 전송하는 Action Server 간의 통신이라고 볼 수 있다. 이는 ROS 1의 액션 컨셉과 동일하다.
추가로 액션의 구현 방식을 더 자세히 살펴보면 아래 그림과 같이 토픽과 서비스의 혼합이라고 볼 수 있는데 ROS2에서는 액션 목표(goal), 액션 결과(result), 액션 피드백(feedback)은 토픽과 서비스가 혼합 되어 있다.
즉, Action client
는 Service Client 3개와 Topic Subscriber 2개로 구성되어 있으며, Action Server
는 Service Server 3개와 Topic Publisher 2개로 구성되어 있다.
액션의 데이터 타입은 msg
및 srv
인터페이스의 변형으로 action
인터페이스라고 한다.
액션도 저번 서비스와 마찬가지로 turtlesim
노드와 teleop_key
노드를 이용하여 실습하겠다.
$ ros2 run turtlesim turtlesim_node
$ ros2 run turtlesim turtle_teleop_key
Reading from keyboard
---------------------------
Use arrow keys to move the turtle.
Use G|B|V|C|D|E|R|T keys to rotate to absolute orientations. 'F' to cancel a rotation.
'Q' to quit.
지금까지는 teleop_turtle 노드가 실행된 터미널 창에서 ← ↑ ↓ →
키와 같이 화살표 키를 눌러 거북이를 움직여봤는데 이번에는 G|B|V|C|D|E|R|T
키를 사용해보자.
이 키들은 각 거북이들의 rotate_absolute 액션을 수행함에 있어서 액션의 목표값을 전달하는 목적으로 사용된다.
F
키를 중심으로 주위의 8개의 버튼을 사용하는 것으로 아래 그림과 같이 각 버튼은 거북이를 절대 각도로 회전하도록 목표 값이 설정되어 있다. 그리고 F
키를 누르면 전달한 목표 값을 취소하여 동작을 바로 멈추게 된다.
여기서 G 키는 시계 방향 3시를 가르키는 theta 값인 0.0 값에 해당되고 rotate_absolute 액션의 기준 각도가 된다. 다른 키는 위치별로 0.7854 radian 값씩 정회전 방향(반시계 방향)으로 각 각도 값이 할당되어 있다.
예를 들어 R 키를 누르면 1.5708 radian 목표 값이 전달되어 거북이는 12시 방향으로 회전하게 된다. 각 키에 할당된 라디안 값은 아래 사진을 확인하면 자세히 살펴볼 수 있다.
각 실행된 노드의 액션 정보를 확인하기 위해서는 노드 정보(ros2 node info) 명령어를 사용하는데 액션부분만 발췌하면 아래와 같다.
즉, turtlesim 노드는 Action Server
역할을 하며 turtlesim/action/RotateAbsolute
라는 action 인터페이스를 사용하는 turtle1/rotate_absolute
이라는 이름의 액션 서버임을 확인 할 수 있다. teleop_turtle
노드는 turtle1/rotate_absolute
의 액션의 Action Client
역할을 하고 있다.
$ ros2 node info /turtlesim
/turtlesim
(생략)
Action Servers:
/turtle1/rotate_absolute: turtlesim/action/RotateAbsolute
Action Clients:
$ ros2 node info /teleop_turtle
/teleop_turtle
(생략)
Action Servers:
Action Clients:
/turtle1/rotate_absolute: turtlesim/action/RotateAbsolute
여기에 추가하자면 rotate_absolute
액션은 하기와 같이 send_goal, cancel_goal, status, feedback_goal, get_result 의 5가지로 더 세분화되어 있다.
/turtle1/rotate_absolute/_action/send_goal: turtlesim/action/RotateAbsolute_SendGoal
/turtle1/rotate_absolute/_action/cancel_goal: action_msgs/srv/CancelGoal
/turtle1/rotate_absolute/_action/status: action_msgs/msg/GoalStatusArray
/turtle1/rotate_absolute/_action/feedback: turtlesim/action/RotateAbsolute_FeedbackMessage
/turtle1/rotate_absolute/_action/get_result: turtlesim/action/RotateAbsolute_GetResult
액션 정보를 확인하는 방법으로는 다음과 같다.
$ ros2 action list -t
/turtle1/rotate_absolute [turtlesim/action/RotateAbsolute]
검색된 액션 목록의 더 자세한 정보를 확인하기 위해서는 액션 정보 명령어를 이용하면 되는데 그 결과로 다음과 같은 액션 이름과 해당 액션의 서버 및 클라이언트 노드 이름 및 갯수를 표시해준다.
$ ros2 action info /turtle1/rotate_absolute
Action: /turtle1/rotate_absolute
Action clients: 1
/teleop_turtle
Action servers: 1
/turtlesim
액션 목표(action goal)를 전달하기위해서는 'ros2 action send_goal' 명령어를 통하여 액션 목표를 전달해보겠다. 이 명령어는 다음과 같다.
$ ros2 action send_goal <액션 이름> <액션 형태> "<목표 값>"
↓
$ ros2 action send_goal <action_name> <action_type> "<values>"
예를 들어 거북이를 12시 방향인 theta: 1.5708 값을 목표로 주게되면 그림 5와 같이 이동하게 되며 아래 처럼 전달한 목표 값과 액션 목표의 UID(Unique ID), 결괏값으로 이동 시작 위치로의 변위 값인 delta를 결과로 보여주며 마지막으로 상태를 표시하게 된다.
ros2 action send_goal /turtle1/rotate_absolute turtlesim/action/RotateAbsolute "{theta: 1.5708}"
Waiting for an action server to become available...
Sending goal:
theta: 1.5708
Goal accepted with ID: b991078e96324fc994752b01bc896f49
Result:
delta: -1.5520002841949463
Goal finished with status: SUCCEEDED
위 명령어는 피드백이 포함되어 있지 않았는데 피드백을 표현하기위해서는 --feedback
옵션을 추가하면 된다.
$ ros2 action send_goal /turtle1/rotate_absolute turtlesim/action/RotateAbsolute "{theta: -1.5708}" --feedback
Waiting for an action server to become available...
Sending goal:
theta: -1.5708
Goal accepted with ID: ad7dc695c07c499782d3ad024fa0f3d2
Feedback:
remaining: -3.127622127532959
Feedback:
remaining: -3.111621856689453
Feedback:
remaining: -3.0956220626831055
(생략)
Feedback:
remaining: -0.03962135314941406
Feedback:
remaining: -0.023621320724487305
Feedback:
remaining: -0.007621288299560547
Result:
delta: 3.1040005683898926
Goal finished with status: SUCCEEDED
토픽 메시지 인터페이스는 msg
, 서비스 메시지 인터페이스는 srv
라는것을 배웠다. 액션도 마찬가지로 별도의 인터페이스를 갖고있는데 이를 액션 인터페이스라고 한다.
/turtle1/rotate_absolute
액션을 예시로 보면 /turtle1/rotate_absolute
액션은 turtlesim/action/RotateAbsolute
인터페이스 타입을 갖고있고, float32
형태의 theta, delta, remaining
라는 세개의 데이터가 있음을 알 수 있다. 여기서 서비스와 마찬가지로 ---
이라는 구분자를 사용하여 액션 목표(goal), 액션 결과(result), 액션 피드백(feedback)으로 나누어 사용하게된다. 즉, theta 는 액션 목표, delta는 액션 결과, remaining 은 액션 피드백에 해당한다.
$ ros2 interface show turtlesim/action/RotateAbsolute.action
# The desired heading in radians
float32 theta
---
# The angular displacement in radians to the starting position
float32 delta
---
# The remaining rotation in radians
float32 remaining
이상으로 액션에 대해 알아보았다. 지금까지 ROS2 컨셉 중 매우 중요한 노드, 토픽, 서비스, 액션을 다루었는데 다음에는 이 3가지를 비교 해볼 예정이다.