๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

์นดํ…Œ๊ณ ๋ฆฌ ์—†์Œ

8. rosservice, service client, rossrv

๐Ÿ›Ž๏ธ

8. rosservice, service client, rossrv

์ด๋ฒˆ ์‹œ๊ฐ„์—๋Š” ๋˜๋‹ค๋ฅธ node๊ฐ„ ํ†ต์‹  ๋ฉ”์ปค๋‹ˆ์ฆ˜์ธ Service์— ๋Œ€ํ•ด ๋ฐฐ์›Œ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

ํ•ญ์ƒ ๊ทธ๋žฌ๋˜ ๊ฒƒ์ฒ˜๋Ÿผ, ์˜ˆ์ œ๋ฅผ ์‹คํ–‰์‹œ์ผœ๋ด…์‹œ๋‹ค!!

r2d2 spawn


$ roslaunch gcamp_gazebo gazebo_world.launch 
# gazebo ์‹œ๋ฎฌ๋ ˆ์ด์…˜์ด ์™„์ „ํžˆ ์ผœ์งˆ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ ค ์ฃผ์„ธ์š”!!
$ rosrun service_tutorial spawn_model_client.py

์‚ฌ์ง„๊ณผ ๊ฐ™์ด r2d2๊ฐ€ ๋“ฑ์žฅํ–ˆ๋‚˜์š”? ๐Ÿ—ฟ

์ง€๊ธˆ ์šฐ๋ฆฌ๋Š” gazebo_ros์˜ service server์—๊ฒŒ r2d2๋ฅผ ๋“ฑ์žฅ์‹œ์ผœ ๋‹ฌ๋ผ๋Š” service call์„ ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค!!

ROS Service ๊ฐœ๋…


์ถœ์ฒ˜ : mathworks

๊ทธ๋Ÿผ topic๊ณผ service๋Š” ์–ด๋–ค ์ฐจ์ด๊ฐ€ ์žˆ๋Š” ๊ฑธ๊นŒ์š”?

  1. A topic์ด ์‹คํ–‰๋˜๋Š” ๋™์•ˆ, ๋‹ค๋ฅธ B topic๋„ ๊ฐ™์ด ์‹คํ–‰๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฐ˜๋ฉด, service๋Š” ํ˜„์žฌ ์ง„ํ–‰์ค‘์ธ service์˜ request๊ฐ€ ์ฒ˜๋ฆฌ๋˜๋Š” ๋™์•ˆ, ๋‹ค๋ฅธ service๋Š” ๊ธฐ๋‹ค๋ฆฌ๊ณ  ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  1. topic publish๋ฅผ ํ•˜๋ฉด, A node๋„, B node๋„ subscribe๊ฐ€ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ๋ฐ˜๋ฉด, service๋Š” request๊ฐ€ ์˜จ ๋Œ€์ƒ์—๊ฒŒ๋งŒ response๋ฅผ ์ค๋‹ˆ๋‹ค.

์–ด๋–ค ์ƒํ™ฉ์—๋Š” ๋ฌด์กฐ๊ฑด service๋ฅผ ์จ์•ผ ํ•œ๋‹ค, ์ด๋Ÿฐ ๋ฒ•์น™์€ ์—†์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ, ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ฐ ๋ฉ”์ปค๋‹ˆ์ฆ˜์— ์ ํ•ฉํ•œ ์ƒํ™ฉ์„ ์ƒ๊ฐํ•ด ๋ณผ ์ˆ˜ ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

  • ๋ถ„๋ช…ํ•œ ์š”์ฒญ์˜ ์ฃผ์ฒด๊ฐ€ ์žˆ์œผ๋ฉฐ, ๋น ๋ฅด๊ฒŒ ๋™์ž‘์ด ์™„๋ฃŒ๋˜๋Š” ๊ฒฝ์šฐ์—๋Š” service
  • ๋ถˆํŠน์ •ํ•œ node๊ฐ€ subscribe์˜ ๋Œ€์ƒ์ด ๋˜๋ฉฐ, ์ง€์†์ ์œผ๋กœ ๋ฐ์ดํ„ฐ์˜ ์†ก์ˆ˜์‹ ์ด ์ผ์–ด๋‚˜๋Š” ๊ฒฝ์šฐ์—๋Š” topic

์ง€๋‚œ ์‹œ๊ฐ„์—๋„ ์–ธ๊ธ‰ํ–ˆ์ง€๋งŒ, ์ œ ๊ฐœ์ธ์ ์œผ๋กœ๋Š” ์ฐธ๊ณ ํ•  ๋งŒํ•œ ์˜คํ”ˆ์†Œ์Šค ํ”„๋กœ์ ํŠธ๋ฅผ ์‚ดํ”ผ๋Š” ๊ฒƒ์„ ์ถ”์ฒœํ•ฉ๋‹ˆ๋‹ค.

