[ROS2] QoS(Quality of Service) Profile이란?

YJ·2024년 6월 13일

ROS2

목록 보기
6/9

QoS Profile이란?

QoS Profile이란 쉽게 말해 데이터 통신 옵션을 설정하는 것이다. ROS2를 통해 msg를 주고 받을 때 이 QoS Profile을 설정하여 통신을 최적화하고 시스템의 안정성을 높일 수 있다. ROS2에서 제공하는 QoS Profile은 History, Reliability, Durability, Deadline, Lifespan, Liveliness 등을 설정할 수 있으며, 표준 설정을 제공하기도 한다. 각 policy 무엇을 의미하는지 면밀히 살펴보고, qos profile을 설정하여 통신하는 방법을 알아보자.



Qos Profile의 option

History

지난 history를 얼마나 저장할지에 대한 옵션이다.

  • keep all: 모든 history를 저장한다.
  • keep last: 최대 N개(기본값은 1)의 history를 저장하며, queue(FIFO - 선입선출) 방식을 이용한다. N을 직접 설정할 수도 있다.(depth 옵션)

Reliability

속도가 중요한지 메세지의 유실방지가 중요한지를 정하는 옵션이다. 가장 많이 설정하는 옵션.

  • best effort: 유실보다 전달 속도를 중요시하는 옵션이다.
  • reliable: 데이터가 유실되지 않는 것을 중요시하는 옵션이다.

Durability

subscriber가 생기기 전 data를 유지할 것인가에 대한 옵션이다.

  • transient local: subscirber가 생기기 전 data도 유지한다. 전달된 메세지가 저장된다.
  • volatile: subscriber가 생기기 전 data를 유지하지 않는다. 전달된 메세지가 휘발된다.

Deadline

topic에서 전송되는 메세지와 후속 메세지 사이의 최대 시간을 설정한다(float). 메세지가 이 기간 안에 전송되지 못할 경우, 경고 메세지가 뜬다. 기본 값은 무한대이다.

Lifespan

메세지의 유효기간을 설정한다(float). 유효 기간이 지난 메세지는 유효하지 않다고 판정되어 삭제된다. 수신자가 이 메세지를 받았을 때 유효기간이 지나면 자연스럽게 파기된다는 의미. 기본 값은 무한대이다.

Liveliness

  • Automatic: publisher가 lease duration 기간동안 메세지를 전송하지 않으면 비활성 상태로 간주한다.
  • Manual by topic: publisher가 살아 있다고 수동으로 메세지를 보내, liveliness를 확인시켜야 한다.

(Liveliness) Lease duration

게시자가 활성상태임을 나타내는 최대 기간. 이 기간을 넘어서면 활성 상태라고 인지하지 않는다. 기본 값은 무한대이다.



제공되는 QoS Profile

ROS에서는 자주 쓰이는 표준적인 QoS Profile을 제공한다. 보통 history, reliability, durability를 설정하고 나머지는 default로 둔다. (liveliness는 automatic, lease duration의 기본 값이 무한대이므로, 활성 상태를 파악하지 않는다고 봐도 무방하다.) qos profile을 customize 하기 전에 이 프로필들에 쓸만한 것이 있는지 먼저 확인하자.

Sensor Data

  • History: KEEP_LAST
  • Depth: 5
  • Reliability: BEST_EFFORT
  • Durability: VOLATILE

주로 이미지, 레이더, 라이더와 같은 센서 데이터 스트림에 사용된다. 데이터의 최신 상태를 유지하는 것이 중요하며, 일부 데이터 손실이 발생해도 괜찮은 경우에 적합하다.

Default

  • History: KEEP_LAST
  • Depth: 10
  • Reliability: RELIABLE
  • Durability: VOLATILE

일반적인 통신에 사용한다. 신뢰성 있는 데이터 전송이 필요하며, 최신 몇 개의 메시지를 유지하는 것이 중요할 때 사용된다.

Services

  • History: KEEP_LAST
  • Depth: 10
  • Reliability: RELIABLE
  • Durability: VOLATILE

서비스 통신에 사용된다. 서비스 통신의 요청-응답 패턴에서는 신뢰성 있는 데이터 전송이 필요합니다.

Parameters

  • History: KEEP_LAST
  • Depth: 1000
  • Reliability: RELIABLE
  • Durability: VOLATILE

파라미터 통신에 사용된다. 대규모 파라미터 데이터 전송 시 신뢰성 있는 데이터 전송이 필요하기 때문에, reliable로 이용한다.

