"""The wire shapes this node publishes. Declared, never inferred. pyarrow reads `{"value": None}` as `null` and `{"value": 1.0}` as `double`, so an inferred `command` would change the type of its port depending on which verb was pressed — `stop` and `freedrive` would not agree. The same hazard that makes an unplugged gamepad retype a `joy` port. dora 1.0 has no standard type for either of these, so these structs and the manifest that describes them are the whole contract a consumer gets. """ import pyarrow as pa # A velocity, in SI. Metres per second and radians per second, in the frame # named by `frame` — the units a robot node should consume, and the same ones a # UR or MoveIt would take. TWIST = pa.struct( [ ("linear", pa.list_(pa.float64())), ("angular", pa.list_(pa.float64())), ("frame", pa.string()), ] ) # One discrete thing to do. `action` is a robot-agnostic verb; `value` carries # its argument where it has one and is null otherwise. COMMAND = pa.struct([("action", pa.string()), ("value", pa.float64())]) # `dora-ulite6`'s velocity, in mm/s and deg/s. Deprecated along with the `jog` # port it goes out on. JOG = pa.struct([("velocity", pa.list_(pa.float64()))]) def pack_twist(twist: dict) -> pa.Array: """Build one `twist` message.""" return pa.array([twist], type=TWIST) def pack_command(action: str, value: float | None) -> pa.Array: """Build one `command` message.""" return pa.array([{"action": action, "value": value}], type=COMMAND) def pack_jog(velocity: list[float]) -> pa.Array: """Build one deprecated `jog` message.""" return pa.array([{"velocity": [float(v) for v in velocity]}], type=JOG)