Skip to content

Axis Streaming quickstart

Use Axis Streaming when your application needs to interpret input itself. For 3D camera or object movement, I strongly recommend the Navigation quickstart.

The examples subscribe to all six standard axes and print each incoming rate beside its name. Rotatrix must be running. Python and C# use standalone console programs; C++ uses native scheduler dispatch and TypeScript provides a helper for an existing browser application.

From the OpenAxis repository root, install the Python SDK with python -m pip install -e py/openaxis. Save this as a Python script and run it while Rotatrix is running:

import asyncio
from openaxis.client import OpenAxisClient, OpenAxisListener
from openaxis.connection_manager import OpenAxisConnectionManager, ConnectionMetadata
class MyAxisConsumer(OpenAxisListener):
def __init__(self):
self.axes = []
def on_axes(self, axes):
self.axes = axes # Server-confirmed order for subsequent frame values.
def on_frame(self, frame):
print(frame.t_us, dict(zip(self.axes, frame.values)))
async def main():
client = OpenAxisClient(client_name="axis-example", listener=MyAxisConsumer())
connection = OpenAxisConnectionManager(
client,
metadata=lambda: ConnectionMetadata(
tags=("app.axis-example",),
axes=("tx", "ty", "tz", "rx", "ry", "rz"),
focused=True, # This standalone example claims focus.
),
)
await connection.run() # Retry until interrupted; cancellation cleans up.
try:
asyncio.run(main())
except KeyboardInterrupt:
pass

Move the device and confirm that the console prints timestamps and named rates. For the console examples, press Ctrl+C to stop; embedded applications call their teardown hook when closing. The TypeScript helper returns that hook.

OpenAxisClient delivers axis names and motion frames to an input listener. OpenAxisConnectionManager keeps that client connected and announces the desired axis subscription and application focus. The application’s listener decides what the values do; no camera adapter or NavigationSession is involved.

The axis announcement defines the order of values in subsequent frames. A frame contains a timestamp and one rate per announced axis. These are mapped input rates, not camera poses or distances in scene units.

The listener saves the confirmed axis order before processing frames. Python callbacks run on the asyncio loop, C# callbacks on the receive task, and browser callbacks on the event loop. An integration that updates thread-bound application state dispatches that work to the application’s thread.

The console examples claim focus while running. An embedded integration instead reports its application’s actual focus so Rotatrix can select the active recipient.

OpenAxisConnectionManager reconnects if Rotatrix is unavailable or restarts, then reannounces the tags, subscription and focus. See Application context and focus for context changes and connection management for readiness, retry settings and shutdown.

Rotatrix applies the user’s axis maps before streaming. For example, a map can route sideways ball movement to a translation control or to a rotation control. The six standard names are preserved from the axis map into OpenAxis:

Axis namesControl
tx, ty, tzTranslation along X, Y, Z
rx, ry, rzRotation about X, Y, Z

Rotatrix converts per-frame mapped deltas into rates before sending them: streamed rate = mapped delta / dt, where dt is the frame interval in seconds. Names identify controls; the Axis Streaming contract defines their values as rates.

All six axes are gain-mapped ball angular rates in radians per second. t* denotes logical translation controls, not scene distance per second. For device travel, multiply each rate by the interval between t_us timestamps in seconds, then choose how that travel affects your application.

When integrating rates, discard older sequence numbers and reset timing on motion start/end and connection changes so idle time does not become movement. The manager re-subscribes after reconnecting. The Axis Streaming contract defines axis order, units and timestamps.

Move the device and confirm that printed values use the announced axis names. Change the Rotatrix axis mapping and check that the corresponding named controls change. Restart Rotatrix while the example remains open; axis announcements and frames should resume after reconnection.

For an embedded application, switch focus and confirm that input is delivered only when the application is the active recipient. If rates drive accumulated movement, pause input and reconnect: neither should produce a jump from an old timestamp.

Keep the callback that interprets rates in your application. Add connection recovery and shutdown and application context and focus when embedding it in a host. Use local session logs to capture SDK and application messages. The Navigation recipes apply only if you also opt into server-computed poses.