Metadata-Version: 2.4
Name: voyant-api
Version: 0.5.0
Classifier: Programming Language :: Rust
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: License :: Other/Proprietary License
Classifier: Intended Audience :: Developers
Classifier: Topic :: Scientific/Engineering
Requires-Dist: numpy>=2.0
Requires-Dist: pandas>=2.0
Requires-Dist: pypcd4>=1.4
Requires-Dist: pytest>=8.0 ; extra == 'dev'
Requires-Dist: mypy>=1.15 ; extra == 'dev'
Requires-Dist: pyo3-stubgen>=0.3 ; extra == 'dev'
Provides-Extra: dev
License-File: LICENSE
Summary: Python bindings for Voyant Photonics, Inc. sensors
Author-email: "Voyant Photonics, Inc." <support@voyantphotonics.com>
Requires-Python: >=3.9
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
Project-URL: Documentation, https://voyant-photonics.github.io/
Project-URL: Examples, https://github.com/Voyant-Photonics/voyant-sdk
Project-URL: Homepage, https://voyant-photonics.github.io/
Project-URL: Issues, https://github.com/Voyant-Photonics/voyant-sdk/issues

# Voyant API - Python Bindings

Python bindings for Voyant Photonics LiDAR sensors, providing high-performance access to point cloud data.

## Installation

```bash
pip install voyant-api
```

## Quick Start

### Receiving Live Data

```python
from voyant_api import VoyantClient, init_voyant_logging

init_voyant_logging()

client = VoyantClient(
    bind_addr="0.0.0.0:4444",
    group_addr="224.0.0.0",
    interface_addr="127.0.0.1",
    filter_points=True,  # Remove invalid points
)

while True:
    frame = client.try_receive_frame()
    if frame is not None:
        print(frame)

        # Get point cloud as numpy array (N x 4: x, y, z, radial_vel)
        xyzv = frame.xyzv()
        print(f"Points shape: {xyzv.shape}")
```

### Recording Data

```python
from voyant_api import VoyantClient, VoyantRecorder, RecordStatus, init_voyant_logging

init_voyant_logging()

client = VoyantClient(
    bind_addr="0.0.0.0:4444",
    group_addr="224.0.0.0",
    interface_addr="127.0.0.1",
)

with VoyantRecorder(
    output_path="my_recording.bin",
    timestamp_filename=True,
    max_total_frames=1000,  # Optional: stop after 1000 frames
) as recorder:
    while True:
        frame = client.try_receive_frame()
        if frame is not None:
            status = recorder.record_frame(frame)
            if status == RecordStatus.STOP:
                break
```

### Playing Back Recordings

```python
from voyant_api import VoyantPlayback, init_voyant_logging
from voyant_api.pandas_utils import frame_to_dataframe

init_voyant_logging()

with VoyantPlayback(filter_points=True) as playback:
    playback.open("my_recording.bin")

    for frame in playback:
        if frame is None:
            break

        print(frame)

        # Convert to pandas DataFrame
        df = frame_to_dataframe(frame)
        print(df.head())
```

### Converting Recordings to PCD

```python
from voyant_api import VoyantPlayback, init_voyant_logging
from voyant_api.pcd_utils import save_frame_to_pcd, frame_to_extended_pcd

init_voyant_logging()

with VoyantPlayback(filter_points=True) as playback:
    playback.open("my_recording.bin")

    for frame in playback:
        if frame is None:
            break

        # Save directly to .pcd file
        save_frame_to_pcd(frame, f"frame_{frame.frame_index}.pcd")

        # Or get a PointCloud object for further processing
        pc = frame_to_extended_pcd(frame)
        pc.save(f"frame_{frame.frame_index}.pcd")
```

## Features

- **High Performance**: Rust-based implementation with zero-copy data access
- **NumPy Integration**: Direct conversion to NumPy arrays via `frame.xyzv()`
- **Pandas Support**: DataFrame conversion via `voyant_api.pandas_utils`
- **PCD Support**: Point Cloud Data export via `voyant_api.pcd_utils`
- **Type Hints**: Full type annotations for IDE support (`.pyi` stubs included)
- **Recording & Playback**: Save and replay sensor data with timestamp preservation
- **Network Streaming**: Multicast UDP support for live sensor data

## API Overview

### VoyantClient

Receives live data from Voyant sensors over multicast UDP.

```python
client = VoyantClient(
    bind_addr="0.0.0.0:4444",      # Local socket to bind
    group_addr="224.0.0.0",         # Multicast group
    interface_addr="127.0.0.1",     # Network interface
    filter_points=True,             # Remove invalid points
    use_msg_stamps=False,           # Use message timestamps (False for Meadowlark, True for Carbon)
)
```

### VoyantRecorder

Records frames to binary files with automatic splitting options.

```python
recorder = VoyantRecorder(
    output_path="recording.bin",
    timestamp_filename=True,         # Add timestamp to filename
    frames_per_file=None,            # Split after N frames
    duration_per_file=None,          # Split after N seconds
    size_per_file_mb=None,           # Split after N megabytes
    max_total_frames=None,           # Stop after N total frames
    max_total_duration=None,         # Stop after N total seconds
    max_total_size_mb=None,          # Stop after N total megabytes
)
```

### VoyantPlayback

Plays back recorded data with rate control.

```python
playback = VoyantPlayback(
    rate=1.0,              # Playback speed (None = as fast as possible)
    loopback=False,        # Loop continuously
    filter_points=True,    # Remove invalid points
)
playback.open("recording.bin")
```

### Frame Data Access

```python
# NumPy arrays
xyz   = frame.xyz()            # (N x 3): [x, y, z]
xyzv  = frame.xyzv()           # (N x 4): [x, y, z, radial_vel]
sph   = frame.spherical()      # (N x 3): [range, azimuth, elevation]

# Pandas DataFrames (via voyant_api.pandas_utils)
from voyant_api.pandas_utils import frame_to_dataframe, frame_to_extended_dataframe
df          = frame_to_dataframe(frame)           # 7 columns
df_extended = frame_to_extended_dataframe(frame)  # 11 columns

# PCD PointCloud objects (via voyant_api.pcd_utils)
from voyant_api.pcd_utils import frame_to_pcd, frame_to_extended_pcd, save_frame_to_pcd
pc = frame_to_pcd(frame)           # 7 fields
pc = frame_to_extended_pcd(frame)  # 11 fields
save_frame_to_pcd(frame, "out.pcd")

# Frame metadata
print(frame.frame_index)
print(frame.timestamp)
print(frame.n_points)
print(frame.n_valid_points)
```

## Complete Examples

Full example scripts are available in the [voyant-sdk repository](https://github.com/Voyant-Photonics/voyant-sdk):

- `client_example.py` — Live data streaming
- `recorder_example.py` — Recording with all options
- `playback_example.py` — Playback and processing
- `pcd_conversion_example.py` — Converting recordings to PCD files

## System Requirements

- **Python**: 3.9 or later
- **Dependencies**: NumPy 2.0+, Pandas 2.0+, pypcd4 1.4+
- **Platforms**: Linux, Windows, macOS
- **Hardware**: Compatible with Voyant Photonics LiDAR sensors

## Documentation

- **Full Documentation**: https://voyant-photonics.github.io/
- **Examples Repository**: https://github.com/Voyant-Photonics/voyant-sdk

## Support

- **Issues**: https://github.com/Voyant-Photonics/voyant-sdk/issues
- **Email**: support@voyantphotonics.com

## License

Proprietary - for use with Voyant Photonics hardware products only.

Copyright © 2025 Voyant Photonics, Inc. All rights reserved.

