Skip to main content
Version: 3.5.x

v3.5.0

Our largest release since the API rewrite a year ago. 3.5.0 introduces a unified 3D math layer, full Minverse support, a typed event stream, a complete settings API, and a cleaner HTTP surface — alongside a year of bug fixes and quality-of-life improvements.

Highlights

  • Unified 3D math layer — a composable transformation pipeline with first-class primitives for device basis (frame), mount transform, workspace transform, and navigation transform, plus explicit conversions between local, session, application, and internal spaces.
  • Bubble Navigation — navigate large virtual workspaces through shaped zones (SDF primitives) with velocity-mapped rate control, hysteresis-aware collision detection, and optional drift-toward-cursor. Fully configurable over HTTP and WebSocket with app-space round-trip.
  • Typed event stream — a dedicated WebSocket event channel for device lifecycle, safety alerts, calibration, battery, control-rate warnings, and deprecation hints.
  • Settings API — a complete key-value settings system with HTTP CRUD, type hints, range constraints, and descriptions, replacing the old nested config file.
  • Consistent device configuration — one set of HTTP routes for every device: basis, mount, preset, transform, filters, handedness, torque_scaling, gravity_compensation, home_return.
  • Synchronized Minverse + pen calibration — the device and its pen now calibrate together; calibration stays locked until a grip is physically attached.
  • Quality-of-life HTTP — index-based device selectors (target a device by index, no ID needed), a unified request/response shape shared with WebSocket, an opt-in {ok, error, data} envelope (?format=json), and wildcard session selectors.

New features

Devices

  • Minverse — official support shipped with this release: detection, ready sequence, safety notifications, and the synchronized calibration workflow.
  • Ruko and Kingfisher recognized as official grip product types.
  • Device simulator support — detect and talk to software-simulated devices alongside real hardware.
  • Connection-loop protection — misbehaving ports are automatically blocked; reset with POST /ports/{port}/reset.
  • Pen attachment heartbeat — reliable grip attach/detach detection with debounce.

Sessions, commands & WebSocket

  • Session profile filtering and persistence — sessions declare a profile name and required SDK version that the service remembers across reconnects; clients and monitoring tools can filter and target sessions by that profile.
  • Per-session command buffers — one slow session can no longer stall another.
  • Explicit configure map for one-shot commandsbasis, preset, mount, force_gate, damping per device, plus profile and basis per session, now all live in configure — aligned with the output config map so what you send round-trips with what you read back.
  • Customizable device mount — pick a built-in workspace preset (defaults, arm_front, arm_front_centered, led_front, led_front_centered) or send an explicit transform; manual mount changes automatically flip the preset to custom.
  • Named command fieldsposition, vector, angles, torques replace the generic values array.
  • set_angular_torques replaces set_angular_torque (singular deprecated).
  • Session frame extensions — v3.0 and v3.1 session frames now carry extensible config, state, and status objects; new output fields include current_cursor_force, current_cursor_position, current_angular_torques, current_angular_position, control_domain, control_mode, transform, transform_velocity, richer config.*, and status.safety (hidden by default).
  • Partial transform updates — send only the sub-fields you want to change (position, rotation, scale) on mount, workspace transform, and navigation shape.

HTTP

  • GET / — service version.
  • GET/POST/DELETE /settings and /settings/* — full key-value settings API.
  • GET /sessions/{session} and GET/POST/DELETE /sessions/{session}/profile.
  • GET /devices?session=<selector> — convert device coordinates into a given session's application space.
  • Index-based device selectors — target any device by index without knowing its ID (/inverse3/0/... for the first Inverse3; /inverse*/*/... for all Inverse-family devices).
  • Unified request/response shape — POST/GET bodies use the same command_data JSON shapes as WebSocket; code written against one transport works against the other.
  • Opt-in envelope via ?format=json on any route; /settings* and GET /home_return default to {ok, error, data}. Use ?format=plain for the raw shape.
  • Session selector wildcards* (any sequence) and ? (single char) in profile names.
  • Percent-decoded selectors%2A, %3A, etc. are decoded before routing.

Events

  • Dedicated WebSocket event stream on communication/events/port.
  • 24 typed event categories including device lifecycle, safety (e-brake, foreign-object detection, stall), calibration failures, battery alerts, session warnings, low/critical control rate, input validation, and deprecation hints.

Observability

  • Log messages forwarded to Tracy with level-based colors when profiling.
  • Tracy zones on every HTTP handler.
  • Main-loop timing statistics events.
  • Configurable log directory and server hostname (Docker-friendly).

Coming in 3.6

  • SDF Haptic Effects (SDF HFX) — the groundwork has landed in 3.5 (module, lifecycle, module-contributed command/state serialization) and the public API will ship with full documentation in 3.6.