๋”๋ถˆ์–ด, ์ข€ ๋” ์ž์„ธํ•œ ๋น„๊ต ๋ถ„์„์— ๋Œ€ํ•œ ๋ ˆํผ๋Ÿฐ์Šค๋ฅผ ๋‚จ๊ธฐ๋‹ˆ, ํ•œ๋ฒˆ์”ฉ ๋ณด์‹œ๋ฉด ์ข‹์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค ๐Ÿ‘

from wiki.ros.org : Topics vs Services vs Actionlib...

rosservice ์ปค๋งจ๋“œ


์ด๋ฒˆ์—๋Š” ๋“ฑ์žฅ์‹œํ‚จ r2d2 ๋กœ๋ด‡์„ ์‚ญ์ œ์‹œ์ผœ๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

$ rosservice call /gazebo/delete_model "model_name: 'r2d2'"

rostopic์ฒ˜๋Ÿผ rosservice ๋˜ํ•œ ์—ฌ๋Ÿฌ ์˜ต์…˜์„ ๊ฐ€์ง„ service์šฉ ์ปค๋งจ๋“œ์ž…๋‹ˆ๋‹ค. rosservice call์„ ํ†ตํ•ด ์šฐ๋ฆฌ๋Š” ๋ฐฉ๊ธˆ /gazebo/delete_model ๋ผ๋Š” service์—๊ฒŒ r2d2๋ฅผ ์—†์• ๋‹ฌ๋ผ๊ณ  ์š”์ฒญํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ด์ „ topic ์‹œ๊ฐ„์—์„œ๋„ ๋ณด์•˜๋“ฏ์ด, ๊ฐ„๋‹จํ•œ ROS ํ†ต์‹  ๋ฉ”์ปค๋‹ˆ์ฆ˜์€ ํ„ฐ๋ฏธ๋„์—์„œ๋„ ํ˜ธ์ถœ์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ง€๊ธˆ๊ณผ ๊ฐ™์€ ๊ฒฝ์šฐ, ๋‹จ์ˆœํžˆ model delete๋ฅผ call ํ•œ ๊ฒƒ์ด๋ฏ€๋กœ ์ด๋ ‡๊ฒŒ ํ„ฐ๋ฏธ๋„ ๋‹จ์—์„œ ํ•ด๊ฒฐํ•œ ๊ฒƒ์ด์ฃ .

service client ์ฝ”๋“œ ๋ถ„์„


gazebo service server์— call์„ ํ•ด์„œ r2d2๋ฅผ ๋“ฑ์žฅ์‹œ์ผฐ๋˜ ์ฝ”๋“œ๋ฅผ ๋ถ„์„ํ•ด ๋ณผ๊นŒ์š”? ?

#! /usr/bin/env python

import math
import rospy
import rospkg
from geometry_msgs.msg import Pose
from gazebo_msgs.srv import SpawnModel

rospy.init_node("gazebo_spawn_model")

# model_name
model_name = 'r2d2'

# model_xml
rospack = rospkg.RosPack()
model_path = rospack.get_path('service_tutorial')+'/models/'

with open (model_path + model_name + '.urdf', 'r') as xml_file:
    model_xml = xml_file.read().replace('\n', '')

# robot_namespace
robot_namespace = ''

# initial_pose
initial_pose = Pose()
initial_pose.position.x = -2
initial_pose.position.y = 1
initial_pose.position.z = 1

# z rotation -pi/2 to Quaternion
initial_pose.orientation.z = -0.707
initial_pose.orientation.w = 0.707 

# reference_frame
reference_frame = 'world'

# service call
spawn_model_prox = rospy.ServiceProxy('gazebo/spawn_urdf_model', SpawnModel)
result = spawn_model_prox(model_name, model_xml, robot_namespace, initial_pose, reference_frame) 

''' result fromat
bool success
string status_message
'''

print(result)

  • ์–ด๋–ค ํ˜•์‹์„ ์š”๊ตฌํ•˜๊ธธ๋ž˜ ์ด๋ ‡๊ฒŒ ๋ณต์žกํ• ๊นŒ์š”? ์‚ฌ์‹ค์ƒ srv๋ฅผ ์ฑ„์šฐ๋Š” ๋ถ€๋ถ„์ด ๋‹ค์ˆ˜์ด๋ฉฐ ์•ž์„  topic์—์„œ๋Š” msg ํ˜•์‹์„ ์‚ฌ์šฉํ–ˆ๋˜ ๊ฒƒ์ฒ˜๋Ÿผ, ์„œ๋น„์Šค๋Š” srv๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
