00 DDS Neden? Broker-less Mimari
MQTT ve AMQP gibi broker tabanlı sistemler tek nokta hata riski taşır ve gecikme ekler. DDS broker gerektirmeyen, şema-farkında, gerçek zamanlı bir yayın/abonelik middleware'idir.
Broker Tabanlı Mimarinin Sınırları
DDS'in Kullanıldığı Alanlar
| Alan | Kullanım Örneği | Standart |
|---|---|---|
| Otonom araç | Sensör füzyonu, aktüatör komutları, araç durumu | AUTOSAR Adaptive |
| Robot yazılımı | ROS 2 middleware katmanı (rmw) | OMG DDS |
| Savunma / havacılık | Uçuş veri bus alternatifi (FACE standardı) | OMG DDS-FACE |
| Tıbbi cihaz | Gerçek zamanlı hasta verisi dağıtımı | OMG DDS |
| Endüstriyel SCADA | PLC ile HMI ve tarihsel veri tabanı | IEC 62541 + DDS |
| Deniz sistemleri | STANAG 4586 UAV kontrol sistemi | STANAG + DDS |
Topoloji Karşılaştırması
[MQTT] Yayinci --> Broker --> Abone
(2 sicrama, merkezi, SPOF)
[DDS] Yayinci <--RTPS/UDP--> Abone
(dogrudan, dagitik, broker yok)
[gRPC] Istemci --> Sunucu
(istek/yanit, noktadan noktaya)
[DDS] DataWriter ---(kesif)---> DataReader
(veri merkezli, cok-cok)
01 DDS Kavramları ve Hiyerarşi
DDS varlık hiyerarşisi Domain, Participant, Publisher/Subscriber, DataWriter/DataReader zincirinden oluşur. Topic ortak veri sözleşmesini tanımlar.
Temel Varlık Hiyerarşisi
Domain (sayisal kimlik: 0, 1, ...)
|
+-- DomainParticipant (surec / makine temsili)
|
+-- Publisher
| +-- DataWriter (Topic'e veri yazar)
|
+-- Subscriber
| +-- DataReader (Topic'ten veri okur)
|
+-- Topic (ad + tip + QoS)
Domain ve Katılımcı
Domain, DDS iletişimini mantıksal olarak yalıtır. Farklı domain kimliklerine sahip katılımcılar birbirini göremez. Bu özellik alt sistemlerin birbirinden izole edilmesini sağlar:
Topic ve IDL Veri Tipi Tanımı
Topic, konuya özgü veri yapısını (IDL ile tanımlanan) ve adını birleştirir. IDL (Interface Definition Language) dil bağımsız veri tanımı sağlar:
// sensors.idl
module Sensors {
struct Temperature {
@key string sensor_id; // @key: katilimci kimligi (instance)
float value; // Celsius cinsinden sicaklik
long timestamp; // Unix millisaniye
boolean alarmed; // Esik asimi bayragi
};
struct IMUData {
@key string unit_id;
float accel_x;
float accel_y;
float accel_z;
float gyro_x;
float gyro_y;
float gyro_z;
};
};
IDL'den C Kodu Üretimi (fastddsgen)
# eProsima Fast-DDS ile IDL derleyici
fastddsgen -cs sensors.idl
# Uretilen dosyalar:
# sensors.h -- struct tanimlari
# sensorsPubSubTypes.h -- serializasyon/deserializasyon
# sensorsCdrAux.h -- CDR (Common Data Representation)
# Cyclone DDS ile IDL derleyici
idlc -l c sensors.idl
# Uretilen: sensors.h, sensors.c
DataWriter ve DataReader İlişkisi
| Varlık | Görevi |
|---|---|
| DomainParticipant | Domain'e giriş noktası; keşif (discovery) başlatır |
| Topic | Veri adı + tipi + QoS tanımı; paylaşılan sözleşme |
| Publisher | DataWriter'ların konteyner nesnesi |
| DataWriter | Topic'e veri yazar; yayıncı rolü |
| Subscriber | DataReader'ların konteyner nesnesi |
| DataReader | Topic'ten veri okur; abone rolü |
02 QoS Politikaları
QoS (Quality of Service) politikaları veri teslimat davranışını kontrol eder. DataWriter ve DataReader QoS'larının uyumlu olması eşleşme için zorunludur; uyumsuzluk sessiz eşleşme başarısızlığına yol açar.
Temel QoS Politikaları
| Politika | Değerler | Etkisi | Uyum Kuralı |
|---|---|---|---|
| RELIABILITY | BEST_EFFORT / RELIABLE | Kayıp veri toleransı | DW >= DR gerekir |
| DURABILITY | VOLATILE / TRANSIENT_LOCAL / TRANSIENT | Yeni abonelere geçmiş veri | DW >= DR gerekir |
| HISTORY | KEEP_LAST(n) / KEEP_ALL | Kuyruk derinliği | Bağımsız |
| DEADLINE | period = Duration | Yeni veri beklenen maksimum aralık | DW <= DR gerekir |
| LIVELINESS | AUTOMATIC / MANUAL | Yayıncı canlılık teyidi | DW >= DR gerekir |
| LIFESPAN | Duration | Veri geçerlilik süresi; eskiyen veri atılır | Bağımsız |
| RESOURCE_LIMITS | max_samples, max_instances | Bellek tüketim sınırı | Bağımsız |
DURABILITY Politikası Davranışı
VOLATILE: [W yazar] [R baginlir] --> yalnizca baginlanmadan sonraki veri alinir Sensor verisi, canli kontrol komutu icin uygundur TRANSIENT_LOCAL: [W yazar] [R baginlir] --> HISTORY derinligi kadar gecmis alinir Konfigurasyonu gec gelen abone icin uygundur TRANSIENT: [W kapanir] [W tekrar acar] --> veri ayri servis tarafindan korunur Sistem yeniden baslatmalarinda veri kaybi olmaz
Gömülü Sistem için Önerilen QoS Kombinasyonları
03 Cyclone DDS Kurulumu
Eclipse Cyclone DDS, OMG DDS standardının hafif ve hızlı C/C++ implementasyonudur. ROS 2 ile birlikte çalışır ve Yocto meta-ros katmanıyla gömülü sistemlere entegre edilir.
Ubuntu / Debian Kurulumu
# Paket yoneticisi ile
sudo apt install ros-humble-cyclonedds # ROS 2 ile
# veya bagimsiz:
sudo apt install cyclonedds-dev
# Kaynak koddan derleme
git clone https://github.com/eclipse-cyclonedds/cyclonedds.git
cd cyclonedds
mkdir build && cd build
cmake .. \
-DCMAKE_BUILD_TYPE=Release \
-DBUILD_EXAMPLES=ON \
-DENABLE_SSL=ON
make -j$(nproc)
sudo make install
CMake Entegrasyonu
cmake_minimum_required(VERSION 3.16)
project(dds_sensor_app C)
find_package(CycloneDDS REQUIRED)
# IDL dosyasindan kod uret
idlc_generate(TARGET sensors_idl
FILES sensors.idl
WARNINGS no-implicit-extensibility)
# Uygulamayi derle
add_executable(sensor_publisher publisher.c)
target_link_libraries(sensor_publisher
sensors_idl
CycloneDDS::ddsc)
add_executable(sensor_subscriber subscriber.c)
target_link_libraries(sensor_subscriber
sensors_idl
CycloneDDS::ddsc)
Yocto Meta-ROS ile Gömülü Linux
# meta-ros katmanini ekle
git clone https://github.com/ros/meta-ros.git \
/path/to/poky/meta-ros
# bblayers.conf
BBLAYERS += " \
/path/to/poky/meta-ros/meta-ros2 \
/path/to/poky/meta-ros/meta-ros2-humble \
"
# local.conf -- minimal DDS imaji
IMAGE_INSTALL:append = " \
ros-humble-cyclonedds \
ros-humble-rmw-cyclonedds-cpp \
"
# Sadece Cyclone DDS (ROS 2 olmadan)
IMAGE_INSTALL:append = " cyclonedds"
Cross-Compilation (ARM64)
# toolchain-aarch64.cmake
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR aarch64)
set(CMAKE_C_COMPILER aarch64-linux-gnu-gcc)
set(CMAKE_CXX_COMPILER aarch64-linux-gnu-g++)
set(CMAKE_SYSROOT /usr/aarch64-linux-gnu)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
# Cross-compile komutu
cmake .. \
-DCMAKE_TOOLCHAIN_FILE=toolchain-aarch64.cmake \
-DCMAKE_BUILD_TYPE=Release \
-DBUILD_SHARED_LIBS=ON \
-DENABLE_SSL=OFF \
-DBUILD_EXAMPLES=OFF
make -j$(nproc)
04 İlk Yayın / Abonelik Uygulaması
Cyclone DDS C API'si ile tam işlevsel yayın/abonelik uygulaması yazılır. Participant, topic, writer ve reader oluşturma adımları gösterilir.
Yayıncı (Publisher) — Tam C Örneği
#include "dds/dds.h"
#include "sensors.h" /* IDL'den uretildi */
#include <stdio.h>
#include <string.h>
#include <unistd.h>
int main(void)
{
dds_entity_t participant, topic, writer;
dds_qos_t *qos;
dds_return_t rc;
Sensors_Temperature msg;
/* 1. Domain Participant olustur (domain 0) */
participant = dds_create_participant(0, NULL, NULL);
if (participant < 0) {
fprintf(stderr, "Participant olusturulamadi: %s\n",
dds_strretcode(-participant));
return 1;
}
/* 2. Topic olustur */
topic = dds_create_topic(
participant,
&Sensors_Temperature_desc,
"SensorTemperature",
NULL, NULL);
if (topic < 0) {
fprintf(stderr, "Topic olusturulamadi\n");
return 1;
}
/* 3. QoS ayarla -- guvenilir, gecici yerel */
qos = dds_create_qos();
dds_qset_reliability(qos,
DDS_RELIABILITY_RELIABLE,
DDS_MSECS(1000));
dds_qset_durability(qos,
DDS_DURABILITY_TRANSIENT_LOCAL);
dds_qset_history(qos,
DDS_HISTORY_KEEP_LAST, 10);
/* 4. DataWriter olustur */
writer = dds_create_writer(participant, topic, qos, NULL);
dds_delete_qos(qos);
if (writer < 0) {
fprintf(stderr, "Writer olusturulamadi\n");
return 1;
}
printf("Yayinci baslatildi. Veri gonderiliyor...\n");
/* 5. Veri gonder */
memset(&msg, 0, sizeof(msg));
for (int i = 0; i < 20; i++) {
msg.sensor_id = "rpi4-sensor-01";
msg.value = 20.0f + (float)i * 0.5f;
msg.timestamp = (long)(i * 1000);
msg.alarmed = (msg.value > 27.0f);
rc = dds_write(writer, &msg);
if (rc != DDS_RETCODE_OK) {
fprintf(stderr, "Yazma hatasi: %s\n",
dds_strretcode(-rc));
} else {
printf("[%d] Gonderildi: %.1f C%s\n",
i, msg.value,
msg.alarmed ? " [ALARM]" : "");
}
sleep(1);
}
/* 6. Temizlik */
dds_delete(participant);
return 0;
}
Abone (Subscriber) — Tam C Örneği
#include "dds/dds.h"
#include "sensors.h"
#include <stdio.h>
#include <string.h>
/* Listener callback: veri hazir oldugunda cagirilir */
static void
on_data_available(dds_entity_t reader, void *arg)
{
Sensors_Temperature msg;
void *samples[1] = { &msg };
dds_sample_info_t info[1];
int32_t n;
(void)arg;
memset(&msg, 0, sizeof(msg));
n = dds_take(reader, samples, info, 1, 1);
if (n < 0) {
fprintf(stderr, "Okuma hatasi: %s\n",
dds_strretcode(-n));
return;
}
if (n > 0 && info[0].valid_data) {
printf("Alindi [%s]: %.1f C, alarm=%s\n",
msg.sensor_id,
msg.value,
msg.alarmed ? "EVET" : "hayir");
}
}
int main(void)
{
dds_entity_t participant, topic, subscriber, reader;
dds_listener_t *listener;
dds_qos_t *qos;
participant = dds_create_participant(0, NULL, NULL);
topic = dds_create_topic(
participant,
&Sensors_Temperature_desc,
"SensorTemperature",
NULL, NULL);
qos = dds_create_qos();
dds_qset_reliability(qos,
DDS_RELIABILITY_RELIABLE,
DDS_MSECS(1000));
dds_qset_durability(qos,
DDS_DURABILITY_TRANSIENT_LOCAL);
/* Listener ile asenkron okuma */
listener = dds_create_listener(NULL);
dds_lset_data_available(listener, on_data_available);
reader = dds_create_reader(
participant, topic, qos, listener);
dds_delete_qos(qos);
printf("Abone bekleniyor... Ctrl+C ile dur.\n");
/* Mesaj alindi bildirimi bekle */
uint32_t mask = DDS_DATA_AVAILABLE_STATUS;
while (1) {
dds_waitset_wait(
dds_create_waitset(participant),
NULL, 0, DDS_INFINITY);
}
dds_delete(participant);
return 0;
}
05 Güvenilir İletim
RELIABLE QoS, HEARTBEAT/ACKNACK mekanizması ile kayıpsız veri teslimatını garanti eder. Sample kaybı tespiti ve deadline miss bildirimleri uygulamada ele alınmalıdır.
RELIABLE İletim Akışı
DataWriter DataReader | | |-- DATA (seq=1) --------------->| Alindi |-- DATA (seq=2) --------------->| Alindi |-- DATA (seq=3) -------X | KAYIP |-- DATA (seq=4) --------------->| | | |<-- HEARTBEAT talep (seq 1-4) --| | | |-- GAP (seq=3 eksik) ---------->| veya |-- DATA (seq=3) tekrar --------->| Yeniden gonderildi | | |<-- ACKNACK (seq 1-4 OK) -------| Tum alinanlarin teyidi
Sample Kaybı Dinleyicisi
#include "dds/dds.h"
/* Sample kaybi callback'i */
static void
on_sample_lost(dds_entity_t reader,
const dds_sample_lost_status_t *status,
void *arg)
{
printf("SAMPLE KAYBI: toplam=%d, son_artas=%d\n",
status->total_count,
status->total_count_change);
}
/* Deadline miss callback'i */
static void
on_requested_deadline_missed(
dds_entity_t reader,
const dds_requested_deadline_missed_status_t *status,
void *arg)
{
printf("DEADLINE GECILDI: toplam=%d\n",
status->total_count);
/* Yayincinin olup olmadigini kontrol et */
}
/* QoS uyumsuzlugu callback'i */
static void
on_requested_incompatible_qos(
dds_entity_t reader,
const dds_requested_incompatible_qos_status_t *status,
void *arg)
{
printf("QoS UYUMSUZLUGU: politika kimlik=%d\n",
status->last_policy_id);
/* 11 = RELIABILITY, 7 = DURABILITY */
}
/* Listener kaydi */
void setup_reader_listeners(dds_entity_t reader)
{
dds_listener_t *l = dds_create_listener(NULL);
dds_lset_sample_lost(l, on_sample_lost);
dds_lset_requested_deadline_missed(
l, on_requested_deadline_missed);
dds_lset_requested_incompatible_qos(
l, on_requested_incompatible_qos);
dds_set_listener(reader, l);
dds_delete_listener(l);
}
Deadline QoS Yapılandırması
/* Writer tarafinda deadline: her 100 ms'de en az 1 ornek */
dds_qos_t *wqos = dds_create_qos();
dds_qset_deadline(wqos, DDS_MSECS(100));
dds_qset_reliability(wqos,
DDS_RELIABILITY_RELIABLE, DDS_MSECS(500));
dds_entity_t writer = dds_create_writer(
participant, topic, wqos, NULL);
/* Reader tarafinda deadline: 100 ms gecerse bildir */
dds_qos_t *rqos = dds_create_qos();
dds_qset_deadline(rqos, DDS_MSECS(100));
dds_qset_reliability(rqos,
DDS_RELIABILITY_RELIABLE, DDS_MSECS(500));
dds_entity_t reader = dds_create_reader(
participant, topic, rqos, listener);
06 Gömülü Kaynak Yönetimi
Bellek kısıtlı gömülü Linux sistemlerinde DDS ayak izini küçültmek için BEST_EFFORT modu, küçük HISTORY derinlikleri ve statik discovery yapılandırması kullanılır.
BEST_EFFORT Modu — Düşük Yük
/* Yuksek frekanslı sensör verisi için BEST_EFFORT */
dds_qos_t *qos = dds_create_qos();
/* BEST_EFFORT: kayip kabul edilebilir, ACK/NACK mekanizmasi yok */
dds_qset_reliability(qos,
DDS_RELIABILITY_BEST_EFFORT, 0);
/* KEEP_LAST(1): yalnizca en son deger tutulur */
dds_qset_history(qos, DDS_HISTORY_KEEP_LAST, 1);
/* VOLATILE: gecmis veri gonderilmez */
dds_qset_durability(qos, DDS_DURABILITY_VOLATILE);
/* Kaynak limitleri: bellek tasarrufu */
dds_qset_resource_limits(qos,
4, /* max_samples */
2, /* max_instances */
2); /* max_samples_per_instance */
dds_entity_t writer = dds_create_writer(
participant, topic, qos, NULL);
Statik Discovery (Dinamik Multicast Yok)
# cyclonedds.xml -- statik katilimci yapılandırmasi
# Dinamik SPDP multicast yerine bilinen adresler kullan
<CycloneDDS xmlns="https://cdds.io/config">
<Domain id="any">
<General>
<Interfaces>
<NetworkInterface name="eth0" />
</Interfaces>
</General>
<Discovery>
<!-- Multicast devre disi -- bilinen adresler kullan -->
<Peers>
<Peer address="192.168.1.10"/>
<Peer address="192.168.1.20"/>
</Peers>
<MaxAutoParticipantIndex>5</MaxAutoParticipantIndex>
</Discovery>
<Internal>
<!-- Fragment boyutu: kucuk paketler icin -->
<FragmentSize>1344</FragmentSize>
<!-- Gonlarim buffer boyutu azalt -->
<SendRevisionPeriod>0 s</SendRevisionPeriod>
</Internal>
</Domain>
</CycloneDDS>
# Ortam degiskeni ile yukle
export CYCLONEDDS_URI=file:///etc/cyclonedds.xml
Bellek Kullanımı — Kıyaslama
| Yapılandırma | RAM Kullanımı | Uygun Senaryo |
|---|---|---|
| RELIABLE + KEEP_ALL + dinamik discovery | ~15-30 MB | Güçlü gömülü Linux (i.MX8) |
| RELIABLE + KEEP_LAST(10) + statik discovery | ~5-10 MB | Raspberry Pi, BeagleBone |
| BEST_EFFORT + KEEP_LAST(1) + statik discovery | ~2-4 MB | Kısıtlı ARM Cortex-A5/A7 |
| Micro XRCE-DDS (MCU tarafı) | <64 KB | STM32, ESP32, FreeRTOS |
07 DDS-XRCE ile MCU Entegrasyonu
Micro XRCE-DDS, kaynak kısıtlı mikrodenetleyicileri (STM32, ESP32, FreeRTOS) DDS ağına bağlar. XRCE-DDS protokolü bir Agent aracısı üzerinden çalışır; MCU tarafında çalışan istemci, agent üzerinden tam DDS varlıkları oluşturur.
XRCE-DDS Mimarisi
[MCU -- FreeRTOS / Zephyr] [Linux Agent] [DDS Agi] micro-XRCE istemci XRCE-DDS Agent | | | |---(UART / UDP / SPI)---> | | | XRCE Protocol |---(Cyclone DDS)-->| |<-----------------------------------|<------------------| | komut yaniti / veri | |
Linux'ta XRCE-DDS Agent Kurulumu
git clone https://github.com/eProsima/Micro-XRCE-DDS-Agent.git
cd Micro-XRCE-DDS-Agent
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
make -j$(nproc)
sudo make install
# UDP Agent (MCU UDP 2018 portuna baglanir)
MicroXRCEAgent udp4 --port 2018
# UART Agent (STM32 seri port, 115200 baud)
MicroXRCEAgent serial --dev /dev/ttyUSB0 -b 115200
# CAN-FD Agent (otomotiv)
MicroXRCEAgent canfd --dev can0
MCU Tarafı — FreeRTOS + Micro-XRCE İstemci
/* STM32 / FreeRTOS -- Micro-XRCE istemci ornegi */
#include <uxr/client/client.h>
#include <ucdr/microcdr.h>
#define AGENT_IP "192.168.1.100"
#define AGENT_PORT 2018
void dds_sensor_task(void *pvParameters)
{
uxrUDPTransport transport;
uxrUDPPlatform platform;
/* Agent baglantisi */
uxr_init_udp_transport(&transport, &platform,
UXR_IPv4, AGENT_IP, AGENT_PORT);
/* Oturum baslatma */
uxrSession session;
uxr_init_session(&session, &transport.comm,
0xAAAABBBB /* oturum ID */);
if (!uxr_create_session(&session)) {
/* Baglanti hatasi */
vTaskDelete(NULL);
return;
}
/* Guvenilir cikis stream */
uint8_t output_buf[512];
uxrStreamId rel_out = uxr_create_output_reliable_stream(
&session, output_buf, sizeof(output_buf), 1);
/* Participant olustur (XML ile) */
uxrObjectId pid = uxr_object_id(1, UXR_PARTICIPANT_ID);
uxr_buffer_create_participant_xml(
&session, rel_out, pid, 0,
"<dds><participant><rtps>"
"<name>mcu_participant</name>"
"</rtps></participant></dds>",
UXR_REPLACE);
/* Topic, Publisher, DataWriter olustur */
uxrObjectId tid = uxr_object_id(1, UXR_TOPIC_ID);
uxr_buffer_create_topic_xml(
&session, rel_out, tid, pid, 0,
"<dds><topic>"
"<name>SensorTemperature</name>"
"<dataType>Sensors::Temperature</dataType>"
"</topic></dds>",
UXR_REPLACE);
uxrObjectId pub_id = uxr_object_id(1, UXR_PUBLISHER_ID);
uxr_buffer_create_publisher_xml(
&session, rel_out, pub_id, pid, 0,
"<publisher/>", UXR_REPLACE);
uxrObjectId dw_id = uxr_object_id(1, UXR_DATAWRITER_ID);
uxr_buffer_create_datawriter_xml(
&session, rel_out, dw_id, pub_id, 0,
"<datawriter>"
"<topic><kind>NO_KEY</kind></topic>"
"</datawriter>",
UXR_REPLACE);
uxr_run_session_time(&session, 500);
/* Veri yayini dongusu */
uint8_t topic_buf[64];
while (1) {
float temp = read_adc_temperature();
ucdrBuffer ub;
ucdr_init_buffer(&ub, topic_buf, sizeof(topic_buf));
ucdr_serialize_string(&ub, "stm32-sensor-01");
ucdr_serialize_float(&ub, temp);
ucdr_serialize_int32_t(&ub, xTaskGetTickCount());
ucdr_serialize_bool(&ub, temp > 75.0f);
uxr_prepare_output_stream(
&session, rel_out, dw_id,
&ub, ucdr_buffer_length(&ub));
uxr_run_session_time(&session, 100);
vTaskDelay(pdMS_TO_TICKS(500));
}
}
08 Hata Ayıklama
Cyclone ddsperf ile performans ölçümü yapılır; OpenDDS Monitor veya Fast-DDS Monitor ile varlıklar izlenir; Wireshark RTPS dissector ile ağ paketleri analiz edilir.
ddsperf ile Performans Ölçümü
# Cyclone DDS ile birlikte gelen performans araci
# Gecikme olcumu (publisher <--> subscriber)
ddsperf pub &
ddsperf sub
# Verim testi (throughput)
ddsperf --size 1024 --duration 30 pub &
ddsperf --size 1024 sub
# Ornek cikti:
# Round-trip latency: avg=45 us, min=12 us, max=200 us
# Throughput: 850 MB/s (loopback, SHM transport)
# Uzak makine arasi gecikme
ddsperf --peer 192.168.1.20 pub &
ddsperf sub
# Ortalama gecikme: ~200 us (UDP, LAN)
Wireshark RTPS Dissector
# Wireshark ile RTPS trafigi yakalama
tcpdump -i eth0 -w rtps.pcap udp
# Wireshark filtreleri:
# Tum RTPS:
rtps
# Yalnizca DATA alt mesajlari:
rtps.sm.id == 0x15
# SPDP kesif mesajlari (multicast, port 7400):
udp.dstport == 7400
# Belirli GUID ile filtrele:
rtps.guid_prefix == 01:0f:1a:2b:3c:4d:5e:6f:7a:8b:9c:0d
# Yalnizca HEARTBEAT mesajlari:
rtps.sm.id == 0x07
# RTPS paket boyutuna gore siralama Wireshark'ta:
# Statistics -> Protocol Hierarchy -> RTPS
Cyclone DDS Log Seviyeleri
# cyclonedds.xml ile log yapilandirmasi
<CycloneDDS>
<Domain>
<Tracing>
<!-- Seviyeler: FINEST, FINER, FINE, CONFIG,
INFO, WARNING, SEVERE -->
<Verbosity>CONFIG</Verbosity>
<OutputFile>/var/log/cyclonedds.log</OutputFile>
</Tracing>
</Domain>
</CycloneDDS>
# Ortam degiskeni ile hizli degistirme
export CYCLONEDDS_URI="<CycloneDDS><Domain><Tracing>\
<Verbosity>FINE</Verbosity></Tracing></Domain></CycloneDDS>"
Yaygın Sorunlar ve Çözümleri
| Sorun | Olası Neden | Çözüm |
|---|---|---|
| DataWriter/DataReader eşleşmiyor | QoS uyumsuzluğu (RELIABILITY veya DURABILITY) | on_requested_incompatible_qos callback'ini incele, politika ID'sini bul |
| Keşif yok — multicast engeli | Güvenlik duvarı UDP 7400 portunu engelliyor | sudo ufw allow 7400/udp; veya statik peers kullan |
| Yüksek gecikme (aynı makine) | SHM transport devre dışı | cyclonedds.xml'de SharedMemory transport etkinleştir |
| Sample kaybı (RELIABLE mod) | HISTORY derinliği çok az, gönderici hızı fazla | KEEP_LAST derinliğini artır veya RESOURCE_LIMITS ayarla |
| Yüksek CPU (keşif) | SPDP çok sık gönderiliyor | Discovery/LeaseDuration artır; statik discovery'e geç |
| XRCE-DDS agent bağlantısı kurulamıyor | Firewall UDP 2018 engelliyor | iptables -I INPUT -p udp --dport 2018 -j ACCEPT |
Fast-DDS Monitor ile Görsel İzleme
# Fast-DDS Monitor kurulumu (Qt5 gerektirir)
git clone https://github.com/eProsima/Fast-DDS-monitor.git
cd Fast-DDS-monitor && mkdir build && cd build
cmake .. && make -j$(nproc)
./bin/fastdds_monitor
# Monitorde gorulebilecekler:
# - Domain katilimcilari listesi
# - Topic listesi ve DataWriter/DataReader ciftleri
# - QoS bilgisi ve uyumsuzluk uyarilari
# - GUID ve locator (IP:port) bilgisi
# - Gercek zamanli mesaj sayaci ve verim grafigi
# Fast-DDS discovery CLI ile hizli kontrol
fastdds discovery -d 0 -v
# Cikti: tum katilimci GUID'leri, topic'ler, QoS ayarlari