Post

ROS2 (Robot Operating System)

ROS2에 대해 알아보자

ROS2 (Robot Operating System)

How to Install ROS2 (Humble or Jassy)

WSL Ubuntu 24에서 Humble의 경우 repo list에서 지원하지 않아 Jassy로 설치하여 진행함

  • Humble : link
  • Jazzy : link

  • rqt_graph로 현재 실행중인 노드 및 발행된 topic 정보 확인 가능

ROS2 특징

  • setup.sh
    • sudo apt install 명령으로 설치한 ros pkg들이 저장된 곳이 /opt/ros/[Version, ex.huble/jassyh]이며, 해당 경로의 setup.bash를 sourc로 읽어 들여야 ros2 개발환경 사용이 가능
  • ROS_DOMAIN_ID
    • DDS(Data Distribution Service, 데이터 분산 서비스)을 재택하여 시스템의 실시간성/규모가변성/안정성/고성능을 가능케 하도록 Publish/Subscribe 네트워크 커뮤니케이션 구조의 미들웨어를 사용함
    • 따라서 다른 네트워크에서 들어오는 정보를 구분 짓기 위해 ROS_DOMAIN_ID라는 시스템 변수를 사용함

ROS 구조

Node :

  • 실행가능한 최소 단위를 말함
  • 노드확인 명령어 : ros2 run <PKG Name> <Node Name>
    • ex. ros2 run turtlesim turtlesim_node
  • 그외 명령어 ros2 node list : 실행중인 노드 리스트 확인 가능 ros2 node info turtlesim : 현재 실행중인 노드의 정보를 출력
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
gyyeon@DESKTOP-A9M7R8S:~$ ros2 node list # 현재 실행중인 노드 리스트 확인
/turtlesim
gyyeon@DESKTOP-A9M7R8S:~$ ros2 node info /turtlesim # 이 노드가 어떤것을 제공하는지 확인 가능
/turtlesim
  Subscribers:
    /parameter_events: rcl_interfaces/msg/ParameterEvent
    /turtle1/cmd_vel: geometry_msgs/msg/Twist
  Publishers:
    /parameter_events: rcl_interfaces/msg/ParameterEvent
    /rosout: rcl_interfaces/msg/Log
    /turtle1/color_sensor: turtlesim/msg/Color
    /turtle1/pose: turtlesim/msg/Pose
  Service Servers:
    /clear: std_srvs/srv/Empty
    /kill: turtlesim/srv/Kill
    /reset: std_srvs/srv/Empty
    /spawn: turtlesim/srv/Spawn
    /turtle1/set_pen: turtlesim/srv/SetPen
    /turtle1/teleport_absolute: turtlesim/srv/TeleportAbsolute
    /turtle1/teleport_relative: turtlesim/srv/TeleportRelative
    /turtlesim/describe_parameters: rcl_interfaces/srv/DescribeParameters
    /turtlesim/get_parameter_types: rcl_interfaces/srv/GetParameterTypes
    /turtlesim/get_parameters: rcl_interfaces/srv/GetParameters
    /turtlesim/get_type_description: type_description_interfaces/srv/GetTypeDescription
    /turtlesim/list_parameters: rcl_interfaces/srv/ListParameters
    /turtlesim/set_parameters: rcl_interfaces/srv/SetParameters
    /turtlesim/set_parameters_atomically: rcl_interfaces/srv/SetParametersAtomically
  Service Clients:

  Action Servers:
    /turtle1/rotate_absolute: turtlesim/action/RotateAbsolute
  Action Clients:

Service

  • 클라이언트가 요청한 것을 서버측이 받아 응답하는 것을 말하며, 주고받는 Request/Response에 타입을 지정하여 사용함.
  • Service Type Definition의 경우 ---를 기준으로 위 = Request/아래 = Response에 대한 타입을 정의하며 파일 포맷은 srv(service의 약어)이다.

  • 서비스 확인 명령어 : ros2 service list
  • 그외 명령어
    • ros2 service type <서비스> : 제공하는 서비스의 타입 파일(srv) 경로 확인
      • ex. ros2 service type /turtle1/teleport_absolute
    • ros2 interface show <srv 경로> : 정의된 서비스 타입 파일의 정보 확인
      • ex. ros2 interface show /turtle1/teleport_absolute
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
gyyeon@DESKTOP-A9M7R8S:~$ ros2 service list
/clear
/kill
/reset
/spawn
/turtle1/set_pen
/turtle1/teleport_absolute
/turtle1/teleport_relative
/turtlesim/describe_parameters
/turtlesim/get_parameter_types
/turtlesim/get_parameters
/turtlesim/get_type_description
/turtlesim/list_parameters
/turtlesim/set_parameters
/turtlesim/set_parameters_atomically
# 서비스 타입 파일 확인
gyyeon@DESKTOP-A9M7R8S:~$ ros2 service type /turtle1/teleport_absolute
turtlesim/srv/TeleportAbsolute
# srv의 서비스 타입 정보 확인(--- 기준 위는 request, 밑은 response)
gyyeon@DESKTOP-A9M7R8S:~$ ros2 interface show turtlesim/srv/TeleportAbsolute
float32 x
float32 y
float32 theta
---