import math
import rospy
import rospkg
from geometry_msgs.msg import Pose
from gazebo_msgs.srv import SpawnModel

  • ๋ชจ๋ธ์„ spawn์‹œํ‚ค๊ธฐ ์œ„ํ•ด์„œ ์–ด๋–ค service์—๊ฒŒ ์š”์ฒญํ• ์ง€, ์ด๋Ÿฐ ์ •๋ณด๋Š” gazebo ๋ฌธ์„œ์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. โ‡’ gazebo/spawn_urdf_model

ROS communication
Gazebo provides a set of ROS API's that allows users to modify and get information about various aspects of the simulated world. In the following sections, we will demonstrate some of the utilities for manipulating the simulation world and objects. The complete list of ROS messages and services for gazebo can be found here also.
http://gazebosim.org/tutorials/?tut=ros_comm

$ rosservice info gazebo/spawn_urdf_model

$ rossrv show gazebo_msgs/SpawnModel

string model_name
string model_xml
string robot_namespace
geometry_msgs/Pose initial_pose
  geometry_msgs/Point position
    float64 x
    float64 y
    float64 z
  geometry_msgs/Quaternion orientation
    float64 x
    float64 y
    float64 z
    float64 w
string reference_frame
---
bool success
string status_message

topic ์‹œ๊ฐ„์—์„œ message type์„ ์กฐ์‚ฌํ–ˆ๋˜ ๊ณผ์ •๊ณผ ์œ ์‚ฌํ•˜์ฃ ? service์—์„œ ์˜ค๊ฐ€๋Š” ๋ฐ์ดํ„ฐ ํ˜•์‹์„ ์กฐํšŒํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” rossrv show ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค!!

gazebo_msgs/SpawnModel Documentation
string model_name # name of the model to be spawn string model_xml # this should be an urdf or gazebo xml string robot_namespace # spawn robot and all ROS interfaces under this namespace geometry_msgs/Pose initial_pose # only applied to canonical body string reference_frame # initial_pose is defined relative to the frame of this model/body # if left empty or "world", then gazebo world frame is used # if non-existent model/body is specified, an error is returned # and the model is not spawned ---bool success # return true if spawn successful string status_message # comments if available
http://docs.ros.org/en/jade/api/gazebo_msgs/html/srv/SpawnModel.html

  • rossrv show vs rossrv info
Wiki
The rossrv tool provides information about srv files. The rosservice command implements a variety of commands that let you discover which services are currently online from which nodes and further drill down to get specific information about a service, such as its type, URI, and arguments.
http://wiki.ros.org/rosservice

  • ์ค‘๊ฐ„์— - - - ์ด๋Ÿฐ ๋ถ€๋ถ„์ด ๋ณด์ž…๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ request์™€ response๋ฅผ ๊ตฌ๋ถ„ํ•ด์ฃผ๋Š” ์นธ๋ง‰์ด๋ผ๊ณ  ์ƒ๊ฐํ•˜์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค.
uint32 time_duration
float64 angular_vel
---
bool success

uint32, float64, bool, string๊ณผ ๊ฐ™์ด ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด์—์„œ ์ด๋ฏธ ์ต์ˆ™ํ•œ ์ž๋ฃŒํ˜•์„ ์“ธ ์ˆ˜๋„ ์žˆ๊ณ , ROS์—์„œ ์ œ๊ณตํ•˜๋Š” geometry_msgs, sensor_msgs์™€ ๊ฐ™์€ ์ž๋ฃŒํ˜•๋„ ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

๋”๋ถˆ์–ด, ์ด๋“ค์„ ์กฐํ•ฉํ•ด์„œ ๋‚˜๋งŒ์˜ srv ํƒ€์ž…๋„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์ง€์š”. ํ˜„ ๊ฐ•์˜์—์„œ๋Š” ์ž์„ธํ•˜๊ฒŒ ๋‹ค๋ฃจ์ง€ ์•Š๊ฒ ์ง€๋งŒ, ์ถ”๊ฐ€ ๋ ˆํผ๋Ÿฐ์Šค๋ฅผ ๊ณต์œ ํ•˜๋‹ˆ ํ•œ๋ฒˆ์”ฉ ๋”ฐ๋ผํ•ด ๋ณด์…”๋„ ์ข‹์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค!!

[ROS in 5 mins] 030 - How to compile ROS Service messages - The Construct
Hello ROS Developers! In today's video we are going learn how to create a ROS Service file, how to compile and how to import it. For that we are going to use Robot Ignite Academy, which is the best tool if you want to Learn ROS Fast.
https://www.theconstructsim.com/ros-5-mins-030-compile-ros-service-messages/

