SuperHQ Motion experiment: locomotion and action checkpoints, runtime, clips, evaluation
6adbbb1 verified Download src/movement-network.js from superhq-ai/motion: direct link, hf CLI and curl.
- Browser
- Download file 3.38 kB
-
https://huggingface.co/superhq-ai/motion/resolve/main/src/movement-network.js
- Command line
-
hf download hf://superhq-ai/motion/src/movement-network.js
-
curl -L -o movement-network.js https://huggingface.co/superhq-ai/motion/resolve/main/src/movement-network.js
3.38 kB
| import { DenseNetwork } from './network.js'; | |
| /** Gated action residuals. Ordinary movement uses the frozen base. */ | |
| export class MovementNetwork { | |
| constructor(manifest, base, adapter, jumpAdapter=null) { | |
| if (!['superhq-motion-gated-v1','superhq-motion-branched-v1'].includes(manifest.format) || manifest.input_width !== 48 || | |
| manifest.output_width !== 143 || manifest.gate_indices?.join(',') !== '34,35,36,37' || | |
| base.layers[0].inputs !== 34 || adapter.layers[0].inputs !== 48 || | |
| base.layers.at(-1).outputs !== 143 || adapter.layers.at(-1).outputs !== 143) { | |
| throw new Error('Invalid movement action network contract.'); | |
| } | |
| this.base = base; | |
| this.adapter = adapter; | |
| this.branched=manifest.format==='superhq-motion-branched-v1';this.jumpAdapter=jumpAdapter; | |
| if(this.branched&&(!jumpAdapter||jumpAdapter.layers[0].inputs!==48||jumpAdapter.layers.at(-1).outputs!==143))throw Error('Missing jump residual.'); | |
| this.output = new Float32Array(143); | |
| } | |
| forward(input) { | |
| if (!(input instanceof Float32Array) || input.length !== 48 || !input.every(Number.isFinite)) { | |
| throw new Error('Expected 48 finite action features.'); | |
| } | |
| const gate = Math.max(0, Math.min(1, input[34] + input[35] + input[36] + input[37])); | |
| if(this.branched&&(Array.from(input.subarray(34,38)).some(v=>v<0||v>1)||(input[34]>0&&input.subarray(35,38).some(v=>v>0))))throw Error('Stance and jump gates must be exclusive.'); | |
| this.output.set(this.base.forward(input.subarray(0, 34))); | |
| if (gate > 0) { | |
| const delta = (this.branched&&input[34]===0?this.jumpAdapter:this.adapter).forward(input); | |
| for (let i = 0; i < this.output.length; i++) this.output[i] += gate * delta[i]; | |
| } | |
| if (!this.output.every(Number.isFinite)) throw new Error('Nonfinite movement prediction.'); | |
| return this.output; | |
| } | |
| static async load(baseUrl,{fetch:fetcher=globalThis.fetch}={}) { | |
| const root = new URL(baseUrl, globalThis.location?.href); | |
| const request = async url => { | |
| const response = await fetcher(url); | |
| if (!response.ok) throw new Error(`Movement asset failed (${response.status}).`); | |
| return response; | |
| }; | |
| const manifest = await (await request(new URL('movement.json', root))).json(); | |
| if (manifest.base !== 'base/' || manifest.adapter !== 'adapter/') throw new Error('Invalid action asset paths.'); | |
| if(manifest.format==='superhq-motion-branched-v1'&&manifest.jump_adapter!=='jump/')throw Error('Invalid jump asset path.'); | |
| const load = async name => { | |
| const folder = new URL(name, root); | |
| const data = await (await request(new URL('network.json', folder))).json(); | |
| if (data.weights !== 'weights.bin') throw new Error('Invalid weight path.'); | |
| const buffer = await (await request(new URL(data.weights, folder))).arrayBuffer(); | |
| const digest = await crypto.subtle.digest('SHA-256', buffer); | |
| const hash = Array.from(new Uint8Array(digest), b => b.toString(16).padStart(2, '0')).join(''); | |
| if (hash !== data.sha256) throw new Error('Movement weight checksum differs.'); | |
| return new DenseNetwork(data, buffer); | |
| }; | |
| const [base, adapter,jump] = await Promise.all([load(manifest.base), load(manifest.adapter),manifest.jump_adapter?load(manifest.jump_adapter):null]); | |
| return new MovementNetwork(manifest, base, adapter,jump); | |
| } | |
| } | |