Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
398db99
cortex init
sudoRicheek Nov 28, 2025
c80d0c1
update github action
sudoRicheek Nov 28, 2025
b01d678
separate executors, new github action to pytest
sudoRicheek Nov 28, 2025
a684f9f
fix circular imports
sudoRicheek Nov 28, 2025
c058d7b
fix graceful termination of daemons for py3.10
sudoRicheek Nov 28, 2025
636f07a
added test for executor, made node running simpler
sudoRicheek Nov 28, 2025
e219870
dont terminate context from daemon thread
sudoRicheek Nov 28, 2025
0bc3f8c
prevent race conditions in discovery client
sudoRicheek Nov 28, 2025
4a8df9e
linger update
sudoRicheek Nov 28, 2025
a19aaf0
stop discovery client from killing context
sudoRicheek Nov 28, 2025
3d861f2
do not busy wait to get topics. move waiting to asyncio when subscrib…
sudoRicheek Nov 29, 2025
de1a5c6
add 3.13,3.14 to tests
sudoRicheek Nov 29, 2025
f5fabfc
Added uvloop for better async for UNIX systems
sudoRicheek Nov 29, 2025
ffd37a8
bomb heartbeat, we got no heart
sudoRicheek Nov 29, 2025
c7c657a
Python 3.14 CI test hangs. need to debug
sudoRicheek Nov 29, 2025
8116f1e
made pub async as well, since it was using async zmq contexts
sudoRicheek Nov 29, 2025
5425b64
made pub async as well, since it was using async zmq contexts
sudoRicheek Nov 29, 2025
0b7028e
Bad things happen if publisher is async. It is nonblocking by default
sudoRicheek Nov 30, 2025
3faaa20
fix uniqueness of ipc address
sudoRicheek Dec 3, 2025
ee2cc1d
improved logging. discovery daemon is now single threaded. heartbeats…
sudoRicheek Dec 3, 2025
930549c
give daemon enough time to kts
sudoRicheek Dec 3, 2025
000341a
the issue is dameon rep socket is now blocking, so we wait
sudoRicheek Dec 3, 2025
a014474
improved latency, throughput and added some docs for help
sudoRicheek Mar 17, 2026
3686597
ruff chore
sudoRicheek Mar 17, 2026
1fd549f
update docstrings and prep codebase for mkdocs
sudoRicheek Apr 18, 2026
986aea1
docs added
sudoRicheek Apr 18, 2026
d871198
make docs and push to githhub pages
sudoRicheek Apr 18, 2026
9b093c6
shorten readme
sudoRicheek Apr 18, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 64 additions & 0 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
name: Docs

on:
push:
branches: [main]
pull_request:
branches: [main]
workflow_dispatch:

permissions:
contents: write


jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"
cache: pip

- name: Install package with docs extra
run: |
python -m pip install --upgrade pip
pip install -e ".[docs]"

- name: Build docs (strict)
run: zensical build --strict -f docs/mkdocs.yml

- name: Upload built site
uses: actions/upload-artifact@v4
with:
name: site
path: docs/site
retention-days: 7

deploy:
needs: build
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"
cache: pip

- name: Install package with docs extra
run: |
python -m pip install --upgrade pip
pip install -e ".[docs]"

- name: Deploy to GitHub Pages
run: zensical gh-deploy --force --clean -f docs/mkdocs.yml
27 changes: 27 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: Lint

on:
push:
branches: [main, dev]
pull_request:
branches: [main, dev]

jobs:
ruff:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"

- name: Install ruff
run: pip install ruff

- name: Run ruff check
run: ruff check .

- name: Run ruff format check
run: ruff format --check .
30 changes: 30 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: Test

on:
push:
branches: [main, dev]
pull_request:
branches: [main, dev]

jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]

steps:
- uses: actions/checkout@v4

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e ".[dev]"

- name: Run tests
run: pytest
104 changes: 104 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
# Cortex

Lightweight Python pub/sub over ZeroMQ, for robotics and beyond.

**[Documentation](https://sudoRicheek.github.io/cortex/)** · [Quickstart](https://sudoRicheek.github.io/cortex/getting-started/quickstart/) · [API Reference](https://sudoRicheek.github.io/cortex/reference/)

## Overview

Cortex is a pub/sub communication layer built on ZeroMQ IPC. Nodes publish typed messages on named topics; subscribers receive them via async callbacks. A small discovery daemon handles endpoint resolution so publishers and subscribers find each other automatically.

- **Typed messages** with 64-bit fingerprint verification — no silent type mismatches
- **Zero-copy frames** for NumPy arrays and PyTorch tensors over IPC
- **uvloop-backed async** for low tail latency on Linux/macOS
- **Simple API**: `Node`, `Publisher`, `Subscriber`, rate-based `Executor`

```
┌──────────────────────────────────────┐
│ Discovery Daemon │
│ ipc:///tmp/cortex_discovery │
└──────┬───────────────────────┬───────┘
│ REQ/REP (register) │ REQ/REP (lookup)
┌──────┴──────┐ ┌──────┴──────┐
│ Publisher │─PUB/SUB─│ Subscriber │
└─────────────┘ IPC └─────────────┘
```

## Installation

```bash
git clone https://github.com/sudoRicheek/cortex.git
cd cortex
pip install -e "." # core
pip install -e ".[torch]" # + PyTorch
```

## Quick Start

```bash
cortex-discovery # terminal 1: start the discovery daemon
```

```python
# publisher.py
import numpy as np
from cortex import Node, ArrayMessage

node = Node("sensor")
pub = node.create_publisher("/sensor/data", ArrayMessage)
pub.publish(ArrayMessage(data=np.random.randn(640, 480, 3).astype("f4"), name="frame"))
```

```python
# subscriber.py
from cortex import Node, ArrayMessage

def on_msg(msg: ArrayMessage, header):
print(f"got {msg.name}: {msg.data.shape}")

node = Node("proc")
node.create_subscriber("/sensor/data", ArrayMessage, callback=on_msg)
node.spin()
```

Custom message types, rate-based executors, multi-node systems — see the **[docs](https://sudoRicheek.github.io/cortex/)**.

## Messages

Define messages as plain dataclasses — registration, fingerprinting, and serialization are automatic:

```python
from dataclasses import dataclass
import numpy as np
from cortex.messages.base import Message

@dataclass
class RobotState(Message):
position: np.ndarray # zero-copy over IPC
joint_angles: np.ndarray
is_moving: bool
```

Built-ins cover the common cases: `StringMessage`, `ArrayMessage`, `ImageMessage`, `PointCloudMessage`, `PoseMessage`, `TensorMessage`, and more. See the [Messages reference](https://sudoRicheek.github.io/cortex/components/messages/).

## Examples

See the `examples/` directory for complete examples. One example:

```bash
python -m cortex.discovery.daemon # Terminal 1
python examples/publisher_numpy.py # Terminal 2
python examples/subscriber_numpy.py # Terminal 3
```

Full walkthroughs in the [Tutorials](https://sudoRicheek.github.io/cortex/tutorials/custom-messages/).

## Testing

```bash
pytest
```

## License

Apache 2.0 — see [LICENSE](LICENSE).
1 change: 1 addition & 0 deletions benchmarks/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Benchmarks for Cortex framework."""
Loading
Loading