├── LICENSE ├── DDS_Optimizer.py └── README.md /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 DGIST CSI LAB 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /DDS_Optimizer.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import sys 3 | import math 4 | 5 | def parse_args(args): 6 | """Parse command line arguments""" 7 | params = {} 8 | for arg in args: 9 | if '=' in arg: 10 | key, val = arg.split('=') 11 | params[key.strip()] = float(val.strip()) 12 | return params 13 | 14 | def compute_parameters(params): 15 | """Compute QoS parameters""" 16 | r = params.get("r", 10) 17 | u = params.get("u", 100000) 18 | T = params.get("T", 1e8) 19 | w = params.get("w", 0.5) 20 | 21 | retrans_ns = int(1e9 / (2 * r)) 22 | history_cache = math.floor(T / u) 23 | 24 | return { 25 | "r": int(r), 26 | "u": int(u), 27 | "T": int(T), 28 | "w": w, 29 | "retrans_ns": retrans_ns, 30 | "history_cache": history_cache 31 | } 32 | 33 | def generate_publisher_xml(params, output_file): 34 | """Generate Publisher XML""" 35 | xml_content = f""" 36 | 37 | 38 | 39 | 40 | udp_transport 41 | UDPv4 42 | 1472 43 | 44 | 45 | 46 | 47 | 48 | udp_transport 49 | 50 | false 51 | 52 | 53 | 54 | 55 | 56 | KEEP_ALL 57 | 58 | 59 | {params['history_cache']} 60 | 10 61 | {params['history_cache']} 62 | 63 | 64 | 65 | true 66 | 67 | RELIABLE 68 | 69 | 1000 70 | 71 | 72 | 73 | 74 | 75 | 0 76 | 77 | 78 | 0 79 | {params['retrans_ns']} 80 | 81 | 82 | 0 83 | 84 | 85 | 0 86 | 87 | 88 | 89 | 90 | 91 | """ 92 | with open(output_file, "w") as f: 93 | f.write(xml_content) 94 | print(f"[INFO] Publisher XML: {output_file}") 95 | 96 | def generate_subscriber_xml(params, output_file): 97 | """Generate Subscriber XML""" 98 | xml_content = f""" 99 | 100 | 101 | 102 | 103 | udp_transport 104 | UDPv4 105 | 1472 106 | 107 | 108 | 109 | 110 | 111 | udp_transport 112 | 113 | false 114 | 115 | 116 | 117 | 118 | 119 | {params['history_cache']} 120 | 10 121 | {params['history_cache']} 122 | 123 | 124 | 125 | 126 | AUTOMATIC 127 | 128 | DURATION_INFINITY 129 | 130 | 131 | DURATION_INFINITY 132 | 133 | 134 | 135 | 136 | 137 | 0 138 | 0 139 | 140 | 141 | 0 142 | 0 143 | 144 | 145 | 146 | 147 | 148 | """ 149 | with open(output_file, "w") as f: 150 | f.write(xml_content) 151 | print(f"[INFO] Subscriber XML: {output_file}") 152 | 153 | def main(): 154 | required_keys = {"r", "u", "T", "w"} 155 | 156 | if len(sys.argv) < 2: 157 | print("Usage: python3 DDS_Optimizer.py r=30 u=330000 T=90000000 w=0.6") 158 | sys.exit(1) 159 | 160 | args = parse_args(sys.argv[1:]) 161 | if not required_keys.issubset(args.keys()): 162 | print("Usage: python3 DDS_Optimizer.py r=30 u=330000 T=90000000 w=0.6") 163 | sys.exit(1) 164 | 165 | qos = compute_parameters(args) 166 | pub_filename = "Optimized_profile_pub.xml" 167 | sub_filename = "Optimized_profile_sub.xml" 168 | 169 | generate_publisher_xml(qos, pub_filename) 170 | generate_subscriber_xml(qos, sub_filename) 171 | 172 | print(f"[INFO] HistoryCache_size = {qos['history_cache']} | Retransmission_ns = {qos['retrans_ns']}") 173 | 174 | if __name__ == "__main__": 175 | main() 176 | 177 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DDS Optimizer for Wirelss Large Payload Transfer 2 |