๋‹ค์‹œ ์†Œ์Šค์ฝ”๋“œ๋กœ ๋Œ์•„์™€์„œ, ๋‹ค์†Œ ๋ณต์žกํ•ด ๋ณด์˜€์ง€๋งŒ gazebo์—์„œ ์š”๊ตฌํ•˜๋Š” ์ •๋ณด๋“ค์ด ๋‹ค์–‘ํ•ด์„œ ๋งž์ถฐ์ฃผ๊ธฐ ์œ„ํ•œ ๋ฐ‘๋‹จ๊ณ„๊ฐ€ ๋งŽ์„ ๋ฟ ํ•ต์‹ฌ์€ ๋‹ค์Œ ๋‘์ค„์ž…๋‹ˆ๋‹ค.

  • ์ด๊ฒƒ์ด ํ•ต์‹ฌ!!
# service call
spawn_model_prox = rospy.ServiceProxy('gazebo/spawn_urdf_model', SpawnModel)
result = spawn_model_prox(model_name, model_xml, robot_namespace, initial_pose, reference_frame) 
  • rospy.ServiceProxy('<service-server-name>', service-type)

rospy.ServiceProxy()๋ฅผ ํ†ตํ•ด service client ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค๊ณ , ์•ž์„œ ์‚ดํŽด๋ณธ๋Œ€๋กœ ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋“ค์„ ์ทจํ•ฉํ•œ ๋’ค, requestํ•˜๋Š” ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค!!

requestํ•œ ๋’ค์—๋Š” ๋ญ๊ฐ€ ์˜ค์ฃ ? โ‡’ response๊ฐ€ ์˜ต๋‹ˆ๋‹ค.

result์— ๋ฐ”๋กœ response๊ฐ€ ๋‹ด๊ฒจ ์žˆ์œผ๋ฉฐ, ๊ทธ๋ž˜์„œ ์ด๋ฅผ ์ถœ๋ ฅํ–ˆ์„ ์‹œ, ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ผ์ธ์ด ๋“ฑ์žฅํ–ˆ๋˜ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

success: True
status_message: "SpawnModel: Successfully spawned entity"

์ง€๊ธˆ๊นŒ์ง€ service client์— ๋Œ€ํ•ด ์„ค๋ช…ํ–ˆ๋Š”๋ฐ์š”, gazebo/spawn_urdf_model๋ผ๋Š” service server๋Š” ์–ธ์ œ ์‹คํ–‰๋œ ๊ฒƒ์ผ๊นŒ์š”??

  • gazebo_world.launch
<!-- Launch Gazebo World -->
  <include file="$(find gazebo_ros)/launch/empty_world.launch">
    <arg name="use_sim_time" value="true"/>
    <arg name="debug" value="false"/>
    <arg name="gui" value="true" />
    <arg name="world_name" value="$(arg world_file)"/>
  </include>

gazebo_ros/empty_world.launch๋ฅผ ์‹คํ–‰์‹œํ‚ค๋ฉด, gazebo์™€ ๊ด€๋ จ๋œ ์ˆ˜๋งŽ์€ service๋“ค์ด ํ•จ๊ป˜ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. ์ด ์ค‘์— gazebo_msgs/SpawnModel๋„ ์žˆ๋Š” ๊ฒƒ์ด์ฃ .

$ rosservice list | grep gazebo

๋ชป๋ณด๋˜ ์ƒˆ๋กœ์šด ํ‚ค์›Œ๋“œ๊ฐ€ ๋“ฑ์žฅํ–ˆ์Šต๋‹ˆ๋‹ค. | grep gazebo ?? ์ด๊ฑด ์–ด๋–ค ๋œป์ผ๊นŒ์š”??

grep ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด, ์•ž์„  ํ‚ค์›Œ๋“œ์˜ ๊ฒฐ๊ณผ์— ์ถ”๊ฐ€์ ์œผ๋กœ ๊ฒ€์ƒ‰์กฐ๊ฑด์„ ๋ถ™์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํŒŒ์ผ์ด๋‚˜, ํด๋”๋ฅผ ์ฐพ๊ณ  ์‹ถ์€ ๊ฒฝ์šฐ๋„ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋ฉฐ, ์ด๋Ÿด ๋•Œ๋Š” find ์ปค๋งจ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค.

$ ls -al | grep <something>
$ find -name <file-or-directory-name>

์ด๋ฒˆ ์‹œ๊ฐ„์—๋„ ๋งŽ์€ ๊ฒƒ๋“ค์„ ๋ฐฐ์› ์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ ์‹œ๊ฐ„์—๋Š” service server์— ๋Œ€ํ•œ ๋‚ด์šฉ๋ถ€ํ„ฐ ์‹œ์ž‘ํ•˜๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค! ๐Ÿ‘๐Ÿ‘๐Ÿ‘