| Crates.io | openigtlink-rust |
| lib.rs | openigtlink-rust |
| version | 0.4.1 |
| created_at | 2025-10-08 04:04:09.94881+00 |
| updated_at | 2025-10-14 12:09:04.898192+00 |
| description | Rust implementation of the OpenIGTLink protocol for image-guided therapy |
| homepage | |
| repository | https://github.com/gongfour/openigtlink-rust |
| max_upload_size | |
| id | 1873423 |
| size | 736,890 |
A high-performance, type-safe Rust implementation of the OpenIGTLink protocol for real-time communication in image-guided therapy and surgical navigation systems.
OpenIGTLink is the industry-standard open network protocol used in medical applications like 3D Slicer, PLUS Toolkit, and numerous surgical navigation systems worldwide.
The most common use case is receiving messages dynamically without knowing the type in advance:
use openigtlink_rust::io::builder::ClientBuilder;
use openigtlink_rust::protocol::AnyMessage;
// Connect to an OpenIGTLink server
let mut client = ClientBuilder::new()
.tcp("127.0.0.1:18944")
.async_mode()
.build()
.await?;
// Receive any message type dynamically
let msg = client.receive_any().await?;
// Pattern match to handle different message types
match msg {
AnyMessage::Transform(transform_msg) => {
println!("Received transform from {}", transform_msg.header.device_name.as_str()?);
// Access the 4x4 transformation matrix
let matrix = &transform_msg.content.matrix;
}
AnyMessage::Image(image_msg) => {
println!("Received {}x{}x{} image",
image_msg.content.size[0],
image_msg.content.size[1],
image_msg.content.size[2]);
}
AnyMessage::Status(status_msg) => {
println!("Status: {}", status_msg.content.status_string);
}
_ => println!("Received: {}", msg.message_type()),
}
Try it now - Run your first example in 30 seconds:
# Terminal 1: Start a server that sends various message types
cargo run --example async_server
# Terminal 2: Receive and handle messages dynamically
cargo run --example async_dynamic_receiver
For sending specific message types, use the type-safe API:
use openigtlink_rust::protocol::message::IgtlMessage;
use openigtlink_rust::protocol::types::TransformMessage;
let transform = TransformMessage::identity();
let msg = IgtlMessage::new(transform, "SurgicalTool")?;
client.send(&msg).await?;
Receive any message type without compile-time knowledge - perfect for monitoring tools, protocol analyzers, and multi-device applications:
use openigtlink_rust::protocol::AnyMessage;
// Receive messages dynamically at runtime
let msg = client.receive_any().await?;
// Access common header information
println!("Device: {}, Type: {}", msg.device_name()?, msg.message_type());
// Pattern match for specific handling
match msg {
AnyMessage::Transform(t) => { /* handle transform */ },
AnyMessage::Image(i) => { /* handle image */ },
AnyMessage::Status(s) => { /* handle status */ },
AnyMessage::Unknown { header, body } => {
// Handle custom/unknown message types
println!("Custom type: {}", header.type_name.as_str()?);
}
_ => { /* handle other types */ }
}
Use cases:
See dynamic_receiver.rs and async_dynamic_receiver.rs for complete examples.
Create clients with exactly the features you need using the type-state builder pattern:
use openigtlink_rust::io::{builder::ClientBuilder, ReconnectConfig};
use std::sync::Arc;
use tokio_rustls::rustls;
// Simple TCP client
let client = ClientBuilder::new()
.tcp("127.0.0.1:18944")
.async_mode()
.build()
.await?;
// TLS-encrypted client
let tls_config = Arc::new(
rustls::ClientConfig::builder()
.with_root_certificates(rustls::RootCertStore::empty())
.with_no_client_auth()
);
let client = ClientBuilder::new()
.tcp("hospital-server.local:18944")
.async_mode()
.with_tls(tls_config.clone())
.build()
.await?;
// Auto-reconnecting client
let reconnect_config = ReconnectConfig::with_max_attempts(10);
let client = ClientBuilder::new()
.tcp("127.0.0.1:18944")
.async_mode()
.with_reconnect(reconnect_config.clone())
.build()
.await?;
// TLS + Auto-reconnect (previously impossible!)
let client = ClientBuilder::new()
.tcp("hospital-server.local:18944")
.async_mode()
.with_tls(tls_config.clone())
.with_reconnect(reconnect_config)
.build()
.await?;
// UDP for low-latency tracking (bind any available local port)
let client = ClientBuilder::new()
.udp("0.0.0.0:0")
.build()?;
Compile-time safety: Unsupported combinations (like UDP + TLS) are prevented at compile time!
Add to your Cargo.toml:
[dependencies]
openigtlink-rust = "0.3" # Latest: Dynamic message dispatch support
Or install from source:
git clone https://github.com/gongfour/openigtlink-rust.git
cd openigtlink-rust
cargo build --release
The library uses a type-state builder pattern to ensure compile-time safety:
ClientBuilder::new()
.tcp(addr) // Or .udp(addr)
.async_mode() // Or .sync() for blocking I/O
.with_tls(config) // Optional: Add TLS encryption
.with_reconnect(cfg) // Optional: Enable auto-reconnection
.verify_crc(true) // Optional: CRC verification
.build() // Returns Result<Client>
Key Design Decisions:
No Variant Explosion: Instead of creating separate types for every feature combination (TcpAsync, TcpAsyncTls, TcpAsyncReconnect, TcpAsyncTlsReconnect...), we use a single UnifiedAsyncClient with optional features.
Type-Safe States: The builder uses Rust's type system to prevent invalid configurations at compile time. For example, you cannot call .with_tls() on a UDP client.
Zero Runtime Cost: The PhantomData markers used for type states have zero size and are optimized away at compile time.
pub struct UnifiedAsyncClient {
// Internal transport (Plain TCP or TLS)
transport: Option<Transport>,
// Optional auto-reconnection
reconnect_config: Option<ReconnectConfig>,
// Connection parameters
conn_params: ConnectionParams,
// CRC verification
verify_crc: bool,
}
enum Transport {
Plain(TcpStream),
Tls(TlsStream<TcpStream>),
}
This design:
| Builder | Result Type | Best For | Key Features |
|---|---|---|---|
.tcp().sync() |
SyncIgtlClient |
Simple applications | Blocking I/O, easy to use |
.tcp().async_mode() |
UnifiedAsyncClient |
High concurrency | Tokio async, 100+ clients |
.tcp().async_mode().with_tls() |
UnifiedAsyncClient |
Secure networks | Certificate-based encryption |
.tcp().async_mode().with_reconnect() |
UnifiedAsyncClient |
Unreliable networks | Auto-reconnect with backoff |
.udp() |
UdpClient |
Real-time tracking | Low latency (120+ Hz) |
// Track surgical tools in real-time with UDP
let mut client = ClientBuilder::new()
.udp("127.0.0.1:18944")
.build()?;
loop {
let transform = get_tool_position();
let msg = IgtlMessage::new(transform, "Scalpel")?;
client.send(&msg)?;
tokio::time::sleep(Duration::from_millis(8)).await; // 120 Hz
}
use openigtlink_rust::protocol::types::ImageMessage;
// Stream CT/MRI scans with compression
let image = ImageMessage::new(
ImageScalarType::Uint16,
[512, 512, 100],
image_data
)?;
let msg = IgtlMessage::new(image, "CTScan")?;
client.send(&msg).await?;
use openigtlink_rust::io::tls_client::insecure_tls_config;
use std::sync::Arc;
// TLS-encrypted communication with auto-reconnection
let tls_config = Arc::new(insecure_tls_config());
let reconnect_config = ReconnectConfig::with_max_attempts(10);
let mut client = ClientBuilder::new()
.tcp("hospital-server.local:18944")
.async_mode()
.with_tls(tls_config)
.with_reconnect(reconnect_config)
.build()
.await?;
client.send(&patient_data).await?;
// Production-ready client with all features
let client = ClientBuilder::new()
.tcp("production-server:18944")
.async_mode()
.with_tls(load_production_certs()?)
.with_reconnect(
ReconnectConfig::with_max_attempts(100)
)
.verify_crc(true)
.build()
.await?;
✅ 20/20 message types fully implemented - Complete OpenIGTLink protocol coverage
Plus 22 query/control messages: GET_, STT_, STP_, RTS_
📝 Ready-to-run examples covering all features - Browse all examples
New to OpenIGTLink? Start here:
# 1. Dynamic message receiver (recommended - works with any message type)
cargo run --example async_server # Terminal 1
cargo run --example async_dynamic_receiver # Terminal 2
# 2. Basic client/server (specific message types)
cargo run --example server # Terminal 1
cargo run --example client # Terminal 2
Key examples:
# CT/MRI/Ultrasound streaming
cargo run --example image_streaming ct
cargo run --example image_streaming ultrasound
# Real-time video
cargo run --example video_streaming h264
# Tool tracking at 60-120 Hz
cargo run --example tracking_server
cargo run --example udp_tracking
# Fiducial registration
cargo run --example point_navigation
# Force/torque sensors
cargo run --example sensor_logger force
# IMU data
cargo run --example sensor_logger imu
# TLS encryption
./examples/generate_test_certs.sh
cargo run --example tls_communication
# Auto-reconnection
cargo run --example reconnect
# Multi-client server
cargo run --example session_manager
# Image compression (98-99% ratio)
cargo run --example compression
# UDP low-latency
cargo run --example udp_tracking compare
# Message queuing
cargo run --example message_queue
# Query & streaming control
cargo run --example query_streaming
# Connect to remote Slicer
cargo run --example query_streaming -- 192.168.1.100:18944
cargo test # 102 tests
cargo bench # Performance benchmarks
RUST_LOG=debug cargo run --example logging
Real-world benchmarks on Apple M1:
| Operation | Performance | Details |
|---|---|---|
| Message Throughput | 10,000+ msg/sec | TRANSFORM, STATUS messages |
| Image Encoding | ~50ms | 512×512×100 CT scan (16-bit) |
| Compression | 98-99% | Medical images (Deflate) |
| UDP Latency | <1ms RTT | TRANSFORM messages |
| Concurrency | 100+ clients | Single async thread |
Run benchmarks:
cargo bench
Contributions welcome! Feel free to:
✅ Production-ready - Used in real surgical navigation systems
| Metric | Status |
|---|---|
| Message Types | 20/20 ✅ |
| Query/Control | 22/22 ✅ |
| Tests | 102 passing ✅ |
| C++ Compatibility | 100% ✅ |
| Documentation | Complete ✅ |
MIT License - See LICENSE for details
⭐ Star on GitHub • 📦 View on crates.io • 📚 Read the Docs
Built with ❤️ for the medical robotics community