Multi-Axis T-Code: Advanced Haptic Script Control with 8 Axes

Deep dive into multi-axis T-code haptic scripting. Learn about the 8 axes (L0-L2, R0-R2, V0, A0), T-code format syntax, advanced devices, and how HaptiQ generates multi-axis output.

Standard funscripts control a single axis of motion: up and down. But advanced haptic devices like the OSR2+, SR6, and SSR1 support up to 8 independent axes of motion, delivering rotation, twist, surge, sway, and vibration alongside the primary stroke. Controlling these axes requires the T-code protocol, a serial command format that sends real-time position updates to multi-axis firmware. This guide covers everything you need to know about multi-axis T-code scripting, from protocol syntax to practical creation workflows with HaptiQ.

What Is T-Code?

T-code (TCode, T-Code Protocol) is a serial communication protocol designed for controlling multi-axis haptic devices. It was created by the open-source hardware community alongside devices like the OSR2 (Open Source Robotic Stroker) to provide a standardized way to send position commands to firmware that controls multiple servos or motors simultaneously.

Unlike funscript, which is a file format stored as JSON, T-code is a real-time command protocol. Commands are sent over a serial connection (USB or Bluetooth Serial) as plain-text strings. Each command specifies an axis identifier and a position value that the firmware immediately executes.

The relationship between funscript and T-code is complementary: funscript defines what the device should do over time (the script), and T-code is the real-time protocol that delivers those commands to the device's firmware at the correct moments during playback.

The 8 Axes Explained

The T-code specification defines 8 standard axes, organized into four groups. Each axis controls a different dimension of device motion:

Axis Name Motion Type Description
L0StrokeLinearPrimary up/down stroke (equivalent to standard funscript)
L1SurgeLinearForward/backward push motion
L2SwayLinearLeft/right lateral motion
R0TwistRotationalClockwise/counterclockwise twist around the vertical axis
R1RollRotationalRoll rotation (tilt side to side)
R2PitchRotationalPitch rotation (tilt forward/backward)
V0VibrateVibrationPrimary vibration intensity
A0ValveAuxiliaryAir valve or suction control

Linear Axes (L0, L1, L2)

The three linear axes represent translational motion in three dimensions. L0 is the primary stroke (what standard funscripts control), L1 adds a forward/backward push that creates a thrusting sensation, and L2 adds lateral sway that mimics side-to-side movement. Together, these three axes can reproduce complex spatial movement patterns that single-axis devices cannot approximate.

Rotational Axes (R0, R1, R2)

The three rotational axes add twist and tilt to the device's motion. R0 (twist) is the most commonly used rotation axis, creating a wringing or twisting sensation. R1 (roll) and R2 (pitch) tilt the device along different planes, adding dimensional complexity. On devices like the SR6, which has 6 servo-driven axes, combining rotation with linear motion creates remarkably lifelike movement.

Vibration and Auxiliary (V0, A0)

V0 controls vibration intensity from 0 (off) to 100 (maximum). This adds a continuous stimulation layer on top of the mechanical motion. A0 controls auxiliary features like air valves or suction mechanisms, which some advanced devices use for additional sensation types.

T-Code Command Syntax

T-code commands are plain-text strings sent over serial connections. The basic syntax is:

# Basic format: AxisPositionSpeed
L09999        # L0 axis to position 9999 (99.99%) at maximum speed
L05000I1000   # L0 axis to position 5000 (50%) over 1000ms
R02500        # R0 (twist) to position 2500 (25%)

# Multiple axes in one command (space-separated):
L09000 R05000 V03000
# L0 to 90%, R0 to 50%, V0 to 30% simultaneously

# Device info query:
D0            # Request device identifier
D1            # Request TCode version
D2            # Request axis count

Position Values

T-code position values range from 0 to 9999, providing much finer granularity than funscript's 0-100 range. The value 0000 represents the minimum position, 5000 is the midpoint, and 9999 is the maximum. When converting from funscript to T-code, the position is scaled: funscript pos 50 becomes T-code position 5000, funscript pos 100 becomes 9999.

