cozyclay 2.1.1 → 3.0.1
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 +88 -0
- package/README.md +12 -30
- package/bin/agent/agent-routes.mjs +43 -116
- package/bin/agent/agent-runner.mjs +14 -15
- 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/session-store.mjs +2 -2
- package/bin/agent/studio-context-budget.mjs +93 -0
- 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-BWCqdgWA.js +1 -0
- package/dist/assets/app-DfTCxaKk.js +5087 -0
- package/dist/assets/app-f-fkV5uP.css +1 -0
- package/dist/assets/compile-worker-BxKXh07s.js +5 -0
- package/dist/assets/fflate.module-KbGj5-H6.js +5 -0
- package/dist/assets/{first-shot-handoff-msLI71g1.js → first-shot-handoff-DNO8kv_N.js} +1 -1
- package/dist/assets/{landing-ChUvB_zL.js → landing-yfZaJkWc.js} +1 -1
- package/dist/assets/scene-asset-sync-U3kS2rvK.js +20 -0
- package/dist/assets/scene-asset-sync-_S8NQl5B.css +1 -0
- package/dist/assets/workflow-D78eiKTa.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 +151 -2625
- package/src/agent-progress.js +80 -0
- package/src/agent-turn-mark.js +30 -0
- package/src/analytics.js +1 -19
- package/src/app-context.js +12 -2
- 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 +10 -8
- 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 +214 -0
- package/src/commands/objects.js +6 -4
- package/src/commands/shot.js +55 -13
- 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 +53 -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 +47 -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 +60 -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 +79 -0
- package/src/motion3/compile-worker.js +10 -0
- package/src/motion3/compiler/anchors.js +113 -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 +197 -0
- package/src/motion3/compiler/math.js +72 -0
- package/src/motion3/compiler/pose.js +177 -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 +144 -0
- package/src/motion3/compiler/validate-parts.js +118 -0
- package/src/motion3/compiler/validate.js +122 -0
- package/src/motion3/compiler/vocab.js +74 -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 +177 -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 +204 -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/people.js +82 -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 +125 -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 +195 -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 +44 -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/people-checks.js +37 -0
- package/src/motion3/qa/severity.js +38 -0
- package/src/motion3/qa/spec-checks.js +65 -0
- package/src/motion3/qa/style.js +228 -0
- package/src/motion3/qa/wrist-checks.js +69 -0
- package/src/motion3/qa/wrist-obs.js +60 -0
- package/src/motion3/refs.js +129 -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 +113 -0
- package/src/motion3/schema/types.js +149 -0
- package/src/motion3/search.js +117 -0
- package/src/motion3/second-hand.js +112 -0
- package/src/motion3/settle.js +136 -0
- package/src/motion3/skills/basic.js +83 -0
- package/src/motion3/skills/book.js +76 -0
- package/src/motion3/skills/car.js +145 -0
- package/src/motion3/skills/flip.js +200 -0
- package/src/motion3/skills/frames-auto.js +29 -0
- package/src/motion3/skills/impact.js +109 -0
- package/src/motion3/skills/index.js +85 -0
- package/src/motion3/skills/info.js +80 -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/qa-label.js +25 -0
- 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 +16 -14
- package/src/studio-agent-commands.js +19 -16
- package/src/studio-agent-motion.js +9 -9
- package/src/studio-agent-protocol.js +47 -77
- package/src/studio-app-binding.js +27 -47
- 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 +15 -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 +109 -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 +9 -125
- 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,382 +0,0 @@
|
|
|
1
|
-
"""Image and physical terms for the deterministic cskel27 clip fit.
|
|
2
|
-
|
|
3
|
-
No image renderer is needed: exterior signed-DT samples prevent spill, and a
|
|
4
|
-
foreground-to-surface Chamfer prevents shrinkage. Nearest-neighbour selection
|
|
5
|
-
is discrete; its selected squared distance retains the exact local gradient.
|
|
6
|
-
"""
|
|
7
|
-
from __future__ import annotations
|
|
8
|
-
|
|
9
|
-
import numpy as np
|
|
10
|
-
import torch
|
|
11
|
-
from scipy.ndimage import distance_transform_edt
|
|
12
|
-
|
|
13
|
-
from rig import State, cskel27_fk, studio_skin
|
|
14
|
-
from scene import (FOOT_JOINTS, SceneBoxes, camera_center, foot_points, penetration_loss,
|
|
15
|
-
ray_occlusion, skate_loss, support_height)
|
|
16
|
-
|
|
17
|
-
# Face landmarks have no cskel27 counterpart and receive zero data weight.
|
|
18
|
-
COCO_JOINTS = [5, 5, 5, 5, 5, 14, 8, 15, 9, 16, 10, 23, 19, 24, 20, 25, 21]
|
|
19
|
-
# Bilateral Shoulder, Arm, ForeArm, Hand; exclude HandEnd/Thumb on both sides.
|
|
20
|
-
ARM_TRUST_JOINTS = [7, 8, 9, 10, 13, 14, 15, 16]
|
|
21
|
-
JOINT_CAPS_DEG = [180, 65, 65, 65, 90, 90, 180,
|
|
22
|
-
90, 175, 175, 110, 150, 180,
|
|
23
|
-
90, 175, 175, 110, 150, 180,
|
|
24
|
-
160, 175, 100, 80, 160, 175, 100, 80]
|
|
25
|
-
|
|
26
|
-
# --track-ablate levels. Each level adds one component to the previous one;
|
|
27
|
-
# keypoints and priors (acceleration, limits, endpoints, nuisance) are always
|
|
28
|
-
# on, and weights/schedule are identical at every level. 'occlusion' is the
|
|
29
|
-
# ray/box visibility of keypoints and surface samples in the fit.
|
|
30
|
-
ABLATIONS = {
|
|
31
|
-
'kp-only': frozenset(),
|
|
32
|
-
'silhouette': frozenset({'silhouette'}),
|
|
33
|
-
'viterbi': frozenset({'silhouette', 'viterbi'}),
|
|
34
|
-
'contacts': frozenset({'silhouette', 'viterbi', 'contacts'}),
|
|
35
|
-
'full': frozenset({'silhouette', 'viterbi', 'contacts', 'occlusion'}),
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
def huber(x, delta=1.0):
|
|
40
|
-
return torch.where(x <= delta, 0.5 * x.square(), delta * (x - 0.5 * delta))
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
def project(points, camera, nuisance):
|
|
44
|
-
"""OpenCV projection; nuisance = scale offset, yaw/pitch degrees, focal %."""
|
|
45
|
-
xyz = points @ camera[0].T + camera[1]
|
|
46
|
-
yaw, pitch = nuisance[1:3] * (np.pi / 180)
|
|
47
|
-
cy, sy, cp, sp = yaw.cos(), yaw.sin(), pitch.cos(), pitch.sin()
|
|
48
|
-
x, y, z = xyz.unbind(-1)
|
|
49
|
-
x, z = cy * x + sy * z, -sy * x + cy * z
|
|
50
|
-
y, z = cp * y - sp * z, sp * y + cp * z
|
|
51
|
-
xy = torch.stack((x, y), -1) / z.clamp_min(1e-3).unsqueeze(-1)
|
|
52
|
-
K = camera[2]
|
|
53
|
-
return xy * torch.stack((K[0, 0], K[1, 1])) * (1 + nuisance[3] / 100) + K[:2, 2], z
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
def camera_tensors(camera, device):
|
|
57
|
-
w = torch.tensor(camera['worldToCamera'], dtype=torch.float32, device=device)
|
|
58
|
-
return w[:3, :3], w[:3, 3], torch.tensor(camera['K'], dtype=torch.float32, device=device)
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
def slice_boxes(boxes, start, end):
|
|
62
|
-
return SceneBoxes(boxes.centers[:, start:end], boxes.half, boxes.yaw[:, start:end])
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
class MaskEvidence:
|
|
66
|
-
def __init__(self, prob, width, height, count=1000):
|
|
67
|
-
self.binary = np.asarray(prob) >= 0.5
|
|
68
|
-
self.ratio = np.array([prob.shape[2] / width, prob.shape[1] / height], np.float32)
|
|
69
|
-
rng = np.random.default_rng(0)
|
|
70
|
-
distances, targets, valid = [], [], []
|
|
71
|
-
for mask in self.binary:
|
|
72
|
-
distances.append(distance_transform_edt(~mask) - distance_transform_edt(mask))
|
|
73
|
-
y, x = np.nonzero(mask)
|
|
74
|
-
if len(x):
|
|
75
|
-
# Stratification avoids over-representing a dense image region.
|
|
76
|
-
idx = np.minimum(((np.arange(count) + rng.random(count)) * len(x) / count).astype(int), len(x) - 1)
|
|
77
|
-
targets.append(np.stack((x[idx] + 0.5, y[idx] + 0.5), -1))
|
|
78
|
-
valid.append(True)
|
|
79
|
-
else:
|
|
80
|
-
targets.append(np.zeros((count, 2)))
|
|
81
|
-
valid.append(False)
|
|
82
|
-
self.dt = np.asarray(distances, np.float32)
|
|
83
|
-
self.targets = np.asarray(targets, np.float32)
|
|
84
|
-
self.valid = np.asarray(valid)
|
|
85
|
-
|
|
86
|
-
def window(self, start, end, device):
|
|
87
|
-
return tuple(torch.as_tensor(x, device=device) for x in
|
|
88
|
-
(self.dt[start:end], self.targets[start:end], self.valid[start:end], self.ratio))
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
def bilinear_dt(dt, uv):
|
|
92
|
-
"""Pixel centres are at n+0.5. Include off-image distance (no border escape)."""
|
|
93
|
-
h, w = dt.shape[-2:]
|
|
94
|
-
q = uv - 0.5
|
|
95
|
-
x, y = q[..., 0].clamp(0, w - 1.001), q[..., 1].clamp(0, h - 1.001)
|
|
96
|
-
ix, iy = x.long(), y.long()
|
|
97
|
-
fx, fy = x - ix, y - iy
|
|
98
|
-
flat = dt.flatten(1)
|
|
99
|
-
at = lambda dx, dy: flat.gather(1, (iy + dy) * w + ix + dx)
|
|
100
|
-
d = (1 - fy) * ((1 - fx) * at(0, 0) + fx * at(1, 0)) + fy * ((1 - fx) * at(0, 1) + fx * at(1, 1))
|
|
101
|
-
return d + (q - torch.stack((x, y), -1)).norm(dim=-1)
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
def coverage_loss(uv, visible, target, frame_valid, delta):
|
|
105
|
-
# Query tiles bound scratch to 240*64*2000 floats (<118 MiB), with no
|
|
106
|
-
# T*foreground*surface autograd graph. All 1000 queries still participate.
|
|
107
|
-
indices = []
|
|
108
|
-
with torch.no_grad():
|
|
109
|
-
detached = uv.detach()
|
|
110
|
-
vv = detached.square().sum(-1)[:, None]
|
|
111
|
-
for chunk in target.split(64, dim=1):
|
|
112
|
-
distance = chunk.square().sum(-1, keepdim=True) + vv - 2 * (chunk @ detached.transpose(1, 2))
|
|
113
|
-
distance.masked_fill_(~visible[:, None], float('inf'))
|
|
114
|
-
indices.append(distance.argmin(-1))
|
|
115
|
-
idx = torch.cat(indices, 1)
|
|
116
|
-
nearest = uv.gather(1, idx[..., None].expand(-1, -1, 2))
|
|
117
|
-
active = (visible.any(-1) & frame_valid).float()
|
|
118
|
-
loss = huber((nearest - target).norm(dim=-1) / delta).mean(-1)
|
|
119
|
-
return (loss * active).sum() / active.sum().clamp_min(1)
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
def surface_samples(rig, count=2000):
|
|
123
|
-
"""Fixed area-stratified face samples, reused across frames and all runs."""
|
|
124
|
-
v = rig.dec_vertices.detach().cpu().numpy()
|
|
125
|
-
f = rig.dec_faces.cpu().numpy()
|
|
126
|
-
area = np.linalg.norm(np.cross(v[f[:, 1]] - v[f[:, 0]], v[f[:, 2]] - v[f[:, 0]]), axis=-1)
|
|
127
|
-
rng = np.random.default_rng(0)
|
|
128
|
-
cdf = np.cumsum(area) / area.sum()
|
|
129
|
-
selected = np.searchsorted(cdf, (np.arange(count) + rng.random(count)) / count)
|
|
130
|
-
a, b = np.sqrt(rng.random(count)), rng.random(count)
|
|
131
|
-
bary = np.stack((1 - a, a * (1 - b), a * b), -1)
|
|
132
|
-
return (torch.as_tensor(f[selected], device=rig.dec_vertices.device),
|
|
133
|
-
torch.tensor(bary, dtype=rig.dec_vertices.dtype, device=rig.dec_vertices.device))
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
def trust_region_loss(root, rotations, initial_root, initial_rotations):
|
|
137
|
-
"""Bounded G5 tether: retain trajectory shape, not its placement error.
|
|
138
|
-
|
|
139
|
-
A 25 cm centred path deviation or 30 degree rotation has unit squared
|
|
140
|
-
residual. Saturation lets persistent image evidence escape a bad G5 basin.
|
|
141
|
-
"""
|
|
142
|
-
shift = root - initial_root
|
|
143
|
-
path_squared = ((shift - shift.mean(0)) / 0.25).square().sum(-1)
|
|
144
|
-
angle_squared = (rotations - initial_rotations).square().sum((-1, -2)) / (8 * np.sin(np.pi / 12) ** 2)
|
|
145
|
-
weights = rotations.new_ones(27)
|
|
146
|
-
weights[0] = 2
|
|
147
|
-
weights[ARM_TRUST_JOINTS] = 4
|
|
148
|
-
return (2 * (path_squared / (1 + path_squared)).mean()
|
|
149
|
-
+ (weights * angle_squared / (1 + angle_squared)).mean())
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
@torch.no_grad()
|
|
153
|
-
def articulation_reliability(projected, assigned, seen, delta):
|
|
154
|
-
"""G5 shape disagreement, excluding common image translation and L/R swaps.
|
|
155
|
-
|
|
156
|
-
Residuals within detector noise are fully trusted. Beyond that band use
|
|
157
|
-
Geman-McClure influence weights; confidence/visibility can only reduce them.
|
|
158
|
-
These labels are frozen per block, not learned by fitting the bad keypoint.
|
|
159
|
-
"""
|
|
160
|
-
offset = projected - assigned[..., :2]
|
|
161
|
-
valid = seen & (assigned[..., 2] >= 0.5)
|
|
162
|
-
body = offset[:, 5:].masked_fill(~valid[:, 5:, None], float('inf'))
|
|
163
|
-
# Same lower median as nanmedian, without its nondeterministic CUDA
|
|
164
|
-
# indices kernel. No-evidence frames use zero common translation.
|
|
165
|
-
ordered = body.sort(dim=1, stable=True).values
|
|
166
|
-
count = valid[:, 5:].sum(-1)
|
|
167
|
-
middle = ((count - 1) // 2).clamp_min(0)
|
|
168
|
-
center = ordered.gather(1, middle[:, None, None].expand(-1, 1, 2)).squeeze(1)
|
|
169
|
-
center = torch.where(count[:, None] > 0, center, torch.zeros_like(center))
|
|
170
|
-
excess = ((offset - center[:, None]).norm(dim=-1) / delta - 1).relu() / 2
|
|
171
|
-
return assigned[..., 2] * seen / (1 + excess.square()).square()
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
def articulation_trust_loss(rotations, initial_rotations, uncertainty):
|
|
175
|
-
"""Local rotations only; 15-degree Huber scale, no root/placement tether."""
|
|
176
|
-
chord = (rotations[:, 1:] - initial_rotations[:, 1:]).norm(dim=(-1, -2))
|
|
177
|
-
return (huber(chord / np.sqrt(8 * np.sin(np.pi / 24) ** 2)) * uncertainty).mean()
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
def heading_rate_loss(root_rotations, fps):
|
|
181
|
-
"""World-Y twist increments, circularly unwrapped rather than Euler-smoothed.
|
|
182
|
-
|
|
183
|
-
Ordinary turns below 3 rad/s are free; excess rate is Huber-robust at
|
|
184
|
-
3 rad/s. Near a 180-degree tilt yaw is undefined, so omit only those pairs.
|
|
185
|
-
No absolute heading is prescribed, and L/R assignment remains independent.
|
|
186
|
-
"""
|
|
187
|
-
cs = torch.stack((root_rotations[:, 0, 0] + root_rotations[:, 2, 2],
|
|
188
|
-
root_rotations[:, 0, 2] - root_rotations[:, 2, 0]), -1)
|
|
189
|
-
defined = cs.square().sum(-1) > 1e-4
|
|
190
|
-
cs = torch.where(defined[:, None], cs, cs.new_tensor([1, 0]))
|
|
191
|
-
cosine = (cs[1:] * cs[:-1]).sum(-1)
|
|
192
|
-
sine = cs[1:, 1] * cs[:-1, 0] - cs[1:, 0] * cs[:-1, 1]
|
|
193
|
-
rate = torch.atan2(sine, cosine).abs() * fps
|
|
194
|
-
active = defined[1:] & defined[:-1]
|
|
195
|
-
return (huber((rate - 3).relu() / 3) * active).sum() / active.sum().clamp_min(1)
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
class ClipObjective:
|
|
199
|
-
def __init__(self, rig, bone_scale, camera, boxes, masks, kp, fps, delta_px, endpoints, initializer, components=ABLATIONS['full']):
|
|
200
|
-
self.rig, self.bone_scale = rig, bone_scale
|
|
201
|
-
self.components = components
|
|
202
|
-
self.camera = camera_tensors(camera, rig.neutral.device)
|
|
203
|
-
self.camera_pos = camera_center(camera)
|
|
204
|
-
self.boxes, self.masks, self.kp = boxes, masks, kp
|
|
205
|
-
self.fps, self.delta = fps, delta_px
|
|
206
|
-
self.endpoints = endpoints
|
|
207
|
-
self.initial_root = initializer.transl.detach().clone()
|
|
208
|
-
self.initial_rotations = initializer.local_rot_mats().detach().clone()
|
|
209
|
-
self.initial_local6d = initializer.local6d.detach().clone()
|
|
210
|
-
# An observed joint constrains the local chain leading to it. Leaves
|
|
211
|
-
# without their own keypoint inherit their parent's evidence, not root.
|
|
212
|
-
influence = np.zeros((27, 17), np.float32)
|
|
213
|
-
for coco, joint in enumerate(COCO_JOINTS[5:], start=5):
|
|
214
|
-
while joint > 0:
|
|
215
|
-
influence[joint, coco] = 1
|
|
216
|
-
joint = rig.parents[joint]
|
|
217
|
-
for joint in range(1, 27):
|
|
218
|
-
if not influence[joint].any():
|
|
219
|
-
influence[joint] = influence[rig.parents[joint]]
|
|
220
|
-
influence = influence[1:] / np.maximum(1, influence[1:].sum(-1, keepdims=True))
|
|
221
|
-
self.articulation_influence = torch.as_tensor(influence, device=rig.neutral.device)
|
|
222
|
-
self.faces, self.bary = surface_samples(rig)
|
|
223
|
-
self.foot_vertices = [torch.nonzero(
|
|
224
|
-
rig.dec_weights[:, [rig.prep_bone[j] for j in foot]].sum(-1) > 0.5).flatten()
|
|
225
|
-
for foot in FOOT_JOINTS]
|
|
226
|
-
# Generous rest-relative caps preserve stylised motion. Root is free.
|
|
227
|
-
self.caps = torch.tensor(JOINT_CAPS_DEG, device=rig.neutral.device) * (np.pi / 180)
|
|
228
|
-
|
|
229
|
-
def geometry(self, state, nuisance):
|
|
230
|
-
joints, globals_ = cskel27_fk(state, self.bone_scale, self.rig)
|
|
231
|
-
_, verts = studio_skin(globals_, joints, self.rig, bone_scale=self.bone_scale)
|
|
232
|
-
root = state.transl[:, None]
|
|
233
|
-
joints = root + (joints - root) * (1 + nuisance[0])
|
|
234
|
-
verts = root + (verts - root) * (1 + nuisance[0])
|
|
235
|
-
return joints, verts
|
|
236
|
-
|
|
237
|
-
@torch.no_grad()
|
|
238
|
-
def articulation_observation(self, state, nuisance, assigned):
|
|
239
|
-
# Keep G5 articulation but let the fitted root and global orientation
|
|
240
|
-
# explain camera placement. Never tether the global pose to this prior.
|
|
241
|
-
reference = State(state.transl, state.root6d, self.initial_local6d)
|
|
242
|
-
joints, _ = cskel27_fk(reference, self.bone_scale, self.rig)
|
|
243
|
-
joints = state.transl[:, None] + (joints - state.transl[:, None]) * (1 + nuisance[0])
|
|
244
|
-
projected, depth = project(joints[:, COCO_JOINTS], self.camera, nuisance)
|
|
245
|
-
seen = depth > 0
|
|
246
|
-
if 'occlusion' in self.components:
|
|
247
|
-
seen &= ~ray_occlusion(joints[:, COCO_JOINTS], self.camera_pos, self.boxes)
|
|
248
|
-
reliable = articulation_reliability(projected, assigned, seen, self.delta)
|
|
249
|
-
uncertainty = (1 - reliable).square() @ self.articulation_influence.T
|
|
250
|
-
# Retain a weak escape route from a wrong G5 pose; do not renormalize
|
|
251
|
-
# these attenuated data weights back to a full observation's strength.
|
|
252
|
-
return 0.1 + 0.9 * reliable, uncertainty
|
|
253
|
-
|
|
254
|
-
def sole_points(self, vertices):
|
|
255
|
-
"""Lowest four skinned foot vertices, not an ankle-as-sole offset."""
|
|
256
|
-
soles = []
|
|
257
|
-
for indices in self.foot_vertices:
|
|
258
|
-
foot = vertices[:, indices]
|
|
259
|
-
lowest = foot[..., 1].topk(4, dim=1, largest=False).indices
|
|
260
|
-
soles.append(foot.gather(1, lowest[..., None].expand(-1, -1, 3)))
|
|
261
|
-
return torch.stack(soles, 1)
|
|
262
|
-
|
|
263
|
-
@torch.no_grad()
|
|
264
|
-
def support_observation(self, state, nuisance, assigned, stance, hidden):
|
|
265
|
-
"""Freeze reliable stance/support labels between blocks; no ankle ray pin.
|
|
266
|
-
|
|
267
|
-
The HMM is relative to a clip percentile and alone can label hovering
|
|
268
|
-
or a jump apex as stance. Require absolute proximity, two quiet motion
|
|
269
|
-
intervals and a consistent confident ankle observation as well.
|
|
270
|
-
"""
|
|
271
|
-
joints, vertices = self.geometry(state, nuisance)
|
|
272
|
-
sole = self.sole_points(vertices)
|
|
273
|
-
height = support_height(sole.flatten(1, 2), self.boxes).reshape(sole.shape[:-1])
|
|
274
|
-
support = height.mean(-1)
|
|
275
|
-
clearance = sole[..., 1].mean(-1) - support
|
|
276
|
-
uv, depth = project(joints[:, [25, 21]], self.camera, nuisance)
|
|
277
|
-
ankle = assigned[:, [15, 16]]
|
|
278
|
-
active = (stance & (depth > 0) & (ankle[..., 2] >= 0.5)
|
|
279
|
-
& ((uv - ankle[..., :2]).norm(dim=-1) <= 2 * self.delta)
|
|
280
|
-
& (clearance >= -0.03) & (clearance <= 0.10)
|
|
281
|
-
& (height.amax(-1) - height.amin(-1) <= 0.02))
|
|
282
|
-
if 'occlusion' in self.components:
|
|
283
|
-
active &= ~hidden[:, [25, 21]]
|
|
284
|
-
# Stable ankle OR toe across both adjacent intervals. A moving foot
|
|
285
|
-
# is not evidence of ground contact, even if the HMM calls it stance.
|
|
286
|
-
velocity = (foot_points(joints)[1:] - foot_points(joints)[:-1]) * self.fps
|
|
287
|
-
quiet = ((velocity[..., [0, 2]].norm(dim=-1) <= 0.10)
|
|
288
|
-
& (velocity[..., 1].abs() <= 0.15)).any(-1)
|
|
289
|
-
stable = torch.zeros_like(active)
|
|
290
|
-
stable[1:-1] = (active[:-2] & active[1:-1] & active[2:]
|
|
291
|
-
& quiet[:-1] & quiet[1:])
|
|
292
|
-
return support, stable
|
|
293
|
-
|
|
294
|
-
def __call__(self, state, nuisance, start, end, assigned, stance, penetration_weight,
|
|
295
|
-
trust_weight, support=None, articulation=None):
|
|
296
|
-
joints, vertices = self.geometry(state, nuisance)
|
|
297
|
-
boxes = slice_boxes(self.boxes, start, end)
|
|
298
|
-
occlusion = 'occlusion' in self.components
|
|
299
|
-
projected, depth = project(joints[:, COCO_JOINTS], self.camera, nuisance)
|
|
300
|
-
seen = depth > 0
|
|
301
|
-
if occlusion:
|
|
302
|
-
seen = ~ray_occlusion(joints[:, COCO_JOINTS], self.camera_pos, boxes) & seen
|
|
303
|
-
weights = assigned[..., 2] * seen.float()
|
|
304
|
-
residual = (projected - assigned[..., :2]).norm(dim=-1) / self.delta
|
|
305
|
-
kp_terms = huber(residual) * weights
|
|
306
|
-
if articulation is not None:
|
|
307
|
-
kp_terms = kp_terms * articulation[0]
|
|
308
|
-
kp_loss = kp_terms.sum() / weights.sum().clamp_min(1)
|
|
309
|
-
zero = kp_loss * 0
|
|
310
|
-
silhouette = zero
|
|
311
|
-
if 'silhouette' in self.components:
|
|
312
|
-
samples = (vertices[:, self.faces] * self.bary[None, :, :, None]).sum(-2)
|
|
313
|
-
uv, sz = project(samples, self.camera, nuisance)
|
|
314
|
-
visible = sz > 0
|
|
315
|
-
if occlusion:
|
|
316
|
-
visible = ~ray_occlusion(samples, self.camera_pos, boxes) & visible
|
|
317
|
-
dt, target, valid, ratio = self.masks
|
|
318
|
-
uv = uv * ratio
|
|
319
|
-
d = bilinear_dt(dt, uv).relu() / (self.delta * ratio.mean())
|
|
320
|
-
active = visible & valid[:, None]
|
|
321
|
-
boundary = (huber(d) * active).sum() / active.sum().clamp_min(1)
|
|
322
|
-
coverage = coverage_loss(uv, visible, target, valid, self.delta * ratio.mean())
|
|
323
|
-
silhouette = (boundary + coverage) / 2
|
|
324
|
-
# Second differences at the clip's sampling rate, robust above 3 m/s^2;
|
|
325
|
-
# no velocity damping of freely moving limbs.
|
|
326
|
-
if len(joints) > 2:
|
|
327
|
-
acc = (joints[2:] - 2 * joints[1:-1] + joints[:-2]) * self.fps ** 2
|
|
328
|
-
acceleration = huber(acc.norm(dim=-1) / 3).mean()
|
|
329
|
-
else:
|
|
330
|
-
acceleration = zero
|
|
331
|
-
rotations = state.local_rot_mats()
|
|
332
|
-
heading = heading_rate_loss(rotations[:, 0], self.fps)
|
|
333
|
-
articulation_trust = zero if articulation is None else articulation_trust_loss(
|
|
334
|
-
rotations, self.initial_rotations[start:end], articulation[1])
|
|
335
|
-
trust = trust_region_loss(state.transl, rotations, self.initial_root[start:end],
|
|
336
|
-
self.initial_rotations[start:end]) if trust_weight else zero
|
|
337
|
-
cos = ((rotations.diagonal(dim1=-2, dim2=-1).sum(-1) - 1) / 2).clamp(-1 + 1e-6, 1 - 1e-6)
|
|
338
|
-
limits = (cos.acos() - self.caps).relu().square().mean()
|
|
339
|
-
skate = penetration = zero
|
|
340
|
-
if 'contacts' in self.components:
|
|
341
|
-
feet = foot_points(joints)
|
|
342
|
-
skate = skate_loss(feet, stance, self.fps) / max(1, (end - start - 1) * 4)
|
|
343
|
-
pen = penetration_loss(vertices, boxes)
|
|
344
|
-
# Metres -> a 1 cm residual; normalise by points rather than active
|
|
345
|
-
# collisions, so there is no discontinuity when a vertex exits a solid.
|
|
346
|
-
penetration = (pen['box'] + pen['floor']) / (vertices.shape[0] * vertices.shape[1] * 0.01 ** 2)
|
|
347
|
-
support_loss = zero
|
|
348
|
-
if support is not None:
|
|
349
|
-
target_height, reliable = support
|
|
350
|
-
sole_height = self.sole_points(vertices)[..., 1].mean(-1)
|
|
351
|
-
support_loss = (huber((sole_height - target_height).abs() / 0.03)
|
|
352
|
-
* reliable).sum() / reliable.sum().clamp_min(1)
|
|
353
|
-
endpoint = zero
|
|
354
|
-
for frame, pose in self.endpoints.items():
|
|
355
|
-
if start <= frame < end:
|
|
356
|
-
i = frame - start
|
|
357
|
-
endpoint = endpoint + ((state.transl[i] - pose[0]) / 0.05).square().mean() + (rotations[i] - pose[1]).square().mean()
|
|
358
|
-
nuisance_prior = ((nuisance / nuisance.new_tensor([0.01, 0.3, 0.3, 0.3])) ** 2).sum()
|
|
359
|
-
terms = dict(keypoints=kp_loss, silhouette=silhouette, acceleration=acceleration,
|
|
360
|
-
trust=trust, headingRate=heading,
|
|
361
|
-
limits=limits, skate=skate, penetration=penetration,
|
|
362
|
-
endpoints=endpoint, nuisance=nuisance_prior)
|
|
363
|
-
if articulation is not None:
|
|
364
|
-
terms['articulationTrust'] = articulation_trust
|
|
365
|
-
terms['articulationUncertainty'] = articulation[1].mean()
|
|
366
|
-
terms['keypointReliabilityWeight'] = articulation[0][:, 5:].mean()
|
|
367
|
-
if support is not None:
|
|
368
|
-
terms['supportHeight'] = support_loss
|
|
369
|
-
terms['supportFootFrames'] = support[1].sum()
|
|
370
|
-
# Disabled terms are not evaluated, so they are not reported as zeros.
|
|
371
|
-
if 'silhouette' not in self.components:
|
|
372
|
-
del terms['silhouette']
|
|
373
|
-
if 'contacts' not in self.components:
|
|
374
|
-
del terms['skate'], terms['penetration']
|
|
375
|
-
# Keep the silhouette depth support; bounded G5 trust discourages
|
|
376
|
-
# unsupported articulation/path excursions without pinning placement.
|
|
377
|
-
total = (kp_loss + 6.0 * silhouette + 0.05 * acceleration
|
|
378
|
-
+ trust_weight * trust + articulation_trust + 0.2 * heading
|
|
379
|
-
+ 0.3 * support_loss
|
|
380
|
-
+ 0.1 * limits + skate + penetration_weight * penetration
|
|
381
|
-
+ 0.2 * endpoint + nuisance_prior)
|
|
382
|
-
return total, terms
|