Improvements

  • Force oscillation filtered — per-axis oscillation detection, 8-stage graduated recovery, entry vote with hysteresis, and asymmetric release windows.
  • Runtime force-gate filter — configurable via configure.force_gate.gain over WebSocket or HTTP with a persistent default.
  • Main loop maximum frequency raised to 32 kHz for precision applications.
  • Smaller WebSocket payloads — identity-default transform sub-fields (position = 0, rotation = identity, scale = 1) are omitted from output by default, cutting payload size and restoring compatibility with the 4 KB message limit of older Unity packages. Two advanced settings (serialization/explicit_fields, serialization/force_complete_transforms) reinstate every field for consumers that need it.
  • Lower main-loop jitter — WebSocket message processing no longer blocks the main-loop tick during JSON parsing and network send; session tick scheduling moved ahead of response serialization.
  • Servers default to localhost-only — opt in to network access with the communication/bind_all_interfaces setting.
  • Device-selector wildcards use prefix syntax (e.g. inverse* matches all Inverse-family devices).
  • Damping commands moved into the configure map alongside force_gate.
  • Rotating file logger replaces the previous one, with configurable directory.
  • Module-contributed commands and state — modules can inject their own commands, configure fields, and state output into the WebSocket frame without touching the core schema.

Fixes

A year of bug fixes; the most impactful are below.

  • Erratic session velocity under certain conditions.
  • GripHook (Verse Grip Stopper) did not cleanly release when no simulation was running.
  • Inverse3 timeouts were too aggressive and caused disconnection loops on slow-booting devices.
  • Unclean service stop on Windows — the HTTP server was not always cleaned up on shutdown.
  • Reconnection loop when the service sent unsupported commands to older firmware versions.
  • Bluetooth device enumeration flooded the log on systems with Bluetooth adapters.
  • Crash when restarting the service multiple times in a row.
  • Wireless Verse Grip dongle freeze on Ubuntu laptops after sleep/resume.
  • Wireless Verse Grip handshake on Linux and macOS now falls back correctly when the first detection attempt fails.
  • MacOS config file location — config is now stored in ~/Library/Application Support/ instead of the wrong path.
  • SIGSEGV signal handling on Linux and macOS — the process no longer loops on fatal signals when multi-thread crash capture is enabled.
  • Cross-session command overwrite — config commands from one session could be silently replaced by commands from another; they are now filtered and merged correctly.
  • Probe commands overwriting config — monitoring sessions (e.g. Haply Hub) sending probe_position no longer silently overwrite pending basis / preset / profile changes.
  • Prototype grips display — prototype hardware incorrectly appeared as a standard grip instead of a custom one.
  • Legacy set_basis matrix convention honored again for clients that had not migrated.
  • Inverse3 force kick on session disconnect no longer produces a residual force spike.
  • WebSocket connection lost race during rapid connect/disconnect cycles.
  • WebSocket session_id was serialized as 0 in some outgoing payloads.
  • On Windows, --log-level is now respected when combined with --dev (previously silently reset to debug).

Deprecations

Still functional, but will be removed in a future major version. Responses include a deprecation_warning field where applicable.

DeprecatedReplacement
POST /force_scalePOST /settings/devices/inverse*/filters/force_scale/gain
POST /gravity_compensationPOST /{device}/{id}/config/gravity_compensation
POST /torque_scalingPOST /{device}/{id}/config/torque_scaling
POST /device_handednessPOST /{device}/{id}/config/handedness
POST /serial_enablePOST /settings/communication/serial/enabled
POST /experimental/features/grip_dropped_simulation_stopperSettings API
POST /experimental/features/screensaver_enableSettings API
WebSocket command_data.valuesposition, vector, angles, torques
WebSocket set_angular_torqueset_angular_torques
WebSocket probe_cursor_positionprobe_position
WebSocket set_coordinate_originconfigure.preset
WebSocket session-level set_basisconfigure.basis

Compatibility notes

No hard breaking changes against 3.4.19. Two soft notes for existing integrations:

  1. Deprecated HTTP endpoints now include a deprecation_warning field in the response — clients that strictly validate response schemas should allow the extra field.
  2. The values field in WebSocket command_data is deprecated but still parsed; prefer the named fields.

Tutorials & documentation

  • New tutorials: 05 Position Control, 06 Combined (Inverse3 + Verse Grip), 07 Basis and Mount, 08 HTTP Remote Configurator, 09 WebSocket Remote Control, 10 Event Stream Listener.
  • New Glaze variant of every C++ tutorial (cpp-glz/) alongside the existing nlohmann/json variant.
  • All tutorials rewritten for the v3.1 API (port 10001, configure.preset, named command fields, print_state() helpers).
  • Removed the old Verse Grip Stopper tutorial — replaced by the new Combined tutorial.
  • Public documentation refreshed across the SDK guides, API reference, and hardware pages.