Skip to content

Commit 8cb06bd

Browse files
committed
Added article for interfacing ROS2 websocket visualization
1 parent e58fb72 commit 8cb06bd

2 files changed

Lines changed: 220 additions & 0 deletions

File tree

_data/navigation.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,8 @@ wiki:
255255
url: /wiki/interfacing/microros-for-ros2-on-microcontrollers/
256256
- title: ROS 1 - ROS 2 Bridge
257257
url: /wiki/interfacing/ros1_ros2_bridge/
258+
- title: Interfacing Streamlit, ROS2, and HTML/CSS/JS for visualization
259+
url: /wiki/interfacing/interfacing-streamlit-ros2-and-html-css-js-for-visualization.md
258260
- title: Computing
259261
url: /wiki/computing/
260262
children:
Lines changed: 218 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,218 @@
1+
# Interfacing Streamlit, ROS2, and HTML/CSS/JS for Visualizations
2+
3+
## Introduction
4+
5+
Modern robotics applications demand sophisticated visualization and control interfaces that can handle real-time data while providing rich interactive features. This guide explores the integration of Streamlit, ROS2, and web technologies to create a powerful, real-time robotics visualization dashboard. By combining these technologies, we can create interfaces that are both functional and user-friendly, while maintaining the robust communication capabilities required for robotics applications.
6+
7+
## System Architecture Overview
8+
9+
The integration of Streamlit with ROS2 and web visualizations creates a multi-layered architecture that balances performance with functionality. At its core, the system uses ROS2 for reliable robotics communication, Streamlit for rapid interface development, and custom web components for rich visualizations. This architecture enables real-time data flow while maintaining system responsiveness and user interaction capabilities.
10+
11+
The key components interact through a carefully designed communication layer that consists of:
12+
13+
The ROS2 Backend manages robot communication and data flow, serving as the foundation for all robotics operations. The Streamlit Frontend provides the user interface framework, enabling rapid development of interactive features. Custom Web Components enable rich interactive visualizations, while the State Management system coordinates data flow between all components.
14+
15+
### Technology Stack Deep Dive
16+
17+
The system relies on several key technologies, each serving a specific purpose in the architecture. ROS2 provides the foundation for robotic system communication, offering reliable publish-subscribe patterns and service-based interactions. Streamlit serves as the primary web framework, chosen for its Python-native approach and rapid development capabilities. The WebSocket protocol enables real-time communication between the web interface and ROS2 system, while custom JavaScript components provide rich visualization capabilities.
18+
19+
## Implementation Guide
20+
21+
### 1. Foundation Setup
22+
23+
The project structure needs to support both development workflow and runtime requirements. Here's the recommended organization:
24+
25+
```plaintext
26+
project_root/
27+
├── src/
28+
│ ├── frontend/
29+
│ │ ├── components/
30+
│ │ ├── pages/
31+
│ ├── ros/
32+
│ │ ├── nodes/
33+
│ └── shared/
34+
├── static/
35+
└── config/
36+
```
37+
38+
This structure provides clear separation of concerns while maintaining easy access to shared resources. Each directory serves a specific purpose in the application's architecture, allowing for modular development and easy maintenance.
39+
40+
### 2. ROS2 Integration Layer
41+
42+
The ROS2 integration represents a critical aspect of the system. Here's a comprehensive implementation:
43+
44+
```python
45+
class ROSInterface:
46+
def __init__(self):
47+
# Initialize ROS2 node
48+
rclpy.init()
49+
self.node = Node('visualization_interface')
50+
51+
# Thread-safe state management
52+
self.state_lock = threading.Lock()
53+
self.shared_state = {}
54+
55+
# Set up message filters and synchronization
56+
self.sync_filters = {}
57+
self.subscribers = {}
58+
59+
# Initialize communication interfaces
60+
self._setup_communications()
61+
62+
def _setup_communications(self):
63+
"""Configure ROS2 publishers/subscribers with thread safety"""
64+
# Set up main data subscribers
65+
self.subscribers['telemetry'] = self.node.create_subscription(
66+
TelemetryMsg,
67+
'/robot/telemetry',
68+
self._telemetry_callback,
69+
qos_profile=qos.QoSProfile(
70+
reliability=qos.ReliabilityPolicy.BEST_EFFORT,
71+
durability=qos.DurabilityPolicy.VOLATILE,
72+
history=qos.HistoryPolicy.KEEP_LAST,
73+
depth=10
74+
)
75+
)
76+
```
77+
78+
### 3. WebSocket Bridge Implementation
79+
80+
The WebSocket bridge enables real-time communication between ROS2 and the web interface:
81+
82+
```python
83+
class WebSocketBridge:
84+
def __init__(self, host='localhost', port=9090):
85+
self.host = host
86+
self.port = port
87+
self.connections = set()
88+
self.message_handlers = {}
89+
90+
# Set up asyncio event loop
91+
self.loop = asyncio.get_event_loop()
92+
self.server = None
93+
94+
async def start_server(self):
95+
"""Initialize WebSocket server with error handling"""
96+
try:
97+
self.server = await websockets.serve(
98+
self._handle_connection,
99+
self.host,
100+
self.port,
101+
ping_interval=20,
102+
ping_timeout=30
103+
)
104+
print(f"WebSocket server running on ws://{self.host}:{self.port}")
105+
except Exception as e:
106+
print(f"Failed to start WebSocket server: {e}")
107+
raise
108+
```
109+
110+
### 4. Interactive Visualization Component
111+
112+
The visualization component handles rendering and user interaction:
113+
114+
```javascript
115+
class RobotVisualizer {
116+
constructor(config) {
117+
// Initialize canvas layers
118+
this.mainCanvas = document.createElement('canvas');
119+
this.overlayCanvas = document.createElement('canvas');
120+
this.setupCanvasLayers();
121+
122+
// Initialize WebGL context
123+
this.gl = this.mainCanvas.getContext('webgl2');
124+
if (!this.gl) {
125+
throw new Error('WebGL2 not supported');
126+
}
127+
128+
// Set up rendering pipeline
129+
this.setupShaders();
130+
this.setupBuffers();
131+
this.setupInteraction();
132+
}
133+
134+
setupCanvasLayers() {
135+
// Configure canvas properties
136+
this.mainCanvas.style.position = 'absolute';
137+
this.overlayCanvas.style.position = 'absolute';
138+
139+
// Set up high-DPI support
140+
this.setupHighDPI();
141+
142+
// Configure canvas container
143+
this.container = document.createElement('div');
144+
this.container.style.position = 'relative';
145+
this.container.appendChild(this.mainCanvas);
146+
this.container.appendChild(this.overlayCanvas);
147+
}
148+
}
149+
```
150+
151+
### 5. State Management System
152+
153+
A robust state management implementation:
154+
155+
```python
156+
class SharedState:
157+
def __init__(self):
158+
self._state = {}
159+
self._callbacks = {}
160+
self._lock = threading.Lock()
161+
self._history = {}
162+
self._max_history = 1000
163+
164+
def subscribe(self, key, callback):
165+
"""Register callback for state changes"""
166+
with self._lock:
167+
if key not in self._callbacks:
168+
self._callbacks[key] = set()
169+
self._callbacks[key].add(callback)
170+
171+
def update(self, key, value, store_history=False):
172+
"""Thread-safe state update with history tracking"""
173+
with self._lock:
174+
self._state[key] = value
175+
176+
if store_history:
177+
if key not in self._history:
178+
self._history[key] = []
179+
self._history[key].append({
180+
'timestamp': time.time(),
181+
'value': value
182+
})
183+
184+
# Maintain history size
185+
if len(self._history[key]) > self._max_history:
186+
self._history[key].pop(0)
187+
188+
# Notify subscribers
189+
self._notify_subscribers(key, value)
190+
```
191+
192+
## Best Practices
193+
194+
### Error Handling
195+
196+
Implement comprehensive error handling throughout the system:
197+
198+
- Create error boundaries at component boundaries
199+
- Provide clear, actionable error messages
200+
- Handle network failures gracefully
201+
- Implement appropriate fallback behaviors
202+
- Log errors appropriately for debugging
203+
204+
### Resource Management
205+
206+
Proper resource management prevents memory leaks and ensures system stability:
207+
208+
- Clean up WebSocket connections when they're no longer needed
209+
- Manage canvas and WebGL resources efficiently
210+
- Implement proper memory management strategies
211+
- Handle component lifecycle events appropriately
212+
- Monitor system resource usage
213+
214+
## Conclusion
215+
216+
The integration of Streamlit, ROS2, and web visualizations provides a powerful foundation for building sophisticated robotics interfaces. Success with this architecture requires careful attention to threading and state management, implementation of appropriate optimization strategies, adherence to best practices for resource management, and regular monitoring and performance optimization.
217+
218+
Remember to adapt these patterns to your specific use case while maintaining the core principles of performance, reliability, and maintainability. Regular testing and monitoring of the system will help ensure it continues to meet the demands of modern robotics visualization requirements.

0 commit comments

Comments
 (0)