ros에서 제공하는 서비스 타입의 경우 단위는 KMS, radian을 주로 사용한다

Service Call

  • 제공하는 서비스에 대해 사용 요청하는 서비스 콜 명령어에 대해 알아보자
  • 서비스 콜 명령어 : ros2 service call '서비스타입(srv) "data" -ex.
    • ros2 service call /turtle1/teleport_absolute turtlesim/srv/TeleportAbsolute “{x: 2, y: 2, theta: 1.57}”
    • ros2 service call /reset std_srvs/srv/Empty {}

Service Call(Name Space)

  • 어떤 로봇인지 구분하기 위해 Name Space를 사용하며 ros2 service list를 쳐보면 확인 가능
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 임의의 터틀봇 생성
gyyeon@DESKTOP-A9M7R8S:~$ ros2 service call /spawn turtlesim/srv/Spawn "{x: 3, y: 5, theta: 3.14, name: ''}"
requester: making request: turtlesim.srv.Spawn_Request(x=3.0, y=5.0, theta=3.14, name='')
response:
turtlesim.srv.Spawn_Response(name='turtle2')
# 터틀봇 서비스 리스트 정보를 확인해보면 turtle1/2 namespace로 개별 동작 서비스가 나눠져 있음이 확인 가능
gyyeon@DESKTOP-A9M7R8S:~$ ros2 service list
/clear
/kill
/reset
/spawn
/turtle1/set_pen              #<------
/turtle1/teleport_absolute    #<------
/turtle1/teleport_relative    #<------
/turtle2/set_pen              #>------
/turtle2/teleport_absolute    #>------
/turtle2/teleport_relative    #>------
/turtlesim/describe_parameters
/turtlesim/get_parameter_types
/turtlesim/get_parameters
/turtlesim/get_type_description
/turtlesim/list_parameters
/turtlesim/set_parameters
/turtlesim/set_parameters_atomically


TOPIC

  • Publisher측에서 brodcast로 특정 Topic으로 정보를 제공할때 사용되며,
  • Subscriber측은 Topic Name/Message Type을 알면 어느 노드건 해당 메세지를 받아 볼수 있음
  • 토픽 리스트 확인 명령어 : ros2 topic list [-t|-v, 토픽 메시지 타입까지 표여줌| pub,sub 정보를 다보여줌]
  • 토픽 확인 명령어 : ros2 topic echo [토픽] (ex. ros2 topic echo /turtle1/pose)
    • 그외 명령어
      • ros2 topic type [토픽] : 토픽의 메세지 타입 파일 확인 -ex. ros2 topic type /turtle1/pose
      • ros2 topic info [토픽] : 토픽 타입 및 pub/sub 갯수 확인 가능(ex. subscription cnt:0이라면 아무도 안듣고 있는 상황)
      • ros2 interface show <토픽 Msg 타입> : 토픽 Msg 타입 정보 확인 -ex. ros2 interface show turtlesim/msg/Pose
      • ros2 topic echo [토픽] : 특정 토픽을 subscribe 수행
      • rqt_graph : 실행중인 노드 및 토픽 정보를 확인 가능(debug를 꺼야 cli로 sub중인 상태들까지 확인 가능)
      • ros2 topic pub [토픽] [타입] [데이터] : 특정 토픽으로 msg pub 수행 (옵션으로 명령어 주기 설정 가능 –once / –rate [Hz])

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# [default] 토픽 정보 확인
gyyeon@DESKTOP-A9M7R8S:~$ ros2 topic list
/rosout
/turtle1/cmd_vel
/turtle1/color_sensor
/turtle1/pose
/turtle2/cmd_vel
/turtle2/color_sensor
/turtle2/pose
/turtle3/cmd_vel
/turtle3/color_sensor
/turtle3/pose
# [t] 토픽 정보를 토픽 타입 파일과 함께 확인
gyyeon@DESKTOP-A9M7R8S:~$ ros2 topic list -t
/parameter_events [rcl_interfaces/msg/ParameterEvent]
/rosout [rcl_interfaces/msg/Log]
/turtle1/cmd_vel [geometry_msgs/msg/Twist]
/turtle1/color_sensor [turtlesim/msg/Color]
/turtle1/pose [turtlesim/msg/Pose]
/turtle2/cmd_vel [geometry_msgs/msg/Twist]
/turtle2/color_sensor [turtlesim/msg/Color]
/turtle2/pose [turtlesim/msg/Pose]
/turtle3/cmd_vel [geometry_msgs/msg/Twist]
/turtle3/color_sensor [turtlesim/msg/Color]
/turtle3/pose [turtlesim/msg/Pose]
# [v] 토픽 세부 정보 확인
gyyeon@DESKTOP-A9M7R8S:~$ ros2 topic list -v
Published topics:
 * /parameter_events [rcl_interfaces/msg/ParameterEvent] 2 publishers
 * /rosout [rcl_interfaces/msg/Log] 2 publishers
 * /turtle1/color_sensor [turtlesim/msg/Color] 1 publisher
 * /turtle1/pose [turtlesim/msg/Pose] 1 publisher
 * /turtle2/color_sensor [turtlesim/msg/Color] 1 publisher
 * /turtle2/pose [turtlesim/msg/Pose] 1 publisher
 * /turtle3/color_sensor [turtlesim/msg/Color] 1 publisher
 * /turtle3/pose [turtlesim/msg/Pose] 1 publisher

