zainar-halo
ZaiNar RF halo awareness — egocentric proximity for Device Connect nodes.
A robot's onboard sensors see line-of-sight only. ZaiNar's RF network sees
every tagged entity in a facility, through walls and around blind corners.
zainar-halo packages that awareness as Device Connect–native primitives:
a halo (per-node view of surrounding entities) computed locally by the
robot from a zone broadcast, with no GPU and no training run required.
Install
pip install zainar-halo
Requires device-connect-edge>=0.2.5.
What's in the box
| Class | What it does |
|---|---|
ZainarLocationService |
DeviceDriver publisher: ingest_position() queue → 1Hz @periodic tick → @emit per zone |
RobotDriver |
DeviceDriver subscriber: @on halo_update → local compute_halo() → @rpc |
HaloConfig |
Per-node filter spec — radius, entity types, time-decay, detail, k-cap |
Position |
One tracked entity's 3D position (cm-int, spatial_vocab wire types) |
HaloProvider |
Computes halos from a list of positions |
TMIPayload / TMIEntity |
TMI (Traffic Management Information) zone broadcast wire contract |
Quick start — location service (publisher side)
from zainar_halo import ZainarLocationService, HaloConfig, Position
import time
service = ZainarLocationService(
operator_configs={"amr-7": HaloConfig(radius_cm=1500, entity_types=["forklift", "human"])},
)
# register with DeviceRuntime and connect
# In your kinesis-gw subscriber callback:
service.ingest_position(Position(
device_id="amr-7", entity_type="amr",
x_cm=2200, y_cm=500, z_cm=0,
measurement_time=time.time(),
))
# The @periodic tick broadcasts automatically at 1Hz
Quick start — robot subscriber
from zainar_halo import HaloConfig, RobotDriver
class MyRobot(RobotDriver):
async def _on_halo_computed(self, halo: dict) -> None:
# feed to costmap, planner, alerting...
nearest = halo["nearest_entity_type"]
dist_m = (halo["nearest_distance_cm"] or 0) / 100
print(f"{nearest} at {dist_m:.1f}m")
robot = MyRobot(halo_config=HaloConfig(radius_cm=1500, entity_types=["forklift", "human"]))
# register with DeviceRuntime and connect — the @on subscription is automatic
Design note — awareness not firehose
get_halo(device_id) returns a filtered, egocentric view — entities within
radius_cm, capped by entity_types and max_age_s. It is not a raw position
feed. This is intentional:
- An MCP agent asking "what's around amr-7?" gets a safety-relevant subset, not the full facility tracking log.
- Operators set the filter via
set_halo_config(). The config is stamped into every broadcast tick so all consumers use the same safety perimeter. - For raw zone position lists, use
get_zone_entities(zone).
Dense zones and the k-cap
When a zone has many tracked entities, HaloConfig.max_members limits the
halo to the nearest k. This bounds per-robot compute to O(k) regardless of
zone density:
# Nearest 10 only — ignores everything beyond the 10th closest
HaloConfig(radius_cm=1500, max_members=10)
Default: None (unbounded — all entities within radius).
Performance
From the S5 scale test (200 robots, one zone, NATS on localhost):
| Metric | Value |
|---|---|
| Payload size (200 entities) | 55 KB |
| Per-entity overhead | 284 bytes |
| All 200 robots received halo | 0.50s wall clock after first tick |
| Per-robot halo compute | < 1ms (pure CPU, O(k) in zone member count) |
Payload is O(N) in entity count — one JSON list, one NATS publish per zone, N local computes (no central aggregation, no fan-out amplification).
Units and conventions
- Lengths: centimeters as
int(distance_cm,radius_cm,x_cm/y_cm/z_cm) - Speeds: cm/s as
int(closing_speed_cmps,vx_cmps) - Entity types: spatial_vocab wire values —
human,amr,forklift,drone,pallet, … - 3D throughout — distance is 3D Euclidean; a drone 4m overhead is 400cm away
See also
zainar-halo-agent-tools— FastMCP server exposing halo tools to LLM agentsCLAUDE.mdat repo root — full architecture, scenario, and integration guide
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file zainar_halo-0.1.4.tar.gz.
File metadata
- Download URL: zainar_halo-0.1.4.tar.gz
- Upload date:
- Size: 27.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cc269e8ce5f3f9742f75e3bb9374c228f4a04822238aec780b300ffdf263f748
|
|
| MD5 |
a71104dfab9b9e0ccca8287c540a38dd
|
|
| BLAKE2b-256 |
7e0aa7f00df73afa84eef647cfb7209a6d3a4924917808cb4942c3c5426881d9
|
File details
Details for the file zainar_halo-0.1.4-py3-none-any.whl.
File metadata
- Download URL: zainar_halo-0.1.4-py3-none-any.whl
- Upload date:
- Size: 27.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
43ebb5b4a7f126e0e71dfa225e09ee9fc43bf6b2f2afd3b44abe21d11a28b645
|
|
| MD5 |
cb847be175517398f6ab80f37059a135
|
|
| BLAKE2b-256 |
1c9dd97ccfb45a72d288395f8f1c7f5cc7f56af1bcd902930d4fc88865703b21
|