# DDS 관련 로그 해석 및 에러 메시지

#### DDS 로그의 특성과 이해

ROS2 Humble에서 DDS(Dataplicity Distribution Service)는 노드 간 통신을 담당하는 핵심 미들웨어이다. DDS 구현체(예: Fast DDS, Cyclone DDS, Connext 등)마다 로그 형식과 심각도 레벨 표기 방식이 다를 수 있다. 따라서 DDS에서 출력되는 로그를 이해하고 적절히 대응하기 위해서는 다음과 같은 특성을 미리 숙지해야 한다.

1. **Discovery 과정의 로그** DDS는 로컬 네트워크 상에서 노드(Participant)를 자동으로 찾기 위해 Discovery 과정을 수행한다. 이때 Participant 간 버전, QoS 설정 불일치 또는 네트워크 이슈가 있을 경우 에러나 경고 로그가 발생한다.
   * `DISCOVERY: Participant X not found in domain Y`
   * `DISCOVERY: Inconsistent QoS between local and remote participants`
2. **QoS 불일치 관련 로그** 같은 메시지 타입이라도 QoS(Profile)가 다르면 통신이 정상적으로 이뤄지지 않는다. QoS mismatch는 DDS 레벨에서 에러 혹은 경고를 출력하며, ROS2 레벨에서 Subscriber/Publisher 간 연결 실패로 나타난다.
   * `DDS_RTPS_CreatedReader: Inconsistent QoS for Topic "example_topic"`
3. **Transport 설정 관련 로그** DDS는 UDP 또는 TCP(특정 구현체)를 통한 메시지 전송을 수행하며, 저수준 Transport 설정이 잘못되어 있으면 소켓 생성에 실패하거나 Binding 문제로 인한 에러 로그가 발생한다. 예를 들어 eProsima Fast DDS의 경우 다음과 같은 메시지가 대표적이다.
   * `TRANSPORT: Could not create receive socket on port XXXX`
   * `TRANSPORT: Failed to bind to 0.0.0.0:XXXX`

#### 에러 메시지 해석 예시: Participant 생성 문제

ROS2 노드가 실행될 때, DDS Participant가 성공적으로 생성되지 못하면 통신이 전혀 이루어지지 않는다. 대표적인 로그 예시는 아래와 같다.

**Fast DDS**:

```
1602469188.727380 [RTPS_TRANSPORT_SHM Error] Failed to create segment for SHM -> Function create_segment
1602469188.728442 [RTPS Participant Error] Could not create DomainParticipant, return code = 1
```

이 로그는 Shared Memory Transport를 활성화했으나 운영체제 권한 문제 혹은 메모리 설정 충돌로 인해 세그먼트를 생성하지 못했음을 의미한다.

**Cyclone DDS**:

```
ddsc: create_participant: failed to create domain participant (domain id=0)
ddsc: error: not enough privileges to open shared memory segment
```

이는 DomainParticipant를 만들지 못했고, 공동 메모리 영역 접근 권한이 없음을 알려 준다.

이를 해결하기 위해서는 DDS에서 사용하는 Shared Memory Transport를 비활성화하거나 OS 권한을 수정하는 방법 등을 고려할 수 있다.

#### 에러 메시지 해석 예시: QoS 설정 충돌

ROS2에서 QoS는 신뢰성(Reliable, Best Effort), 내구성(Transient Local, Volatile) 등 다양한 항목이 있다. DDS 레벨에서 QoS가 불일치하면 다음과 같은 로그가 발생한다.

* `DDS_ReaderQos: Inconsistent QoS detected between local reader and remote writer`
* `Topic "example_topic" has unmatching QoS policies with remote endpoint`

이러한 로그는 노드 간의 QoS mismatch로 인해 통신이 성사되지 않고 있음을 의미한다. 예를 들어, Publisher는 `Reliability: Reliable`를 사용하지만 Subscriber는 `Reliability: BestEffort`를 사용하는 경우 DDS 상에서 서로 인식하더라도 실제 데이터 스트리밍이 이뤄지지 않을 수 있다.

#### 에러 메시지 해석 예시: Discovery 문제

여러 노드 간 통신에서 가장 빈번하게 발생하는 문제 중 하나가 Discovery이다. 특히, 멀티캐스트 제한이나 방화벽 설정으로 인해 Discovery 패킷이 차단될 수 있다.

