CLoSDSmoke.kt
src/jvmMain/kotlin/afield/animation/mocap/CLoSDSmoke.kt · 62 lines
package afield.animation.mocap
import org.json.JSONObject
import java.nio.file.Files
import java.nio.file.Path
import java.util.concurrent.TimeUnit
FIELD_TEST id: motion.closd.gpu runner: jvm-main entrypoint: afield.animation.mocap.CLoSDSmoke tags: [smoke, optional, animation, motion, gpu, closd] timeoutSec: 240 expect: exitCode: 0 stdoutContains: - "CLoSD motion smoke"
object CLoSDSmoke
Real Kotlin process/skeleton/reference/executed/intervention check, explicitly skipped without its opt-in home.
@JvmStatic fun main(args: Array<String>)
@JvmStatic fun main(args: Array<String>) {
val home = System.getenv("FIELD_MOTION_HOME")
if (home.isNullOrBlank()) {
println("CLoSD motion smoke SKIPPED: set FIELD_MOTION_HOME to the validated development environment")
return
}
val scratch = if (args.isEmpty()) Files.createTempDirectory("field-closd-smoke") else Path.of(args[0])
Files.createDirectories(scratch)
try {
val session = CLoSD.openAsync(MotionProcessConfig(home = Path.of(home))).get(180, TimeUnit.SECONDS)
val recorder = session.record(scratch.resolve("kotlin.f4motion"), JSONObject().put("backend", "closd").put("seed", 0))
session.use {
check(session.skeleton.size == 24)
check(session.capabilities.backend == "closd")
check(session.setPrompt("A person walks forward.", 0.0).get(5, TimeUnit.SECONDS)?.appliedTime == null)
val first = session.advance(.5).get(120, TimeUnit.SECONDS)
check(first.frames.size == 15 && first.frames.all { it.intended != null && !it.intended.hasRotations })
val frame = first.frames.last()
check(frame.diagnostics.getValue("prefixResidualM") == 0.0)
val index = session.skeleton.joint("L_Ankle")
val anchor = frame.executed.worldPositions.subList(index * 3, index * 3 + 3)
session.attach(MotionAttachment("smoke", "L_Ankle", listOf(0.0, 0.0, 0.0), anchor), frame.time).get(5, TimeUnit.SECONDS)
val tethered = session.advance(.3).get(120, TimeUnit.SECONDS)
check(tethered.events.any { it.optString("type") == "tetherPhysics" })
check(tethered.events.filter { it.optString("type") == "tetherPhysics" }.all { it.getDouble("forceN") <= 50.00001 })
session.detach("smoke", tethered.frames.last().time).get(5, TimeUnit.SECONDS)
session.applyImpulse("Torso", listOf(0.0, 0.0, 0.0), listOf(1.0, 0.0, 0.0), tethered.frames.last().time).get(5, TimeUnit.SECONDS)
val released = session.advance(.2).get(120, TimeUnit.SECONDS)
check(released.events.count { it.optString("type") == "impulsePhysics" } == 1)
check(session.buffer.size() <= session.buffer.capacity)
check(session.failure == null)
}
recorder.close()
val replay = MotionRecording(scratch.resolve("kotlin.f4motion"))
check(replay.frames().count() == 30)
check(replay.events().any { it.optString("type") == "impulsePhysics" })
println("CLoSD motion smoke passed: real GPU, 24 joints, 30 frames, positions-only reference, tether/release/one-shot impulse, exact replay")
} finally { if (args.isEmpty()) scratch.toFile().deleteRecursively() }
}
}