3 | ROS2 logo 4 | Fast DDS logo 5 |

6 | 7 | 8 | ## 📝 Paper Summary 9 | ROS 2 uses a DDS-based communication stack, but suffers from severe performance degradation when transmitting large payloads over wireless networks. The key root causes are identified as IP fragmentation, inefficient retransmission timing, and buffer bursts. To address these issues, the paper proposes a lightweight optimization framework that leverages only XML-based QoS configuration without modifying the DDS protocol. The optimization consists of: (i) setting the RTPS message size to 1472 B, (ii) configuring the retransmission rate as *n* = *2r*, and (iii) adjusting the HistoryCache size based on payload size *u* and link bandwidth. All improvements are fully compatible with existing ROS 2 applications and require no changes to application logic or middleware internals. Experiments were conducted on ROS 2 Humble using Fast DDS 2.6.9 version over IEEE 802.11ac wireless links. Test scenarios included different packet error rates (1%, 20%), temporary link outages, and varying payload sizes (32–512 KB). Default DDS and LARGE_DATA mode failed to maintain performance under high loss, while the proposed optimization remained stable up to 512 KB. The effectiveness of HistoryCache tuning was particularly evident in link outage recovery scenarios. Overall, this work demonstrates that practical, protocol-compliant DDS tuning enables robust and real-time wireless communication in ROS 2. 10 | 11 | ## Essential QoS Settings for Topic Communication 12 | | QoS Policy| QoS Value | Function | 13 | |------|---------|---------| 14 | | **history** | **KEEP_ALL** | To store all data without loss | 15 | | **reliability** | **RELIABLE** | To ensure that every message sample is delivered without loss | 16 | | **reliability.max_blocking_time** | **A sufficiently large value** | To prevent publisher blocking or data loss | 17 | 18 | ## About DDS Optimizer 19 | Our forthcoming paper introduces an optimizer for configuring parameters to efficiently transmit large payloads. 20 | 21 | > **Input**: Publish rate *r*, payload size *u*, link-layer throughput *T*OS→Link, link utilization 𝜔 22 | > **Step 1**: **Prevents IP fragmentation** Set RTPS maxMessageSize = 1472 B 23 | > **Step 2**: **Minimize Retransmission Jitter** Set retransmission rate *n* = *2r* 24 | > **Step 3**: **Prevent Buffer Burst** Set HistoryCache size as
image
25 | > **Output**: Optimized ROS 2 XML QoS profile 26 | 27 | ### XML Configuration Details 28 | 29 | Each optimization step is implemented through specific XML configurations: 30 | 31 | **Step 1: Prevents IP fragmentation** 32 | 33 | > **XML Configuration:** 34 | > ```xml 35 | > 36 | > udp_transport 37 | > UDPv4 38 | > 1472 39 | > 40 | > ``` 41 | 42 | This setting limits the RTPS message size to 1472 bytes to prevent IP fragmentation over wireless networks. 43 | 44 | **Step 2: Minimize Retransmission Jitter** 45 | 46 | > **XML Configuration:** 47 | > ```xml 48 | > 49 | > 0 50 | > [Optimized Value] 51 | > 52 | > ``` 53 | 54 | The heartbeat rate is optimized to `n = 2r` where `r` is the publish rate, reducing retransmission jitter and improving control traffic efficiency. 55 | 56 | **Step 3: Prevent Buffer Burst** 57 | 58 | > **XML Configuration:** 59 | > ```xml 60 | > 61 | > [Optimized Value] 62 | > 10 63 | > [Optimized Value] 64 | > 65 | > ``` 66 | 67 | The HistoryCache size is calculated as `⌊T × ω / u⌋` where: 68 | - `T` is the link-layer throughput 69 | - `ω` is the link utilization (default: 0.6-0.7, reduce for congested links) 70 | - `u` is the payload size 71 | 72 | This prevents buffer overflow and ensures stable data transmission by considering actual available bandwidth. 73 | 74 | 75 | ## 💡 How to run it from the terminal 76 | 77 | ### Step-by-Step Guide 78 | 79 | #### 1. Navigate to your ROS 2 package directory 80 | ```bash 81 | # Example: Navigate to ROS 2 package on Ubuntu 82 | cd ~/ros2_ws/src/your_package_name 83 | ``` 84 | 85 | #### 2. Verify that your code satisfies the Essential QoS Settings 86 | 87 | **Python version (rclpy):** 88 | ```python 89 | qos = QoSProfile( 90 | history=HistoryPolicy.KEEP_ALL, 91 | reliability=ReliabilityPolicy.RELIABLE 92 | ) 93 | # Publisher 94 | publisher = node.create_publisher(String, 'topic_name', qos) 95 | 96 | # Subscriber 97 | subscriber = node.create_subscription(String, 'topic_name', callback, qos) 98 | ``` 99 | 100 | **C++ version (rclcpp):** 101 | ```cpp 102 | auto qos = rclcpp::QoS(10) 103 | .keep_all() 104 | .reliable(); 105 | 106 | // Publisher 107 | auto publisher = node->create_publisher("topic_name", qos); 108 | 109 | // Subscriber 110 | auto subscriber = node->create_subscription( 111 | "topic_name", qos, callback); 112 | ``` 113 | 114 | #### 3. Clone DDS Optimizer and navigate to the optimizer directory 115 | ```bash 116 | git clone https://github.com/anonymous-ld/large-data-optimization.git 117 | cd large-data-optimization 118 | ``` 119 | 120 | #### 4. Run DDS_Optimizer.py 121 | ```bash 122 | # Basic usage 123 | python3 DDS_Optimizer.py r={publish rate} u={payload size} T={link-layer throughput} w={link utilization} 124 | 125 | # Example: [publish rate = 30 Hz], [payload size = 330 KB], [link-layer throughput = 90 Mb/s], [link utilization = 0.6] 126 | python3 DDS_Optimizer.py r=30 u=330000 T=90000000 w=0.6 127 | ``` 128 | 129 | **Output example:** 130 | ``` 131 | [INFO] Publisher XML: Optimized_profile_pub.xml 132 | [INFO] Subscriber XML: Optimized_profile_sub.xml 133 | [INFO] HistoryCache_size = 309 | Retransmission_ns = 16666666 134 | ``` 135 | 136 | #### 5. Apply the generated XML to your pub and sub 137 | 138 | **5-1. Set as default XML using environment variables (Recommended)** 139 | ```bash 140 | # Linux/macOS 141 | export FASTRTPS_DEFAULT_PROFILES_FILE=/path/to/generated_pub.xml 142 | ``` 143 | 144 | **5-2. Set the generated XML as default XML in your code** 145 | ```python 146 | # Set environment variable in Python 147 | import os 148 | os.environ['FASTRTPS_DEFAULT_PROFILES_FILE'] = '/path/to/generated_pub.xml' 149 | ``` 150 | 151 | ```cpp 152 | // Set environment variable in C++ 153 | #include 154 | setenv("FASTRTPS_DEFAULT_PROFILES_FILE", "/path/to/generated_pub.xml", 1); 155 | ``` 156 | 157 | ## Performance Comparision 158 |
159 | table2 160 |
161 | 162 | 163 | ## 📢 Notice 164 | This project is currently compatible with ROS 2 Humble using Fast DDS 2.6.9. 165 | Support for other DDS vendors such as Cyclone DDS and OpenDDS is planned in future updates. 166 | 167 | ### Contact & Collaboration 168 | If you have any issues or questions about using this tool, please feel free to contact us anytime. 169 | 170 | **Email**: [leesh2913@dgist.ac.kr](mailto:leesh2913@dgist.ac.kr) 171 | **Homepage**: [hun0130.github.io](https://hun0130.github.io/) 172 | 173 | Research collaborations and industry-academia partnerships are also welcome! 174 | 175 | --------------------------------------------------------------------------------