**Fast DDS**:

```
DISCOVERY: participant 1234@192.168.X.X could not be discovered
DISCOVERY: Timed out while waiting for remote participants
```

네트워크 구성 문제 혹은 방화벽 차단으로 인한 Discovery 단계 실패를 의미한다.

**Cyclone DDS**:

```
ddsi_discovery: no matching endpoints found for participant instance handle
ddsi_discovery: discovered participant but QoS handshake failed
```

Remote Participant를 찾았으나 QoS 핸드셰이크 과정에서 문제가 발생했음을 뜻한다.

#### 에러 메시지 해석 예시: 샘플 전송 장애

Discovery가 성공하더라도 실제로 데이터를 교환할 때 문제가 생기면 전송 장애 로그가 발생한다. 예를 들어 메시지가 특정 바이트 수 이상에서 단편화(Fragmentation)되어 전송될 때 Transport 계층에서 문제가 있을 수 있다.

* `RTPSMessageGroup: Error sending fragmented submessage`
* `SEND_BUFFER: Could not allocate enough space for the large message`

이러한 메시지가 나오면 MTU 설정, DDS 내부의 최대 세그먼트 크기 설정, 혹은 사용하는 RMW 구현체가 제공하는 Transport 버퍼 사이즈를 점검해야 한다.

#### 에러 메시지 해석 예시: Topic 타입 불일치

ROS2에서 동일한 메시지 타입을 사용하는 것처럼 보이지만, 빌드 중에 발생하는 C++ 헤더 문제나 다른 패키지 버전 불일치 등으로 실제 DDS 레벨에서 인식하는 메시지 타입이 달라지는 경우가 있다.

* `DDS_DynamicTypeSupport: Received type does not match local type for Topic "chatter"`
* `TypeError: Attempted to deserialize invalid data`

이런 상황에서는 메시지 구조체의 실제 크기나 필드가 달라 DDS의 Deserializer가 에러를 내기도 한다. 메시지 타입 이름만 같다고 해서 DDS 단에서 완전히 호환되는 것은 아니므로, 빌드 설정과 메시지 정의 파일(.idl 또는 .msg)을 재확인해야 한다.

#### 에러 메시지 해석 예시: 네임서버 혹은 DNS 관련

ROS2에서 노드 이름, service discovery 등을 수행할 때 DNS를 사용할 수 있다. 일반적으로 로컬 호스트 이름이나 IP 설정이 잘못되어 있으면 다음과 같은 DDS 에러가 발생한다.

* `DNS lookup failed for host: <hostname>`
* `Could not resolve <hostname> to a valid IP address`

이 문제를 해결하려면 `/etc/hosts` 파일 또는 내부 DNS 서버 설정을 확인하여 DDS가 노드 호스트명을 올바르게 해석할 수 있도록 해야 한다.

#### DDS 로그 수준 해석

DDS 구현체 대부분은 로그 수준(Level)을 제공하여, Debug/Info/Warning/Error/Fatal 식으로 구분한다. 예를 들어 Fast DDS에서 `--log-level warning` 옵션을 주면 경고 이상의 메시지만 출력되도록 설정할 수 있다. 실제 시스템 배포 시에는 필요 없는 정보성 로그가 과다하게 쌓이는 것을 막기 위해 로그 수준을 조절한다.

* **Debug**: DDS 내부 동작, 성능 측정에 활용
* **Info**: 정상 동작 관련 메시지(Discovery 완료, Participant 생성 등)
* **Warning**: 잠재적인 문제(설정 불일치, 비권장 사용)
* **Error**: DDS 동작에 실패, 심각한 충돌로 인해 시스템이 기능을 잃을 수 있음
* **Fatal**: 더 이상 진행이 불가능한 상황

이를 통해 시스템 모니터링 시 필요한 로그만 추려낼 수 있도록 설정하는 것이 중요하다.

#### 쉘에서 DDS 로그 레벨 조절 예시(Fast DDS)

ROS2 Humble 환경에서 eProsima Fast DDS를 사용 중이라면 다음과 같이 환경 변수를 통해 로그 레벨을 조절할 수 있다.

```bash
export FASTRTPS_DEFAULT_PROFILES_FILE=./fastdds_profiles.xml
```