Subscribed topics:
 * /parameter_events [rcl_interfaces/msg/ParameterEvent] 2 subscribers
 * /turtle1/cmd_vel [geometry_msgs/msg/Twist] 1 subscriber
 * /turtle2/cmd_vel [geometry_msgs/msg/Twist] 1 subscriber
 * /turtle3/cmd_vel [geometry_msgs/msg/Twist] 1 subscriber

# 토픽 타입 파일 정보 확인
gyyeon@DESKTOP-A9M7R8S:~$ ros2 interface show turtlesim/msg/
Pose
float32 x
float32 y
float32 theta 

float32 linear_velocity
float32 angular_velocity

gyyeon@DESKTOP-A9M7R8S:~$ ros2 topic echo /turtle1/pose
x: 5.544444561004639
y: 5.544444561004639
theta: 0.0
linear_velocity: 0.0
angular_velocity: 0.0
---

gyyeon@DESKTOP-A9M7R8S:~$ ros2 topic pub /gyu/cmd_vel geometry_msgs/msg/Twist "{linear: {x: 2, y: 0, z: 0}, angular: {x: 0, y: 0, z: 2}}"

Action

  • Action은 Goal/Result service와 그리고 중간 과정을 모니터링을 위한 feedback topic으로 구성됨
  • Service + topic = action으로 생각하면 되고 action server를 두고 실행된다고 생각하면 됨 - ex. 로봇한테 10,10 좌표로 이동하라고 골을 주면, 이동하는 동안 피드백으로 좌표를 확인하고, 목표에 도착하면 result를 받는게 action임
  • 명령어
    • ros2 action list -t : 액션 리스트 타입과 함께 확인
    • ros2 interface show [액션타입] : 액션 타입 메시지 확인
      • ---를 기준으로 goal/result/feedback으로 영역이 나눠져 있음 (service의 경우에는 request/response 타입 정보였음)
    • ros2 action send_goal [액션] [액션타입] [데이타] : 액션 실행
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
  gyyeon@gyeon  ~  ros2 run turtlesim turtlesim_node
  gyyeon@gyeon  ~  ros2 run turtlesim turtle_teleop_key => rqt_graph로 확인해보면 /turtle1/rotate_absolute라는 토픽의 액션을 확인 가능
  gyyeon@gyeon  ~  ros2 action list -t
/gyu/rotate_absolute [turtlesim/action/RotateAbsolute]
/turtle1/rotate_absolute [turtlesim/action/RotateAbsolute]
  gyyeon@gyeon  ~  ros2 interface show turtlesim/action/RotateAbsolute
# 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
  gyyeon@gyeon  ~ 
  ✘  gyyeon@gyeon  ~  ros2 action send_goal /turtle1/rotate_absolute turtlesim/action/RotateAbsolute "{ theta: 2.11 }"
Waiting for an action server to become available...
Sending goal:
     theta: 2.11

Goal accepted with ID: 2717c10c13194056b6d0aabf6007c746

Result:
    delta: 1.0399997234344482

Goal finished with status: SUCCEEDED

Topic Subscribe/Publish (Python) ROS2 Docs

