Expand description
OpenIGTLink Protocol Implementation in Rust
This library provides a Rust implementation of the OpenIGTLink protocol, which is an open network protocol for image-guided therapy environments.
§Features
- Type-safe message handling - Leverages Rust’s type system for protocol correctness
- Comprehensive message types - 20 message types fully implemented
- Synchronous and asynchronous I/O - Works with both sync and async Rust
- Full protocol compliance - OpenIGTLink Version 2 and 3
- Memory safe - No buffer overflows or memory leaks
- Zero-copy parsing - Efficient deserialization where possible
§Quick Start
§Basic Client-Server Example
Server:
use openigtlink_rust::io::IgtlServer;
use openigtlink_rust::protocol::types::StatusMessage;
use openigtlink_rust::protocol::message::IgtlMessage;
let server = IgtlServer::bind("127.0.0.1:18944")?;
let mut client_conn = server.accept()?;
let status = StatusMessage::ok("Server ready");
let msg = IgtlMessage::new(status, "Server")?;
client_conn.send(&msg)?;
Client:
use openigtlink_rust::io::ClientBuilder;
use openigtlink_rust::protocol::types::TransformMessage;
use openigtlink_rust::protocol::message::IgtlMessage;
let mut client = ClientBuilder::new()
.tcp("127.0.0.1:18944")
.sync()
.build()?;
let transform = TransformMessage::identity();
let msg = IgtlMessage::new(transform, "Device")?;
client.send(&msg)?;
let response = client.receive::<TransformMessage>()?;
§Sending Medical Images
use openigtlink_rust::protocol::types::{ImageMessage, ImageScalarType};
use openigtlink_rust::protocol::message::IgtlMessage;
use openigtlink_rust::io::ClientBuilder;
let mut client = ClientBuilder::new()
.tcp("127.0.0.1:18944")
.sync()
.build()?;
let image = ImageMessage::new(
ImageScalarType::Uint8,
[512, 512, 1],
vec![0u8; 512 * 512]
)?;
let msg = IgtlMessage::new(image, "Device")?;
client.send(&msg)?;
§Architecture
The library is organized into three main modules:
§Module Structure
-
protocol
- Core protocol implementationheader
- OpenIGTLink message header (58 bytes)types
- All 20 message type implementationscrc
- CRC-64 checksum validation
-
io
- Network I/O layerClientBuilder
- Type-state builder for configuring clientsSyncIgtlClient
/AsyncIgtlClient
- TCP clients for sync/async workflowsIgtlServer
- TCP server for accepting connections
-
error
- Error handlingIgtlError
- Unified error type for all operationsResult<T>
- Type alias forResult<T, IgtlError>
§Design Principles
- Type Safety: Each message type is a distinct Rust type
- Zero-cost Abstractions: Minimal runtime overhead
- Explicit Error Handling: All network and parsing errors are explicit
- Protocol Compliance: Strict adherence to OpenIGTLink specification
§Supported Message Types
This implementation includes all major OpenIGTLink message types:
- Transform & Tracking: TRANSFORM, POSITION, QTDATA, TDATA
- Medical Imaging: IMAGE, IMGMETA, LBMETA, COLORTABLE
- Geometric Data: POINT, POLYDATA, TRAJECTORY
- Sensor Data: SENSOR, NDARRAY
- Communication: STATUS, CAPABILITY, STRING, COMMAND, BIND
- Video Streaming: VIDEO, VIDEOMETA
§Choosing Message Types
§Transform & Tracking
-
TRANSFORM - Single 4x4 homogeneous transformation matrix
- Use for: Robot end-effector pose, single tool tracking
- Example: Surgical instrument position
-
TDATA - Array of transformation matrices with names
- Use for: Multiple tracking tools simultaneously
- Example: Tracking 5 surgical instruments at once
-
POSITION - 3D position only (no orientation)
- Use for: Point cloud data, simplified tracking
- Example: Marker positions without rotation
-
QTDATA - Position + Quaternion (alternative to TRANSFORM)
- Use for: More compact rotation representation
- Example: IMU sensor orientation
§Medical Imaging
-
IMAGE - 2D/3D medical image with metadata
- Use for: CT, MRI, ultrasound images
- Supports: 8/16-bit grayscale, RGB, RGBA
- Example: Real-time ultrasound streaming
-
VIDEO - Real-time video frames
- Use for: Endoscopic video, webcam feeds
- Supports: MJPEG, H.264, raw formats
- Example: Laparoscopic camera feed
-
IMGMETA - Metadata for multiple images
- Use for: Image catalog, DICOM series info
- Example: List of available CT slices
§Sensor Data
-
SENSOR - Multi-channel sensor readings
- Use for: Force sensors, temperature arrays
- Example: 6-axis force/torque sensor
-
NDARRAY - N-dimensional array data
- Use for: Generic numerical data
- Example: Spectrogram, multi-dimensional measurements
§Geometric Data
-
POINT - Collection of 3D points with attributes
- Use for: Fiducial markers, anatomical landmarks
- Example: Registration points for navigation
-
POLYDATA - 3D mesh with vertices and polygons
- Use for: Organ surfaces, tumor boundaries
- Example: Liver segmentation mesh
-
TRAJECTORY - Planned surgical paths
- Use for: Needle insertion paths, biopsy planning
- Example: Brain biopsy trajectory
§Communication
-
STATUS - Status/error messages
- Use for: Operation success/failure notifications
- Example: “Registration completed successfully”
-
STRING - Text messages
- Use for: Logging, user messages
- Example: “Patient positioned, ready to scan”
-
COMMAND - Remote procedure calls
- Use for: Controlling remote devices
- Example: “StartScanning”, “StopMotor”
§Examples
§Example 1: Sending Transform Data
use openigtlink_rust::io::ClientBuilder;
use openigtlink_rust::protocol::types::TransformMessage;
use openigtlink_rust::protocol::message::IgtlMessage;
let mut client = ClientBuilder::new()
.tcp("192.168.1.100:18944")
.sync()
.build()?;
// Create transformation matrix (4x4)
let mut transform = TransformMessage::identity();
// Set translation (in mm)
transform.matrix[0][3] = 100.0; // X
transform.matrix[1][3] = 50.0; // Y
transform.matrix[2][3] = 200.0; // Z
// Send to server
let msg = IgtlMessage::new(transform, "RobotArm")?;
client.send(&msg)?;
§Example 2: Streaming Medical Images
use openigtlink_rust::io::ClientBuilder;
use openigtlink_rust::protocol::types::{ImageMessage, ImageScalarType};
use openigtlink_rust::protocol::message::IgtlMessage;
let mut client = ClientBuilder::new()
.tcp("localhost:18944")
.sync()
.build()?;
// Simulate ultrasound image stream (640x480 grayscale)
for frame_num in 0..100 {
// Generate synthetic image data
let image_data = vec![((frame_num % 256) as u8); 640 * 480];
let image = ImageMessage::new(
ImageScalarType::Uint8,
[640, 480, 1],
image_data
)?;
let msg = IgtlMessage::new(image, "UltrasoundProbe")?;
client.send(&msg)?;
std::thread::sleep(std::time::Duration::from_millis(33)); // ~30 fps
}
§Example 3: Multi-Channel Sensor Data
use openigtlink_rust::io::ClientBuilder;
use openigtlink_rust::protocol::types::SensorMessage;
use openigtlink_rust::protocol::message::IgtlMessage;
let mut client = ClientBuilder::new()
.tcp("localhost:18944")
.sync()
.build()?;
// 6-axis force/torque sensor
// Forces (Fx, Fy, Fz) and Torques (Tx, Ty, Tz)
let readings = vec![1.2, -0.5, 3.8, 0.1, 0.05, -0.2];
let sensor = SensorMessage::with_unit(1, 0x0101, readings)?;
let msg = IgtlMessage::new(sensor, "ForceSensor")?;
client.send(&msg)?;
§Example 4: Status Message Handling
use openigtlink_rust::io::IgtlServer;
use openigtlink_rust::protocol::types::StatusMessage;
use openigtlink_rust::protocol::message::IgtlMessage;
let server = IgtlServer::bind("0.0.0.0:18944")?;
let mut client_conn = server.accept()?;
// Receive message
let message = client_conn.receive::<StatusMessage>()?;
// Send acknowledgment
let status = StatusMessage::ok("Data received successfully");
let msg = IgtlMessage::new(status, "Server")?;
client_conn.send(&msg)?;
§Example 5: Error Handling and Recovery
use openigtlink_rust::io::ClientBuilder;
use openigtlink_rust::protocol::types::TransformMessage;
use openigtlink_rust::protocol::message::IgtlMessage;
use openigtlink_rust::IgtlError;
fn send_with_retry(addr: &str) -> Result<(), IgtlError> {
let max_retries = 3;
for attempt in 0..max_retries {
match ClientBuilder::new().tcp(addr).sync().build() {
Ok(mut client) => {
let transform = TransformMessage::identity();
let msg = IgtlMessage::new(transform, "Device")?;
return client.send(&msg);
}
Err(e) if attempt < max_retries - 1 => {
eprintln!("Connection failed (attempt {}): {}", attempt + 1, e);
std::thread::sleep(std::time::Duration::from_secs(1));
continue;
}
Err(e) => return Err(e),
}
}
unreachable!()
}
§Error Handling
All operations return Result<T, IgtlError>
. Common error types:
- IoError - Network communication failures
- InvalidHeader - Malformed message headers
- CrcMismatch - Data corruption detected
- UnsupportedMessage - Unknown message type
- InvalidData - Invalid message body
use openigtlink_rust::io::ClientBuilder;
use openigtlink_rust::IgtlError;
match ClientBuilder::new().tcp("localhost:18944").sync().build() {
Ok(client) => println!("Connected"),
Err(IgtlError::Io(e)) => eprintln!("Network error: {}", e),
Err(e) => eprintln!("Other error: {}", e),
}
Re-exports§
Modules§
- compression
- Message compression support for OpenIGTLink
- error
- Error types for OpenIGTLink protocol operations
- io
- Network I/O module for OpenIGTLink communication
- protocol
- OpenIGTLink protocol implementation module