Technical Architecture - Forestry-Robotics-UC/fruc_dataset_apparatus GitHub Wiki
Technical Architecture
Overview
The FRUC Dataset Apparatus is a comprehensive multi-sensor recording system built on ROS2 (Jazzy distribution) using containerized architecture. It is designed to capture synchronized sensor data from multiple sources for robotics research and dataset collection.
System Architecture
High-Level Design
┌─────────────────────────────────────────────────────────────┐
│ FRUC Dataset Apparatus │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Docker Compose Network (ROS2 Jazzy) │ │
│ │ │ │
│ │ ┌──────────────┐ ┌──────────────┐ ┌───────────┐ │ │
│ │ │ Xsens │ │ Realsense │ │ Ouster │ │ │
│ │ │ IMU │ │ D435i │ │ LiDAR │ │ │
│ │ │ Container │ │ Container │ │ Container │ │ │
│ │ └──────┬───────┘ └──────┬───────┘ └─────┬─────┘ │ │
│ │ │ │ │ │ │
│ │ ┌──────────────┐ ┌──────────────┐ ┌───────────┐ │ │
│ │ │ Emlid │ │ Robot State │ │ Foxglove │ │ │
│ │ │ GNSS │ │ Publisher │ │ Bridge │ │ │
│ │ │ Container │ │ Container │ │(Visualization) │
│ │ └──────┬───────┘ └──────────────┘ └───────────┘ │ │
│ │ │ │ │
│ │ └──────────────┬──────────────────────────┘ │ │
│ │ │ │ │
│ │ ┌──────────────▼──────────────┐ │ │
│ │ │ Recording Container │ │ │
│ │ │ (hector_recorder + │ │ │
│ │ │ ros2 bag record) │ │ │
│ │ └──────────────┬──────────────┘ │ │
│ │ │ │ │
│ └────────────────────────┼─────────────────────────────┘ │
│ │ │
│ ┌────────────────────────▼──────────────────────────────┐ │
│ │ Rosbag Output (/rosbags/) │ │
│ │ - Timestamped recordings │ │
│ │ - Configurable split (by size or duration) │ │
│ │ - Compression profiles (zstd, etc.) │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
Container Structure
The system is organized as a collection of modular OCI (Open Container Initiative) compliant containers, each handling a specific sensor or functionality:
- Desktop (Docker): Runs under Docker daemon and docker-compose
- SteamDeck (Podman): Runs under Podman daemon and podman-compose
- Compatibility: Identical container images work on both Docker and Podman - no modifications needed
Sensor Containers
-
Xsens IMU Container (
Dockerfile.xsens)- Runs the Norlab Xsens driver (ROS2 Jazzy branch)
- Provides IMU data, magnetometer readings, and computed heading
- Communicates via serial device
/dev/ttyUSB0(460800 baud rate) - Topics:
/imu/data,/imu/mag,/heading
-
RealSense Container (
Dockerfile.realsense)- Compiles librealsense2 library with USB backend
- Runs RealSense ROS2 driver with custom launch configuration
- Supports RGB color, depth, and infrared streams
- Publishes camera intrinsics and extrinsics
- Topics:
/camera/color/image_raw,/camera/aligned_depth_to_color/image_raw, etc.
-
Ouster LiDAR Container (
Dockerfile.ouster)- Runs Ouster ROS2 driver with custom configuration
- Connects to Ouster sensor via network (169.254.49.182 by default)
- Outputs raw lidar packets and processed point clouds
- Topics:
/ouster/lidar_packets,/ouster/imu_packets,/ouster/points, etc.
-
Emlid GNSS Container (
Dockerfile.emlid)- Runs nmea_navsat_driver for GNSS/GPS data
- Provides position, velocity, and satellite information
- Topics:
/fix,/fix_velocity
Utility Containers
-
Recording Container (
Dockerfile.recording)- Handles ROS2 bag recording using
hector_recorderandros2 bag record - Splits bags by size or duration as configured
- Stores rosbags in
/rosbagsmount - Applies compression profiles (none, fastwrite, zstd_fast, zstd_small)
- Handles ROS2 bag recording using
-
Publisher Container (
Dockerfile.publisher)- Runs the robot state publisher from
apparatus_descriptionpackage - Publishes URDF transforms and TF frames
- Topics:
/tf,/tf_static,/robot_description
- Runs the robot state publisher from
-
Visualization Container (Foxglove Bridge)
- Provides web-based real-time visualization
- Accessible via port 9092
- Bridges ROS2 topics to web interface
Time Synchronization
The system implements hardware time synchronization:
- Raspberry Pi Pico coordinates time across all sensors
- Each sensor driver receives synchronized timestamps
- Ensures data alignment across heterogeneous sensors
- Critical for multi-modal fusion applications
Network Architecture
Network: ros2-net (Docker bridge)
├─ Xsens IMU Container
├─ RealSense Container
├─ Ouster LiDAR Container
├─ Emlid GNSS Container
├─ Robot Publisher Container
├─ Recording Container
├─ Monitoring Container
└─ Foxglove Bridge (exposed on port 9092)
Optional: link-local-net (for specific deployments)
Data Flow
Recording Pipeline
-
Sensor Data Acquisition
- Each sensor container publishes data to ROS2 topics
- Data timestamped with hardware synchronization
-
Topic Selection
- User selects which topics to record via interactive GUI
- Selection passed to recording container
-
Recording Process
- Recording container subscribes to selected topics
- Uses
ros2 bag recordwith specified compression profile - Splits bags based on configured limits (size or time)
- Stores in timestamped directories under
/rosbags
-
Post-Recording
- Bag metadata saved to
info.txt metadata.yamlgenerated with recording information- Bags ready for offline processing
- Bag metadata saved to
Topic Organization
IMU Topics:
/imu/data- Full IMU measurements (9-DOF)/imu/mag- Magnetometer readings/heading- Computed heading angle
LiDAR Topics:
/ouster/lidar_packets- Raw packet data/ouster/imu_packets- Internal IMU from LiDAR/ouster/metadata- Configuration metadata/ouster/points- Processed point cloud/ouster/imu- Processed IMU data/ouster/range_image- Range visualization/ouster/reflec_image- Reflectivity data
Camera Topics:
/camera/color/image_raw- RGB color image/camera/color/camera_info- Color camera intrinsics/camera/aligned_depth_to_color/image_raw- Aligned depth map/camera/aligned_depth_to_color/camera_info- Depth camera intrinsics/camera/left/image_raw- Left IR stream/camera/right/image_raw- Right IR stream/camera/extrinsics/depth_to_color- Extrinsic calibration
Navigation Topics:
/fix- GNSS position information/fix_velocity- GNSS velocity information
Transform Topics:
/tf- Dynamic transform frames/tf_static- Static transform frames/robot_description- URDF robot model
Deployment Modes
Container Runtime
The system supports two container runtimes, transparently handled by launch scripts:
| Runtime | Platform | Installation | Notes |
|---|---|---|---|
| Docker | Desktop/Workstation | Manual installation required | Standard Docker daemon |
| Podman | SteamDeck | Pre-installed, rootless mode | Drop-in Docker replacement |
Automatic Detection: Launch scripts automatically detect and use the appropriate runtime:
- Desktop systems: Use
dockeranddocker-compose - SteamDeck: Use
podmanandpodman-compose
Command Compatibility: Podman and Docker use identical command syntax, so scripts work on both platforms.
Mode 1: Interactive GUI (KDE Desktop)
- Launches via
launch-system.sh - Provides kdialog menus for configuration
- Suitable for desktop environments and SteamDeck
- Runtime: Docker (desktop) / Podman (SteamDeck)
Mode 2: GNOME Desktop
- Launches via
gnome-launch-system.sh - Native GNOME integration
- Runtime: Docker (desktop) / Podman (SteamDeck)
Mode 3: Direct Container Compose (Advanced)
Manual control via container compose commands:
Desktop (Docker):
docker-compose up -d
SteamDeck (Podman):
podman-compose up -d
- No automatic recording
- Useful for custom scripts and headless operations
Mode 4: Pre-Recording Test
- Automated test via
pre_recording_test.sh - Validates sensor connectivity
- Records sample data for diagnostics
- Runtime: Automatically detects Docker or Podman
Performance Characteristics
Sampling Rates
- IMU (Xsens): Up to 2000 Hz (configurable)
- LiDAR (Ouster): Up to 10 Hz point cloud, 2000 Hz IMU
- RealSense D435i: 30 Hz RGB (1920x1080), 90 Hz depth (1280x720)
- GNSS (Emlid): 10 Hz position updates
Storage Requirements
- High-quality recording: ~2-5 GB/minute (uncompressed)
- Compressed (zstd_fast): ~500 MB-1 GB/minute
- Compressed (zstd_small): ~200-500 MB/minute
- Bag splitting prevents operating system file size limits
Supported Compression Profiles
none- No compression (fastest)fastwrite- Fast compressionzstd_fast- Fast ZSTD compressionzstd_small- High compression ratio (slower write)
Hardware Requirements
Host System
- OS: Linux (Ubuntu recommended)
- Docker: 20.10+ compatible
- CPU: Quad-core minimum (8-core recommended)
- RAM: 8 GB minimum (16 GB recommended)
- Storage: Fast SSD (500 GB+ for extended recordings)
Supported Deployments
- SteamDeck (with Linux environment)
- Desktop Workstations
- Embedded Systems (Jetson, etc.)
Sensor Requirements
- Xsens MTi USB interface (460800 baud)
- RealSense D435i USB 3.0
- Ouster OS1/OS2 Ethernet connection (link-local 169.254.0.0/16)
- Emlid Reach via serial or Ethernet
URDF and Transform Structure
The apparatus_description ROS2 package defines:
- Robot kinematic chain and sensor mounting
- URDF models with mesh definitions
- Transform relationships between sensors
- Static transforms to common reference frame
Stored in: /docker_build/apparatus_description/urdf/
Extensibility
The modular container design allows:
- Adding New Sensors: Create new Dockerfile, add to docker-compose.yml
- Custom Recording Logic: Modify hector_recorder or ros2 bag record parameters
- Post-Processing: Hooks for automatic dataset conversion (rosbag → MCAP, etc.)
- Visualization Tools: Replace or supplement Foxglove Bridge
What's Next?
See the following documents for more information:
- Installation and Setup - Installation instructions
- Tools and Libraries - Complete dependency list
- Developer Guide - For developers modifying the system
- User Manual - For end-users recording data
- Scripts Reference - Detailed script documentation