노드 생성 및 topic 구독

  • cnt를 활용해 Topic 받는 횟수를 제한함(cnt를 없애면 계속 구독)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
import rclpy as rp #rclp : robot common library python
from turtlesim.msg import Pose # Data Type(Pose)을 import로 받아옴
import time

# ros2 run turtlesim turtlesim_node

# subscription은 토픽이 들어올때마다 실행할 함수를 필수로 지정해야함
cnt = 0
def callback(data):
	global cnt
	print("--->")
	print("/turtle1/pose : ", data)
	print("X :", data.x)
	print("Y : ", data.y)
	print("Theta : ", data.theta)
	cnt = cnt + 1

	if cnt>3:
		raise Exception("Subscription Stop")


def main():
    #노드 create
    rp.init()
    test_node = rp.create_node('sub_test')

    # while 1 :
    #     time.sleep(1)
    #     print(test_node, "is running")

	#subscription 수행
	# 생성한 노드에 토픽/메세지 타입/콜백을 등록하여 sub 가능
    test_node.create_subscription(Pose, '/turtle1/pose', callback, 10)

	#rp.spin_once(test_node) #=> 토픽을 한번만 받음
    rp.spin(test_node) #=> 토픽을 계속 받음



if __name__ == "__main__":
	main()

노드 생성 및 topic 발행

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
import rclpy as rp #rclp : robot common library python
from geometry_msgs.msg import Twist # Data Type(Twist)을 import로 받아옴
import time

# ros2 run turtlesim turtlesim_node

# subscription은 토픽이 들어올때마다 실행할 함수를 필수로 지정해야함
cnt = 0
def timer_callback(pub, msg):
	global cnt
	print(cnt)
	cnt += 1
	pub.publish(msg)
	if cnt>100:
		raise Exception("Publisher Stop")


def main():
    #노드 create
    rp.init()
    test_node = rp.create_node('pub_test')

	#Twist Class 인스턴스화(instantiation)
    msg=Twist()
    print(msg) # default값으로 linear/angular로 바뀜

	# 아래와 같이 twist 값 설정
	# msg.angular.z = 1.8
	# msg.linear.x = 2

	# ex.
	# 	  gyyeon@gyeon  ~  ros2 topic list -t
	# /parameter_events [rcl_interfaces/msg/ParameterEvent]
	# /rosout [rcl_interfaces/msg/Log]
	# /turtle1/cmd_vel [geometry_msgs/msg/Twist]
	# /turtle1/color_sensor [turtlesim/msg/Color]
	# /turtle1/pose [turtlesim/msg/Pose]

    # publisher 생성(publish할 토픽과 메세지 타입을 지정)
	# 한번만 pub 수행
    pub = test_node.create_publisher(Twist, '/turtle1/cmd_vel', 10)
    pub.publish(msg)
    msg.angular.z = 1.6
    msg.linear.x = 4.0

    # 여러번 pub 수행을 하고자 할경우 timer_callback() 사용
    timer_period=0.1
    timer = test_node.create_timer(timer_period,  lambda:timer_callback(pub, msg))
    rp.spin(test_node)

	## 노드 종료
    test_node.destroy_node()


if __name__ == "__main__":
	main()

ROS2 Service Client 다루기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
import rclpy as rp #rclp : robot common library python
from turtlesim.srv import TeleportAbsolute
import time

# ros2 run turtlesim turtlesim_node

# subscription은 토픽이 들어올때마다 실행할 함수를 필수로 지정해야함
cnt = 0
def timer_callback(pub, msg):
	global cnt
	print(cnt)
	cnt += 1
	pub.publish(msg)
	if cnt>100:
		raise Exception("Publisher Stop")


def main():
    #노드 create
    rp.init()
    test_node = rp.create_node('client_test')

    service_name = '/turtle1/teleport_absolute'
    cli = test_node.create_client(TeleportAbsolute, service_name)

	# 서비스 Req Type 인스턴스 생성
    req = TeleportAbsolute.Request()
    print(req)
    req.x = 1.
    req.y = 1.
    req.theta = 1.

    cli.call_async(req)

    # 서비스 노드가 기동할때까지 기다리는 함수
    while not cli.wait_for_service(timeout_sec=1.0):
        print("Waiting for service")

    # 서비스콜 한번만 수행
    # rp.spin_once(test_node) # spin() will not return until the node is shutdown

    # 서비스가 실행되는 결과 받아오기
    future = cli.call_async(req)
    while not future.done():
        rp.spin_once(test_node)
        print(future.done(), future.result())

	## 노드 종료
    test_node.destroy_node()


if __name__ == "__main__":
	main()
This post is licensed under CC BY 4.0 by the author.