libosrmpy 0.1.1
Python bindings for libosrm using pybind11
Requires Python: >=3.12

# libosrmpy

Python bindings for OSRM (Open Source Routing Machine).

## Installation

### Using uv (Recommended)

[uv](https://docs.astral.sh/uv/) is a fast Python package manager.

```bash
# Add to your project
uv add libosrmpy

# Or install directly
uv pip install libosrmpy
```

### Using pip

```bash
pip install libosrmpy
```

> **Note**: Pre-built wheels are available for:
> - Linux (x86_64, manylinux)
> - macOS (arm64, x86_64)
>
> The package manager automatically downloads the correct wheel for your platform.

### Using Pre-built Wheel Directly

If you have a wheel file, you can install it directly:

```bash
# Using uv
uv pip install libosrmpy-0.1.0-cp312-cp312-manylinux_2_17_x86_64.whl

# Using pip
pip install libosrmpy-0.1.0-cp312-cp312-manylinux_2_17_x86_64.whl
```

### Build from Source

Building from source requires the OSRM C++ library and its dependencies.

#### Linux (Docker - Recommended)

The easiest way to build on Linux is using the provided Docker environment:

```bash
# Build the Docker image
docker build -t libosrmpy-builder .

# Start a container
docker run -d --name libosrmpy-dev -v $(pwd):/app libosrmpy-builder tail -f /dev/null

# Build the wheel inside the container
docker exec -it libosrmpy-dev bash -c "cd /app && uv sync && uv build && uvx auditwheel repair dist/*.whl -w wheelhouse/"
```

The wheel will be created in the `wheelhouse/` directory.

#### macOS

Prerequisites (using Homebrew):

```bash
# Install dependencies
brew install cmake boost tbb

# Build and install OSRM
git clone --depth 1 --branch v6.0.0 https://github.com/Project-OSRM/osrm-backend.git
cd osrm-backend && mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release -DENABLE_NODE_BINDINGS=OFF
make -j$(sysctl -n hw.ncpu)
sudo make install
cd ../..

# Build the wheel
uv build
```

## Usage

```python
from libosrmpy import Engine, Algorithm
from libosrmpy.schema import Coordinate

# Initialize engine with map data
engine = Engine("/path/to/map.osrm", algorithm=Algorithm.MLD)

# Define coordinates (longitude, latitude)
coords = [
    Coordinate(longitude=126.9780, latitude=37.5665),
    Coordinate(longitude=126.9784, latitude=37.5660),
]

# Calculate distance/duration matrix
table_result = engine.table(coords)
print(table_result.durations)  # Duration matrix in seconds
print(table_result.distances)  # Distance matrix in meters

# Calculate route
route = engine.route(coords)
print(f"Distance: {route.distance}m, Duration: {route.duration}s")

# Find nearest point on road network
nearest = engine.nearest(coords[0])
print(nearest.waypoints[0].location)

# Match GPS trace to road network
match_result = engine.match(coords)
print(match_result.matchings[0].confidence)

# Calculate optimal trip (TSP solver)
trip = engine.trip(coords, roundtrip=True)
print(f"Optimized distance: {trip.distance}m")
```

## Preparing Map Data

OSRM requires pre-processed map data. Here's how to prepare it using Docker:

### 1. Download OSM Data

```bash
# Example: Download South Korea OSM data from Geofabrik
curl -L -o korea.osm.pbf http://download.geofabrik.de/asia/south-korea-latest.osm.pbf
```

> You can find regional OSM data at [Geofabrik](https://download.geofabrik.de/).

### 2. Process OSRM Data

```bash
# Extract
docker run -t --rm -v $(pwd):/data ghcr.io/project-osrm/osrm-backend:latest \
    osrm-extract -p /opt/car.lua /data/korea.osm.pbf

# Partition
docker run -t --rm -v $(pwd):/data ghcr.io/project-osrm/osrm-backend:latest \
    osrm-partition /data/korea.osrm

# Customize
docker run -t --rm -v $(pwd):/data ghcr.io/project-osrm/osrm-backend:latest \
    osrm-customize /data/korea.osrm
```

### Routing Profiles

- `/opt/car.lua` - Car routing
- `/opt/bicycle.lua` - Bicycle routing
- `/opt/foot.lua` - Pedestrian routing

## API Reference

### Engine Methods

| Method | Description |
|--------|-------------|
| `table(coordinates, sources?, destinations?)` | Calculate duration/distance matrix |
| `route(coordinates)` | Calculate route between coordinates |
| `nearest(coordinate, number_of_results=1)` | Find nearest road network point(s) |
| `match(coordinates, timestamps?, radiuses?)` | Match GPS trace to road network |
| `trip(coordinates, roundtrip=True, source?, destination?)` | Calculate optimal trip (TSP) |

### Schema Classes

- `Coordinate` - Input coordinate with `longitude` and `latitude`
- `TableResult` - Matrix result with `durations`, `distances`, `sources`, `destinations`
- `RouteResult` - Route with `distance`, `duration`, `waypoints`
- `NearestResult` - Nearest points with `waypoints`
- `MatchResult` - Matched route with `matchings`, `tracepoints`
- `TripResult` - Optimized trip with `distance`, `duration`, `waypoints`

## Development

### Running Tests

```bash
uv sync
uv run pytest
```

### Running Examples

```bash
uv run python examples/hello_libosrm.py
```

## License

MIT License