OrthoRoute/docs/ORP_ORS_file_formats.md

8.9 KiB

OrthoRoute File Formats

This document describes the file formats used by OrthoRoute for cloud routing workflows.

Overview

OrthoRoute uses two specialized file formats to enable routing PCBs without KiCad:

  • .ORP (OrthoRoute PCB) - Contains board geometry and design rules
  • .ORS (OrthoRoute Solution) - Contains routing results (traces and vias)

Both formats use JSON with gzip compression for efficient storage and transfer.


.ORP Format (OrthoRoute PCB)

Purpose: Export board data from KiCad for routing on remote machines

Creation: File → Export PCB (Ctrl+E) in OrthoRoute GUI

Contents:

  • Board metadata (filename, dimensions, layer count)
  • Pad locations and net assignments
  • Net definitions (terminal positions)
  • Design rules (clearances, track widths, via sizes)
  • Grid parameters

File Structure

{
  "format_version": "1.0",

  "board_metadata": {
    "filename": "MyBoard.kicad_pcb",
    "bounds": {
      "x_min": 100.0,
      "y_min": 50.0,
      "x_max": 200.0,
      "y_max": 150.0
    },
    "layer_count": 6
  },

  "pads": [
    {
      "position": [150.5, 100.2],
      "net": "VCC",
      "drill": 0.8,
      "layer_mask": 4227858432
    }
  ],

  "nets": {
    "VCC": [[150.5, 100.2], [175.3, 120.5]],
    "GND": [[160.0, 110.0], [180.0, 130.0]]
  },

  "drc_rules": {
    "clearance": 0.15,
    "track_width": 0.25,
    "via_diameter": 0.6,
    "via_drill": 0.3,
    "min_drill": 0.2
  },

  "grid_parameters": {
    "pitch": 0.4
  }
}

Coordinate System

  • Units: Millimeters (mm)
  • Origin: Board lower-left corner (x_min, y_min)
  • Axes: X increases right, Y increases up
  • Layer IDs: KiCad layer numbering (0=F.Cu, 31=B.Cu, 1-30=Internal)

Typical File Sizes

  • Small board (50 nets): ~15 KB compressed
  • Medium board (200 nets): ~40 KB compressed
  • Large board (500 nets): ~80 KB compressed

.ORS Format (OrthoRoute Solution)

Purpose: Store routing results for import back into KiCad

Creation: Automatically generated by python main.py headless <board>.ORP

Contents:

  • Routed traces (per net, per layer)
  • Via locations and layer spans
  • Iteration metrics (convergence history)
  • Final routing statistics

File Structure

{
  "format_version": "1.0",

  "geometry": {
    "by_net": {
      "VCC": {
        "net_id": "VCC",
        "tracks": [
          {
            "layer": "In1.Cu",
            "start": {"x": 150.5, "y": 100.2},
            "end": {"x": 151.5, "y": 100.2},
            "width": 0.25
          }
        ],
        "vias": [
          {
            "position": {"x": 150.5, "y": 100.2},
            "from_layer": "F.Cu",
            "to_layer": "In1.Cu",
            "diameter": 0.6,
            "drill": 0.3
          }
        ]
      }
    },
    "all_tracks": [...],
    "all_vias": [...],
    "layer_usage": {
      "In1.Cu": 250,
      "In2.Cu": 180
    }
  },

  "iteration_metrics": [
    {
      "iteration": 1,
      "overuse_count": 42000,
      "nets_routed": 512,
      "overflow_cost": 85000.0,
      "wirelength": 15000.5,
      "via_count": 1250,
      "iteration_time_seconds": 45.2
    }
  ],

  "metadata": {
    "export_timestamp": "2025-11-13T18:19:50Z",
    "orthoroute_version": "0.1.0",
    "board_name": "MyBoard.kicad_pcb",
    "total_iterations": 71,
    "converged": true,
    "total_time_seconds": 1680.5,
    "notes": ""
  },

  "statistics": {
    "total_tracks": 4128,
    "total_vias": 2593,
    "total_wirelength_mm": 12500.8,
    "nets_routed": 512,
    "final_overuse_count": 0,
    "final_overflow_cost": 0.0,
    "converged": true,
    "iterations_completed": 71
  }
}

Coordinate System

Same as .ORP format - all coordinates in millimeters relative to board origin.

Layer Naming

Layers use KiCad naming convention:

  • F.Cu - Front copper
  • B.Cu - Back copper
  • In1.Cu through In30.Cu - Internal layers

