10. action, action server, action client ์ค๋ช
์ด๋ฒ ์๊ฐ์๋ ๋๋์ด ROS์ ํต์ ๋ฉ์ปค๋์ฆ ๋ง์ง๋ง์ผ๋ก action์ ๋ํด ๋ฐฐ์๋ณด๊ฒ ์ต๋๋ค.
์์ ๋ฅผ ์ดํด๋ณด์์ฃ !!
๋ฏธ๋ก ํ์ถ
$ roslaunch gcamp_gazebo maze_world.launch
๋ณธ ์์ ๋ ์ค๋ช ์ด ์ด์ง ํ์ํฉ๋๋ค.
- ๋ก๋ด์ ์ด๋ก ๋ฐ์ค๊ฐ ์๋ ํ์ถ๊ตฌ๊น์ง ์ด๋์์ผ์ผ ํฉ๋๋ค.
- ๋ก๋ด์ด ํ์ ํ๋ ๋ฐฉํฅ์ ์ฌ์ง๊ณผ ๊ฐ์ต๋๋ค.
- ๋ก๋ด์ ํ์ ํ ๋ค, ์ง๋ topic ์์ ์ฒ๋ผ ๋ฒฝ๊ณผ ์ผ์ ํ ๊ฑฐ๋ฆฌ๋ฅผ ๋๊ณ ๋ฉ์ถ๋๋ก ๋์ด ์์ต๋๋ค.
2, 1, 0, ... ์ฒ๋ผ ๋ก๋ด์๊ฒ ์ด๋ํด์ผ ํ ๋ฐฉํฅ์ ์ค ๋ณด์ธ์.
๊ทธ๋ผ action server & client๋ฅผ ์คํ์์ผ ๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
- maze_action_server
# ์ ํฐ๋ฏธ๋
$ rosrun action_tutorial maze_action_server.py
==== MazeActionClass Constructed ====
==== Waiting for Client Goal... ====
- maze_action_client
-
์ซ์๋ฅผ ๋ชจ๋ ์ ๋ ฅํ ๋ค, ๋๋ด๊ณ ์ถ๋ค๋ฉด
stop
์ ์ ๋ ฅํฉ๋๋ค.
# ์ ํฐ๋ฏธ๋
$ rosrun action_tutorial maze_action_client.py
[INFO] [1610254457.453111, 322.000000]: Action Server Found.../maze_action_server
Enter numbers [or stop] :
2
1
stop
('Your sequence list : ', [2, 1])
[INFO] [1610254462.019717, 326.139000]: State Result from Server : 0
feedback_msg: "Turning to Down"
feedback_msg: "Moving Forward ..."
feedback_msg: "Turning to Right"
feedback_msg: "Moving Forward ..."
[...]
# server ์ฐฝ์๋ ์ง์์ ์ผ๋ก ์ด๋ฌํ ๋ด์ฉ๋ค์ด ๋์ฌ ๊ฒ์
๋๋ค.
==== Maze Action Server Executing ====
Turning Sequence : 2
Turning Sequence : 1
[...]
์ฃผ์ด์ง ๋ช ๋ น์ ๋ชจ๋ ์คํํ ๋ค์๋ ๋ก๋ด์ด ์ด๋ก ๋ฐ์ค์ ๋๋ฌํ๊ธฐ ๋ชปํ๋ฉด, server ํฐ๋ฏธ๋์์ ์คํจํ๋ค๋ ๋นจ๊ฐ ๊ธ์๊ฐ ๋์ค๊ฒ ๋ฉ๋๋ค.
Action ์ค๋ช
์ด์ service ๊ฐ์์์ ๋ค์๊ณผ ๊ฐ์ ๋ถ๋ถ์ด ํน์ ๊ธฐ์ต๋์๋์?
A topic์ด ์คํ๋๋ ๋์, ๋ค๋ฅธ B topic๋ ๊ฐ์ด ์คํ๋ ์ ์์ต๋๋ค. ๋ฐ๋ฉด, service๋ ํ์ฌ ์งํ์ค์ธ service์ request๊ฐ ์ฒ๋ฆฌ๋๋ ๋์, ๋ค๋ฅธ service๋ ๊ธฐ๋ค๋ฆฌ๊ณ ์์ด์ผ ํฉ๋๋ค.
action์ service์ ๋น์ทํฉ๋๋ค. ํ์ง๋ง ํฐ ์ฐจ์ด์ ์ด ์๋๋ฐ์.
๊ฒฐ๋ก ๋ถํฐ ๋ง์๋๋ฆฌ์๋ฉด,
- action client๋ action server๊ฐ response๋ฅผ ๋ณด๋ด๊ธฐ ์ ๊น์ง ๊ธฐ๋ค๋ฆฌ์ง ์๊ณ , ๋ค๋ฅธ ์ผ์ ํ ์ ์์ต๋๋ค!
- action client์ request๋ฅผ ๋ณด๋ธ ๋ค์๋ ์ง์์ ์ผ๋ก feedback์ ๋ฐ์ ์ ์์ต๋๋ค!!
image from : The Construct
์ฌ์ง๊ณผ ๊ฐ์ด client์ server๊ฐ ์ฃผ๊ณ ๋ฐ๋ ๋ด์ฉ์ ํฌ๊ฒ 5๊ฐ์ง๊ฐ ์์ต๋๋ค. ๋๋ถ์ด ์ด๋ค์ด ์ ๊ฐ๋๋ ์์๋ฅผ ์ดํด๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
- client โ server goal (service request์ ์ ์ฌํฉ๋๋ค.)
- server โ client feedback
- client โ server cancel
- server โ client status
- server โ client result
ํ๋์ฉ ์ดํด๋ณด๊ฒ ์ต๋๋ค. ๐๐
- client โ server goal : ์ด์ service resquest์ ์ ์ฌํ๊ฒ server๋ก ์์ฒญ์ ํฉ๋๋ค.
- server โ client feedback : goal์ ์ผ๋ง๋ ๋๋ฌํ๋์ง๋ฑ์ ์ง์์ ์ธ ํผ๋๋ฐฑ์ ์ฃผ๊ณ ๋ฐ์ต๋๋ค.
- client โ server cancel : feedback์ ์ง์ผ๋ณด๋ client๊ฐ ๋ถ๋์ดํ๊ฒ goal์ ์ทจ์ํ๊ณ ์ถ์ ๊ฒฝ์ฐ cancel์ ์์ฒญํ ์ ์์ต๋๋ค.
- server โ client status : Server๊ฐ ์์ ์ค์ธ ๋์ client๊ฐ ๋ค๋ฅธ ์ผ์ ํ ์ ์๋ค๊ณ ๋งํ์ฃ ? ๊ทธ๋ฌ๊ธฐ ์ํด์๋ server์ ์ํ, status๋ฅผ ์์์ผ ํ ๊ฒ์ ๋๋ค.
- server โ client result : ๋ชจ๋ ์์ฒญ๋ ์์ ์ด ์๋ฃ๋๋ฉด, server๋ result๋ฅผ ๋ฐํํฉ๋๋ค.
๊ทธ๋์, action server๋ฅผ ์คํ์ํจ ๋ค, rostopic list
๋ฅผ
์คํ์์ผ๋ณด๋ฉด, ๋ค์๊ณผ ๊ฐ์ด ๊ธฐ๋ณธ 5๊ฐ์ ๋ฆฌ์คํธ๋ฅผ ํ์ธํ ์ ์์ต๋๋ค.
$ rostopic list
...
/maze_action_server/cancel
/maze_action_server/feedback
/maze_action_server/goal
/maze_action_server/result
/maze_action_server/status
topic์ msg, service์ srv๊ฐ ์๋ฏ์ด, action์๋ ์ฃผ๊ณ ๋ฐ๋ ๋ฐ์ดํฐ ํ์์ด ์์ต๋๋ค. ๋ฐ๋ก action์ ๋๋ค.
์ด action์ goal, result, feedback์ผ๋ก ๊ตฌ์ฑ๋์ด ์์ผ๋ฉฐ, service์ ๋น์ทํ๊ฒ ---๋ก ๊ตฌ๋ถ๋ฉ๋๋ค.
- Fibonacci.action
#goal definition
int32 order
---
#result definition
int32[] sequence
---
#feedback
int32[] sequence
ํ์์ service์ ๋น์ทํ๋ฐ, ์ค์ ๋ก ์กฐํํ ๋์๋
rosmsg
๋ก ์กฐํํ๋, ํผ๋ํ์ง ์๋๋ก ์ฃผ์ํฉ์๋ค.
$ rosmsg list | grep Fibonacci
actionlib_tutorials/FibonacciAction
actionlib_tutorials/FibonacciActionFeedback
actionlib_tutorials/FibonacciActionGoal
actionlib_tutorials/FibonacciActionResult
actionlib_tutorials/FibonacciFeedback
actionlib_tutorials/FibonacciGoal
actionlib_tutorials/FibonacciResult
์ฌ๊ธฐ์ ์๋ฌธ์ด ์๊ธฐ๋๋ฐ์, ๋ถ๋ช , action์ ๋ค์ฏ ์ข ๋ฅ์ ์ฃผ๊ณ ๋ฐ๋ ํ์์ด ์๋ค๊ณ ํ๋๋ฐ, ์์ ํ์ผ์๋ ์ธ๊ฐ์ง๋ง ์ ํ ์์ต๋๋คโ๏ธ
๋๋จธ์ง cancel
, status
๋ action์์
์ง์ ํด๋ ๊ณ ์ ๊ฐ์ด ์์ต๋๋ค. status์ ๋ํด์ ์ดํด๋ด
์๋ค.
uint8 PENDING = 0 # The goal has yet to be processed by the action server
uint8 ACTIVE = 1 # The goal is currently being processed by the action server
uint8 PREEMPTED = 2 # The goal received a cancel request after it started executing
# and has since completed its execution (Terminal State)
uint8 SUCCEEDED = 3 # The goal was achieved successfully by the action server (Terminal State)
uint8 ABORTED = 4 # The goal was aborted during execution by the action server due
# to some failure (Terminal State)
uint8 REJECTED = 5 # The goal was rejected by the action server without being processed,
# because the goal was unattainable or invalid (Terminal State)
uint8 PREEMPTING = 6 # The goal received a cancel request after it started executing
# and has not yet completed execution
uint8 RECALLING = 7 # The goal received a cancel request before it started executing,
# but the action server has not yet confirmed that the goal is canceled
uint8 RECALLED = 8 # The goal received a cancel request before it started executing
# and was successfully cancelled (Terminal State)
uint8 LOST = 9 # An action client can determine that a goal is LOST. This should not be
# sent over the wire by an action server
#Allow for the user to associate a string with GoalStatus for debugging
string t
์์ ๋ฅผ ์คํํ๊ธฐ ์ ์, ์์ ๋ฏธ๋ก์ฐพ๊ธฐ ์์ ๋ฅผ ์ดํดํ๊ธฐ์๋ ์ ํ ์ง์๋ค์ด ์ ์ง ์๊ธฐ์, ์ด๋ฒ ๊ฐ์์์๋ wiki.ros.org/์์ ์ ๊ณตํ๋ ์์๋ค์ ์ฐ์ ์ดํด๋ณธ ๋ค์, ๋ค์ ๊ฐ์์์ ๋ฏธ๋ก์ฐพ๊ธฐ ์์ ์ฝ๋๋ฅผ ์ดํด๋ณด๊ณ ์ ํฉ๋๋ค.
OpenCV, ํ์ด์ฌ ํจํค์ง์ Class, Quaternion๊ณผ Euler Angle์
๋ํ ์ง์์ด ํ์ํฉ๋๋ค.
๊ฐ๋จ ์์ ์คํ
$ roslaunch action_tutorial fibonacci_server.launch
[INFO] [1610620215.219295]: Fibonacci Action Server Executing, creating fibonacci sequence of order 20 with seeds 0, 1
[INFO] [1610620234.220412]: Succeeded calculating the Fibonacci
# ์ ํฐ๋ฏธ๋ ์คํ
$ rosrun action_tutorial fibonacci_action_client.py
==== Sending Goal to Server ====
sequence: [0, 1, 1]
sequence: [0, 1, 1, 2]
sequence: [0, 1, 1, 2, 3]
sequence: [0, 1, 1, 2, 3, 5]
sequence: [0, 1, 1, 2, 3, 5, 8]
sequence: [0, 1, 1, 2, 3, 5, 8, 13]
sequence: [0, 1, 1, 2, 3, 5, 8, 13, 21]
(...)
์ ์์ ๋ ํผ๋ณด๋์น ์์ด์ action์ผ๋ก ๊ตฌํํ ๊ฒ์ ๋๋ค.
- ํผ๋ณด๋์น ์์ด์ด๋?
image from : wiki
์ฌ์ค ํผ๋ณด๋์น ์์ด์ด ์ค์ํ๊ธฐ๋ณด๋ค action server & client์ ๋ํด ๋ฐฐ์ฐ๋ ๊ฒ์ด ๋ชฉ์ ์ด๊ธฐ ๋๋ฌธ์, ์งง๊ฒ ๋์ด๊ฐ๊ฒ ์ต๋๋ค. client ๋ถ๋ถ๋ถํฐ ๋ณด๊ฒ ์ต๋๋ค!!
Fibonacci Action Client
#! /usr/bin/env python
"""
Fibonacci Action Client
referenced from wiki.ros.org
url: http://wiki.ros.org/actionlib_tutorials/Tutorials/Writing%20a%20Simple%20Action%20Client%20%28Python%29
"""
import rospy
import actionlib
from actionlib_tutorials.msg import FibonacciAction, FibonacciGoal
# Action Status (primitive)
PENDING = 0
ACTIVE = 1
PREEMPTED = 2
SUCCEEDED = 3
ABORTED = 4
REJECTED = 5
PREEMPTING = 6
RECALLING = 7
RECALLED = 8
LOST = 9
def fb_callback(feedback):
print(feedback)
rospy.init_node("fibonacci_client")
rate = rospy.Rate(5)
client = actionlib.SimpleActionClient("fibonacci_action_server", FibonacciAction)
client.wait_for_server()
goal = FibonacciGoal()
goal.order = 20
print("==== Sending Goal to Server ====")
client.send_goal(goal, feedback_cb=fb_callback)
state_result = client.get_state()
while state_result < PREEMPTED:
# Doing Stuff while waiting for the Server to give a result....
rate.sleep()
state_result = client.get_state()
if state_result == SUCCEEDED:
rospy.logwarn("Action Done State Result : " + str(client.get_result()))
else:
rospy.logerr("Something went wrong, result state : " + str(state_result))
ํ๋์ฉ ์ฐจ๊ทผ์ฐจ๊ทผ ์ง์ด๊ฐ๊ฒ ์ต๋๋ค. action client๋ service client์ ์์ฃผ ์ ์ฌํ๊ธฐ ๋๋ฌธ์, ์ฝ๊ฒ ์ดํดํ ์ ์์ต๋๋ค.
- import ๋ถ๋ถ
import rospy
import actionlib
from actionlib_tutorials.msg import FibonacciAction, FibonacciGoal
client๊ฐ ํ์ํ ๊ฒ์ Goal์ด๋ฉฐ ์์ ๊ฐ์ด [ํด๋น-action-์ด๋ฆ]Goal๋ก import ํ ์ ์์ต๋๋ค.
from service_tutorial.srv import ControlTurningMessage, ControlTurningMessageRequest
- action Goal status
# Action Status (primitive)
PENDING = 0
ACTIVE = 1
PREEMPTED = 2
SUCCEEDED = 3
ABORTED = 4
REJECTED = 5
PREEMPTING = 6
RECALLING = 7
RECALLED = 8
LOST = 9
์์ ๋ฐฐ์ ๋ ๋ฐ์ ๊ฐ์ด GoalStatus๋ฅผ ๋ณด๊ธฐ ์ฝ๊ฒ ์์๋ก ์ ์ํด ๋์์ต๋๋ค.
- client ์์ฑ, wait_for_server
rospy.init_node("fibonacci_client")
rate = rospy.Rate(5)
client = actionlib.SimpleActionClient("fibonacci_action_server", FibonacciAction)
client.wait_for_server()
- actionlib.SimpleActionClient("server-name", "action-type-name")
Action Client๋ ์์ ๊ฐ์ด ์์ฑํ๋ฉฐ, server์ ์ด๋ฆ๊ณผ ๋์ผํด์ผ ํจ์ ์ ์ํฉ๋๋ค!
service client์ ๋ง์ฐฌ๊ฐ์ง๋ก, server๊ฐ ์คํ๋ ๋๊น์ง ๊ธฐ๋ค๋ ค์ผ ํ๋ฉฐ ๊ตฌํ์ ์์ ๊ฐ์ต๋๋ค.
rospy.wait_for_service("/control_robot_angle")
service_client = rospy.ServiceProxy("/control_robot_angle", ControlTurningMessage)
- send_goal, feedback
def fb_callback(feedback):
print(feedback)
(...)
goal = FibonacciGoal()
goal.order = 20
print("==== Sending Goal to Server ====")
client.send_goal(goal, feedback_cb=fb_callback)
์ฌ๊ธฐ๊น์ง๋ service์ ์์ฃผ ์ ์ฌํ์ง์??
- Fibonacci.action
#goal definition
int32 order
---
#result definition
int32[] sequence
---
#feedback
int32[] sequence
- ์ค์!! Action๋ง์ ๊ธฐ๋ฅ!!
while state_result < PREEMPTED:
# Doing Stuff while waiting for the Server to give a result....
rate.sleep()
state_result = client.get_state()
if state_result == SUCCEEDED:
rospy.logwarn("Action Done Result : " + str(client.get_result()))
else:
rospy.logerr("Something went wrong, result state : " + str(state_result))
# Action Status (primitive)
PENDING = 0
ACTIVE = 1
PREEMPTED = 2
SUCCEEDED = 3
ABORTED = 4
REJECTED = 5
PREEMPTING = 6
RECALLING = 7
RECALLED = 8
LOST = 9
action์ ์์ ๊ฐ์ด server๋ก๋ถํฐ ์์ง ์์ฒญ์ ์คํ์ค์ด๋ผ๋ ์ํ๊ฐ ๋์์ค๋ฉด, ๊ทธ๋์ ๋ค๋ฅธ ์ผ์ ํ๋๋ก ํ ์๊ฐ ์์ต๋๋ค!! ํ ์์ ์์๋ ํฐ ์์ ์ ํ ๋นํ์ง ์์์ง๋ง, ์ค์ ๋ก๋ด์ ๋ง๋ค๋ค๋ณด๋ฉด ์ ๋ง ์ ์ฉํ ๊ธฐ๋ฅ์ผ ๊ฒ์ ๋๋ค. ๐๐๐
๋ค์์ผ๋ก Action Server
์ฝ๋๋ฅผ ์ดํด๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
Fibonacci Action Server
#! /usr/bin/env python
"""
Fibonacci Action Server
referenced from wiki.ros.org
url: http://wiki.ros.org/actionlib_tutorials/Tutorials/Writing%20a%20Simple%20Action%20Server%20using%20the%20Execute%20Callback%20%28Python%29#Compiling
"""
import rospy
import actionlib
from actionlib_tutorials.msg import FibonacciFeedback, FibonacciResult, FibonacciAction
g_feedback = FibonacciFeedback()
g_result = FibonacciResult()
def execute_cb(goal):
r = rospy.Rate(5)
success = True
g_feedback.sequence = []
g_feedback.sequence.append(0)
g_feedback.sequence.append(1)
rospy.loginfo(
"Fibonacci Action Server Executing, creating fibonacci sequence of order %i with seeds %i, %i"
% (goal.order, g_feedback.sequence[0], g_feedback.sequence[1])
)
for i in range(1, goal.order):
if _as.is_preempt_requested():
rospy.loginfo("The goal has been cancelled/preempted")
_as.set_preempted()
success = False
break
g_feedback.sequence.append(g_feedback.sequence[i] + g_feedback.sequence[i - 1])
_as.publish_feedback(g_feedback)
r.sleep()
if success:
g_result.sequence = g_feedback.sequence
rospy.loginfo("Succeeded calculating the Fibonacci")
_as.set_succeeded(g_result)
rospy.init_node("fibonacci")
_as = actionlib.SimpleActionServer(
"fibonacci_action_server", FibonacciAction, execute_cb, False
)
_as.start()
print("==== Waiting for Client Goal... ====")
rospy.spin()
goal_callback ๋ถ๋ถ์ด ์๋นํ ๊ธธ์ง์? ์ฐจ๊ทผ์ฐจ๊ทผ ๋ฏ์ด๋ด ์๋ค!!
- import, global variables
import rospy
import actionlib
from actionlib_tutorials.msg import FibonacciFeedback, FibonacciResult, FibonacciAction
g_feedback = FibonacciFeedback()
g_result = FibonacciResult()
server๋จ์๋ Feedback, Result๊ฐ ํ์ํฉ๋๋ค.
callback์์์๋ ์ฌ์ฉํ๊ธฐ ์ํด ์ ์ญ ๋ณ์๋ก ํ ๋นํ์์ต๋๋ค.
- main
rospy.init_node("fibonacci")
_as = actionlib.SimpleActionServer(
"fibonacci_action_server", FibonacciAction, execute_cb, False
)
_as.start()
print("==== Waiting for Client Goal... ====")
rospy.spin()
actionlib.SimpleActionServer( "server-name", "action-type-name", "execute_cb", "auto_start")
Action Server๋ ์์ ๊ฐ์ด ์์ฑํ๋ฉฐ, ์ฒซ๋ฒ์งธ ์ธ์๋ Client ์์ฑ ์์ ๋์ผํ๊ฒ ๊ธฐ์ ํด์ผ ์ ๋๋ก ์๋ํฉ๋๋ค.
False๋ก ์ ํ ์๋ ๋ถ๋ถ์ auto_start๋ผ๋ ๋งค๊ฐ๋ณ์์ธ๋ฐ์, ๋ง ๊ทธ๋๋ก server๋ฅผ
์์ฑ ํ ์๋ ์คํํ ๊ฒ์ธ์ง ์ค์ ํ๋ ๋งค๊ฐ๋ณ์์ด๋ฉฐ, ์ง๊ธ์ _as.start()
๋ฅผ ํตํด ์๋์ผ๋ก ์คํ์ํค๊ณ ์์ต๋๋ค.
- callback
def execute_cb(goal):
r = rospy.Rate(5)
success = True
g_feedback.sequence = []
g_feedback.sequence.append(0)
g_feedback.sequence.append(1)
rospy.loginfo(
"Fibonacci Action Server Executing, creating fibonacci sequence of order %i with seeds %i, %i"
% (goal.order, g_feedback.sequence[0], g_feedback.sequence[1])
)
for i in range(1, goal.order):
if _as.is_preempt_requested():
rospy.loginfo("The goal has been cancelled/preempted")
goal_callback์ client๋ก๋ถํฐ์ goal์ ๋งค๊ฐ๋ณ์๋ก ๋ฐ๊ฒ ๋๋ฉฐ, FibonacciAction์ด ์ด๋ป๊ฒ ์๊ฒผ๋์ง ๋ค์ ํ ๋ฒ ๋ณด๊ฒ ์ต๋๋ค.
- Fibonacci.action
#goal definition
int32 order
---
#result definition
int32[] sequence
---
#feedback
int32[] sequence
- ํผ๋ณด๋์น ๋ก์ง, is_preempt_requested()
for i in range(1, goal.order):
if _as.is_preempt_requested():
rospy.loginfo("The goal has been cancelled/preempted")
_as.set_preempted()
success = False
break
g_feedback.sequence.append(g_feedback.sequence[i] + g_feedback.sequence[i - 1])
_as.publish_feedback(g_feedback)
r.sleep()
if success:
g_result.sequence = g_feedback.sequence
rospy.loginfo("Succeeded calculating the Fibonacci")
_as.set_succeeded(g_result)
callback ์ค์์๋ ํต์ฌ์ธ for๋ฌธ ์์ ๊ฐ์ ธ์์ต๋๋ค.
์ง๊ธ์ ๊ฒฝ์ฐ order ๋งํผ ๋ฐ๋ณตํ๋ฉฐ ํผ๋ณด๋์น ์์ด์ ๋ง๋ค๊ณ , list ์๋ฃํ์ ๊ฐ์ง sequence์ appendํ๊ณ ์์ง์?
- action์ ์ฑ๊ฒฉ์, ์งง์ request - response ๋ณด๋ค, ๊ธธ๊ณ ๋ณต์กํ request๊ฐ ๋ง์ด ์ฌ์ฉ๋ ๊ฒ์ ๋๋ค. (์งง์ request - response๊ฐ ํ์ํ ๊ฒฝ์ฐ ์ ๋ผ๋ฉด service๋ฅผ ์ฐ๊ฒ ์ต๋๋ค.)
- ๊ธด ์คํ ๋์ feedback์ ๋ณด๋ด๊ณ , ๋์ค์ client๊ฐ cancel, ํน์ preempt(์ ์ )์ ์์ฒญํ ์๋ ์๊ธฐ์ ์ด์ ๋ํ ์ฒ๋ฆฌ๊ฐ ๊ตฌํ๋์ด ์์ต๋๋ค.
[WARN] [1610621159.608869]: Inbound TCP/IP connection failed: connection from sender terminated before handshake header received. 0 bytes were received. Please check sender for additional details.
if success
๋ก ์์ํ๋ ๋ถ๋ถ์ ROS์์ ์ ๊ณตํ๋ ๊ฒ์ด ์๋, ๋ณดํธ์ ์ผ๋ก ๋ง์ด ์ฌ์ฉ๋๋ python flag๋ฅผ ๊ตฌํํ ๊ฒ์ผ๋ก ROS API๋ฅผ ์ฐธ๊ณ ํ์ฌ ๋ ๋ค์ํ ๊ธฐ๋ฅ์ ๊ตฌํํ ์ ์์ ๊ฒ์ ๋๋ค.
[Tip] AxClient
$ rosrun actionlib axclient.py /fibonacci_action_server
or
# ์ด์ ์ ~/.bashrc์ ์ถ๊ฐํ์ต๋๋ค :)
$ axclient /fibonacci_action_server
Goal ๋ถ๋ถ์ ์ํ๋ order๋ฅผ ๋ฃ์ด์ SEND GOAL
์ ํด๋ฆญํ๋ฉด,
๋ณด๊ธฐ ์ข๊ฒ Feedback๊ณผ Result๋ฅผ ํ์ธํ ์ ์์ต๋๋ค. ๋์
rosrun actionlib
axclient.py
๋ค์, ์ด๋ฆ์ ์ ๋ง์ถฐ์ค์ผ
ํฉ๋๋ค. rostopic list
๋ก ๋ณผ ์ ์๊ฒ ์ง์?
์ ๐ ์ฌ๊ธฐ๊น์ง, ROS์ ํต์ ๋ฉ์ปค๋์ฆ์ ๋ชจ๋ ์ดํด๋ณด์์ต๋๋ค. ์์ผ๋ก ์ด์ด์ง๋ ๋ช๊ฐ์ ๊ฐ์๋ค์ ๋ณด๋ค ์ฌํ๋ ์์ ๋ฅผ ๋ถ์ํด๋ณด๊ณ ์ ํฉ๋๋ค. ํด๋น ๋ถ๋ถ์ ํ์์ ์ด ์๋๋ฉฐ ์ ๊ฐ ์ ๋ชฉ์๋ [Option]์ ๋ถ์ฌ๋๊ฒ ์ต๋๋ค!!