---
# System prepended metadata

title: Tracing ROS2 DDS internal
tags: [Robotics]

---

###### tags: `Robotics`

# Tracing ROS2 DDS internal

## Mapping between ROS2 topic and DDS topic

觀察一個 ROS2 topic 和 DDS topic 的映射關係，可以看到在 ROS2 中叫做 chatter 的 topic，在 DDS 中加了一個 rt 的 prefix


| ROS2 topic name | DDS topic name |
| ---------- | -------- |
| `chatter`  | `rt/chatter`  |


根據 [ROS2 Design](http://design.ros2.org/articles/topic_and_service_names.html) 描述這兩者之間的映射，每種 ROS2 的傳輸類型 (如 service, action 等) 都有一個對應的 prefix，如下表

| ROS Subsystem | Prefix |
| ------------- | ------ |
| ROS Topics    | rt     |
| ROS Service Request | rq |
| ROS Service Response | rr |
| ROS Service | rs |
| ROS Parameter	| rp |
| ROS Action |	ra| 


## Get topic name in ROS2 layer
列出 ROS2 中與 publisher 相關的 struct
```cpp
// rcl/publisher.h
/// Structure which encapsulates a ROS Publisher.
typedef struct rcl_publisher_t
{
  struct rcl_publisher_impl_t * impl;
} rcl_publisher_t;


// rcl/publisher_impl.h
typedef struct rcl_publisher_impl_t
{
  rcl_publisher_options_t options;
  rmw_qos_profile_t actual_qos;
  rcl_context_t * context;
  rmw_publisher_t * rmw_handle;
} rcl_publisher_impl_t;


// rmw/types.h
typedef struct RMW_PUBLIC_TYPE rmw_publisher_t
{
  const char * implementation_identifier;
  void * data;
  const char * topic_name;
} rmw_publisher_t;
```

在 `rmw_publisher_t` 結構中包含了最底層的資訊，包括：

1. `implementation_identifier`: 使用的 DDS 版本，如 Opensplice、RTI Connext 或 fastrtps，預設是使用 fastrtps
2. `data`: 此欄位提供給不同 DDS 的 rmw_adapter 層使用，指向某個底層的物件
3. `topic_name`: 給 ROS2 使用的 topic name，底層 DDS 會使用映射過後的 topic name

### Calculate offset
使用 gdb 計算 `rmw_handle` 欄位的位移，追蹤 `rmw_publisher_t` 中的資訊
```gdb
gef➤  p/d &((rcl_publisher_t *) 0)->impl 
$55 = 0
gef➤  p/d &((rcl_publisher_impl_t *) 0)->rmw_handle 
$56 = 224
```

### Using uprobe

簡單寫個 eBPF 程式就能印出這些資訊，attach_uprobe 到 `rcl_publish()` 這個函式上

ts 代表 timestamp，implemetation 和 topic_name 為以上 `rmw_publisher_t` 中的資料成員，最右邊兩欄為 `rcl_publish()` 函式兩個參數的記憶體位址，一個指向 rcl_publisher_t 的物件，另一個為 ros_message 的位址。

```
ts              comm        pid      implementation         topic_name             publisher          ros_message       
917.22159       listener    11856    rmw_fastrtps_cpp       /parameter_events      0x558df4c1c708     0x558df4c282d0    
941.02000       talker      11953    rmw_opensplice_cpp     /parameter_events      0x55fafbcd0088     0x55fafbd4cad0    
942.03501       talker      11953    rmw_opensplice_cpp     /chatter               0x55fafbd53f68     0x55fafbd6c710    
942.03708       listener    11856    rmw_fastrtps_cpp       /rosout                0x7ffe9d2c1398     0x558df49b7c10    
942.13561       talker      11953    rmw_opensplice_cpp     /chatter               0x55fafbd53f68     0x55fafbd6c710    
942.13739       listener    11856    rmw_fastrtps_cpp       /rosout                0x7ffe9d2c1398     0x558df49b7c10
```

## `CacheChange_t`
```cpp
struct RTPS_DllAPI CacheChange_t
{
    //!Kind of change, default value ALIVE.
    ChangeKind_t kind;
    //!GUID_t of the writer that generated this change.
    GUID_t writerGUID;
    //!Handle of the data associated wiht this change.
    InstanceHandle_t instanceHandle;
    //!SequenceNumber of the change
    SequenceNumber_t sequenceNumber;
    //!Serialized Payload associated with the change.
    SerializedPayload_t serializedPayload;
    //!Indicates if the cache has been read (only used in READERS)
    bool isRead;
    //!Source TimeStamp (only used in Readers)
    Time_t sourceTimestamp;

    WriteParams write_params;
    bool is_untyped_;
}
```