System Default

  • History: KEEP_LAST
  • Depth: 1
  • Reliability: RELIABLE
  • Durability: VOLATILE

시스템 기본값으로 사용된다. 일반적인 설정으로, 많은 경우에 적합하지만, 특정 상황에 맞게 조정이 필요할 수 있다.

Parameter Events

History: KEEP_ALL
Depth: 1000
Reliability: RELIABLE
Durability: TRANSIENT_LOCAL

파라미터 이벤트 통신에 사용된다. 파라미터 변경 사항이 모두 전달되도록 보장한다.

이용 예제

sensor data qos profile을 사용하는 예제를 살펴보자.

publisher의 경우 아래와 같이 작성하면 된다.

...
from rclpy.qos import QoSPresetProfiles
...

class SensorDataPublisher(Node):
    def __init__(self):
        super().__init__('sensor_data_publisher')
        qos_profile = QoSPresetProfiles.SENSOR_DATA.value
        self.publisher_ = self.create_publisher(String, 'sensor_data_topic', qos_profile)
        ...(생략)

def main(args=None):
    rclpy.init(args=args)
    sensor_data_publisher = SensorDataPublisher()
    rclpy.spin(sensor_data_publisher)
    sensor_data_publisher.destroy_node()
    rclpy.shutdown()

if __name__ == '__main__':
    main()

QoSPresetProfiles를 import하여 그 중 SENSOR_DATA의 값을 받아온다. 다른 profile도 마찬가지로 이용할 수 있다. 그리고 단순히 publisher를 설정할 때, qos_profile을 자료형, 토픽 이름 다음에 넣어주기만 하면 된다.

subscriber를 살펴보자.

...
from rclpy.qos import QoSPresetProfiles
...

class SensorDataSubscriber(Node):
    def __init__(self):
        super().__init__('sensor_data_subscriber')
        qos_profile = QoSPresetProfiles.SENSOR_DATA.value
        self.subscription = self.create_subscription(
            String,
            'sensor_data_topic',
            self.listener_callback,
            qos_profile)
        self.subscription  # prevent unused variable warning

    def listener_callback(self, msg):
        self.get_logger().info(f'Received: "{msg.data}"')

def main(args=None):
    rclpy.init(args=args)
    sensor_data_subscriber = SensorDataSubscriber()
    rclpy.spin(sensor_data_subscriber)
    sensor_data_subscriber.destroy_node()
    rclpy.shutdown()

if __name__ == '__main__':
    main()

subscriber도 마찬가지로 qos profile을 받아온 뒤, subscriber를 선언할 때 자료형, 토픽이름, 콜백함수 다음에 넣어주기만 하면 된다.



QoS Profile customize

customize도 간단하다. QoS profile을 작성하여 publisher, subscriber 등을 선언할 때 넣어주기만 하면 된다. 그렇다면 QoS profile을 작성하는 방법을 알아보자.

from rclpy.qos import QoSProfile, QoSReliabilityPolicy, QoSHistoryPolicy

QoSProfile과 설정을 원하는 policy class들을 import해주면 된다.

 qos_profile = QoSProfile(
            history=QoSHistoryPolicy.KEEP_LAST,
            depth=5,
            reliability=QoSReliabilityPolicy.BEST_EFFORT
        )

그 뒤 QoSProfile class의 인스턴스를 선언해주면 되는데, 이 때 설정을 원하는 옵션을 불러와 사용하면 된다. vscode를 이용한다면 원하는 변수를 쉽게 불러올 수 있을 것이다.



QoS Profile의 중요성

ROS에서 통신이 되지 않는 경우, RVIZ에서 topic을 받아오고 있는데도 visualize가 안되는 경우가 가끔 존재한다. 특히 ROS driver를 사서 센서를 연결할 때 그럴 수 있는데, 이는 sensor에서 발행하는 토픽의 qos profile이 호환되지 않기 때문이다. 통신이 되지 않을 때 qos profile을 확인해볼 필요가 있다. 반드시 일치할 필요는 없고, 호환이 안되는 경우만 주의하면 된다.

예를 들어 RVIZ에서 laser_scan data를 확인할 때, reliability를 best effort로 설정해야만 data가 보인다. 이런 qos profile의 중요성을 이해하고 넘어가도록 하자.



참고 사이트

https://robot-log.me/8
https://docs.ros.org/en/rolling/Concepts/Intermediate/About-Quality-of-Service-Settings.html

0개의 댓글