Speed Control (Interval)

The optional I suffix specifies the time interval (in milliseconds) over which the axis should reach the target position. Without the interval, the device moves to the position as fast as its servos allow. With an interval, the firmware interpolates smoothly, producing gentler transitions.

Devices That Support Multi-Axis T-Code

Multi-axis T-code is primarily used with DIY and open-source hardware devices. These are enthusiast-grade machines that provide a level of haptic fidelity far beyond consumer devices:

Device Axes Type Notes
OSR2+ / OSR2x22-3DIY servo-drivenMost popular T-code device, open-source design
SR66DIY servo-drivenFull 6-axis Stewart platform, highest fidelity
SSR16DIY servo-drivenAlternative 6-axis design
Romeo16+CommercialCommercial multi-axis with T-code firmware
Custom builds1-8DIYAny Arduino/ESP32 device running TCode firmware

Multi-Axis Funscript Files

While T-code is the real-time protocol for commanding devices, multi-axis content is typically stored as multiple funscript files, one per axis. The naming convention uses the axis identifier as a suffix:

my-video.funscript          # L0 (primary stroke) - default
my-video.L1.funscript       # L1 (surge/thrust)
my-video.L2.funscript       # L2 (sway)
my-video.R0.funscript       # R0 (twist)
my-video.R1.funscript       # R1 (roll)
my-video.R2.funscript       # R2 (pitch)
my-video.V0.funscript       # V0 (vibration)
my-video.A0.funscript       # A0 (valve/suction)

Each axis file is a standard funscript JSON with an actions array. The only difference is which axis the positions control. Players that support multi-axis playback (like HaptiQ, MultiFunPlayer, and Heresphere) load all matching axis files and convert the timed positions into T-code commands during playback.

Creating Multi-Axis Scripts with HaptiQ

HaptiQ generates multi-axis T-code output by analyzing different motion components from the optical flow data during its 5-stage AI pipeline. Here is how each axis is derived:

Primary Axis (L0): Direct Generation

The L0 axis is generated directly from the dominant vertical motion vectors in the region of interest. This is the same process used for standard single-axis funscript generation, and it produces the primary up/down stroke pattern.

Secondary Linear Axes (L1, L2): Motion Decomposition

L1 (surge) is derived from the depth component of the optical flow, representing forward/backward motion. L2 (sway) comes from the horizontal component. HaptiQ decomposes the 2D optical flow vectors into directional components and maps each to the appropriate axis with proper scaling.

Rotation Axes (R0, R1, R2): Algorithmic Derivation

Rotation axes can be derived algorithmically from the primary motion pattern. R0 (twist) is commonly generated as a phase-shifted derivative of L0 -- when the stroke changes direction, a slight twist adds realism. R1 and R2 can be derived from the lateral and depth motion components respectively, scaled down to create subtle complementary movement.

Vibration and Auxiliary (V0, A0): Pattern-Based

V0 vibration intensity is typically derived from the overall motion magnitude -- faster motion produces stronger vibration. A0 can be linked to specific motion patterns or left for manual configuration in HaptiQ's multi-axis editor.

The Multi-Axis Editor in HaptiQ

HaptiQ's Pro tier includes a multi-lane timeline editor that displays all 8 axes simultaneously. Each axis gets its own lane with independent zoom, selection, and editing controls. You can:

Converting Single-Axis to Multi-Axis

If you already have a single-axis funscript (either hand-made or AI-generated), HaptiQ can derive secondary axes algorithmically. This process analyzes the L0 motion pattern and generates complementary motion on the other axes:

  1. Import your single-axis funscript into HaptiQ.
  2. Navigate to the multi-axis view from the editor toolbar.
  3. Click "Derive Secondary Axes" and configure the derivation parameters (amplitude, phase offset, smoothing).
  4. Preview the result on the multi-lane timeline.
  5. Fine-tune individual axes as needed.
  6. Export as multi-axis funscript files or T-code.

T-Code vs Funscript: When to Use Each