그리고 `fastdds_profiles.xml` 파일 내에서 `<log>` 태그를 설정하여 로그 레벨을 세밀하게 제어할 수 있다.

```xml
<log>
    <logLevel>WARNING</logLevel>
    <filename>fastdds_log.txt</filename>
    <categoryFilter>*</categoryFilter>
    <outputFormat>%time% - %msg%</outputFormat>
</log>
```

이를 통해 DDS 로그 파일이 `fastdds_log.txt`에 기록되며, Warning 이상 레벨만 남긴다.

#### DDS 에러 분석 시의 체크포인트

DDS 관련 문제를 디버깅할 때 다음 사항을 점검하면 좋다.

1. IP/포트 충돌 및 방화벽
   * 도커 컨테이너 환경, NAT, 방화벽 설정 등을 통해 멀티캐스트 패킷이 막히는지 확인
2. Domain ID
   * 노드가 서로 같은 Domain ID를 사용하는지 확인
3. QoS 프로파일
   * Reliability, Durability, Deadline 등 주요 QoS가 서로 일치하는지 확인
4. 메시지 타입
   * .idl/.msg 정의 파일 버전이 일치하는지 확인
5. DDS 버전/빌드 옵션
   * RTI Connext, Cyclone DDS 등 서로 다른 구현체 간 호환성 이슈 점검

#### DDS Discovery 프로세스 구조와 로그 분석

DDS Discovery는 크게 다음 두 단계로 나눌 수 있다.

1. **Participant Discovery(메타데이터 교환)**
   * Simple Participant Discovery Protocol(SPDP)에 의해 서로의 Participant 정보를 브로드캐스팅 및 수신한다.
   * 여기에 문제가 있으면 "Could not find remote participant" 또는 "SPDP Packets dropped"와 같은 로그가 발생할 수 있다.
2. **Endpoint Discovery(토픽/타입 정보 교환)**
   * Participant 정보를 교환한 뒤, 해당 Participant에 속한 Publisher/Subscriber(Endpoint) 정보를 교환한다.
   * SEDP(Simple Endpoint Discovery Protocol)을 사용하며, 토픽명, 타입명, QoS 등을 주고받는다.
   * "No matching endpoints found" 또는 "Type mismatch detected for Topic" 등 로그가 이 단계에서 발생한다.

**SPDP 단계에서 발생하는 에러 로그 예시**

* `SPDP: discovered participant has invalid vendor ID`
* `SPDP: timed out waiting for participant <GUID>`

이는 서로 다른 DDS 구현체 간 호환성 문제 또는 네트워크 레벨에서 브로드캐스팅이 차단되었음을 의심해 볼 수 있다.

**SEDP 단계에서 발생하는 에러 로그 예시**

* `SEDP: Reader for topic "foo_topic" could not be matched with remote writer`
* `SEDP: Endpoint creation failed due to QoS mismatch`

이 때는 구체적인 토픽명과 QoS가 어느 지점에서 불일치하는지 자세히 살펴봐야 한다.

#### Wireshark를 활용한 DDS 패킷 분석

DDS 로그만으로 문제가 해결되지 않을 때는 Wireshark 같은 패킷 스니퍼 툴을 활용할 수 있다. Wireshark는 기본적으로 RTPS(Real-Time Publish-Subscribe) 프로토콜을 디코딩할 수 있다.

* **필터 예시**: `rtps` RTPS 패킷만 추출하여 Discovery 패킷의 송수신 여부를 확인한다.
* 주요 필드

  :

  * SPDP(Participant) 패킷
  * SEDP(Writer/Reader) 패킷
  * DATA/DATA\_FRAG 서브메시지

이러한 패킷을 보면 각 스테이지에서 어떤 메시지가 오고 가는지, QoS나 토픽 정보를 교환하는지 여부를 좀 더 구체적으로 확인 가능하다.

#### DDS 에러 발생 시 흔히 놓치는 설정 요소

1. **TCP/UDP 전송 모드 충돌**
   * 일부 DDS 구현체는 TCP를 사용할 수 있으나, ROS2 기본 구성은 주로 UDP 기반이다.
   * ROS2가 사용하는 RMW 계층 설정이 UDP이지만, DDS 쪽에서 TCP만 활성화되어 있으면 통신이 이루어지지 않고 에러 로그가 발생할 수 있다.