Typical File Sizes

  • Small board (50 nets, 500 tracks): ~80 KB compressed
  • Medium board (200 nets, 2000 tracks): ~250 KB compressed
  • Large board (500 nets, 4000 tracks): ~450 KB compressed

Workflow

┌─────────────┐
│   KiCad     │
│   Design    │
└──────┬──────┘
       │
       │ Export (Ctrl+E)
       ▼
┌─────────────┐
│  .ORP File  │  ◄── Upload to cloud GPU
└──────┬──────┘
       │
       │ python main.py headless board.ORP
       ▼
┌─────────────┐
│  .ORS File  │  ◄── Download from cloud
└──────┬──────┘
       │
       │ Import (Ctrl+I)
       ▼
┌─────────────┐
│   KiCad     │
│  (Routed)   │
└─────────────┘

File Format Versioning

Current Version: 1.0

Both .ORP and .ORS files include a "format_version" field. Future versions of OrthoRoute will maintain backward compatibility by checking this version and handling older formats appropriately.

Version History

  • 1.0 (2025-11-13) - Initial format specification
    • Basic board geometry export
    • Net-organized routing results
    • Iteration metrics and statistics

Working with Files

Reading Files Manually

Both formats are gzip-compressed JSON, so you can inspect them with:

import gzip
import json

# Read ORP file
with gzip.open('board.ORP', 'rt', encoding='utf-8') as f:
    orp_data = json.load(f)
    print(f"Board: {orp_data['board_metadata']['filename']}")
    print(f"Nets: {len(orp_data['nets'])}")

# Read ORS file
with gzip.open('board.ORS', 'rt', encoding='utf-8') as f:
    ors_data = json.load(f)
    print(f"Tracks: {ors_data['statistics']['total_tracks']}")
    print(f"Vias: {ors_data['statistics']['total_vias']}")
    print(f"Converged: {ors_data['metadata']['converged']}")

Programmatic Access

Use the OrthoRoute serialization module:

from orthoroute.infrastructure.serialization import (
    import_board_from_orp,
    export_board_to_orp,
    import_solution_from_ors,
    export_solution_to_ors
)

# Import board
board_data = import_board_from_orp('board.ORP')

# Import solution
geometry_data, metadata = import_solution_from_ors('board.ORS')

# Access data
print(f"Total nets: {len(geometry_data['by_net'])}")
print(f"Convergence: {metadata['metadata']['converged']}")
print(f"Total time: {metadata['metadata']['total_time_seconds']:.1f}s")

Cloud Provider Setup

The .ORP/.ORS workflow is designed for cloud GPU routing. Typical setup:

  1. Export .ORP file locally
  2. Upload to cloud instance via SCP:
    scp board.ORP user@gpu-instance:/workspace/
    
  3. Route on cloud:
    ssh user@gpu-instance
    cd /workspace
    python main.py headless board.ORP
    
  4. Download .ORS file:
    scp user@gpu-instance:/workspace/board.ORS ./
    
  5. Import in KiCad with Ctrl+I

Recommended Providers:


File Validation

OrthoRoute validates files on import:

ORP Validation:

  • ✓ Format version is supported
  • ✓ Required fields present (board_metadata, pads, nets, drc_rules)
  • ✓ Coordinate ranges are reasonable
  • ✓ Net references are consistent

ORS Validation:

  • ✓ Format version is supported
  • ✓ Required sections present (geometry, metadata, statistics)
  • ✓ Track coordinates are valid
  • ✓ Layer names are recognized

Invalid files will show a clear error message indicating what's wrong.


Limitations and Future Work

Current Limitations:

  1. Existing traces not exported - .ORP assumes a clean board
  2. Keepout zones not serialized - Must manually avoid keepouts
  3. No parameter override - Uses default routing parameters
  4. No component information - Only pads and nets exported

Planned Enhancements:

  • Export existing traces for partial routing
  • Include keepout zone definitions
  • Support custom parameter JSON files
  • Component placement data for reference
  • Differential pair information
  • Impedance control specifications

Technical Notes

Why gzip compression?

Plain JSON files can be 1-2 MB for large boards. Gzip compression reduces this to ~50-100 KB (95%+ reduction), making uploads/downloads much faster.

Why JSON instead of binary?

JSON is:

  • Human-readable and debuggable
  • Easy to parse in any language
  • Self-documenting
  • Extensible for future versions
  • Well-supported by all platforms

The gzip compression eliminates most of the size overhead of JSON.

Thread safety

Both import and export functions are thread-safe and can be called concurrently from multiple threads if needed.


Last Updated: November 13, 2025 Format Version: 1.0 OrthoRoute Version: 0.1.0