Aspect Funscript (.funscript) T-Code Protocol
PurposeStorage and distributionReal-time device control
FormatJSON fileSerial text commands
AxesSingle-axis per file8 axes in one command stream
Position range0-1000-9999
TimingEmbedded timestamps (at)Sent at correct moment by player
Device supportAll haptic devicesOSR2+, SR6, SSR1, custom builds

In practice, you create and store scripts as funscript files and the playback software converts them to T-code commands in real-time during playback. HaptiQ handles this conversion automatically when a multi-axis device is connected.

Best Practices for Multi-Axis Scripts

Unlock Multi-Axis T-Code Support

HaptiQ Pro includes full 8-axis T-code generation, multi-lane editing, and export in funscript, T-code, and CSV formats.

Start Free Trial See Pro Plans

Frequently asked questions

What are the 8 T-code axes and what does each control?

T-code defines 8 independent axes for multi-axis haptic devices. L0 is the primary linear axis (up/down stroke), L1 is surge (forward/backward translation), L2 is sway (side-to-side translation). R0 is twist (rotation around the stroke axis), R1 is roll, R2 is pitch. V0 is vibration intensity, and A0 is auxiliary air or suction. Devices like the OSR2+ typically implement L0, R0, R1, and R2. The SR6 adds L1 and L2 for full 6-degrees-of-freedom motion. Higher-end rigs support all 8. Each axis accepts a 0–9999 position value at millisecond timestamps, sent over serial at up to 100Hz update rate. HaptiQ generates multi-axis output by mapping different optical-flow components to different axes — vertical motion to L0, horizontal rotation cues to R0 and R1.

How does T-code format differ from standard funscript JSON?

Standard funscript is JSON: an actions array of {at: milliseconds, pos: 0-100} entries, single axis. T-code is a serial command stream sent in real time: each line is a command like L050I100 meaning "move axis L to position 50 over 100 milliseconds" (I for interval), or L050S500 where S is speed. Commands for multiple axes chain on one line (L050I100R075I100V500I50) for coordinated multi-axis moves. HaptiQ can export in either format: standard .funscript for single-axis devices (872 supported), or T-code for the OSR2+, SR6, and SSR1. Multi-axis .funscript extensions (like .funscript plus .roll.funscript and .twist.funscript sidecars) are also supported for backwards compatibility with older multi-axis workflows.

Which devices support multi-axis T-code?

The OSR2+ is the most common entry-level multi-axis device, supporting L0, R0, R1, and R2 over USB-serial. The SR6 adds L1 and L2 surge/sway for a full 6-DOF experience. SSR1 supports similar axis layouts with premium actuators. TempestMAX and TempestMAX Prime are high-end options with all 8 axes. All multi-axis devices run custom firmware based on the T-code reference implementation and accept commands at 50–100Hz. HaptiQ connects via WebSerial in Chrome/Edge or via Buttplug.io with a T-code-aware driver. Secondary axes can be derived algorithmically in HaptiQ: roll (R2) is often a 90-degree-phase-shifted copy of primary stroke motion, and vibration (V0) can be generated from stroke speed magnitude. Pro tier unlocks multi-axis export; free tier includes single-axis output.

How do I create a multi-axis script with HaptiQ?

Open a project in HaptiQ and load your video. If you want AI-generated multi-axis output, enable "Multi-axis T-code" in the project settings before running generation — the pipeline will analyze horizontal as well as vertical optical-flow components and populate up to all 8 axes. For manual authoring, open the multi-axis editor (EditorPage with multi-axis mode on), which presents separate timeline lanes per axis with synchronized scrubbing. You can derive secondary axes from the primary: select L0, pick "Derive R0" from the axis menu, and HaptiQ generates a rotation track algorithmically. Export options include combined T-code (.tcode), multi-file .funscript sidecars (one per axis), and CSV for analysis. The full workflow is multi-axis-native: 8 lanes, independent keyframes, T-code syntax highlighting.

Create a free HaptiQ account to generate a funscript from your own video.

Open in HaptiQ