cozyclay 2.1.1 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +60 -0
- package/README.md +12 -30
- package/bin/agent/agent-routes.mjs +40 -113
- package/bin/agent/agent-runner.mjs +9 -10
- package/bin/agent/cliproxy-provider.mjs +135 -0
- package/bin/agent/credential-store.mjs +30 -7
- package/bin/agent/pi-tools.mjs +4 -1
- package/bin/agent/provider-keys.mjs +32 -0
- package/bin/agent/provider-login.mjs +110 -0
- package/bin/agent/provider-routes.mjs +99 -0
- package/bin/agent/providers.mjs +19 -97
- package/bin/agent/script-tool.mjs +17 -4
- package/bin/agent/studio-motion-reference.mjs +23 -0
- package/bin/agent/studio-prompt.mjs +1 -1
- package/bin/agent/studio-rebase-text.mjs +32 -0
- package/bin/agent/studio-rebase.mjs +26 -39
- package/bin/agent/studio-tools.mjs +9 -28
- package/bin/agent/tool-arguments.mjs +49 -0
- package/bin/agent/turn-frames.mjs +66 -0
- package/bin/codex-auth.mjs +9 -2
- package/bin/cozyclay.mjs +10 -116
- package/bin/live/cli.mjs +3 -3
- package/bin/mcp-runtime.mjs +2 -12
- package/bin/package-signature.mjs +0 -4
- package/dist/app/index.html +7 -6
- package/dist/assets/EXRLoader-CvVIvGVE.js +1 -0
- package/dist/assets/analytics-C9sUnndd.js +1 -0
- package/dist/assets/app-CCh--1Hc.js +5087 -0
- package/dist/assets/app-f-fkV5uP.css +1 -0
- package/dist/assets/compile-worker-CkxiD6lH.js +5 -0
- package/dist/assets/fflate.module-KbGj5-H6.js +5 -0
- package/dist/assets/{first-shot-handoff-msLI71g1.js → first-shot-handoff-CC4xe4HM.js} +1 -1
- package/dist/assets/{landing-ChUvB_zL.js → landing-DjHD8u7k.js} +1 -1
- package/dist/assets/scene-asset-sync-Hx_FzdOH.js +20 -0
- package/dist/assets/scene-asset-sync-_S8NQl5B.css +1 -0
- package/dist/assets/workflow-C4yKH1p4.js +179 -0
- package/dist/cozyclay-package.json +1 -1
- package/dist/index.html +3 -3
- package/dist/sw.js +3 -6
- package/dist/workflow/index.html +5 -4
- package/mcp/LIVE-PROTOCOL.md +7 -47
- package/mcp/README.md +16 -26
- package/mcp/live-hub.mjs +6 -10
- package/mcp/package.json +1 -3
- package/mcp/tool-handlers.mjs +4 -168
- package/package.json +3 -22
- package/src/App.jsx +150 -2624
- package/src/agent-progress.js +79 -0
- package/src/agent-turn-mark.js +30 -0
- package/src/analytics.js +1 -19
- package/src/app-context.js +5 -0
- package/src/app-stage.jsx +2 -34
- package/src/asset-pane.jsx +6 -5
- package/src/camera-block.js +21 -0
- package/src/camera-direction.js +120 -0
- package/src/character-kind.js +3 -9
- package/src/command-bus.js +8 -6
- package/src/commands/cast.js +5 -34
- package/src/commands/elements/character.js +1 -1
- package/src/commands/elements/motion.js +1 -6
- package/src/commands/elements/object.js +6 -2
- package/src/commands/elements/shot.js +4 -1
- package/src/commands/elements.js +38 -14
- package/src/commands/index.js +3 -1
- package/src/commands/kits.js +37 -0
- package/src/commands/motion-timing.js +57 -0
- package/src/commands/motion.js +9 -152
- package/src/commands/motion3-compile.js +65 -0
- package/src/commands/motion3.js +207 -0
- package/src/commands/objects.js +6 -4
- package/src/commands/shot.js +49 -11
- package/src/commands/stage.js +14 -1
- package/src/commands/view.js +4 -1
- package/src/document-mirrors.js +42 -0
- package/src/document-store.js +4 -0
- package/src/domains/cast.js +19 -194
- package/src/domains/motion/motion-range-pin-rules.js +1 -1
- package/src/domains/motion/take-source.js +51 -0
- package/src/domains/motion.js +60 -1838
- package/src/domains/scenes.js +12 -55
- package/src/domains/shots.js +2 -2
- package/src/domains/stage.js +4 -2
- package/src/draft-ghost.js +46 -0
- package/src/draft-ghost.jsx +129 -0
- package/src/dualview.jsx +4 -3
- package/src/effects/EffectsLayer.jsx +112 -0
- package/src/effects/effect-meshes.js +232 -0
- package/src/effects/effect-record.js +103 -0
- package/src/effects/emitter.js +59 -0
- package/src/effects/simulate.js +261 -0
- package/src/effects/state.js +59 -0
- package/src/execution-telemetry.js +2 -3
- package/src/first-success-guide.jsx +5 -5
- package/src/ghost-set.js +257 -0
- package/src/held-object-edit.jsx +113 -0
- package/src/held-object-pose.js +175 -0
- package/src/hierarchy-model.js +1 -1
- package/src/hierarchy-panel.jsx +1 -1
- package/src/imported-mesh.jsx +103 -0
- package/src/kits/held.js +84 -0
- package/src/kits/index.js +70 -0
- package/src/kits/smoking.js +57 -0
- package/src/light-blockers.js +93 -0
- package/src/motion/beat-board-model.js +84 -0
- package/src/motion/beat-board.css +124 -0
- package/src/motion/beat-board.jsx +59 -0
- package/src/motion/center-of-mass.js +66 -0
- package/src/motion/fix-collisions.js +850 -0
- package/src/motion/physics-review.js +118 -0
- package/src/{ardy → motion}/physics-support.js +1 -76
- package/src/motion/rig-snapshot.js +22 -0
- package/src/motion/take-segments.jsx +140 -0
- package/src/{ardy → motion}/timeline-coordinates.js +0 -21
- package/src/{ardy → motion}/timeline.css +1 -2
- package/src/{ardy → motion}/timeline.jsx +42 -413
- package/src/motion/waypoints.js +76 -0
- package/src/motion3/beats.js +83 -0
- package/src/motion3/body.js +158 -0
- package/src/motion3/bones.js +47 -0
- package/src/motion3/carried.js +47 -0
- package/src/motion3/compile-job.js +75 -0
- package/src/motion3/compile-worker.js +10 -0
- package/src/motion3/compiler/anchors.js +105 -0
- package/src/motion3/compiler/arm-orient.js +128 -0
- package/src/motion3/compiler/channels.js +125 -0
- package/src/motion3/compiler/compile.js +205 -0
- package/src/motion3/compiler/gait-rhythm.js +97 -0
- package/src/motion3/compiler/grip.js +171 -0
- package/src/motion3/compiler/head-steady.js +48 -0
- package/src/motion3/compiler/hold.js +134 -0
- package/src/motion3/compiler/idle.js +113 -0
- package/src/motion3/compiler/limbs.js +170 -0
- package/src/motion3/compiler/math.js +72 -0
- package/src/motion3/compiler/pose.js +162 -0
- package/src/motion3/compiler/quat.js +49 -0
- package/src/motion3/compiler/skeleton.js +74 -0
- package/src/motion3/compiler/validate-common.js +32 -0
- package/src/motion3/compiler/validate-goals.js +118 -0
- package/src/motion3/compiler/validate-objects.js +143 -0
- package/src/motion3/compiler/validate-parts.js +116 -0
- package/src/motion3/compiler/validate.js +122 -0
- package/src/motion3/compiler/vocab.js +73 -0
- package/src/motion3/compiler/walk-pelvis.js +275 -0
- package/src/motion3/compiler/walk.js +207 -0
- package/src/motion3/compiler/wrist-clamp.js +32 -0
- package/src/motion3/delta.js +47 -0
- package/src/motion3/describe.js +174 -0
- package/src/motion3/docs.js +27 -0
- package/src/motion3/edit-carry.js +21 -0
- package/src/motion3/fix/ease.js +16 -0
- package/src/motion3/fix/ground.js +37 -0
- package/src/motion3/fix/index.js +52 -0
- package/src/motion3/fix/push.js +71 -0
- package/src/motion3/fix/reach.js +46 -0
- package/src/motion3/fix/retime.js +79 -0
- package/src/motion3/fix/self.js +211 -0
- package/src/motion3/fix/slide.js +70 -0
- package/src/motion3/fix/turn.js +51 -0
- package/src/motion3/follow.js +39 -0
- package/src/motion3/free-motion.js +173 -0
- package/src/motion3/grip-choice.js +130 -0
- package/src/motion3/hold-plan.js +157 -0
- package/src/motion3/json-patch.js +77 -0
- package/src/motion3/key-aim.js +105 -0
- package/src/motion3/key-edit.js +82 -0
- package/src/motion3/lenient.js +127 -0
- package/src/motion3/object-keys.js +236 -0
- package/src/motion3/object-pose.js +182 -0
- package/src/motion3/object-tracks.js +12 -0
- package/src/motion3/pipeline.js +102 -0
- package/src/motion3/playback.js +51 -0
- package/src/motion3/probes.js +91 -0
- package/src/motion3/qa/body-checks.js +34 -0
- package/src/motion3/qa/check-names.js +14 -0
- package/src/motion3/qa/checks.js +121 -0
- package/src/motion3/qa/contact-checks.js +51 -0
- package/src/motion3/qa/explain.js +80 -0
- package/src/motion3/qa/fmt.js +5 -0
- package/src/motion3/qa/foot-checks.js +72 -0
- package/src/motion3/qa/geometry.js +77 -0
- package/src/motion3/qa/goals.js +191 -0
- package/src/motion3/qa/ground.js +60 -0
- package/src/motion3/qa/hints-contact.js +179 -0
- package/src/motion3/qa/hints-goal.js +160 -0
- package/src/motion3/qa/hints-knee.js +24 -0
- package/src/motion3/qa/hints-motion.js +209 -0
- package/src/motion3/qa/hints-object.js +91 -0
- package/src/motion3/qa/index.js +42 -0
- package/src/motion3/qa/key-checks.js +82 -0
- package/src/motion3/qa/near.js +96 -0
- package/src/motion3/qa/object-checks.js +135 -0
- package/src/motion3/qa/patch.js +161 -0
- package/src/motion3/qa/severity.js +38 -0
- package/src/motion3/qa/spec-checks.js +65 -0
- package/src/motion3/qa/style.js +218 -0
- package/src/motion3/qa/wrist-checks.js +69 -0
- package/src/motion3/qa/wrist-obs.js +60 -0
- package/src/motion3/refs.js +120 -0
- package/src/motion3/repair-tune.js +121 -0
- package/src/motion3/repair.js +83 -0
- package/src/motion3/report.js +67 -0
- package/src/motion3/rigs/index.js +14 -0
- package/src/motion3/rigs/x-bot-tpose-body.json +1 -0
- package/src/motion3/rigs/x-bot-tpose.json +1 -0
- package/src/motion3/rigs/y-bot-tpose-body.json +1 -0
- package/src/motion3/rigs/y-bot-tpose.json +1 -0
- package/src/motion3/scene.js +60 -0
- package/src/motion3/schema/brief.js +89 -0
- package/src/motion3/schema/fields.js +44 -0
- package/src/motion3/schema/spec-examples.js +46 -0
- package/src/motion3/schema/topics.js +111 -0
- package/src/motion3/schema/types.js +147 -0
- package/src/motion3/search.js +117 -0
- package/src/motion3/second-hand.js +112 -0
- package/src/motion3/skills/basic.js +82 -0
- package/src/motion3/skills/book.js +76 -0
- package/src/motion3/skills/car.js +145 -0
- package/src/motion3/skills/frames-auto.js +29 -0
- package/src/motion3/skills/index.js +83 -0
- package/src/motion3/skills/info.js +65 -0
- package/src/motion3/skills/smoke-kit.js +109 -0
- package/src/motion3/skills/smoke.js +160 -0
- package/src/motion3/spec-store.js +59 -0
- package/src/motion3/take-edit.js +155 -0
- package/src/motion3/take.js +63 -0
- package/src/motion3/timeline.js +127 -0
- package/src/motion3/views.js +121 -0
- package/src/motion3/walk-plan.js +119 -0
- package/src/object-catalog.jsx +7 -1
- package/src/object-colors.js +98 -0
- package/src/object-gizmo-parts.js +115 -0
- package/src/object-gizmo.jsx +37 -122
- package/src/object-glow.js +139 -0
- package/src/object-hidden.js +33 -0
- package/src/object-look.js +196 -0
- package/src/object-size.js +10 -0
- package/src/object-travel.js +71 -6
- package/src/panels/CameraPanel.jsx +7 -7
- package/src/panels/HdrEnvironmentControls.jsx +59 -0
- package/src/panels/LightPanel.jsx +25 -4
- package/src/panels/ObjectLookPanel.jsx +88 -0
- package/src/panels/PosePanel.jsx +2 -17
- package/src/panels/RigControlPanel.jsx +5 -53
- package/src/panels/SubjectBox.jsx +4 -1
- package/src/panels/details.css +14 -0
- package/src/posestudio.jsx +4 -27
- package/src/project-browser.jsx +3 -4
- package/src/project-resources.js +18 -31
- package/src/project.js +13 -104
- package/src/props.jsx +25 -280
- package/src/rail-dot-drag.js +23 -0
- package/src/render-passes.js +10 -0
- package/src/resource-status.jsx +1 -0
- package/src/result-modal.jsx +4 -19
- package/src/room.jsx +20 -12
- package/src/scene-assets.js +8 -6
- package/src/scene-light-place.js +72 -0
- package/src/scene-lights.jsx +148 -0
- package/src/scene-objects.js +31 -139
- package/src/scenes.js +15 -105
- package/src/semantic-edit.js +2 -5
- package/src/set-pieces.jsx +183 -0
- package/src/settings-menu.jsx +3 -11
- package/src/shell/BottomDock.jsx +9 -51
- package/src/shell/DetailsSlot.jsx +16 -200
- package/src/shell/GhostsMenuGroup.jsx +74 -0
- package/src/shell/LibrarySlot.jsx +1 -3
- package/src/shell/MenuBar.jsx +3 -3
- package/src/shell/PreferencesDialog.jsx +15 -264
- package/src/shell/PreferencesSlot.jsx +2 -8
- package/src/shell/TopBar.jsx +5 -84
- package/src/shell/ViewportToolbar.jsx +10 -70
- package/src/shell/agent-glass.css +19 -6
- package/src/shell/details-selection.js +42 -0
- package/src/shell/ghosts-menu.css +22 -0
- package/src/shell/glass-regions.css +29 -3
- package/src/shell/preferences.css +6 -1
- package/src/shot-authoring.js +4 -7
- package/src/soft-shadows.js +37 -0
- package/src/stage-attach-frames.js +12 -12
- package/src/stage-canvas-rigs.jsx +3 -3
- package/src/stage-capture.jsx +42 -8
- package/src/stage-characters.jsx +22 -216
- package/src/stage-editor-gizmos.jsx +6 -6
- package/src/stage-environment.js +93 -0
- package/src/stage-hdr-builtins.js +107 -0
- package/src/stage-hdr-image.js +116 -0
- package/src/stage-hdr-library.js +70 -0
- package/src/stage-hdr-map.js +94 -0
- package/src/stage-hdr.js +130 -0
- package/src/stage-lighting.js +149 -0
- package/src/stage-occlusion.js +210 -0
- package/src/stage-sky.jsx +159 -0
- package/src/stage-startup-defaults.js +5 -9
- package/src/studio-actions.js +12 -14
- package/src/studio-agent-commands.js +19 -16
- package/src/studio-agent-motion.js +9 -9
- package/src/studio-agent-protocol.js +41 -71
- package/src/studio-app-binding.js +25 -45
- package/src/studio-asset-list.js +17 -0
- package/src/studio-contact-sheet.js +37 -5
- package/src/studio-elements.js +27 -7
- package/src/studio-entity-bounds.js +18 -0
- package/src/studio-error-codes.js +8 -0
- package/src/studio-export-framing.js +152 -0
- package/src/studio-lighting-check.js +103 -0
- package/src/studio-motion-visual.js +150 -0
- package/src/studio-schema-errors.js +80 -0
- package/src/studio-support-gap.js +74 -0
- package/src/styles.css +1 -19
- package/src/timeline-defaults.js +5 -0
- package/src/timeline-extent.js +8 -20
- package/src/tutorial-walk.js +17 -0
- package/src/ui-scrub.js +1 -1
- package/src/use-shot-camera-tracks.js +12 -0
- package/src/view-ghosts.js +97 -0
- package/src/view-ghosts.jsx +49 -0
- package/src/workflow/AgentPanel.jsx +47 -166
- package/src/workflow/AgentProgressCard.jsx +107 -0
- package/src/workflow/AgentReplyText.jsx +37 -0
- package/src/workflow/AgentTurnSteps.jsx +84 -0
- package/src/workflow/LoginPanel.jsx +140 -0
- package/src/workflow/WorkflowBuilder.jsx +7 -23
- package/src/workflow/agent-client.js +54 -51
- package/src/workflow/agent-panel.css +71 -1
- package/src/workflow/agent-progress-card.css +167 -0
- package/src/workflow/agent-progress-view.js +47 -0
- package/src/workflow/agent-turn-steps.css +113 -0
- package/src/workflow/agent-turn.js +191 -0
- package/src/workflow/login-client.js +34 -0
- package/src/workflow/motion-input.js +18 -31
- package/src/workflow/node-schema.js +1 -1
- package/src/workflow/reply-markdown.js +69 -0
- package/src/workflow/scene-asset-sync.js +8 -8
- package/tools/agent-session-stats.mjs +61 -0
- package/tools/dev-full.mjs +5 -56
- package/tools/eslint-baseline.json +12 -13
- package/tools/knip-baseline.json +0 -179
- package/tools/loc-baseline.json +31 -81
- package/tools/motion3/extract-body.mjs +103 -0
- package/tools/motion3/extract-rig.mjs +85 -0
- package/tools/process-supervisor.mjs +0 -88
- package/tools/run-tests.mjs +8 -124
- package/bin/agent/motion-runtime.mjs +0 -76
- package/dist/ardy/cskel27-rest.json +0 -557
- package/dist/assets/analytics-C9pMpW7s.js +0 -1
- package/dist/assets/app-B_2XB9rw.css +0 -1
- package/dist/assets/app-DAuvKPP8.js +0 -4920
- package/dist/assets/config-Bx7pYsD9.js +0 -1
- package/dist/assets/config-DeoFTYzb.css +0 -1
- package/dist/assets/demo-CvKuBgy5.js +0 -1
- package/dist/assets/scene-asset-sync-DKkpjKBV.js +0 -19
- package/dist/assets/scene-asset-sync-DjJ_cJ2R.css +0 -1
- package/dist/assets/ticket-BPk2Ni95.js +0 -1
- package/dist/assets/workflow-jJRBR94Z.js +0 -179
- package/dist/demo/walk-then-stop.npz +0 -0
- package/mcp/ardy-prompts.mjs +0 -218
- package/src/ardy/auto-fix-panel.css +0 -108
- package/src/ardy/auto-physics.js +0 -1194
- package/src/ardy/client.js +0 -153
- package/src/ardy/convert.js +0 -313
- package/src/ardy/cskel27-neutral.js +0 -39
- package/src/ardy/cskel27.js +0 -77
- package/src/ardy/export.js +0 -165
- package/src/ardy/fix-collisions.js +0 -2257
- package/src/ardy/foot-lock.js +0 -230
- package/src/ardy/motion-calibration.js +0 -118
- package/src/ardy/motion-edit.js +0 -213
- package/src/ardy/motion-url.js +0 -55
- package/src/ardy/mp4-duration.js +0 -102
- package/src/ardy/npz.js +0 -595
- package/src/ardy/physics-panel.css +0 -21
- package/src/ardy/physics-panel.jsx +0 -89
- package/src/ardy/physics-refine.js +0 -111
- package/src/ardy/physics-review.js +0 -567
- package/src/ardy/physics-temporal.js +0 -54
- package/src/ardy/platform-fit-panel.css +0 -64
- package/src/ardy/platform-fit-panel.jsx +0 -41
- package/src/ardy/platform-fit.js +0 -326
- package/src/ardy/playback.js +0 -711
- package/src/ardy/pose-pin.js +0 -97
- package/src/ardy/prompt-clips.js +0 -30
- package/src/ardy/retime.js +0 -211
- package/src/ardy/root-drop.js +0 -369
- package/src/ardy/timeline-resize.js +0 -13
- package/src/ardy/to-cskel27.js +0 -225
- package/src/ardy/trim.js +0 -33
- package/src/ardy/waypoints.js +0 -369
- package/src/ardy-bridge-contract.js +0 -281
- package/src/domains/motion/motion-video-capture.js +0 -664
- package/src/i2v-motion-client.js +0 -77
- package/src/i2v-motion-studio.jsx +0 -180
- package/src/line-edit.js +0 -1348
- package/src/motion/generation.js +0 -105
- package/src/motion-readiness-ui.jsx +0 -67
- package/src/motion-readiness.js +0 -40
- package/src/motion-resources.js +0 -177
- package/src/motion-store.js +0 -65
- package/src/motion-trail.js +0 -601
- package/src/multimodel-ingest.js +0 -394
- package/src/panels/PromptBlocksPanel.jsx +0 -444
- package/src/panels/VideoCapturePanel.jsx +0 -181
- package/src/pose-extract/browser.js +0 -42
- package/src/pose-extract/detector.js +0 -100
- package/src/pose-extract/fit.js +0 -227
- package/src/pose-extract/image-frame.js +0 -51
- package/src/pose-extract/index.js +0 -58
- package/src/pose-extract/keyframes.js +0 -74
- package/src/pose-extract/landmarks.js +0 -162
- package/src/pose-extract/mirror.js +0 -153
- package/src/pose-extract/take.js +0 -131
- package/src/pose-extract/video-frames.js +0 -91
- package/src/take-recipe.js +0 -165
- package/src/trail-key-conflicts.js +0 -39
- package/src/trail-pick.js +0 -59
- package/src/use-i2v-capture-modal.js +0 -15
- package/tools/ardy/BRIDGE.md +0 -37
- package/tools/ardy/GVHMR-NPZ.md +0 -68
- package/tools/ardy/README.md +0 -124
- package/tools/ardy/__pycache__/cclay_gvhmr_worker.cpython-313.pyc +0 -0
- package/tools/ardy/artifacts.mjs +0 -34
- package/tools/ardy/bridge.mjs +0 -1732
- package/tools/ardy/bvh-cskel27.mjs +0 -1265
- package/tools/ardy/cclay_constrained_generate.py +0 -561
- package/tools/ardy/cclay_gvhmr_worker.py +0 -264
- package/tools/ardy/cclay_motion_edit.py +0 -510
- package/tools/ardy/cclay_sequence_generate.py +0 -705
- package/tools/ardy/cclay_worker.py +0 -304
- package/tools/ardy/dump-npz.py +0 -205
- package/tools/ardy/extract-rest.mjs +0 -299
- package/tools/ardy/extract.mjs +0 -507
- package/tools/ardy/footage.mjs +0 -467
- package/tools/ardy/gvhmr-floor.mjs +0 -102
- package/tools/ardy/gvhmr-to-cskel27.mjs +0 -21
- package/tools/ardy/gvhmr_fastpath.py +0 -168
- package/tools/ardy/gvhmr_trajectory.py +0 -240
- package/tools/ardy/merge-text-encoder.py +0 -160
- package/tools/ardy/mocap-metrics.mjs +0 -200
- package/tools/ardy/mocap-quality-gate.mjs +0 -110
- package/tools/ardy/motion-stabilize.mjs +0 -348
- package/tools/ardy/npz.mjs +0 -414
- package/tools/ardy/pose-to-npz.mjs +0 -106
- package/tools/ardy/prompt-limits.mjs +0 -5
- package/tools/ardy/run-edit-on-box.sh +0 -73
- package/tools/ardy/run-local.mjs +0 -233
- package/tools/ardy/run-on-box.sh +0 -593
- package/tools/ardy/run-sequence-on-box.sh +0 -177
- package/tools/ardy/runners/gvhmr-worker.mjs +0 -206
- package/tools/ardy/runners/index.mjs +0 -18
- package/tools/ardy/runners/local.mjs +0 -455
- package/tools/ardy/runners/proc.mjs +0 -125
- package/tools/ardy/runners/remote.mjs +0 -252
- package/tools/ardy/setup-local.mjs +0 -189
- package/tools/ardy/setup-text-encoder-on-box.sh +0 -93
- package/tools/ardy/setup-text-encoder.py +0 -306
- package/tools/ardy/smpl-cskel27.mjs +0 -178
- package/tools/ardy/visual-qa.mjs +0 -196
- package/tools/ardy/vq-car.mjs +0 -52
- package/tools/bench/EXP3.md +0 -61
- package/tools/bench/cclay_bench_extract_incam.py +0 -125
- package/tools/bench/cclay_bench_extract_obs.py +0 -204
- package/tools/bench/cclay_bench_runner.py +0 -42
- package/tools/bench/cube-contact.mjs +0 -162
- package/tools/bench/exp3.mjs +0 -152
- package/tools/bench/extract-bench-lib.mjs +0 -216
- package/tools/bench/extract-bench.mjs +0 -302
- package/tools/bench/fal-generate.mjs +0 -88
- package/tools/bench/fit/README.md +0 -189
- package/tools/bench/fit/camera.mjs +0 -59
- package/tools/bench/fit/contact.mjs +0 -419
- package/tools/bench/fit/footlock.mjs +0 -234
- package/tools/bench/fit/motion.mjs +0 -85
- package/tools/bench/fit/pin.mjs +0 -27
- package/tools/bench/fit/remote.mjs +0 -105
- package/tools/bench/fit-bench.mjs +0 -126
- package/tools/bench/fit-sanity.mjs +0 -45
- package/tools/bench/metrics.mjs +0 -313
- package/tools/bench/obs/depth.mjs +0 -258
- package/tools/bench/obs/extrinsics.mjs +0 -175
- package/tools/bench/obs/fit_mannequin_betas.py +0 -340
- package/tools/bench/obs/ground.mjs +0 -294
- package/tools/bench/obs/heading.mjs +0 -151
- package/tools/bench/obs/ladder.mjs +0 -555
- package/tools/bench/obs/mannequin-betas.json +0 -124
- package/tools/bench/obs/remote.mjs +0 -83
- package/tools/bench/obs/rest_joints.py +0 -52
- package/tools/bench/obs/ybot-targets.mjs +0 -49
- package/tools/bench/obs-bench.mjs +0 -520
- package/tools/bench/score.mjs +0 -343
- package/tools/bench/summarize.mjs +0 -86
- package/tools/demo-worker/README.md +0 -137
- package/tools/demo-worker/api-client.mjs +0 -233
- package/tools/demo-worker/generate.mjs +0 -301
- package/tools/demo-worker/index.mjs +0 -466
- package/tools/demo-worker/sign-core.mjs +0 -112
- package/tools/demo-worker/sign.mjs +0 -161
- package/tools/gt-render/browser.mjs +0 -182
- package/tools/gt-render/camera-math.mjs +0 -276
- package/tools/gt-render/page.mjs +0 -267
- package/tools/gt-render/render.mjs +0 -514
- package/tools/gt-render/scene-box.mjs +0 -31
- package/tools/gt-render/take-transform.mjs +0 -87
- package/tools/kimodo/compare-seam.mjs +0 -108
- package/tools/kimodo/constraints.mjs +0 -244
- package/tools/kimodo/edit.mjs +0 -259
- package/tools/kimodo/effector-constraints.mjs +0 -200
- package/tools/kimodo/generate.mjs +0 -646
- package/tools/kimodo/local-output.mjs +0 -265
- package/tools/kimodo/measure-pose.mjs +0 -65
- package/tools/kimodo/measure-preserve.mjs +0 -899
- package/tools/kimodo/measure-waypoints.mjs +0 -55
- package/tools/kimodo/mlx-generate.py +0 -111
- package/tools/kimodo/pose-constraints.mjs +0 -248
- package/tools/kimodo/preserve-mask.mjs +0 -543
- package/tools/kimodo/read-npz.mjs +0 -189
- package/tools/kimodo/run-edit-on-box.mjs +0 -155
- package/tools/kimodo/run-sequence-on-box.mjs +0 -178
- package/tools/kimodo/runner.mjs +0 -284
- package/tools/kimodo/seam-batch.mjs +0 -77
- package/tools/kimodo/setup-local.mjs +0 -30
- package/tools/kimodo/setup-on-box.sh +0 -339
- package/tools/kimodo/soma77-to-cskel27.mjs +0 -305
- package/tools/morphgs/assets/gen_truth.py +0 -39
- package/tools/morphgs/assets/mesh_ori_rig.txt +0 -27
- package/tools/morphgs/assets/playback-check.mjs +0 -30
- package/tools/morphgs/demo-gate.sh +0 -26
- package/tools/morphgs/fbx2morphgs.mjs +0 -68
- package/tools/morphgs/morphgs-to-cskel27.mjs +0 -105
- package/tools/morphgs/patches/preprocess_src-none-mode.patch +0 -76
- package/tools/morphgs/setup-on-cluster.sh +0 -126
- package/tools/projflow/driver.py +0 -1069
- package/tools/projflow/generate.mjs +0 -805
- package/tools/projflow/hml22-to-cskel27.mjs +0 -735
- package/tools/projflow/line-edit-job.mjs +0 -547
- package/tools/projflow/replay.mjs +0 -452
- package/tools/projflow/runner.mjs +0 -269
- package/tools/projflow/service.mjs +0 -742
- package/tools/track/DESIGN.md +0 -513
- package/tools/track/backfill-provenance.mjs +0 -116
- package/tools/track/budget.mjs +0 -8
- package/tools/track/check-rig.mjs +0 -209
- package/tools/track/diagnostics.schema.json +0 -60
- package/tools/track/export-rig.mjs +0 -256
- package/tools/track/fallback.mjs +0 -7
- package/tools/track/fk-parity-fixture.mjs +0 -161
- package/tools/track/gate.mjs +0 -349
- package/tools/track/masks.mjs +0 -318
- package/tools/track/metrics.mjs +0 -201
- package/tools/track/publish-obs.mjs +0 -108
- package/tools/track/py/check_env.py +0 -61
- package/tools/track/py/eval_lr.py +0 -229
- package/tools/track/py/lr_viterbi.py +0 -294
- package/tools/track/py/masks.py +0 -405
- package/tools/track/py/objective.py +0 -382
- package/tools/track/py/rig.py +0 -508
- package/tools/track/py/scene.py +0 -326
- package/tools/track/py/test_joint_indices.py +0 -123
- package/tools/track/py/test_lr_viterbi.py +0 -195
- package/tools/track/py/test_masks.py +0 -229
- package/tools/track/py/test_rig.py +0 -288
- package/tools/track/py/test_scene.py +0 -354
- package/tools/track/py/test_track.py +0 -328
- package/tools/track/py/track.py +0 -411
- package/tools/track/remote.mjs +0 -140
- package/tools/track/rig-dump.mjs +0 -227
- package/tools/track/run-box-tests.mjs +0 -14
- package/tools/track/run-box.mjs +0 -168
- package/tools/track/setup-box.sh +0 -59
- package/tools/track/study-2d.mjs +0 -728
- /package/src/{ardy → motion}/collision-blockers.js +0 -0
- /package/src/{ardy → motion}/ground.js +0 -0
- /package/src/{ardy → motion}/ik-drag.js +0 -0
- /package/src/{ardy → motion}/ik-key-json.js +0 -0
- /package/src/{ardy → motion}/ik.js +0 -0
- /package/src/{ardy → motion}/physics-surface.js +0 -0
- /package/src/{ardy → motion}/playback-clock.js +0 -0
- /package/src/{ardy → motion}/range-pin.js +0 -0
|
@@ -1,168 +0,0 @@
|
|
|
1
|
-
"""Quality-preserving preparation around the existing box-side GVHMR runner.
|
|
2
|
-
|
|
3
|
-
No model, dtype, batch size, flip test, tracker, camera or motion math changes.
|
|
4
|
-
Only two strictly checkpoint-loaded preprocessing models are cached on CPU.
|
|
5
|
-
The upstream/checkpoint files remain untouched; all patches are scoped.
|
|
6
|
-
"""
|
|
7
|
-
import contextlib
|
|
8
|
-
import gc
|
|
9
|
-
import importlib
|
|
10
|
-
import sys
|
|
11
|
-
import time
|
|
12
|
-
import weakref
|
|
13
|
-
from pathlib import Path
|
|
14
|
-
|
|
15
|
-
import torch
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
@contextlib.contextmanager
|
|
19
|
-
def checked_fast_load():
|
|
20
|
-
"""Skip only random initialization that a complete checkpoint overwrites.
|
|
21
|
-
|
|
22
|
-
Audit live skipped tensors against tensors covered by load_state_dict.
|
|
23
|
-
Constants/zeros and non-persistent buffers are not skipped. An incomplete
|
|
24
|
-
checkpoint cannot leave uninitialized parameters silently in production.
|
|
25
|
-
"""
|
|
26
|
-
saved = []
|
|
27
|
-
skipped = []
|
|
28
|
-
covered = []
|
|
29
|
-
loads = []
|
|
30
|
-
original_load = torch.load
|
|
31
|
-
original_state_load = torch.nn.Module.load_state_dict
|
|
32
|
-
|
|
33
|
-
def patch(owner, name, value):
|
|
34
|
-
saved.append((owner, name, getattr(owner, name)))
|
|
35
|
-
setattr(owner, name, value)
|
|
36
|
-
|
|
37
|
-
def skip(tensor, *args, **kwargs):
|
|
38
|
-
skipped.append(weakref.ref(tensor))
|
|
39
|
-
return tensor
|
|
40
|
-
|
|
41
|
-
def mmap_load(*args, **kwargs):
|
|
42
|
-
if "mmap" in kwargs:
|
|
43
|
-
return original_load(*args, **kwargs)
|
|
44
|
-
try:
|
|
45
|
-
return original_load(*args, **kwargs, mmap=True)
|
|
46
|
-
except (RuntimeError, ValueError) as exc:
|
|
47
|
-
# Old torch checkpoint serialization cannot be memory-mapped.
|
|
48
|
-
if "mmap" not in str(exc).lower():
|
|
49
|
-
raise
|
|
50
|
-
return original_load(*args, **kwargs)
|
|
51
|
-
|
|
52
|
-
def state_load(module, state, *args, **kwargs):
|
|
53
|
-
result = original_state_load(module, state, *args, **kwargs)
|
|
54
|
-
if result.missing_keys or result.unexpected_keys:
|
|
55
|
-
raise RuntimeError("gvhmr-fast-load-incomplete-checkpoint")
|
|
56
|
-
loads.append(module)
|
|
57
|
-
covered.extend(weakref.ref(v) for v in module.state_dict(keep_vars=True).values())
|
|
58
|
-
return result
|
|
59
|
-
|
|
60
|
-
try:
|
|
61
|
-
for name in ("uniform_", "normal_", "trunc_normal_", "kaiming_uniform_", "kaiming_normal_",
|
|
62
|
-
"xavier_uniform_", "xavier_normal_", "orthogonal_", "sparse_"):
|
|
63
|
-
patch(torch.nn.init, name, skip)
|
|
64
|
-
# timm's imported trunc_normal_ delegates to this module-global helper.
|
|
65
|
-
for name in ("timm.layers.weight_init", "timm.models.layers.weight_init"):
|
|
66
|
-
module = sys.modules.get(name)
|
|
67
|
-
if module is not None and hasattr(module, "_trunc_normal_"):
|
|
68
|
-
patch(module, "_trunc_normal_", skip)
|
|
69
|
-
patch(torch, "load", mmap_load)
|
|
70
|
-
patch(torch.nn.Module, "load_state_dict", state_load)
|
|
71
|
-
yield
|
|
72
|
-
live = [ref() for ref in skipped if ref() is not None]
|
|
73
|
-
covered_storage = {ref().untyped_storage().data_ptr() for ref in covered if ref() is not None}
|
|
74
|
-
if not loads or any(t.untyped_storage().data_ptr() not in covered_storage for t in live):
|
|
75
|
-
raise RuntimeError("gvhmr-fast-load-uncovered-initialization")
|
|
76
|
-
finally:
|
|
77
|
-
for owner, name, value in reversed(saved):
|
|
78
|
-
setattr(owner, name, value)
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
class FastRuntime:
|
|
82
|
-
def __init__(self, runner, enabled=True):
|
|
83
|
-
self.runner = runner
|
|
84
|
-
self.enabled = enabled
|
|
85
|
-
self.cache = {}
|
|
86
|
-
self.signature = None
|
|
87
|
-
self.stats = {}
|
|
88
|
-
|
|
89
|
-
def invalidate_changed_weights(self):
|
|
90
|
-
paths = [Path(self.runner.__file__), Path(".git/HEAD"),
|
|
91
|
-
Path("inputs/checkpoints/vitpose/vitpose-h-multi-coco.pth"),
|
|
92
|
-
Path("inputs/checkpoints/hmr2/epoch=10-step=25000.ckpt")]
|
|
93
|
-
signature = tuple((str(p.resolve()), p.stat().st_size, p.stat().st_mtime_ns) for p in paths if p.exists())
|
|
94
|
-
if self.signature is not None and signature != self.signature:
|
|
95
|
-
self.cache.clear()
|
|
96
|
-
gc.collect()
|
|
97
|
-
self.signature = signature
|
|
98
|
-
|
|
99
|
-
def release_gpu(self):
|
|
100
|
-
for item, attribute in self.cache.values():
|
|
101
|
-
getattr(item, attribute).cpu()
|
|
102
|
-
gc.collect()
|
|
103
|
-
torch.cuda.empty_cache()
|
|
104
|
-
|
|
105
|
-
def acquire(self, name, factory, attribute):
|
|
106
|
-
started = time.perf_counter()
|
|
107
|
-
if name in self.cache:
|
|
108
|
-
item = self.cache[name][0]
|
|
109
|
-
getattr(item, attribute).cuda().eval()
|
|
110
|
-
self.stats["modelCacheHits"].append(name)
|
|
111
|
-
else:
|
|
112
|
-
with checked_fast_load():
|
|
113
|
-
item = factory()
|
|
114
|
-
self.cache[name] = (item, attribute)
|
|
115
|
-
self.stats["modelLoadSeconds"][name] = time.perf_counter() - started
|
|
116
|
-
return item
|
|
117
|
-
|
|
118
|
-
@contextlib.contextmanager
|
|
119
|
-
def job(self, evidence=None):
|
|
120
|
-
self.invalidate_changed_weights()
|
|
121
|
-
self.stats = {"modelCacheHits": [], "modelLoadSeconds": {}, "decodeCropCalls": 0,
|
|
122
|
-
"sharedCropHits": 0, "decodeCropSeconds": 0, "mode": "exact-fast" if self.enabled else "reference"}
|
|
123
|
-
runner = self.runner
|
|
124
|
-
vp = importlib.import_module("hmr4d.utils.preproc.vitpose")
|
|
125
|
-
vf = importlib.import_module("hmr4d.utils.preproc.vitfeat_extractor")
|
|
126
|
-
original_crop, original_vp_crop = vf.get_batch, vp.get_batch
|
|
127
|
-
original_preprocess, original_release = runner.preprocess, runner._release_gpu
|
|
128
|
-
original_vit, original_hmr = runner.VitPoseExtractor, runner.Extractor
|
|
129
|
-
crops = []
|
|
130
|
-
|
|
131
|
-
def shared_crop(path, boxes, *args, **kwargs):
|
|
132
|
-
for prior_path, prior_boxes, prior_args, prior_kwargs, output in crops:
|
|
133
|
-
if str(path) == prior_path and args == prior_args and kwargs == prior_kwargs and torch.equal(boxes, prior_boxes):
|
|
134
|
-
self.stats["sharedCropHits"] += 1
|
|
135
|
-
# Both consumers read their input. Cloning prevents a future
|
|
136
|
-
# in-place consumer from contaminating the other model.
|
|
137
|
-
return tuple(v.clone() for v in output)
|
|
138
|
-
started = time.perf_counter()
|
|
139
|
-
output = original_crop(path, boxes, *args, **kwargs)
|
|
140
|
-
self.stats["decodeCropCalls"] += 1
|
|
141
|
-
self.stats["decodeCropSeconds"] += time.perf_counter() - started
|
|
142
|
-
if self.enabled:
|
|
143
|
-
crops.append((str(path), boxes.clone(), args, dict(kwargs), tuple(v.clone() for v in output)))
|
|
144
|
-
return output
|
|
145
|
-
|
|
146
|
-
def preprocess(*args, **kwargs):
|
|
147
|
-
started = time.perf_counter()
|
|
148
|
-
data = original_preprocess(*args, **kwargs)
|
|
149
|
-
self.stats["preprocessSeconds"] = time.perf_counter() - started
|
|
150
|
-
if evidence:
|
|
151
|
-
torch.save(data, Path(evidence) / "preprocess.pt")
|
|
152
|
-
crops.clear()
|
|
153
|
-
return data
|
|
154
|
-
|
|
155
|
-
try:
|
|
156
|
-
vf.get_batch = vp.get_batch = shared_crop
|
|
157
|
-
runner.preprocess = preprocess
|
|
158
|
-
if self.enabled:
|
|
159
|
-
runner.VitPoseExtractor = lambda: self.acquire("vitpose", original_vit, "pose")
|
|
160
|
-
runner.Extractor = lambda: self.acquire("hmr2", original_hmr, "extractor")
|
|
161
|
-
runner._release_gpu = self.release_gpu
|
|
162
|
-
yield self.stats
|
|
163
|
-
finally:
|
|
164
|
-
runner.preprocess, runner._release_gpu = original_preprocess, original_release
|
|
165
|
-
runner.VitPoseExtractor, runner.Extractor = original_vit, original_hmr
|
|
166
|
-
vf.get_batch, vp.get_batch = original_crop, original_vp_crop
|
|
167
|
-
crops.clear()
|
|
168
|
-
self.release_gpu()
|
|
@@ -1,240 +0,0 @@
|
|
|
1
|
-
"""Observation-anchored recovery of delayed vertical descents from GVHMR.
|
|
2
|
-
|
|
3
|
-
This is NOT a ground-every-frame filter or a general dynamics solver. A
|
|
4
|
-
stationary-camera take must contain a large, confident image-space descent
|
|
5
|
-
and an observed landing plateau. A delayed world endpoint may be recovered
|
|
6
|
-
from that observation when it never settles. Frames, rotations and XZ
|
|
7
|
-
are never changed. Ambiguous events retain the original output.
|
|
8
|
-
"""
|
|
9
|
-
import contextlib
|
|
10
|
-
import json
|
|
11
|
-
import time
|
|
12
|
-
from pathlib import Path
|
|
13
|
-
|
|
14
|
-
import numpy as np
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
def smooth(values, sigma):
|
|
18
|
-
radius = max(1, int(np.ceil(3 * sigma)))
|
|
19
|
-
x = np.arange(-radius, radius + 1)
|
|
20
|
-
weights = np.exp(-0.5 * (x / max(sigma, 0.25)) ** 2)
|
|
21
|
-
weights /= weights.sum()
|
|
22
|
-
return np.convolve(np.pad(values, (radius, radius), mode="edge"), weights, mode="valid")
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
def center_of_mass(joints):
|
|
26
|
-
"""Approximate segment-mass COM; normalized weights, not a pelvis proxy."""
|
|
27
|
-
segments = [(0, 12, .497), (12, 15, .081),
|
|
28
|
-
(1, 4, .100), (2, 5, .100), (4, 7, .0465), (5, 8, .0465),
|
|
29
|
-
(7, 10, .0145), (8, 11, .0145),
|
|
30
|
-
(16, 18, .028), (17, 19, .028), (18, 20, .016), (19, 21, .016),
|
|
31
|
-
(20, 20, .006), (21, 21, .006)]
|
|
32
|
-
return sum((joints[:, a] + joints[:, b]) * (weight * .5)
|
|
33
|
-
for a, b, weight in segments) / sum(s[2] for s in segments)
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
def recover_vertical(root, joints, camera_joints, keypoints, intrinsics, camera_up, fps):
|
|
37
|
-
"""Pure NumPy kernel. Returns Y corrections and inspectable diagnostics.
|
|
38
|
-
|
|
39
|
-
Units are meters and seconds. COCO hips 11/12 provide translation
|
|
40
|
-
observations; the ballistic proposal uses whole-body COM. FPS is always
|
|
41
|
-
the actual source FPS, never inferred from number of frames.
|
|
42
|
-
"""
|
|
43
|
-
root = np.asarray(root, dtype=np.float64)
|
|
44
|
-
n = len(root)
|
|
45
|
-
delta = np.zeros(n, dtype=np.float64)
|
|
46
|
-
report = {"version": 2, "status": "unchanged", "events": [], "rejected": [],
|
|
47
|
-
"frames": n, "fps": float(fps), "changedFrames": 0}
|
|
48
|
-
arrays = [root, joints, camera_joints, keypoints, intrinsics, camera_up]
|
|
49
|
-
if not np.isfinite(fps) or not 5 <= fps <= 240 or n < 12 or any(not np.isfinite(a).all() for a in arrays):
|
|
50
|
-
report["reason"] = "invalid-input"
|
|
51
|
-
return delta, report
|
|
52
|
-
joints, camera_joints = np.asarray(joints), np.asarray(camera_joints)
|
|
53
|
-
keypoints, intrinsics = np.asarray(keypoints), np.asarray(intrinsics)
|
|
54
|
-
if root.shape != (n, 3) or joints.shape != (n, 22, 3) or camera_joints.shape != (n, 22, 3) or keypoints.shape != (n, 17, 3):
|
|
55
|
-
report["reason"] = "unsupported-shape"
|
|
56
|
-
return delta, report
|
|
57
|
-
k = intrinsics[0] if intrinsics.ndim == 3 else intrinsics
|
|
58
|
-
up = np.asarray(camera_up)
|
|
59
|
-
projected_up = np.array([k[0, 0] * up[0], k[1, 1] * up[1]])
|
|
60
|
-
norm = np.linalg.norm(projected_up)
|
|
61
|
-
depth = camera_joints[:, 0, 2]
|
|
62
|
-
if norm < .45 * min(k[0, 0], k[1, 1]) or np.median(depth) <= 0:
|
|
63
|
-
report["reason"] = "gravity-axis-not-observable"
|
|
64
|
-
return delta, report
|
|
65
|
-
if intrinsics.ndim == 3 and np.max(np.abs(intrinsics - k)) > .01 * np.max(k):
|
|
66
|
-
report["reason"] = "variable-intrinsics"
|
|
67
|
-
return delta, report
|
|
68
|
-
hip_conf = np.minimum(keypoints[:, 11, 2], keypoints[:, 12, 2])
|
|
69
|
-
hips = keypoints[:, [11, 12], :2].mean(axis=1)
|
|
70
|
-
# Fixed metric scale over the take avoids bbox/depth breathing as the
|
|
71
|
-
# person curls up. Only timing is recovered: endpoint world heights are
|
|
72
|
-
# retained, so this does not pretend to solve monocular absolute scale.
|
|
73
|
-
scale = np.median(depth) / norm
|
|
74
|
-
observed = smooth(hips @ (projected_up / norm) * scale, max(.6, fps * .04))
|
|
75
|
-
height = float(np.median(np.linalg.norm(joints[:, 12] - joints[:, 0], axis=1) +
|
|
76
|
-
np.linalg.norm(joints[:, 0] - joints[:, 4], axis=1) +
|
|
77
|
-
np.linalg.norm(joints[:, 4] - joints[:, 7], axis=1)) * 1.35)
|
|
78
|
-
height = max(.8, height)
|
|
79
|
-
velocity = np.gradient(observed) * fps
|
|
80
|
-
base = root[:, 1]
|
|
81
|
-
base_smooth = smooth(base, max(.6, fps * .04))
|
|
82
|
-
base_velocity = np.gradient(base_smooth) * fps
|
|
83
|
-
settle = max(4, round(.25 * fps))
|
|
84
|
-
com_offset = center_of_mass(joints)[:, 1] - base
|
|
85
|
-
i = 1
|
|
86
|
-
while i < n - settle:
|
|
87
|
-
if velocity[i] >= -.65 * height:
|
|
88
|
-
i += 1
|
|
89
|
-
continue
|
|
90
|
-
fast_start = i
|
|
91
|
-
while i < n - 1 and velocity[i] < -.3 * height:
|
|
92
|
-
i += 1
|
|
93
|
-
end_fast = i
|
|
94
|
-
start = fast_start
|
|
95
|
-
while start > 0 and velocity[start - 1] < -.1 * height and fast_start - start < .4 * fps:
|
|
96
|
-
start -= 1
|
|
97
|
-
# Landing evidence is a stable observed pelvis, not a local minimum
|
|
98
|
-
# of the already incorrect GVHMR root or a hard-coded pose category.
|
|
99
|
-
landing = None
|
|
100
|
-
for t in range(end_fast, min(n - settle, end_fast + round(.6 * fps)) + 1):
|
|
101
|
-
if np.max(observed[t:t + settle]) - np.min(observed[t:t + settle]) < .025 * height:
|
|
102
|
-
landing = t
|
|
103
|
-
break
|
|
104
|
-
if landing is None:
|
|
105
|
-
report["rejected"].append({"start": start, "reason": "no-observed-landing"})
|
|
106
|
-
continue
|
|
107
|
-
drop = observed[start] - np.median(observed[landing:landing + settle])
|
|
108
|
-
if drop < .35 * height or not .12 <= (landing - start) / fps <= 2.0:
|
|
109
|
-
continue
|
|
110
|
-
if np.quantile(hip_conf[start:landing + settle], .1) < .55:
|
|
111
|
-
report["rejected"].append({"start": start, "landing": landing, "reason": "uncertain-keypoints"})
|
|
112
|
-
continue
|
|
113
|
-
if np.ptp(depth[start:landing + settle]) > .35 * np.median(depth[start:landing + settle]):
|
|
114
|
-
report["rejected"].append({"start": start, "landing": landing, "reason": "uncertain-depth"})
|
|
115
|
-
continue
|
|
116
|
-
anchor = None
|
|
117
|
-
for t in range(landing, min(n - settle, landing + round(3 * fps)) + 1):
|
|
118
|
-
if np.max(np.abs(base_velocity[t:t + settle])) < .08 * height:
|
|
119
|
-
anchor = t + settle - 1
|
|
120
|
-
break
|
|
121
|
-
endpoint_source = "settled-world"
|
|
122
|
-
if anchor is None:
|
|
123
|
-
# A lagging prediction often keeps descending past the end of a
|
|
124
|
-
# short clip. Requiring that same prediction to settle prevented
|
|
125
|
-
# recovery exactly when it was needed. Use a persistent observed
|
|
126
|
-
# plateau and metric camera scale, NOT the erroneous last height.
|
|
127
|
-
anchor = n - 1
|
|
128
|
-
if anchor - landing < round(.4 * fps):
|
|
129
|
-
report["rejected"].append({"start": start, "landing": landing, "reason": "landing-observation-too-short"})
|
|
130
|
-
continue
|
|
131
|
-
endpoint_source = "observed-plateau"
|
|
132
|
-
# The image must remain on its plateau while the world catches up.
|
|
133
|
-
# This rejects another jump, stairs and camera motion during the tail.
|
|
134
|
-
if np.ptp(observed[landing:anchor + 1]) > .07 * height:
|
|
135
|
-
report["rejected"].append({"start": start, "landing": landing, "reason": "moving-landing"})
|
|
136
|
-
continue
|
|
137
|
-
tail_drift = base[landing] - base[anchor]
|
|
138
|
-
total_drop = base[start] - base[anchor]
|
|
139
|
-
if tail_drift < .12 * height or total_drop < .35 * height:
|
|
140
|
-
i = landing + settle
|
|
141
|
-
continue
|
|
142
|
-
stop_observed = float(np.median(observed[landing:anchor + 1]))
|
|
143
|
-
endpoint_y = base[anchor] if endpoint_source == "settled-world" else base[start] - (observed[start] - stop_observed)
|
|
144
|
-
progress = np.clip((observed[start] - observed[start:anchor + 1]) /
|
|
145
|
-
max(observed[start] - stop_observed, 1e-8), 0, 1)
|
|
146
|
-
target = base[start] + progress * (endpoint_y - base[start])
|
|
147
|
-
# Keep the original endpoint exactly, with a short smooth residual
|
|
148
|
-
# bridge inside the observed plateau (no tail offset after the event).
|
|
149
|
-
end_blend = min(settle, len(target))
|
|
150
|
-
blend = np.linspace(0, 1, end_blend)
|
|
151
|
-
blend = blend * blend * (3 - 2 * blend)
|
|
152
|
-
target[-end_blend:] += (endpoint_y - target[-1]) * blend
|
|
153
|
-
airborne = landing - start + 1
|
|
154
|
-
observed_com = target[:airborne] + com_offset[start:landing + 1]
|
|
155
|
-
# The stable landing window includes a few post-impact frames.
|
|
156
|
-
# Do not force those frames to keep accelerating under gravity.
|
|
157
|
-
# Locate an impact endpoint near the plateau, after >=90% descent
|
|
158
|
-
# (the short image denoising kernel blurs the impact discontinuity).
|
|
159
|
-
ballistic_error, ballistic, gravity_end = float("inf"), None, None
|
|
160
|
-
for stop in range(max(4, airborne - round(.15 * fps)), airborne + 1):
|
|
161
|
-
if progress[stop - 1] < .9:
|
|
162
|
-
continue
|
|
163
|
-
times = np.arange(stop) / fps
|
|
164
|
-
duration = times[-1]
|
|
165
|
-
initial_velocity = (observed_com[stop - 1] - observed_com[0] + .5 * 9.81 * duration ** 2) / duration
|
|
166
|
-
proposal = observed_com[0] + initial_velocity * times - .5 * 9.81 * times ** 2
|
|
167
|
-
error = float(np.sqrt(np.mean((proposal - observed_com[:stop]) ** 2)))
|
|
168
|
-
if error < ballistic_error:
|
|
169
|
-
ballistic_error, ballistic, gravity_end = error, proposal, stop
|
|
170
|
-
gravity_applied = ballistic_error < .025 * height
|
|
171
|
-
if gravity_applied:
|
|
172
|
-
target[:gravity_end] = ballistic - com_offset[start:start + gravity_end]
|
|
173
|
-
change = target - base[start:anchor + 1]
|
|
174
|
-
if np.max(np.abs(change)) > 2.5 * height:
|
|
175
|
-
report["rejected"].append({"start": start, "reason": "excessive-correction"})
|
|
176
|
-
continue
|
|
177
|
-
delta[start:anchor + 1] = change
|
|
178
|
-
report["events"].append({"start": start, "landing": landing, "anchor": anchor,
|
|
179
|
-
"endpointSource": endpoint_source,
|
|
180
|
-
"sourceDropM": float(drop), "worldDropM": float(total_drop),
|
|
181
|
-
"tailDriftBeforeM": float(tail_drift),
|
|
182
|
-
"tailDriftAfterM": float(target[airborne - 1] - target[-1]),
|
|
183
|
-
"maxCorrectionM": float(np.max(np.abs(change))),
|
|
184
|
-
"gravityApplied": bool(gravity_applied),
|
|
185
|
-
"gravityFitRmseM": ballistic_error if np.isfinite(ballistic_error) else None,
|
|
186
|
-
"gravityIntervalEnd": start + gravity_end - 1 if gravity_applied else None,
|
|
187
|
-
"mode": "ballistic-com" if gravity_applied else "observed-timing",
|
|
188
|
-
"gravityReason": None if gravity_applied else "ballistic-curve-disagrees-with-video"})
|
|
189
|
-
i = anchor + 1
|
|
190
|
-
report["changedFrames"] = int(np.count_nonzero(np.abs(delta) > 1e-6))
|
|
191
|
-
report["status"] = "corrected" if report["events"] else "unchanged"
|
|
192
|
-
if not report["events"]:
|
|
193
|
-
report["reason"] = "no-confident-delayed-descent"
|
|
194
|
-
return delta, report
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
@contextlib.contextmanager
|
|
198
|
-
def trajectory_job(runner, video, output_root, *, enabled=True):
|
|
199
|
-
"""Scoped post-inference hook; upstream files and original runner stay intact."""
|
|
200
|
-
stats = {"version": 1, "status": "disabled", "changedFrames": 0}
|
|
201
|
-
if not enabled:
|
|
202
|
-
yield stats
|
|
203
|
-
return
|
|
204
|
-
import torch
|
|
205
|
-
from pytorch3d.transforms import axis_angle_to_matrix
|
|
206
|
-
original = runner.DemoPL.predict
|
|
207
|
-
# The legacy NPZ exporter rounds FPS to an integer. Keep fractional
|
|
208
|
-
# source rates here so the physical proposal uses seconds, not that label.
|
|
209
|
-
fps = float(runner.iio.immeta(str(video), plugin="pyav").get("fps") or runner.video_fps(str(video)))
|
|
210
|
-
|
|
211
|
-
def predict(model, data, static_cam=False):
|
|
212
|
-
result = original(model, data, static_cam=static_cam)
|
|
213
|
-
began = time.perf_counter()
|
|
214
|
-
if not static_cam:
|
|
215
|
-
stats.update(status="unchanged", reason="moving-camera-not-supported")
|
|
216
|
-
return result
|
|
217
|
-
with torch.no_grad():
|
|
218
|
-
endecoder = model.pipeline.endecoder
|
|
219
|
-
gp, cp = result["smpl_params_global"], result["smpl_params_incam"]
|
|
220
|
-
w = endecoder.fk_v2(**{k: v[None] for k, v in gp.items()})[0]
|
|
221
|
-
c = endecoder.fk_v2(**{k: v[None] for k, v in cp.items()})[0]
|
|
222
|
-
r_c2w = axis_angle_to_matrix(gp["global_orient"][0]) @ axis_angle_to_matrix(cp["global_orient"][0]).T
|
|
223
|
-
cpu = lambda a: a.detach().cpu().numpy()
|
|
224
|
-
delta, report = recover_vertical(cpu(gp["transl"]), cpu(w), cpu(c), cpu(data["kp2d"]),
|
|
225
|
-
cpu(data["K_fullimg"]), cpu(r_c2w.T[:, 1]), fps)
|
|
226
|
-
if report["events"]:
|
|
227
|
-
corrected = gp["transl"].clone()
|
|
228
|
-
corrected[:, 1] += torch.as_tensor(delta, device=corrected.device, dtype=corrected.dtype)
|
|
229
|
-
gp["transl"] = corrected
|
|
230
|
-
result["net_outputs"]["pred_smpl_params_global"]["transl"] = corrected[None]
|
|
231
|
-
stats.update(report)
|
|
232
|
-
stats["seconds"] = time.perf_counter() - began
|
|
233
|
-
Path(output_root, "trajectory.json").write_text(json.dumps(stats, indent=2))
|
|
234
|
-
return result
|
|
235
|
-
|
|
236
|
-
runner.DemoPL.predict = predict
|
|
237
|
-
try:
|
|
238
|
-
yield stats
|
|
239
|
-
finally:
|
|
240
|
-
runner.DemoPL.predict = original
|
|
@@ -1,160 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""merge-text-encoder.py - bake the MNTP LoRA into the base weights.
|
|
3
|
-
|
|
4
|
-
Run under the ARDY text-encoder venv (needs torch, peft, transformers, and
|
|
5
|
-
the `ardy` package importable — i.e. from the ARDY checkout):
|
|
6
|
-
|
|
7
|
-
cd ~/ardy && .venv/bin/python merge-text-encoder.py --dest ~/cclay-text-encoders
|
|
8
|
-
|
|
9
|
-
Why this exists: transformers v5 removed the automatic PEFT-adapter
|
|
10
|
-
resolution that `from_pretrained` did in v4 (`find_adapter_config_file` is
|
|
11
|
-
gone from modeling_utils). ARDY's vendored LLM2Vec loader relies on that
|
|
12
|
-
behavior — it points `from_pretrained` at the MNTP *adapter* repo and lets
|
|
13
|
-
transformers chase `adapter_config.json` to the (gated) base. Under v5 that
|
|
14
|
-
path simply fails with "no model.safetensors found".
|
|
15
|
-
|
|
16
|
-
So instead of an adapter directory, the local MNTP path becomes a full
|
|
17
|
-
model: this script loads the ungated base (NousResearch mirror, already
|
|
18
|
-
hash-verified by setup-text-encoder.py), applies the MNTP LoRA with peft,
|
|
19
|
-
`merge_and_unload()`s it — the exact math upstream LLM2Vec performs at load
|
|
20
|
-
time — and saves the merged weights to the path ARDY's TEXT_ENCODERS_DIR
|
|
21
|
-
override resolves. Plain full-model loading works identically under
|
|
22
|
-
transformers v4 and v5; the supervised LoRA keeps loading through peft
|
|
23
|
-
directly, which both versions support.
|
|
24
|
-
|
|
25
|
-
Layout before: <dest>/McGill-NLP/...-mntp (downloaded adapter files)
|
|
26
|
-
Layout after: <dest>/McGill-NLP/...-mntp-src (the downloads, kept for
|
|
27
|
-
provenance + re-merges)
|
|
28
|
-
<dest>/McGill-NLP/...-mntp (merged full model +
|
|
29
|
-
tokenizer + MERGE_MANIFEST)
|
|
30
|
-
|
|
31
|
-
The merged config.json keeps `_name_or_path` =
|
|
32
|
-
"meta-llama/Meta-Llama-3-8B-Instruct": it is a metadata string (no download
|
|
33
|
-
or gate involved) that LLM2Vec's `prepare_for_tokenization` matches to pick
|
|
34
|
-
the Llama-3 chat template — losing it would silently change every prompt
|
|
35
|
-
embedding.
|
|
36
|
-
"""
|
|
37
|
-
|
|
38
|
-
import argparse
|
|
39
|
-
import hashlib
|
|
40
|
-
import json
|
|
41
|
-
import os
|
|
42
|
-
import shutil
|
|
43
|
-
import sys
|
|
44
|
-
|
|
45
|
-
BASE = "NousResearch/Meta-Llama-3-8B-Instruct"
|
|
46
|
-
MNTP = "McGill-NLP/LLM2Vec-Meta-Llama-3-8B-Instruct-mntp"
|
|
47
|
-
MNTP_SRC = MNTP + "-src"
|
|
48
|
-
NAME_OR_PATH = "meta-llama/Meta-Llama-3-8B-Instruct"
|
|
49
|
-
TOKENIZER_FILES = ["tokenizer.json", "tokenizer_config.json", "special_tokens_map.json"]
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
def log(msg):
|
|
53
|
-
print("merge-text-encoder: %s" % msg, flush=True)
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
def fail(msg):
|
|
57
|
-
print("merge-text-encoder: ERROR: %s" % msg, file=sys.stderr, flush=True)
|
|
58
|
-
sys.exit(1)
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
def sha256_file(path):
|
|
62
|
-
h = hashlib.sha256()
|
|
63
|
-
with open(path, "rb") as f:
|
|
64
|
-
for block in iter(lambda: f.read(1024 * 1024), b""):
|
|
65
|
-
h.update(block)
|
|
66
|
-
return h.hexdigest()
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
def main():
|
|
70
|
-
ap = argparse.ArgumentParser(description=__doc__.splitlines()[0])
|
|
71
|
-
ap.add_argument("--dest", default=os.environ.get(
|
|
72
|
-
"TEXT_ENCODERS_DIR", os.path.expanduser("~/cclay-text-encoders")))
|
|
73
|
-
args = ap.parse_args()
|
|
74
|
-
dest = os.path.abspath(os.path.expanduser(args.dest))
|
|
75
|
-
base_dir = os.path.join(dest, BASE)
|
|
76
|
-
mntp_dir = os.path.join(dest, MNTP)
|
|
77
|
-
src_dir = os.path.join(dest, MNTP_SRC)
|
|
78
|
-
|
|
79
|
-
if not os.path.isfile(os.path.join(base_dir, "model.safetensors.index.json")):
|
|
80
|
-
fail("base model missing under %s — run setup-text-encoder.py first" % base_dir)
|
|
81
|
-
|
|
82
|
-
# Migrate a pre-merge tree: the download step used to land the adapter
|
|
83
|
-
# files directly at the mntp path.
|
|
84
|
-
if os.path.isdir(mntp_dir) and not os.path.isdir(src_dir) \
|
|
85
|
-
and os.path.isfile(os.path.join(mntp_dir, "adapter_model.safetensors")) \
|
|
86
|
-
and not os.path.isfile(os.path.join(mntp_dir, "model.safetensors.index.json")):
|
|
87
|
-
os.rename(mntp_dir, src_dir)
|
|
88
|
-
log("moved downloaded adapter layout to %s" % MNTP_SRC)
|
|
89
|
-
|
|
90
|
-
if not os.path.isfile(os.path.join(src_dir, "adapter_model.safetensors")):
|
|
91
|
-
fail("MNTP adapter missing under %s — run setup-text-encoder.py first" % src_dir)
|
|
92
|
-
|
|
93
|
-
adapter_sha = sha256_file(os.path.join(src_dir, "adapter_model.safetensors"))
|
|
94
|
-
manifest_path = os.path.join(mntp_dir, "MERGE_MANIFEST.json")
|
|
95
|
-
if os.path.isfile(manifest_path):
|
|
96
|
-
with open(manifest_path, "r", encoding="utf-8") as f:
|
|
97
|
-
manifest = json.load(f)
|
|
98
|
-
if manifest.get("mntp_adapter_sha256") == adapter_sha \
|
|
99
|
-
and os.path.isfile(os.path.join(mntp_dir, "model.safetensors.index.json")):
|
|
100
|
-
log("merged model already present and matches the adapter hash — nothing to do")
|
|
101
|
-
return
|
|
102
|
-
|
|
103
|
-
import torch # deferred: keep --help fast and errors readable
|
|
104
|
-
import peft
|
|
105
|
-
import transformers
|
|
106
|
-
from peft import PeftModel
|
|
107
|
-
from ardy.model.llm2vec.llm2vec import LLM2Vec
|
|
108
|
-
|
|
109
|
-
log("loading base (bfloat16, cpu) from %s" % base_dir)
|
|
110
|
-
model_class = LLM2Vec._get_model_class("LlamaConfig", enable_bidirectional=True)
|
|
111
|
-
model = model_class.from_pretrained(base_dir, torch_dtype=torch.bfloat16)
|
|
112
|
-
|
|
113
|
-
log("applying + merging the MNTP LoRA from %s" % src_dir)
|
|
114
|
-
model = PeftModel.from_pretrained(model, src_dir)
|
|
115
|
-
model = model.merge_and_unload()
|
|
116
|
-
|
|
117
|
-
tmp_out = mntp_dir + ".merging"
|
|
118
|
-
if os.path.isdir(tmp_out):
|
|
119
|
-
shutil.rmtree(tmp_out)
|
|
120
|
-
log("saving merged model to %s" % mntp_dir)
|
|
121
|
-
model.save_pretrained(tmp_out, safe_serialization=True)
|
|
122
|
-
del model
|
|
123
|
-
|
|
124
|
-
for name in TOKENIZER_FILES:
|
|
125
|
-
src = os.path.join(src_dir, name)
|
|
126
|
-
if os.path.isfile(src):
|
|
127
|
-
shutil.copy2(src, os.path.join(tmp_out, name))
|
|
128
|
-
|
|
129
|
-
# Preserve the chat-template key and the source architecture label.
|
|
130
|
-
cfg_path = os.path.join(tmp_out, "config.json")
|
|
131
|
-
with open(cfg_path, "r", encoding="utf-8") as f:
|
|
132
|
-
cfg = json.load(f)
|
|
133
|
-
with open(os.path.join(src_dir, "config.json"), "r", encoding="utf-8") as f:
|
|
134
|
-
src_cfg = json.load(f)
|
|
135
|
-
cfg["_name_or_path"] = NAME_OR_PATH
|
|
136
|
-
if "architectures" in src_cfg:
|
|
137
|
-
cfg["architectures"] = src_cfg["architectures"]
|
|
138
|
-
with open(cfg_path, "w", encoding="utf-8") as f:
|
|
139
|
-
json.dump(cfg, f, indent=2)
|
|
140
|
-
f.write("\n")
|
|
141
|
-
|
|
142
|
-
with open(os.path.join(tmp_out, "MERGE_MANIFEST.json"), "w", encoding="utf-8") as f:
|
|
143
|
-
json.dump({
|
|
144
|
-
"base": BASE,
|
|
145
|
-
"mntp_adapter_sha256": adapter_sha,
|
|
146
|
-
"torch": torch.__version__,
|
|
147
|
-
"transformers": transformers.__version__,
|
|
148
|
-
"peft": peft.__version__,
|
|
149
|
-
"name_or_path": NAME_OR_PATH,
|
|
150
|
-
}, f, indent=2)
|
|
151
|
-
f.write("\n")
|
|
152
|
-
|
|
153
|
-
if os.path.isdir(mntp_dir):
|
|
154
|
-
shutil.rmtree(mntp_dir)
|
|
155
|
-
os.rename(tmp_out, mntp_dir)
|
|
156
|
-
log("done — %s is a full merged model; the supervised LoRA stays a peft adapter" % MNTP)
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
if __name__ == "__main__":
|
|
160
|
-
main()
|