Views
JointAngleView
N-DoF joint-angle display — numeric readout plus per-joint signed bar chart.
Compatible dtypes: joint_angles
Purpose
Visualize a robot's joint state over time, continuously interpolated. useMergedTrack merges the current chunk with its contiguous neighbors; useTrackSample with lerp gives the value at the current clock.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
src | string | — | m3u8 playlist URL |
clock | TimelineClock | null | context | Falls back to <ClockProvider> |
className | string | — | Wrapper class |
fps | number | 15 | React render rate |
jointNames | string[] | J0…J{N-1} | Labels for each DoF |
range | number | Math.PI | Soft limit used for bar scaling |
Data Schema
import type { JointAngleSample } from '@vuer-ai/vuer-m3u';
type JointAngleSample = {
ts: number; // seconds on playlist timeline
data: number[]; // length = DoF count; order = jointNames order
};| Field | Unit | Notes |
|---|---|---|
ts | seconds | Absolute playlist time |
data | radians (convention) | One value per joint; must be consistent across the whole playlist |
Stride is inferred from the first sample — keep data.length constant across every chunk. Recommended source rate: 30–250 Hz.
Example
7-DoF arm, first four rows:
{"ts": 0.000, "data": [ 0.00, -1.57, 0.00, 1.57, 0.00, 0.00, 0.00]}
{"ts": 0.010, "data": [ 0.00, -1.56, 0.01, 1.56, 0.00, -0.01, 0.00]}
{"ts": 0.020, "data": [ 0.01, -1.55, 0.01, 1.54, 0.01, -0.01, 0.01]}
{"ts": 0.030, "data": [ 0.01, -1.54, 0.02, 1.52, 0.01, -0.02, 0.01]}Usage
Loading demo...
import {
useTimeline,
ClockProvider,
TimelineController,
JointAngleView,
} from '@vuer-ai/vuer-m3u'
const JOINTS_URL = '/vuer-m3u-demo/joints/playlist.m3u8'
export function JointAngleViewDemo() {
const { clock, state, play, pause, seek, setPlaybackRate, setLoop } = useTimeline()
return (
<ClockProvider clock={clock}>
<JointAngleView
src={JOINTS_URL}
jointNames={[
'shoulder_pan',
'shoulder_lift',
'elbow',
'wrist_1',
'wrist_2',
'wrist_3',
'gripper',
]}
/>
<TimelineController
state={state}
onPlay={play}
onPause={pause}
onSeek={seek}
onSpeedChange={setPlaybackRate}
onLoopChange={setLoop}
/>
</ClockProvider>
)
}Under the Hood
Reads the "data" track from useMergedTrack(engine).tracks and samples it with useTrackSample(track, time, lerp). See Custom Views — continuous data for a hand-rolled mini version.