autoplay
theme
2026 · active · Robotics · Tool · Installation

Motion-Core

Software I built end to end: authoring, validation, simulation and a runtime that drives industrial robot arms from hand-authored animation at 100 Hz under continuous safety gating.

Motion-Core sits between an animator's keyframes and the arms.

The pipeline

An animator keyframes the arms in Blender on an FK/IK rig. A plugin bakes the motion and exports it with the robot and environment geometry as a scene bundle. The control server imports that bundle, proves it in a physics simulation, and only then streams it to hardware, while a TouchDesigner client reads live robot state back into the visuals.

Blender + xArm plugin
author robot animation
↓
scene bundle · JSON + CSV + URDF
Motion-CorePython control server · PyBullet digital twin
1
Import
2
Validate
3
Simulate
4
Play
collision + joint-speed + TCP-speed validation · hard gate before play
↓
ServoJ · 100 Hz
xArm UF850 ×N
real robots
↓
telemetry · 100 Hz
TouchDesigner
read-only twin · interactive content
Motion-Core holds command authority. Consumers read telemetry; they never command the arms.
Motion-Core 3D view: two robot arms moving through the venue's collision volumes, their trajectories traced in colour
Two arms in the digital twin, trajectories overlaid through the venue's collision model.

The gate

On this path, no move reaches a real arm until it has been proven in simulation. Every frame, not sampled keyframes, against collisions with the environment and with itself, joint speed, tool-tip speed, and the blends between scenes including the loop seam. Failures name the frame, the measured value and the limit: a near-miss reads 19.6mm (threshold 20mm). Serious ones block playback; minor ones warn.

The strictest rule came out of studio testing. The move sending an arm from wherever it was to a scene's start pose was not held to the same validation as the scenes themselves. In one test it took an unchecked path and the tool hit the screen. That move is now a two-stage operation that dry-runs its exact route in simulation and executes only the approved path.

Motion-Core console showing validation blocked with 36 issues, including environment collisions measured to the tenth of a millimetre
The validator refusing a playlist. 36 issues, each linking to its frame.

Live

Commands stream to each arm at 100 Hz with automatic reconnection, so one slow link never stalls the others. Motion-Core alone holds command authority; every other client, TouchDesigner included, reads telemetry only. A Prometheus and Grafana stack watches robot connectivity and service health across the run.

Production IK and collision checking run on PyBullet. I evaluated GPU-based planning with cuRobo against it; it stayed a research spike, written up in Studies.

Motion-Core operator console driving a two-arm show
The operator console during a show.
Four arms on one playlist, rehearsing against a test grid.
A 360-degree tiny-planet photograph of the studio: the LED wall running particles above, the team standing around the rig below
The team mid-test in the studio.
Role
Creator and sole engineer. Blender exporter, control server, TouchDesigner twin
Built with
Python · PyBullet · xArm SDK · WebSocket · React · Docker · Blender
Ran
4 arms at OFFF Barcelona · 2 each at Sónar+D and Vibecon, unattended across 2–3 day installs
Seen in
Astral Twin, the installation it drove
Authoring
xArm Blender Animation, rig setup, limit validation, scene-bundle export · Houdini Robot Toolkit, curve-driven, exports the same joint CSV
Source
Company-owned and private. This page describes architecture and engineering decisions, not implementation.

Gallery

Motion-Core, image 1
Motion-Core, image 2
Motion-Core, image 3
Tools
Python · PyBullet · xArm SDK · WebSocket · React · Docker · Blender