2. **멀티캐스트 IP 범위 제한**
   * 멀티캐스트를 사용하는 네트워크 대역(예: 239.x.x.x)을 방화벽 또는 라우터에서 차단하면 Discovery가 실패한다.
3. **Shared Memory Transport(로컬 환경)**
   * 같은 호스트 내 컨테이너끼리 통신 시 쉐어드 메모리 전송이 활성화되면, 컨테이너 간에는 실제로 메모리를 공유할 수 없어서 에러가 난다.
   * 이 경우, "Failed to create SHM segment" 로그가 대표적으로 나타난다.
4. **IPv6/IPv4 동시 사용 충돌**
   * 어느 시스템에서는 IPv6를 활성화했으나 DDS가 IPv4만 듣고 있으면, 로그에 `No valid IPv6 address found`와 같은 경고가 뜰 수 있다.
   * 결과적으로 Discovery 과정에서 참가자끼리 서로 주소를 교환하지 못한다.

#### DDS 레이어에서의 타임아웃 로그

일정 시간 안에 Discovery 응답이 오지 않거나, 메시지 전송 확인이 되지 않을 때 DDS 레벨에서 타임아웃 로그가 발생한다.

* `DISCOVERY: Timed out while waiting for participant with GUID ...`
* `WRITER: Timed out waiting for ACK from remote reader`

이 경우 네트워크 레이턴시, QoS의 Deadline/LatencyBudget, 방화벽, NAT 등을 종합적으로 살펴봐야 한다. 특히, 무선 LAN 환경에서의 패킷 손실률이 높을 경우 Timed out 로그가 자주 관측될 수 있다.

#### 실제 로그 예시와 단계별 해석

다음은 Fast DDS에서 QoS 문제로 인해 Discovery가 완전히 이루어지지 않고 있는 상황을 가정한 예시 로그이다.

```bash
[RTPS_PARTICIPANT Error] SimpleEDP::processLocalReaderProxyData() -- Inconsistent QoS for writer 92.1.5.6
[RTPS_PARTICIPANT Warning] Remote Participant discovery failed for participant 72.0.13.4
[DISCOVERY Info] Found new participant 72.0.13.4 but could not match endpoints
```

1. 이전 단계에서 participant를 발견
   * `Found new participant 72.0.13.4`
2. 하지만 엔드포인트(Writer/Reader)간 QoS가 일치하지 않음
   * `Inconsistent QoS for writer 92.1.5.6`
3. Discovery가 완료되지 않아 엔드포인트를 매칭하지 못함
   * `could not match endpoints`

이런 경우 Participant 자체는 발견했지만, 실제 Topic을 주고받는 단계에서 QoS 충돌이 있으므로 통신에 실패한다.

#### DDS 로그를 통한 성능 모니터링

DDS 로그에는 에러/경고뿐 아니라 성능 정보(패킷 전송 간격, 데이터 처리량 등)를 담은 Debug/Info 메시지도 포함될 수 있다. 예를 들어 다음과 같은 로그가 반복된다면, 네트워크 병목이나 성능 이슈를 의심할 수 있다.

* `WRITER: High latency detected on topic "xyz_topic"`
* `READER: Data read took longer than expected`

또한, 프로파일링 툴(예: eProsima Fast DDS Monitor, RTI Admin Console 등)을 연계해 DDS 로그와 성능 통계를 함께 확인하면 문제의 원인을 좁히는 데 도움이 된다.

#### DDS 로그와 ROS2 노드 로깅의 연계

ROS2에서는 DDS 로그와 별개로 rclcpp/rclpy에서 제공하는 로깅 매크로(예: `RCLCPP_ERROR`, `RCLCPP_WARN` 등)를 통해 각 노드에서 자체 로그를 남긴다. 두 로깅 정보를 함께 보면 다음과 같은 시나리오를 추적할 수 있다.

1. 노드에서 특정 토픽에 Publish 요청
2. ROS2 레벨에서는 정상 동작 로그 출력
3. DDS 레벨에서 전송 실패 로그 출력
4. 노드에서 Subscriber 쪽 콜백이 호출되지 않음

이를 근거로 ROS2와 DDS 간 인터페이스 어디에서 문제가 생기는지 정확히 구분할 수 있다.
