feat(perception): integrate calibrated operator pipeline

Add calibrated K1 projection, recorded and near-live perception qualification, unified Rerun operator layers, bounded replay admission, audited viewer controls, worker experiments, and lab evidence.
This commit is contained in:
DCCONSTRUCTIONS
2026-07-23 00:23:28 +03:00
parent ada2a55ee6
commit b53d6d5a45
221 changed files with 55923 additions and 1357 deletions
@@ -0,0 +1,153 @@
[CmdletBinding()]
param(
[ValidateRange(1, 1000)] [int]$FreeGiBFloor = 360,
[string]$RuntimeRoot = "D:\NDC_MISSIONCORE\runtime",
[string]$ContainerImage = "nvcr.io/nvidia/tritonserver:26.06-py3@sha256:58df7489c3f2276f9591d500a012dee03e23d35543ce3c390b4c001e6bf90794",
[string]$RuntimeName = "perception-e15-media-pyav180-lz445-v1"
)
$ErrorActionPreference = "Stop"
$ProgressPreference = "SilentlyContinue"
function Assert-LastExitCode([string]$Operation) {
if ($LASTEXITCODE -ne 0) { throw "$Operation failed with exit code $LASTEXITCODE" }
}
function Resolve-DDirectory([string]$Path, [string]$Label) {
$item = Get-Item -LiteralPath (Resolve-Path -LiteralPath $Path).Path -Force
$root = [IO.Path]::GetPathRoot($item.FullName).TrimEnd("\")
if (-not $item.PSIsContainer -or ($item.Attributes -band [IO.FileAttributes]::ReparsePoint) -or $root -ine "D:") {
throw "$Label must be a real D: directory"
}
return $item.FullName
}
function Convert-ToDockerPath([string]$Path) { return $Path.Replace("\", "/") }
function Assert-FreeSpace([string]$Phase) {
$free = [int64](Get-PSDrive -Name D).Free
$floor = [int64]$FreeGiBFloor * 1GB
Write-Host (
"DISK_GUARD PHASE={0} DRIVE=D FREE_BYTES={1} FREE_GIB={2} FLOOR_GIB={3}" -f
$Phase, $free, [math]::Round($free / 1GB, 3), $FreeGiBFloor
)
if ($free -lt ($floor + 2GB)) {
throw "D: lacks the guarded LAB E15 media-runtime reserve during $Phase"
}
return $free
}
function Get-PayloadDigest([string]$Root) {
$resolved = Resolve-DDirectory $Root "E15 media runtime"
$lines = @(
Get-ChildItem -LiteralPath $resolved -Recurse -File -Force |
Where-Object { $_.Name -ne "manifest.json" } |
Sort-Object FullName |
ForEach-Object {
$relative = $_.FullName.Substring($resolved.Length).TrimStart("\").Replace("\", "/")
$hash = (Get-FileHash -LiteralPath $_.FullName -Algorithm SHA256).Hash.ToLowerInvariant()
"{0}`t{1}`t{2}" -f $relative, $_.Length, $hash
}
)
if ($lines.Count -lt 4) { throw "E15 media runtime payload is incomplete" }
$bytes = [Text.Encoding]::UTF8.GetBytes(($lines -join "`n") + "`n")
$hasher = [Security.Cryptography.SHA256]::Create()
try {
return ([BitConverter]::ToString($hasher.ComputeHash($bytes))).Replace("-", "").ToLowerInvariant()
}
finally { $hasher.Dispose() }
}
function Assert-Runtime([string]$Path) {
$root = Resolve-DDirectory $Path "E15 media runtime"
$manifestPath = Join-Path $root "manifest.json"
if (-not (Test-Path -LiteralPath $manifestPath -PathType Leaf)) {
throw "E15 media runtime manifest is missing"
}
$manifest = Get-Content -LiteralPath $manifestPath -Raw | ConvertFrom-Json
if (
$manifest.schema_version -ne "missioncore.e15-media-runtime/v1" -or
$manifest.runtime_name -ne $RuntimeName -or
$manifest.container_image -ne $ContainerImage -or
$manifest.packages.av -ne "18.0.0" -or
$manifest.packages.lz4 -ne "4.4.5" -or
$manifest.payload_sha256 -ne (Get-PayloadDigest $root)
) { throw "E15 media runtime identity changed" }
$dockerRoot = Convert-ToDockerPath $root
$verifyCode = "import av,lz4.version;print(av.__version__);print(lz4.version.version)"
$verifyOutput = @(& docker run --rm --network none --read-only `
--security-opt "no-new-privileges:true" --cap-drop ALL --pids-limit 64 `
--tmpfs "/tmp:rw,noexec,nosuid,size=64m" `
-e "PYTHONPATH=/opt/media" -e "PYTHONDONTWRITEBYTECODE=1" `
-v ("{0}:/opt/media:ro" -f $dockerRoot) `
--entrypoint python3 $ContainerImage -c $verifyCode)
Assert-LastExitCode "E15 media runtime verification"
if ($verifyOutput.Count -ne 2 -or $verifyOutput[0] -ne "18.0.0" -or $verifyOutput[1] -ne "4.4.5") {
throw "E15 media runtime package versions changed"
}
Write-Host "MEDIA_RUNTIME_OK pyav=18.0.0 lz4=4.4.5"
return $root
}
$runtime = Resolve-DDirectory $RuntimeRoot "Runtime root"
$derived = Resolve-DDirectory (Join-Path $runtime "derived") "Runtime derived root"
$destination = Join-Path $derived $RuntimeName
$freeBefore = Assert-FreeSpace "media-runtime-preflight"
& docker image inspect $ContainerImage *> $null
Assert-LastExitCode "Pinned container image inspection"
if (Test-Path -LiteralPath $destination) {
$resolved = Assert-Runtime $destination
Write-Output "STATE=existing-verified"
Write-Output ("MEDIA_RUNTIME_ROOT={0}" -f $resolved)
Write-Output ("DISK_FREE_BYTES_BEFORE={0}" -f $freeBefore)
Write-Output ("DISK_FREE_BYTES_AFTER={0}" -f ([int64](Get-PSDrive -Name D).Free))
return
}
$token = [Guid]::NewGuid().ToString("N")
$staging = Join-Path $derived (".{0}-{1}.tmp" -f $RuntimeName, $token)
$null = New-Item -ItemType Directory -Path $staging
$completed = $false
try {
$dockerStaging = Convert-ToDockerPath $staging
Write-Output "PHASE=media-runtime-install-start"
& docker run --rm --network bridge --read-only `
--security-opt "no-new-privileges:true" --cap-drop ALL --pids-limit 128 `
--tmpfs "/tmp:rw,nosuid,size=1g" `
-e "PIP_DISABLE_PIP_VERSION_CHECK=1" -e "PYTHONDONTWRITEBYTECODE=1" `
-v ("{0}:/target:rw" -f $dockerStaging) `
--entrypoint python3 $ContainerImage -m pip install `
--no-cache-dir --only-binary ":all:" --target /target `
"av==18.0.0" "lz4==4.4.5"
Assert-LastExitCode "E15 media runtime installation"
$payloadSha256 = Get-PayloadDigest $staging
$manifest = [ordered]@{
schema_version = "missioncore.e15-media-runtime/v1"
runtime_name = $RuntimeName
created_at_utc = [DateTime]::UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fffZ")
container_image = $ContainerImage
packages = [ordered]@{ av = "18.0.0"; lz4 = "4.4.5" }
payload_sha256 = $payloadSha256
storage_scope = "D-only-immutable-runtime"
}
$manifest | ConvertTo-Json -Depth 8 | Set-Content -LiteralPath (Join-Path $staging "manifest.json") -Encoding utf8
$null = Assert-Runtime $staging
Move-Item -LiteralPath $staging -Destination $destination
$completed = $true
$resolved = Assert-Runtime $destination
$freeAfter = Assert-FreeSpace "media-runtime-published"
Write-Output "STATE=created-verified"
Write-Output ("MEDIA_RUNTIME_ROOT={0}" -f $resolved)
Write-Output ("PAYLOAD_SHA256={0}" -f $payloadSha256)
Write-Output ("DISK_FREE_BYTES_BEFORE={0}" -f $freeBefore)
Write-Output ("DISK_FREE_BYTES_AFTER={0}" -f $freeAfter)
}
finally {
if (-not $completed -and (Test-Path -LiteralPath $staging)) {
Remove-Item -LiteralPath $staging -Recurse -Force
}
}
@@ -0,0 +1,313 @@
[CmdletBinding()]
param(
[Parameter(Mandatory = $true)] [string]$JobRoot,
[Parameter(Mandatory = $true)] [string]$RunnerPath,
[Parameter(Mandatory = $true)] [string]$ProfilePath,
[Parameter(Mandatory = $true)] [string]$DetectorProfilePath,
[Parameter(Mandatory = $true)] [string]$SemanticProfilePath,
[Parameter(Mandatory = $true)] [string]$ValidFovRoot,
[Parameter(Mandatory = $true)] [string]$LidarPackRoot,
[ValidateRange(0, 1000000)] [int]$StartFrame = 1000,
[ValidateRange(0, 1000000)] [int]$EndFrame = 1600,
[ValidateRange(1, 1000)] [int]$FreeGiBFloor = 360,
[string]$RuntimeRoot = "D:\NDC_MISSIONCORE\runtime",
[string]$ModelRoot = "D:\NDC_MISSIONCORE\runtime\models\yolox_s",
[string]$TritonContainer = "mission-core-triton",
[string]$ContainerImage = "nvcr.io/nvidia/tritonserver:26.06-py3"
)
$ErrorActionPreference = "Stop"
$ProgressPreference = "SilentlyContinue"
function Assert-LastExitCode([string]$Operation) {
if ($LASTEXITCODE -ne 0) { throw "$Operation failed with exit code $LASTEXITCODE" }
}
function Resolve-DDirectory([string]$Path, [string]$Label) {
$item = Get-Item -LiteralPath (Resolve-Path -LiteralPath $Path).Path -Force
$root = [IO.Path]::GetPathRoot($item.FullName).TrimEnd("\")
if (-not $item.PSIsContainer -or ($item.Attributes -band [IO.FileAttributes]::ReparsePoint) -or $root -ine "D:") {
throw "$Label must be a real D: directory"
}
return $item.FullName
}
function Resolve-DFile([string]$Path, [string]$Label) {
$item = Get-Item -LiteralPath (Resolve-Path -LiteralPath $Path).Path -Force
$root = [IO.Path]::GetPathRoot($item.FullName).TrimEnd("\")
if ($item.PSIsContainer -or ($item.Attributes -band [IO.FileAttributes]::ReparsePoint) -or $root -ine "D:") {
throw "$Label must be a regular D: file"
}
return $item.FullName
}
function Convert-ToDockerPath([string]$Path) { return $Path.Replace("\", "/") }
function Get-DFreeBytes { return [int64](Get-PSDrive -Name D).Free }
function Assert-FreeSpace([string]$Phase, [int64]$RequiredAdditionalBytes = 0) {
$free = Get-DFreeBytes
$floor = [int64]$FreeGiBFloor * 1GB
Write-Host (
"DISK_GUARD PHASE={0} DRIVE=D FREE_BYTES={1} FREE_GIB={2} FLOOR_GIB={3} REQUIRED_ADDITIONAL_GIB={4}" -f
$Phase, $free, [math]::Round($free / 1GB, 3), $FreeGiBFloor,
[math]::Round($RequiredAdditionalBytes / 1GB, 3)
)
if ($free -lt ($floor + $RequiredAdditionalBytes)) {
throw "D: lacks the guarded LAB E10 reserve during $Phase"
}
return $free
}
function Test-TritonModelReady {
try {
$response = Invoke-WebRequest -UseBasicParsing -TimeoutSec 10 `
-Uri "http://127.0.0.1:8000/v2/models/yolox_s/ready"
return $response.StatusCode -eq 200
}
catch { return $false }
}
$jobDirectory = Resolve-DDirectory $JobRoot "Job root"
$runner = Resolve-DFile $RunnerPath "LAB E10 runner"
$profile = Resolve-DFile $ProfilePath "LAB E10 profile"
$detectorProfile = Resolve-DFile $DetectorProfilePath "Detector profile"
$semanticProfile = Resolve-DFile $SemanticProfilePath "Semantic profile"
$validFov = Resolve-DDirectory $ValidFovRoot "Valid-FOV root"
$lidarPack = Resolve-DDirectory $LidarPackRoot "LiDAR replay pack"
$runtime = Resolve-DDirectory $RuntimeRoot "Runtime root"
$model = Resolve-DDirectory $ModelRoot "YOLOX model root"
$runnerRoot = Split-Path $runner -Parent
foreach ($path in @($profile, $detectorProfile, $semanticProfile)) {
if ((Split-Path $path -Parent) -ne $runnerRoot) { throw "Runner and profiles must share one mount" }
}
foreach ($dependency in @(
"e10_fusion_runtime.py",
"run_e9_multirate_perception.py",
"run_e8_realtime_tracking.py",
"run_e5_instance_tracking.py",
"run_e4_full_session_segmentation.py",
"run_recorded_perception_epoch.py",
"run_e3_rectified_segmentation.py",
"run_evaluation_prelabels.py"
)) {
$null = Resolve-DFile (Join-Path $runnerRoot $dependency) "LAB E10 dependency"
}
$job = Get-Content -LiteralPath (Join-Path $jobDirectory "job.json") -Raw | ConvertFrom-Json
if ($job.schema_version -ne "missioncore.compute-job/v1" -or $job.job_id -ne (Split-Path $jobDirectory -Leaf)) {
throw "Compute job manifest is incompatible"
}
$sourceId = [string]$job.input.source_id
$epoch = [int]$job.input.codec_epoch
$fullFrameCount = [int]$job.input.segment_count
$clipFrameCount = $EndFrame - $StartFrame + 1
$timelineStart = [double]$job.input.timeline.start_seconds
if ($sourceId -ne "sensor.camera.right" -or $StartFrame -lt 0 -or $EndFrame -lt $StartFrame -or $EndFrame -ge $fullFrameCount -or $clipFrameCount -lt 2) {
throw "LAB E10 clip escapes the camera job"
}
$lidarManifest = Get-Content -LiteralPath (Join-Path $lidarPack "manifest.json") -Raw | ConvertFrom-Json
if (
$lidarManifest.schema_version -ne "missioncore.e10-lidar-replay-pack/v1" -or
$lidarManifest.identity.job_id -ne $job.job_id -or
[int]$lidarManifest.identity.source_start_frame_index -ne $StartFrame -or
[int]$lidarManifest.identity.source_end_frame_index -ne $EndFrame -or
[int]$lidarManifest.identity.frame_count -ne $clipFrameCount
) { throw "LAB E10 LiDAR pack differs from the selected camera clip" }
Write-Output ("PHASE=inputs-validated JOB={0} CLIP={1}-{2} FRAMES={3} LIDAR_PACK={4}" -f $job.job_id, $StartFrame, $EndFrame, $clipFrameCount, $lidarManifest.pack_id)
$epochRoot = Resolve-DDirectory (Join-Path $jobDirectory ("input\camera\{0}\epoch-{1}" -f $sourceId, $epoch)) "Camera epoch"
$initPath = Resolve-DFile (Join-Path $epochRoot "init.mp4") "Camera init"
$segmentsRoot = Resolve-DDirectory (Join-Path $epochRoot "segments") "Camera segments"
$derivedRoot = Join-Path $runtime "derived"
$tmpRoot = Join-Path $runtime "tmp"
$cacheRoot = Resolve-DDirectory (Join-Path $runtime "cache\perception-e3-models-v1") "EoMT cache"
$e3Environment = Resolve-DDirectory (Join-Path $derivedRoot "perception-e3-opencv413092-v1") "E3 environment"
$torchEnvironment = Resolve-DDirectory (Join-Path $derivedRoot "perception-p0-env-v1") "Torch environment"
$transformersEnvironment = Resolve-DDirectory (Join-Path $derivedRoot "perception-p0-transformers4576-v1") "Transformers environment"
$pixelWorkingSet = [int64]$clipFrameCount * 800 * 600 * 3
$partialStreamReserve = [int64][math]::Ceiling(([int64]$job.input.byte_length * ($EndFrame + 1) / $fullFrameCount) * 1.2)
$workingSetReserve = [int64][math]::Ceiling($pixelWorkingSet * 1.4) + $partialStreamReserve + 3GB
$freeBytesBefore = Assert-FreeSpace "preflight" $workingSetReserve
& docker image inspect $ContainerImage *> $null
Assert-LastExitCode "Existing container image inspection"
$tritonState = docker inspect --format "{{.State.Running}}" $TritonContainer
Assert-LastExitCode "Triton container inspection"
if ($tritonState.Trim().ToLowerInvariant() -ne "true") { throw "LAB E10 requires the existing Triton container" }
$runnerName = Split-Path $runner -Leaf
$profileName = Split-Path $profile -Leaf
$detectorProfileName = Split-Path $detectorProfile -Leaf
$semanticProfileName = Split-Path $semanticProfile -Leaf
$lidarMount = "/" + (Split-Path $lidarPack -Leaf)
$orchestratorSha256 = (Get-FileHash -LiteralPath $PSCommandPath -Algorithm SHA256).Hash.ToLowerInvariant()
$commonMounts = @(
"-e", "PYTHONPATH=/runner:/opt/transformers:/opt/env",
"-e", "TORCH_HOME=/cache/torch",
"-e", "HF_HOME=/cache/huggingface",
"-e", "HF_HUB_OFFLINE=1",
"-e", "TRANSFORMERS_OFFLINE=1",
"-v", ((Convert-ToDockerPath $jobDirectory) + ":/job:ro"),
"-v", ((Convert-ToDockerPath $validFov) + ":/valid-fov:ro"),
"-v", ((Convert-ToDockerPath $lidarPack) + (":{0}:ro" -f $lidarMount)),
"-v", ((Convert-ToDockerPath $model) + ":/model:ro"),
"-v", ((Convert-ToDockerPath $cacheRoot) + ":/cache:ro"),
"-v", ((Convert-ToDockerPath $e3Environment) + ":/environment:ro"),
"-v", ((Convert-ToDockerPath $torchEnvironment) + ":/opt/env:ro"),
"-v", ((Convert-ToDockerPath $transformersEnvironment) + ":/opt/transformers:ro"),
"-v", ((Convert-ToDockerPath $runnerRoot) + ":/runner:ro")
)
$commonRunnerArgs = @(
"--job", "/job",
"--profile", ("/runner/{0}" -f $profileName),
"--detector-profile", ("/runner/{0}" -f $detectorProfileName),
"--semantic-profile", ("/runner/{0}" -f $semanticProfileName),
"--valid-fov-root", "/valid-fov",
"--model-root", "/model",
"--cache", "/cache",
"--environment", "/environment",
"--lidar-pack", $lidarMount
)
$preflightArgs = @(
"run", "--rm", "--gpus", "all", "--network", "none", "--read-only",
"--security-opt", "no-new-privileges:true", "--cap-drop", "ALL",
"--pids-limit", "512", "--shm-size", "4g",
"--tmpfs", "/tmp:rw,noexec,nosuid,size=2g"
) + $commonMounts + @(
"--entrypoint", "python3", $ContainerImage,
("/runner/{0}" -f $runnerName), "preflight"
) + $commonRunnerArgs
Write-Output "PHASE=e10-preflight-start"
& docker @preflightArgs
Assert-LastExitCode "LAB E10 preflight"
Write-Output "PHASE=e10-preflight-complete"
$modelWasReady = Test-TritonModelReady
$loadedByRun = $false
if (-not $modelWasReady) {
Invoke-WebRequest -UseBasicParsing -TimeoutSec 60 -Uri "http://127.0.0.1:8000/v2/repository/models/yolox_s/load" -Method Post -ContentType "application/json" -Body "{}" *> $null
$loadedByRun = $true
$deadline = [DateTime]::UtcNow.AddSeconds(60)
while (-not (Test-TritonModelReady)) {
if ([DateTime]::UtcNow -ge $deadline) { throw "YOLOX-S did not become ready" }
Start-Sleep -Milliseconds 500
}
}
Write-Output ("PHASE=e10-model-ready LOADED_BY_RUN={0}" -f $loadedByRun)
$token = [Guid]::NewGuid().ToString("N")
$workRoot = Join-Path $tmpRoot ("{0}-e10-{1}" -f $job.job_id, $token)
$framesRoot = Join-Path $workRoot "frames"
$streamPath = Join-Path $workRoot "camera.mp4"
$ptsPath = Join-Path $workRoot "pts.json"
$timelinePath = Join-Path $workRoot "timeline.jsonl"
$publishRoot = Join-Path $derivedRoot (".{0}-e10-{1}.publish" -f $job.job_id, $token)
$stagingRoot = Join-Path $publishRoot "output"
$null = New-Item -ItemType Directory -Path $framesRoot
$null = New-Item -ItemType Directory -Path $publishRoot
$completed = $false
$totalWatch = [Diagnostics.Stopwatch]::StartNew()
try {
$stream = [IO.File]::Open($streamPath, [IO.FileMode]::CreateNew, [IO.FileAccess]::Write, [IO.FileShare]::None)
try {
$input = [IO.File]::OpenRead($initPath)
try { $input.CopyTo($stream) } finally { $input.Dispose() }
for ($sequence = 1; $sequence -le ($EndFrame + 1); $sequence++) {
$path = Resolve-DFile (Join-Path $segmentsRoot ("{0}.m4s" -f $sequence)) "Camera segment"
$input = [IO.File]::OpenRead($path)
try { $input.CopyTo($stream) } finally { $input.Dispose() }
}
$stream.Flush($true)
}
finally { $stream.Dispose() }
$null = Assert-FreeSpace "post-stream-reconstruction"
$extractWatch = [Diagnostics.Stopwatch]::StartNew()
$selectFilter = "select='between(n,{0},{1})'" -f $StartFrame, $EndFrame
& ffmpeg -hide_banner -loglevel fatal -i $streamPath -map 0:v:0 -vf $selectFilter -fps_mode passthrough (Join-Path $framesRoot "frame-%06d.png")
Assert-LastExitCode "LAB E10 camera extraction"
& ffprobe -v error -select_streams v:0 -show_entries frame=best_effort_timestamp_time -of json $streamPath | Set-Content -LiteralPath $ptsPath -Encoding utf8
Assert-LastExitCode "LAB E10 timestamp probe"
$decoded = @(Get-ChildItem -LiteralPath $framesRoot -File -Filter "frame-*.png")
$pts = @((Get-Content -LiteralPath $ptsPath -Raw | ConvertFrom-Json).frames)
if ($decoded.Count -ne $clipFrameCount -or $pts.Count -ne ($EndFrame + 1)) { throw "LAB E10 decoded frame count changed" }
$firstEpochSeconds = [double]::Parse(([string]$pts[0].best_effort_timestamp_time).Trim(), [Globalization.CultureInfo]::InvariantCulture)
$writer = [IO.StreamWriter]::new($timelinePath, $false, [Text.UTF8Encoding]::new($false))
try {
for ($local = 0; $local -lt $clipFrameCount; $local++) {
$source = $StartFrame + $local
$epochSeconds = [double]::Parse(([string]$pts[$source].best_effort_timestamp_time).Trim(), [Globalization.CultureInfo]::InvariantCulture) - $firstEpochSeconds
$row = [ordered]@{
frame_index = $local
sequence = $local + 1
source_frame_index = $source
source_sequence = $source + 1
epoch_seconds = $epochSeconds
session_seconds = $timelineStart + $epochSeconds
}
$writer.WriteLine(($row | ConvertTo-Json -Compress))
}
$writer.Flush()
}
finally { $writer.Dispose() }
$extractWatch.Stop()
$freePostExtract = Assert-FreeSpace "post-frame-extraction"
$runArgs = @(
"run", "--rm", "--gpus", "all", "--network", ("container:{0}" -f $TritonContainer),
"--read-only", "--security-opt", "no-new-privileges:true", "--cap-drop", "ALL",
"--pids-limit", "512", "--shm-size", "4g",
"--tmpfs", "/tmp:rw,noexec,nosuid,size=2g"
) + $commonMounts + @(
"-v", ((Convert-ToDockerPath $framesRoot) + ":/frames:ro"),
"-v", ((Convert-ToDockerPath $workRoot) + ":/work:ro"),
"-v", ((Convert-ToDockerPath $publishRoot) + ":/publish:rw"),
"--entrypoint", "python3", $ContainerImage,
("/runner/{0}" -f $runnerName), "run"
) + $commonRunnerArgs + @(
"--frames", "/frames",
"--timeline", "/work/timeline.jsonl",
"--output", "/publish/output",
"--triton-url", "http://127.0.0.1:8000",
"--free-bytes-floor", [string]([int64]$FreeGiBFloor * 1GB),
"--orchestrator-sha256", $orchestratorSha256,
"--container-image", $ContainerImage
)
Write-Output ("PHASE=e10-integrated-replay-start FRAMES={0}" -f $clipFrameCount)
& docker @runArgs
Assert-LastExitCode "LAB E10 integrated replay"
$freePostReplay = Assert-FreeSpace "post-replay"
$result = Get-Content -LiteralPath (Join-Path $stagingRoot "result.json") -Raw | ConvertFrom-Json
if ($result.schema_version -ne "missioncore.e10-integrated-perception-result/v1" -or $result.result_id -notmatch "^e10-integrated-perception-[a-f0-9]{64}$") {
throw "LAB E10 result manifest is incompatible"
}
$finalRoot = Join-Path $derivedRoot ([string]$result.result_id)
if (Test-Path -LiteralPath $finalRoot) { throw "Immutable LAB E10 result already exists" }
Move-Item -LiteralPath $stagingRoot -Destination $finalRoot
Remove-Item -LiteralPath $publishRoot -Force
$completed = $true
$totalWatch.Stop()
$freeFinal = Assert-FreeSpace "post-publication"
Write-Output ("RESULT_ROOT={0}" -f $finalRoot)
Write-Output ("RESULT_ID={0}" -f $result.result_id)
Write-Output ("ACCEPTANCE_STATE={0}" -f $result.acceptance_state)
Write-Output ("PREPARATION_SECONDS={0}" -f $extractWatch.Elapsed.TotalSeconds)
Write-Output ("ORCHESTRATOR_WALL_SECONDS={0}" -f $totalWatch.Elapsed.TotalSeconds)
Write-Output ("DISK_FREE_BYTES_BEFORE={0}" -f $freeBytesBefore)
Write-Output ("DISK_FREE_BYTES_POST_EXTRACT={0}" -f $freePostExtract)
Write-Output ("DISK_FREE_BYTES_POST_REPLAY={0}" -f $freePostReplay)
Write-Output ("DISK_FREE_BYTES_FINAL={0}" -f $freeFinal)
}
finally {
if (Test-Path -LiteralPath $workRoot) { Remove-Item -LiteralPath $workRoot -Recurse -Force }
if (-not $completed -and (Test-Path -LiteralPath $publishRoot)) { Remove-Item -LiteralPath $publishRoot -Recurse -Force }
if ($loadedByRun) {
try {
Invoke-WebRequest -UseBasicParsing -TimeoutSec 60 -Uri "http://127.0.0.1:8000/v2/repository/models/yolox_s/unload" -Method Post -ContentType "application/json" -Body "{}" *> $null
Write-Output "PHASE=e10-model-state-restored"
}
catch { Write-Warning "LAB E10 could not restore the prior YOLOX-S state" }
}
}
@@ -0,0 +1,100 @@
[CmdletBinding()]
param(
[switch]$TokenStdin,
[ValidatePattern("^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$")]
[string]$RequestId = ("physical-k1-shadow-{0}" -f [Guid]::NewGuid().ToString("N")),
[string]$PersistentContainer = "mission-core-perception-worker",
[string]$PersistentOutputRoot = "D:\NDC_MISSIONCORE\runtime\derived\.perception-persistent-publish",
[ValidateRange(1024, 65535)] [int]$PersistentPort = 18020,
[ValidateRange(1, 1000)] [int]$FreeGiBFloor = 360
)
$ErrorActionPreference = "Stop"
$ProgressPreference = "SilentlyContinue"
function Assert-LastExitCode([string]$Operation) {
if ($LASTEXITCODE -ne 0) { throw "$Operation failed with exit code $LASTEXITCODE" }
}
function Resolve-DDirectory([string]$Path, [string]$Label) {
$item = Get-Item -LiteralPath (Resolve-Path -LiteralPath $Path).Path -Force
$root = [IO.Path]::GetPathRoot($item.FullName).TrimEnd("\")
if (-not $item.PSIsContainer -or ($item.Attributes -band [IO.FileAttributes]::ReparsePoint) -or $root -ine "D:") {
throw "$Label must be a real D: directory"
}
return $item.FullName
}
function Get-DFreeBytes { return [int64](Get-PSDrive -Name D).Free }
if (-not $TokenStdin) { throw "Persistent shadow run requires the token through stdin" }
$token = [Console]::In.ReadLine()
if (-not $token -or $token.Length -lt 40 -or $token.Length -gt 512) {
throw "Persistent shadow token is missing or malformed"
}
$outputRoot = Resolve-DDirectory $PersistentOutputRoot "Persistent output root"
$freeBefore = Get-DFreeBytes
if ($freeBefore -lt ([int64]$FreeGiBFloor * 1GB + 512MB)) {
throw "D: lacks the guarded persistent-run reserve"
}
$containerRunning = docker inspect --format "{{.State.Running}}" $PersistentContainer
Assert-LastExitCode "Persistent worker inspection"
if ($containerRunning.Trim().ToLowerInvariant() -ne "true") {
throw "Persistent worker is not running"
}
$outputName = $RequestId
$request = @{
request_id = $RequestId
output_name = $outputName
token = $token
} | ConvertTo-Json -Compress
$token = $null
$client = (
"import sys,urllib.request,urllib.error;data=sys.stdin.buffer.read();" +
"request=urllib.request.Request('http://127.0.0.1:{0}/run',data=data," -f $PersistentPort
) + "headers={'Content-Type':'application/json'},method='POST');" +
"`ntry:`n response=urllib.request.urlopen(request,timeout=3600); body=response.read(); code=response.status" +
"`nexcept urllib.error.HTTPError as exc:`n body=exc.read(); code=exc.code" +
"`nsys.stdout.buffer.write(body);raise SystemExit(0 if code==200 else 22)"
try {
$responseJson = $request | & docker exec -i $PersistentContainer python3 -c $client
$request = $null
Assert-LastExitCode "Persistent worker request"
}
finally {
$token = $null
$request = $null
}
$response = $responseJson | ConvertFrom-Json
if ($response.request_id -ne $RequestId -or $response.models_reused -ne $true) {
throw "Persistent worker response contract changed"
}
$staging = Join-Path $outputRoot $outputName
$resultPath = Join-Path $staging "result.json"
if (-not (Test-Path -LiteralPath $resultPath -PathType Leaf)) {
throw "Persistent worker result manifest is missing"
}
$result = Get-Content -LiteralPath $resultPath -Raw | ConvertFrom-Json
if (
$result.schema_version -ne "missioncore.e15-shadow-inference-result/v1" -or
$result.result_id -notmatch "^e15-shadow-inference-[a-f0-9]{64}$" -or
$result.publication_scope -ne "live-shadow-diagnostic-only"
) { throw "Persistent worker result manifest is incompatible" }
$derivedRoot = Resolve-DDirectory (Split-Path $outputRoot -Parent) "Runtime derived root"
$finalRoot = Join-Path $derivedRoot ([string]$result.result_id)
if (Test-Path -LiteralPath $finalRoot) {
throw "Immutable persistent-worker result already exists"
}
Move-Item -LiteralPath $staging -Destination $finalRoot
$freeFinal = Get-DFreeBytes
if ($freeFinal -lt ([int64]$FreeGiBFloor * 1GB)) {
throw "D: crossed the guarded floor after persistent run"
}
Write-Output ("RESULT_ROOT={0}" -f $finalRoot)
Write-Output ("RESULT_ID={0}" -f $result.result_id)
Write-Output ("ACCEPTANCE_STATE={0}" -f $result.acceptance_state)
Write-Output ("RUNNER_EXIT_CODE={0}" -f $response.exit_code)
Write-Output "MODELS_REUSED=true"
Write-Output ("DISK_FREE_BYTES_BEFORE={0}" -f $freeBefore)
Write-Output ("DISK_FREE_BYTES_FINAL={0}" -f $freeFinal)
@@ -0,0 +1,432 @@
[CmdletBinding()]
param(
[Parameter(Mandatory = $true)] [string]$JobRoot,
[Parameter(Mandatory = $true)] [string]$RunnerPath,
[Parameter(Mandatory = $true)] [string]$LiveProfilePath,
[Parameter(Mandatory = $true)] [string]$E14ProfilePath,
[Parameter(Mandatory = $true)] [string]$DetectorProfilePath,
[Parameter(Mandatory = $true)] [string]$SemanticProfilePath,
[Parameter(Mandatory = $true)] [string]$ValidFovRoot,
[Parameter(Mandatory = $true)] [string]$ProjectionPackRoot,
[Parameter(Mandatory = $true)] [string]$PackageRoot,
[switch]$PreflightOnly,
[switch]$PersistentService,
[switch]$TokenStdin,
[ValidateRange(5, 3600)] [int]$MaximumDurationSeconds = 20,
[ValidateRange(1, 1000)] [int]$FreeGiBFloor = 360,
[ValidateRange(1024, 65535)] [int]$SourcePort = 18012,
[string]$SourceHost = "host.docker.internal",
[string]$SourcePath = "/api/v1/device-plugins/nodedc.device.xgrids-lixelkity-k1/live-perception-shadow",
[string]$RuntimeRoot = "D:\NDC_MISSIONCORE\runtime",
[string]$ModelRoot = "D:\NDC_MISSIONCORE\runtime\models\yolox_s",
[string]$MediaRuntimeRoot = "D:\NDC_MISSIONCORE\runtime\derived\perception-e15-media-pyav180-lz445-v1",
[string]$TritonContainer = "mission-core-triton",
[string]$PersistentContainer = "mission-core-perception-worker",
[string]$PersistentOutputRoot = "D:\NDC_MISSIONCORE\runtime\derived\.perception-persistent-publish",
[ValidateRange(1024, 65535)] [int]$PersistentPort = 18020,
[string]$ContainerImage = "nvcr.io/nvidia/tritonserver:26.06-py3@sha256:58df7489c3f2276f9591d500a012dee03e23d35543ce3c390b4c001e6bf90794"
)
$ErrorActionPreference = "Stop"
$ProgressPreference = "SilentlyContinue"
function Assert-LastExitCode([string]$Operation) {
if ($LASTEXITCODE -ne 0) { throw "$Operation failed with exit code $LASTEXITCODE" }
}
function Resolve-DDirectory([string]$Path, [string]$Label) {
$item = Get-Item -LiteralPath (Resolve-Path -LiteralPath $Path).Path -Force
$root = [IO.Path]::GetPathRoot($item.FullName).TrimEnd("\")
if (-not $item.PSIsContainer -or ($item.Attributes -band [IO.FileAttributes]::ReparsePoint) -or $root -ine "D:") {
throw "$Label must be a real D: directory"
}
return $item.FullName
}
function Resolve-DFile([string]$Path, [string]$Label) {
$item = Get-Item -LiteralPath (Resolve-Path -LiteralPath $Path).Path -Force
$root = [IO.Path]::GetPathRoot($item.FullName).TrimEnd("\")
if ($item.PSIsContainer -or ($item.Attributes -band [IO.FileAttributes]::ReparsePoint) -or $root -ine "D:") {
throw "$Label must be a regular D: file"
}
return $item.FullName
}
function Convert-ToDockerPath([string]$Path) { return $Path.Replace("\", "/") }
function Get-DFreeBytes { return [int64](Get-PSDrive -Name D).Free }
function Assert-FreeSpace([string]$Phase, [int64]$RequiredAdditionalBytes = 0) {
$free = Get-DFreeBytes
$floor = [int64]$FreeGiBFloor * 1GB
Write-Host (
"DISK_GUARD PHASE={0} DRIVE=D FREE_BYTES={1} FREE_GIB={2} FLOOR_GIB={3} REQUIRED_ADDITIONAL_GIB={4}" -f
$Phase, $free, [math]::Round($free / 1GB, 3), $FreeGiBFloor,
[math]::Round($RequiredAdditionalBytes / 1GB, 3)
)
if ($free -lt ($floor + $RequiredAdditionalBytes)) {
throw "D: lacks the guarded LAB E15 reserve during $Phase"
}
return $free
}
function Test-TritonModelReady {
try {
$response = Invoke-WebRequest -UseBasicParsing -TimeoutSec 10 `
-Uri "http://127.0.0.1:8000/v2/models/yolox_s/ready"
return $response.StatusCode -eq 200
}
catch { return $false }
}
$jobDirectory = Resolve-DDirectory $JobRoot "Job root"
$runner = Resolve-DFile $RunnerPath "LAB E15 runner"
$liveProfile = Resolve-DFile $LiveProfilePath "LAB E15 live profile"
$e14Profile = Resolve-DFile $E14ProfilePath "Accepted E14 profile"
$detectorProfile = Resolve-DFile $DetectorProfilePath "Detector profile"
$semanticProfile = Resolve-DFile $SemanticProfilePath "Semantic profile"
$validFov = Resolve-DDirectory $ValidFovRoot "Valid-FOV root"
$projectionPack = Resolve-DDirectory $ProjectionPackRoot "E15 projection pack"
$package = Resolve-DDirectory $PackageRoot "Mission Core package root"
$runtime = Resolve-DDirectory $RuntimeRoot "Runtime root"
$model = Resolve-DDirectory $ModelRoot "YOLOX model root"
$mediaRuntime = Resolve-DDirectory $MediaRuntimeRoot "E15 media runtime"
$runnerRoot = Split-Path $runner -Parent
foreach ($path in @($liveProfile, $e14Profile, $detectorProfile, $semanticProfile)) {
if ((Split-Path $path -Parent) -ne $runnerRoot) {
throw "Runner and profiles must share one immutable mount"
}
}
foreach ($dependency in @(
"e10_fusion_runtime.py",
"e15_shadow_runtime.py",
"run_e10_integrated_perception.py",
"run_e12_shadow_transport_probe.py",
"run_e9_multirate_perception.py",
"run_e8_realtime_tracking.py",
"run_e5_instance_tracking.py",
"run_e4_full_session_segmentation.py",
"run_recorded_perception_epoch.py",
"run_e3_rectified_segmentation.py",
"run_evaluation_prelabels.py"
)) {
$null = Resolve-DFile (Join-Path $runnerRoot $dependency) "LAB E15 dependency"
}
if (-not (Test-Path -LiteralPath (Join-Path $package "k1link\compute\live_perception.py") -PathType Leaf)) {
throw "Mission Core package mount lacks live perception synchronization"
}
$job = Get-Content -LiteralPath (Join-Path $jobDirectory "job.json") -Raw | ConvertFrom-Json
if (
$job.schema_version -ne "missioncore.compute-job/v1" -or
$job.job_id -ne (Split-Path $jobDirectory -Leaf) -or
$job.input.source_id -ne "sensor.camera.right"
) { throw "Compute bootstrap job manifest is incompatible" }
$live = Get-Content -LiteralPath $liveProfile -Raw | ConvertFrom-Json
if (
$live.schema_version -ne "missioncore.e15-shadow-inference-profile/v1" -or
$live.mode -ne "replay-shadow-gate" -or
[bool]$live.authority.commands_enabled -or
[bool]$live.authority.navigation_or_safety_accepted -or
$live.transport.pyav_version -ne "18.0.0"
) { throw "LAB E15 replay-shadow authority contract changed" }
$projection = Get-Content -LiteralPath (Join-Path $projectionPack "manifest.json") -Raw | ConvertFrom-Json
if (
$projection.schema_version -ne "missioncore.e15-live-projection-pack/v1" -or
$projection.identity.source_id -ne "sensor.camera.right" -or
$projection.identity.calibration_slot -ne "camera_1" -or
$projection.identity.calibration_sha256 -ne $live.source.calibration_sha256
) { throw "LAB E15 projection pack binding changed" }
$mediaManifest = Get-Content -LiteralPath (Join-Path $mediaRuntime "manifest.json") -Raw | ConvertFrom-Json
if (
$mediaManifest.schema_version -ne "missioncore.e15-media-runtime/v1" -or
$mediaManifest.container_image -ne $ContainerImage -or
$mediaManifest.packages.av -ne "18.0.0" -or
$mediaManifest.packages.lz4 -ne "4.4.5"
) { throw "LAB E15 media runtime identity changed" }
$derivedRoot = Resolve-DDirectory (Join-Path $runtime "derived") "Runtime derived root"
$cacheRoot = Resolve-DDirectory (Join-Path $runtime "cache\perception-e3-models-v1") "EoMT cache"
$e3Environment = Resolve-DDirectory (Join-Path $derivedRoot "perception-e3-opencv413092-v1") "E3 environment"
$torchEnvironment = Resolve-DDirectory (Join-Path $derivedRoot "perception-p0-env-v1") "Torch environment"
$transformersEnvironment = Resolve-DDirectory (Join-Path $derivedRoot "perception-p0-transformers4576-v1") "Transformers environment"
$freeBytesBefore = Assert-FreeSpace "preflight" 512MB
& docker image inspect $ContainerImage *> $null
Assert-LastExitCode "Pinned container image inspection"
$tritonState = docker inspect --format "{{.State.Running}}" $TritonContainer
Assert-LastExitCode "Triton container inspection"
if ($tritonState.Trim().ToLowerInvariant() -ne "true") {
throw "LAB E15 requires the existing Triton container"
}
$runnerName = Split-Path $runner -Leaf
$liveProfileName = Split-Path $liveProfile -Leaf
$e14ProfileName = Split-Path $e14Profile -Leaf
$detectorProfileName = Split-Path $detectorProfile -Leaf
$semanticProfileName = Split-Path $semanticProfile -Leaf
$projectionMount = "/" + (Split-Path $projectionPack -Leaf)
$packageMount = "/" + (Split-Path $package -Leaf)
$orchestratorSha256 = (Get-FileHash -LiteralPath $PSCommandPath -Algorithm SHA256).Hash.ToLowerInvariant()
$commonMounts = @(
"-e", ("PYTHONPATH=/runner:{0}:/opt/media:/opt/transformers:/opt/env" -f $packageMount),
"-e", "PYTHONDONTWRITEBYTECODE=1",
"-e", "TORCH_HOME=/cache/torch",
"-e", "HF_HOME=/cache/huggingface",
"-e", "HF_HUB_OFFLINE=1",
"-e", "TRANSFORMERS_OFFLINE=1",
"-v", ((Convert-ToDockerPath $jobDirectory) + ":/job:ro"),
"-v", ((Convert-ToDockerPath $validFov) + ":/valid-fov:ro"),
"-v", ((Convert-ToDockerPath $projectionPack) + (":{0}:ro" -f $projectionMount)),
"-v", ((Convert-ToDockerPath $model) + ":/model:ro"),
"-v", ((Convert-ToDockerPath $cacheRoot) + ":/cache:ro"),
"-v", ((Convert-ToDockerPath $e3Environment) + ":/environment:ro"),
"-v", ((Convert-ToDockerPath $torchEnvironment) + ":/opt/env:ro"),
"-v", ((Convert-ToDockerPath $transformersEnvironment) + ":/opt/transformers:ro"),
"-v", ((Convert-ToDockerPath $mediaRuntime) + ":/opt/media:ro"),
"-v", ((Convert-ToDockerPath $package) + (":{0}:ro" -f $packageMount)),
"-v", ((Convert-ToDockerPath $runnerRoot) + ":/runner:ro")
)
$commonRunnerArgs = @(
"--job", "/job",
"--live-profile", ("/runner/{0}" -f $liveProfileName),
"--e14-profile", ("/runner/{0}" -f $e14ProfileName),
"--detector-profile", ("/runner/{0}" -f $detectorProfileName),
"--semantic-profile", ("/runner/{0}" -f $semanticProfileName),
"--valid-fov-root", "/valid-fov",
"--projection-pack", $projectionMount,
"--model-root", "/model",
"--cache", "/cache",
"--environment", "/environment",
"--worker-package", $packageMount
)
if ($PersistentService) {
if ($PreflightOnly -or $TokenStdin) {
throw "Persistent service cannot be combined with one-shot switches"
}
$persistentParent = Resolve-DDirectory (Split-Path $PersistentOutputRoot -Parent) "Persistent output parent"
if (-not (Test-Path -LiteralPath $PersistentOutputRoot)) {
$null = New-Item -ItemType Directory -Path $PersistentOutputRoot
}
$persistentOutput = Resolve-DDirectory $PersistentOutputRoot "Persistent output root"
if ((Split-Path $persistentOutput -Parent) -ne $persistentParent) {
throw "Persistent output root must be a direct child of its guarded D: parent"
}
$runnerSha256 = (Get-FileHash -LiteralPath $runner -Algorithm SHA256).Hash.ToLowerInvariant()
$existingContainerId = docker ps -a --filter ("name=^{0}$" -f $PersistentContainer) --format "{{.ID}}"
Assert-LastExitCode "Persistent worker container lookup"
if ($existingContainerId) {
$labels = (docker inspect --format "{{json .Config.Labels}}" $PersistentContainer) | ConvertFrom-Json
Assert-LastExitCode "Persistent worker label inspection"
if (
$labels.'missioncore.role' -ne "perception-persistent-worker" -or
$labels.'missioncore.runner.sha256' -ne $runnerSha256
) { throw "Existing persistent worker has a different immutable identity" }
$running = docker inspect --format "{{.State.Running}}" $PersistentContainer
Assert-LastExitCode "Persistent worker state inspection"
if ($running.Trim().ToLowerInvariant() -ne "true") {
throw "Matching persistent worker exists but is not running"
}
$healthProbe = (
"import json,urllib.request;d=json.load(urllib.request.urlopen(" +
"'http://127.0.0.1:{0}/health',timeout=5));" -f $PersistentPort
) + "raise SystemExit(0 if d.get('ok') and d.get('models_loaded') else 2)"
$previousErrorPreference = $ErrorActionPreference
$ErrorActionPreference = "Continue"
& docker exec $PersistentContainer python3 -c $healthProbe 2>$null
$healthExitCode = $LASTEXITCODE
$ErrorActionPreference = $previousErrorPreference
if ($healthExitCode -ne 0) { throw "Existing persistent worker health probe failed" }
Write-Output "STATE=persistent-worker-reused"
Write-Output ("CONTAINER={0}" -f $PersistentContainer)
return
}
if (-not (Test-TritonModelReady)) {
Invoke-WebRequest -UseBasicParsing -TimeoutSec 60 `
-Uri "http://127.0.0.1:8000/v2/repository/models/yolox_s/load" `
-Method Post -ContentType "application/json" -Body "{}" *> $null
$deadline = [DateTime]::UtcNow.AddSeconds(60)
while (-not (Test-TritonModelReady)) {
if ([DateTime]::UtcNow -ge $deadline) { throw "YOLOX-S did not become ready" }
Start-Sleep -Milliseconds 500
}
}
$serveArgs = @(
"run", "--detach", "--name", $PersistentContainer,
"--label", "missioncore.role=perception-persistent-worker",
"--label", ("missioncore.runner.sha256={0}" -f $runnerSha256),
"--gpus", "all", "--network", ("container:{0}" -f $TritonContainer),
"--read-only", "--security-opt", "no-new-privileges:true", "--cap-drop", "ALL",
"--pids-limit", "512", "--shm-size", "4g",
"--tmpfs", "/tmp:rw,noexec,nosuid,size=2g"
) + $commonMounts + @(
"-v", ((Convert-ToDockerPath $persistentOutput) + ":/publish:rw"),
"--entrypoint", "python3", $ContainerImage,
("/runner/{0}" -f $runnerName), "serve"
) + $commonRunnerArgs + @(
"--host", $SourceHost,
"--port", [string]$SourcePort,
"--path", $SourcePath,
"--triton-url", "http://127.0.0.1:8000",
"--output-root", "/publish",
"--listen-host", "127.0.0.1",
"--listen-port", [string]$PersistentPort,
"--max-duration-seconds", [string]$MaximumDurationSeconds,
"--free-bytes-floor", [string]([int64]$FreeGiBFloor * 1GB),
"--orchestrator-sha256", $orchestratorSha256,
"--container-image", $ContainerImage
)
Write-Output "PHASE=persistent-worker-model-load-start"
& docker @serveArgs
Assert-LastExitCode "Persistent worker container start"
$healthProbe = (
"import json,urllib.request;d=json.load(urllib.request.urlopen(" +
"'http://127.0.0.1:{0}/health',timeout=5));" -f $PersistentPort
) + "print(json.dumps(d,sort_keys=True));raise SystemExit(0 if d.get('ok') and d.get('models_loaded') else 2)"
$deadline = [DateTime]::UtcNow.AddSeconds(240)
do {
Start-Sleep -Seconds 2
$running = docker inspect --format "{{.State.Running}}" $PersistentContainer
if ($LASTEXITCODE -ne 0 -or $running.Trim().ToLowerInvariant() -ne "true") {
& docker logs --tail 80 $PersistentContainer
throw "Persistent worker exited during model load"
}
$previousErrorPreference = $ErrorActionPreference
$ErrorActionPreference = "Continue"
$health = & docker exec $PersistentContainer python3 -c $healthProbe 2>$null
$healthExitCode = $LASTEXITCODE
$ErrorActionPreference = $previousErrorPreference
$healthy = $healthExitCode -eq 0
} while (-not $healthy -and [DateTime]::UtcNow -lt $deadline)
if (-not $healthy) {
& docker logs --tail 80 $PersistentContainer
throw "Persistent worker model load did not become ready"
}
Write-Output "STATE=persistent-worker-ready"
Write-Output ("CONTAINER={0}" -f $PersistentContainer)
Write-Output ("HEALTH={0}" -f $health)
Write-Output ("DISK_FREE_BYTES={0}" -f (Get-DFreeBytes))
return
}
$preflightArgs = @(
"run", "--rm", "--gpus", "all", "--network", "none", "--read-only",
"--security-opt", "no-new-privileges:true", "--cap-drop", "ALL",
"--pids-limit", "512", "--shm-size", "4g",
"--tmpfs", "/tmp:rw,noexec,nosuid,size=2g"
) + $commonMounts + @(
"--entrypoint", "python3", $ContainerImage,
("/runner/{0}" -f $runnerName), "preflight"
) + $commonRunnerArgs
Write-Output "PHASE=e15-preflight-start"
& docker @preflightArgs
Assert-LastExitCode "LAB E15 preflight"
Write-Output "PHASE=e15-preflight-complete"
if ($PreflightOnly) {
Write-Output "STATE=preflight-ready"
Write-Output ("DISK_FREE_BYTES_BEFORE={0}" -f $freeBytesBefore)
Write-Output ("DISK_FREE_BYTES_AFTER={0}" -f (Get-DFreeBytes))
return
}
if (-not $TokenStdin) { throw "LAB E15 requires the shadow token through stdin" }
$shadowToken = [Console]::In.ReadLine()
if (-not $shadowToken -or $shadowToken.Length -lt 40 -or $shadowToken.Length -gt 512) {
throw "LAB E15 shadow token is missing or malformed"
}
$modelWasReady = Test-TritonModelReady
$loadedByRun = $false
if (-not $modelWasReady) {
Invoke-WebRequest -UseBasicParsing -TimeoutSec 60 `
-Uri "http://127.0.0.1:8000/v2/repository/models/yolox_s/load" `
-Method Post -ContentType "application/json" -Body "{}" *> $null
$loadedByRun = $true
$deadline = [DateTime]::UtcNow.AddSeconds(60)
while (-not (Test-TritonModelReady)) {
if ([DateTime]::UtcNow -ge $deadline) { throw "YOLOX-S did not become ready" }
Start-Sleep -Milliseconds 500
}
}
Write-Output ("PHASE=e15-model-ready LOADED_BY_RUN={0}" -f $loadedByRun)
$token = [Guid]::NewGuid().ToString("N")
$publishRoot = Join-Path $derivedRoot (".{0}-e15-{1}.publish" -f $job.job_id, $token)
$stagingRoot = Join-Path $publishRoot "output"
$null = New-Item -ItemType Directory -Path $publishRoot
$completed = $false
$totalWatch = [Diagnostics.Stopwatch]::StartNew()
try {
$runArgs = @(
"run", "--rm", "--interactive", "--gpus", "all",
"--network", ("container:{0}" -f $TritonContainer),
"--read-only", "--security-opt", "no-new-privileges:true", "--cap-drop", "ALL",
"--pids-limit", "512", "--shm-size", "4g",
"--tmpfs", "/tmp:rw,noexec,nosuid,size=2g"
) + $commonMounts + @(
"-v", ((Convert-ToDockerPath $publishRoot) + ":/publish:rw"),
"--entrypoint", "python3", $ContainerImage,
("/runner/{0}" -f $runnerName), "run"
) + $commonRunnerArgs + @(
"--host", $SourceHost,
"--port", [string]$SourcePort,
"--path", $SourcePath,
"--token-stdin",
"--triton-url", "http://127.0.0.1:8000",
"--output", "/publish/output",
"--max-duration-seconds", [string]$MaximumDurationSeconds,
"--free-bytes-floor", [string]([int64]$FreeGiBFloor * 1GB),
"--orchestrator-sha256", $orchestratorSha256,
"--container-image", $ContainerImage
)
Write-Output ("PHASE=e15-shadow-inference-start MAX_DURATION_SECONDS={0}" -f $MaximumDurationSeconds)
$shadowToken | & docker @runArgs
$runnerExitCode = $LASTEXITCODE
$shadowToken = $null
if ($runnerExitCode -ne 0 -and $runnerExitCode -ne 2) {
throw "LAB E15 shadow inference failed with exit code $runnerExitCode"
}
$null = Assert-FreeSpace "post-shadow-inference"
$resultPath = Join-Path $stagingRoot "result.json"
if (-not (Test-Path -LiteralPath $resultPath -PathType Leaf)) {
throw "LAB E15 result manifest is missing"
}
$result = Get-Content -LiteralPath $resultPath -Raw | ConvertFrom-Json
if (
$result.schema_version -ne "missioncore.e15-shadow-inference-result/v1" -or
$result.result_id -notmatch "^e15-shadow-inference-[a-f0-9]{64}$" -or
$result.publication_scope -ne "live-shadow-diagnostic-only"
) { throw "LAB E15 result manifest is incompatible" }
$finalRoot = Join-Path $derivedRoot ([string]$result.result_id)
if (Test-Path -LiteralPath $finalRoot) { throw "Immutable LAB E15 result already exists" }
Move-Item -LiteralPath $stagingRoot -Destination $finalRoot
Remove-Item -LiteralPath $publishRoot -Force
$completed = $true
$totalWatch.Stop()
$freeFinal = Assert-FreeSpace "post-publication"
Write-Output ("RESULT_ROOT={0}" -f $finalRoot)
Write-Output ("RESULT_ID={0}" -f $result.result_id)
Write-Output ("ACCEPTANCE_STATE={0}" -f $result.acceptance_state)
Write-Output ("RUNNER_EXIT_CODE={0}" -f $runnerExitCode)
Write-Output ("ORCHESTRATOR_WALL_SECONDS={0}" -f $totalWatch.Elapsed.TotalSeconds)
Write-Output ("DISK_FREE_BYTES_BEFORE={0}" -f $freeBytesBefore)
Write-Output ("DISK_FREE_BYTES_FINAL={0}" -f $freeFinal)
}
finally {
$shadowToken = $null
if (-not $completed -and (Test-Path -LiteralPath $publishRoot)) {
Remove-Item -LiteralPath $publishRoot -Recurse -Force
}
if ($loadedByRun) {
try {
Invoke-WebRequest -UseBasicParsing -TimeoutSec 60 `
-Uri "http://127.0.0.1:8000/v2/repository/models/yolox_s/unload" `
-Method Post -ContentType "application/json" -Body "{}" *> $null
Write-Output "PHASE=e15-model-state-restored"
}
catch { Write-Warning "LAB E15 could not restore the prior YOLOX-S state" }
}
}
@@ -0,0 +1,251 @@
[CmdletBinding()]
param(
[Parameter(Mandatory = $true)]
[string]$EvaluationPack,
[Parameter(Mandatory = $true)]
[string]$E2Prelabels,
[Parameter(Mandatory = $true)]
[string]$ValidFovRoot,
[Parameter(Mandatory = $true)]
[string]$RunnerPath,
[Parameter(Mandatory = $true)]
[string]$BaselineRunnerPath,
[Parameter(Mandatory = $true)]
[string]$ProfilePath,
[ValidateRange(0, 64)]
[int]$MaxFrames = 0,
[ValidateRange(1, 1000)]
[int]$FreeGiBFloor = 360,
[string]$RuntimeRoot = "D:\NDC_MISSIONCORE\runtime",
[string]$ContainerImage = "nvcr.io/nvidia/tritonserver:26.06-py3"
)
$ErrorActionPreference = "Stop"
$ProgressPreference = "SilentlyContinue"
function Assert-LastExitCode {
param([string]$Operation)
if ($LASTEXITCODE -ne 0) {
throw "$Operation failed with exit code $LASTEXITCODE"
}
}
function Assert-RegularFile {
param([string]$Path, [string]$Label)
$item = Get-Item -LiteralPath $Path -Force
if (-not $item.PSIsContainer -and -not ($item.Attributes -band [IO.FileAttributes]::ReparsePoint)) {
return $item.FullName
}
throw "$Label is not a regular file"
}
function Assert-Directory {
param([string]$Path, [string]$Label)
$item = Get-Item -LiteralPath $Path -Force
if ($item.PSIsContainer -and -not ($item.Attributes -band [IO.FileAttributes]::ReparsePoint)) {
return $item.FullName
}
throw "$Label is not a real directory"
}
function Assert-DDrivePath {
param([string]$Path, [string]$Label)
$fullPath = [IO.Path]::GetFullPath($Path)
if ([IO.Path]::GetPathRoot($fullPath).TrimEnd("\") -ine "D:") {
throw "$Label must be stored on D:"
}
return $fullPath
}
function Assert-FreeSpace {
param([string]$Phase)
$freeBytes = [int64](Get-PSDrive -Name D).Free
$floorBytes = [int64]$FreeGiBFloor * 1GB
$freeGiB = [math]::Round($freeBytes / 1GB, 3)
Write-Output ("DISK_GUARD PHASE={0} DRIVE=D FREE_GIB={1} FLOOR_GIB={2}" -f $Phase, $freeGiB, $FreeGiBFloor)
if ($freeBytes -lt $floorBytes) {
throw "D: free-space floor was crossed during $Phase"
}
}
function Convert-ToDockerPath {
param([string]$Path)
return $Path.Replace("\", "/")
}
$packRoot = Assert-DDrivePath (Assert-Directory (Resolve-Path -LiteralPath $EvaluationPack).Path "Evaluation pack") "Evaluation pack"
$prelabelsRoot = Assert-DDrivePath (Assert-Directory (Resolve-Path -LiteralPath $E2Prelabels).Path "E2 prelabels") "E2 prelabels"
$validFov = Assert-DDrivePath (Assert-Directory (Resolve-Path -LiteralPath $ValidFovRoot).Path "Valid-FOV root") "Valid-FOV root"
$runner = Assert-DDrivePath (Assert-RegularFile (Resolve-Path -LiteralPath $RunnerPath).Path "LAB E3 runner") "LAB E3 runner"
$baselineRunner = Assert-DDrivePath (Assert-RegularFile (Resolve-Path -LiteralPath $BaselineRunnerPath).Path "Baseline runner") "Baseline runner"
$profile = Assert-DDrivePath (Assert-RegularFile (Resolve-Path -LiteralPath $ProfilePath).Path "LAB E3 profile") "LAB E3 profile"
$runtime = Assert-DDrivePath (Assert-Directory (Resolve-Path -LiteralPath $RuntimeRoot).Path "Runtime root") "Runtime root"
if (
(Split-Path $runner -Parent) -ne (Split-Path $baselineRunner -Parent) -or
(Split-Path $runner -Parent) -ne (Split-Path $profile -Parent)
) {
throw "LAB E3 runner, baseline runner, and profile must share one read-only mount"
}
$pack = Get-Content -LiteralPath (Join-Path $packRoot "manifest.json") -Raw | ConvertFrom-Json
$prelabels = Get-Content -LiteralPath (Join-Path $prelabelsRoot "result.json") -Raw | ConvertFrom-Json
$profileDocument = Get-Content -LiteralPath $profile -Raw | ConvertFrom-Json
$packFrameCount = @($pack.identity.frames).Count
if (
$pack.schema_version -ne "missioncore.perception-evaluation-pack/v1" -or
$pack.generation_id -ne (Split-Path $packRoot -Leaf) -or
$pack.identity.source_id -ne "sensor.camera.right" -or
$pack.identity.calibration_slot -ne "camera_1" -or
$packFrameCount -ne 64 -or
$prelabels.schema_version -ne "missioncore.perception-evaluation-prelabels/v1" -or
$prelabels.identity.evaluation_pack_id -ne $pack.generation_id -or
$profileDocument.schema_version -ne "missioncore.k1-e3-rectified-segmentation-profile/v1" -or
$profileDocument.source.source_id -ne $pack.identity.source_id -or
$profileDocument.source.calibration_slot -ne $pack.identity.calibration_slot -or
$profileDocument.source.calibration_sha256 -ne $pack.identity.calibration_sha256
) {
throw "LAB E3 inputs are incompatible"
}
$null = Assert-RegularFile (Join-Path $validFov "manifest.json") "Valid-FOV manifest"
$null = Assert-RegularFile (Join-Path $validFov "mask.png") "Valid-FOV mask"
& docker image inspect $ContainerImage *> $null
Assert-LastExitCode "Existing container image inspection"
Assert-FreeSpace "preflight"
$cacheRoot = Join-Path $runtime "cache\perception-e3-models-v1"
$derivedRoot = Join-Path $runtime "derived\e3-segmentation"
$environmentRoot = Join-Path $runtime "derived\perception-e3-opencv413092-v1"
$torchEnvironment = Assert-Directory (Join-Path $runtime "derived\perception-p0-env-v1") "Torch environment"
$transformersEnvironment = Assert-Directory (Join-Path $runtime "derived\perception-p0-transformers4576-v1") "Transformers environment"
$runnerRoot = Split-Path $runner -Parent
$runnerName = Split-Path $runner -Leaf
$profileName = Split-Path $profile -Leaf
$null = New-Item -ItemType Directory -Path $cacheRoot -Force
$null = New-Item -ItemType Directory -Path $derivedRoot -Force
if (-not (Test-Path -LiteralPath $environmentRoot)) {
$environmentToken = [Guid]::NewGuid().ToString("N")
$environmentStaging = Join-Path (Split-Path $environmentRoot -Parent) (".e3-environment-{0}.publish" -f $environmentToken)
$null = New-Item -ItemType Directory -Path $environmentStaging
$null = New-Item -ItemType Directory -Path (Join-Path $environmentStaging "tmp")
try {
$prepareArgs = @(
"run", "--rm", "--network", "bridge", "--read-only",
"--security-opt", "no-new-privileges:true", "--cap-drop", "ALL",
"--pids-limit", "512", "--tmpfs", "/tmp:rw,noexec,nosuid,size=1g",
"-e", "PYTHONPATH=/opt/transformers:/opt/env",
"-e", "HF_HOME=/cache/huggingface",
"-e", "PIP_NO_CACHE_DIR=1",
"-e", "HOME=/environment/tmp",
"-e", "TMPDIR=/environment/tmp",
"-v", ((Convert-ToDockerPath $cacheRoot) + ":/cache:rw"),
"-v", ((Convert-ToDockerPath $environmentStaging) + ":/environment:rw"),
"-v", ((Convert-ToDockerPath $torchEnvironment) + ":/opt/env:ro"),
"-v", ((Convert-ToDockerPath $transformersEnvironment) + ":/opt/transformers:ro"),
"-v", ((Convert-ToDockerPath $runnerRoot) + ":/runner:ro"),
"--entrypoint", "python3",
$ContainerImage,
("/runner/{0}" -f $runnerName), "prepare",
"--profile", ("/runner/{0}" -f $profileName),
"--cache", "/cache",
"--environment", "/environment"
)
Write-Output "PHASE=e3-dependency-prepare-start"
& docker @prepareArgs
Assert-LastExitCode "LAB E3 dependency preparation"
$null = Assert-RegularFile (Join-Path $environmentStaging "manifest.json") "LAB E3 dependency manifest"
Remove-Item -LiteralPath (Join-Path $environmentStaging "tmp") -Recurse -Force
Move-Item -LiteralPath $environmentStaging -Destination $environmentRoot
Write-Output "PHASE=e3-dependency-prepare-complete"
}
finally {
if (Test-Path -LiteralPath $environmentStaging) {
Remove-Item -LiteralPath $environmentStaging -Recurse -Force
}
}
}
$environment = Assert-Directory $environmentRoot "LAB E3 dependency environment"
$null = Assert-RegularFile (Join-Path $environment "manifest.json") "LAB E3 dependency manifest"
Assert-FreeSpace "post-dependency-prepare"
$runToken = [Guid]::NewGuid().ToString("N")
$publishRoot = Join-Path $derivedRoot (".{0}-{1}.publish" -f $pack.generation_id, $runToken)
$stagingRoot = Join-Path $publishRoot "output"
$null = New-Item -ItemType Directory -Path $publishRoot
try {
$runArgs = @(
"run", "--rm", "--gpus", "all", "--network", "none", "--read-only",
"--security-opt", "no-new-privileges:true", "--cap-drop", "ALL",
"--pids-limit", "512", "--shm-size", "4g",
"--tmpfs", "/tmp:rw,noexec,nosuid,size=2g",
"-e", "PYTHONPATH=/opt/transformers:/opt/env",
"-e", "TORCH_HOME=/cache/torch",
"-e", "HF_HOME=/cache/huggingface",
"-e", "HF_HUB_OFFLINE=1",
"-e", "TRANSFORMERS_OFFLINE=1",
"-e", "HOME=/tmp",
"-v", ((Convert-ToDockerPath $packRoot) + ":/evaluation-pack:ro"),
"-v", ((Convert-ToDockerPath $prelabelsRoot) + ":/e2-prelabels:ro"),
"-v", ((Convert-ToDockerPath $validFov) + ":/valid-fov:ro"),
"-v", ((Convert-ToDockerPath $publishRoot) + ":/publish:rw"),
"-v", ((Convert-ToDockerPath $cacheRoot) + ":/cache:ro"),
"-v", ((Convert-ToDockerPath $environment) + ":/environment:ro"),
"-v", ((Convert-ToDockerPath $torchEnvironment) + ":/opt/env:ro"),
"-v", ((Convert-ToDockerPath $transformersEnvironment) + ":/opt/transformers:ro"),
"-v", ((Convert-ToDockerPath $runnerRoot) + ":/runner:ro"),
"--entrypoint", "python3",
$ContainerImage,
("/runner/{0}" -f $runnerName), "run",
"--profile", ("/runner/{0}" -f $profileName),
"--evaluation-pack", "/evaluation-pack",
"--e2-prelabels", "/e2-prelabels",
"--valid-fov-root", "/valid-fov",
"--cache", "/cache",
"--environment", "/environment",
"--output", "/publish/output",
"--telemetry-interval-seconds", "1"
)
if ($MaxFrames -gt 0) {
$runArgs += @("--max-frames", [string]$MaxFrames)
}
$expectedFrames = if ($MaxFrames -gt 0) { $MaxFrames } else { $packFrameCount }
Write-Output ("PHASE=e3-run-start PACK={0} FRAMES={1}" -f $pack.generation_id, $expectedFrames)
& docker @runArgs
Assert-LastExitCode "LAB E3 segmentation"
$result = Get-Content -LiteralPath (Join-Path $stagingRoot "result.json") -Raw | ConvertFrom-Json
if (
$result.schema_version -ne "missioncore.k1-e3-rectified-segmentation-result/v1" -or
$result.result_id -notmatch "^e3-segmentation-[a-f0-9]{64}$" -or
$result.identity.evaluation_pack_id -ne $pack.generation_id -or
[int]$result.identity.frame_count -ne $expectedFrames -or
$result.ground_truth -ne $false
) {
throw "LAB E3 result manifest is incompatible"
}
$finalRoot = Join-Path $derivedRoot ([string]$result.result_id)
if (Test-Path -LiteralPath $finalRoot) {
throw "An immutable LAB E3 result with the same identity already exists: $finalRoot"
}
Move-Item -LiteralPath $stagingRoot -Destination $finalRoot
Remove-Item -LiteralPath $publishRoot -Force
Assert-FreeSpace "post-run"
Write-Output ("RESULT_ROOT={0}" -f $finalRoot)
Write-Output ("RESULT_ID={0}" -f $result.result_id)
}
finally {
if (Test-Path -LiteralPath $publishRoot) {
Remove-Item -LiteralPath $publishRoot -Recurse -Force
}
}
@@ -0,0 +1,421 @@
[CmdletBinding()]
param(
[Parameter(Mandatory = $true)]
[string]$JobRoot,
[Parameter(Mandatory = $true)]
[string]$RunnerPath,
[Parameter(Mandatory = $true)]
[string]$ProfilePath,
[Parameter(Mandatory = $true)]
[string]$ValidFovRoot,
[ValidateRange(0, 256)]
[int]$PilotFrames = 0,
[ValidateRange(1, 1000)]
[int]$FreeGiBFloor = 360,
[string]$RuntimeRoot = "D:\NDC_MISSIONCORE\runtime",
[string]$ContainerImage = "nvcr.io/nvidia/tritonserver:26.06-py3"
)
$ErrorActionPreference = "Stop"
$ProgressPreference = "SilentlyContinue"
function Assert-LastExitCode {
param([string]$Operation)
if ($LASTEXITCODE -ne 0) {
throw "$Operation failed with exit code $LASTEXITCODE"
}
}
function Assert-RegularFile {
param([string]$Path, [string]$Label)
$item = Get-Item -LiteralPath $Path -Force
if (-not $item.PSIsContainer -and -not ($item.Attributes -band [IO.FileAttributes]::ReparsePoint)) {
return $item.FullName
}
throw "$Label is not a regular file"
}
function Assert-Directory {
param([string]$Path, [string]$Label)
$item = Get-Item -LiteralPath $Path -Force
if ($item.PSIsContainer -and -not ($item.Attributes -band [IO.FileAttributes]::ReparsePoint)) {
return $item.FullName
}
throw "$Label is not a real directory"
}
function Assert-DDrivePath {
param([string]$Path, [string]$Label)
$fullPath = [IO.Path]::GetFullPath($Path)
if ([IO.Path]::GetPathRoot($fullPath).TrimEnd("\") -ine "D:") {
throw "$Label must be stored on D:"
}
return $fullPath
}
function Get-DFreeBytes {
return [int64](Get-PSDrive -Name D).Free
}
function Assert-FreeSpace {
param(
[string]$Phase,
[int64]$RequiredAdditionalBytes = 0
)
$freeBytes = Get-DFreeBytes
$floorBytes = [int64]$FreeGiBFloor * 1GB
$requiredBytes = $floorBytes + $RequiredAdditionalBytes
Write-Host (
"DISK_GUARD PHASE={0} DRIVE=D FREE_BYTES={1} FREE_GIB={2} FLOOR_GIB={3} REQUIRED_ADDITIONAL_GIB={4}" -f
$Phase,
$freeBytes,
[math]::Round($freeBytes / 1GB, 3),
$FreeGiBFloor,
[math]::Round($RequiredAdditionalBytes / 1GB, 3)
)
if ($freeBytes -lt $requiredBytes) {
throw "D: does not have the guarded LAB E4 working-set reserve during $Phase"
}
return $freeBytes
}
function Convert-ToDockerPath {
param([string]$Path)
return $Path.Replace("\", "/")
}
$jobDirectory = Assert-DDrivePath (Assert-Directory (Resolve-Path -LiteralPath $JobRoot).Path "Job root") "Job root"
$runner = Assert-DDrivePath (Assert-RegularFile (Resolve-Path -LiteralPath $RunnerPath).Path "LAB E4 runner") "LAB E4 runner"
$profile = Assert-DDrivePath (Assert-RegularFile (Resolve-Path -LiteralPath $ProfilePath).Path "LAB E4 profile") "LAB E4 profile"
$validFov = Assert-DDrivePath (Assert-Directory (Resolve-Path -LiteralPath $ValidFovRoot).Path "Valid-FOV root") "Valid-FOV root"
$runtime = Assert-DDrivePath (Assert-Directory (Resolve-Path -LiteralPath $RuntimeRoot).Path "Runtime root") "Runtime root"
$runnerRoot = Split-Path $runner -Parent
if ((Split-Path $profile -Parent) -ne $runnerRoot) {
throw "LAB E4 runner and profile must share one read-only mount"
}
foreach ($dependency in @(
"run_recorded_perception_epoch.py",
"run_e3_rectified_segmentation.py",
"run_evaluation_prelabels.py"
)) {
$null = Assert-RegularFile (Join-Path $runnerRoot $dependency) "LAB E4 runner dependency"
}
$job = Get-Content -LiteralPath (Join-Path $jobDirectory "job.json") -Raw | ConvertFrom-Json
if ($job.schema_version -ne "missioncore.compute-job/v1" -or $job.job_id -ne (Split-Path $jobDirectory -Leaf)) {
throw "Compute job manifest is incompatible"
}
$sourceId = [string]$job.input.source_id
$epoch = [int]$job.input.codec_epoch
$fullFrameCount = [int]$job.input.segment_count
$activeFrameCount = if ($PilotFrames -gt 0) { $PilotFrames } else { $fullFrameCount }
$timelineStart = [double]$job.input.timeline.start_seconds
$timelineEnd = [double]$job.input.timeline.end_seconds
$timelineDuration = $timelineEnd - $timelineStart
if (
$sourceId -ne "sensor.camera.right" -or
$fullFrameCount -lt 1 -or
$activeFrameCount -gt $fullFrameCount -or
$timelineDuration -le 0
) {
throw "LAB E4 camera job contract is invalid"
}
Write-Output ("PHASE=job-manifest-validated JOB={0} FRAMES={1}/{2}" -f $job.job_id, $activeFrameCount, $fullFrameCount)
$epochRoot = Join-Path $jobDirectory ("input\camera\{0}\epoch-{1}" -f $sourceId, $epoch)
$epochRoot = Assert-DDrivePath (Assert-Directory $epochRoot "Camera epoch") "Camera epoch"
$initPath = Assert-RegularFile (Join-Path $epochRoot "init.mp4") "Camera init"
$segmentsRoot = Assert-Directory (Join-Path $epochRoot "segments") "Camera segments"
$derivedRoot = Join-Path $runtime "derived"
$tmpRoot = Join-Path $runtime "tmp"
$cacheRoot = Assert-DDrivePath (Assert-Directory (Join-Path $runtime "cache\perception-e3-models-v1") "EoMT cache") "EoMT cache"
$e3Environment = Assert-DDrivePath (Assert-Directory (Join-Path $derivedRoot "perception-e3-opencv413092-v1") "E3 dependency environment") "E3 dependency environment"
$torchEnvironment = Assert-DDrivePath (Assert-Directory (Join-Path $derivedRoot "perception-p0-env-v1") "Torch environment") "Torch environment"
$transformersEnvironment = Assert-DDrivePath (Assert-Directory (Join-Path $derivedRoot "perception-p0-transformers4576-v1") "Transformers environment") "Transformers environment"
$null = New-Item -ItemType Directory -Path $derivedRoot -Force
$null = New-Item -ItemType Directory -Path $tmpRoot -Force
# Conservative upper bound: decoded RGB + RGB overlay + one-byte semantic mask,
# plus 20% filesystem/encoding overhead and the reconstructed source stream.
$pixelWorkingSet = [int64]$activeFrameCount * 800 * 600 * 7
$workingSetReserve = [int64][math]::Ceiling(($pixelWorkingSet * 1.2) + [int64]$job.input.byte_length)
$freeBytesBefore = Assert-FreeSpace "preflight" $workingSetReserve
& docker image inspect $ContainerImage *> $null
Assert-LastExitCode "Existing container image inspection"
$runnerName = Split-Path $runner -Leaf
$profileName = Split-Path $profile -Leaf
$orchestratorSha256 = (Get-FileHash -LiteralPath $PSCommandPath -Algorithm SHA256).Hash.ToLowerInvariant()
$preflightArgs = @(
"run", "--rm", "--gpus", "all", "--network", "none", "--read-only",
"--security-opt", "no-new-privileges:true", "--cap-drop", "ALL",
"--pids-limit", "512", "--shm-size", "4g",
"--tmpfs", "/tmp:rw,noexec,nosuid,size=2g",
"-e", "PYTHONPATH=/opt/transformers:/opt/env",
"-e", "TORCH_HOME=/cache/torch",
"-e", "HF_HOME=/cache/huggingface",
"-e", "HF_HUB_OFFLINE=1",
"-e", "TRANSFORMERS_OFFLINE=1",
"-v", ((Convert-ToDockerPath $jobDirectory) + ":/job:ro"),
"-v", ((Convert-ToDockerPath $validFov) + ":/valid-fov:ro"),
"-v", ((Convert-ToDockerPath $cacheRoot) + ":/cache:ro"),
"-v", ((Convert-ToDockerPath $e3Environment) + ":/environment:ro"),
"-v", ((Convert-ToDockerPath $torchEnvironment) + ":/opt/env:ro"),
"-v", ((Convert-ToDockerPath $transformersEnvironment) + ":/opt/transformers:ro"),
"-v", ((Convert-ToDockerPath $runnerRoot) + ":/runner:ro"),
"--entrypoint", "python3",
$ContainerImage,
("/runner/{0}" -f $runnerName), "preflight",
"--job", "/job",
"--profile", ("/runner/{0}" -f $profileName),
"--valid-fov-root", "/valid-fov",
"--cache", "/cache",
"--environment", "/environment"
)
Write-Output "PHASE=e4-preflight-start"
& docker @preflightArgs
Assert-LastExitCode "LAB E4 preflight"
Write-Output "PHASE=e4-preflight-complete"
$runToken = [Guid]::NewGuid().ToString("N")
$workRoot = Join-Path $tmpRoot ("{0}-e4-{1}" -f $job.job_id, $runToken)
$framesRoot = Join-Path $workRoot "frames"
$streamPath = Join-Path $workRoot "camera.mp4"
$ptsPath = Join-Path $workRoot "pts.json"
$timelinePath = Join-Path $workRoot "timeline.jsonl"
$publishRoot = Join-Path $derivedRoot (".{0}-e4-{1}.publish" -f $job.job_id, $runToken)
$stagingRoot = Join-Path $publishRoot "output"
$null = New-Item -ItemType Directory -Path $framesRoot
$null = New-Item -ItemType Directory -Path $publishRoot
$totalWatch = [Diagnostics.Stopwatch]::StartNew()
$completed = $false
Write-Output "PHASE=e4-private-staging-created"
try {
$stream = [IO.File]::Open($streamPath, [IO.FileMode]::CreateNew, [IO.FileAccess]::Write, [IO.FileShare]::None)
try {
$input = [IO.File]::OpenRead($initPath)
try {
$input.CopyTo($stream)
}
finally {
$input.Dispose()
}
for ($sequence = 1; $sequence -le $activeFrameCount; $sequence++) {
$path = Assert-RegularFile (Join-Path $segmentsRoot ("{0}.m4s" -f $sequence)) "Camera segment"
$input = [IO.File]::OpenRead($path)
try {
$input.CopyTo($stream)
}
finally {
$input.Dispose()
}
if ($sequence % 500 -eq 0 -or $sequence -eq $activeFrameCount) {
Write-Output ("PHASE=e4-stream-reconstruction SEGMENTS={0}/{1}" -f $sequence, $activeFrameCount)
}
}
$stream.Flush($true)
}
finally {
$stream.Dispose()
}
$null = Assert-FreeSpace "post-stream-reconstruction"
$extractWatch = [Diagnostics.Stopwatch]::StartNew()
Write-Output "PHASE=e4-frame-extraction-start"
& ffmpeg -hide_banner -loglevel fatal -i $streamPath -map 0:v:0 -fps_mode passthrough -frames:v $activeFrameCount (Join-Path $framesRoot "frame-%06d.png")
Assert-LastExitCode "LAB E4 camera extraction"
& ffprobe -v error -select_streams v:0 -show_entries frame=best_effort_timestamp_time -of json $streamPath | Set-Content -LiteralPath $ptsPath -Encoding utf8
Assert-LastExitCode "LAB E4 camera timestamp probe"
$decodedFrames = @(Get-ChildItem -LiteralPath $framesRoot -File -Filter "frame-*.png")
$ptsDocument = Get-Content -LiteralPath $ptsPath -Raw | ConvertFrom-Json
$pts = @($ptsDocument.frames)
if ($decodedFrames.Count -ne $activeFrameCount -or $pts.Count -lt $activeFrameCount) {
throw "Decoded LAB E4 frame count differs from the requested camera epoch"
}
$firstEpochSeconds = [double]::Parse(
([string]$pts[0].best_effort_timestamp_time).Trim(),
[Globalization.CultureInfo]::InvariantCulture
)
$previousEpochSeconds = -1.0
$timelineWriter = [IO.StreamWriter]::new($timelinePath, $false, [Text.UTF8Encoding]::new($false))
try {
for ($index = 0; $index -lt $activeFrameCount; $index++) {
$epochSeconds = [double]::Parse(
([string]$pts[$index].best_effort_timestamp_time).Trim(),
[Globalization.CultureInfo]::InvariantCulture
) - $firstEpochSeconds
if ($epochSeconds -le $previousEpochSeconds -or $epochSeconds -gt ($timelineDuration + 0.001)) {
throw "Decoded LAB E4 timestamps are not strictly monotonic inside the camera timeline"
}
$row = [ordered]@{
frame_index = $index
epoch_seconds = $epochSeconds
session_seconds = $timelineStart + $epochSeconds
}
$timelineWriter.WriteLine(($row | ConvertTo-Json -Compress))
$previousEpochSeconds = $epochSeconds
}
$timelineWriter.Flush()
}
finally {
$timelineWriter.Dispose()
}
$extractWatch.Stop()
$freeBytesPostExtract = Assert-FreeSpace "post-frame-extraction"
Write-Output ("PHASE=e4-frame-extraction-complete FRAMES={0}" -f $activeFrameCount)
$runArgs = @(
"run", "--rm", "--gpus", "all", "--network", "none", "--read-only",
"--security-opt", "no-new-privileges:true", "--cap-drop", "ALL",
"--pids-limit", "512", "--shm-size", "4g",
"--tmpfs", "/tmp:rw,noexec,nosuid,size=2g",
"-e", "PYTHONPATH=/opt/transformers:/opt/env",
"-e", "TORCH_HOME=/cache/torch",
"-e", "HF_HOME=/cache/huggingface",
"-e", "HF_HUB_OFFLINE=1",
"-e", "TRANSFORMERS_OFFLINE=1",
"-v", ((Convert-ToDockerPath $jobDirectory) + ":/job:ro"),
"-v", ((Convert-ToDockerPath $validFov) + ":/valid-fov:ro"),
"-v", ((Convert-ToDockerPath $framesRoot) + ":/frames:ro"),
"-v", ((Convert-ToDockerPath $workRoot) + ":/work:ro"),
"-v", ((Convert-ToDockerPath $publishRoot) + ":/publish:rw"),
"-v", ((Convert-ToDockerPath $cacheRoot) + ":/cache:ro"),
"-v", ((Convert-ToDockerPath $e3Environment) + ":/environment:ro"),
"-v", ((Convert-ToDockerPath $torchEnvironment) + ":/opt/env:ro"),
"-v", ((Convert-ToDockerPath $transformersEnvironment) + ":/opt/transformers:ro"),
"-v", ((Convert-ToDockerPath $runnerRoot) + ":/runner:ro"),
"--entrypoint", "python3",
$ContainerImage,
("/runner/{0}" -f $runnerName), "run",
"--job", "/job",
"--profile", ("/runner/{0}" -f $profileName),
"--valid-fov-root", "/valid-fov",
"--frames", "/frames",
"--timeline", "/work/timeline.jsonl",
"--cache", "/cache",
"--environment", "/environment",
"--output", "/publish/output",
"--frame-limit", [string]$activeFrameCount,
"--free-bytes-floor", [string]([int64]$FreeGiBFloor * 1GB),
"--orchestrator-sha256", $orchestratorSha256,
"--container-image", $ContainerImage,
"--telemetry-interval-seconds", "1"
)
Write-Output ("PHASE=e4-inference-start FRAMES={0}" -f $activeFrameCount)
& docker @runArgs
Assert-LastExitCode "LAB E4 semantic inference"
$freeBytesPostInference = Assert-FreeSpace "post-inference"
Write-Output "PHASE=e4-inference-complete"
if ($PilotFrames -gt 0) {
$pilotParent = Join-Path $derivedRoot "e4-pilots"
$null = New-Item -ItemType Directory -Path $pilotParent -Force
$pilotRoot = Join-Path $pilotParent ("pilot-{0}-{1}" -f $activeFrameCount, $runToken)
Move-Item -LiteralPath $stagingRoot -Destination $pilotRoot
Remove-Item -LiteralPath $publishRoot -Force
$completed = $true
Write-Output ("PILOT_ROOT={0}" -f $pilotRoot)
Write-Output ("PILOT_FRAMES={0}" -f $activeFrameCount)
Write-Output ("DISK_FREE_BYTES_BEFORE={0}" -f $freeBytesBefore)
Write-Output ("DISK_FREE_BYTES_POST_EXTRACT={0}" -f $freeBytesPostExtract)
Write-Output ("DISK_FREE_BYTES_POST_INFERENCE={0}" -f $freeBytesPostInference)
return
}
$videoPath = Join-Path $stagingRoot "perception.mp4"
$encodeWatch = [Diagnostics.Stopwatch]::StartNew()
$averageFps = $fullFrameCount / $timelineDuration
$fpsText = $averageFps.ToString("0.#########", [Globalization.CultureInfo]::InvariantCulture)
$durationText = $timelineDuration.ToString("0.#########", [Globalization.CultureInfo]::InvariantCulture)
& ffmpeg -hide_banner -loglevel error -framerate $fpsText -i (Join-Path $stagingRoot "overlay-frames\frame-%06d.png") -t $durationText -c:v h264_nvenc -preset p4 -tune hq -rc vbr -cq 21 -b:v 0 -pix_fmt yuv420p -movflags +faststart $videoPath
Assert-LastExitCode "LAB E4 video encoding"
$encodeWatch.Stop()
$null = Assert-FreeSpace "post-video-encoding"
Write-Output "PHASE=e4-video-encoding-complete"
$masksPath = Join-Path $stagingRoot "masks.tar.gz"
$archiveWatch = [Diagnostics.Stopwatch]::StartNew()
& tar.exe -czf $masksPath -C $stagingRoot semantic-masks
Assert-LastExitCode "LAB E4 mask archive publication"
$archiveWatch.Stop()
$freeBytesPostArtifacts = Assert-FreeSpace "post-mask-archive"
Write-Output "PHASE=e4-mask-archive-complete"
$totalWatch.Stop()
$finalizeArgs = @(
"run", "--rm", "--network", "none", "--read-only",
"--security-opt", "no-new-privileges:true", "--cap-drop", "ALL",
"--pids-limit", "128", "--tmpfs", "/tmp:rw,noexec,nosuid,size=256m",
"-e", "PYTHONPATH=/opt/transformers:/opt/env",
"-v", ((Convert-ToDockerPath $stagingRoot) + ":/output:rw"),
"-v", ((Convert-ToDockerPath $runnerRoot) + ":/runner:ro"),
"--entrypoint", "python3",
$ContainerImage,
("/runner/{0}" -f $runnerName), "finalize",
"--output", "/output",
"--video", "/output/perception.mp4",
"--masks", "/output/masks.tar.gz",
"--extract-seconds", $extractWatch.Elapsed.TotalSeconds.ToString("0.######", [Globalization.CultureInfo]::InvariantCulture),
"--encode-seconds", $encodeWatch.Elapsed.TotalSeconds.ToString("0.######", [Globalization.CultureInfo]::InvariantCulture),
"--archive-seconds", $archiveWatch.Elapsed.TotalSeconds.ToString("0.######", [Globalization.CultureInfo]::InvariantCulture),
"--wall-seconds", $totalWatch.Elapsed.TotalSeconds.ToString("0.######", [Globalization.CultureInfo]::InvariantCulture),
"--encoder", "ffmpeg-h264_nvenc-p4-cq21-yuv420p-faststart",
"--disk-free-before-bytes", [string]$freeBytesBefore,
"--disk-free-post-extract-bytes", [string]$freeBytesPostExtract,
"--disk-free-post-inference-bytes", [string]$freeBytesPostInference,
"--disk-free-post-artifacts-bytes", [string]$freeBytesPostArtifacts,
"--disk-floor-bytes", [string]([int64]$FreeGiBFloor * 1GB),
"--working-set-reserve-bytes", [string]$workingSetReserve
)
& docker @finalizeArgs
Assert-LastExitCode "LAB E4 result finalization"
$result = Get-Content -LiteralPath (Join-Path $stagingRoot "result.json") -Raw | ConvertFrom-Json
if (
$result.schema_version -ne "missioncore.recorded-perception-result/v2" -or
$result.result_id -notmatch "^result-[a-f0-9]{64}$" -or
[int]$result.frames_processed -ne $fullFrameCount -or
$result.ground_truth -ne $false
) {
throw "Final LAB E4 result manifest is incompatible"
}
$finalRoot = Join-Path $derivedRoot ([string]$result.result_id)
if (Test-Path -LiteralPath $finalRoot) {
throw "An immutable result with the same LAB E4 identity already exists: $finalRoot"
}
foreach ($temporaryChild in @("overlay-frames", "semantic-masks")) {
$temporaryPath = Join-Path $stagingRoot $temporaryChild
if (Test-Path -LiteralPath $temporaryPath) {
Remove-Item -LiteralPath $temporaryPath -Recurse -Force
}
}
Move-Item -LiteralPath $stagingRoot -Destination $finalRoot
Remove-Item -LiteralPath $publishRoot -Force
$completed = $true
$freeBytesFinal = Assert-FreeSpace "post-publication"
Write-Output ("RESULT_ROOT={0}" -f $finalRoot)
Write-Output ("RESULT_ID={0}" -f $result.result_id)
Write-Output ("DISK_FREE_BYTES_BEFORE={0}" -f $freeBytesBefore)
Write-Output ("DISK_FREE_BYTES_POST_EXTRACT={0}" -f $freeBytesPostExtract)
Write-Output ("DISK_FREE_BYTES_POST_INFERENCE={0}" -f $freeBytesPostInference)
Write-Output ("DISK_FREE_BYTES_POST_ARTIFACTS={0}" -f $freeBytesPostArtifacts)
Write-Output ("DISK_FREE_BYTES_FINAL={0}" -f $freeBytesFinal)
}
finally {
if (Test-Path -LiteralPath $workRoot) {
Remove-Item -LiteralPath $workRoot -Recurse -Force
}
if (-not $completed -and (Test-Path -LiteralPath $publishRoot)) {
Remove-Item -LiteralPath $publishRoot -Recurse -Force
}
}
@@ -0,0 +1,544 @@
[CmdletBinding()]
param(
[Parameter(Mandatory = $true)]
[string]$JobRoot,
[Parameter(Mandatory = $true)]
[string]$RunnerPath,
[Parameter(Mandatory = $true)]
[string]$ProfilePath,
[Parameter(Mandatory = $true)]
[string]$ValidFovRoot,
[ValidateRange(0, 1000000)]
[int]$StartFrame = 1000,
[ValidateRange(0, 1000000)]
[int]$EndFrame = 1600,
[ValidateRange(1, 1000)]
[int]$FreeGiBFloor = 360,
[string]$RuntimeRoot = "D:\NDC_MISSIONCORE\runtime",
[string]$ModelRoot = "D:\NDC_MISSIONCORE\runtime\models\yolox_s",
[string]$TritonContainer = "mission-core-triton",
[string]$ContainerImage = "nvcr.io/nvidia/tritonserver:26.06-py3"
)
$ErrorActionPreference = "Stop"
$ProgressPreference = "SilentlyContinue"
function Assert-LastExitCode {
param([string]$Operation)
if ($LASTEXITCODE -ne 0) {
throw "$Operation failed with exit code $LASTEXITCODE"
}
}
function Assert-RegularFile {
param([string]$Path, [string]$Label)
$item = Get-Item -LiteralPath $Path -Force
if (-not $item.PSIsContainer -and -not ($item.Attributes -band [IO.FileAttributes]::ReparsePoint)) {
return $item.FullName
}
throw "$Label is not a regular file"
}
function Assert-Directory {
param([string]$Path, [string]$Label)
$item = Get-Item -LiteralPath $Path -Force
if ($item.PSIsContainer -and -not ($item.Attributes -band [IO.FileAttributes]::ReparsePoint)) {
return $item.FullName
}
throw "$Label is not a real directory"
}
function Assert-DDrivePath {
param([string]$Path, [string]$Label)
$fullPath = [IO.Path]::GetFullPath($Path)
if ([IO.Path]::GetPathRoot($fullPath).TrimEnd("\") -ine "D:") {
throw "$Label must be stored on D:"
}
return $fullPath
}
function Get-DFreeBytes {
return [int64](Get-PSDrive -Name D).Free
}
function Assert-FreeSpace {
param(
[string]$Phase,
[int64]$RequiredAdditionalBytes = 0
)
$freeBytes = Get-DFreeBytes
$floorBytes = [int64]$FreeGiBFloor * 1GB
Write-Host (
"DISK_GUARD PHASE={0} DRIVE=D FREE_BYTES={1} FREE_GIB={2} FLOOR_GIB={3} REQUIRED_ADDITIONAL_GIB={4}" -f
$Phase,
$freeBytes,
[math]::Round($freeBytes / 1GB, 3),
$FreeGiBFloor,
[math]::Round($RequiredAdditionalBytes / 1GB, 3)
)
if ($freeBytes -lt ($floorBytes + $RequiredAdditionalBytes)) {
throw "D: does not have the guarded LAB E5 working-set reserve during $Phase"
}
return $freeBytes
}
function Convert-ToDockerPath {
param([string]$Path)
return $Path.Replace("\", "/")
}
function Test-TritonModelReady {
param([string]$ModelName)
try {
$response = Invoke-WebRequest `
-Uri ("http://127.0.0.1:8000/v2/models/{0}/ready" -f $ModelName) `
-Method Get `
-UseBasicParsing `
-TimeoutSec 10
return $response.StatusCode -eq 200
}
catch {
return $false
}
}
$jobDirectory = Assert-DDrivePath (
Assert-Directory (Resolve-Path -LiteralPath $JobRoot).Path "Job root"
) "Job root"
$runner = Assert-DDrivePath (
Assert-RegularFile (Resolve-Path -LiteralPath $RunnerPath).Path "LAB E5 runner"
) "LAB E5 runner"
$profile = Assert-DDrivePath (
Assert-RegularFile (Resolve-Path -LiteralPath $ProfilePath).Path "LAB E5 profile"
) "LAB E5 profile"
$validFov = Assert-DDrivePath (
Assert-Directory (Resolve-Path -LiteralPath $ValidFovRoot).Path "Valid-FOV root"
) "Valid-FOV root"
$runtime = Assert-DDrivePath (
Assert-Directory (Resolve-Path -LiteralPath $RuntimeRoot).Path "Runtime root"
) "Runtime root"
$model = Assert-DDrivePath (
Assert-Directory (Resolve-Path -LiteralPath $ModelRoot).Path "YOLOX model root"
) "YOLOX model root"
$runnerRoot = Split-Path $runner -Parent
if ((Split-Path $profile -Parent) -ne $runnerRoot) {
throw "LAB E5 runner and profile must share one read-only mount"
}
foreach ($dependency in @(
"run_recorded_perception_epoch.py",
"run_e3_rectified_segmentation.py",
"run_evaluation_prelabels.py"
)) {
$null = Assert-RegularFile (Join-Path $runnerRoot $dependency) "LAB E5 runner dependency"
}
$job = Get-Content -LiteralPath (Join-Path $jobDirectory "job.json") -Raw | ConvertFrom-Json
if ($job.schema_version -ne "missioncore.compute-job/v1" -or $job.job_id -ne (Split-Path $jobDirectory -Leaf)) {
throw "Compute job manifest is incompatible"
}
$sourceId = [string]$job.input.source_id
$epoch = [int]$job.input.codec_epoch
$fullFrameCount = [int]$job.input.segment_count
$clipFrameCount = $EndFrame - $StartFrame + 1
$timelineStart = [double]$job.input.timeline.start_seconds
if (
$sourceId -ne "sensor.camera.right" -or
$StartFrame -lt 0 -or
$EndFrame -lt $StartFrame -or
$EndFrame -ge $fullFrameCount -or
$clipFrameCount -lt 2
) {
throw "LAB E5 clip escapes the camera job"
}
Write-Output (
"PHASE=job-manifest-validated JOB={0} CLIP={1}-{2} FRAMES={3}" -f
$job.job_id, $StartFrame, $EndFrame, $clipFrameCount
)
$epochRoot = Join-Path $jobDirectory ("input\camera\{0}\epoch-{1}" -f $sourceId, $epoch)
$epochRoot = Assert-DDrivePath (Assert-Directory $epochRoot "Camera epoch") "Camera epoch"
$initPath = Assert-RegularFile (Join-Path $epochRoot "init.mp4") "Camera init"
$segmentsRoot = Assert-Directory (Join-Path $epochRoot "segments") "Camera segments"
$derivedRoot = Join-Path $runtime "derived"
$tmpRoot = Join-Path $runtime "tmp"
$pythonEnvironment = Assert-DDrivePath (
Assert-Directory (Join-Path $derivedRoot "perception-p0-env-v1") "Python environment"
) "Python environment"
$null = New-Item -ItemType Directory -Path $derivedRoot -Force
$null = New-Item -ItemType Directory -Path $tmpRoot -Force
# Conservative bound: partial reconstructed stream, decoded RGB PNG payload,
# RGB overlays, encoded result and 2 GiB of filesystem/codec overhead.
$pixelWorkingSet = [int64]$clipFrameCount * 800 * 600 * 6
$partialStreamReserve = [int64][math]::Ceiling(
([int64]$job.input.byte_length * ($EndFrame + 1) / $fullFrameCount) * 1.2
)
$workingSetReserve = [int64][math]::Ceiling($pixelWorkingSet * 1.4) + $partialStreamReserve + 2GB
$freeBytesBefore = Assert-FreeSpace "preflight" $workingSetReserve
& docker image inspect $ContainerImage *> $null
Assert-LastExitCode "Existing container image inspection"
$tritonState = docker inspect --format "{{.State.Running}}" $TritonContainer
Assert-LastExitCode "Triton container inspection"
if ($tritonState.Trim().ToLowerInvariant() -ne "true") {
throw "LAB E5 requires the existing Triton container"
}
$runnerName = Split-Path $runner -Leaf
$profileName = Split-Path $profile -Leaf
$orchestratorSha256 = (Get-FileHash -LiteralPath $PSCommandPath -Algorithm SHA256).Hash.ToLowerInvariant()
$preflightArgs = @(
"run", "--rm", "--network", "none", "--read-only",
"--security-opt", "no-new-privileges:true", "--cap-drop", "ALL",
"--pids-limit", "128", "--tmpfs", "/tmp:rw,noexec,nosuid,size=256m",
"-e", "PYTHONPATH=/runner:/opt/env",
"-v", ((Convert-ToDockerPath $jobDirectory) + ":/job:ro"),
"-v", ((Convert-ToDockerPath $validFov) + ":/valid-fov:ro"),
"-v", ((Convert-ToDockerPath $model) + ":/model:ro"),
"-v", ((Convert-ToDockerPath $pythonEnvironment) + ":/opt/env:ro"),
"-v", ((Convert-ToDockerPath $runnerRoot) + ":/runner:ro"),
"--entrypoint", "python3",
$ContainerImage,
("/runner/{0}" -f $runnerName), "preflight",
"--job", "/job",
"--profile", ("/runner/{0}" -f $profileName),
"--valid-fov-root", "/valid-fov",
"--model-root", "/model"
)
Write-Output "PHASE=e5-preflight-start"
& docker @preflightArgs
Assert-LastExitCode "LAB E5 preflight"
Write-Output "PHASE=e5-preflight-complete"
$modelWasReady = Test-TritonModelReady "yolox_s"
$loadedByRun = $false
if (-not $modelWasReady) {
Invoke-WebRequest `
-Uri "http://127.0.0.1:8000/v2/repository/models/yolox_s/load" `
-Method Post `
-ContentType "application/json" `
-Body "{}" `
-UseBasicParsing `
-TimeoutSec 60 *> $null
$loadedByRun = $true
$deadline = [DateTime]::UtcNow.AddSeconds(60)
while (-not (Test-TritonModelReady "yolox_s")) {
if ([DateTime]::UtcNow -ge $deadline) {
throw "YOLOX-S did not become ready in Triton"
}
Start-Sleep -Milliseconds 500
}
}
Write-Output ("PHASE=e5-model-ready LOADED_BY_RUN={0}" -f $loadedByRun)
$runToken = [Guid]::NewGuid().ToString("N")
$workRoot = Join-Path $tmpRoot ("{0}-e5-{1}" -f $job.job_id, $runToken)
$framesRoot = Join-Path $workRoot "frames"
$streamPath = Join-Path $workRoot "camera.mp4"
$ptsPath = Join-Path $workRoot "pts.json"
$timelinePath = Join-Path $workRoot "timeline.jsonl"
$publishRoot = Join-Path $derivedRoot (".{0}-e5-{1}.publish" -f $job.job_id, $runToken)
$stagingRoot = Join-Path $publishRoot "output"
$null = New-Item -ItemType Directory -Path $framesRoot
$null = New-Item -ItemType Directory -Path $publishRoot
$totalWatch = [Diagnostics.Stopwatch]::StartNew()
$completed = $false
Write-Output "PHASE=e5-private-staging-created"
try {
$stream = [IO.File]::Open(
$streamPath,
[IO.FileMode]::CreateNew,
[IO.FileAccess]::Write,
[IO.FileShare]::None
)
try {
$input = [IO.File]::OpenRead($initPath)
try {
$input.CopyTo($stream)
}
finally {
$input.Dispose()
}
for ($sequence = 1; $sequence -le ($EndFrame + 1); $sequence++) {
$path = Assert-RegularFile (
Join-Path $segmentsRoot ("{0}.m4s" -f $sequence)
) "Camera segment"
$input = [IO.File]::OpenRead($path)
try {
$input.CopyTo($stream)
}
finally {
$input.Dispose()
}
if ($sequence % 500 -eq 0 -or $sequence -eq ($EndFrame + 1)) {
Write-Output (
"PHASE=e5-stream-reconstruction SEGMENTS={0}/{1}" -f
$sequence, ($EndFrame + 1)
)
}
}
$stream.Flush($true)
}
finally {
$stream.Dispose()
}
$null = Assert-FreeSpace "post-stream-reconstruction"
$extractWatch = [Diagnostics.Stopwatch]::StartNew()
Write-Output "PHASE=e5-frame-extraction-start"
$selectFilter = "select='between(n,{0},{1})'" -f $StartFrame, $EndFrame
& ffmpeg `
-hide_banner -loglevel fatal `
-i $streamPath `
-map 0:v:0 `
-vf $selectFilter `
-fps_mode passthrough `
(Join-Path $framesRoot "frame-%06d.png")
Assert-LastExitCode "LAB E5 camera clip extraction"
& ffprobe `
-v error `
-select_streams v:0 `
-show_entries frame=best_effort_timestamp_time `
-of json `
$streamPath | Set-Content -LiteralPath $ptsPath -Encoding utf8
Assert-LastExitCode "LAB E5 camera timestamp probe"
$decodedFrames = @(Get-ChildItem -LiteralPath $framesRoot -File -Filter "frame-*.png")
$ptsDocument = Get-Content -LiteralPath $ptsPath -Raw | ConvertFrom-Json
$pts = @($ptsDocument.frames)
if ($decodedFrames.Count -ne $clipFrameCount -or $pts.Count -ne ($EndFrame + 1)) {
throw "Decoded LAB E5 frame/timestamp count differs from the selected clip"
}
$firstEpochSeconds = [double]::Parse(
([string]$pts[0].best_effort_timestamp_time).Trim(),
[Globalization.CultureInfo]::InvariantCulture
)
$previousSessionSeconds = -1.0
$timelineWriter = [IO.StreamWriter]::new(
$timelinePath,
$false,
[Text.UTF8Encoding]::new($false)
)
try {
for ($localIndex = 0; $localIndex -lt $clipFrameCount; $localIndex++) {
$sourceIndex = $StartFrame + $localIndex
$epochSeconds = [double]::Parse(
([string]$pts[$sourceIndex].best_effort_timestamp_time).Trim(),
[Globalization.CultureInfo]::InvariantCulture
) - $firstEpochSeconds
$sessionSeconds = $timelineStart + $epochSeconds
if ($sessionSeconds -le $previousSessionSeconds) {
throw "Decoded LAB E5 clip timestamps are not strictly monotonic"
}
$row = [ordered]@{
frame_index = $localIndex
sequence = $localIndex + 1
source_frame_index = $sourceIndex
source_sequence = $sourceIndex + 1
epoch_seconds = $epochSeconds
session_seconds = $sessionSeconds
}
$timelineWriter.WriteLine(($row | ConvertTo-Json -Compress))
$previousSessionSeconds = $sessionSeconds
}
$timelineWriter.Flush()
}
finally {
$timelineWriter.Dispose()
}
$extractWatch.Stop()
$freeBytesPostExtract = Assert-FreeSpace "post-frame-extraction"
Write-Output ("PHASE=e5-frame-extraction-complete FRAMES={0}" -f $clipFrameCount)
$runArgs = @(
"run", "--rm", "--gpus", "all",
"--network", ("container:{0}" -f $TritonContainer),
"--read-only",
"--security-opt", "no-new-privileges:true", "--cap-drop", "ALL",
"--pids-limit", "256", "--shm-size", "1g",
"--tmpfs", "/tmp:rw,noexec,nosuid,size=512m",
"-e", "PYTHONPATH=/runner:/opt/env",
"-v", ((Convert-ToDockerPath $jobDirectory) + ":/job:ro"),
"-v", ((Convert-ToDockerPath $validFov) + ":/valid-fov:ro"),
"-v", ((Convert-ToDockerPath $model) + ":/model:ro"),
"-v", ((Convert-ToDockerPath $pythonEnvironment) + ":/opt/env:ro"),
"-v", ((Convert-ToDockerPath $framesRoot) + ":/frames:ro"),
"-v", ((Convert-ToDockerPath $workRoot) + ":/work:ro"),
"-v", ((Convert-ToDockerPath $publishRoot) + ":/publish:rw"),
"-v", ((Convert-ToDockerPath $runnerRoot) + ":/runner:ro"),
"--entrypoint", "python3",
$ContainerImage,
("/runner/{0}" -f $runnerName), "run",
"--job", "/job",
"--profile", ("/runner/{0}" -f $profileName),
"--valid-fov-root", "/valid-fov",
"--model-root", "/model",
"--frames", "/frames",
"--timeline", "/work/timeline.jsonl",
"--output", "/publish/output",
"--triton-url", "http://127.0.0.1:8000",
"--free-bytes-floor", [string]([int64]$FreeGiBFloor * 1GB),
"--orchestrator-sha256", $orchestratorSha256,
"--container-image", $ContainerImage,
"--telemetry-interval-seconds", "1"
)
Write-Output ("PHASE=e5-inference-start FRAMES={0}" -f $clipFrameCount)
& docker @runArgs
Assert-LastExitCode "LAB E5 detector/tracker inference"
$freeBytesPostInference = Assert-FreeSpace "post-inference"
Write-Output "PHASE=e5-inference-complete"
$timelineRows = @(Get-Content -LiteralPath $timelinePath | ForEach-Object {
$_ | ConvertFrom-Json
})
$clipSpanSeconds = [double]$timelineRows[-1].session_seconds - [double]$timelineRows[0].session_seconds
if ($clipSpanSeconds -le 0) {
throw "LAB E5 clip duration is invalid"
}
$averageFps = ($clipFrameCount - 1) / $clipSpanSeconds
$fpsText = $averageFps.ToString("0.#########", [Globalization.CultureInfo]::InvariantCulture)
$videoPath = Join-Path $stagingRoot "tracking.mp4"
$encodeWatch = [Diagnostics.Stopwatch]::StartNew()
& ffmpeg `
-hide_banner -loglevel error `
-framerate $fpsText `
-i (Join-Path $stagingRoot "overlay-frames\frame-%06d.png") `
-c:v h264_nvenc `
-preset p4 `
-tune hq `
-rc vbr `
-cq 21 `
-b:v 0 `
-pix_fmt yuv420p `
-movflags +faststart `
$videoPath
Assert-LastExitCode "LAB E5 video encoding"
$encodeWatch.Stop()
Write-Output "PHASE=e5-video-encoding-complete"
$contactSheetPath = Join-Path $stagingRoot "contact-sheet.png"
$tileColumns = if ($clipFrameCount -le 60) { 4 } else { 3 }
$tileRows = 2
$sampleInterval = [math]::Max(0.25, $clipSpanSeconds / ($tileColumns * $tileRows))
$sampleText = $sampleInterval.ToString("0.######", [Globalization.CultureInfo]::InvariantCulture)
$contactFilter = "fps=1/{0},scale=400:-1,tile={1}x{2}:padding=8:margin=8:color=black" -f `
$sampleText, $tileColumns, $tileRows
& ffmpeg `
-hide_banner -loglevel error `
-i $videoPath `
-vf $contactFilter `
-frames:v 1 `
$contactSheetPath
Assert-LastExitCode "LAB E5 contact-sheet generation"
$probe = & ffprobe `
-v error `
-select_streams v:0 `
-count_frames `
-show_entries stream=codec_name,width,height,nb_read_frames `
-of json `
$videoPath | ConvertFrom-Json
Assert-LastExitCode "LAB E5 result video probe"
$videoStream = @($probe.streams)[0]
if (
$videoStream.codec_name -ne "h264" -or
[int]$videoStream.width -ne 800 -or
[int]$videoStream.height -ne 600 -or
[int]$videoStream.nb_read_frames -ne $clipFrameCount
) {
throw "LAB E5 result video contract changed"
}
$freeBytesPostArtifacts = Assert-FreeSpace "post-artifacts"
$totalWatch.Stop()
$finalizeArgs = @(
"run", "--rm", "--network", "none", "--read-only",
"--security-opt", "no-new-privileges:true", "--cap-drop", "ALL",
"--pids-limit", "128", "--tmpfs", "/tmp:rw,noexec,nosuid,size=256m",
"-e", "PYTHONPATH=/runner",
"-v", ((Convert-ToDockerPath $stagingRoot) + ":/output:rw"),
"-v", ((Convert-ToDockerPath $runnerRoot) + ":/runner:ro"),
"--entrypoint", "python3",
$ContainerImage,
("/runner/{0}" -f $runnerName), "finalize",
"--output", "/output",
"--video", "/output/tracking.mp4",
"--contact-sheet", "/output/contact-sheet.png",
"--extract-seconds", $extractWatch.Elapsed.TotalSeconds.ToString("0.######", [Globalization.CultureInfo]::InvariantCulture),
"--encode-seconds", $encodeWatch.Elapsed.TotalSeconds.ToString("0.######", [Globalization.CultureInfo]::InvariantCulture),
"--wall-seconds", $totalWatch.Elapsed.TotalSeconds.ToString("0.######", [Globalization.CultureInfo]::InvariantCulture),
"--encoder", "ffmpeg-h264_nvenc-p4-cq21-yuv420p-faststart",
"--disk-free-before-bytes", [string]$freeBytesBefore,
"--disk-free-post-extract-bytes", [string]$freeBytesPostExtract,
"--disk-free-post-inference-bytes", [string]$freeBytesPostInference,
"--disk-free-post-artifacts-bytes", [string]$freeBytesPostArtifacts,
"--disk-floor-bytes", [string]([int64]$FreeGiBFloor * 1GB),
"--working-set-reserve-bytes", [string]$workingSetReserve
)
& docker @finalizeArgs
Assert-LastExitCode "LAB E5 result finalization"
$result = Get-Content -LiteralPath (Join-Path $stagingRoot "result.json") -Raw | ConvertFrom-Json
if (
$result.schema_version -ne "missioncore.e5-tracking-result/v1" -or
$result.result_id -notmatch "^e5-tracking-[a-f0-9]{64}$" -or
[int]$result.frames_processed -ne $clipFrameCount -or
$result.ground_truth -ne $false -or
$result.publication_scope -ne "qualification-clip-only"
) {
throw "Final LAB E5 result manifest is incompatible"
}
$finalRoot = Join-Path $derivedRoot ([string]$result.result_id)
if (Test-Path -LiteralPath $finalRoot) {
throw "An immutable result with the same LAB E5 identity already exists: $finalRoot"
}
$overlayFrames = Join-Path $stagingRoot "overlay-frames"
if (Test-Path -LiteralPath $overlayFrames) {
Remove-Item -LiteralPath $overlayFrames -Recurse -Force
}
Move-Item -LiteralPath $stagingRoot -Destination $finalRoot
Remove-Item -LiteralPath $publishRoot -Force
$completed = $true
$freeBytesFinal = Assert-FreeSpace "post-publication"
Write-Output ("RESULT_ROOT={0}" -f $finalRoot)
Write-Output ("RESULT_ID={0}" -f $result.result_id)
Write-Output ("DISK_FREE_BYTES_BEFORE={0}" -f $freeBytesBefore)
Write-Output ("DISK_FREE_BYTES_POST_EXTRACT={0}" -f $freeBytesPostExtract)
Write-Output ("DISK_FREE_BYTES_POST_INFERENCE={0}" -f $freeBytesPostInference)
Write-Output ("DISK_FREE_BYTES_POST_ARTIFACTS={0}" -f $freeBytesPostArtifacts)
Write-Output ("DISK_FREE_BYTES_FINAL={0}" -f $freeBytesFinal)
}
finally {
if (Test-Path -LiteralPath $workRoot) {
Remove-Item -LiteralPath $workRoot -Recurse -Force
}
if (-not $completed -and (Test-Path -LiteralPath $publishRoot)) {
Remove-Item -LiteralPath $publishRoot -Recurse -Force
}
if ($loadedByRun) {
try {
Invoke-WebRequest `
-Uri "http://127.0.0.1:8000/v2/repository/models/yolox_s/unload" `
-Method Post `
-ContentType "application/json" `
-Body "{}" `
-UseBasicParsing `
-TimeoutSec 60 *> $null
Write-Output "PHASE=e5-model-state-restored"
}
catch {
Write-Warning "LAB E5 could not restore the prior unloaded YOLOX-S state"
}
}
}
@@ -0,0 +1,411 @@
[CmdletBinding()]
param(
[Parameter(Mandatory = $true)]
[string]$JobRoot,
[Parameter(Mandatory = $true)]
[string]$RunnerPath,
[Parameter(Mandatory = $true)]
[string]$ProfilePath,
[Parameter(Mandatory = $true)]
[string]$ValidFovRoot,
[ValidateRange(0, 1000000)]
[int]$StartFrame = 1000,
[ValidateRange(0, 1000000)]
[int]$EndFrame = 1600,
[ValidateRange(1, 1000)]
[int]$FreeGiBFloor = 360,
[string]$RuntimeRoot = "D:\NDC_MISSIONCORE\runtime",
[string]$ModelRoot = "D:\NDC_MISSIONCORE\runtime\models\yolox_s",
[string]$TritonContainer = "mission-core-triton",
[string]$ContainerImage = "nvcr.io/nvidia/tritonserver:26.06-py3"
)
$ErrorActionPreference = "Stop"
$ProgressPreference = "SilentlyContinue"
function Assert-LastExitCode {
param([string]$Operation)
if ($LASTEXITCODE -ne 0) {
throw "$Operation failed with exit code $LASTEXITCODE"
}
}
function Assert-RegularFile {
param([string]$Path, [string]$Label)
$item = Get-Item -LiteralPath $Path -Force
if (-not $item.PSIsContainer -and -not ($item.Attributes -band [IO.FileAttributes]::ReparsePoint)) {
return $item.FullName
}
throw "$Label is not a regular file"
}
function Assert-Directory {
param([string]$Path, [string]$Label)
$item = Get-Item -LiteralPath $Path -Force
if ($item.PSIsContainer -and -not ($item.Attributes -band [IO.FileAttributes]::ReparsePoint)) {
return $item.FullName
}
throw "$Label is not a real directory"
}
function Assert-DDrivePath {
param([string]$Path, [string]$Label)
$fullPath = [IO.Path]::GetFullPath($Path)
if ([IO.Path]::GetPathRoot($fullPath).TrimEnd("\") -ine "D:") {
throw "$Label must be stored on D:"
}
return $fullPath
}
function Convert-ToDockerPath {
param([string]$Path)
return $Path.Replace("\", "/")
}
function Get-DFreeBytes {
return [int64](Get-PSDrive -Name D).Free
}
function Assert-FreeSpace {
param([string]$Phase, [int64]$RequiredAdditionalBytes = 0)
$freeBytes = Get-DFreeBytes
$floorBytes = [int64]$FreeGiBFloor * 1GB
Write-Host (
"DISK_GUARD PHASE={0} DRIVE=D FREE_BYTES={1} FREE_GIB={2} FLOOR_GIB={3} REQUIRED_ADDITIONAL_GIB={4}" -f
$Phase,
$freeBytes,
[math]::Round($freeBytes / 1GB, 3),
$FreeGiBFloor,
[math]::Round($RequiredAdditionalBytes / 1GB, 3)
)
if ($freeBytes -lt ($floorBytes + $RequiredAdditionalBytes)) {
throw "D: does not have the guarded LAB E8 working-set reserve during $Phase"
}
return $freeBytes
}
function Test-TritonModelReady {
try {
$response = Invoke-WebRequest `
-Uri "http://127.0.0.1:8000/v2/models/yolox_s/ready" `
-Method Get -UseBasicParsing -TimeoutSec 10
return $response.StatusCode -eq 200
}
catch {
return $false
}
}
$jobDirectory = Assert-DDrivePath (
Assert-Directory (Resolve-Path -LiteralPath $JobRoot).Path "Job root"
) "Job root"
$runner = Assert-DDrivePath (
Assert-RegularFile (Resolve-Path -LiteralPath $RunnerPath).Path "LAB E8 runner"
) "LAB E8 runner"
$profile = Assert-DDrivePath (
Assert-RegularFile (Resolve-Path -LiteralPath $ProfilePath).Path "LAB E8 profile"
) "LAB E8 profile"
$validFov = Assert-DDrivePath (
Assert-Directory (Resolve-Path -LiteralPath $ValidFovRoot).Path "Valid-FOV root"
) "Valid-FOV root"
$runtime = Assert-DDrivePath (
Assert-Directory (Resolve-Path -LiteralPath $RuntimeRoot).Path "Runtime root"
) "Runtime root"
$model = Assert-DDrivePath (
Assert-Directory (Resolve-Path -LiteralPath $ModelRoot).Path "YOLOX model root"
) "YOLOX model root"
$runnerRoot = Split-Path $runner -Parent
if ((Split-Path $profile -Parent) -ne $runnerRoot) {
throw "LAB E8 runner and profile must share one read-only mount"
}
foreach ($dependency in @(
"run_e5_instance_tracking.py",
"run_recorded_perception_epoch.py",
"run_e3_rectified_segmentation.py",
"run_evaluation_prelabels.py"
)) {
$null = Assert-RegularFile (Join-Path $runnerRoot $dependency) "LAB E8 runner dependency"
}
$job = Get-Content -LiteralPath (Join-Path $jobDirectory "job.json") -Raw | ConvertFrom-Json
if ($job.schema_version -ne "missioncore.compute-job/v1" -or $job.job_id -ne (Split-Path $jobDirectory -Leaf)) {
throw "Compute job manifest is incompatible"
}
$sourceId = [string]$job.input.source_id
$epoch = [int]$job.input.codec_epoch
$fullFrameCount = [int]$job.input.segment_count
$clipFrameCount = $EndFrame - $StartFrame + 1
$timelineStart = [double]$job.input.timeline.start_seconds
if (
$sourceId -ne "sensor.camera.right" -or
$StartFrame -lt 0 -or
$EndFrame -lt $StartFrame -or
$EndFrame -ge $fullFrameCount -or
$clipFrameCount -lt 2
) {
throw "LAB E8 clip escapes the camera job"
}
Write-Output (
"PHASE=job-manifest-validated JOB={0} CLIP={1}-{2} FRAMES={3}" -f
$job.job_id, $StartFrame, $EndFrame, $clipFrameCount
)
$epochRoot = Assert-DDrivePath (
Assert-Directory (
Join-Path $jobDirectory ("input\camera\{0}\epoch-{1}" -f $sourceId, $epoch)
) "Camera epoch"
) "Camera epoch"
$initPath = Assert-RegularFile (Join-Path $epochRoot "init.mp4") "Camera init"
$segmentsRoot = Assert-Directory (Join-Path $epochRoot "segments") "Camera segments"
$derivedRoot = Join-Path $runtime "derived"
$tmpRoot = Join-Path $runtime "tmp"
$pythonEnvironment = Assert-DDrivePath (
Assert-Directory (Join-Path $derivedRoot "perception-p0-env-v1") "Python environment"
) "Python environment"
$null = New-Item -ItemType Directory -Path $derivedRoot -Force
$null = New-Item -ItemType Directory -Path $tmpRoot -Force
# LAB E8 has temporary decoded input but no per-frame output images. Reserve
# decoded RGB payload, partial stream and two GiB for filesystem/codec overhead.
$pixelWorkingSet = [int64]$clipFrameCount * 800 * 600 * 3
$partialStreamReserve = [int64][math]::Ceiling(
([int64]$job.input.byte_length * ($EndFrame + 1) / $fullFrameCount) * 1.2
)
$workingSetReserve = [int64][math]::Ceiling($pixelWorkingSet * 1.4) + $partialStreamReserve + 2GB
$freeBytesBefore = Assert-FreeSpace "preflight" $workingSetReserve
& docker image inspect $ContainerImage *> $null
Assert-LastExitCode "Existing container image inspection"
$tritonState = docker inspect --format "{{.State.Running}}" $TritonContainer
Assert-LastExitCode "Triton container inspection"
if ($tritonState.Trim().ToLowerInvariant() -ne "true") {
throw "LAB E8 requires the existing Triton container"
}
$runnerName = Split-Path $runner -Leaf
$profileName = Split-Path $profile -Leaf
$orchestratorSha256 = (Get-FileHash -LiteralPath $PSCommandPath -Algorithm SHA256).Hash.ToLowerInvariant()
$preflightArgs = @(
"run", "--rm", "--network", "none", "--read-only",
"--security-opt", "no-new-privileges:true", "--cap-drop", "ALL",
"--pids-limit", "128", "--tmpfs", "/tmp:rw,noexec,nosuid,size=256m",
"-e", "PYTHONPATH=/runner:/opt/env",
"-v", ((Convert-ToDockerPath $jobDirectory) + ":/job:ro"),
"-v", ((Convert-ToDockerPath $validFov) + ":/valid-fov:ro"),
"-v", ((Convert-ToDockerPath $model) + ":/model:ro"),
"-v", ((Convert-ToDockerPath $pythonEnvironment) + ":/opt/env:ro"),
"-v", ((Convert-ToDockerPath $runnerRoot) + ":/runner:ro"),
"--entrypoint", "python3", $ContainerImage,
("/runner/{0}" -f $runnerName), "preflight",
"--job", "/job",
"--profile", ("/runner/{0}" -f $profileName),
"--valid-fov-root", "/valid-fov",
"--model-root", "/model"
)
Write-Output "PHASE=e8-preflight-start"
& docker @preflightArgs
Assert-LastExitCode "LAB E8 preflight"
Write-Output "PHASE=e8-preflight-complete"
$modelWasReady = Test-TritonModelReady
$loadedByRun = $false
if (-not $modelWasReady) {
Invoke-WebRequest `
-Uri "http://127.0.0.1:8000/v2/repository/models/yolox_s/load" `
-Method Post -ContentType "application/json" -Body "{}" `
-UseBasicParsing -TimeoutSec 60 *> $null
$loadedByRun = $true
$deadline = [DateTime]::UtcNow.AddSeconds(60)
while (-not (Test-TritonModelReady)) {
if ([DateTime]::UtcNow -ge $deadline) {
throw "YOLOX-S did not become ready in Triton"
}
Start-Sleep -Milliseconds 500
}
}
Write-Output ("PHASE=e8-model-ready LOADED_BY_RUN={0}" -f $loadedByRun)
$runToken = [Guid]::NewGuid().ToString("N")
$workRoot = Join-Path $tmpRoot ("{0}-e8-{1}" -f $job.job_id, $runToken)
$framesRoot = Join-Path $workRoot "frames"
$streamPath = Join-Path $workRoot "camera.mp4"
$ptsPath = Join-Path $workRoot "pts.json"
$timelinePath = Join-Path $workRoot "timeline.jsonl"
$publishRoot = Join-Path $derivedRoot (".{0}-e8-{1}.publish" -f $job.job_id, $runToken)
$stagingRoot = Join-Path $publishRoot "output"
$null = New-Item -ItemType Directory -Path $framesRoot
$null = New-Item -ItemType Directory -Path $publishRoot
$totalWatch = [Diagnostics.Stopwatch]::StartNew()
$completed = $false
Write-Output "PHASE=e8-private-staging-created"
try {
$stream = [IO.File]::Open(
$streamPath, [IO.FileMode]::CreateNew, [IO.FileAccess]::Write, [IO.FileShare]::None
)
try {
$input = [IO.File]::OpenRead($initPath)
try { $input.CopyTo($stream) } finally { $input.Dispose() }
for ($sequence = 1; $sequence -le ($EndFrame + 1); $sequence++) {
$path = Assert-RegularFile (
Join-Path $segmentsRoot ("{0}.m4s" -f $sequence)
) "Camera segment"
$input = [IO.File]::OpenRead($path)
try { $input.CopyTo($stream) } finally { $input.Dispose() }
}
$stream.Flush($true)
}
finally {
$stream.Dispose()
}
$null = Assert-FreeSpace "post-stream-reconstruction"
$extractWatch = [Diagnostics.Stopwatch]::StartNew()
Write-Output "PHASE=e8-frame-extraction-start"
$selectFilter = "select='between(n,{0},{1})'" -f $StartFrame, $EndFrame
& ffmpeg -hide_banner -loglevel fatal -i $streamPath -map 0:v:0 `
-vf $selectFilter -fps_mode passthrough (Join-Path $framesRoot "frame-%06d.png")
Assert-LastExitCode "LAB E8 camera clip extraction"
& ffprobe -v error -select_streams v:0 `
-show_entries frame=best_effort_timestamp_time -of json $streamPath |
Set-Content -LiteralPath $ptsPath -Encoding utf8
Assert-LastExitCode "LAB E8 camera timestamp probe"
$decodedFrames = @(Get-ChildItem -LiteralPath $framesRoot -File -Filter "frame-*.png")
$ptsDocument = Get-Content -LiteralPath $ptsPath -Raw | ConvertFrom-Json
$pts = @($ptsDocument.frames)
if ($decodedFrames.Count -ne $clipFrameCount -or $pts.Count -ne ($EndFrame + 1)) {
throw "Decoded LAB E8 frame/timestamp count differs from the selected clip"
}
$firstEpochSeconds = [double]::Parse(
([string]$pts[0].best_effort_timestamp_time).Trim(),
[Globalization.CultureInfo]::InvariantCulture
)
$previousSessionSeconds = -1.0
$timelineWriter = [IO.StreamWriter]::new(
$timelinePath, $false, [Text.UTF8Encoding]::new($false)
)
try {
for ($localIndex = 0; $localIndex -lt $clipFrameCount; $localIndex++) {
$sourceIndex = $StartFrame + $localIndex
$epochSeconds = [double]::Parse(
([string]$pts[$sourceIndex].best_effort_timestamp_time).Trim(),
[Globalization.CultureInfo]::InvariantCulture
) - $firstEpochSeconds
$sessionSeconds = $timelineStart + $epochSeconds
if ($sessionSeconds -le $previousSessionSeconds) {
throw "Decoded LAB E8 clip timestamps are not strictly monotonic"
}
$row = [ordered]@{
frame_index = $localIndex
sequence = $localIndex + 1
source_frame_index = $sourceIndex
source_sequence = $sourceIndex + 1
epoch_seconds = $epochSeconds
session_seconds = $sessionSeconds
}
$timelineWriter.WriteLine(($row | ConvertTo-Json -Compress))
$previousSessionSeconds = $sessionSeconds
}
$timelineWriter.Flush()
}
finally {
$timelineWriter.Dispose()
}
$extractWatch.Stop()
$freeBytesPostExtract = Assert-FreeSpace "post-frame-extraction"
Write-Output ("PHASE=e8-frame-extraction-complete FRAMES={0}" -f $clipFrameCount)
$runArgs = @(
"run", "--rm", "--gpus", "all",
"--network", ("container:{0}" -f $TritonContainer),
"--read-only", "--security-opt", "no-new-privileges:true", "--cap-drop", "ALL",
"--pids-limit", "256", "--shm-size", "1g",
"--tmpfs", "/tmp:rw,noexec,nosuid,size=512m",
"-e", "PYTHONPATH=/runner:/opt/env",
"-v", ((Convert-ToDockerPath $jobDirectory) + ":/job:ro"),
"-v", ((Convert-ToDockerPath $validFov) + ":/valid-fov:ro"),
"-v", ((Convert-ToDockerPath $model) + ":/model:ro"),
"-v", ((Convert-ToDockerPath $pythonEnvironment) + ":/opt/env:ro"),
"-v", ((Convert-ToDockerPath $framesRoot) + ":/frames:ro"),
"-v", ((Convert-ToDockerPath $workRoot) + ":/work:ro"),
"-v", ((Convert-ToDockerPath $publishRoot) + ":/publish:rw"),
"-v", ((Convert-ToDockerPath $runnerRoot) + ":/runner:ro"),
"--entrypoint", "python3", $ContainerImage,
("/runner/{0}" -f $runnerName), "run",
"--job", "/job",
"--profile", ("/runner/{0}" -f $profileName),
"--valid-fov-root", "/valid-fov",
"--model-root", "/model",
"--frames", "/frames",
"--timeline", "/work/timeline.jsonl",
"--output", "/publish/output",
"--triton-url", "http://127.0.0.1:8000",
"--free-bytes-floor", [string]([int64]$FreeGiBFloor * 1GB),
"--orchestrator-sha256", $orchestratorSha256,
"--container-image", $ContainerImage,
"--telemetry-interval-seconds", "1"
)
Write-Output ("PHASE=e8-source-paced-replay-start FRAMES={0}" -f $clipFrameCount)
& docker @runArgs
Assert-LastExitCode "LAB E8 source-paced detector/tracker"
$freeBytesPostReplay = Assert-FreeSpace "post-replay"
Write-Output "PHASE=e8-source-paced-replay-complete"
$result = Get-Content -LiteralPath (Join-Path $stagingRoot "result.json") -Raw | ConvertFrom-Json
if (
$result.schema_version -ne "missioncore.e8-realtime-tracking-result/v1" -or
$result.result_id -notmatch "^e8-realtime-tracking-[a-f0-9]{64}$" -or
$result.acceptance_state -ne "accepted" -or
$result.ground_truth -ne $false
) {
throw "Final LAB E8 result manifest is incompatible or rejected"
}
$finalRoot = Join-Path $derivedRoot ([string]$result.result_id)
if (Test-Path -LiteralPath $finalRoot) {
throw "An immutable result with the same LAB E8 identity already exists: $finalRoot"
}
Move-Item -LiteralPath $stagingRoot -Destination $finalRoot
Remove-Item -LiteralPath $publishRoot -Force
$totalWatch.Stop()
$completed = $true
$freeBytesFinal = Assert-FreeSpace "post-publication"
Write-Output ("RESULT_ROOT={0}" -f $finalRoot)
Write-Output ("RESULT_ID={0}" -f $result.result_id)
Write-Output ("PREPARATION_SECONDS={0}" -f $extractWatch.Elapsed.TotalSeconds)
Write-Output ("ORCHESTRATOR_WALL_SECONDS={0}" -f $totalWatch.Elapsed.TotalSeconds)
Write-Output ("DISK_FREE_BYTES_BEFORE={0}" -f $freeBytesBefore)
Write-Output ("DISK_FREE_BYTES_POST_EXTRACT={0}" -f $freeBytesPostExtract)
Write-Output ("DISK_FREE_BYTES_POST_REPLAY={0}" -f $freeBytesPostReplay)
Write-Output ("DISK_FREE_BYTES_FINAL={0}" -f $freeBytesFinal)
}
finally {
if (Test-Path -LiteralPath $workRoot) {
Remove-Item -LiteralPath $workRoot -Recurse -Force
}
if (-not $completed -and (Test-Path -LiteralPath $publishRoot)) {
Remove-Item -LiteralPath $publishRoot -Recurse -Force
}
if ($loadedByRun) {
try {
Invoke-WebRequest `
-Uri "http://127.0.0.1:8000/v2/repository/models/yolox_s/unload" `
-Method Post -ContentType "application/json" -Body "{}" `
-UseBasicParsing -TimeoutSec 60 *> $null
Write-Output "PHASE=e8-model-state-restored"
}
catch {
Write-Warning "LAB E8 could not restore the prior unloaded YOLOX-S state"
}
}
}
@@ -0,0 +1,349 @@
[CmdletBinding()]
param(
[Parameter(Mandatory = $true)] [string]$JobRoot,
[Parameter(Mandatory = $true)] [string]$RunnerPath,
[Parameter(Mandatory = $true)] [string]$ProfilePath,
[Parameter(Mandatory = $true)] [string]$DetectorProfilePath,
[Parameter(Mandatory = $true)] [string]$SemanticProfilePath,
[Parameter(Mandatory = $true)] [string]$ValidFovRoot,
[ValidateRange(0, 1000000)] [int]$StartFrame = 1000,
[ValidateRange(0, 1000000)] [int]$EndFrame = 1600,
[ValidateRange(1, 1000)] [int]$FreeGiBFloor = 360,
[string]$RuntimeRoot = "D:\NDC_MISSIONCORE\runtime",
[string]$ModelRoot = "D:\NDC_MISSIONCORE\runtime\models\yolox_s",
[string]$TritonContainer = "mission-core-triton",
[string]$ContainerImage = "nvcr.io/nvidia/tritonserver:26.06-py3"
)
$ErrorActionPreference = "Stop"
$ProgressPreference = "SilentlyContinue"
function Assert-LastExitCode {
param([string]$Operation)
if ($LASTEXITCODE -ne 0) { throw "$Operation failed with exit code $LASTEXITCODE" }
}
function Resolve-DDirectory {
param([string]$Path, [string]$Label)
$item = Get-Item -LiteralPath (Resolve-Path -LiteralPath $Path).Path -Force
$root = [IO.Path]::GetPathRoot($item.FullName).TrimEnd("\")
if (-not $item.PSIsContainer -or ($item.Attributes -band [IO.FileAttributes]::ReparsePoint) -or $root -ine "D:") {
throw "$Label must be a real D: directory"
}
return $item.FullName
}
function Resolve-DFile {
param([string]$Path, [string]$Label)
$item = Get-Item -LiteralPath (Resolve-Path -LiteralPath $Path).Path -Force
$root = [IO.Path]::GetPathRoot($item.FullName).TrimEnd("\")
if ($item.PSIsContainer -or ($item.Attributes -band [IO.FileAttributes]::ReparsePoint) -or $root -ine "D:") {
throw "$Label must be a regular D: file"
}
return $item.FullName
}
function Convert-ToDockerPath {
param([string]$Path)
return $Path.Replace("\", "/")
}
function Get-DFreeBytes { return [int64](Get-PSDrive -Name D).Free }
function Assert-FreeSpace {
param([string]$Phase, [int64]$RequiredAdditionalBytes = 0)
$freeBytes = Get-DFreeBytes
$floorBytes = [int64]$FreeGiBFloor * 1GB
Write-Host (
"DISK_GUARD PHASE={0} DRIVE=D FREE_BYTES={1} FREE_GIB={2} FLOOR_GIB={3} REQUIRED_ADDITIONAL_GIB={4}" -f
$Phase, $freeBytes, [math]::Round($freeBytes / 1GB, 3), $FreeGiBFloor,
[math]::Round($RequiredAdditionalBytes / 1GB, 3)
)
if ($freeBytes -lt ($floorBytes + $RequiredAdditionalBytes)) {
throw "D: does not have the guarded LAB E9 working-set reserve during $Phase"
}
return $freeBytes
}
function Test-TritonModelReady {
try {
$response = Invoke-WebRequest -UseBasicParsing -TimeoutSec 10 `
-Uri "http://127.0.0.1:8000/v2/models/yolox_s/ready"
return $response.StatusCode -eq 200
}
catch { return $false }
}
$jobDirectory = Resolve-DDirectory $JobRoot "Job root"
$runner = Resolve-DFile $RunnerPath "LAB E9 runner"
$profile = Resolve-DFile $ProfilePath "LAB E9 profile"
$detectorProfile = Resolve-DFile $DetectorProfilePath "LAB E9 detector profile"
$semanticProfile = Resolve-DFile $SemanticProfilePath "LAB E9 semantic profile"
$validFov = Resolve-DDirectory $ValidFovRoot "Valid-FOV root"
$runtime = Resolve-DDirectory $RuntimeRoot "Runtime root"
$model = Resolve-DDirectory $ModelRoot "YOLOX model root"
$runnerRoot = Split-Path $runner -Parent
foreach ($path in @($profile, $detectorProfile, $semanticProfile)) {
if ((Split-Path $path -Parent) -ne $runnerRoot) {
throw "LAB E9 runner and profiles must share one read-only mount"
}
}
foreach ($dependency in @(
"run_e8_realtime_tracking.py",
"run_e5_instance_tracking.py",
"run_e4_full_session_segmentation.py",
"run_recorded_perception_epoch.py",
"run_e3_rectified_segmentation.py",
"run_evaluation_prelabels.py"
)) {
$null = Resolve-DFile (Join-Path $runnerRoot $dependency) "LAB E9 runner dependency"
}
$job = Get-Content -LiteralPath (Join-Path $jobDirectory "job.json") -Raw | ConvertFrom-Json
if ($job.schema_version -ne "missioncore.compute-job/v1" -or $job.job_id -ne (Split-Path $jobDirectory -Leaf)) {
throw "Compute job manifest is incompatible"
}
$sourceId = [string]$job.input.source_id
$epoch = [int]$job.input.codec_epoch
$fullFrameCount = [int]$job.input.segment_count
$clipFrameCount = $EndFrame - $StartFrame + 1
$timelineStart = [double]$job.input.timeline.start_seconds
if (
$sourceId -ne "sensor.camera.right" -or $StartFrame -lt 0 -or
$EndFrame -lt $StartFrame -or $EndFrame -ge $fullFrameCount -or $clipFrameCount -lt 2
) { throw "LAB E9 clip escapes the camera job" }
Write-Output (
"PHASE=job-manifest-validated JOB={0} CLIP={1}-{2} FRAMES={3}" -f
$job.job_id, $StartFrame, $EndFrame, $clipFrameCount
)
$epochRoot = Resolve-DDirectory (
Join-Path $jobDirectory ("input\camera\{0}\epoch-{1}" -f $sourceId, $epoch)
) "Camera epoch"
$initPath = Resolve-DFile (Join-Path $epochRoot "init.mp4") "Camera init"
$segmentsRoot = Resolve-DDirectory (Join-Path $epochRoot "segments") "Camera segments"
$derivedRoot = Join-Path $runtime "derived"
$tmpRoot = Join-Path $runtime "tmp"
$cacheRoot = Resolve-DDirectory (Join-Path $runtime "cache\perception-e3-models-v1") "EoMT cache"
$e3Environment = Resolve-DDirectory (Join-Path $derivedRoot "perception-e3-opencv413092-v1") "E3 environment"
$torchEnvironment = Resolve-DDirectory (Join-Path $derivedRoot "perception-p0-env-v1") "Torch environment"
$transformersEnvironment = Resolve-DDirectory (Join-Path $derivedRoot "perception-p0-transformers4576-v1") "Transformers environment"
$null = New-Item -ItemType Directory -Path $derivedRoot -Force
$null = New-Item -ItemType Directory -Path $tmpRoot -Force
$pixelWorkingSet = [int64]$clipFrameCount * 800 * 600 * 3
$partialStreamReserve = [int64][math]::Ceiling(
([int64]$job.input.byte_length * ($EndFrame + 1) / $fullFrameCount) * 1.2
)
$workingSetReserve = [int64][math]::Ceiling($pixelWorkingSet * 1.4) + $partialStreamReserve + 3GB
$freeBytesBefore = Assert-FreeSpace "preflight" $workingSetReserve
& docker image inspect $ContainerImage *> $null
Assert-LastExitCode "Existing container image inspection"
$tritonState = docker inspect --format "{{.State.Running}}" $TritonContainer
Assert-LastExitCode "Triton container inspection"
if ($tritonState.Trim().ToLowerInvariant() -ne "true") {
throw "LAB E9 requires the existing Triton container"
}
$runnerName = Split-Path $runner -Leaf
$profileName = Split-Path $profile -Leaf
$detectorProfileName = Split-Path $detectorProfile -Leaf
$semanticProfileName = Split-Path $semanticProfile -Leaf
$orchestratorSha256 = (Get-FileHash -LiteralPath $PSCommandPath -Algorithm SHA256).Hash.ToLowerInvariant()
$commonMounts = @(
"-e", "PYTHONPATH=/runner:/opt/transformers:/opt/env",
"-e", "TORCH_HOME=/cache/torch",
"-e", "HF_HOME=/cache/huggingface",
"-e", "HF_HUB_OFFLINE=1",
"-e", "TRANSFORMERS_OFFLINE=1",
"-v", ((Convert-ToDockerPath $jobDirectory) + ":/job:ro"),
"-v", ((Convert-ToDockerPath $validFov) + ":/valid-fov:ro"),
"-v", ((Convert-ToDockerPath $model) + ":/model:ro"),
"-v", ((Convert-ToDockerPath $cacheRoot) + ":/cache:ro"),
"-v", ((Convert-ToDockerPath $e3Environment) + ":/environment:ro"),
"-v", ((Convert-ToDockerPath $torchEnvironment) + ":/opt/env:ro"),
"-v", ((Convert-ToDockerPath $transformersEnvironment) + ":/opt/transformers:ro"),
"-v", ((Convert-ToDockerPath $runnerRoot) + ":/runner:ro")
)
$commonRunnerArgs = @(
"--job", "/job",
"--profile", ("/runner/{0}" -f $profileName),
"--detector-profile", ("/runner/{0}" -f $detectorProfileName),
"--semantic-profile", ("/runner/{0}" -f $semanticProfileName),
"--valid-fov-root", "/valid-fov",
"--model-root", "/model",
"--cache", "/cache",
"--environment", "/environment"
)
$preflightArgs = @(
"run", "--rm", "--gpus", "all", "--network", "none", "--read-only",
"--security-opt", "no-new-privileges:true", "--cap-drop", "ALL",
"--pids-limit", "512", "--shm-size", "4g",
"--tmpfs", "/tmp:rw,noexec,nosuid,size=2g"
) + $commonMounts + @(
"--entrypoint", "python3", $ContainerImage,
("/runner/{0}" -f $runnerName), "preflight"
) + $commonRunnerArgs
Write-Output "PHASE=e9-preflight-start"
& docker @preflightArgs
Assert-LastExitCode "LAB E9 preflight"
Write-Output "PHASE=e9-preflight-complete"
$modelWasReady = Test-TritonModelReady
$loadedByRun = $false
if (-not $modelWasReady) {
Invoke-WebRequest -UseBasicParsing -TimeoutSec 60 `
-Uri "http://127.0.0.1:8000/v2/repository/models/yolox_s/load" `
-Method Post -ContentType "application/json" -Body "{}" *> $null
$loadedByRun = $true
$deadline = [DateTime]::UtcNow.AddSeconds(60)
while (-not (Test-TritonModelReady)) {
if ([DateTime]::UtcNow -ge $deadline) { throw "YOLOX-S did not become ready" }
Start-Sleep -Milliseconds 500
}
}
Write-Output ("PHASE=e9-model-ready LOADED_BY_RUN={0}" -f $loadedByRun)
$runToken = [Guid]::NewGuid().ToString("N")
$workRoot = Join-Path $tmpRoot ("{0}-e9-{1}" -f $job.job_id, $runToken)
$framesRoot = Join-Path $workRoot "frames"
$streamPath = Join-Path $workRoot "camera.mp4"
$ptsPath = Join-Path $workRoot "pts.json"
$timelinePath = Join-Path $workRoot "timeline.jsonl"
$publishRoot = Join-Path $derivedRoot (".{0}-e9-{1}.publish" -f $job.job_id, $runToken)
$stagingRoot = Join-Path $publishRoot "output"
$null = New-Item -ItemType Directory -Path $framesRoot
$null = New-Item -ItemType Directory -Path $publishRoot
$completed = $false
$totalWatch = [Diagnostics.Stopwatch]::StartNew()
try {
$stream = [IO.File]::Open($streamPath, [IO.FileMode]::CreateNew, [IO.FileAccess]::Write, [IO.FileShare]::None)
try {
$input = [IO.File]::OpenRead($initPath)
try { $input.CopyTo($stream) } finally { $input.Dispose() }
for ($sequence = 1; $sequence -le ($EndFrame + 1); $sequence++) {
$path = Resolve-DFile (Join-Path $segmentsRoot ("{0}.m4s" -f $sequence)) "Camera segment"
$input = [IO.File]::OpenRead($path)
try { $input.CopyTo($stream) } finally { $input.Dispose() }
}
$stream.Flush($true)
}
finally { $stream.Dispose() }
$null = Assert-FreeSpace "post-stream-reconstruction"
$extractWatch = [Diagnostics.Stopwatch]::StartNew()
$selectFilter = "select='between(n,{0},{1})'" -f $StartFrame, $EndFrame
& ffmpeg -hide_banner -loglevel fatal -i $streamPath -map 0:v:0 `
-vf $selectFilter -fps_mode passthrough (Join-Path $framesRoot "frame-%06d.png")
Assert-LastExitCode "LAB E9 camera clip extraction"
& ffprobe -v error -select_streams v:0 -show_entries frame=best_effort_timestamp_time `
-of json $streamPath | Set-Content -LiteralPath $ptsPath -Encoding utf8
Assert-LastExitCode "LAB E9 camera timestamp probe"
$decodedFrames = @(Get-ChildItem -LiteralPath $framesRoot -File -Filter "frame-*.png")
$pts = @((Get-Content -LiteralPath $ptsPath -Raw | ConvertFrom-Json).frames)
if ($decodedFrames.Count -ne $clipFrameCount -or $pts.Count -ne ($EndFrame + 1)) {
throw "Decoded LAB E9 frame/timestamp count changed"
}
$firstEpochSeconds = [double]::Parse(
([string]$pts[0].best_effort_timestamp_time).Trim(),
[Globalization.CultureInfo]::InvariantCulture
)
$previousSessionSeconds = -1.0
$timelineWriter = [IO.StreamWriter]::new(
$timelinePath, $false, [Text.UTF8Encoding]::new($false)
)
try {
for ($localIndex = 0; $localIndex -lt $clipFrameCount; $localIndex++) {
$sourceIndex = $StartFrame + $localIndex
$epochSeconds = [double]::Parse(
([string]$pts[$sourceIndex].best_effort_timestamp_time).Trim(),
[Globalization.CultureInfo]::InvariantCulture
) - $firstEpochSeconds
$sessionSeconds = $timelineStart + $epochSeconds
if ($sessionSeconds -le $previousSessionSeconds) { throw "LAB E9 timeline is not monotonic" }
$row = [ordered]@{
frame_index = $localIndex
sequence = $localIndex + 1
source_frame_index = $sourceIndex
source_sequence = $sourceIndex + 1
epoch_seconds = $epochSeconds
session_seconds = $sessionSeconds
}
$timelineWriter.WriteLine(($row | ConvertTo-Json -Compress))
$previousSessionSeconds = $sessionSeconds
}
$timelineWriter.Flush()
}
finally { $timelineWriter.Dispose() }
$extractWatch.Stop()
$freeBytesPostExtract = Assert-FreeSpace "post-frame-extraction"
Write-Output ("PHASE=e9-frame-extraction-complete FRAMES={0}" -f $clipFrameCount)
$runArgs = @(
"run", "--rm", "--gpus", "all", "--network", ("container:{0}" -f $TritonContainer),
"--read-only", "--security-opt", "no-new-privileges:true", "--cap-drop", "ALL",
"--pids-limit", "512", "--shm-size", "4g",
"--tmpfs", "/tmp:rw,noexec,nosuid,size=2g"
) + $commonMounts + @(
"-v", ((Convert-ToDockerPath $framesRoot) + ":/frames:ro"),
"-v", ((Convert-ToDockerPath $workRoot) + ":/work:ro"),
"-v", ((Convert-ToDockerPath $publishRoot) + ":/publish:rw"),
"--entrypoint", "python3", $ContainerImage,
("/runner/{0}" -f $runnerName), "run"
) + $commonRunnerArgs + @(
"--frames", "/frames",
"--timeline", "/work/timeline.jsonl",
"--output", "/publish/output",
"--triton-url", "http://127.0.0.1:8000",
"--free-bytes-floor", [string]([int64]$FreeGiBFloor * 1GB),
"--orchestrator-sha256", $orchestratorSha256,
"--container-image", $ContainerImage,
"--telemetry-interval-seconds", "1"
)
Write-Output ("PHASE=e9-multirate-replay-start FRAMES={0}" -f $clipFrameCount)
& docker @runArgs
Assert-LastExitCode "LAB E9 multirate replay"
$freeBytesPostReplay = Assert-FreeSpace "post-replay"
$result = Get-Content -LiteralPath (Join-Path $stagingRoot "result.json") -Raw | ConvertFrom-Json
if (
$result.schema_version -ne "missioncore.e9-multirate-perception-result/v1" -or
$result.result_id -notmatch "^e9-multirate-perception-[a-f0-9]{64}$" -or
$result.acceptance_state -notin @("accepted", "rejected") -or
$result.ground_truth -ne $false
) { throw "LAB E9 result manifest is incompatible" }
$finalRoot = Join-Path $derivedRoot ([string]$result.result_id)
if (Test-Path -LiteralPath $finalRoot) { throw "Immutable LAB E9 result already exists" }
Move-Item -LiteralPath $stagingRoot -Destination $finalRoot
Remove-Item -LiteralPath $publishRoot -Force
$completed = $true
$totalWatch.Stop()
$freeBytesFinal = Assert-FreeSpace "post-publication"
Write-Output ("RESULT_ROOT={0}" -f $finalRoot)
Write-Output ("RESULT_ID={0}" -f $result.result_id)
Write-Output ("ACCEPTANCE_STATE={0}" -f $result.acceptance_state)
Write-Output ("PREPARATION_SECONDS={0}" -f $extractWatch.Elapsed.TotalSeconds)
Write-Output ("ORCHESTRATOR_WALL_SECONDS={0}" -f $totalWatch.Elapsed.TotalSeconds)
Write-Output ("DISK_FREE_BYTES_BEFORE={0}" -f $freeBytesBefore)
Write-Output ("DISK_FREE_BYTES_POST_EXTRACT={0}" -f $freeBytesPostExtract)
Write-Output ("DISK_FREE_BYTES_POST_REPLAY={0}" -f $freeBytesPostReplay)
Write-Output ("DISK_FREE_BYTES_FINAL={0}" -f $freeBytesFinal)
}
finally {
if (Test-Path -LiteralPath $workRoot) { Remove-Item -LiteralPath $workRoot -Recurse -Force }
if (-not $completed -and (Test-Path -LiteralPath $publishRoot)) {
Remove-Item -LiteralPath $publishRoot -Recurse -Force
}
if ($loadedByRun) {
try {
Invoke-WebRequest -UseBasicParsing -TimeoutSec 60 `
-Uri "http://127.0.0.1:8000/v2/repository/models/yolox_s/unload" `
-Method Post -ContentType "application/json" -Body "{}" *> $null
Write-Output "PHASE=e9-model-state-restored"
}
catch { Write-Warning "LAB E9 could not restore the prior unloaded YOLOX-S state" }
}
}
@@ -0,0 +1,133 @@
[CmdletBinding()]
param(
[Parameter(Mandatory = $true)]
[string]$EvaluationPack,
[Parameter(Mandatory = $true)]
[string]$ValidFovRoot,
[Parameter(Mandatory = $true)]
[string]$RunnerPath,
[Parameter(Mandatory = $true)]
[string]$BaselineRunnerPath,
[string]$RuntimeRoot = "D:\NDC_MISSIONCORE\runtime"
)
$ErrorActionPreference = "Stop"
$ProgressPreference = "SilentlyContinue"
function Assert-LastExitCode {
param([string]$Operation)
if ($LASTEXITCODE -ne 0) {
throw "$Operation failed with exit code $LASTEXITCODE"
}
}
function Assert-RegularFile {
param([string]$Path, [string]$Label)
$item = Get-Item -LiteralPath $Path -Force
if (-not $item.PSIsContainer -and -not ($item.Attributes -band [IO.FileAttributes]::ReparsePoint)) {
return $item.FullName
}
throw "$Label is not a regular file"
}
function Assert-Directory {
param([string]$Path, [string]$Label)
$item = Get-Item -LiteralPath $Path -Force
if ($item.PSIsContainer -and -not ($item.Attributes -band [IO.FileAttributes]::ReparsePoint)) {
return $item.FullName
}
throw "$Label is not a real directory"
}
function Convert-ToDockerPath {
param([string]$Path)
return $Path.Replace("\", "/")
}
$packRoot = Assert-Directory (Resolve-Path -LiteralPath $EvaluationPack).Path "Evaluation pack"
$validFov = Assert-Directory (Resolve-Path -LiteralPath $ValidFovRoot).Path "Valid-FOV root"
$runner = Assert-RegularFile (Resolve-Path -LiteralPath $RunnerPath).Path "Prelabel runner"
$baselineRunner = Assert-RegularFile (Resolve-Path -LiteralPath $BaselineRunnerPath).Path "Baseline runner"
if ((Split-Path $runner -Parent) -ne (Split-Path $baselineRunner -Parent)) {
throw "Prelabel and baseline runners must share one read-only mount"
}
$runtime = Assert-Directory (Resolve-Path -LiteralPath $RuntimeRoot).Path "Runtime root"
$pack = Get-Content -LiteralPath (Join-Path $packRoot "manifest.json") -Raw | ConvertFrom-Json
if (
$pack.schema_version -ne "missioncore.perception-evaluation-pack/v1" -or
$pack.generation_id -ne (Split-Path $packRoot -Leaf) -or
$pack.identity.preprocessing_profile -ne "fixed-valid-fov-fill/v1"
) {
throw "Evaluation pack manifest is incompatible"
}
$null = Assert-RegularFile (Join-Path $validFov "manifest.json") "Valid-FOV manifest"
$null = Assert-RegularFile (Join-Path $validFov "mask.png") "Valid-FOV mask"
$cacheRoot = Assert-Directory (Join-Path $runtime "cache\perception-p0-models-v1") "Model cache"
$torchEnvironment = Assert-Directory (Join-Path $runtime "derived\perception-p0-env-v1") "Torch environment"
$transformersEnvironment = Assert-Directory (Join-Path $runtime "derived\perception-p0-transformers4576-v1") "Transformers environment"
$runnerRoot = Split-Path $runner -Parent
$runnerName = Split-Path $runner -Leaf
$derivedRoot = Join-Path $runtime "derived\evaluation-prelabels"
$null = New-Item -ItemType Directory -Path $derivedRoot -Force
$runToken = [Guid]::NewGuid().ToString("N")
$publishRoot = Join-Path $derivedRoot (".{0}-{1}.publish" -f $pack.generation_id, $runToken)
$stagingRoot = Join-Path $publishRoot "output"
$null = New-Item -ItemType Directory -Path $publishRoot
try {
$dockerArgs = @(
"run", "--rm", "--gpus", "all", "--network", "none",
"--security-opt", "no-new-privileges:true", "--cap-drop", "ALL",
"--shm-size", "2g",
"-e", "PYTHONPATH=/opt/transformers:/opt/env",
"-e", "TORCH_HOME=/cache/torch",
"-e", "HF_HOME=/cache/huggingface",
"-e", "HF_HUB_OFFLINE=1",
"-e", "TRANSFORMERS_OFFLINE=1",
"-v", ((Convert-ToDockerPath $packRoot) + ":/evaluation-pack:ro"),
"-v", ((Convert-ToDockerPath $validFov) + ":/valid-fov:ro"),
"-v", ((Convert-ToDockerPath $publishRoot) + ":/publish:rw"),
"-v", ((Convert-ToDockerPath $cacheRoot) + ":/cache:rw"),
"-v", ((Convert-ToDockerPath $torchEnvironment) + ":/opt/env:ro"),
"-v", ((Convert-ToDockerPath $transformersEnvironment) + ":/opt/transformers:ro"),
"-v", ((Convert-ToDockerPath $runnerRoot) + ":/runner:ro"),
"--entrypoint", "python3",
"nvcr.io/nvidia/tritonserver:26.06-py3",
("/runner/{0}" -f $runnerName),
"--evaluation-pack", "/evaluation-pack",
"--valid-fov-root", "/valid-fov",
"--output", "/publish/output",
"--cache", "/cache",
"--telemetry-interval-seconds", "1"
)
Write-Output ("PHASE=e2-prelabels-start PACK={0}" -f $pack.generation_id)
& docker @dockerArgs
Assert-LastExitCode "E2 prelabel generation"
$result = Get-Content -LiteralPath (Join-Path $stagingRoot "result.json") -Raw | ConvertFrom-Json
if (
$result.schema_version -ne "missioncore.perception-evaluation-prelabels/v1" -or
$result.result_id -notmatch "^evaluation-prelabels-[a-f0-9]{64}$" -or
$result.identity.evaluation_pack_id -ne $pack.generation_id
) {
throw "E2 prelabel result manifest is incompatible"
}
$finalRoot = Join-Path $derivedRoot ([string]$result.result_id)
if (Test-Path -LiteralPath $finalRoot) {
throw "An immutable E2 prelabel result with the same identity already exists: $finalRoot"
}
Move-Item -LiteralPath $stagingRoot -Destination $finalRoot
Remove-Item -LiteralPath $publishRoot -Force
Write-Output ("RESULT_ROOT={0}" -f $finalRoot)
Write-Output ("RESULT_ID={0}" -f $result.result_id)
}
finally {
if (Test-Path -LiteralPath $publishRoot) {
Remove-Item -LiteralPath $publishRoot -Recurse -Force
}
}
@@ -0,0 +1,276 @@
[CmdletBinding()]
param(
[Parameter(Mandatory = $true)]
[string]$JobRoot,
[Parameter(Mandatory = $true)]
[string]$RunnerPath,
[Parameter(Mandatory = $true)]
[string]$BaselineRunnerPath,
[Parameter(Mandatory = $true)]
[string]$QualificationManifest,
[Parameter(Mandatory = $true)]
[string]$ValidFovRoot,
[string]$RuntimeRoot = "D:\NDC_MISSIONCORE\runtime",
[string]$CalibrationSha256 = "05f3ad9b38b3a4fc95388a8ec83da83c745e217709e51787b3d5aad0969f6fa9",
[string]$CalibrationSlot = "camera_1"
)
$ErrorActionPreference = "Stop"
$ProgressPreference = "SilentlyContinue"
function Assert-LastExitCode {
param([string]$Operation)
if ($LASTEXITCODE -ne 0) {
throw "$Operation failed with exit code $LASTEXITCODE"
}
}
function Assert-RegularFile {
param([string]$Path, [string]$Label)
$item = Get-Item -LiteralPath $Path -Force
if (-not $item.PSIsContainer -and -not ($item.Attributes -band [IO.FileAttributes]::ReparsePoint)) {
return $item.FullName
}
throw "$Label is not a regular file"
}
function Assert-Directory {
param([string]$Path, [string]$Label)
$item = Get-Item -LiteralPath $Path -Force
if ($item.PSIsContainer -and -not ($item.Attributes -band [IO.FileAttributes]::ReparsePoint)) {
return $item.FullName
}
throw "$Label is not a real directory"
}
function Convert-ToDockerPath {
param([string]$Path)
return $Path.Replace("\", "/")
}
$jobDirectory = Assert-Directory (Resolve-Path -LiteralPath $JobRoot).Path "Job root"
$runner = Assert-RegularFile (Resolve-Path -LiteralPath $RunnerPath).Path "Qualification runner"
$baselineRunner = Assert-RegularFile (Resolve-Path -LiteralPath $BaselineRunnerPath).Path "Baseline runner"
$qualification = Assert-RegularFile (Resolve-Path -LiteralPath $QualificationManifest).Path "Qualification manifest"
$validFov = Assert-Directory (Resolve-Path -LiteralPath $ValidFovRoot).Path "Valid-FOV root"
$null = Assert-RegularFile (Join-Path $validFov "manifest.json") "Valid-FOV manifest"
$null = Assert-RegularFile (Join-Path $validFov "mask.png") "Valid-FOV mask"
if ((Split-Path $runner -Parent) -ne (Split-Path $baselineRunner -Parent)) {
throw "Qualification and baseline runners must share one read-only mount"
}
$runtime = Assert-Directory (Resolve-Path -LiteralPath $RuntimeRoot).Path "Runtime root"
$job = Get-Content -LiteralPath (Join-Path $jobDirectory "job.json") -Raw | ConvertFrom-Json
if ($job.schema_version -ne "missioncore.compute-job/v1" -or $job.job_id -ne (Split-Path $jobDirectory -Leaf)) {
throw "Compute job manifest is incompatible"
}
if ($CalibrationSha256 -notmatch "^[a-f0-9]{64}$" -or $CalibrationSlot -notmatch "^[A-Za-z0-9._-]+$") {
throw "Calibration binding is invalid"
}
$sourceId = [string]$job.input.source_id
$epoch = [int]$job.input.codec_epoch
$frameCount = [int]$job.input.segment_count
$timelineStart = [double]$job.input.timeline.start_seconds
$timelineEnd = [double]$job.input.timeline.end_seconds
$timelineDuration = $timelineEnd - $timelineStart
if ($frameCount -lt 1 -or $timelineDuration -le 0) {
throw "Compute job frame/timeline contract is invalid"
}
$qualificationDocument = Get-Content -LiteralPath $qualification -Raw | ConvertFrom-Json
if (
$qualificationDocument.schema_version -ne "missioncore.recorded-qualification-slice/v1" -or
$qualificationDocument.identity.job_id -ne $job.job_id -or
$qualificationDocument.identity.input_sha256 -ne $job.input_sha256
) {
throw "Qualification manifest is not bound to this job"
}
Write-Output ("PHASE=inputs-validated QUALIFICATION_FRAMES={0}" -f @($qualificationDocument.frames).Count)
$epochRoot = Join-Path $jobDirectory ("input\camera\{0}\epoch-{1}" -f $sourceId, $epoch)
$epochRoot = Assert-Directory $epochRoot "Camera epoch"
$initPath = Assert-RegularFile (Join-Path $epochRoot "init.mp4") "Camera init"
$segmentsRoot = Assert-Directory (Join-Path $epochRoot "segments") "Camera segments"
$derivedRoot = Join-Path $runtime "derived\qualification"
$tmpRoot = Join-Path $runtime "tmp"
$cacheRoot = Assert-Directory (Join-Path $runtime "cache\perception-p0-models-v1") "Model cache"
$torchEnvironment = Assert-Directory (Join-Path $runtime "derived\perception-p0-env-v1") "Torch environment"
$transformersEnvironment = Assert-Directory (Join-Path $runtime "derived\perception-p0-transformers4576-v1") "Transformers environment"
$runnerRoot = Split-Path $runner -Parent
$runnerName = Split-Path $runner -Leaf
$baselineRunnerName = Split-Path $baselineRunner -Leaf
$qualificationRoot = Split-Path $qualification -Parent
$qualificationName = Split-Path $qualification -Leaf
$null = New-Item -ItemType Directory -Path $derivedRoot -Force
$null = New-Item -ItemType Directory -Path $tmpRoot -Force
$preflightArgs = @(
"run", "--rm", "--gpus", "all", "--network", "none",
"--security-opt", "no-new-privileges:true", "--cap-drop", "ALL",
"-e", "PYTHONPATH=/opt/transformers:/opt/env",
"-e", "TORCH_HOME=/cache/torch",
"-e", "HF_HOME=/cache/huggingface",
"-e", "HF_HUB_OFFLINE=1",
"-e", "TRANSFORMERS_OFFLINE=1",
"-v", ((Convert-ToDockerPath $jobDirectory) + ":/job:ro"),
"-v", ((Convert-ToDockerPath $cacheRoot) + ":/cache:rw"),
"-v", ((Convert-ToDockerPath $torchEnvironment) + ":/opt/env:ro"),
"-v", ((Convert-ToDockerPath $transformersEnvironment) + ":/opt/transformers:ro"),
"-v", ((Convert-ToDockerPath $runnerRoot) + ":/runner:ro"),
"--entrypoint", "python3",
"nvcr.io/nvidia/tritonserver:26.06-py3",
("/runner/{0}" -f $baselineRunnerName), "preflight",
"--job", "/job",
"--cache", "/cache"
)
Write-Output "PHASE=worker-preflight-started"
& docker @preflightArgs
Assert-LastExitCode "Worker preflight"
Write-Output "PHASE=worker-preflight-complete"
$runToken = [Guid]::NewGuid().ToString("N")
$workRoot = Join-Path $tmpRoot ("{0}-e1-{1}" -f $job.job_id, $runToken)
$framesRoot = Join-Path $workRoot "frames"
$streamPath = Join-Path $workRoot "camera.mp4"
$ptsPath = Join-Path $workRoot "pts.json"
$timelinePath = Join-Path $workRoot "timeline.jsonl"
$publishRoot = Join-Path $derivedRoot (".{0}-e1-{1}.publish" -f $job.job_id, $runToken)
$stagingRoot = Join-Path $publishRoot "output"
$null = New-Item -ItemType Directory -Path $framesRoot
$null = New-Item -ItemType Directory -Path $publishRoot
Write-Output "PHASE=private-staging-created"
try {
$stream = [IO.File]::Open($streamPath, [IO.FileMode]::CreateNew, [IO.FileAccess]::Write, [IO.FileShare]::None)
try {
$input = [IO.File]::OpenRead($initPath)
try {
$input.CopyTo($stream)
}
finally {
$input.Dispose()
}
for ($sequence = 1; $sequence -le $frameCount; $sequence++) {
$path = Assert-RegularFile (Join-Path $segmentsRoot ("{0}.m4s" -f $sequence)) "Camera segment"
$input = [IO.File]::OpenRead($path)
try {
$input.CopyTo($stream)
}
finally {
$input.Dispose()
}
if ($sequence % 500 -eq 0 -or $sequence -eq $frameCount) {
Write-Output ("PHASE=stream-reconstruction SEGMENTS={0}/{1}" -f $sequence, $frameCount)
}
}
$stream.Flush($true)
}
finally {
$stream.Dispose()
}
Write-Output "PHASE=frame-extraction-started"
& ffmpeg -hide_banner -loglevel fatal -i $streamPath -map 0:v:0 -fps_mode passthrough (Join-Path $framesRoot "frame-%06d.png")
Assert-LastExitCode "Camera extraction"
& ffprobe -v error -select_streams v:0 -show_entries frame=best_effort_timestamp_time -of json $streamPath | Set-Content -LiteralPath $ptsPath -Encoding utf8
Assert-LastExitCode "Camera timestamp probe"
$decodedFrames = @(Get-ChildItem -LiteralPath $framesRoot -File -Filter "frame-*.png")
$ptsDocument = Get-Content -LiteralPath $ptsPath -Raw | ConvertFrom-Json
$pts = @($ptsDocument.frames)
if ($decodedFrames.Count -ne $frameCount -or $pts.Count -ne $frameCount) {
throw "Decoded frame count differs from the compute job"
}
$firstEpochSeconds = [double]::Parse(
([string]$pts[0].best_effort_timestamp_time).Trim(),
[Globalization.CultureInfo]::InvariantCulture
)
$previousEpochSeconds = -1.0
$timelineWriter = [IO.StreamWriter]::new($timelinePath, $false, [Text.UTF8Encoding]::new($false))
try {
for ($index = 0; $index -lt $frameCount; $index++) {
$epochSeconds = [double]::Parse(
([string]$pts[$index].best_effort_timestamp_time).Trim(),
[Globalization.CultureInfo]::InvariantCulture
) - $firstEpochSeconds
if ($epochSeconds -le $previousEpochSeconds -or $epochSeconds -gt ($timelineDuration + 0.001)) {
throw "Decoded camera timestamps are not strictly monotonic inside the compute job timeline"
}
$row = [ordered]@{
frame_index = $index
epoch_seconds = $epochSeconds
session_seconds = $timelineStart + $epochSeconds
}
$timelineWriter.WriteLine(($row | ConvertTo-Json -Compress))
$previousEpochSeconds = $epochSeconds
}
$timelineWriter.Flush()
}
finally {
$timelineWriter.Dispose()
}
Write-Output ("PHASE=frame-extraction-complete FRAMES={0}" -f $frameCount)
$dockerArgs = @(
"run", "--rm", "--gpus", "all", "--network", "none",
"--security-opt", "no-new-privileges:true", "--cap-drop", "ALL",
"--shm-size", "2g",
"-e", "PYTHONPATH=/opt/transformers:/opt/env",
"-e", "TORCH_HOME=/cache/torch",
"-e", "HF_HOME=/cache/huggingface",
"-e", "HF_HUB_OFFLINE=1",
"-e", "TRANSFORMERS_OFFLINE=1",
"-v", ((Convert-ToDockerPath $jobDirectory) + ":/job:ro"),
"-v", ((Convert-ToDockerPath $framesRoot) + ":/frames:ro"),
"-v", ((Convert-ToDockerPath $workRoot) + ":/work:ro"),
"-v", ((Convert-ToDockerPath $publishRoot) + ":/publish:rw"),
"-v", ((Convert-ToDockerPath $cacheRoot) + ":/cache:rw"),
"-v", ((Convert-ToDockerPath $torchEnvironment) + ":/opt/env:ro"),
"-v", ((Convert-ToDockerPath $transformersEnvironment) + ":/opt/transformers:ro"),
"-v", ((Convert-ToDockerPath $runnerRoot) + ":/runner:ro"),
"-v", ((Convert-ToDockerPath $qualificationRoot) + ":/qualification:ro"),
"-v", ((Convert-ToDockerPath $validFov) + ":/valid-fov:ro"),
"--entrypoint", "python3",
"nvcr.io/nvidia/tritonserver:26.06-py3",
("/runner/{0}" -f $runnerName),
"--job", "/job",
"--frames", "/frames",
"--timeline", "/work/timeline.jsonl",
"--qualification", ("/qualification/{0}" -f $qualificationName),
"--valid-fov-root", "/valid-fov",
"--output", "/publish/output",
"--cache", "/cache",
"--calibration-sha256", $CalibrationSha256,
"--calibration-slot", $CalibrationSlot,
"--telemetry-interval-seconds", "1"
)
& docker @dockerArgs
Assert-LastExitCode "Preprocessing qualification"
$result = Get-Content -LiteralPath (Join-Path $stagingRoot "result.json") -Raw | ConvertFrom-Json
if (
$result.schema_version -ne "missioncore.perception-preprocessing-qualification-result/v1" -or
$result.result_id -notmatch "^qualification-result-[a-f0-9]{64}$"
) {
throw "Qualification result manifest is incompatible"
}
$finalRoot = Join-Path $derivedRoot ([string]$result.result_id)
if (Test-Path -LiteralPath $finalRoot) {
throw "An immutable qualification result with the same identity already exists: $finalRoot"
}
Move-Item -LiteralPath $stagingRoot -Destination $finalRoot
Remove-Item -LiteralPath $publishRoot -Force
Write-Output ("RESULT_ROOT={0}" -f $finalRoot)
Write-Output ("RESULT_ID={0}" -f $result.result_id)
}
finally {
if (Test-Path -LiteralPath $workRoot) {
Remove-Item -LiteralPath $workRoot -Recurse -Force
}
}
@@ -0,0 +1,292 @@
[CmdletBinding()]
param(
[Parameter(Mandatory = $true)]
[string]$JobRoot,
[Parameter(Mandatory = $true)]
[string]$RunnerPath,
[string]$RuntimeRoot = "D:\NDC_MISSIONCORE\runtime",
[string]$CalibrationSha256 = "05f3ad9b38b3a4fc95388a8ec83da83c745e217709e51787b3d5aad0969f6fa9",
[string]$CalibrationSlot = "camera_1"
)
$ErrorActionPreference = "Stop"
$ProgressPreference = "SilentlyContinue"
function Assert-LastExitCode {
param([string]$Operation)
if ($LASTEXITCODE -ne 0) {
throw "$Operation failed with exit code $LASTEXITCODE"
}
}
function Assert-RegularFile {
param([string]$Path, [string]$Label)
$item = Get-Item -LiteralPath $Path -Force
if (-not $item.PSIsContainer -and -not ($item.Attributes -band [IO.FileAttributes]::ReparsePoint)) {
return $item.FullName
}
throw "$Label is not a regular file"
}
function Assert-Directory {
param([string]$Path, [string]$Label)
$item = Get-Item -LiteralPath $Path -Force
if ($item.PSIsContainer -and -not ($item.Attributes -band [IO.FileAttributes]::ReparsePoint)) {
return $item.FullName
}
throw "$Label is not a real directory"
}
function Convert-ToDockerPath {
param([string]$Path)
return $Path.Replace("\", "/")
}
$jobDirectory = Assert-Directory (Resolve-Path -LiteralPath $JobRoot).Path "Job root"
$runner = Assert-RegularFile (Resolve-Path -LiteralPath $RunnerPath).Path "Runner"
$runtime = Assert-Directory (Resolve-Path -LiteralPath $RuntimeRoot).Path "Runtime root"
$job = Get-Content -LiteralPath (Join-Path $jobDirectory "job.json") -Raw | ConvertFrom-Json
if ($job.schema_version -ne "missioncore.compute-job/v1" -or $job.job_id -ne (Split-Path $jobDirectory -Leaf)) {
throw "Compute job manifest is incompatible"
}
if ($CalibrationSha256 -notmatch "^[a-f0-9]{64}$" -or $CalibrationSlot -notmatch "^[A-Za-z0-9._-]+$") {
throw "Calibration binding is invalid"
}
Write-Output "PHASE=job-manifest-validated"
$sourceId = [string]$job.input.source_id
$epoch = [int]$job.input.codec_epoch
$frameCount = [int]$job.input.segment_count
$timelineStart = [double]$job.input.timeline.start_seconds
$timelineEnd = [double]$job.input.timeline.end_seconds
$timelineDuration = $timelineEnd - $timelineStart
if ($frameCount -lt 1 -or $timelineDuration -le 0) {
throw "Compute job frame/timeline contract is invalid"
}
$epochRoot = Join-Path $jobDirectory ("input\camera\{0}\epoch-{1}" -f $sourceId, $epoch)
$epochRoot = Assert-Directory $epochRoot "Camera epoch"
$initPath = Assert-RegularFile (Join-Path $epochRoot "init.mp4") "Camera init"
$segmentsRoot = Assert-Directory (Join-Path $epochRoot "segments") "Camera segments"
$derivedRoot = Join-Path $runtime "derived"
$tmpRoot = Join-Path $runtime "tmp"
$cacheRoot = Assert-Directory (Join-Path $runtime "cache\perception-p0-models-v1") "Model cache"
$torchEnvironment = Assert-Directory (Join-Path $derivedRoot "perception-p0-env-v1") "Torch environment"
$transformersEnvironment = Assert-Directory (Join-Path $derivedRoot "perception-p0-transformers4576-v1") "Transformers environment"
$runnerRoot = Split-Path $runner -Parent
$runnerName = Split-Path $runner -Leaf
$null = New-Item -ItemType Directory -Path $derivedRoot -Force
$null = New-Item -ItemType Directory -Path $tmpRoot -Force
$preflightArgs = @(
"run", "--rm", "--gpus", "all", "--network", "none",
"--security-opt", "no-new-privileges:true", "--cap-drop", "ALL",
"-e", "PYTHONPATH=/opt/transformers:/opt/env",
"-e", "TORCH_HOME=/cache/torch",
"-e", "HF_HOME=/cache/huggingface",
"-e", "HF_HUB_OFFLINE=1",
"-e", "TRANSFORMERS_OFFLINE=1",
"-v", ((Convert-ToDockerPath $jobDirectory) + ":/job:ro"),
"-v", ((Convert-ToDockerPath $cacheRoot) + ":/cache:rw"),
"-v", ((Convert-ToDockerPath $torchEnvironment) + ":/opt/env:ro"),
"-v", ((Convert-ToDockerPath $transformersEnvironment) + ":/opt/transformers:ro"),
"-v", ((Convert-ToDockerPath $runnerRoot) + ":/runner:ro"),
"--entrypoint", "python3",
"nvcr.io/nvidia/tritonserver:26.06-py3",
("/runner/{0}" -f $runnerName), "preflight",
"--job", "/job",
"--cache", "/cache"
)
Write-Output "PHASE=worker-preflight-started"
& docker @preflightArgs
Assert-LastExitCode "Worker preflight"
Write-Output "PHASE=worker-preflight-complete"
$runToken = [Guid]::NewGuid().ToString("N")
$workRoot = Join-Path $tmpRoot ("{0}-panoptic-{1}" -f $job.job_id, $runToken)
$framesRoot = Join-Path $workRoot "frames"
$streamPath = Join-Path $workRoot "camera.mp4"
$ptsPath = Join-Path $workRoot "pts.json"
$timelinePath = Join-Path $workRoot "timeline.jsonl"
$publishRoot = Join-Path $derivedRoot (".{0}-panoptic-{1}.publish" -f $job.job_id, $runToken)
$stagingRoot = Join-Path $publishRoot "output"
$null = New-Item -ItemType Directory -Path $framesRoot
$null = New-Item -ItemType Directory -Path $publishRoot
$totalWatch = [Diagnostics.Stopwatch]::StartNew()
Write-Output "PHASE=private-staging-created"
try {
$stream = [IO.File]::Open($streamPath, [IO.FileMode]::CreateNew, [IO.FileAccess]::Write, [IO.FileShare]::None)
try {
foreach ($path in @($initPath)) {
$input = [IO.File]::OpenRead($path)
try {
$input.CopyTo($stream)
}
finally {
$input.Dispose()
}
}
for ($sequence = 1; $sequence -le $frameCount; $sequence++) {
$path = Assert-RegularFile (Join-Path $segmentsRoot ("{0}.m4s" -f $sequence)) "Camera segment"
$input = [IO.File]::OpenRead($path)
try {
$input.CopyTo($stream)
}
finally {
$input.Dispose()
}
if ($sequence % 500 -eq 0 -or $sequence -eq $frameCount) {
Write-Output ("PHASE=stream-reconstruction SEGMENTS={0}/{1}" -f $sequence, $frameCount)
}
}
$stream.Flush($true)
}
finally {
$stream.Dispose()
}
$extractWatch = [Diagnostics.Stopwatch]::StartNew()
Write-Output "PHASE=frame-extraction-started"
# This archive contains valid strictly-increasing PTS but image2 rounds DTS
# to its own time base and reports harmless duplicate-DTS diagnostics. Exact
# frame-count and JSON timestamp checks below are the admission boundary.
& ffmpeg -hide_banner -loglevel fatal -i $streamPath -map 0:v:0 -fps_mode passthrough (Join-Path $framesRoot "frame-%06d.png")
Assert-LastExitCode "Camera extraction"
& ffprobe -v error -select_streams v:0 -show_entries frame=best_effort_timestamp_time -of json $streamPath | Set-Content -LiteralPath $ptsPath -Encoding utf8
Assert-LastExitCode "Camera timestamp probe"
$decodedFrames = @(Get-ChildItem -LiteralPath $framesRoot -File -Filter "frame-*.png")
$ptsDocument = Get-Content -LiteralPath $ptsPath -Raw | ConvertFrom-Json
$pts = @($ptsDocument.frames)
if ($decodedFrames.Count -ne $frameCount -or $pts.Count -ne $frameCount) {
throw "Decoded frame count differs from the compute job"
}
$firstEpochSeconds = [double]::Parse(
([string]$pts[0].best_effort_timestamp_time).Trim(),
[Globalization.CultureInfo]::InvariantCulture
)
$previousEpochSeconds = -1.0
$timelineWriter = [IO.StreamWriter]::new($timelinePath, $false, [Text.UTF8Encoding]::new($false))
try {
for ($index = 0; $index -lt $frameCount; $index++) {
$epochSeconds = [double]::Parse(
([string]$pts[$index].best_effort_timestamp_time).Trim(),
[Globalization.CultureInfo]::InvariantCulture
) - $firstEpochSeconds
if ($epochSeconds -le $previousEpochSeconds -or $epochSeconds -gt ($timelineDuration + 0.001)) {
throw "Decoded camera timestamps are not strictly monotonic inside the compute job timeline"
}
$sessionSeconds = $timelineStart + $epochSeconds
$row = [ordered]@{
frame_index = $index
epoch_seconds = $epochSeconds
session_seconds = $sessionSeconds
}
$timelineWriter.WriteLine(($row | ConvertTo-Json -Compress))
$previousEpochSeconds = $epochSeconds
}
$timelineWriter.Flush()
}
finally {
$timelineWriter.Dispose()
}
$extractWatch.Stop()
Write-Output ("PHASE=frame-extraction-complete FRAMES={0}" -f $frameCount)
$dockerArgs = @(
"run", "--rm", "--gpus", "all", "--network", "none",
"--security-opt", "no-new-privileges:true", "--cap-drop", "ALL",
"--shm-size", "2g",
"-e", "PYTHONPATH=/opt/transformers:/opt/env",
"-e", "TORCH_HOME=/cache/torch",
"-e", "HF_HOME=/cache/huggingface",
"-e", "HF_HUB_OFFLINE=1",
"-e", "TRANSFORMERS_OFFLINE=1",
"-v", ((Convert-ToDockerPath $jobDirectory) + ":/job:ro"),
"-v", ((Convert-ToDockerPath $framesRoot) + ":/frames:ro"),
"-v", ((Convert-ToDockerPath $workRoot) + ":/work:ro"),
"-v", ((Convert-ToDockerPath $publishRoot) + ":/publish:rw"),
"-v", ((Convert-ToDockerPath $cacheRoot) + ":/cache:rw"),
"-v", ((Convert-ToDockerPath $torchEnvironment) + ":/opt/env:ro"),
"-v", ((Convert-ToDockerPath $transformersEnvironment) + ":/opt/transformers:ro"),
"-v", ((Convert-ToDockerPath $runnerRoot) + ":/runner:ro"),
"--entrypoint", "python3",
"nvcr.io/nvidia/tritonserver:26.06-py3",
("/runner/{0}" -f $runnerName), "run",
"--job", "/job",
"--frames", "/frames",
"--timeline", "/work/timeline.jsonl",
"--output", "/publish/output",
"--cache", "/cache",
"--calibration-sha256", $CalibrationSha256,
"--calibration-slot", $CalibrationSlot,
"--telemetry-interval-seconds", "1"
)
& docker @dockerArgs
Assert-LastExitCode "Panoptic inference"
Write-Output "PHASE=panoptic-inference-complete"
$videoPath = Join-Path $stagingRoot "perception.mp4"
$encodeWatch = [Diagnostics.Stopwatch]::StartNew()
$averageFps = $frameCount / $timelineDuration
$fpsText = $averageFps.ToString("0.#########", [Globalization.CultureInfo]::InvariantCulture)
$durationText = $timelineDuration.ToString("0.#########", [Globalization.CultureInfo]::InvariantCulture)
& ffmpeg -hide_banner -loglevel error -framerate $fpsText -i (Join-Path $stagingRoot "overlay-frames\frame-%06d.png") -t $durationText -c:v h264_nvenc -preset p4 -tune hq -rc vbr -cq 21 -b:v 0 -pix_fmt yuv420p -movflags +faststart $videoPath
Assert-LastExitCode "Panoptic video encoding"
$encodeWatch.Stop()
Write-Output "PHASE=video-encoding-complete"
$masksPath = Join-Path $stagingRoot "masks.tar.gz"
& tar.exe -czf $masksPath -C $stagingRoot instance-masks semantic-masks
Assert-LastExitCode "Mask archive publication"
$totalWatch.Stop()
$finalizeArgs = @(
"run", "--rm", "--network", "none",
"--security-opt", "no-new-privileges:true", "--cap-drop", "ALL",
"-v", ((Convert-ToDockerPath $stagingRoot) + ":/output:rw"),
"-v", ((Convert-ToDockerPath $runnerRoot) + ":/runner:ro"),
"--entrypoint", "python3",
"nvcr.io/nvidia/tritonserver:26.06-py3",
("/runner/{0}" -f $runnerName), "finalize",
"--output", "/output",
"--video", "/output/perception.mp4",
"--masks", "/output/masks.tar.gz",
"--extract-seconds", $extractWatch.Elapsed.TotalSeconds.ToString("0.######", [Globalization.CultureInfo]::InvariantCulture),
"--encode-seconds", $encodeWatch.Elapsed.TotalSeconds.ToString("0.######", [Globalization.CultureInfo]::InvariantCulture),
"--wall-seconds", $totalWatch.Elapsed.TotalSeconds.ToString("0.######", [Globalization.CultureInfo]::InvariantCulture),
"--encoder", "ffmpeg-h264_nvenc-p4-cq21-yuv420p-faststart"
)
& docker @finalizeArgs
Assert-LastExitCode "Result finalization"
$result = Get-Content -LiteralPath (Join-Path $stagingRoot "result.json") -Raw | ConvertFrom-Json
if ($result.schema_version -ne "missioncore.recorded-perception-result/v2" -or $result.result_id -notmatch "^result-[a-f0-9]{64}$") {
throw "Final result manifest is incompatible"
}
$finalRoot = Join-Path $derivedRoot ([string]$result.result_id)
if (Test-Path -LiteralPath $finalRoot) {
throw "An immutable result with the same identity already exists: $finalRoot"
}
foreach ($temporaryChild in @("overlay-frames", "instance-masks", "semantic-masks")) {
$temporaryPath = Join-Path $stagingRoot $temporaryChild
if (Test-Path -LiteralPath $temporaryPath) {
Remove-Item -LiteralPath $temporaryPath -Recurse -Force
}
}
Move-Item -LiteralPath $stagingRoot -Destination $finalRoot
Remove-Item -LiteralPath $publishRoot -Force
Write-Output ("RESULT_ROOT={0}" -f $finalRoot)
Write-Output ("RESULT_ID={0}" -f $result.result_id)
}
finally {
if (Test-Path -LiteralPath $workRoot) {
Remove-Item -LiteralPath $workRoot -Recurse -Force
}
}
@@ -0,0 +1,62 @@
# Mission Core CVAT D-only profile
This profile installs the annotation control plane in a dedicated WSL2
distribution named `MissionCore-CVAT`. Its VHDX, Docker image store, CVAT
source, persistent volumes, reports, and imported datasets live below
`D:\NDC_MISSIONCORE`. It does not use the Docker Desktop image store that backs
the Triton, Frigate, and Ollama containers.
Pinned inputs:
- Ubuntu 24.04.4 WSL AMD64 image, SHA-256
`9b2f7730dc68227dd04a9f3e5eab86ad85caf556b8606ad94f1f29ff5c4fd3f5`
- CVAT `v2.70.0`
- D free-space floor: `360 GiB`
- WSL VHD logical ceiling: `32 GB` (sparse allocation)
The official CVAT Compose topology is retained. The override only replaces its
named volumes with explicit bind-backed directories inside the D-hosted WSL
VHD. Images are pulled serially and the D free-space floor is checked before and
after every image.
Run from the Windows host:
```powershell
wsl -d MissionCore-CVAT -u root -- bash /mnt/d/NDC_MISSIONCORE/workspace/mission-core-compute/cvat/provision_cvat_wsl.sh
wsl -d MissionCore-CVAT -u root -- bash /mnt/d/NDC_MISSIONCORE/workspace/mission-core-compute/cvat/ensure_cvat_admin.sh
wsl -d MissionCore-CVAT -u root -- bash /mnt/d/NDC_MISSIONCORE/workspace/mission-core-compute/cvat/import_e2_workspace.sh
```
After a Windows reboot, start the existing deployment without pulling images or
re-provisioning it:
```powershell
& D:\NDC_MISSIONCORE\workspace\mission-core-compute\cvat\Start-Cvat.ps1
```
The launcher checks the `360 GiB` D-drive floor, starts the pinned Compose
topology in the D-hosted WSL distribution, waits for the API, and keeps the WSL
runtime alive. It writes startup logs only below
`D:\NDC_MISSIONCORE\runtime\annotation\cvat\logs`.
From the Mission Core repository on the Mac, start CVAT if needed, discover the
current WSL address, and open the SSH tunnel without a hard-coded IP:
```bash
bash experiments/perception/worker/cvat/open_cvat_tunnel.sh
```
Keep that terminal open and use `http://localhost:18080`. The same SSH session
keeps the WSL runtime alive. Pass `--background` when detached runtime and
tunnel sessions are preferred; rerun the helper after a Mac or Windows reboot.
The generated administrator password is stored only in
`D:\NDC_MISSIONCORE\secrets\cvat\admin.env`; it is not printed by the script or
committed to Git.
Traefik binds inside the dedicated WSL environment to `127.0.0.1:8080` and
`127.0.0.1:8090`. It also publishes container port `8080` as WSL-internal port
`18080` so the existing Windows SSH service can forward it without relying on
Windows-to-WSL localhost forwarding. Remote review still uses the exact SSH
host alias and a local forward; this profile does not add routes, Windows port
proxies, DNS changes, or firewall rules.
@@ -0,0 +1,58 @@
[CmdletBinding()]
param(
[int]$TimeoutSeconds = 180
)
$ErrorActionPreference = 'Stop'
$Distro = 'MissionCore-CVAT'
$Root = 'D:\NDC_MISSIONCORE'
$RuntimeRoot = Join-Path $Root 'runtime\annotation\cvat'
$LogRoot = Join-Path $RuntimeRoot 'logs'
$LinuxStartScript = '/mnt/d/NDC_MISSIONCORE/workspace/mission-core-compute/cvat/start_cvat_runtime.sh'
$FreeGiBFloor = 360
$drive = Get-PSDrive -Name D
$freeGiB = [math]::Floor($drive.Free / 1GB)
if ($freeGiB -lt $FreeGiBFloor) {
throw "D: free-space floor crossed ($freeGiB GiB free; $FreeGiBFloor GiB required)"
}
try {
$about = Invoke-RestMethod -Uri 'http://localhost:8080/api/server/about' -TimeoutSec 3
if ($about.version -eq '2.70.0') {
Write-Output "CVAT already ready version=$($about.version) free_gib=$freeGiB"
exit 0
}
} catch {
# A stopped WSL distribution is the normal condition after a Windows reboot.
}
New-Item -ItemType Directory -Path $LogRoot -Force | Out-Null
$timestamp = (Get-Date).ToUniversalTime().ToString('yyyyMMddTHHmmssZ')
$stdoutPath = Join-Path $LogRoot "start-$timestamp.stdout.log"
$stderrPath = Join-Path $LogRoot "start-$timestamp.stderr.log"
$arguments = @(
'-d', $Distro,
'-u', 'root',
'--', 'bash', $LinuxStartScript, '--keepalive'
)
Start-Process -FilePath 'wsl.exe' -ArgumentList $arguments -WindowStyle Hidden `
-RedirectStandardOutput $stdoutPath -RedirectStandardError $stderrPath
$deadline = (Get-Date).AddSeconds($TimeoutSeconds)
do {
Start-Sleep -Seconds 2
try {
$about = Invoke-RestMethod -Uri 'http://localhost:8080/api/server/about' -TimeoutSec 3
if ($about.version -eq '2.70.0') {
Write-Output "CVAT ready version=$($about.version) free_gib=$freeGiB"
Write-Output "startup_log=$stdoutPath"
exit 0
}
} catch {
# Continue until the complete CVAT Compose topology is ready.
}
} while ((Get-Date) -lt $deadline)
throw "CVAT did not become ready within $TimeoutSeconds seconds; inspect $stderrPath"
@@ -0,0 +1,50 @@
services:
traefik:
ports: !override
- 127.0.0.1:8080:8080
- 127.0.0.1:8090:8090
- 0.0.0.0:18080:8080
volumes:
cvat_db:
driver: local
driver_opts:
type: none
o: bind
device: /srv/mission-core-cvat/volumes/cvat_db
cvat_data:
driver: local
driver_opts:
type: none
o: bind
device: /srv/mission-core-cvat/volumes/cvat_data
cvat_keys:
driver: local
driver_opts:
type: none
o: bind
device: /srv/mission-core-cvat/volumes/cvat_keys
cvat_logs:
driver: local
driver_opts:
type: none
o: bind
device: /srv/mission-core-cvat/volumes/cvat_logs
cvat_inmem_db:
driver: local
driver_opts:
type: none
o: bind
device: /srv/mission-core-cvat/volumes/cvat_inmem_db
cvat_events_db:
driver: local
driver_opts:
type: none
o: bind
device: /srv/mission-core-cvat/volumes/cvat_events_db
cvat_cache_db:
driver: local
driver_opts:
type: none
o: bind
device: /srv/mission-core-cvat/volumes/cvat_cache_db
@@ -0,0 +1,39 @@
#!/usr/bin/env bash
set -Eeuo pipefail
export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
readonly SECRET_ROOT="/mnt/d/NDC_MISSIONCORE/secrets/cvat"
readonly SECRET_FILE="${SECRET_ROOT}/admin.env"
if [[ "${EUID}" -ne 0 ]]; then
echo "ensure_cvat_admin.sh must run as root" >&2
exit 2
fi
install -d -m 0700 "${SECRET_ROOT}"
if [[ ! -f "${SECRET_FILE}" ]]; then
umask 077
password="$(openssl rand -hex 24)"
{
printf 'CVAT_ADMIN_USERNAME=missioncore\n'
printf 'CVAT_ADMIN_EMAIL=missioncore@local.invalid\n'
printf 'CVAT_ADMIN_PASSWORD=%s\n' "${password}"
} >"${SECRET_FILE}"
fi
set -a
# shellcheck disable=SC1090
. "${SECRET_FILE}"
set +a
docker exec \
-e "CVAT_ADMIN_USERNAME=${CVAT_ADMIN_USERNAME}" \
-e "CVAT_ADMIN_EMAIL=${CVAT_ADMIN_EMAIL}" \
-e "CVAT_ADMIN_PASSWORD=${CVAT_ADMIN_PASSWORD}" \
cvat_server \
python3 /home/django/manage.py shell -c \
'import os; from django.contrib.auth import get_user_model; User = get_user_model(); user, _ = User.objects.get_or_create(username=os.environ["CVAT_ADMIN_USERNAME"]); user.email = os.environ["CVAT_ADMIN_EMAIL"]; user.is_staff = True; user.is_superuser = True; user.set_password(os.environ["CVAT_ADMIN_PASSWORD"]); user.save()'
printf 'admin_ready=true\nusername=%s\nsecret_file=%s\n' \
"${CVAT_ADMIN_USERNAME}" "${SECRET_FILE}"
@@ -0,0 +1,284 @@
from __future__ import annotations
import argparse
import hashlib
import json
import os
import time
from collections import Counter
from datetime import UTC, datetime
from pathlib import Path
from typing import Any
from cvat_sdk import make_client, models
from cvat_sdk.api_client.exceptions import ServiceException
from cvat_sdk.core.proxies.tasks import ResourceType
WORKSPACE_ID = (
"annotation-workspace-"
"9a950d1c37d56dc12cc285b13c5addd7795285879cbcb1fbb2d5811c3c69821a"
)
EVALUATION_PACK_ID = (
"evaluation-pack-"
"7a983bba75d46c7c260252cb2d461e1384dcb92cda9e164397e841e6ebb37789"
)
EXPECTED_FRAME_COUNT = 64
EXPECTED_INSTANCE_COUNT = 775
BACKGROUND_LABEL = {
"name": "background",
"color": "#000000",
"attributes": [],
}
def _sha256(path: Path) -> str:
digest = hashlib.sha256()
with path.open("rb") as source:
for chunk in iter(lambda: source.read(1024 * 1024), b""):
digest.update(chunk)
return digest.hexdigest()
def _label_specs(raw_labels: list[dict[str, Any]]) -> list[dict[str, Any]]:
labels = [
{
"name": item["name"],
"color": item["color"],
"attributes": [],
}
for item in raw_labels
]
if not any(label["name"] == BACKGROUND_LABEL["name"] for label in labels):
labels.insert(0, dict(BACKGROUND_LABEL))
return labels
def _annotation_counts(task: Any) -> dict[str, int]:
annotations = task.get_annotations()
return {
"shape_count": len(annotations.shapes),
"tag_count": len(annotations.tags),
"track_count": len(annotations.tracks),
}
def _list_tasks_when_ready(client: Any, *, attempts: int = 60) -> list[Any]:
for attempt in range(1, attempts + 1):
try:
return list(client.tasks.list())
except ServiceException as error:
if error.status not in {500, 502, 503} or attempt == attempts:
raise
time.sleep(2)
raise AssertionError("unreachable")
def _task_record(task: Any, *, disposition: str, expected_labels: list[str]) -> dict[str, Any]:
task.fetch()
task_labels = list(task.get_labels())
actual_labels = sorted(label.name for label in task_labels)
if task.size != EXPECTED_FRAME_COUNT:
raise RuntimeError(
f"Task {task.id} has {task.size} frames, expected {EXPECTED_FRAME_COUNT}"
)
if actual_labels != sorted(expected_labels):
raise RuntimeError(
f"Task {task.id} labels differ: actual={actual_labels!r} "
f"expected={sorted(expected_labels)!r}"
)
annotation_counts = _annotation_counts(task)
label_names_by_id = {label.id: label.name for label in task_labels}
annotations = task.get_annotations()
shape_counts_by_label = dict(
sorted(
Counter(
label_names_by_id.get(shape.label_id, f"unknown:{shape.label_id}")
for shape in annotations.shapes
).items()
)
)
return {
"id": task.id,
"name": task.name,
"disposition": disposition,
"frame_count": task.size,
"label_names": actual_labels,
**annotation_counts,
"shape_counts_by_label": shape_counts_by_label,
"url_path": f"/tasks/{task.id}",
}
def _ensure_task(
client: Any,
*,
name: str,
labels: list[dict[str, Any]],
images_path: Path,
annotation_path: Path,
annotation_format: str,
expected_shape_count: int | None,
) -> dict[str, Any]:
matches = [task for task in _list_tasks_when_ready(client) if task.name == name]
if len(matches) > 1:
raise RuntimeError(f"Multiple CVAT tasks have the reserved name {name!r}")
expected_labels = [label["name"] for label in labels]
if matches:
task = matches[0]
task.fetch()
actual_labels = sorted(label.name for label in task.get_labels())
expected_without_background = sorted(
label for label in expected_labels if label != BACKGROUND_LABEL["name"]
)
disposition = "reused"
if (
actual_labels == expected_without_background
and BACKGROUND_LABEL["name"] in expected_labels
):
task.update(
models.PatchedTaskWriteRequest(
labels=[models.PatchedLabelRequest(**BACKGROUND_LABEL)]
)
)
disposition = "reused-and-background-label-added"
record = _task_record(
task,
disposition=disposition,
expected_labels=expected_labels,
)
if record["shape_count"] == 0:
task.import_annotations(annotation_format, annotation_path)
record = _task_record(
task,
disposition=f"{disposition}-and-annotations-imported",
expected_labels=expected_labels,
)
if expected_shape_count is not None and record["shape_count"] != expected_shape_count:
raise RuntimeError(
f"Task {task.id} has {record['shape_count']} shapes, "
f"expected {expected_shape_count}"
)
return record
task = client.tasks.create_from_data(
spec=models.TaskWriteRequest(
name=name,
labels=labels,
segment_size=EXPECTED_FRAME_COUNT,
overlap=0,
),
resources=[images_path],
resource_type=ResourceType.LOCAL,
data_params={
"image_quality": 100,
"sorting_method": "lexicographical",
"use_cache": False,
},
annotation_path=annotation_path,
annotation_format=annotation_format,
status_check_period=2,
)
record = _task_record(task, disposition="created", expected_labels=expected_labels)
if expected_shape_count is not None and record["shape_count"] != expected_shape_count:
raise RuntimeError(
f"Task {task.id} has {record['shape_count']} shapes, "
f"expected {expected_shape_count}"
)
return record
def main() -> None:
parser = argparse.ArgumentParser()
parser.add_argument("--server", required=True)
parser.add_argument("--username", required=True)
parser.add_argument("--password-env", required=True)
parser.add_argument("--workspace", type=Path, required=True)
parser.add_argument("--report", type=Path, required=True)
args = parser.parse_args()
password = os.environ.get(args.password_env)
if not password:
raise RuntimeError(f"Password environment variable {args.password_env!r} is empty")
workspace = args.workspace.resolve()
if workspace.name != WORKSPACE_ID:
raise RuntimeError(f"Unexpected annotation workspace: {workspace}")
manifest_path = workspace / "manifest.json"
labels_path = workspace / "cvat" / "labels.json"
images_path = workspace / "cvat" / "images.zip"
instance_path = workspace / "cvat" / "instance-coco.zip"
semantic_path = workspace / "cvat" / "semantic-mask.zip"
manifest = json.loads(manifest_path.read_text(encoding="utf-8"))
labels = json.loads(labels_path.read_text(encoding="utf-8"))
if manifest["ground_truth"] is not False:
raise RuntimeError("LAB E2 import must remain an unreviewed model draft")
if manifest["identity"]["frame_count"] != EXPECTED_FRAME_COUNT:
raise RuntimeError("Unexpected LAB E2 frame count")
if manifest["identity"]["draft_instance_count"] != EXPECTED_INSTANCE_COUNT:
raise RuntimeError("Unexpected LAB E2 instance count")
task_specs = [
{
"name": "LAB E2 | K1 | instance prelabels | pack 7a983bba",
"labels": _label_specs(labels["instance_task"]),
"annotation_path": instance_path,
"annotation_format": "COCO 1.0",
"expected_shape_count": EXPECTED_INSTANCE_COUNT,
},
{
"name": "LAB E2 | K1 | dense semantic prelabels | pack 7a983bba",
"labels": _label_specs(labels["semantic_task"]),
"annotation_path": semantic_path,
"annotation_format": "Segmentation mask 1.1",
"expected_shape_count": None,
},
]
with make_client(args.server, credentials=(args.username, password)) as client:
client.check_server_version(fail_if_unsupported=True)
task_records = [
_ensure_task(
client,
name=task_spec["name"],
labels=task_spec["labels"],
images_path=images_path,
annotation_path=task_spec["annotation_path"],
annotation_format=task_spec["annotation_format"],
expected_shape_count=task_spec["expected_shape_count"],
)
for task_spec in task_specs
]
report = {
"schema_version": "missioncore.lab-e2-cvat-import/v1",
"created_at_utc": datetime.now(UTC).isoformat(timespec="milliseconds").replace(
"+00:00", "Z"
),
"server": args.server,
"cvat_version": "v2.70.0",
"workspace_id": WORKSPACE_ID,
"evaluation_pack_id": EVALUATION_PACK_ID,
"workspace_manifest_sha256": _sha256(manifest_path),
"ground_truth": False,
"inputs": {
"images_zip_sha256": _sha256(images_path),
"instance_coco_zip_sha256": _sha256(instance_path),
"semantic_mask_zip_sha256": _sha256(semantic_path),
},
"tasks": task_records,
"next_gate": (
"two-pass human review and reviewed export; "
"do not treat drafts as accuracy evidence"
),
}
args.report.parent.mkdir(parents=True, exist_ok=True)
args.report.write_text(json.dumps(report, indent=2) + "\n", encoding="utf-8")
print(json.dumps(report, indent=2))
if __name__ == "__main__":
main()
@@ -0,0 +1,89 @@
#!/usr/bin/env bash
set -Eeuo pipefail
export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
readonly FREE_GIB_FLOOR="${FREE_GIB_FLOOR:-360}"
readonly WINDOWS_ROOT="/mnt/d/NDC_MISSIONCORE"
readonly COMPUTE_ROOT="${WINDOWS_ROOT}/workspace/mission-core-compute"
readonly TOOL_ROOT="/srv/mission-core-cvat/tools/e2-import"
readonly SECRET_FILE="${WINDOWS_ROOT}/secrets/cvat/admin.env"
readonly WORKSPACE_ROOT="${WINDOWS_ROOT}/runtime/annotation/imports/LAB-E2/annotation-workspace-9a950d1c37d56dc12cc285b13c5addd7795285879cbcb1fbb2d5811c3c69821a"
readonly REPORT_ROOT="${WINDOWS_ROOT}/runtime/annotation/cvat/reports"
if [[ "${EUID}" -ne 0 ]]; then
echo "import_e2_workspace.sh must run as root" >&2
exit 2
fi
free_gib() {
df -BG --output=avail "${WINDOWS_ROOT}" | tail -n 1 | tr -dc '0-9'
}
guard_disk() {
local stage="$1"
local free
free="$(free_gib)"
printf 'disk_guard stage=%s free_gib=%s floor_gib=%s\n' \
"${stage}" "${free}" "${FREE_GIB_FLOOR}"
if (( free < FREE_GIB_FLOOR )); then
echo "D: free-space floor crossed; refusing further writes" >&2
exit 3
fi
}
wait_for_cvat() {
local attempt http_code
for attempt in $(seq 1 60); do
http_code="$(
curl --silent --output /dev/null --write-out '%{http_code}' \
"http://localhost:8080/api/server/about" || true
)"
if [[ "${http_code}" == "200" ]]; then
http_code="$(
curl --silent --output /dev/null --write-out '%{http_code}' \
"http://localhost:8080/api/tasks" || true
)"
if [[ "${http_code}" == "200" || "${http_code}" == "401" || "${http_code}" == "403" ]]; then
printf 'cvat_ready attempt=%s tasks_http=%s\n' "${attempt}" "${http_code}"
return 0
fi
fi
sleep 2
done
echo "CVAT API did not become ready within 120 seconds" >&2
return 1
}
test -f "${SECRET_FILE}"
test -f "${WORKSPACE_ROOT}/manifest.json"
test -f "${COMPUTE_ROOT}/cvat/import_e2_workspace.py"
guard_disk preflight
export DEBIAN_FRONTEND=noninteractive
apt-get update
apt-get install -y python3-venv
install -d -m 0750 "${TOOL_ROOT}" "${REPORT_ROOT}"
if [[ ! -x "${TOOL_ROOT}/venv/bin/python" ]]; then
python3 -m venv "${TOOL_ROOT}/venv"
"${TOOL_ROOT}/venv/bin/pip" install --disable-pip-version-check \
"cvat-sdk==2.70.0"
fi
set -a
# shellcheck disable=SC1090
. "${SECRET_FILE}"
set +a
wait_for_cvat
report="${REPORT_ROOT}/lab-e2-cvat-import-$(date -u +%Y%m%dT%H%M%SZ).json"
"${TOOL_ROOT}/venv/bin/python" "${COMPUTE_ROOT}/cvat/import_e2_workspace.py" \
--server "http://localhost:8080" \
--username "${CVAT_ADMIN_USERNAME}" \
--password-env CVAT_ADMIN_PASSWORD \
--workspace "${WORKSPACE_ROOT}" \
--report "${report}"
guard_disk imported
printf 'import_report=%s\n' "${report}"
@@ -0,0 +1,179 @@
from __future__ import annotations
import argparse
import hashlib
import json
import os
from datetime import UTC, datetime
from pathlib import Path, PurePosixPath
from typing import Any
from cvat_sdk import make_client
from import_e2_workspace import _ensure_task, _label_specs, _sha256
WORKSPACE_SCHEMA = "missioncore.lab-e3-cvat-review-workspace/v1"
IDENTITY_SCHEMA = "missioncore.lab-e3-cvat-review-identity/v1"
EXPECTED_PACK_ID = (
"evaluation-pack-"
"7a983bba75d46c7c260252cb2d461e1384dcb92cda9e164397e841e6ebb37789"
)
EXPECTED_RESULT_ID = (
"e3-segmentation-"
"01bd497c44c2b940add145ec784d3418010327bce0baddd4420b0925317e8a16"
)
EXPECTED_FRAMES = 64
def _canonical_json(value: object) -> bytes:
return json.dumps(
value,
ensure_ascii=False,
sort_keys=True,
separators=(",", ":"),
allow_nan=False,
).encode()
def _valid_sha256(value: object) -> bool:
return (
isinstance(value, str)
and len(value) == 64
and all(character in "0123456789abcdef" for character in value)
)
def _read_object(path: Path) -> dict[str, Any]:
value = json.loads(path.read_text(encoding="utf-8"))
if not isinstance(value, dict):
raise RuntimeError(f"JSON root is not an object: {path}")
return value
def _safe_artifact(root: Path, encoded: object) -> Path:
if not isinstance(encoded, str):
raise RuntimeError("artifact path is not a string")
relative = PurePosixPath(encoded)
if relative.is_absolute() or ".." in relative.parts or not relative.parts:
raise RuntimeError("artifact path is unsafe")
path = root.joinpath(*relative.parts).resolve(strict=True)
if not path.is_file() or not path.is_relative_to(root):
raise RuntimeError("artifact path escaped its root")
return path
def _workspace(root: Path, images_zip: Path) -> tuple[dict[str, Any], dict[str, Path]]:
manifest_path = root / "manifest.json"
manifest = _read_object(manifest_path)
identity = manifest.get("identity")
identity_sha256 = manifest.get("identity_sha256")
if (
manifest.get("schema_version") != WORKSPACE_SCHEMA
or manifest.get("ground_truth") is not False
or not isinstance(identity, dict)
or identity.get("schema_version") != IDENTITY_SCHEMA
or not _valid_sha256(identity_sha256)
or hashlib.sha256(_canonical_json(identity)).hexdigest() != identity_sha256
or manifest.get("workspace_id") != f"e3-cvat-review-{identity_sha256}"
or root.name != manifest.get("workspace_id")
or identity.get("evaluation_pack_id") != EXPECTED_PACK_ID
or identity.get("e3_result_id") != EXPECTED_RESULT_ID
or identity.get("frame_count") != EXPECTED_FRAMES
or _sha256(images_zip) != identity.get("images_zip_sha256")
):
raise RuntimeError("LAB E3 CVAT review workspace is incompatible")
artifacts: dict[str, Path] = {}
descriptors = manifest.get("artifacts")
if not isinstance(descriptors, list):
raise RuntimeError("LAB E3 CVAT artifact list is invalid")
for descriptor in descriptors:
if not isinstance(descriptor, dict):
raise RuntimeError("LAB E3 CVAT artifact descriptor is invalid")
path = _safe_artifact(root, descriptor.get("path"))
if (
path.stat().st_size != descriptor.get("bytes")
or not _valid_sha256(descriptor.get("sha256"))
or _sha256(path) != descriptor["sha256"]
):
raise RuntimeError(f"LAB E3 CVAT artifact changed: {path.name}")
artifacts[path.name] = path
if set(artifacts) != {
"labels.json",
"control-fisheye-mask.zip",
"challenger-kb4-cubemap5.zip",
}:
raise RuntimeError("LAB E3 CVAT artifact set changed")
return manifest, artifacts
def main() -> None:
parser = argparse.ArgumentParser()
parser.add_argument("--server", required=True)
parser.add_argument("--username", required=True)
parser.add_argument("--password-env", required=True)
parser.add_argument("--workspace", type=Path, required=True)
parser.add_argument("--images-zip", type=Path, required=True)
parser.add_argument("--report", type=Path, required=True)
args = parser.parse_args()
password = os.environ.get(args.password_env)
if not password:
raise RuntimeError(f"Password environment variable {args.password_env!r} is empty")
workspace = args.workspace.resolve(strict=True)
images_zip = args.images_zip.resolve(strict=True)
manifest, artifacts = _workspace(workspace, images_zip)
labels_document = _read_object(artifacts["labels.json"])
semantic_labels = labels_document.get("semantic_task")
if not isinstance(semantic_labels, list):
raise RuntimeError("semantic labels are absent")
labels = _label_specs(semantic_labels)
task_specs = (
{
"name": "LAB E3 | K1 | EoMT fisheye control | pack 7a983bba",
"annotation": artifacts["control-fisheye-mask.zip"],
"role": "control",
},
{
"name": "LAB E3 | K1 | EoMT KB4 cubemap5 challenger | pack 7a983bba",
"annotation": artifacts["challenger-kb4-cubemap5.zip"],
"role": "challenger",
},
)
with make_client(args.server, credentials=(args.username, password)) as client:
client.check_server_version(fail_if_unsupported=True)
tasks = []
for spec in task_specs:
record = _ensure_task(
client,
name=spec["name"],
labels=labels,
images_path=images_zip,
annotation_path=spec["annotation"],
annotation_format="Segmentation mask 1.1",
expected_shape_count=None,
)
record["role"] = spec["role"]
tasks.append(record)
report = {
"schema_version": "missioncore.lab-e3-cvat-import/v1",
"created_at_utc": datetime.now(UTC)
.isoformat(timespec="milliseconds")
.replace("+00:00", "Z"),
"server": args.server,
"cvat_version": "v2.70.0",
"workspace_id": manifest["workspace_id"],
"workspace_manifest_sha256": _sha256(workspace / "manifest.json"),
"evaluation_pack_id": EXPECTED_PACK_ID,
"e3_result_id": EXPECTED_RESULT_ID,
"ground_truth": False,
"priority_image_ids": manifest["identity"]["priority_image_ids"],
"tasks": tasks,
"next_gate": "two-pass human review and reviewed export",
}
args.report.parent.mkdir(parents=True, exist_ok=True)
args.report.write_text(json.dumps(report, indent=2) + "\n", encoding="utf-8")
print(json.dumps(report, indent=2))
if __name__ == "__main__":
main()
@@ -0,0 +1,79 @@
#!/usr/bin/env bash
set -Eeuo pipefail
export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
readonly FREE_GIB_FLOOR="${FREE_GIB_FLOOR:-360}"
readonly WINDOWS_ROOT="/mnt/d/NDC_MISSIONCORE"
readonly COMPUTE_ROOT="${WINDOWS_ROOT}/workspace/mission-core-compute"
readonly TOOL_ROOT="/srv/mission-core-cvat/tools/e2-import"
readonly SECRET_FILE="${WINDOWS_ROOT}/secrets/cvat/admin.env"
readonly WORKSPACE_ID="e3-cvat-review-ca599521e345446ca8e9af5a9013062099278e7317f83ff89740c6b092ddc52f"
readonly WORKSPACE_ROOT="${WINDOWS_ROOT}/runtime/annotation/imports/LAB-E3/${WORKSPACE_ID}"
readonly E2_WORKSPACE_ID="annotation-workspace-9a950d1c37d56dc12cc285b13c5addd7795285879cbcb1fbb2d5811c3c69821a"
readonly IMAGES_ZIP="${WINDOWS_ROOT}/runtime/annotation/imports/LAB-E2/${E2_WORKSPACE_ID}/cvat/images.zip"
readonly REPORT_ROOT="${WINDOWS_ROOT}/runtime/annotation/cvat/reports"
if [[ "${EUID}" -ne 0 ]]; then
echo "import_e3_review.sh must run as root" >&2
exit 2
fi
free_gib() {
df -BG --output=avail "${WINDOWS_ROOT}" | tail -n 1 | tr -dc '0-9'
}
guard_disk() {
local stage="$1"
local free
free="$(free_gib)"
printf 'disk_guard stage=%s free_gib=%s floor_gib=%s\n' \
"${stage}" "${free}" "${FREE_GIB_FLOOR}"
if (( free < FREE_GIB_FLOOR )); then
echo "D: free-space floor crossed; refusing further writes" >&2
exit 3
fi
}
wait_for_cvat() {
local attempt http_code
for attempt in $(seq 1 60); do
http_code="$(
curl --silent --output /dev/null --write-out '%{http_code}' \
"http://localhost:8080/api/server/about" || true
)"
if [[ "${http_code}" == "200" ]]; then
printf 'cvat_ready attempt=%s\n' "${attempt}"
return 0
fi
sleep 2
done
echo "CVAT API did not become ready within 120 seconds" >&2
return 1
}
test -x "${TOOL_ROOT}/venv/bin/python"
test -f "${SECRET_FILE}"
test -f "${WORKSPACE_ROOT}/manifest.json"
test -f "${IMAGES_ZIP}"
test -f "${COMPUTE_ROOT}/cvat/import_e2_workspace.py"
test -f "${COMPUTE_ROOT}/cvat/import_e3_review.py"
guard_disk preflight
set -a
# shellcheck disable=SC1090
. "${SECRET_FILE}"
set +a
wait_for_cvat
report="${REPORT_ROOT}/lab-e3-cvat-import-$(date -u +%Y%m%dT%H%M%SZ).json"
"${TOOL_ROOT}/venv/bin/python" "${COMPUTE_ROOT}/cvat/import_e3_review.py" \
--server "http://localhost:8080" \
--username "${CVAT_ADMIN_USERNAME}" \
--password-env CVAT_ADMIN_PASSWORD \
--workspace "${WORKSPACE_ROOT}" \
--images-zip "${IMAGES_ZIP}" \
--report "${report}"
guard_disk imported
printf 'import_report=%s\n' "${report}"
@@ -0,0 +1,91 @@
#!/usr/bin/env bash
set -Eeuo pipefail
readonly SSH_ALIAS="mission-gpu"
readonly LOCAL_PORT="${CVAT_LOCAL_PORT:-18080}"
readonly REMOTE_WSL_PORT="18080"
readonly LINUX_START_SCRIPT='/mnt/d/NDC_MISSIONCORE/workspace/mission-core-compute/cvat/start_cvat_runtime.sh'
if curl --max-time 2 --fail --silent \
"http://localhost:${LOCAL_PORT}/api/server/about" >/dev/null 2>&1; then
printf 'cvat_tunnel_ready url=http://localhost:%s\n' "${LOCAL_PORT}"
exit 0
fi
if command -v lsof >/dev/null \
&& lsof -nP -iTCP:"${LOCAL_PORT}" -sTCP:LISTEN >/dev/null 2>&1; then
echo "Local port ${LOCAL_PORT} is already occupied by a non-responsive process" >&2
exit 2
fi
runtime_command="wsl.exe -d MissionCore-CVAT -u root -- bash ${LINUX_START_SCRIPT} --keepalive"
background=false
if [[ "${1:-}" == "--background" ]]; then
background=true
ssh -f "${SSH_ALIAS}" "${runtime_command}"
else
ssh "${SSH_ALIAS}" "${runtime_command}" &
runtime_ssh_pid=$!
cleanup() {
if [[ -n "${tunnel_ssh_pid:-}" ]]; then
kill "${tunnel_ssh_pid}" 2>/dev/null || true
fi
kill "${runtime_ssh_pid}" 2>/dev/null || true
}
trap cleanup EXIT INT TERM
fi
for attempt in $(seq 1 30); do
cvat_ip="$(
ssh "${SSH_ALIAS}" \
"wsl.exe -d MissionCore-CVAT -u root -- hostname -I" \
| tr -d '\r' | awk '{print $1}'
)"
if [[ "${cvat_ip}" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
break
fi
sleep 1
done
if [[ ! "${cvat_ip:-}" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "MissionCore-CVAT did not return a valid WSL address" >&2
if [[ "${background}" == false ]]; then
kill "${runtime_ssh_pid}" 2>/dev/null || true
fi
exit 3
fi
forward=(
-N
-L "${LOCAL_PORT}:${cvat_ip}:${REMOTE_WSL_PORT}"
-o ExitOnForwardFailure=yes
"${SSH_ALIAS}"
)
if [[ "${background}" == true ]]; then
ssh -f "${forward[@]}"
else
ssh "${forward[@]}" &
tunnel_ssh_pid=$!
fi
for attempt in $(seq 1 60); do
if curl --max-time 2 --fail --silent \
"http://localhost:${LOCAL_PORT}/api/server/about" >/dev/null 2>&1; then
printf 'cvat_tunnel_ready url=http://localhost:%s wsl_ip=%s\n' \
"${LOCAL_PORT}" "${cvat_ip}"
if [[ "${background}" == true ]]; then
exit 0
fi
wait "${tunnel_ssh_pid}"
tunnel_status=$?
kill "${runtime_ssh_pid}" 2>/dev/null || true
exit "${tunnel_status}"
fi
sleep 2
done
echo "CVAT tunnel did not become ready within 120 seconds" >&2
if [[ "${background}" == false ]]; then
kill "${tunnel_ssh_pid}" "${runtime_ssh_pid}" 2>/dev/null || true
fi
exit 4
@@ -0,0 +1,132 @@
#!/usr/bin/env bash
set -Eeuo pipefail
# Do not inherit Windows executables into this D-only runtime. In particular,
# Docker Desktop's docker.exe belongs to a different image store.
export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
readonly CVAT_TAG="${CVAT_TAG:-v2.70.0}"
readonly FREE_GIB_FLOOR="${FREE_GIB_FLOOR:-360}"
readonly WINDOWS_ROOT="/mnt/d/NDC_MISSIONCORE"
readonly COMPUTE_ROOT="${WINDOWS_ROOT}/workspace/mission-core-compute"
readonly RUNTIME_ROOT="${WINDOWS_ROOT}/runtime/annotation/cvat"
readonly CVAT_ROOT="${RUNTIME_ROOT}/source/cvat-${CVAT_TAG}"
readonly STATE_ROOT="/srv/mission-core-cvat"
readonly OVERRIDE_FILE="${COMPUTE_ROOT}/cvat/docker-compose.override.yml"
if [[ "${EUID}" -ne 0 ]]; then
echo "provision_cvat_wsl.sh must run as root" >&2
exit 2
fi
free_gib() {
df -BG --output=avail "${WINDOWS_ROOT}" | tail -n 1 | tr -dc '0-9'
}
guard_disk() {
local stage="$1"
local free
free="$(free_gib)"
printf 'disk_guard stage=%s free_gib=%s floor_gib=%s\n' \
"${stage}" "${free}" "${FREE_GIB_FLOOR}"
if (( free < FREE_GIB_FLOOR )); then
echo "D: free-space floor crossed; refusing further writes" >&2
exit 3
fi
}
guard_disk preflight
export DEBIAN_FRONTEND=noninteractive
apt-get update
apt-get install -y ca-certificates curl git
if ! dpkg-query -W -f='${Status}' docker-ce 2>/dev/null \
| grep -qx 'install ok installed'; then
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
-o /etc/apt/keyrings/docker.asc
chmod a+r /etc/apt/keyrings/docker.asc
# shellcheck disable=SC1091
. /etc/os-release
arch="$(dpkg --print-architecture)"
printf 'deb [arch=%s signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu %s stable\n' \
"${arch}" "${VERSION_CODENAME}" >/etc/apt/sources.list.d/docker.list
apt-get update
apt-get install -y \
docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
fi
systemctl enable --now docker
docker version
docker compose version
guard_disk docker-engine
install -d -m 0750 \
"${STATE_ROOT}/volumes/cvat_db" \
"${STATE_ROOT}/volumes/cvat_data" \
"${STATE_ROOT}/volumes/cvat_keys" \
"${STATE_ROOT}/volumes/cvat_logs" \
"${STATE_ROOT}/volumes/cvat_inmem_db" \
"${STATE_ROOT}/volumes/cvat_events_db" \
"${STATE_ROOT}/volumes/cvat_cache_db" \
"${RUNTIME_ROOT}/source" \
"${RUNTIME_ROOT}/reports"
if [[ ! -d "${CVAT_ROOT}/.git" ]]; then
git clone --depth 1 --branch "${CVAT_TAG}" \
https://github.com/cvat-ai/cvat.git "${CVAT_ROOT}"
fi
test "$(git -C "${CVAT_ROOT}" describe --tags --exact-match)" = "${CVAT_TAG}"
test -f "${OVERRIDE_FILE}"
guard_disk cvat-source
export CVAT_VERSION="${CVAT_TAG}"
export CVAT_HOST="localhost"
export CVAT_HTTP_PORT="8080"
export COMPOSE_PROJECT_NAME="missioncore-cvat"
compose=(
docker compose
--project-directory "${CVAT_ROOT}"
-f "${CVAT_ROOT}/docker-compose.yml"
-f "${OVERRIDE_FILE}"
)
"${compose[@]}" config --quiet
mapfile -t images < <("${compose[@]}" config --images | sort -u)
for image in "${images[@]}"; do
guard_disk "before-pull:${image}"
docker pull "${image}"
guard_disk "after-pull:${image}"
done
"${compose[@]}" up -d --no-build
guard_disk cvat-started
deadline=$((SECONDS + 600))
until curl --fail --silent --show-error http://localhost:8080/api/server/about \
>/dev/null; do
if (( SECONDS >= deadline )); then
"${compose[@]}" ps
echo "CVAT did not become ready within 600 seconds" >&2
exit 4
fi
sleep 5
done
report="${RUNTIME_ROOT}/reports/deployment-$(date -u +%Y%m%dT%H%M%SZ).txt"
{
printf 'cvat_tag=%s\n' "${CVAT_TAG}"
printf 'cvat_commit=%s\n' "$(git -C "${CVAT_ROOT}" rev-parse HEAD)"
printf 'docker_version=%s\n' "$(docker version --format '{{.Server.Version}}')"
printf 'compose_version=%s\n' "$(docker compose version --short)"
printf 'free_gib=%s\n' "$(free_gib)"
printf 'generated_at_utc=%s\n' "$(date -u +%Y-%m-%dT%H:%M:%SZ)"
docker image inspect "${images[@]}" \
--format 'image={{index .RepoTags 0}} id={{.Id}} size={{.Size}}'
"${compose[@]}" ps
} | tee "${report}"
printf 'CVAT ready at http://localhost:8080\nreport=%s\n' "${report}"
@@ -0,0 +1,69 @@
#!/usr/bin/env bash
set -Eeuo pipefail
export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
readonly FREE_GIB_FLOOR="${FREE_GIB_FLOOR:-360}"
readonly WINDOWS_ROOT="/mnt/d/NDC_MISSIONCORE"
readonly COMPUTE_ROOT="${WINDOWS_ROOT}/workspace/mission-core-compute"
readonly CVAT_ROOT="${WINDOWS_ROOT}/runtime/annotation/cvat/source/cvat-v2.70.0"
readonly OVERRIDE_FILE="${COMPUTE_ROOT}/cvat/docker-compose.override.yml"
if [[ "${EUID}" -ne 0 ]]; then
echo "start_cvat_runtime.sh must run as root" >&2
exit 2
fi
free_gib="$(df -BG --output=avail "${WINDOWS_ROOT}" | tail -n 1 | tr -dc '0-9')"
printf 'disk_guard stage=start free_gib=%s floor_gib=%s\n' \
"${free_gib}" "${FREE_GIB_FLOOR}"
if (( free_gib < FREE_GIB_FLOOR )); then
echo "D: free-space floor crossed; refusing to start CVAT" >&2
exit 3
fi
test -f "${CVAT_ROOT}/docker-compose.yml"
test -f "${OVERRIDE_FILE}"
systemctl start docker
export CVAT_VERSION="v2.70.0"
export CVAT_HOST="localhost"
export CVAT_HTTP_PORT="8080"
export COMPOSE_PROJECT_NAME="missioncore-cvat"
compose=(
docker compose
--project-directory "${CVAT_ROOT}"
-f "${CVAT_ROOT}/docker-compose.yml"
-f "${OVERRIDE_FILE}"
)
"${compose[@]}" up -d --no-build
deadline=$((SECONDS + 180))
while true; do
about_http="$(
curl --silent --output /dev/null --write-out '%{http_code}' \
http://localhost:8080/api/server/about || true
)"
tasks_http="$(
curl --silent --output /dev/null --write-out '%{http_code}' \
http://localhost:8080/api/tasks || true
)"
if [[ "${about_http}" == "200" ]] \
&& [[ "${tasks_http}" == "200" || "${tasks_http}" == "401" || "${tasks_http}" == "403" ]]; then
break
fi
if (( SECONDS >= deadline )); then
"${compose[@]}" ps
echo "CVAT did not become ready within 180 seconds" >&2
exit 4
fi
sleep 2
done
printf 'cvat_ready about_http=%s tasks_http=%s free_gib=%s\n' \
"${about_http}" "${tasks_http}" "${free_gib}"
if [[ "${1:-}" == "--keepalive" ]]; then
exec sleep infinity
fi
@@ -0,0 +1,87 @@
{
"schema_version": "missioncore.e10-integrated-perception-profile/v1",
"mode": "full-session-qualification",
"source": {
"source_id": "sensor.camera.right",
"resolution": [800, 600],
"calibration_slot": "camera_1",
"calibration_sha256": "05f3ad9b38b3a4fc95388a8ec83da83c745e217709e51787b3d5aad0969f6fa9"
},
"selection": {
"required_frame_count": 4489,
"required_source_start_frame_index": 0,
"required_source_end_frame_index": 4488,
"minimum_source_span_seconds": 448.0
},
"replay": {
"speed": 1.0,
"detector_queue_capacity": 2,
"semantic_queue_capacity": 1,
"semantic_sample_every_frames": 5,
"semantic_ttl_ms": 750.0
},
"association": {
"box_inset": {
"bottom_fraction": 0.02,
"horizontal_fraction": 0.05,
"top_fraction": 0.04
},
"depth_cluster_gap_fraction": 0.06,
"depth_cluster_minimum_gap_m": 0.5,
"group_nms_iou_threshold": 0.55,
"maximum_cuboid_span_m": 12.0,
"maximum_distance_innovation_fraction": 0.25,
"maximum_distance_innovation_m": 1.5,
"maximum_oriented_extent_m": {
"bicycle": [3.5, 2.0, 2.5],
"motorcycle": [3.5, 2.0, 2.5],
"person": [1.5, 1.5, 2.8],
"vehicle": [6.5, 3.5, 4.0]
},
"minimum_cuboid_extent_m": 0.15,
"minimum_support_points": {
"bicycle": 3,
"motorcycle": 3,
"person": 3,
"vehicle": 5
},
"semantic_ids": {
"bicycle": [2],
"motorcycle": [3],
"person": [1],
"vehicle": [4, 5]
},
"spatial_cluster_radius_m": {
"bicycle": 0.9,
"motorcycle": 0.9,
"person": 0.9,
"vehicle": 1.5
},
"vehicle_labels": ["car", "truck", "bus"],
"distance_history_frames": 5
},
"world_state": {
"velocity_history_limit_s": 1.0,
"clearance": {
"sector_count": 72,
"minimum_range_m": 0.5,
"maximum_range_m": 30.0,
"ground_percentile": 5.0,
"minimum_height_above_ground_m": 0.2,
"maximum_height_above_ground_m": 3.0,
"front_half_angle_degrees": 15.0
}
},
"acceptance": {
"detector_minimum_effective_fps": 9.5,
"detector_maximum_drop_fraction": 0.0,
"maximum_p95_world_state_age_ms": 175.0,
"semantic_minimum_effective_fps": 1.8,
"semantic_maximum_drop_fraction": 0.05,
"semantic_maximum_p95_completion_age_ms": 400.0,
"minimum_fresh_semantic_coverage": 0.9,
"minimum_lidar_fused_frames": 3500,
"minimum_accepted_cuboids": 500,
"require_zero_failures": true
}
}
@@ -0,0 +1,81 @@
{
"schema_version": "missioncore.e10-integrated-perception-profile/v1",
"mode": "qualification",
"source": {
"source_id": "sensor.camera.right",
"resolution": [800, 600],
"calibration_slot": "camera_1",
"calibration_sha256": "05f3ad9b38b3a4fc95388a8ec83da83c745e217709e51787b3d5aad0969f6fa9"
},
"replay": {
"speed": 1.0,
"detector_queue_capacity": 2,
"semantic_queue_capacity": 1,
"semantic_sample_every_frames": 5,
"semantic_ttl_ms": 750.0
},
"association": {
"box_inset": {
"bottom_fraction": 0.02,
"horizontal_fraction": 0.05,
"top_fraction": 0.04
},
"depth_cluster_gap_fraction": 0.06,
"depth_cluster_minimum_gap_m": 0.5,
"group_nms_iou_threshold": 0.55,
"maximum_cuboid_span_m": 12.0,
"maximum_distance_innovation_fraction": 0.25,
"maximum_distance_innovation_m": 1.5,
"maximum_oriented_extent_m": {
"bicycle": [3.5, 2.0, 2.5],
"motorcycle": [3.5, 2.0, 2.5],
"person": [1.5, 1.5, 2.8],
"vehicle": [6.5, 3.5, 4.0]
},
"minimum_cuboid_extent_m": 0.15,
"minimum_support_points": {
"bicycle": 3,
"motorcycle": 3,
"person": 3,
"vehicle": 5
},
"semantic_ids": {
"bicycle": [2],
"motorcycle": [3],
"person": [1],
"vehicle": [4, 5]
},
"spatial_cluster_radius_m": {
"bicycle": 0.9,
"motorcycle": 0.9,
"person": 0.9,
"vehicle": 1.5
},
"vehicle_labels": ["car", "truck", "bus"],
"distance_history_frames": 5
},
"world_state": {
"velocity_history_limit_s": 1.0,
"clearance": {
"sector_count": 72,
"minimum_range_m": 0.5,
"maximum_range_m": 30.0,
"ground_percentile": 5.0,
"minimum_height_above_ground_m": 0.2,
"maximum_height_above_ground_m": 3.0,
"front_half_angle_degrees": 15.0
}
},
"acceptance": {
"detector_minimum_effective_fps": 9.5,
"detector_maximum_drop_fraction": 0.005,
"maximum_p95_world_state_age_ms": 175.0,
"semantic_minimum_effective_fps": 1.8,
"semantic_maximum_drop_fraction": 0.05,
"semantic_maximum_p95_completion_age_ms": 400.0,
"minimum_fresh_semantic_coverage": 0.9,
"minimum_lidar_fused_frames": 450,
"minimum_accepted_cuboids": 100,
"require_zero_failures": true
}
}
@@ -0,0 +1,78 @@
{
"schema_version": "missioncore.e10-integrated-perception-profile/v1",
"mode": "semantic-loss-negative-control",
"source": {
"source_id": "sensor.camera.right",
"resolution": [800, 600],
"calibration_slot": "camera_1",
"calibration_sha256": "05f3ad9b38b3a4fc95388a8ec83da83c745e217709e51787b3d5aad0969f6fa9"
},
"replay": {
"speed": 1.0,
"detector_queue_capacity": 2,
"semantic_queue_capacity": 1,
"semantic_sample_every_frames": 5,
"semantic_ttl_ms": 750.0
},
"semantic_loss": {
"stop_after_completed_results": 20
},
"association": {
"box_inset": {
"bottom_fraction": 0.02,
"horizontal_fraction": 0.05,
"top_fraction": 0.04
},
"depth_cluster_gap_fraction": 0.06,
"depth_cluster_minimum_gap_m": 0.5,
"group_nms_iou_threshold": 0.55,
"maximum_cuboid_span_m": 12.0,
"maximum_distance_innovation_fraction": 0.25,
"maximum_distance_innovation_m": 1.5,
"maximum_oriented_extent_m": {
"bicycle": [3.5, 2.0, 2.5],
"motorcycle": [3.5, 2.0, 2.5],
"person": [1.5, 1.5, 2.8],
"vehicle": [6.5, 3.5, 4.0]
},
"minimum_cuboid_extent_m": 0.15,
"minimum_support_points": {
"bicycle": 3,
"motorcycle": 3,
"person": 3,
"vehicle": 5
},
"semantic_ids": {
"bicycle": [2],
"motorcycle": [3],
"person": [1],
"vehicle": [4, 5]
},
"spatial_cluster_radius_m": {
"bicycle": 0.9,
"motorcycle": 0.9,
"person": 0.9,
"vehicle": 1.5
},
"vehicle_labels": ["car", "truck", "bus"],
"distance_history_frames": 5
},
"world_state": {
"velocity_history_limit_s": 1.0,
"clearance": {
"sector_count": 72,
"minimum_range_m": 0.5,
"maximum_range_m": 30.0,
"ground_percentile": 5.0,
"minimum_height_above_ground_m": 0.2,
"maximum_height_above_ground_m": 3.0,
"front_half_angle_degrees": 15.0
}
},
"acceptance": {
"detector_minimum_effective_fps": 9.5,
"detector_maximum_drop_fraction": 0.005,
"maximum_p95_world_state_age_ms": 175.0,
"minimum_stale_detector_frames": 450
}
}
@@ -0,0 +1,144 @@
{
"schema_version": "missioncore.e10-integrated-perception-profile/v1",
"mode": "pilot",
"source": {
"source_id": "sensor.camera.right",
"resolution": [800, 600],
"calibration_slot": "camera_1",
"calibration_sha256": "05f3ad9b38b3a4fc95388a8ec83da83c745e217709e51787b3d5aad0969f6fa9"
},
"replay": {
"speed": 1.0,
"detector_queue_capacity": 2,
"semantic_queue_capacity": 1,
"semantic_sample_every_frames": 5,
"semantic_ttl_ms": 750.0
},
"association": {
"box_inset": {
"bottom_fraction": 0.02,
"horizontal_fraction": 0.05,
"top_fraction": 0.04
},
"depth_cluster_gap_fraction": 0.06,
"depth_cluster_minimum_gap_m": 0.5,
"group_nms_iou_threshold": 0.5,
"maximum_cuboid_span_m": 15.0,
"maximum_distance_innovation_fraction": 0.25,
"maximum_distance_innovation_m": 1.5,
"maximum_oriented_extent_m": {
"bicycle": [3.5, 2.0, 2.5],
"motorcycle": [3.5, 2.0, 2.5],
"person": [1.5, 1.5, 2.8],
"vehicle": [12.5, 4.0, 4.5]
},
"minimum_cuboid_extent_m": 0.15,
"minimum_support_points": {
"bicycle": 4,
"motorcycle": 4,
"person": 4,
"vehicle": 8
},
"semantic_ids": {
"bicycle": [2],
"motorcycle": [3],
"person": [1],
"vehicle": [4, 5]
},
"spatial_cluster_radius_m": {
"bicycle": 0.9,
"motorcycle": 0.9,
"person": 0.9,
"vehicle": 1.5
},
"vehicle_labels": ["car", "truck", "bus"],
"distance_history_frames": 5
},
"cuboid_completion": {
"mode": "class-prior-amodal-v1",
"failure_policy": "reject",
"classes": {
"person": {
"nominal_size_m": [0.55, 0.55, 1.72],
"minimum_size_m": [0.35, 0.35, 1.3],
"maximum_size_m": [1.2, 1.2, 2.3],
"support_padding_m": [0.12, 0.12, 0.12]
},
"bicycle": {
"nominal_size_m": [1.8, 0.65, 1.5],
"minimum_size_m": [1.2, 0.4, 1.0],
"maximum_size_m": [2.5, 1.2, 2.2],
"support_padding_m": [0.18, 0.12, 0.12]
},
"motorcycle": {
"nominal_size_m": [2.1, 0.8, 1.45],
"minimum_size_m": [1.4, 0.5, 1.0],
"maximum_size_m": [3.0, 1.4, 2.2],
"support_padding_m": [0.2, 0.14, 0.14]
},
"car": {
"nominal_size_m": [4.5, 1.85, 1.55],
"minimum_size_m": [3.2, 1.45, 1.2],
"maximum_size_m": [5.8, 2.4, 2.3],
"support_padding_m": [0.25, 0.18, 0.15]
},
"truck": {
"nominal_size_m": [7.0, 2.5, 3.0],
"minimum_size_m": [4.8, 1.8, 1.8],
"maximum_size_m": [12.5, 3.2, 4.2],
"support_padding_m": [0.35, 0.22, 0.2]
},
"bus": {
"nominal_size_m": [10.5, 2.55, 3.2],
"minimum_size_m": [7.0, 2.1, 2.5],
"maximum_size_m": [13.5, 3.2, 4.2],
"support_padding_m": [0.4, 0.24, 0.2]
}
},
"ground": {
"local_radius_m": 2.5,
"lower_percentile": 8.0,
"maximum_below_support_m": 1.2,
"maximum_above_support_m": 0.15,
"fallback_below_support_m": 0.25
},
"orientation": {
"minimum_anisotropy_ratio": 1.35,
"face_width_switch_fraction": 1.05
},
"temporal": {
"center_alpha": 0.4,
"size_alpha": 0.2,
"yaw_alpha": 0.25,
"maximum_center_innovation_m": 2.0,
"maximum_yaw_innovation_degrees": 55.0,
"maximum_idle_s": 1.0,
"confirmation_hits": 3
},
"minimum_support_coverage_fraction": 0.75
},
"world_state": {
"velocity_history_limit_s": 1.0,
"clearance": {
"sector_count": 72,
"minimum_range_m": 0.5,
"maximum_range_m": 30.0,
"ground_percentile": 5.0,
"minimum_height_above_ground_m": 0.2,
"maximum_height_above_ground_m": 3.0,
"front_half_angle_degrees": 15.0
}
},
"acceptance": {
"detector_minimum_effective_fps": 9.5,
"detector_maximum_drop_fraction": 0.005,
"maximum_p95_world_state_age_ms": 175.0,
"semantic_minimum_effective_fps": 1.8,
"semantic_maximum_drop_fraction": 0.05,
"semantic_maximum_p95_completion_age_ms": 400.0,
"minimum_fresh_semantic_coverage": 0.9,
"minimum_lidar_fused_frames": 450,
"minimum_accepted_cuboids": 100,
"require_zero_failures": true
}
}
@@ -0,0 +1,150 @@
{
"schema_version": "missioncore.e10-integrated-perception-profile/v1",
"mode": "full-session-qualification",
"source": {
"source_id": "sensor.camera.right",
"resolution": [800, 600],
"calibration_slot": "camera_1",
"calibration_sha256": "05f3ad9b38b3a4fc95388a8ec83da83c745e217709e51787b3d5aad0969f6fa9"
},
"selection": {
"required_frame_count": 4489,
"required_source_start_frame_index": 0,
"required_source_end_frame_index": 4488,
"minimum_source_span_seconds": 448.0
},
"replay": {
"speed": 1.0,
"detector_queue_capacity": 2,
"semantic_queue_capacity": 1,
"semantic_sample_every_frames": 5,
"semantic_ttl_ms": 750.0
},
"association": {
"box_inset": {
"bottom_fraction": 0.02,
"horizontal_fraction": 0.05,
"top_fraction": 0.04
},
"depth_cluster_gap_fraction": 0.06,
"depth_cluster_minimum_gap_m": 0.5,
"group_nms_iou_threshold": 0.5,
"maximum_cuboid_span_m": 15.0,
"maximum_distance_innovation_fraction": 0.25,
"maximum_distance_innovation_m": 1.5,
"maximum_oriented_extent_m": {
"bicycle": [3.5, 2.0, 2.5],
"motorcycle": [3.5, 2.0, 2.5],
"person": [1.5, 1.5, 2.8],
"vehicle": [12.5, 4.0, 4.5]
},
"minimum_cuboid_extent_m": 0.15,
"minimum_support_points": {
"bicycle": 4,
"motorcycle": 4,
"person": 4,
"vehicle": 8
},
"semantic_ids": {
"bicycle": [2],
"motorcycle": [3],
"person": [1],
"vehicle": [4, 5]
},
"spatial_cluster_radius_m": {
"bicycle": 0.9,
"motorcycle": 0.9,
"person": 0.9,
"vehicle": 1.5
},
"vehicle_labels": ["car", "truck", "bus"],
"distance_history_frames": 5
},
"cuboid_completion": {
"mode": "class-prior-amodal-v1",
"failure_policy": "reject",
"classes": {
"person": {
"nominal_size_m": [0.55, 0.55, 1.72],
"minimum_size_m": [0.35, 0.35, 1.3],
"maximum_size_m": [1.2, 1.2, 2.3],
"support_padding_m": [0.12, 0.12, 0.12]
},
"bicycle": {
"nominal_size_m": [1.8, 0.65, 1.5],
"minimum_size_m": [1.2, 0.4, 1.0],
"maximum_size_m": [2.5, 1.2, 2.2],
"support_padding_m": [0.18, 0.12, 0.12]
},
"motorcycle": {
"nominal_size_m": [2.1, 0.8, 1.45],
"minimum_size_m": [1.4, 0.5, 1.0],
"maximum_size_m": [3.0, 1.4, 2.2],
"support_padding_m": [0.2, 0.14, 0.14]
},
"car": {
"nominal_size_m": [4.5, 1.85, 1.55],
"minimum_size_m": [3.2, 1.45, 1.2],
"maximum_size_m": [5.8, 2.4, 2.3],
"support_padding_m": [0.25, 0.18, 0.15]
},
"truck": {
"nominal_size_m": [7.0, 2.5, 3.0],
"minimum_size_m": [4.8, 1.8, 1.8],
"maximum_size_m": [12.5, 3.2, 4.2],
"support_padding_m": [0.35, 0.22, 0.2]
},
"bus": {
"nominal_size_m": [10.5, 2.55, 3.2],
"minimum_size_m": [7.0, 2.1, 2.5],
"maximum_size_m": [13.5, 3.2, 4.2],
"support_padding_m": [0.4, 0.24, 0.2]
}
},
"ground": {
"local_radius_m": 2.5,
"lower_percentile": 8.0,
"maximum_below_support_m": 1.2,
"maximum_above_support_m": 0.15,
"fallback_below_support_m": 0.25
},
"orientation": {
"minimum_anisotropy_ratio": 1.35,
"face_width_switch_fraction": 1.05
},
"temporal": {
"center_alpha": 0.4,
"size_alpha": 0.2,
"yaw_alpha": 0.25,
"maximum_center_innovation_m": 2.0,
"maximum_yaw_innovation_degrees": 55.0,
"maximum_idle_s": 1.0,
"confirmation_hits": 3
},
"minimum_support_coverage_fraction": 0.75
},
"world_state": {
"velocity_history_limit_s": 1.0,
"clearance": {
"sector_count": 72,
"minimum_range_m": 0.5,
"maximum_range_m": 30.0,
"ground_percentile": 5.0,
"minimum_height_above_ground_m": 0.2,
"maximum_height_above_ground_m": 3.0,
"front_half_angle_degrees": 15.0
}
},
"acceptance": {
"detector_minimum_effective_fps": 9.5,
"detector_maximum_drop_fraction": 0.005,
"maximum_p95_world_state_age_ms": 175.0,
"semantic_minimum_effective_fps": 1.8,
"semantic_maximum_drop_fraction": 0.05,
"semantic_maximum_p95_completion_age_ms": 400.0,
"minimum_fresh_semantic_coverage": 0.9,
"minimum_lidar_fused_frames": 3500,
"minimum_accepted_cuboids": 1500,
"require_zero_failures": true
}
}
@@ -0,0 +1,51 @@
{
"schema_version": "missioncore.e15-shadow-inference-profile/v1",
"mode": "replay-shadow-gate",
"authority": {
"commands_enabled": false,
"navigation_or_safety_accepted": false
},
"source": {
"source_id": "sensor.camera.right",
"resolution": [800, 600],
"calibration_slot": "camera_1",
"calibration_sha256": "05f3ad9b38b3a4fc95388a8ec83da83c745e217709e51787b3d5aad0969f6fa9"
},
"transport": {
"wire_schema": "missioncore.live-perception-wire/v1",
"camera_media": "persistent-fmp4-pyav",
"pyav_version": "18.0.0",
"maximum_media_buffer_bytes": 8388608,
"camera_metadata_capacity": 16
},
"scheduling": {
"detector_queue_capacity": 2,
"semantic_queue_capacity": 1,
"semantic_sample_every_frames": 5,
"semantic_ttl_ms": 750.0,
"sensor_wait_ms": 90.0
},
"temporal": {
"binding": "nearest-recorded-host-arrival-best-effort",
"maximum_lidar_camera_delta_ms": 100.0,
"maximum_pose_point_delta_ms": 100.0,
"buffer_capacity_per_modality": 32,
"retention_seconds": 3.0,
"clock_qualification": "not-hardware-synchronized"
},
"acceptance": {
"minimum_camera_frames": 140,
"detector_minimum_effective_fps": 9.5,
"detector_maximum_drop_fraction": 0.01,
"semantic_minimum_effective_fps": 1.8,
"semantic_maximum_drop_fraction": 0.05,
"semantic_maximum_p95_completion_age_ms": 400.0,
"minimum_fresh_semantic_coverage": 0.9,
"minimum_fused_fraction": 0.85,
"maximum_p95_decode_age_ms": 80.0,
"maximum_p95_world_state_age_ms": 200.0,
"require_zero_transport_gaps": true,
"require_zero_camera_sequence_gaps": true,
"require_zero_failures": true
}
}
@@ -0,0 +1,283 @@
"""Bounded media/runtime primitives for the LAB E15 shadow inference worker."""
from __future__ import annotations
import threading
import time
from collections import deque
from collections.abc import Callable
from dataclasses import dataclass
from typing import Any
import numpy as np
class ShadowRuntimeError(RuntimeError):
pass
@dataclass(frozen=True, slots=True)
class CameraFragmentMetadata:
ingress_sequence: int
source_sequence: int
captured_at_epoch_ns: int
worker_received_monotonic: float
@dataclass(frozen=True, slots=True)
class DecodedCameraFrame:
frame_index: int
metadata: CameraFragmentMetadata
image: np.ndarray
decoded_monotonic: float
decode_age_ms: float
class IncrementalMediaBuffer:
"""A bounded non-seekable blocking byte source accepted by PyAV."""
def __init__(self, maximum_buffer_bytes: int) -> None:
if maximum_buffer_bytes < 1024:
raise ValueError("media buffer bound is too small")
self._maximum_buffer_bytes = maximum_buffer_bytes
self._buffer = bytearray()
self._condition = threading.Condition()
self._finished = False
self._failure: BaseException | None = None
self._bytes_published = 0
self._bytes_read = 0
self._maximum_depth = 0
def readable(self) -> bool:
return True
def read(self, size: int = -1) -> bytes:
with self._condition:
self._condition.wait_for(
lambda: bool(self._buffer) or self._finished or self._failure is not None
)
if self._failure is not None:
raise ShadowRuntimeError("incremental media source failed") from self._failure
if not self._buffer:
return b""
count = len(self._buffer) if size < 0 else min(size, len(self._buffer))
result = bytes(self._buffer[:count])
del self._buffer[:count]
self._bytes_read += count
self._condition.notify_all()
return result
def append(self, payload: bytes) -> None:
if not payload:
raise ShadowRuntimeError("empty fMP4 payload is not admitted")
with self._condition:
if self._finished or self._failure is not None:
raise ShadowRuntimeError("incremental media source is closed")
if len(self._buffer) + len(payload) > self._maximum_buffer_bytes:
failure = ShadowRuntimeError("incremental media buffer exceeded its hard bound")
self._failure = failure
self._condition.notify_all()
raise failure
self._buffer.extend(payload)
self._bytes_published += len(payload)
self._maximum_depth = max(self._maximum_depth, len(self._buffer))
self._condition.notify_all()
def finish(self) -> None:
with self._condition:
self._finished = True
self._condition.notify_all()
def fail(self, failure: BaseException) -> None:
with self._condition:
if self._failure is None:
self._failure = failure
self._condition.notify_all()
def snapshot(self) -> dict[str, int | bool]:
with self._condition:
return {
"maximum_buffer_bytes": self._maximum_buffer_bytes,
"depth_bytes": len(self._buffer),
"maximum_depth_bytes": self._maximum_depth,
"bytes_published": self._bytes_published,
"bytes_read": self._bytes_read,
"finished": self._finished,
"failed": self._failure is not None,
}
class CameraMetadataQueue:
"""Fail-closed segment metadata queue; dropping a fragment would corrupt H.264."""
def __init__(self, capacity: int) -> None:
if capacity < 2:
raise ValueError("camera metadata capacity is too small")
self._capacity = capacity
self._items: deque[CameraFragmentMetadata] = deque()
self._condition = threading.Condition()
self._finished = False
self._published = 0
self._consumed = 0
self._maximum_depth = 0
def publish(self, value: CameraFragmentMetadata) -> None:
with self._condition:
if self._finished:
raise ShadowRuntimeError("camera metadata queue is closed")
if len(self._items) >= self._capacity:
raise ShadowRuntimeError("camera metadata queue exceeded its hard bound")
self._items.append(value)
self._published += 1
self._maximum_depth = max(self._maximum_depth, len(self._items))
self._condition.notify_all()
def take(self) -> CameraFragmentMetadata:
with self._condition:
self._condition.wait_for(lambda: bool(self._items) or self._finished)
if not self._items:
raise ShadowRuntimeError("decoder emitted a frame without segment metadata")
self._consumed += 1
return self._items.popleft()
def finish(self) -> None:
with self._condition:
self._finished = True
self._condition.notify_all()
def snapshot(self) -> dict[str, int | bool]:
with self._condition:
return {
"capacity": self._capacity,
"depth": len(self._items),
"maximum_depth": self._maximum_depth,
"published": self._published,
"consumed": self._consumed,
"finished": self._finished,
}
class PersistentFmp4Decoder:
"""Decode one committed fMP4 epoch incrementally without writing frames."""
def __init__(
self,
*,
on_frame: Callable[[DecodedCameraFrame], None],
width: int = 800,
height: int = 600,
maximum_buffer_bytes: int = 8 * 1024 * 1024,
metadata_capacity: int = 16,
) -> None:
if width < 1 or height < 1:
raise ValueError("decoder resolution is invalid")
self._on_frame = on_frame
self._width = width
self._height = height
self._media = IncrementalMediaBuffer(maximum_buffer_bytes)
self._metadata = CameraMetadataQueue(metadata_capacity)
self._thread = threading.Thread(
target=self._decode,
name="lab-e15-fmp4-decoder",
daemon=True,
)
self._started = False
self._init_seen = False
self._last_source_sequence: int | None = None
self._decoded_frames = 0
self._failure: BaseException | None = None
def start(self) -> None:
if self._started:
raise ShadowRuntimeError("fMP4 decoder was already started")
self._started = True
self._thread.start()
def feed_init(self, payload: bytes) -> None:
if not self._started or self._init_seen or self._last_source_sequence is not None:
raise ShadowRuntimeError("camera init ordering is invalid")
self._init_seen = True
self._media.append(payload)
def feed_segment(self, metadata: CameraFragmentMetadata, payload: bytes) -> None:
if not self._init_seen:
raise ShadowRuntimeError("camera media arrived before init")
expected = 1 if self._last_source_sequence is None else self._last_source_sequence + 1
if metadata.source_sequence != expected:
raise ShadowRuntimeError(
f"camera source sequence gap: expected {expected}, got {metadata.source_sequence}"
)
self._metadata.publish(metadata)
try:
self._media.append(payload)
except BaseException as exc:
self._media.fail(exc)
self._metadata.finish()
raise
self._last_source_sequence = metadata.source_sequence
def finish_input(self) -> None:
self._media.finish()
self._metadata.finish()
def join(self, timeout_seconds: float = 30.0) -> None:
self._thread.join(timeout=timeout_seconds)
if self._thread.is_alive():
raise ShadowRuntimeError("persistent fMP4 decoder did not stop")
if self._failure is not None:
raise ShadowRuntimeError("persistent fMP4 decoder failed") from self._failure
metadata = self._metadata.snapshot()
if metadata["published"] != metadata["consumed"] or metadata["depth"] != 0:
raise ShadowRuntimeError("camera segment/frame accounting differs")
def snapshot(self) -> dict[str, Any]:
return {
"init_seen": self._init_seen,
"last_source_sequence": self._last_source_sequence,
"decoded_frames": self._decoded_frames,
"failed": self._failure is not None,
"media": self._media.snapshot(),
"metadata": self._metadata.snapshot(),
}
def _decode(self) -> None:
try:
import av
container = av.open(
self._media,
mode="r",
format="mp4",
options={"probesize": "32", "analyzeduration": "0"},
)
try:
for frame in container.decode(video=0):
metadata = self._metadata.take()
image = frame.to_ndarray(format="rgb24")
if image.shape != (self._height, self._width, 3):
raise ShadowRuntimeError("decoded camera resolution changed")
image.setflags(write=False)
decoded_monotonic = time.perf_counter()
self._on_frame(
DecodedCameraFrame(
frame_index=self._decoded_frames,
metadata=metadata,
image=image,
decoded_monotonic=decoded_monotonic,
decode_age_ms=max(
0.0,
(
decoded_monotonic
- metadata.worker_received_monotonic
)
* 1000,
),
)
)
self._decoded_frames += 1
finally:
container.close()
except BaseException as exc:
self._failure = exc
self._media.fail(exc)
self._metadata.finish()
@@ -0,0 +1,145 @@
{
"schema_version": "missioncore.k1-e3-rectified-segmentation-profile/v1",
"profile_id": "k1-camera1-kb4-cubemap5-eomt-cityscapes/v1",
"source": {
"source_id": "sensor.camera.right",
"calibration_slot": "camera_1",
"calibration_sha256": "05f3ad9b38b3a4fc95388a8ec83da83c745e217709e51787b3d5aad0969f6fa9",
"resolution": [
800,
600
],
"intrinsic_fx_fy_cx_cy": [
194.59817287616025,
194.57531427932872,
396.31861150187996,
301.49644357408005
],
"distortion_kb4": [
-0.023164451386679667,
-0.0014974198594105452,
-0.001039213149441563,
-0.000035237331915978814
]
},
"variants": [
"eomt-fisheye-mask",
"eomt-fisheye-mask-clahe",
"eomt-kb4-cubemap5-clahe"
],
"rectification": {
"projection": "five-perspective-gnomonic/v1",
"tile_size": 768,
"horizontal_fov_degrees": 100.0,
"vertical_fov_degrees": 100.0,
"tile_selection": "maximum-optical-axis-cosine/v1",
"rgb_sampling": "opencv-remap-linear",
"label_sampling": "nearest",
"tiles": [
{
"name": "front",
"yaw_degrees": 0.0,
"pitch_degrees": 0.0
},
{
"name": "left",
"yaw_degrees": -90.0,
"pitch_degrees": 0.0
},
{
"name": "right",
"yaw_degrees": 90.0,
"pitch_degrees": 0.0
},
{
"name": "up",
"yaw_degrees": 0.0,
"pitch_degrees": 90.0
},
{
"name": "down",
"yaw_degrees": 0.0,
"pitch_degrees": -90.0
}
]
},
"contrast": {
"method": "clahe-lab-luminance",
"clip_limit": 2.0,
"tile_grid_size": [
8,
8
]
},
"model": {
"id": "tue-mps/cityscapes_semantic_eomt_large_1024",
"revision": "8d6b6d1a3f7b50d441afd7d247c2ed10db186e8f",
"architecture": "EomtForUniversalSegmentation",
"precision": "fp16-autocast",
"batch_size": 1,
"files": {
"config.json": {
"bytes": 1575,
"sha256": "7f4aa94fa4e43c0dbd79a5420edb511120aef62bd82bfbcbcece79948286a650"
},
"preprocessor_config.json": {
"bytes": 666,
"sha256": "97e2fbf7f0bdba2cfc90251c5133bae9c27ddc9c4410509f40670be2332854e7"
},
"model.safetensors": {
"bytes": 1276175488,
"sha256": "c265da9a74f58f5c3f4826d23ca4ca78beac0b106cca5842beca61580de5b782"
}
}
},
"opencv": {
"distribution": "opencv-python-headless",
"version": "4.13.0.92",
"runtime_version": "4.13.0",
"wheel": {
"filename": "opencv_python_headless-4.13.0.92-cp37-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl",
"bytes": 56016764,
"sha256": "0525a3d2c0b46c611e2130b5fdebc94cf404845d8fa64d2f3a3b679572a5bd22",
"url": "https://files.pythonhosted.org/packages/92/ce/bd17ff5772938267fd49716e94ca24f616ff4cb1ff4c6be13085108037be/opencv_python_headless-4.13.0.92-cp37-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl"
}
},
"target_taxonomy": {
"0": "outside_valid_fov",
"1": "person",
"2": "bicycle",
"3": "motorcycle",
"4": "car",
"5": "heavy_vehicle",
"6": "building_structure",
"7": "paved_road",
"8": "sidewalk_curb",
"9": "ground_dirt",
"10": "grass_low_vegetation",
"11": "tree_woody_vegetation",
"12": "sky",
"13": "static_obstacle",
"14": "animal",
"15": "other_background"
},
"cityscapes_to_target": {
"road": 7,
"sidewalk": 8,
"building": 6,
"wall": 6,
"fence": 13,
"pole": 13,
"traffic light": 13,
"traffic sign": 13,
"vegetation": 11,
"terrain": 10,
"sky": 12,
"person": 1,
"rider": 1,
"car": 4,
"truck": 5,
"bus": 5,
"train": 5,
"motorcycle": 3,
"bicycle": 2
}
}
@@ -0,0 +1,53 @@
{
"schema_version": "missioncore.e5-tracking-profile/v1",
"source": {
"source_id": "sensor.camera.right",
"resolution": [800, 600],
"calibration_slot": "camera_1",
"calibration_sha256": "05f3ad9b38b3a4fc95388a8ec83da83c745e217709e51787b3d5aad0969f6fa9"
},
"model": {
"id": "yolox_s",
"version": 1,
"architecture": "YOLOX-S",
"source": "Megvii-BaseDetection/YOLOX release 0.1.1rc0",
"license": "Apache-2.0",
"model_sha256": "c5c2d13e59ae883e6af3b45daea64af4833a4951c92d116ec270d9ddbe998063",
"config_sha256": "5795c737a7935a655961b069e8404d336d891f9762fb6dffb93956a076479604",
"input_name": "images",
"output_name": "output",
"input_shape": [1, 3, 640, 640],
"classes": "COCO-80"
},
"preprocessing": {
"color_order": "BGR",
"resize": "bilinear-letterbox-top-left",
"pad_value": 114,
"valid_fov_fill_value": 114
},
"detection": {
"minimum_score": 0.1,
"nms_iou_threshold": 0.45,
"nms_containment_threshold": 0.8,
"target_class_ids": [0, 1, 2, 3, 5, 7],
"minimum_box_area_pixels": 64.0,
"maximum_box_area_fraction": 0.5,
"minimum_valid_fov_fraction": 0.5,
"require_center_inside_valid_fov": true
},
"tracking": {
"algorithm": "bytetrack-style-two-stage-iou/v1",
"high_score_threshold": 0.25,
"new_track_threshold": 0.25,
"primary_match_iou": 0.2,
"secondary_match_iou": 0.1,
"lost_track_buffer_frames": 15,
"minimum_confirmed_hits": 2,
"assignment_solver": "scipy-linear-sum-assignment"
},
"overlay": {
"line_width": 3,
"trail_length": 24,
"show_unconfirmed": false
}
}
@@ -0,0 +1,64 @@
{
"schema_version": "missioncore.e8-realtime-tracking-profile/v1",
"mode": "overload-negative-control",
"source": {
"source_id": "sensor.camera.right",
"resolution": [800, 600],
"calibration_slot": "camera_1",
"calibration_sha256": "05f3ad9b38b3a4fc95388a8ec83da83c745e217709e51787b3d5aad0969f6fa9"
},
"model": {
"id": "yolox_s",
"version": 1,
"architecture": "YOLOX-S",
"source": "Megvii-BaseDetection/YOLOX release 0.1.1rc0",
"license": "Apache-2.0",
"model_sha256": "c5c2d13e59ae883e6af3b45daea64af4833a4951c92d116ec270d9ddbe998063",
"config_sha256": "5795c737a7935a655961b069e8404d336d891f9762fb6dffb93956a076479604",
"input_name": "images",
"output_name": "output",
"input_shape": [1, 3, 640, 640],
"classes": "COCO-80"
},
"preprocessing": {
"color_order": "BGR",
"resize": "bilinear-letterbox-top-left",
"pad_value": 114,
"valid_fov_fill_value": 114
},
"detection": {
"minimum_score": 0.1,
"nms_iou_threshold": 0.45,
"nms_containment_threshold": 0.8,
"target_class_ids": [0, 1, 2, 3, 5, 7],
"minimum_box_area_pixels": 64.0,
"maximum_box_area_fraction": 0.5,
"minimum_valid_fov_fraction": 0.5,
"require_center_inside_valid_fov": true
},
"tracking": {
"algorithm": "bytetrack-style-two-stage-iou/v1",
"high_score_threshold": 0.25,
"new_track_threshold": 0.25,
"primary_match_iou": 0.2,
"secondary_match_iou": 0.1,
"lost_track_buffer_frames": 15,
"minimum_confirmed_hits": 2,
"assignment_solver": "scipy-linear-sum-assignment"
},
"realtime": {
"queue_policy": "bounded-latest-wins",
"queue_capacity": 2,
"speed": 1.0,
"consumer_delay_ms": 140.0,
"stale_after_ms": 150.0,
"unavailable_after_ms": 500.0
},
"acceptance": {
"minimum_effective_fps": 0.0,
"maximum_drop_fraction": 1.0,
"maximum_p95_result_age_ms": 5000.0,
"require_zero_failures": true,
"expect_overload": true
}
}
@@ -0,0 +1,64 @@
{
"schema_version": "missioncore.e8-realtime-tracking-profile/v1",
"mode": "qualification",
"source": {
"source_id": "sensor.camera.right",
"resolution": [800, 600],
"calibration_slot": "camera_1",
"calibration_sha256": "05f3ad9b38b3a4fc95388a8ec83da83c745e217709e51787b3d5aad0969f6fa9"
},
"model": {
"id": "yolox_s",
"version": 1,
"architecture": "YOLOX-S",
"source": "Megvii-BaseDetection/YOLOX release 0.1.1rc0",
"license": "Apache-2.0",
"model_sha256": "c5c2d13e59ae883e6af3b45daea64af4833a4951c92d116ec270d9ddbe998063",
"config_sha256": "5795c737a7935a655961b069e8404d336d891f9762fb6dffb93956a076479604",
"input_name": "images",
"output_name": "output",
"input_shape": [1, 3, 640, 640],
"classes": "COCO-80"
},
"preprocessing": {
"color_order": "BGR",
"resize": "bilinear-letterbox-top-left",
"pad_value": 114,
"valid_fov_fill_value": 114
},
"detection": {
"minimum_score": 0.1,
"nms_iou_threshold": 0.45,
"nms_containment_threshold": 0.8,
"target_class_ids": [0, 1, 2, 3, 5, 7],
"minimum_box_area_pixels": 64.0,
"maximum_box_area_fraction": 0.5,
"minimum_valid_fov_fraction": 0.5,
"require_center_inside_valid_fov": true
},
"tracking": {
"algorithm": "bytetrack-style-two-stage-iou/v1",
"high_score_threshold": 0.25,
"new_track_threshold": 0.25,
"primary_match_iou": 0.2,
"secondary_match_iou": 0.1,
"lost_track_buffer_frames": 15,
"minimum_confirmed_hits": 2,
"assignment_solver": "scipy-linear-sum-assignment"
},
"realtime": {
"queue_policy": "bounded-latest-wins",
"queue_capacity": 2,
"speed": 1.0,
"consumer_delay_ms": 0.0,
"stale_after_ms": 150.0,
"unavailable_after_ms": 500.0
},
"acceptance": {
"minimum_effective_fps": 9.5,
"maximum_drop_fraction": 0.005,
"maximum_p95_result_age_ms": 100.0,
"require_zero_failures": true,
"expect_overload": false
}
}
@@ -0,0 +1,27 @@
{
"schema_version": "missioncore.e9-multirate-perception-profile/v1",
"mode": "qualification",
"source": {
"source_id": "sensor.camera.right",
"resolution": [800, 600],
"calibration_slot": "camera_1",
"calibration_sha256": "05f3ad9b38b3a4fc95388a8ec83da83c745e217709e51787b3d5aad0969f6fa9"
},
"replay": {
"speed": 1.0,
"detector_queue_capacity": 2,
"semantic_queue_capacity": 1,
"semantic_sample_every_frames": 5,
"semantic_ttl_ms": 750.0
},
"acceptance": {
"detector_minimum_effective_fps": 9.5,
"detector_maximum_drop_fraction": 0.005,
"detector_maximum_p95_result_age_ms": 100.0,
"semantic_minimum_effective_fps": 1.8,
"semantic_maximum_drop_fraction": 0.05,
"semantic_maximum_p95_completion_age_ms": 350.0,
"minimum_fresh_semantic_coverage": 0.9,
"require_zero_failures": true
}
}
@@ -0,0 +1,27 @@
{
"schema_version": "missioncore.e9-multirate-perception-profile/v1",
"mode": "qualification",
"source": {
"source_id": "sensor.camera.right",
"resolution": [800, 600],
"calibration_slot": "camera_1",
"calibration_sha256": "05f3ad9b38b3a4fc95388a8ec83da83c745e217709e51787b3d5aad0969f6fa9"
},
"replay": {
"speed": 1.0,
"detector_queue_capacity": 2,
"semantic_queue_capacity": 1,
"semantic_sample_every_frames": 5,
"semantic_ttl_ms": 750.0
},
"acceptance": {
"detector_minimum_effective_fps": 9.5,
"detector_maximum_drop_fraction": 0.005,
"detector_maximum_p95_result_age_ms": 150.0,
"semantic_minimum_effective_fps": 1.8,
"semantic_maximum_drop_fraction": 0.05,
"semantic_maximum_p95_completion_age_ms": 350.0,
"minimum_fresh_semantic_coverage": 0.9,
"require_zero_failures": true
}
}
@@ -0,0 +1,976 @@
#!/usr/bin/env python3
"""Run camera inference, LiDAR fusion and world-state publication in one paced loop."""
from __future__ import annotations
import argparse
import hashlib
import importlib.metadata
import json
import os
import platform
import resource
import shutil
import threading
import time
from collections import Counter
from dataclasses import dataclass
from datetime import UTC, datetime
from pathlib import Path
from typing import Any
import numpy as np
import run_e9_multirate_perception as e9
from e10_fusion_runtime import (
CuboidCompletionTracker,
LidarReplayPack,
WorldStateProjector,
_completion_profile,
canonical_json,
clearance,
distance_history,
fuse_tracks,
fusion_document,
project_points,
sha256,
)
from run_e4_full_session_segmentation import TARGET_CLASS_COUNT, _dependency_manifest, _load_model
from run_e4_full_session_segmentation import _profile as read_semantic_profile
from run_e4_full_session_segmentation import _validate_source as validate_semantic_source
from run_e5_instance_tracking import (
TwoStageTracker,
_detections,
_infer,
_load_valid_fov,
_preprocess,
_read_timeline,
_track_document,
_validate_source,
_verify_model,
)
from run_e8_realtime_tracking import LatestWinsQueue
from run_e8_realtime_tracking import _read_profile as read_detector_profile
from run_recorded_perception_epoch import (
_artifact,
_GpuTelemetry,
_percentiles,
_valid_sha256,
_validate_job,
_write_json,
)
PROFILE_SCHEMA = "missioncore.e10-integrated-perception-profile/v1"
RESULT_SCHEMA = "missioncore.e10-integrated-perception-result/v1"
REPORT_SCHEMA = "missioncore.e10-integrated-perception-report/v1"
IDENTITY_SCHEMA = "missioncore.e10-integrated-perception-identity/v1"
SEMANTIC_SCHEMA = "missioncore.e10-semantic-frame/v1"
FUSION_SCHEMA = "missioncore.e10-fusion-frame/v1"
WORLD_SCHEMA = "missioncore.live-perception-world-state/v1"
PIPELINE_ID = "source-paced-yolox-eomt-kb4-lidar-world-state/v1"
def arguments() -> argparse.Namespace:
parser = argparse.ArgumentParser()
commands = parser.add_subparsers(dest="command", required=True)
for name in ("preflight", "run"):
command = commands.add_parser(name)
command.add_argument("--job", type=Path, required=True)
command.add_argument("--profile", type=Path, required=True)
command.add_argument("--detector-profile", type=Path, required=True)
command.add_argument("--semantic-profile", type=Path, required=True)
command.add_argument("--valid-fov-root", type=Path, required=True)
command.add_argument("--model-root", type=Path, required=True)
command.add_argument("--cache", type=Path, required=True)
command.add_argument("--environment", type=Path, required=True)
command.add_argument("--lidar-pack", type=Path, required=True)
if name == "run":
command.add_argument("--frames", type=Path, required=True)
command.add_argument("--timeline", type=Path, required=True)
command.add_argument("--output", type=Path, required=True)
command.add_argument("--triton-url", required=True)
command.add_argument("--free-bytes-floor", type=int, default=0)
command.add_argument("--orchestrator-sha256", required=True)
command.add_argument("--container-image", required=True)
return parser.parse_args()
def read_object(path: Path) -> dict[str, Any]:
value = json.loads(path.read_text(encoding="utf-8-sig"))
if not isinstance(value, dict):
raise RuntimeError(f"JSON root is not an object: {path}")
return value
def read_profile(path: Path) -> tuple[dict[str, Any], str]:
resolved = path.resolve(strict=True)
profile = read_object(resolved)
replay = profile.get("replay")
source = profile.get("source")
association = profile.get("association")
world = profile.get("world_state")
acceptance = profile.get("acceptance")
if (
profile.get("schema_version") != PROFILE_SCHEMA
or profile.get("mode")
not in {
"pilot",
"qualification",
"full-session-qualification",
"semantic-loss-negative-control",
}
or not all(
isinstance(value, dict) for value in (replay, source, association, world, acceptance)
)
or source.get("source_id") != "sensor.camera.right"
or source.get("resolution") != [800, 600]
or set(association.get("semantic_ids", {}))
!= {"person", "bicycle", "motorcycle", "vehicle"}
or not isinstance(world.get("clearance"), dict)
):
raise RuntimeError("LAB E10 profile contract is invalid")
if (
not 0.1 <= float(replay.get("speed", 0)) <= 10
or not 1 <= int(replay.get("detector_queue_capacity", 0)) <= 8
or not 1 <= int(replay.get("semantic_queue_capacity", 0)) <= 4
or not 2 <= int(replay.get("semantic_sample_every_frames", 0)) <= 30
or not 100 <= float(replay.get("semantic_ttl_ms", 0)) <= 5000
):
raise RuntimeError("LAB E10 scheduling contract is invalid")
if profile["mode"] == "semantic-loss-negative-control":
semantic_loss = profile.get("semantic_loss")
if (
not isinstance(semantic_loss, dict)
or not 1 <= int(semantic_loss.get("stop_after_completed_results", 0)) <= 100
or not 1 <= int(acceptance.get("minimum_stale_detector_frames", 0)) <= 1_000_000
):
raise RuntimeError("LAB E10 semantic-loss contract is invalid")
if profile["mode"] == "full-session-qualification":
selection = profile.get("selection")
if (
not isinstance(selection, dict)
or int(selection.get("required_frame_count", 0)) < 2
or int(selection.get("required_source_start_frame_index", -1)) != 0
or int(selection.get("required_source_end_frame_index", -1))
!= int(selection["required_frame_count"]) - 1
or float(selection.get("minimum_source_span_seconds", 0)) <= 0
):
raise RuntimeError("LAB E10 full-session selection contract is invalid")
completion = profile.get("cuboid_completion")
if completion is not None:
if not isinstance(completion, dict):
raise RuntimeError("LAB E13 cuboid completion contract is invalid")
_completion_profile(completion)
return profile, sha256(resolved)
@dataclass(frozen=True, slots=True)
class SemanticResult:
frame_index: int
source_frame_index: int
session_seconds: float
completion_age_ms: float
completed_monotonic: float
mask: np.ndarray
mask_sha256: str
class_pixels: dict[str, int]
class LatestSemantic:
def __init__(self) -> None:
self.lock = threading.Lock()
self.value: SemanticResult | None = None
def publish(self, value: SemanticResult) -> None:
with self.lock:
if self.value is not None and value.frame_index <= self.value.frame_index:
raise RuntimeError("LAB E10 semantic results are not monotonic")
self.value = value
def snapshot(self) -> SemanticResult | None:
with self.lock:
return self.value
def semantic_worker(
*,
queue: LatestWinsQueue,
latest: LatestSemantic,
valid_mask: np.ndarray,
target_lut: np.ndarray,
target_names: dict[int, str],
infer: Any,
latency: dict[str, list[float]],
completed: list[SemanticResult],
failures: list[BaseException],
stop_after_results: int | None,
) -> None:
try:
while (envelope := queue.take()) is not None:
started = time.perf_counter()
latency["queue_wait_ms"].append(max(0.0, (started - envelope.decoded_monotonic) * 1000))
fill_started = time.perf_counter()
model_input = np.where(valid_mask[..., None], envelope.image, 0).astype(np.uint8)
latency["valid_fov_fill_ms"].append((time.perf_counter() - fill_started) * 1000)
semantic, measured = infer(model_input)
if int(semantic.max()) >= len(target_lut):
raise RuntimeError("LAB E10 EoMT emitted an unknown category")
target = target_lut[semantic].copy()
target[~valid_mask] = 0
for name, value in measured.items():
latency[name].append(float(value))
finished = time.perf_counter()
age = max(0.0, (finished - envelope.scheduled_monotonic) * 1000)
latency["completion_age_ms"].append(age)
latency["processing_ms"].append((finished - started) * 1000)
counts = np.bincount(target[valid_mask], minlength=TARGET_CLASS_COUNT)
result = SemanticResult(
frame_index=envelope.frame_index,
source_frame_index=int(envelope.timeline["source_frame_index"]),
session_seconds=float(envelope.timeline["session_seconds"]),
completion_age_ms=age,
completed_monotonic=finished,
mask=target,
mask_sha256=hashlib.sha256(target.tobytes()).hexdigest(),
class_pixels={
target_names[index]: int(counts[index])
for index in range(1, TARGET_CLASS_COUNT)
if int(counts[index]) > 0
},
)
completed.append(result)
latest.publish(result)
if stop_after_results is not None and len(completed) >= stop_after_results:
return
except BaseException as exc:
failures.append(exc)
def semantic_binding(
semantic: SemanticResult | None, frame_seconds: float, ttl_ms: float
) -> tuple[str, float | None]:
if semantic is None:
return "unavailable", None
age = max(0.0, (frame_seconds - semantic.session_seconds) * 1000)
return ("fresh" if age <= ttl_ms else "stale"), age
def preflight(args: argparse.Namespace) -> int:
import torch
job = _validate_job(args.job.resolve(strict=True))
profile, profile_sha256 = read_profile(args.profile)
detector, detector_sha256 = read_detector_profile(args.detector_profile)
semantic, semantic_sha256 = read_semantic_profile(args.semantic_profile)
_validate_source(job, detector)
validate_semantic_source(job, semantic)
if profile["source"] != detector["source"]:
raise RuntimeError("LAB E10 detector source binding changed")
if profile["source"] != {
key: semantic["source"][key]
for key in ("source_id", "resolution", "calibration_slot", "calibration_sha256")
}:
raise RuntimeError("LAB E10 semantic source binding changed")
lidar = LidarReplayPack(args.lidar_pack, expected_job_id=job["job_id"])
try:
if lidar.identity["calibration_sha256"] != profile["source"]["calibration_sha256"]:
raise RuntimeError("LAB E10 LiDAR calibration binding changed")
if profile["mode"] == "full-session-qualification":
selection = profile["selection"]
if (
lidar.frame_count != int(selection["required_frame_count"])
or int(lidar.source_frame_indices[0])
!= int(selection["required_source_start_frame_index"])
or int(lidar.source_frame_indices[-1])
!= int(selection["required_source_end_frame_index"])
or float(lidar.session_seconds[-1] - lidar.session_seconds[0])
< float(selection["minimum_source_span_seconds"])
):
raise RuntimeError("LAB E10 full-session LiDAR selection changed")
_load_valid_fov(args.valid_fov_root, job, detector)
detector_files = _verify_model(detector, args.model_root)
dependency = _dependency_manifest(args.environment.resolve(strict=True))
if dependency["identity"]["profile_sha256"] != semantic_sha256:
raise RuntimeError("LAB E10 semantic dependency identity changed")
if not torch.cuda.is_available():
raise RuntimeError("CUDA is required for LAB E10")
device = torch.device("cuda:0")
processor, model, _labels, _lut, semantic_files = _load_model(
semantic, args.cache.resolve(strict=True), device
)
del processor, model, _labels, _lut
torch.cuda.empty_cache()
print(
json.dumps(
{
"state": "preflight-ready",
"job_id": job["job_id"],
"profile_sha256": profile_sha256,
"detector_profile_sha256": detector_sha256,
"semantic_profile_sha256": semantic_sha256,
"lidar_pack_id": lidar.pack_id,
"detector_files": detector_files,
"semantic_files": semantic_files,
"cuda_device": torch.cuda.get_device_name(),
},
sort_keys=True,
),
flush=True,
)
finally:
lidar.close()
return 0
def run(args: argparse.Namespace) -> int:
import torch
import transformers
from PIL import Image
from scipy.optimize import linear_sum_assignment
if not _valid_sha256(args.orchestrator_sha256):
raise RuntimeError("LAB E10 orchestrator SHA-256 is invalid")
job = _validate_job(args.job.resolve(strict=True))
profile, profile_sha256 = read_profile(args.profile)
detector, detector_sha256 = read_detector_profile(args.detector_profile)
semantic, semantic_sha256 = read_semantic_profile(args.semantic_profile)
_validate_source(job, detector)
validate_semantic_source(job, semantic)
valid_mask, valid_fov = _load_valid_fov(args.valid_fov_root, job, detector)
detector_files = _verify_model(detector, args.model_root)
dependency = _dependency_manifest(args.environment.resolve(strict=True))
if dependency["identity"]["profile_sha256"] != semantic_sha256:
raise RuntimeError("LAB E10 semantic dependency identity changed")
lidar = LidarReplayPack(args.lidar_pack, expected_job_id=job["job_id"])
frames = sorted(args.frames.resolve(strict=True).glob("frame-*.png"))
timeline_path = args.timeline.resolve(strict=True)
timeline = _read_timeline(timeline_path, len(frames))
if (
len(frames) != lidar.frame_count
or [int(row["source_frame_index"]) for row in timeline]
!= lidar.source_frame_indices.tolist()
or not np.allclose(
np.asarray([float(row["session_seconds"]) for row in timeline]),
lidar.session_seconds,
rtol=0,
atol=1e-6,
)
):
lidar.close()
raise RuntimeError("LAB E10 camera and LiDAR replay selections differ")
if profile["mode"] == "full-session-qualification":
selection = profile["selection"]
source_span_seconds = float(timeline[-1]["session_seconds"]) - float(
timeline[0]["session_seconds"]
)
if (
len(frames) != int(selection["required_frame_count"])
or int(timeline[0]["source_frame_index"])
!= int(selection["required_source_start_frame_index"])
or int(timeline[-1]["source_frame_index"])
!= int(selection["required_source_end_frame_index"])
or source_span_seconds < float(selection["minimum_source_span_seconds"])
):
lidar.close()
raise RuntimeError("LAB E10 full-session camera selection changed")
output = args.output.resolve()
if output.exists():
raise RuntimeError("LAB E10 output must be absent")
output.mkdir(mode=0o700, parents=True, exist_ok=False)
assert_disk(output, args.free_bytes_floor, 0)
device = torch.device("cuda:0")
processor, semantic_model, _semantic_labels, target_lut, semantic_files = _load_model(
semantic, args.cache.resolve(strict=True), device
)
target_names = {int(key): str(value) for key, value in semantic["target_taxonomy"].items()}
infer_semantic = e9._semantic_infer_factory(processor, semantic_model, device)
tracker = TwoStageTracker(detector["tracking"])
linear_sum_assignment(np.zeros((1, 1), dtype=np.float64))
with Image.open(frames[0]) as opened:
warm = np.asarray(opened.convert("RGB"), dtype=np.uint8)
_infer(args.triton_url, detector["model"], _preprocess(warm, valid_mask, detector))
infer_semantic(np.where(valid_mask[..., None], warm, 0).astype(np.uint8))
del warm
replay = profile["replay"]
detector_queue = LatestWinsQueue(int(replay["detector_queue_capacity"]))
semantic_queue = LatestWinsQueue(int(replay["semantic_queue_capacity"]))
latest = LatestSemantic()
completed_semantics: list[SemanticResult] = []
producer_errors: list[BaseException] = []
semantic_errors: list[BaseException] = []
semantic_latency = {
name: []
for name in (
"queue_wait_ms",
"valid_fov_fill_ms",
"processor_ms",
"host_to_device_ms",
"forward_ms",
"model_postprocess_ms",
"processing_ms",
"completion_age_ms",
)
}
latency = {
name: []
for name in (
"decode_ms",
"queue_wait_ms",
"detector_ms",
"projection_ms",
"association_ms",
"clearance_ms",
"world_state_ms",
"world_state_age_ms",
)
}
status_counts: Counter[str] = Counter()
fusion_state_counts: Counter[str] = Counter()
rejection_counts: Counter[str] = Counter()
accepted_cuboids = 0
fused_frames = 0
detector_failures = 0
fusion_freshness_violations = 0
history = distance_history(int(profile["association"]["distance_history_frames"]))
projector = WorldStateProjector(float(profile["world_state"]["velocity_history_limit_s"]))
completion_tracker = (
CuboidCompletionTracker(profile["cuboid_completion"])
if "cuboid_completion" in profile
else None
)
semantic_path = output / "semantic-frames.jsonl"
fusion_path = output / "fusion-frames.jsonl"
world_path = output / "world-state.jsonl"
gpu_path = output / "gpu-telemetry.jsonl"
support_offsets = [0]
support_points: list[np.ndarray] = []
support_colors: list[np.ndarray] = []
box_offsets = [0]
box_centers: list[tuple[float, float, float]] = []
box_half_sizes: list[tuple[float, float, float]] = []
box_quaternions: list[tuple[float, float, float, float]] = []
box_colors: list[tuple[int, int, int, int]] = []
frame_times_ns: list[int] = []
disk_before = shutil.disk_usage(output).free
with (
semantic_path.open("x", encoding="utf-8", newline="\n") as semantic_stream,
fusion_path.open("x", encoding="utf-8", newline="\n") as fusion_stream,
world_path.open("x", encoding="utf-8", newline="\n") as world_stream,
gpu_path.open("x", encoding="utf-8", newline="\n") as gpu_stream,
_GpuTelemetry(gpu_stream, 1.0) as gpu,
):
semantic_thread = threading.Thread(
target=semantic_worker,
kwargs={
"queue": semantic_queue,
"latest": latest,
"valid_mask": valid_mask,
"target_lut": target_lut,
"target_names": target_names,
"infer": infer_semantic,
"latency": semantic_latency,
"completed": completed_semantics,
"failures": semantic_errors,
"stop_after_results": (
int(profile["semantic_loss"]["stop_after_completed_results"])
if profile["mode"] == "semantic-loss-negative-control"
else None
),
},
name="lab-e10-semantic",
daemon=True,
)
semantic_thread.start()
replay_started = time.perf_counter() + 0.25
producer = threading.Thread(
target=e9._producer,
kwargs={
"detector_queue": detector_queue,
"semantic_queue": semantic_queue,
"semantic_stride": int(replay["semantic_sample_every_frames"]),
"frame_paths": frames,
"timeline_rows": timeline,
"replay_started": replay_started,
"speed": float(replay["speed"]),
"error": producer_errors,
},
name="lab-e10-source",
daemon=True,
)
producer.start()
while (envelope := detector_queue.take()) is not None:
started = time.perf_counter()
latency["decode_ms"].append(envelope.decode_ms)
latency["queue_wait_ms"].append(max(0.0, (started - envelope.decoded_monotonic) * 1000))
try:
detector_started = time.perf_counter()
tensor = _preprocess(envelope.image, valid_mask, detector)
output_tensor, _request_ms = _infer(args.triton_url, detector["model"], tensor)
detections, _rejected = _detections(output_tensor, detector, valid_mask)
tracks = tracker.update(detections, envelope.frame_index)
latency["detector_ms"].append((time.perf_counter() - detector_started) * 1000)
frame_seconds = float(envelope.timeline["session_seconds"])
current_semantic = latest.snapshot()
semantic_status, semantic_age = semantic_binding(
current_semantic,
frame_seconds,
float(replay["semantic_ttl_ms"]),
)
status_counts[semantic_status] += 1
lidar_frame = lidar.frame(envelope.frame_index)
fusions = ()
points_lidar = np.empty((0, 3), dtype=np.float64)
if lidar_frame is None:
fusion_state = "depth-unavailable-sync-gate"
elif semantic_status != "fresh" or current_semantic is None:
fusion_state = f"semantic-{semantic_status}"
else:
points_map, position, quaternion = lidar_frame
projection_started = time.perf_counter()
pixels, depths, source_indices, points_lidar = project_points(
points_map, position, quaternion, lidar.profile
)
latency["projection_ms"].append(
(time.perf_counter() - projection_started) * 1000
)
association_started = time.perf_counter()
fusions = fuse_tracks(
tracks=[_track_document(track) for track in tracks],
semantic_map=current_semantic.mask,
pixels=pixels,
depths=depths,
source_indices=source_indices,
points_map=points_map,
points_lidar=points_lidar,
association=profile["association"],
distance_history=history,
completion_tracker=completion_tracker,
sensor_position_map=position,
session_seconds=frame_seconds,
)
latency["association_ms"].append(
(time.perf_counter() - association_started) * 1000
)
fusion_state = "fused"
fused_frames += 1
if fusion_state == "fused" and semantic_status != "fresh":
fusion_freshness_violations += 1
fusion_state_counts[fusion_state] += 1
accepted = [item for item in fusions if item.cuboid is not None]
accepted_cuboids += len(accepted)
for item in fusions:
rejection_counts[item.status] += 1
frame_support = []
frame_support_colors = []
for item in accepted:
color_seed = hashlib.sha256(
f"e10:{item.association_group}:{item.track_id}".encode()
).digest()
color = tuple(64 + value % 176 for value in color_seed[:3])
if lidar_frame is None:
continue
points_map = lidar_frame[0]
values = points_map[item.source_indices].astype(np.float32)
frame_support.append(values)
frame_support_colors.append(
np.tile(np.asarray([color], dtype=np.uint8), (values.shape[0], 1))
)
box_centers.append(item.cuboid.center_map)
box_half_sizes.append(item.cuboid.half_size)
box_quaternions.append(item.cuboid.quaternion_xyzw)
box_colors.append((*color, 88))
if frame_support:
support = np.concatenate(frame_support)
colors = np.concatenate(frame_support_colors)
support_points.append(support)
support_colors.append(colors)
support_offsets.append(support_offsets[-1] + support.shape[0])
else:
support_offsets.append(support_offsets[-1])
box_offsets.append(box_offsets[-1] + len(accepted))
clearance_started = time.perf_counter()
clearance_state = clearance(points_lidar, profile["world_state"]["clearance"])
latency["clearance_ms"].append((time.perf_counter() - clearance_started) * 1000)
world_started = time.perf_counter()
result_age = max(0.0, (world_started - envelope.scheduled_monotonic) * 1000)
if result_age >= 1000:
health = "unavailable"
elif result_age >= float(profile["acceptance"]["maximum_p95_world_state_age_ms"]):
health = "stale"
elif fusion_state != "fused":
health = "degraded"
else:
health = "healthy"
delivery = {
"health": health,
"result_age_ms": result_age,
"semantic_status": semantic_status,
"semantic_source_age_ms": semantic_age,
}
world = projector.project(
frame_index=envelope.frame_index,
source_frame_index=int(envelope.timeline["source_frame_index"]),
session_seconds=frame_seconds,
fusion_state=fusion_state,
fusions=fusions,
points_lidar=points_lidar,
clearance_state=clearance_state,
delivery=delivery,
)
latency["world_state_ms"].append((time.perf_counter() - world_started) * 1000)
result_age = max(0.0, (time.perf_counter() - envelope.scheduled_monotonic) * 1000)
world["delivery"]["result_age_ms"] = result_age
latency["world_state_age_ms"].append(result_age)
frame_times_ns.append(round(frame_seconds * 1e9))
fusion_stream.write(
json.dumps(
{
"schema_version": FUSION_SCHEMA,
"frame_index": envelope.frame_index,
"source_frame_index": int(envelope.timeline["source_frame_index"]),
"session_seconds": frame_seconds,
"fusion_state": fusion_state,
"semantic_status": semantic_status,
"semantic_source_frame_index": None
if current_semantic is None
else current_semantic.source_frame_index,
"objects": [fusion_document(item) for item in fusions],
},
sort_keys=True,
separators=(",", ":"),
allow_nan=False,
)
+ "\n"
)
world_stream.write(
json.dumps(world, sort_keys=True, separators=(",", ":"), allow_nan=False) + "\n"
)
except Exception:
detector_failures += 1
raise
consumed = int(detector_queue.snapshot()["consumed"])
if consumed % 100 == 0:
fusion_stream.flush()
world_stream.flush()
assert_disk(output, args.free_bytes_floor, consumed)
print(
json.dumps(
{
"phase": "e10-integrated",
"processed": consumed,
"detector_dropped": detector_queue.snapshot()["dropped_overflow"],
"semantic_processed": semantic_queue.snapshot()["consumed"],
"fused_frames": fused_frames,
"accepted_cuboids": accepted_cuboids,
},
sort_keys=True,
),
flush=True,
)
producer.join(timeout=5)
semantic_thread.join(timeout=30)
if producer.is_alive() or producer_errors:
raise RuntimeError("LAB E10 producer failed")
if semantic_thread.is_alive() or semantic_errors:
raise RuntimeError("LAB E10 semantic worker failed")
for result in completed_semantics:
semantic_stream.write(
json.dumps(
{
"schema_version": SEMANTIC_SCHEMA,
"frame_index": result.frame_index,
"source_frame_index": result.source_frame_index,
"session_seconds": result.session_seconds,
"completion_age_ms": result.completion_age_ms,
"mask_sha256": result.mask_sha256,
"class_pixels": result.class_pixels,
},
sort_keys=True,
separators=(",", ":"),
allow_nan=False,
)
+ "\n"
)
for stream in (semantic_stream, fusion_stream, world_stream):
stream.flush()
os.fsync(stream.fileno())
replay_finished = time.perf_counter()
detector_state = detector_queue.snapshot()
semantic_state = semantic_queue.snapshot()
source_span = (
float(timeline[-1]["session_seconds"]) - float(timeline[0]["session_seconds"])
) / float(replay["speed"])
replay_wall = replay_finished - replay_started
detector_fps = int(detector_state["consumed"]) / max(source_span, replay_wall, 1e-9)
semantic_fps = int(semantic_state["consumed"]) / max(source_span, replay_wall, 1e-9)
scheduled_semantic = ((len(frames) - 1) // int(replay["semantic_sample_every_frames"])) + 1
fresh_coverage = status_counts["fresh"] / max(1, int(detector_state["consumed"]))
latency_summary = {name: _percentiles(values) for name, values in latency.items()}
semantic_summary = {name: _percentiles(values) for name, values in semantic_latency.items()}
arrays_path = output / "transient-perception.npz"
np.savez_compressed(
arrays_path,
frame_times_ns=np.asarray(frame_times_ns, dtype=np.int64),
semantic_frame_indices=np.asarray(
[value.frame_index for value in completed_semantics], dtype=np.int64
),
semantic_masks=np.stack([value.mask for value in completed_semantics]).astype(np.uint8),
support_offsets=np.asarray(support_offsets, dtype=np.int64),
support_points=np.concatenate(support_points)
if support_points
else np.empty((0, 3), dtype=np.float32),
support_colors=np.concatenate(support_colors)
if support_colors
else np.empty((0, 3), dtype=np.uint8),
box_offsets=np.asarray(box_offsets, dtype=np.int64),
box_centers=np.asarray(box_centers, dtype=np.float32).reshape((-1, 3)),
box_half_sizes=np.asarray(box_half_sizes, dtype=np.float32).reshape((-1, 3)),
box_quaternions=np.asarray(box_quaternions, dtype=np.float32).reshape((-1, 4)),
box_colors=np.asarray(box_colors, dtype=np.uint8).reshape((-1, 4)),
)
acceptance = profile["acceptance"]
detector_checks = {
"detector_accounting": int(detector_state["consumed"])
+ int(detector_state["dropped_overflow"])
== len(frames),
"detector_minimum_effective_fps": detector_fps
>= float(acceptance["detector_minimum_effective_fps"]),
"detector_maximum_drop_fraction": int(detector_state["dropped_overflow"]) / len(frames)
<= float(acceptance["detector_maximum_drop_fraction"]),
"maximum_p95_world_state_age_ms": float(latency_summary["world_state_age_ms"]["p95"])
<= float(acceptance["maximum_p95_world_state_age_ms"]),
"zero_detector_failures": detector_failures == 0 and not producer_errors,
}
if profile["mode"] == "semantic-loss-negative-control":
stop_after = int(profile["semantic_loss"]["stop_after_completed_results"])
checks = {
**detector_checks,
"semantic_loss_triggered": len(completed_semantics) == stop_after,
"semantic_queue_accounting": int(semantic_state["consumed"])
+ int(semantic_state["dropped_overflow"])
+ int(semantic_state["final_depth"])
== scheduled_semantic,
"minimum_stale_detector_frames": status_counts["stale"]
>= int(acceptance["minimum_stale_detector_frames"]),
"no_fusion_with_nonfresh_semantics": fusion_freshness_violations == 0,
"semantic_worker_stopped_without_error": not semantic_errors,
}
else:
checks = {
**detector_checks,
"semantic_accounting": int(semantic_state["consumed"])
+ int(semantic_state["dropped_overflow"])
== scheduled_semantic,
"semantic_minimum_effective_fps": semantic_fps
>= float(acceptance["semantic_minimum_effective_fps"]),
"semantic_maximum_drop_fraction": int(semantic_state["dropped_overflow"])
/ scheduled_semantic
<= float(acceptance["semantic_maximum_drop_fraction"]),
"semantic_maximum_p95_completion_age_ms": float(
semantic_summary["completion_age_ms"]["p95"]
)
<= float(acceptance["semantic_maximum_p95_completion_age_ms"]),
"minimum_fresh_semantic_coverage": fresh_coverage
>= float(acceptance["minimum_fresh_semantic_coverage"]),
"minimum_lidar_fused_frames": fused_frames
>= int(acceptance["minimum_lidar_fused_frames"]),
"minimum_accepted_cuboids": accepted_cuboids
>= int(acceptance["minimum_accepted_cuboids"]),
"zero_semantic_failures": not semantic_errors,
}
accepted = all(checks.values())
identity = {
"schema_version": IDENTITY_SCHEMA,
"job_id": job["job_id"],
"input_sha256": job["input_sha256"],
"session_id": job["input"]["session_id"],
"source_id": job["input"]["source_id"],
"lidar_pack_id": lidar.pack_id,
"selection": {
"frame_count": len(frames),
"source_start_frame_index": timeline[0]["source_frame_index"],
"source_end_frame_index": timeline[-1]["source_frame_index"],
"timeline_start_seconds": timeline[0]["session_seconds"],
"timeline_end_seconds": timeline[-1]["session_seconds"],
"timeline_sha256": sha256(timeline_path),
},
"configuration": {
"pipeline": PIPELINE_ID,
"profile": profile,
"profile_sha256": profile_sha256,
"detector_profile_sha256": detector_sha256,
"semantic_profile_sha256": semantic_sha256,
"runner_sha256": sha256(Path(__file__).resolve(strict=True)),
"fusion_runtime_sha256": sha256(
Path(__file__).with_name("e10_fusion_runtime.py").resolve(strict=True)
),
"orchestrator_sha256": args.orchestrator_sha256,
"container_image": args.container_image,
"valid_fov": valid_fov,
},
"models": {
"detector": detector["model"],
"detector_files": detector_files,
"semantic": semantic["model"],
"semantic_files": semantic_files,
},
}
identity_sha256 = hashlib.sha256(canonical_json(identity)).hexdigest()
result_id = f"e10-integrated-perception-{identity_sha256}"
metrics = {
"source_span_seconds": source_span,
"replay_wall_seconds": replay_wall,
"detector": {
"frames_processed": detector_state["consumed"],
"frames_dropped": detector_state["dropped_overflow"],
"effective_fps": detector_fps,
"queue": detector_state,
},
"semantic": {
"frames_processed": semantic_state["consumed"],
"frames_dropped": semantic_state["dropped_overflow"],
"effective_fps": semantic_fps,
"fresh_coverage": fresh_coverage,
"status_counts": dict(status_counts),
"latency_ms": semantic_summary,
},
"fusion": {
"fused_frames": fused_frames,
"fusion_state_counts": dict(fusion_state_counts),
"accepted_cuboids": accepted_cuboids,
"rejection_counts": dict(rejection_counts),
"freshness_violations": fusion_freshness_violations,
},
"semantic_loss": {
"configured": profile["mode"] == "semantic-loss-negative-control",
"stop_after_completed_results": (
int(profile["semantic_loss"]["stop_after_completed_results"])
if profile["mode"] == "semantic-loss-negative-control"
else None
),
"triggered": (
len(completed_semantics)
== int(profile["semantic_loss"]["stop_after_completed_results"])
if profile["mode"] == "semantic-loss-negative-control"
else False
),
},
"latency_ms": latency_summary,
"gpu_telemetry": gpu.summary(),
"process_peak_rss_mib": resource.getrusage(resource.RUSAGE_SELF).ru_maxrss / 1024,
"cuda_peak_memory_allocated_mib": torch.cuda.max_memory_allocated() / 2**20,
"cuda_peak_memory_reserved_mib": torch.cuda.max_memory_reserved() / 2**20,
"disk": {
"free_bytes_before": disk_before,
"free_bytes_after": shutil.disk_usage(output).free,
"free_bytes_floor": args.free_bytes_floor,
},
}
report = {
"schema_version": REPORT_SCHEMA,
"result_id": result_id,
"created_at_utc": datetime.now(UTC)
.isoformat(timespec="milliseconds")
.replace("+00:00", "Z"),
"state": "accepted" if accepted else "rejected",
"ground_truth": False,
"identity": identity,
"runtime": {
"hostname": platform.node(),
"python": platform.python_version(),
"numpy": np.__version__,
"torch": torch.__version__,
"transformers": transformers.__version__,
"scipy": importlib.metadata.version("scipy"),
"gpu": torch.cuda.get_device_name(),
},
"metrics": metrics,
"acceptance": {
"accepted": accepted,
"checks": checks,
"navigation_or_safety_accepted": False,
},
"limitations": [
"Recorded source-paced replay, not direct live K1 transport.",
"Host-arrival camera/LiDAR synchronization is not a hardware-clock proof.",
"COCO and Cityscapes models are not forest-domain or safety validated.",
(
"Completed 3D cuboids mix visible LiDAR support with class-size priors; "
"unobserved volume is inferred, not measured or ground truth."
if "cuboid_completion" in profile
else (
"3D cuboids describe visible LiDAR-supported surfaces, "
"not complete object volume."
)
),
*(
["Semantic inference was intentionally stopped for a negative-control run."]
if profile["mode"] == "semantic-loss-negative-control"
else []
),
],
}
report_path = output / "run-report.json"
_write_json(report_path, report)
artifacts = [
_artifact(semantic_path, "e10-semantic-frames", "application/x-ndjson", SEMANTIC_SCHEMA),
_artifact(fusion_path, "e10-fusion-frames", "application/x-ndjson", FUSION_SCHEMA),
_artifact(world_path, "e10-world-state", "application/x-ndjson", WORLD_SCHEMA),
_artifact(arrays_path, "e10-transient-perception", "application/x-npz"),
_artifact(gpu_path, "worker-gpu-telemetry", "application/x-ndjson"),
_artifact(report_path, "e10-run-report", "application/json", REPORT_SCHEMA),
]
result = {
"schema_version": RESULT_SCHEMA,
"result_id": result_id,
"identity_sha256": identity_sha256,
"identity": identity,
"created_at_utc": report["created_at_utc"],
"acceptance_state": report["state"],
"ground_truth": False,
"publication_scope": (
"recorded-integrated-semantic-loss-negative-control-only"
if profile["mode"] == "semantic-loss-negative-control"
else "recorded-integrated-realtime-qualification-only"
),
"frames_processed": detector_state["consumed"],
"artifacts": artifacts,
}
_write_json(output / "result.json", result)
lidar.close()
print(
json.dumps(
{
"result_id": result_id,
"accepted": accepted,
"detector_fps": detector_fps,
"semantic_fps": semantic_fps,
"world_state_age_p95_ms": latency_summary["world_state_age_ms"]["p95"],
"fused_frames": fused_frames,
"accepted_cuboids": accepted_cuboids,
},
sort_keys=True,
),
flush=True,
)
return 0
def assert_disk(path: Path, floor: int, frame: int) -> None:
if floor < 0 or (floor and shutil.disk_usage(path).free < floor):
raise RuntimeError(f"LAB E10 crossed the D-backed free-space floor at frame {frame}")
def main() -> int:
args = arguments()
return preflight(args) if args.command == "preflight" else run(args)
if __name__ == "__main__":
raise SystemExit(main())
@@ -0,0 +1,304 @@
#!/usr/bin/env python3
"""Receive and qualify the Mission Core live shadow stream without K1 access."""
from __future__ import annotations
import argparse
import base64
import hashlib
import json
import os
import select
import socket
import struct
import sys
import time
from collections import Counter
from contextlib import suppress
from datetime import UTC, datetime
from pathlib import Path
from typing import Any, BinaryIO
WIRE_SCHEMA = "missioncore.live-perception-wire/v1"
REPORT_SCHEMA = "missioncore.e12-shadow-transport-report/v1"
WEBSOCKET_GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
MAX_HEADER_BYTES = 64 * 1024
MAX_FRAME_BYTES = 3 * 1024 * 1024
class ProbeError(RuntimeError):
pass
def _read_exact(stream: BinaryIO, size: int) -> bytes:
parts: list[bytes] = []
remaining = size
while remaining:
chunk = stream.read(remaining)
if not chunk:
raise ProbeError("shadow transport ended unexpectedly")
parts.append(chunk)
remaining -= len(chunk)
return b"".join(parts)
def _read_http_headers(stream: BinaryIO) -> tuple[str, dict[str, str]]:
encoded = bytearray()
while not encoded.endswith(b"\r\n\r\n"):
encoded.extend(_read_exact(stream, 1))
if len(encoded) > MAX_HEADER_BYTES:
raise ProbeError("websocket response headers exceed the bound")
try:
lines = encoded.decode("ascii").split("\r\n")
except UnicodeDecodeError as exc:
raise ProbeError("websocket response headers are not ASCII") from exc
headers: dict[str, str] = {}
for line in lines[1:]:
if not line:
continue
name, separator, value = line.partition(":")
if not separator:
raise ProbeError("malformed websocket response header")
headers[name.strip().lower()] = value.strip()
return lines[0], headers
def _send_client_frame(stream: BinaryIO, opcode: int, payload: bytes) -> None:
if len(payload) > 125:
raise ProbeError("client control frame exceeds websocket bound")
mask = os.urandom(4)
masked = bytes(value ^ mask[index % 4] for index, value in enumerate(payload))
stream.write(bytes((0x80 | opcode, 0x80 | len(payload))) + mask + masked)
stream.flush()
def _read_server_frame(stream: BinaryIO) -> tuple[int, bytes]:
first, second = _read_exact(stream, 2)
if not first & 0x80:
raise ProbeError("fragmented websocket frames are not admitted")
opcode = first & 0x0F
masked = bool(second & 0x80)
length = second & 0x7F
if length == 126:
length = struct.unpack("!H", _read_exact(stream, 2))[0]
elif length == 127:
length = struct.unpack("!Q", _read_exact(stream, 8))[0]
if length > MAX_FRAME_BYTES:
raise ProbeError("websocket frame exceeds the shadow transport bound")
mask = _read_exact(stream, 4) if masked else None
payload = _read_exact(stream, length)
if mask is not None:
payload = bytes(value ^ mask[index % 4] for index, value in enumerate(payload))
return opcode, payload
def _connect(
host: str,
port: int,
path: str,
token: str,
timeout_seconds: float,
) -> tuple[socket.socket, BinaryIO]:
connection = socket.create_connection((host, port), timeout=timeout_seconds)
connection.settimeout(timeout_seconds)
stream = connection.makefile("rwb", buffering=0)
key = base64.b64encode(os.urandom(16)).decode("ascii")
request = (
f"GET {path} HTTP/1.1\r\n"
f"Host: {host}:{port}\r\n"
"Upgrade: websocket\r\n"
"Connection: Upgrade\r\n"
f"Sec-WebSocket-Key: {key}\r\n"
"Sec-WebSocket-Version: 13\r\n"
f"Authorization: Bearer {token}\r\n"
"\r\n"
).encode("ascii")
stream.write(request)
stream.flush()
status, headers = _read_http_headers(stream)
expected_accept = base64.b64encode(
hashlib.sha1(f"{key}{WEBSOCKET_GUID}".encode("ascii")).digest()
).decode("ascii")
if not status.startswith("HTTP/1.1 101 "):
raise ProbeError(f"websocket upgrade failed: {status}")
if headers.get("sec-websocket-accept") != expected_accept:
raise ProbeError("websocket accept identity mismatch")
connection.settimeout(None)
return connection, stream
def _decode_event(frame: bytes) -> tuple[dict[str, Any], bytes]:
if len(frame) < 4:
raise ProbeError("shadow event is truncated")
header_bytes = struct.unpack("!I", frame[:4])[0]
if header_bytes < 2 or header_bytes > MAX_HEADER_BYTES:
raise ProbeError("shadow event header length is invalid")
boundary = 4 + header_bytes
if boundary > len(frame):
raise ProbeError("shadow event header is truncated")
try:
header = json.loads(frame[4:boundary])
except (UnicodeDecodeError, json.JSONDecodeError) as exc:
raise ProbeError("shadow event header is invalid") from exc
if not isinstance(header, dict) or header.get("schema_version") != WIRE_SCHEMA:
raise ProbeError("shadow event schema is incompatible")
payload = frame[boundary:]
if int(header.get("payload_bytes", -1)) != len(payload):
raise ProbeError("shadow event payload length mismatch")
if hashlib.sha256(payload).hexdigest() != header.get("payload_sha256"):
raise ProbeError("shadow event payload digest mismatch")
if header.get("commands_enabled") is not False:
raise ProbeError("shadow transport unexpectedly enables commands")
if header.get("navigation_or_safety_accepted") is not False:
raise ProbeError("shadow transport unexpectedly claims safety acceptance")
return header, payload
def _write_report(output_root: Path, report: dict[str, Any]) -> Path:
root = output_root.expanduser().resolve()
if os.name == "nt" and root.drive.upper() != "D:":
raise ProbeError("Windows probe output must stay on drive D")
root.mkdir(parents=True, exist_ok=True)
stamp = datetime.now(UTC).strftime("%Y%m%dT%H%M%SZ")
temporary = root / f".{stamp}-e12-shadow-transport.json.tmp"
destination = root / f"{stamp}-e12-shadow-transport.json"
encoded = json.dumps(report, indent=2, sort_keys=True).encode("utf-8") + b"\n"
with temporary.open("xb") as stream:
stream.write(encoded)
stream.flush()
os.fsync(stream.fileno())
temporary.replace(destination)
return destination
def run(args: argparse.Namespace) -> dict[str, Any]:
token = sys.stdin.readline().strip() if args.token_stdin else args.token
if not token or len(token) < 40:
raise ProbeError("shadow bearer token is missing or invalid")
started_epoch_ns = time.time_ns()
started_monotonic_ns = time.monotonic_ns()
counts: Counter[str] = Counter()
payload_bytes: Counter[str] = Counter()
first_ingress_sequence: int | None = None
last_ingress_sequence: int | None = None
ingress_gaps = 0
session_ids: set[str] = set()
source_ids: set[str] = set()
session_end_seen = False
connection, stream = _connect(
args.host,
args.port,
args.path,
token,
args.socket_timeout_seconds,
)
try:
deadline = time.monotonic() + args.max_duration_seconds
while time.monotonic() < deadline:
readable, _, _ = select.select(
[connection],
[],
[],
min(0.5, max(0.0, deadline - time.monotonic())),
)
if not readable:
continue
opcode, frame = _read_server_frame(stream)
if opcode == 0x8:
break
if opcode == 0x9:
_send_client_frame(stream, 0xA, frame)
continue
if opcode != 0x2:
raise ProbeError(f"unexpected websocket opcode: {opcode}")
header, payload = _decode_event(frame)
sequence = int(header["ingress_sequence"])
if last_ingress_sequence is not None and sequence > last_ingress_sequence + 1:
ingress_gaps += sequence - last_ingress_sequence - 1
if last_ingress_sequence is not None and sequence <= last_ingress_sequence:
raise ProbeError("shadow ingress sequence is not strictly increasing")
first_ingress_sequence = first_ingress_sequence or sequence
last_ingress_sequence = sequence
modality = str(header["modality"])
counts[modality] += 1
payload_bytes[modality] += len(payload)
session_ids.add(str(header["session_id"]))
source_ids.add(str(header["source_id"]))
if modality == "control":
try:
control = json.loads(payload)
except json.JSONDecodeError as exc:
raise ProbeError("control event payload is invalid") from exc
if control.get("event") == "session-end":
session_end_seen = True
break
finally:
with suppress(Exception):
_send_client_frame(stream, 0x8, b"")
stream.close()
connection.close()
completed_epoch_ns = time.time_ns()
report = {
"schema_version": REPORT_SCHEMA,
"state": "completed" if session_end_seen else "timed-out",
"started_at_epoch_ns": started_epoch_ns,
"completed_at_epoch_ns": completed_epoch_ns,
"wall_seconds": (time.monotonic_ns() - started_monotonic_ns) / 1_000_000_000,
"transport": {
"kind": "ssh-reverse-tunnel-websocket",
"endpoint": f"{args.host}:{args.port}",
"worker_has_k1_connection": False,
"payload_integrity": "sha256-verified-per-event",
"clock_qualification": "not-qualified-cross-host",
},
"authority": {
"mode": "shadow-diagnostic-only",
"commands_enabled": False,
"navigation_or_safety_accepted": False,
},
"events": {
"counts": dict(sorted(counts.items())),
"payload_bytes": dict(sorted(payload_bytes.items())),
"first_ingress_sequence": first_ingress_sequence,
"last_ingress_sequence": last_ingress_sequence,
"ingress_sequence_gaps": ingress_gaps,
"session_end_seen": session_end_seen,
"session_ids": sorted(session_ids),
"source_ids": sorted(source_ids),
},
}
destination = _write_report(Path(args.output_root), report)
report["report_path"] = str(destination)
return report
def _arguments() -> argparse.Namespace:
parser = argparse.ArgumentParser()
parser.add_argument("--host", default="host.docker.internal")
parser.add_argument("--port", type=int, default=18012)
parser.add_argument(
"--path",
default=(
"/api/v1/device-plugins/"
"nodedc.device.xgrids-lixelkity-k1/live-perception-shadow"
),
)
parser.add_argument("--token", default="")
parser.add_argument("--token-stdin", action="store_true")
parser.add_argument("--max-duration-seconds", type=float, default=900.0)
parser.add_argument("--socket-timeout-seconds", type=float, default=30.0)
parser.add_argument(
"--output-root",
default="D:/NDC_MISSIONCORE/runtime/derived/e12-shadow-transport",
)
return parser.parse_args()
if __name__ == "__main__":
try:
print(json.dumps(run(_arguments()), indent=2, sort_keys=True))
except Exception as exc:
print(f"E12_SHADOW_TRANSPORT_ERROR={type(exc).__name__}:{exc}", file=sys.stderr)
raise SystemExit(1) from exc
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,768 @@
#!/usr/bin/env python3
"""Run and seal LAB E4 full-session EoMT semantic segmentation."""
from __future__ import annotations
import argparse
import hashlib
import importlib.metadata
import json
import os
import platform
import resource
import shutil
import time
from collections import Counter
from datetime import UTC, datetime
from pathlib import Path
from typing import Any
from run_e3_rectified_segmentation import (
_dependency_manifest,
_model_snapshot,
_profile,
_resource_delta,
_resource_snapshot,
_verify_model_files,
)
from run_recorded_perception_epoch import (
FRAME_SCHEMA,
REPORT_SCHEMA,
RESULT_SCHEMA,
_artifact,
_canonical_json,
_GpuTelemetry,
_palette,
_percentiles,
_read_timeline,
_sha256,
_valid_sha256,
_validate_job,
_write_json,
)
IDENTITY_SCHEMA = "missioncore.recorded-perception-identity/v2"
VALID_FOV_SCHEMA = "missioncore.k1-valid-fov-mask/v1"
PIPELINE_ID = "recorded-semantic-eomt-fisheye-mask/v1"
SEMANTIC_ALPHA = 0.48
TARGET_CLASS_COUNT = 16
def _arguments() -> argparse.Namespace:
parser = argparse.ArgumentParser()
commands = parser.add_subparsers(dest="command", required=True)
preflight = commands.add_parser("preflight")
preflight.add_argument("--job", type=Path, required=True)
preflight.add_argument("--profile", type=Path, required=True)
preflight.add_argument("--valid-fov-root", type=Path, required=True)
preflight.add_argument("--cache", type=Path, required=True)
preflight.add_argument("--environment", type=Path, required=True)
run = commands.add_parser("run")
run.add_argument("--job", type=Path, required=True)
run.add_argument("--profile", type=Path, required=True)
run.add_argument("--valid-fov-root", type=Path, required=True)
run.add_argument("--frames", type=Path, required=True)
run.add_argument("--timeline", type=Path, required=True)
run.add_argument("--cache", type=Path, required=True)
run.add_argument("--environment", type=Path, required=True)
run.add_argument("--output", type=Path, required=True)
run.add_argument("--frame-limit", type=int, default=0)
run.add_argument("--free-bytes-floor", type=int, default=0)
run.add_argument("--orchestrator-sha256", required=True)
run.add_argument("--container-image", required=True)
run.add_argument("--telemetry-interval-seconds", type=float, default=1.0)
finalize = commands.add_parser("finalize")
finalize.add_argument("--output", type=Path, required=True)
finalize.add_argument("--video", type=Path, required=True)
finalize.add_argument("--masks", type=Path, required=True)
finalize.add_argument("--extract-seconds", type=float, required=True)
finalize.add_argument("--encode-seconds", type=float, required=True)
finalize.add_argument("--archive-seconds", type=float, required=True)
finalize.add_argument("--wall-seconds", type=float, required=True)
finalize.add_argument("--encoder", required=True)
finalize.add_argument("--disk-free-before-bytes", type=int, required=True)
finalize.add_argument("--disk-free-post-extract-bytes", type=int, required=True)
finalize.add_argument("--disk-free-post-inference-bytes", type=int, required=True)
finalize.add_argument("--disk-free-post-artifacts-bytes", type=int, required=True)
finalize.add_argument("--disk-floor-bytes", type=int, required=True)
finalize.add_argument("--working-set-reserve-bytes", type=int, required=True)
return parser.parse_args()
def _read_object(path: Path) -> dict[str, Any]:
value = json.loads(path.read_text(encoding="utf-8-sig"))
if not isinstance(value, dict):
raise RuntimeError(f"JSON root is not an object: {path}")
return value
def _validate_source(job: dict[str, Any], profile: dict[str, Any]) -> None:
source = profile["source"]
input_document = job["input"]
if (
input_document.get("kind") != "canonical-camera-epoch"
or input_document.get("source_id") != source["source_id"]
or source.get("resolution") != [800, 600]
):
raise RuntimeError("LAB E4 profile does not match the camera job")
def _load_valid_fov(
root: Path,
job: dict[str, Any],
profile: dict[str, Any],
) -> tuple[Any, dict[str, Any]]:
import numpy as np
from PIL import Image
resolved = root.resolve(strict=True)
manifest = _read_object(resolved / "manifest.json")
identity = manifest.get("identity")
identity_sha256 = manifest.get("identity_sha256")
artifact = manifest.get("artifact")
source = profile["source"]
if (
manifest.get("schema_version") != VALID_FOV_SCHEMA
or not isinstance(identity, dict)
or not _valid_sha256(identity_sha256)
or hashlib.sha256(_canonical_json(identity)).hexdigest() != identity_sha256
or manifest.get("generation_id") != f"valid-fov-mask-{identity_sha256}"
or identity.get("calibration_sha256") != source["calibration_sha256"]
or identity.get("calibration_slot") != source["calibration_slot"]
or identity.get("source_id") != job["input"]["source_id"]
or identity.get("admitted_resolution") != source["resolution"]
or not isinstance(artifact, dict)
or artifact.get("path") != "mask.png"
or artifact.get("mode") != "L"
or artifact.get("inside_value") != 255
or artifact.get("outside_value") != 0
or not _valid_sha256(artifact.get("sha256"))
):
raise RuntimeError("LAB E4 valid-FOV binding is invalid")
mask_path = (resolved / "mask.png").resolve(strict=True)
if (
mask_path.parent != resolved
or mask_path.stat().st_size != artifact.get("byte_length")
or _sha256(mask_path) != artifact["sha256"]
):
raise RuntimeError("LAB E4 valid-FOV artifact changed")
with Image.open(mask_path) as opened:
mask = np.asarray(opened, dtype=np.uint8)
if mask.shape != (600, 800) or not np.isin(mask, (0, 255)).all():
raise RuntimeError("LAB E4 valid-FOV mask pixels are invalid")
valid = mask > 0
geometry = manifest.get("geometry")
if (
not isinstance(geometry, dict)
or geometry.get("valid_pixel_count") != int(valid.sum())
or int(valid.sum()) < 1
):
raise RuntimeError("LAB E4 valid-FOV geometry changed")
return valid, {
"generation_id": manifest["generation_id"],
"identity_sha256": identity_sha256,
"mask_sha256": artifact["sha256"],
"valid_pixel_count": int(valid.sum()),
"total_pixel_count": int(valid.size),
}
def _load_model(
profile: dict[str, Any],
cache: Path,
device: Any,
) -> tuple[Any, Any, dict[int, str], Any, list[dict[str, Any]]]:
import numpy as np
import torch
from transformers import AutoImageProcessor, EomtForUniversalSegmentation
snapshot = _model_snapshot(profile, cache, offline=True)
model_files = _verify_model_files(profile, snapshot)
processor = AutoImageProcessor.from_pretrained(
snapshot,
local_files_only=True,
use_fast=True,
)
model, loading = EomtForUniversalSegmentation.from_pretrained(
snapshot,
local_files_only=True,
output_loading_info=True,
)
problems = {
name: loading.get(name, [])
for name in ("missing_keys", "unexpected_keys", "mismatched_keys", "error_msgs")
if loading.get(name)
}
if problems:
raise RuntimeError("EoMT checkpoint did not load exactly: " + json.dumps(problems))
model = model.to(device=device, dtype=torch.float16).eval()
labels = {int(key): str(value) for key, value in model.config.id2label.items()}
mapping = profile["cityscapes_to_target"]
if set(labels.values()) != set(mapping):
raise RuntimeError("EoMT runtime taxonomy changed")
target_lut = np.asarray([mapping[labels[index]] for index in range(19)], dtype=np.uint8)
return processor, model, labels, target_lut, model_files
def _preflight(args: argparse.Namespace) -> int:
import torch
job = _validate_job(args.job.resolve(strict=True))
profile, profile_sha256 = _profile(args.profile)
_validate_source(job, profile)
dependency = _dependency_manifest(args.environment.resolve(strict=True))
if dependency["identity"]["profile_sha256"] != profile_sha256:
raise RuntimeError("LAB E4 dependencies belong to another profile")
_load_valid_fov(args.valid_fov_root, job, profile)
if not torch.cuda.is_available() or torch.cuda.device_count() < 1:
raise RuntimeError("CUDA device 0 is unavailable")
device = torch.device("cuda:0")
processor, model, _labels, _target_lut, model_files = _load_model(
profile,
args.cache.resolve(strict=True),
device,
)
del processor, model, _labels, _target_lut
torch.cuda.empty_cache()
print(
json.dumps(
{
"state": "preflight-ready",
"job_id": job["job_id"],
"source_id": job["input"]["source_id"],
"frames": job["input"]["segment_count"],
"pipeline": PIPELINE_ID,
"model_files": model_files,
"cuda_device": torch.cuda.get_device_name(),
},
sort_keys=True,
),
flush=True,
)
return 0
def _class_document(
semantic: Any,
valid_mask: Any,
target_names: dict[int, str],
) -> list[dict[str, Any]]:
import numpy as np
counts = np.bincount(semantic[valid_mask].reshape(-1), minlength=TARGET_CLASS_COUNT)
total = int(valid_mask.sum())
return [
{
"id": index,
"label": target_names[index],
"pixels": int(counts[index]),
"fraction_of_valid_fov": round(float(counts[index]) / total, 9),
}
for index in range(1, TARGET_CLASS_COUNT)
if counts[index] > 0
]
def _overlay(image: Any, semantic: Any) -> Any:
import numpy as np
colors = np.zeros_like(image)
for category_id in range(1, TARGET_CLASS_COUNT):
colors[semantic == category_id] = _palette(category_id)
blended = np.rint(
image.astype(np.float32) * (1.0 - SEMANTIC_ALPHA)
+ colors.astype(np.float32) * SEMANTIC_ALPHA
)
return (
np.where(
(semantic > 0)[..., None],
blended,
image,
)
.clip(0, 255)
.astype(np.uint8)
)
def _write_png(path: Path, array: Any) -> None:
from PIL import Image
Image.fromarray(array).save(path, format="PNG", optimize=False)
def _assert_disk_floor(path: Path, floor: int, frame: int) -> None:
if floor < 0:
raise RuntimeError("disk free-space floor is invalid")
free = shutil.disk_usage(path).free
if floor and free < floor:
raise RuntimeError(f"D-backed output crossed its free-space floor at frame {frame}")
def _run(args: argparse.Namespace) -> int:
import numpy as np
import torch
import transformers
from PIL import Image
job_root = args.job.resolve(strict=True)
if not _valid_sha256(args.orchestrator_sha256):
raise RuntimeError("LAB E4 orchestrator SHA-256 is invalid")
if not 1 <= len(args.container_image) <= 256:
raise RuntimeError("LAB E4 container image identity is invalid")
job = _validate_job(job_root)
profile, profile_sha256 = _profile(args.profile)
_validate_source(job, profile)
dependency = _dependency_manifest(args.environment.resolve(strict=True))
if dependency["identity"]["profile_sha256"] != profile_sha256:
raise RuntimeError("LAB E4 dependencies belong to another profile")
valid_mask, valid_fov = _load_valid_fov(args.valid_fov_root, job, profile)
input_document = job["input"]
full_frame_count = int(input_document["segment_count"])
if args.frame_limit < 0 or args.frame_limit > full_frame_count:
raise RuntimeError("LAB E4 frame limit escapes the camera job")
frame_count = args.frame_limit or full_frame_count
frames_root = args.frames.resolve(strict=True)
frame_paths = [frames_root / f"frame-{index:06d}.png" for index in range(1, frame_count + 1)]
if not all(path.is_file() for path in frame_paths):
raise RuntimeError("decoded LAB E4 frame set is incomplete")
if len(list(frames_root.glob("frame-*.png"))) != frame_count:
raise RuntimeError("decoded LAB E4 frame set contains unexpected files")
timeline = input_document["timeline"]
timestamps = _read_timeline(
args.timeline.resolve(strict=True),
frame_count,
float(timeline["start_seconds"]),
float(timeline["end_seconds"]),
)
output = args.output.resolve()
if output.exists():
raise RuntimeError("LAB E4 output must be absent")
output.mkdir(mode=0o700, parents=True, exist_ok=False)
masks_root = output / "semantic-masks"
overlays_root = output / "overlay-frames"
masks_root.mkdir(mode=0o700)
overlays_root.mkdir(mode=0o700)
_assert_disk_floor(output, args.free_bytes_floor, 0)
if not torch.cuda.is_available():
raise RuntimeError("CUDA is required for LAB E4")
device = torch.device("cuda:0")
processor, model, model_labels, target_lut, model_files = _load_model(
profile,
args.cache.resolve(strict=True),
device,
)
target_names = {int(key): str(value) for key, value in profile["target_taxonomy"].items()}
if set(target_names) != set(range(TARGET_CLASS_COUNT)):
raise RuntimeError("LAB E4 target taxonomy changed")
def infer(image: Any) -> tuple[Any, dict[str, float]]:
processor_started = time.perf_counter()
inputs = processor(images=Image.fromarray(image), return_tensors="pt")
processor_ms = (time.perf_counter() - processor_started) * 1000.0
torch.cuda.synchronize()
transfer_started = time.perf_counter()
inputs = {
name: value.to(device) if isinstance(value, torch.Tensor) else value
for name, value in inputs.items()
}
torch.cuda.synchronize()
transfer_ms = (time.perf_counter() - transfer_started) * 1000.0
forward_started = time.perf_counter()
with torch.inference_mode(), torch.amp.autocast("cuda", dtype=torch.float16):
outputs = model(**inputs)
torch.cuda.synchronize()
forward_ms = (time.perf_counter() - forward_started) * 1000.0
post_started = time.perf_counter()
semantic = processor.post_process_semantic_segmentation(
outputs,
target_sizes=[image.shape[:2]],
)[0]
semantic = semantic.detach().cpu().numpy().astype(np.uint8)
post_ms = (time.perf_counter() - post_started) * 1000.0
del inputs, outputs
return semantic, {
"processor_ms": processor_ms,
"host_to_device_ms": transfer_ms,
"forward_ms": forward_ms,
"model_postprocess_ms": post_ms,
}
with Image.open(frame_paths[0]) as opened:
warm_image = np.asarray(opened.convert("RGB"), dtype=np.uint8)
if warm_image.shape != (600, 800, 3):
raise RuntimeError("LAB E4 input resolution changed")
warm_image = np.where(valid_mask[..., None], warm_image, 0).astype(np.uint8)
warm_semantic, _warm_latency = infer(warm_image)
del warm_semantic, _warm_latency
latency = {
name: []
for name in (
"image_decode_ms",
"valid_fov_fill_ms",
"processor_ms",
"host_to_device_ms",
"forward_ms",
"model_postprocess_ms",
"overlay_ms",
"artifact_write_ms",
"end_to_end_ms",
)
}
total_pixels = Counter()
metadata_path = output / "frames.jsonl"
telemetry_path = output / "gpu-telemetry.jsonl"
resource_before = _resource_snapshot()
disk_before = shutil.disk_usage(output).free
started = time.perf_counter()
with (
telemetry_path.open("x", encoding="utf-8", newline="\n") as telemetry_stream,
metadata_path.open("x", encoding="utf-8", newline="\n") as metadata_stream,
_GpuTelemetry(telemetry_stream, args.telemetry_interval_seconds) as telemetry,
):
for frame_index, (path, session_seconds) in enumerate(
zip(frame_paths, timestamps, strict=True)
):
frame_started = time.perf_counter()
decode_started = time.perf_counter()
with Image.open(path) as opened:
image = np.asarray(opened.convert("RGB"), dtype=np.uint8)
latency["image_decode_ms"].append((time.perf_counter() - decode_started) * 1000.0)
if image.shape != (600, 800, 3):
raise RuntimeError("LAB E4 input resolution changed")
fill_started = time.perf_counter()
model_input = np.where(valid_mask[..., None], image, 0).astype(np.uint8)
latency["valid_fov_fill_ms"].append((time.perf_counter() - fill_started) * 1000.0)
semantic, measured = infer(model_input)
if semantic.max() >= len(target_lut):
raise RuntimeError("EoMT emitted an unknown category")
target = target_lut[semantic]
target = target.copy()
target[~valid_mask] = 0
if target.shape != valid_mask.shape or np.any(target[~valid_mask] != 0):
raise RuntimeError("LAB E4 semantic mask escaped valid FOV")
for name, value in measured.items():
latency[name].append(value)
overlay_started = time.perf_counter()
overlay = _overlay(image, target)
classes = _class_document(target, valid_mask, target_names)
latency["overlay_ms"].append((time.perf_counter() - overlay_started) * 1000.0)
counts = np.bincount(target[valid_mask], minlength=TARGET_CLASS_COUNT)
for category_id in range(1, TARGET_CLASS_COUNT):
total_pixels[target_names[category_id]] += int(counts[category_id])
write_started = time.perf_counter()
_write_png(masks_root / f"frame-{frame_index + 1:06d}.png", target)
_write_png(overlays_root / f"frame-{frame_index + 1:06d}.png", overlay)
metadata_stream.write(
json.dumps(
{
"schema_version": FRAME_SCHEMA,
"frame_index": frame_index,
"sequence": frame_index + 1,
"session_seconds": round(session_seconds, 9),
"instances": [],
"semantic_classes": classes,
},
ensure_ascii=False,
sort_keys=True,
separators=(",", ":"),
allow_nan=False,
)
+ "\n"
)
latency["artifact_write_ms"].append((time.perf_counter() - write_started) * 1000.0)
latency["end_to_end_ms"].append((time.perf_counter() - frame_started) * 1000.0)
completed = frame_index + 1
if completed % 100 == 0 or completed == frame_count:
metadata_stream.flush()
telemetry_stream.flush()
_assert_disk_floor(output, args.free_bytes_floor, completed)
print(
json.dumps(
{
"phase": "semantic",
"frames_processed": completed,
"frames_total": frame_count,
"free_bytes": shutil.disk_usage(output).free,
},
sort_keys=True,
),
flush=True,
)
metadata_stream.flush()
os.fsync(metadata_stream.fileno())
inference_elapsed = time.perf_counter() - started
resource_after = _resource_snapshot()
disk_after = shutil.disk_usage(output).free
report = {
"schema_version": REPORT_SCHEMA,
"run_id": f"{job['job_id']}-e4-eomt-full-session-v1",
"created_at_utc": datetime.now(UTC)
.isoformat(timespec="milliseconds")
.replace("+00:00", "Z"),
"state": (
"inference-complete-awaiting-publication"
if frame_count == full_frame_count
else "technical-pilot-complete-not-publishable"
),
"ground_truth": False,
"input": {
"job_id": job["job_id"],
"input_sha256": job["input_sha256"],
"session_id": input_document["session_id"],
"source_id": input_document["source_id"],
"codec_epoch": input_document["codec_epoch"],
"segment_count": full_frame_count,
"frames_admitted": frame_count,
"byte_length": input_document["byte_length"],
"timeline_start_seconds": timeline["start_seconds"],
"timeline_end_seconds": timeline["end_seconds"],
"frame_timeline_sha256": _sha256(args.timeline.resolve(strict=True)),
},
"calibration": {
"content_identity_sha256": profile["source"]["calibration_sha256"],
"camera_slot": profile["source"]["calibration_slot"],
},
"configuration": {
"pipeline": PIPELINE_ID,
"semantic_alpha": SEMANTIC_ALPHA,
"batch_size": 1,
"precision": "fp16-autocast",
"frame_policy": (
"all-frames-no-sampling"
if frame_count == full_frame_count
else f"technical-pilot-first-{frame_count}-frames"
),
"instance_branch": "disabled",
"profile_sha256": profile_sha256,
"dependency_identity_sha256": dependency["identity_sha256"],
"valid_fov": valid_fov,
"runner_sha256": _sha256(Path(__file__).resolve(strict=True)),
"orchestrator_sha256": args.orchestrator_sha256,
"container_image": args.container_image,
},
"models": {
"semantic": {
"id": profile["model"]["id"],
"revision": profile["model"]["revision"],
"architecture": profile["model"]["architecture"],
"checkpoint_load": "exact-no-missing-unexpected-or-mismatched-keys",
"runtime_labels": {
str(index): label for index, label in sorted(model_labels.items())
},
},
"files": model_files,
},
"runtime": {
"hostname": platform.node(),
"platform": platform.platform(),
"python": platform.python_version(),
"torch": torch.__version__,
"transformers": transformers.__version__,
"cuda_runtime": torch.version.cuda,
"gpu": torch.cuda.get_device_name(),
"gpu_compute_capability": list(torch.cuda.get_device_capability()),
},
"metrics": {
"frames_expected": frame_count,
"frames_processed": frame_count,
"frames_failed": 0,
"frames_skipped": 0,
"instances": 0,
"inference_wall_seconds": round(inference_elapsed, 6),
"inference_frames_per_second": round(frame_count / inference_elapsed, 6),
"latency_ms": {name: _percentiles(values) for name, values in latency.items()},
"semantic_pixel_totals_inside_valid_fov": dict(sorted(total_pixels.items())),
"cuda_peak_memory_allocated_mib": round(
torch.cuda.max_memory_allocated() / 2**20,
3,
),
"cuda_peak_memory_reserved_mib": round(
torch.cuda.max_memory_reserved() / 2**20,
3,
),
"process_peak_rss_mib": round(
resource.getrusage(resource.RUSAGE_SELF).ru_maxrss / 1024,
3,
),
"resource_delta": _resource_delta(resource_before, resource_after),
"gpu_telemetry": telemetry.summary(),
"disk": {
"free_bytes_before_inference": disk_before,
"free_bytes_after_inference": disk_after,
"free_bytes_floor": args.free_bytes_floor,
},
},
"versions": {
name: importlib.metadata.version(name)
for name in ("numpy", "pillow", "torch", "transformers")
},
}
_write_json(output / "run-report.partial.json", report)
print(
json.dumps(
{
"state": report["state"],
"frames": frame_count,
"inference_seconds": round(inference_elapsed, 6),
},
sort_keys=True,
),
flush=True,
)
return 0
def _finalize(args: argparse.Namespace) -> int:
output = args.output.resolve(strict=True)
video = args.video.resolve(strict=True)
masks = args.masks.resolve(strict=True)
if video.parent != output or masks.parent != output:
raise RuntimeError("published LAB E4 artifacts must be direct result children")
partial_path = output / "run-report.partial.json"
frames_path = output / "frames.jsonl"
telemetry_path = output / "gpu-telemetry.jsonl"
partial = _read_object(partial_path)
input_document = partial.get("input")
metrics = partial.get("metrics")
if (
partial.get("schema_version") != REPORT_SCHEMA
or partial.get("state") != "inference-complete-awaiting-publication"
or not isinstance(input_document, dict)
or not isinstance(metrics, dict)
or input_document.get("frames_admitted") != input_document.get("segment_count")
or metrics.get("frames_expected") != input_document.get("segment_count")
or metrics.get("frames_processed") != input_document.get("segment_count")
):
raise RuntimeError("only a complete LAB E4 camera epoch can be finalized")
for value in (
args.extract_seconds,
args.encode_seconds,
args.archive_seconds,
args.wall_seconds,
):
if value <= 0:
raise RuntimeError("LAB E4 publication timing is invalid")
disk_values = (
args.disk_free_before_bytes,
args.disk_free_post_extract_bytes,
args.disk_free_post_inference_bytes,
args.disk_free_post_artifacts_bytes,
args.disk_floor_bytes,
args.working_set_reserve_bytes,
)
if any(value < 0 for value in disk_values):
raise RuntimeError("LAB E4 publication disk telemetry is invalid")
if any(
value < args.disk_floor_bytes
for value in (
args.disk_free_before_bytes,
args.disk_free_post_extract_bytes,
args.disk_free_post_inference_bytes,
args.disk_free_post_artifacts_bytes,
)
):
raise RuntimeError("LAB E4 publication crossed its D: free-space floor")
identity = {
"schema_version": IDENTITY_SCHEMA,
"job_id": input_document["job_id"],
"input_sha256": input_document["input_sha256"],
"calibration": partial["calibration"],
"configuration": partial["configuration"],
"models": partial["models"],
"publication": {
"video_encoder": args.encoder,
"video_media_type": "video/mp4",
"mask_archive_media_type": "application/gzip",
"content": "semantic-overlay-and-semantic-masks",
},
}
identity_sha256 = hashlib.sha256(_canonical_json(identity)).hexdigest()
result_id = f"result-{identity_sha256}"
final_report = {
**partial,
"state": "published",
"result_id": result_id,
"publication": {
"extract_seconds": round(args.extract_seconds, 6),
"encode_seconds": round(args.encode_seconds, 6),
"archive_seconds": round(args.archive_seconds, 6),
"wall_seconds": round(args.wall_seconds, 6),
"end_to_end_frames_per_second": round(
int(metrics["frames_processed"]) / args.wall_seconds,
6,
),
"encoder": args.encoder,
"disk": {
"free_bytes_before": args.disk_free_before_bytes,
"free_bytes_post_extract": args.disk_free_post_extract_bytes,
"free_bytes_post_inference": args.disk_free_post_inference_bytes,
"free_bytes_post_artifacts": args.disk_free_post_artifacts_bytes,
"free_bytes_floor": args.disk_floor_bytes,
"working_set_reserve_bytes": args.working_set_reserve_bytes,
},
},
}
report_path = output / "run-report.json"
_write_json(report_path, final_report)
artifacts = [
_artifact(video, "panoptic-overlay-video", "video/mp4"),
_artifact(masks, "panoptic-mask-archive", "application/gzip"),
_artifact(frames_path, "panoptic-frame-metadata", "application/x-ndjson", FRAME_SCHEMA),
_artifact(telemetry_path, "worker-gpu-telemetry", "application/x-ndjson"),
_artifact(report_path, "perception-run-report", "application/json", REPORT_SCHEMA),
]
result = {
"schema_version": RESULT_SCHEMA,
"result_id": result_id,
"identity_sha256": identity_sha256,
"identity": identity,
"created_at_utc": final_report["created_at_utc"],
"job_id": input_document["job_id"],
"input_sha256": input_document["input_sha256"],
"session_id": input_document["session_id"],
"source_id": input_document["source_id"],
"codec_epoch": input_document["codec_epoch"],
"timestamp_basis": "session-time-seconds",
"timeline_start_seconds": input_document["timeline_start_seconds"],
"timeline_end_seconds": input_document["timeline_end_seconds"],
"frames_processed": metrics["frames_processed"],
"ground_truth": False,
"artifacts": artifacts,
}
_write_json(output / "result.json", result)
partial_path.unlink()
print(
json.dumps(
{"result_id": result_id, "identity_sha256": identity_sha256},
sort_keys=True,
),
flush=True,
)
return 0
def main() -> int:
args = _arguments()
if args.command == "preflight":
return _preflight(args)
if args.command == "run":
return _run(args)
return _finalize(args)
if __name__ == "__main__":
raise SystemExit(main())
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,687 @@
#!/usr/bin/env python3
"""Run source-paced LAB E8 YOLOX plus tracking without synchronous overlays."""
from __future__ import annotations
import argparse
import hashlib
import json
import math
import os
import platform
import resource
import shutil
import tempfile
import threading
import time
from collections import Counter, deque
from dataclasses import dataclass
from datetime import UTC, datetime
from pathlib import Path
from typing import Any
import numpy as np
from run_e5_instance_tracking import (
TwoStageTracker,
_detections,
_duplicate_pairs,
_infer,
_load_valid_fov,
_preprocess,
_read_timeline,
_track_document,
_validate_source,
_verify_model,
)
from run_e5_instance_tracking import (
_read_profile as _read_e5_profile,
)
from run_recorded_perception_epoch import (
_artifact,
_canonical_json,
_GpuTelemetry,
_percentiles,
_sha256,
_valid_sha256,
_validate_job,
_write_json,
)
PROFILE_SCHEMA = "missioncore.e8-realtime-tracking-profile/v1"
FRAME_SCHEMA = "missioncore.e8-realtime-tracking-frame/v1"
TELEMETRY_SCHEMA = "missioncore.e8-realtime-tracking-telemetry/v1"
REPORT_SCHEMA = "missioncore.e8-realtime-tracking-report/v1"
RESULT_SCHEMA = "missioncore.e8-realtime-tracking-result/v1"
IDENTITY_SCHEMA = "missioncore.e8-realtime-tracking-identity/v1"
PIPELINE_ID = "source-paced-yolox-bytetrack-latest-wins/v1"
def _arguments() -> argparse.Namespace:
parser = argparse.ArgumentParser()
commands = parser.add_subparsers(dest="command", required=True)
for name in ("preflight", "run"):
command = commands.add_parser(name)
command.add_argument("--job", type=Path, required=True)
command.add_argument("--profile", type=Path, required=True)
command.add_argument("--valid-fov-root", type=Path, required=True)
command.add_argument("--model-root", type=Path, required=True)
if name == "run":
command.add_argument("--frames", type=Path, required=True)
command.add_argument("--timeline", type=Path, required=True)
command.add_argument("--output", type=Path, required=True)
command.add_argument("--triton-url", required=True)
command.add_argument("--free-bytes-floor", type=int, default=0)
command.add_argument("--orchestrator-sha256", required=True)
command.add_argument("--container-image", required=True)
command.add_argument("--telemetry-interval-seconds", type=float, default=1.0)
return parser.parse_args()
def _read_object(path: Path) -> dict[str, Any]:
value = json.loads(path.read_text(encoding="utf-8-sig"))
if not isinstance(value, dict):
raise RuntimeError(f"JSON root is not an object: {path}")
return value
def _read_profile(path: Path) -> tuple[dict[str, Any], str]:
resolved = path.resolve(strict=True)
profile = _read_object(resolved)
if profile.get("schema_version") != PROFILE_SCHEMA:
raise RuntimeError("LAB E8 profile schema changed")
# Reuse the exhaustively tested E5 detector/tracker validation by changing
# only the schema in memory. No E5 defaults are inferred.
e5_shape = dict(profile)
e5_shape["schema_version"] = "missioncore.e5-tracking-profile/v1"
temporary: Path | None = None
try:
with tempfile.NamedTemporaryFile(
mode="w",
encoding="utf-8",
prefix="lab-e8-e5-validation-",
suffix=".json",
delete=False,
) as stream:
json.dump(e5_shape, stream, sort_keys=True, separators=(",", ":"))
temporary = Path(stream.name)
_read_e5_profile(temporary)
finally:
if temporary is not None:
temporary.unlink(missing_ok=True)
realtime = profile.get("realtime")
acceptance = profile.get("acceptance")
if not isinstance(realtime, dict) or not isinstance(acceptance, dict):
raise RuntimeError("LAB E8 realtime/acceptance configuration is missing")
mode = profile.get("mode")
capacity = realtime.get("queue_capacity")
speed = realtime.get("speed")
delay = realtime.get("consumer_delay_ms")
stale = realtime.get("stale_after_ms")
unavailable = realtime.get("unavailable_after_ms")
if (
mode not in {"pilot", "qualification", "overload-negative-control"}
or realtime.get("queue_policy") != "bounded-latest-wins"
or not isinstance(capacity, int)
or isinstance(capacity, bool)
or not 1 <= capacity <= 8
or not isinstance(speed, int | float)
or isinstance(speed, bool)
or not 0.1 <= float(speed) <= 10.0
or not isinstance(delay, int | float)
or isinstance(delay, bool)
or not 0 <= float(delay) <= 5000
or not isinstance(stale, int | float)
or not isinstance(unavailable, int | float)
or not 0 < float(stale) < float(unavailable)
):
raise RuntimeError("LAB E8 scheduling configuration is invalid")
numeric_acceptance = (
acceptance.get("minimum_effective_fps"),
acceptance.get("maximum_drop_fraction"),
acceptance.get("maximum_p95_result_age_ms"),
)
if (
any(
not isinstance(value, int | float)
or isinstance(value, bool)
or not math.isfinite(float(value))
or float(value) < 0
for value in numeric_acceptance
)
or float(acceptance["maximum_drop_fraction"]) > 1
or not isinstance(acceptance.get("require_zero_failures"), bool)
or not isinstance(acceptance.get("expect_overload"), bool)
):
raise RuntimeError("LAB E8 acceptance configuration is invalid")
return profile, _sha256(resolved)
@dataclass(frozen=True, slots=True)
class FrameEnvelope:
frame_index: int
path: Path
timeline: dict[str, Any]
scheduled_monotonic: float
decoded_monotonic: float
image: np.ndarray
decode_ms: float
source_release_lag_ms: float
class LatestWinsQueue:
def __init__(self, capacity: int) -> None:
self.capacity = capacity
self.items: deque[FrameEnvelope] = deque()
self.condition = threading.Condition()
self.maximum_depth = 0
self.published = 0
self.consumed = 0
self.dropped_overflow = 0
self.closed = False
def publish(self, item: FrameEnvelope) -> None:
with self.condition:
if self.closed:
raise RuntimeError("cannot publish to a closed LAB E8 queue")
if len(self.items) == self.capacity:
self.items.popleft()
self.dropped_overflow += 1
self.items.append(item)
self.published += 1
self.maximum_depth = max(self.maximum_depth, len(self.items))
self.condition.notify()
def take(self) -> FrameEnvelope | None:
with self.condition:
self.condition.wait_for(lambda: bool(self.items) or self.closed)
if not self.items:
return None
value = self.items.popleft()
self.consumed += 1
return value
def close(self) -> None:
with self.condition:
self.closed = True
self.condition.notify_all()
def snapshot(self) -> dict[str, int | bool]:
with self.condition:
return {
"capacity": self.capacity,
"final_depth": len(self.items),
"maximum_depth": self.maximum_depth,
"published": self.published,
"consumed": self.consumed,
"dropped_overflow": self.dropped_overflow,
"closed": self.closed,
}
def _wait_until(deadline: float) -> None:
while True:
remaining = deadline - time.perf_counter()
if remaining <= 0:
return
time.sleep(min(remaining, 0.02))
def _health(age_ms: float, realtime: dict[str, Any]) -> str:
if age_ms >= float(realtime["unavailable_after_ms"]):
return "unavailable"
if age_ms >= float(realtime["stale_after_ms"]):
return "stale"
return "healthy"
def _producer(
*,
queue: LatestWinsQueue,
frame_paths: list[Path],
timeline_rows: list[dict[str, Any]],
replay_started: float,
speed: float,
error: list[BaseException],
) -> None:
from PIL import Image
first_session = float(timeline_rows[0]["session_seconds"])
try:
for frame_index, (path, row) in enumerate(zip(frame_paths, timeline_rows, strict=True)):
scheduled = replay_started + (float(row["session_seconds"]) - first_session) / speed
_wait_until(scheduled)
decode_started = time.perf_counter()
with Image.open(path) as opened:
image = np.asarray(opened.convert("RGB"), dtype=np.uint8)
decoded = time.perf_counter()
if image.shape != (600, 800, 3):
raise RuntimeError("LAB E8 input resolution changed")
queue.publish(
FrameEnvelope(
frame_index=frame_index,
path=path,
timeline=row,
scheduled_monotonic=scheduled,
decoded_monotonic=decoded,
image=image,
decode_ms=(decoded - decode_started) * 1000.0,
source_release_lag_ms=max(0.0, (decode_started - scheduled) * 1000.0),
)
)
except BaseException as exc:
error.append(exc)
finally:
queue.close()
def _assert_disk_floor(path: Path, floor: int, frame: int) -> None:
if floor < 0:
raise RuntimeError("LAB E8 disk floor is invalid")
free = shutil.disk_usage(path).free
if floor and free < floor:
raise RuntimeError(f"LAB E8 crossed the D-backed free-space floor at frame {frame}")
def _preflight(args: argparse.Namespace) -> int:
job = _validate_job(args.job.resolve(strict=True))
profile, profile_sha256 = _read_profile(args.profile)
_validate_source(job, profile)
valid_mask, valid_fov = _load_valid_fov(args.valid_fov_root, job, profile)
model_files = _verify_model(profile, args.model_root)
from scipy.optimize import linear_sum_assignment # noqa: F401
print(
json.dumps(
{
"state": "preflight-ready",
"job_id": job["job_id"],
"profile_sha256": profile_sha256,
"model_files": model_files,
"valid_fov": valid_fov,
"valid_pixels": int(valid_mask.sum()),
},
sort_keys=True,
),
flush=True,
)
return 0
def _run(args: argparse.Namespace) -> int:
from PIL import Image
from scipy.optimize import linear_sum_assignment
if not _valid_sha256(args.orchestrator_sha256):
raise RuntimeError("LAB E8 orchestrator SHA-256 is invalid")
if not args.triton_url.startswith("http://") or len(args.triton_url) > 256:
raise RuntimeError("LAB E8 Triton URL is invalid")
job = _validate_job(args.job.resolve(strict=True))
profile, profile_sha256 = _read_profile(args.profile)
_validate_source(job, profile)
valid_mask, valid_fov = _load_valid_fov(args.valid_fov_root, job, profile)
model_files = _verify_model(profile, args.model_root)
frames_root = args.frames.resolve(strict=True)
frame_paths = sorted(frames_root.glob("frame-*.png"))
if not frame_paths or [path.name for path in frame_paths] != [
f"frame-{index:06d}.png" for index in range(1, len(frame_paths) + 1)
]:
raise RuntimeError("LAB E8 decoded frame sequence changed")
timeline_path = args.timeline.resolve(strict=True)
timeline_rows = _read_timeline(timeline_path, len(frame_paths))
input_timeline = job["input"]["timeline"]
if float(timeline_rows[0]["session_seconds"]) < float(input_timeline["start_seconds"]) or float(
timeline_rows[-1]["session_seconds"]
) > float(input_timeline["end_seconds"]):
raise RuntimeError("LAB E8 clip escaped the source timeline")
output = args.output.resolve()
if output.exists():
raise RuntimeError("LAB E8 output must be absent")
output.mkdir(mode=0o700, parents=True, exist_ok=False)
_assert_disk_floor(output, args.free_bytes_floor, 0)
tracker = TwoStageTracker(profile["tracking"])
linear_sum_assignment(np.zeros((1, 1), dtype=np.float64))
with Image.open(frame_paths[0]) as opened:
warm_image = np.asarray(opened.convert("RGB"), dtype=np.uint8)
warm_tensor = _preprocess(warm_image, valid_mask, profile)
_infer(args.triton_url, profile["model"], warm_tensor)
del warm_tensor, warm_image
realtime = profile["realtime"]
queue = LatestWinsQueue(int(realtime["queue_capacity"]))
producer_errors: list[BaseException] = []
latency = {
name: []
for name in (
"image_decode_ms",
"source_release_lag_ms",
"queue_wait_ms",
"preprocess_ms",
"triton_request_ms",
"postprocess_ms",
"tracking_ms",
"processing_ms",
"result_age_ms",
)
}
detection_labels: Counter[str] = Counter()
track_labels: Counter[str] = Counter()
rejection_reasons: Counter[str] = Counter()
health_counts: Counter[str] = Counter()
unique_track_ids: set[int] = set()
duplicate_pairs = 0
failures = 0
metadata_path = output / "frames.jsonl"
telemetry_path = output / "telemetry.jsonl"
gpu_path = output / "gpu-telemetry.jsonl"
disk_before = shutil.disk_usage(output).free
replay_started = time.perf_counter() + 0.25
producer = threading.Thread(
target=_producer,
kwargs={
"queue": queue,
"frame_paths": frame_paths,
"timeline_rows": timeline_rows,
"replay_started": replay_started,
"speed": float(realtime["speed"]),
"error": producer_errors,
},
name="lab-e8-source-producer",
daemon=True,
)
producer.start()
with (
metadata_path.open("x", encoding="utf-8", newline="\n") as metadata_stream,
telemetry_path.open("x", encoding="utf-8", newline="\n") as telemetry_stream,
gpu_path.open("x", encoding="utf-8", newline="\n") as gpu_stream,
_GpuTelemetry(gpu_stream, args.telemetry_interval_seconds) as gpu_telemetry,
):
while (envelope := queue.take()) is not None:
processing_started = time.perf_counter()
latency["image_decode_ms"].append(envelope.decode_ms)
latency["source_release_lag_ms"].append(envelope.source_release_lag_ms)
latency["queue_wait_ms"].append(
max(0.0, (processing_started - envelope.decoded_monotonic) * 1000.0)
)
try:
preprocess_started = time.perf_counter()
tensor = _preprocess(envelope.image, valid_mask, profile)
latency["preprocess_ms"].append((time.perf_counter() - preprocess_started) * 1000.0)
output_tensor, request_ms = _infer(args.triton_url, profile["model"], tensor)
latency["triton_request_ms"].append(request_ms)
postprocess_started = time.perf_counter()
detections, rejected = _detections(output_tensor, profile, valid_mask)
latency["postprocess_ms"].append(
(time.perf_counter() - postprocess_started) * 1000.0
)
rejection_reasons.update(rejected)
detection_labels.update(str(item["label"]) for item in detections)
tracking_started = time.perf_counter()
tracks = tracker.update(detections, envelope.frame_index)
latency["tracking_ms"].append((time.perf_counter() - tracking_started) * 1000.0)
duplicate_pairs += _duplicate_pairs(tracks)
for track in tracks:
unique_track_ids.add(track.track_id)
track_labels[track.label] += 1
delay_seconds = float(realtime["consumer_delay_ms"]) / 1000.0
if delay_seconds:
time.sleep(delay_seconds)
except Exception:
failures += 1
raise
published = time.perf_counter()
processing_ms = (published - processing_started) * 1000.0
result_age_ms = max(0.0, (published - envelope.scheduled_monotonic) * 1000.0)
latency["processing_ms"].append(processing_ms)
latency["result_age_ms"].append(result_age_ms)
health = _health(result_age_ms, realtime)
health_counts[health] += 1
frame_document = {
"schema_version": FRAME_SCHEMA,
"frame_index": envelope.frame_index,
"sequence": envelope.frame_index + 1,
"source_frame_index": envelope.timeline["source_frame_index"],
"source_sequence": envelope.timeline["source_sequence"],
"session_seconds": round(float(envelope.timeline["session_seconds"]), 9),
"detections": detections,
"tracks": [_track_document(track) for track in tracks],
"delivery": {"health": health, "result_age_ms": round(result_age_ms, 6)},
}
metadata_stream.write(
json.dumps(
frame_document,
ensure_ascii=False,
sort_keys=True,
separators=(",", ":"),
allow_nan=False,
)
+ "\n"
)
queue_state = queue.snapshot()
telemetry_stream.write(
json.dumps(
{
"schema_version": TELEMETRY_SCHEMA,
"frame_index": envelope.frame_index,
"session_seconds": frame_document["session_seconds"],
"health": health,
"result_age_ms": round(result_age_ms, 6),
"processing_ms": round(processing_ms, 6),
"queue_depth_after_take": queue_state["final_depth"],
"queue_dropped_overflow": queue_state["dropped_overflow"],
},
sort_keys=True,
separators=(",", ":"),
)
+ "\n"
)
completed = int(queue_state["consumed"])
if completed % 100 == 0:
metadata_stream.flush()
telemetry_stream.flush()
gpu_stream.flush()
_assert_disk_floor(output, args.free_bytes_floor, completed)
print(
json.dumps(
{
"phase": "realtime-tracking",
"frames_consumed": completed,
"frames_published": queue_state["published"],
"frames_dropped": queue_state["dropped_overflow"],
"maximum_queue_depth": queue_state["maximum_depth"],
},
sort_keys=True,
),
flush=True,
)
producer.join(timeout=5)
if producer.is_alive():
raise RuntimeError("LAB E8 producer did not terminate")
if producer_errors:
raise RuntimeError("LAB E8 producer failed") from producer_errors[0]
metadata_stream.flush()
telemetry_stream.flush()
os.fsync(metadata_stream.fileno())
os.fsync(telemetry_stream.fileno())
finished = time.perf_counter()
queue_state = queue.snapshot()
source_span = (
float(timeline_rows[-1]["session_seconds"]) - float(timeline_rows[0]["session_seconds"])
) / float(realtime["speed"])
wall_seconds = finished - replay_started
effective_fps = int(queue_state["consumed"]) / max(source_span, wall_seconds, 1e-9)
drop_fraction = int(queue_state["dropped_overflow"]) / len(frame_paths)
result_age = _percentiles(latency["result_age_ms"])
acceptance = profile["acceptance"]
expect_overload = bool(acceptance["expect_overload"])
checks = {
"queue_bounded": int(queue_state["maximum_depth"]) <= int(queue_state["capacity"]),
"producer_accounting": int(queue_state["published"]) == len(frame_paths),
"consumer_accounting": (
int(queue_state["consumed"]) + int(queue_state["dropped_overflow"]) == len(frame_paths)
),
"zero_failures": failures == 0,
}
if expect_overload:
checks["overload_drop_observed"] = int(queue_state["dropped_overflow"]) > 0
checks["overload_degraded_or_stale_observed"] = (
health_counts["stale"] + health_counts["unavailable"] > 0
)
else:
checks.update(
{
"minimum_effective_fps": effective_fps
>= float(acceptance["minimum_effective_fps"]),
"maximum_drop_fraction": drop_fraction
<= float(acceptance["maximum_drop_fraction"]),
"maximum_p95_result_age_ms": float(result_age["p95"])
<= float(acceptance["maximum_p95_result_age_ms"]),
}
)
accepted = all(checks.values())
identity = {
"schema_version": IDENTITY_SCHEMA,
"job_id": job["job_id"],
"input_sha256": job["input_sha256"],
"session_id": job["input"]["session_id"],
"source_id": job["input"]["source_id"],
"selection": {
"frame_count": len(frame_paths),
"source_start_frame_index": timeline_rows[0]["source_frame_index"],
"source_end_frame_index": timeline_rows[-1]["source_frame_index"],
"timeline_start_seconds": timeline_rows[0]["session_seconds"],
"timeline_end_seconds": timeline_rows[-1]["session_seconds"],
"timeline_sha256": _sha256(timeline_path),
},
"configuration": {
"pipeline": PIPELINE_ID,
"profile_sha256": profile_sha256,
"profile": profile,
"runner_sha256": _sha256(Path(__file__).resolve(strict=True)),
"orchestrator_sha256": args.orchestrator_sha256,
"container_image": args.container_image,
"valid_fov": valid_fov,
},
"models": {"detector": profile["model"], "files": model_files},
}
identity_sha256 = hashlib.sha256(_canonical_json(identity)).hexdigest()
result_id = f"e8-realtime-tracking-{identity_sha256}"
metrics = {
"frames_expected": len(frame_paths),
"frames_published": queue_state["published"],
"frames_processed": queue_state["consumed"],
"frames_dropped": queue_state["dropped_overflow"],
"frames_failed": failures,
"drop_fraction": round(drop_fraction, 9),
"source_span_seconds": round(source_span, 6),
"replay_wall_seconds": round(wall_seconds, 6),
"effective_frames_per_second": round(effective_fps, 6),
"queue": queue_state,
"latency_ms": {name: _percentiles(values) for name, values in latency.items()},
"health_counts": dict(sorted(health_counts.items())),
"detections": int(sum(detection_labels.values())),
"detections_by_label": dict(sorted(detection_labels.items())),
"detection_rejections": dict(sorted(rejection_reasons.items())),
"unique_confirmed_tracks": len(unique_track_ids),
"track_observations": int(sum(track_labels.values())),
"track_observations_by_label": dict(sorted(track_labels.items())),
"same_class_duplicate_pairs_iou_ge_0_8": duplicate_pairs,
"tracker_tracks_created": tracker.created,
"tracker_tracks_retired": tracker.retired,
"process_peak_rss_mib": round(resource.getrusage(resource.RUSAGE_SELF).ru_maxrss / 1024, 3),
"gpu_telemetry": gpu_telemetry.summary(),
"disk": {
"free_bytes_before_replay": disk_before,
"free_bytes_after_replay": shutil.disk_usage(output).free,
"free_bytes_floor": args.free_bytes_floor,
},
}
report = {
"schema_version": REPORT_SCHEMA,
"result_id": result_id,
"created_at_utc": datetime.now(UTC)
.isoformat(timespec="milliseconds")
.replace("+00:00", "Z"),
"state": "accepted" if accepted else "rejected",
"ground_truth": False,
"identity": identity,
"runtime": {
"hostname": platform.node(),
"platform": platform.platform(),
"python": platform.python_version(),
"numpy": np.__version__,
},
"metrics": metrics,
"acceptance": {
"accepted": accepted,
"checks": checks,
"navigation_or_safety_accepted": False,
},
"limitations": [
"Recorded source-paced replay, not a live K1 transport.",
"Generic COCO detector and IoU-only tracking are not safety validated.",
"No semantic model, LiDAR fusion or navigation actuation is executed in this gate.",
(
"Decoded PNG input is temporary lab transport; camera ingest decode "
"remains a separate gate."
),
],
}
report_path = output / "run-report.json"
_write_json(report_path, report)
artifacts = [
_artifact(metadata_path, "realtime-tracking-frames", "application/x-ndjson", FRAME_SCHEMA),
_artifact(
telemetry_path, "realtime-tracking-telemetry", "application/x-ndjson", TELEMETRY_SCHEMA
),
_artifact(gpu_path, "worker-gpu-telemetry", "application/x-ndjson"),
_artifact(report_path, "realtime-tracking-report", "application/json", REPORT_SCHEMA),
]
result = {
"schema_version": RESULT_SCHEMA,
"result_id": result_id,
"identity_sha256": identity_sha256,
"identity": identity,
"created_at_utc": report["created_at_utc"],
"acceptance_state": report["state"],
"ground_truth": False,
"publication_scope": "recorded-realtime-qualification-only",
"frames_processed": queue_state["consumed"],
"artifacts": artifacts,
}
_write_json(output / "result.json", result)
print(
json.dumps(
{
"result_id": result_id,
"accepted": accepted,
"frames_processed": queue_state["consumed"],
"frames_dropped": queue_state["dropped_overflow"],
"effective_fps": round(effective_fps, 6),
"result_age_p95_ms": result_age["p95"],
},
sort_keys=True,
),
flush=True,
)
return 0 if accepted else 2
def main() -> int:
args = _arguments()
if args.command == "preflight":
return _preflight(args)
return _run(args)
if __name__ == "__main__":
raise SystemExit(main())
@@ -0,0 +1,933 @@
#!/usr/bin/env python3
"""Qualify concurrent 10 Hz tracking and lower-rate semantic perception."""
from __future__ import annotations
import argparse
import hashlib
import importlib.metadata
import json
import math
import os
import platform
import resource
import shutil
import threading
import time
from collections import Counter
from dataclasses import dataclass
from datetime import UTC, datetime
from pathlib import Path
from typing import Any
import numpy as np
from run_e4_full_session_segmentation import (
TARGET_CLASS_COUNT,
_dependency_manifest,
_load_model,
)
from run_e4_full_session_segmentation import (
_profile as _read_semantic_profile,
)
from run_e4_full_session_segmentation import (
_validate_source as _validate_semantic_source,
)
from run_e5_instance_tracking import (
TwoStageTracker,
_detections,
_duplicate_pairs,
_infer,
_load_valid_fov,
_preprocess,
_read_timeline,
_track_document,
_validate_source,
_verify_model,
)
from run_e8_realtime_tracking import (
FrameEnvelope,
LatestWinsQueue,
_wait_until,
)
from run_e8_realtime_tracking import (
_read_profile as _read_detector_profile,
)
from run_recorded_perception_epoch import (
_artifact,
_canonical_json,
_GpuTelemetry,
_percentiles,
_sha256,
_valid_sha256,
_validate_job,
_write_json,
)
PROFILE_SCHEMA = "missioncore.e9-multirate-perception-profile/v1"
DETECTOR_FRAME_SCHEMA = "missioncore.e9-multirate-detector-frame/v1"
SEMANTIC_FRAME_SCHEMA = "missioncore.e9-multirate-semantic-frame/v1"
MERGED_FRAME_SCHEMA = "missioncore.e9-multirate-merged-frame/v1"
REPORT_SCHEMA = "missioncore.e9-multirate-perception-report/v1"
RESULT_SCHEMA = "missioncore.e9-multirate-perception-result/v1"
IDENTITY_SCHEMA = "missioncore.e9-multirate-perception-identity/v1"
PIPELINE_ID = "concurrent-yolox-tracking-eomt-semantic-latest-wins/v1"
def _arguments() -> argparse.Namespace:
parser = argparse.ArgumentParser()
commands = parser.add_subparsers(dest="command", required=True)
for name in ("preflight", "run"):
command = commands.add_parser(name)
command.add_argument("--job", type=Path, required=True)
command.add_argument("--profile", type=Path, required=True)
command.add_argument("--detector-profile", type=Path, required=True)
command.add_argument("--semantic-profile", type=Path, required=True)
command.add_argument("--valid-fov-root", type=Path, required=True)
command.add_argument("--model-root", type=Path, required=True)
command.add_argument("--cache", type=Path, required=True)
command.add_argument("--environment", type=Path, required=True)
if name == "run":
command.add_argument("--frames", type=Path, required=True)
command.add_argument("--timeline", type=Path, required=True)
command.add_argument("--output", type=Path, required=True)
command.add_argument("--triton-url", required=True)
command.add_argument("--free-bytes-floor", type=int, default=0)
command.add_argument("--orchestrator-sha256", required=True)
command.add_argument("--container-image", required=True)
command.add_argument("--telemetry-interval-seconds", type=float, default=1.0)
return parser.parse_args()
def _read_object(path: Path) -> dict[str, Any]:
value = json.loads(path.read_text(encoding="utf-8-sig"))
if not isinstance(value, dict):
raise RuntimeError(f"JSON root is not an object: {path}")
return value
def _read_profile(path: Path) -> tuple[dict[str, Any], str]:
resolved = path.resolve(strict=True)
profile = _read_object(resolved)
replay = profile.get("replay")
acceptance = profile.get("acceptance")
source = profile.get("source")
if (
profile.get("schema_version") != PROFILE_SCHEMA
or profile.get("mode") not in {"pilot", "qualification"}
or not isinstance(replay, dict)
or not isinstance(acceptance, dict)
or not isinstance(source, dict)
or source.get("source_id") != "sensor.camera.right"
or source.get("resolution") != [800, 600]
):
raise RuntimeError("LAB E9 profile contract changed")
speed = replay.get("speed")
detector_capacity = replay.get("detector_queue_capacity")
semantic_capacity = replay.get("semantic_queue_capacity")
semantic_stride = replay.get("semantic_sample_every_frames")
semantic_ttl = replay.get("semantic_ttl_ms")
if (
not _positive_number(speed)
or not 0.1 <= float(speed) <= 10
or not isinstance(detector_capacity, int)
or isinstance(detector_capacity, bool)
or not 1 <= detector_capacity <= 8
or not isinstance(semantic_capacity, int)
or isinstance(semantic_capacity, bool)
or not 1 <= semantic_capacity <= 4
or not isinstance(semantic_stride, int)
or isinstance(semantic_stride, bool)
or not 2 <= semantic_stride <= 30
or not _positive_number(semantic_ttl)
or not 100 <= float(semantic_ttl) <= 5000
):
raise RuntimeError("LAB E9 replay configuration is invalid")
required = (
"detector_minimum_effective_fps",
"detector_maximum_drop_fraction",
"detector_maximum_p95_result_age_ms",
"semantic_minimum_effective_fps",
"semantic_maximum_drop_fraction",
"semantic_maximum_p95_completion_age_ms",
"minimum_fresh_semantic_coverage",
)
if (
any(not _nonnegative_number(acceptance.get(name)) for name in required)
or float(acceptance["detector_maximum_drop_fraction"]) > 1
or float(acceptance["semantic_maximum_drop_fraction"]) > 1
or float(acceptance["minimum_fresh_semantic_coverage"]) > 1
or not isinstance(acceptance.get("require_zero_failures"), bool)
):
raise RuntimeError("LAB E9 acceptance configuration is invalid")
return profile, _sha256(resolved)
def _positive_number(value: object) -> bool:
return _nonnegative_number(value) and float(value) > 0
def _nonnegative_number(value: object) -> bool:
return (
isinstance(value, int | float)
and not isinstance(value, bool)
and math.isfinite(float(value))
and float(value) >= 0
)
@dataclass(frozen=True, slots=True)
class SemanticResult:
frame_index: int
source_frame_index: int
session_seconds: float
completed_monotonic: float
completion_age_ms: float
mask_sha256: str
class_pixels: dict[str, int]
class_fractions: dict[str, float]
class LatestSemantic:
def __init__(self) -> None:
self._lock = threading.Lock()
self._value: SemanticResult | None = None
def publish(self, value: SemanticResult) -> None:
with self._lock:
if self._value is not None and value.frame_index <= self._value.frame_index:
raise RuntimeError("LAB E9 semantic results are not monotonic")
self._value = value
def snapshot(self) -> SemanticResult | None:
with self._lock:
return self._value
def _producer(
*,
detector_queue: LatestWinsQueue,
semantic_queue: LatestWinsQueue,
semantic_stride: int,
frame_paths: list[Path],
timeline_rows: list[dict[str, Any]],
replay_started: float,
speed: float,
error: list[BaseException],
) -> None:
from PIL import Image
first_session = float(timeline_rows[0]["session_seconds"])
try:
for frame_index, (path, row) in enumerate(zip(frame_paths, timeline_rows, strict=True)):
scheduled = replay_started + (float(row["session_seconds"]) - first_session) / speed
_wait_until(scheduled)
decode_started = time.perf_counter()
with Image.open(path) as opened:
image = np.asarray(opened.convert("RGB"), dtype=np.uint8)
decoded = time.perf_counter()
if image.shape != (600, 800, 3):
raise RuntimeError("LAB E9 input resolution changed")
envelope = FrameEnvelope(
frame_index=frame_index,
path=path,
timeline=row,
scheduled_monotonic=scheduled,
decoded_monotonic=decoded,
image=image,
decode_ms=(decoded - decode_started) * 1000.0,
source_release_lag_ms=max(0.0, (decode_started - scheduled) * 1000.0),
)
detector_queue.publish(envelope)
if frame_index % semantic_stride == 0:
semantic_queue.publish(envelope)
except BaseException as exc:
error.append(exc)
finally:
detector_queue.close()
semantic_queue.close()
def _semantic_worker(
*,
queue: LatestWinsQueue,
latest: LatestSemantic,
stream: Any,
valid_mask: np.ndarray,
target_lut: np.ndarray,
target_names: dict[int, str],
infer: Any,
latency: dict[str, list[float]],
failures: list[BaseException],
) -> None:
try:
while (envelope := queue.take()) is not None:
started = time.perf_counter()
latency["image_decode_ms"].append(envelope.decode_ms)
latency["queue_wait_ms"].append(
max(0.0, (started - envelope.decoded_monotonic) * 1000.0)
)
fill_started = time.perf_counter()
model_input = np.where(valid_mask[..., None], envelope.image, 0).astype(np.uint8)
latency["valid_fov_fill_ms"].append((time.perf_counter() - fill_started) * 1000.0)
semantic, measured = infer(model_input)
if semantic.max() >= len(target_lut):
raise RuntimeError("LAB E9 EoMT emitted an unknown category")
target = target_lut[semantic]
target = target.copy()
target[~valid_mask] = 0
for name, value in measured.items():
latency[name].append(float(value))
completed = time.perf_counter()
completion_age_ms = max(0.0, (completed - envelope.scheduled_monotonic) * 1000.0)
latency["completion_age_ms"].append(completion_age_ms)
latency["processing_ms"].append((completed - started) * 1000.0)
counts = np.bincount(target[valid_mask], minlength=TARGET_CLASS_COUNT)
class_pixels = {
target_names[index]: int(counts[index])
for index in range(1, TARGET_CLASS_COUNT)
if int(counts[index]) > 0
}
valid_pixels = int(valid_mask.sum())
result = SemanticResult(
frame_index=envelope.frame_index,
source_frame_index=int(envelope.timeline["source_frame_index"]),
session_seconds=float(envelope.timeline["session_seconds"]),
completed_monotonic=completed,
completion_age_ms=completion_age_ms,
mask_sha256=hashlib.sha256(target.tobytes()).hexdigest(),
class_pixels=class_pixels,
class_fractions={
name: round(count / valid_pixels, 9) for name, count in class_pixels.items()
},
)
latest.publish(result)
stream.write(
json.dumps(
{
"schema_version": SEMANTIC_FRAME_SCHEMA,
"frame_index": result.frame_index,
"source_frame_index": result.source_frame_index,
"session_seconds": round(result.session_seconds, 9),
"completion_age_ms": round(result.completion_age_ms, 6),
"mask_sha256": result.mask_sha256,
"class_pixels": result.class_pixels,
"class_fractions": result.class_fractions,
},
sort_keys=True,
separators=(",", ":"),
allow_nan=False,
)
+ "\n"
)
except BaseException as exc:
failures.append(exc)
def _semantic_binding(
semantic: SemanticResult | None,
*,
frame_session_seconds: float,
ttl_ms: float,
) -> dict[str, Any]:
if semantic is None:
return {
"status": "unavailable",
"source_frame_index": None,
"source_age_ms": None,
"completion_age_ms": None,
"mask_sha256": None,
}
source_age_ms = max(0.0, (frame_session_seconds - semantic.session_seconds) * 1000.0)
return {
"status": "fresh" if source_age_ms <= ttl_ms else "stale",
"source_frame_index": semantic.source_frame_index,
"source_age_ms": round(source_age_ms, 6),
"completion_age_ms": round(semantic.completion_age_ms, 6),
"mask_sha256": semantic.mask_sha256,
}
def _semantic_infer_factory(
processor: Any,
model: Any,
device: Any,
) -> Any:
import torch
from PIL import Image
def infer(image: np.ndarray) -> tuple[np.ndarray, dict[str, float]]:
processor_started = time.perf_counter()
inputs = processor(images=Image.fromarray(image), return_tensors="pt")
processor_ms = (time.perf_counter() - processor_started) * 1000.0
torch.cuda.synchronize()
transfer_started = time.perf_counter()
inputs = {
name: value.to(device) if isinstance(value, torch.Tensor) else value
for name, value in inputs.items()
}
torch.cuda.synchronize()
transfer_ms = (time.perf_counter() - transfer_started) * 1000.0
forward_started = time.perf_counter()
with torch.inference_mode(), torch.amp.autocast("cuda", dtype=torch.float16):
outputs = model(**inputs)
torch.cuda.synchronize()
forward_ms = (time.perf_counter() - forward_started) * 1000.0
post_started = time.perf_counter()
semantic = processor.post_process_semantic_segmentation(
outputs,
target_sizes=[image.shape[:2]],
)[0]
semantic = semantic.detach().cpu().numpy().astype(np.uint8)
post_ms = (time.perf_counter() - post_started) * 1000.0
del inputs, outputs
return semantic, {
"processor_ms": processor_ms,
"host_to_device_ms": transfer_ms,
"forward_ms": forward_ms,
"model_postprocess_ms": post_ms,
}
return infer
def _preflight(args: argparse.Namespace) -> int:
import torch
job = _validate_job(args.job.resolve(strict=True))
profile, profile_sha256 = _read_profile(args.profile)
detector_profile, detector_profile_sha256 = _read_detector_profile(args.detector_profile)
semantic_profile, semantic_profile_sha256 = _read_semantic_profile(args.semantic_profile)
_validate_source(job, detector_profile)
_validate_semantic_source(job, semantic_profile)
if profile["source"] != detector_profile["source"]:
raise RuntimeError("LAB E9 source and detector bindings differ")
if profile["source"] != {
key: semantic_profile["source"][key]
for key in ("source_id", "resolution", "calibration_slot", "calibration_sha256")
}:
raise RuntimeError("LAB E9 source and semantic bindings differ")
valid_mask, valid_fov = _load_valid_fov(args.valid_fov_root, job, detector_profile)
detector_files = _verify_model(detector_profile, args.model_root)
dependency = _dependency_manifest(args.environment.resolve(strict=True))
if dependency["identity"]["profile_sha256"] != semantic_profile_sha256:
raise RuntimeError("LAB E9 semantic dependencies belong to another profile")
if not torch.cuda.is_available():
raise RuntimeError("CUDA is required for LAB E9")
device = torch.device("cuda:0")
processor, model, _labels, _lut, semantic_files = _load_model(
semantic_profile,
args.cache.resolve(strict=True),
device,
)
del processor, model, _labels, _lut
torch.cuda.empty_cache()
print(
json.dumps(
{
"state": "preflight-ready",
"job_id": job["job_id"],
"profile_sha256": profile_sha256,
"detector_profile_sha256": detector_profile_sha256,
"semantic_profile_sha256": semantic_profile_sha256,
"detector_files": detector_files,
"semantic_files": semantic_files,
"valid_fov": valid_fov,
"cuda_device": torch.cuda.get_device_name(),
},
sort_keys=True,
),
flush=True,
)
return 0
def _run(args: argparse.Namespace) -> int:
import torch
import transformers
from PIL import Image
from scipy.optimize import linear_sum_assignment
if not _valid_sha256(args.orchestrator_sha256):
raise RuntimeError("LAB E9 orchestrator SHA-256 is invalid")
job = _validate_job(args.job.resolve(strict=True))
profile, profile_sha256 = _read_profile(args.profile)
detector_profile, detector_profile_sha256 = _read_detector_profile(args.detector_profile)
semantic_profile, semantic_profile_sha256 = _read_semantic_profile(args.semantic_profile)
_validate_source(job, detector_profile)
_validate_semantic_source(job, semantic_profile)
valid_mask, valid_fov = _load_valid_fov(args.valid_fov_root, job, detector_profile)
detector_files = _verify_model(detector_profile, args.model_root)
dependency = _dependency_manifest(args.environment.resolve(strict=True))
if dependency["identity"]["profile_sha256"] != semantic_profile_sha256:
raise RuntimeError("LAB E9 semantic dependency identity changed")
frames_root = args.frames.resolve(strict=True)
frame_paths = sorted(frames_root.glob("frame-*.png"))
if not frame_paths or [path.name for path in frame_paths] != [
f"frame-{index:06d}.png" for index in range(1, len(frame_paths) + 1)
]:
raise RuntimeError("LAB E9 decoded frame sequence changed")
timeline_path = args.timeline.resolve(strict=True)
timeline_rows = _read_timeline(timeline_path, len(frame_paths))
output = args.output.resolve()
if output.exists():
raise RuntimeError("LAB E9 output must be absent")
output.mkdir(mode=0o700, parents=True, exist_ok=False)
_assert_disk_floor(output, args.free_bytes_floor, 0)
if not torch.cuda.is_available():
raise RuntimeError("CUDA is required for LAB E9")
device = torch.device("cuda:0")
processor, semantic_model, semantic_labels, target_lut, semantic_files = _load_model(
semantic_profile,
args.cache.resolve(strict=True),
device,
)
target_names = {
int(key): str(value) for key, value in semantic_profile["target_taxonomy"].items()
}
if set(target_names) != set(range(TARGET_CLASS_COUNT)):
raise RuntimeError("LAB E9 target taxonomy changed")
infer_semantic = _semantic_infer_factory(processor, semantic_model, device)
tracker = TwoStageTracker(detector_profile["tracking"])
linear_sum_assignment(np.zeros((1, 1), dtype=np.float64))
with Image.open(frame_paths[0]) as opened:
warm_image = np.asarray(opened.convert("RGB"), dtype=np.uint8)
detector_tensor = _preprocess(warm_image, valid_mask, detector_profile)
_infer(args.triton_url, detector_profile["model"], detector_tensor)
semantic_input = np.where(valid_mask[..., None], warm_image, 0).astype(np.uint8)
warm_semantic, _warm_latency = infer_semantic(semantic_input)
del detector_tensor, semantic_input, warm_semantic, _warm_latency, warm_image
replay = profile["replay"]
detector_queue = LatestWinsQueue(int(replay["detector_queue_capacity"]))
semantic_queue = LatestWinsQueue(int(replay["semantic_queue_capacity"]))
latest_semantic = LatestSemantic()
producer_errors: list[BaseException] = []
semantic_errors: list[BaseException] = []
detector_failures = 0
detector_latency = {
name: []
for name in (
"image_decode_ms",
"source_release_lag_ms",
"queue_wait_ms",
"preprocess_ms",
"triton_request_ms",
"postprocess_ms",
"tracking_ms",
"processing_ms",
"result_age_ms",
)
}
semantic_latency = {
name: []
for name in (
"image_decode_ms",
"queue_wait_ms",
"valid_fov_fill_ms",
"processor_ms",
"host_to_device_ms",
"forward_ms",
"model_postprocess_ms",
"processing_ms",
"completion_age_ms",
)
}
detector_labels: Counter[str] = Counter()
track_labels: Counter[str] = Counter()
semantic_status: Counter[str] = Counter()
unique_tracks: set[int] = set()
duplicate_pairs = 0
detector_path = output / "detector-frames.jsonl"
semantic_path = output / "semantic-frames.jsonl"
merged_path = output / "merged-frames.jsonl"
gpu_path = output / "gpu-telemetry.jsonl"
disk_before = shutil.disk_usage(output).free
with (
detector_path.open("x", encoding="utf-8", newline="\n") as detector_stream,
semantic_path.open("x", encoding="utf-8", newline="\n") as semantic_stream,
merged_path.open("x", encoding="utf-8", newline="\n") as merged_stream,
gpu_path.open("x", encoding="utf-8", newline="\n") as gpu_stream,
_GpuTelemetry(gpu_stream, args.telemetry_interval_seconds) as gpu_telemetry,
):
semantic_thread = threading.Thread(
target=_semantic_worker,
kwargs={
"queue": semantic_queue,
"latest": latest_semantic,
"stream": semantic_stream,
"valid_mask": valid_mask,
"target_lut": target_lut,
"target_names": target_names,
"infer": infer_semantic,
"latency": semantic_latency,
"failures": semantic_errors,
},
name="lab-e9-semantic-consumer",
daemon=True,
)
semantic_thread.start()
replay_started = time.perf_counter() + 0.25
producer = threading.Thread(
target=_producer,
kwargs={
"detector_queue": detector_queue,
"semantic_queue": semantic_queue,
"semantic_stride": int(replay["semantic_sample_every_frames"]),
"frame_paths": frame_paths,
"timeline_rows": timeline_rows,
"replay_started": replay_started,
"speed": float(replay["speed"]),
"error": producer_errors,
},
name="lab-e9-source-producer",
daemon=True,
)
producer.start()
while (envelope := detector_queue.take()) is not None:
started = time.perf_counter()
detector_latency["image_decode_ms"].append(envelope.decode_ms)
detector_latency["source_release_lag_ms"].append(envelope.source_release_lag_ms)
detector_latency["queue_wait_ms"].append(
max(0.0, (started - envelope.decoded_monotonic) * 1000.0)
)
try:
preprocess_started = time.perf_counter()
tensor = _preprocess(envelope.image, valid_mask, detector_profile)
detector_latency["preprocess_ms"].append(
(time.perf_counter() - preprocess_started) * 1000.0
)
output_tensor, request_ms = _infer(
args.triton_url, detector_profile["model"], tensor
)
detector_latency["triton_request_ms"].append(request_ms)
post_started = time.perf_counter()
detections, _rejected = _detections(output_tensor, detector_profile, valid_mask)
detector_latency["postprocess_ms"].append(
(time.perf_counter() - post_started) * 1000.0
)
tracking_started = time.perf_counter()
tracks = tracker.update(detections, envelope.frame_index)
detector_latency["tracking_ms"].append(
(time.perf_counter() - tracking_started) * 1000.0
)
except Exception:
detector_failures += 1
raise
completed = time.perf_counter()
processing_ms = (completed - started) * 1000.0
result_age_ms = max(0.0, (completed - envelope.scheduled_monotonic) * 1000.0)
detector_latency["processing_ms"].append(processing_ms)
detector_latency["result_age_ms"].append(result_age_ms)
detector_labels.update(str(item["label"]) for item in detections)
duplicate_pairs += _duplicate_pairs(tracks)
for track in tracks:
unique_tracks.add(track.track_id)
track_labels[track.label] += 1
semantic_binding = _semantic_binding(
latest_semantic.snapshot(),
frame_session_seconds=float(envelope.timeline["session_seconds"]),
ttl_ms=float(replay["semantic_ttl_ms"]),
)
semantic_status[str(semantic_binding["status"])] += 1
detector_document = {
"schema_version": DETECTOR_FRAME_SCHEMA,
"frame_index": envelope.frame_index,
"source_frame_index": envelope.timeline["source_frame_index"],
"session_seconds": round(float(envelope.timeline["session_seconds"]), 9),
"result_age_ms": round(result_age_ms, 6),
"detections": detections,
"tracks": [_track_document(track) for track in tracks],
}
detector_stream.write(
json.dumps(
detector_document,
sort_keys=True,
separators=(",", ":"),
allow_nan=False,
)
+ "\n"
)
merged_stream.write(
json.dumps(
{
"schema_version": MERGED_FRAME_SCHEMA,
"frame_index": envelope.frame_index,
"source_frame_index": envelope.timeline["source_frame_index"],
"session_seconds": detector_document["session_seconds"],
"detector_result_age_ms": round(result_age_ms, 6),
"tracks": detector_document["tracks"],
"semantic": semantic_binding,
},
sort_keys=True,
separators=(",", ":"),
allow_nan=False,
)
+ "\n"
)
consumed = int(detector_queue.snapshot()["consumed"])
if consumed % 100 == 0:
detector_stream.flush()
merged_stream.flush()
semantic_stream.flush()
gpu_stream.flush()
_assert_disk_floor(output, args.free_bytes_floor, consumed)
print(
json.dumps(
{
"phase": "multirate",
"detector_consumed": consumed,
"detector_dropped": detector_queue.snapshot()["dropped_overflow"],
"semantic_consumed": semantic_queue.snapshot()["consumed"],
"semantic_dropped": semantic_queue.snapshot()["dropped_overflow"],
},
sort_keys=True,
),
flush=True,
)
producer.join(timeout=5)
if producer.is_alive() or producer_errors:
raise RuntimeError("LAB E9 producer failed")
semantic_thread.join(timeout=30)
if semantic_thread.is_alive():
raise RuntimeError("LAB E9 semantic consumer did not terminate")
if semantic_errors:
raise RuntimeError("LAB E9 semantic consumer failed") from semantic_errors[0]
detector_stream.flush()
semantic_stream.flush()
merged_stream.flush()
os.fsync(detector_stream.fileno())
os.fsync(semantic_stream.fileno())
os.fsync(merged_stream.fileno())
replay_finished = time.perf_counter()
detector_state = detector_queue.snapshot()
semantic_state = semantic_queue.snapshot()
source_span = (
float(timeline_rows[-1]["session_seconds"]) - float(timeline_rows[0]["session_seconds"])
) / float(replay["speed"])
replay_wall = replay_finished - replay_started
scheduled_semantic = ((len(frame_paths) - 1) // int(replay["semantic_sample_every_frames"])) + 1
detector_fps = int(detector_state["consumed"]) / max(source_span, replay_wall, 1e-9)
semantic_fps = int(semantic_state["consumed"]) / max(source_span, replay_wall, 1e-9)
detector_drop_fraction = int(detector_state["dropped_overflow"]) / len(frame_paths)
semantic_drop_fraction = int(semantic_state["dropped_overflow"]) / scheduled_semantic
fresh_coverage = semantic_status["fresh"] / max(1, int(detector_state["consumed"]))
detector_percentiles = {name: _percentiles(values) for name, values in detector_latency.items()}
semantic_percentiles = {name: _percentiles(values) for name, values in semantic_latency.items()}
acceptance = profile["acceptance"]
checks = {
"detector_queue_bounded": int(detector_state["maximum_depth"])
<= int(detector_state["capacity"]),
"detector_accounting": int(detector_state["consumed"])
+ int(detector_state["dropped_overflow"])
== len(frame_paths),
"detector_minimum_effective_fps": detector_fps
>= float(acceptance["detector_minimum_effective_fps"]),
"detector_maximum_drop_fraction": detector_drop_fraction
<= float(acceptance["detector_maximum_drop_fraction"]),
"detector_maximum_p95_result_age_ms": float(detector_percentiles["result_age_ms"]["p95"])
<= float(acceptance["detector_maximum_p95_result_age_ms"]),
"semantic_queue_bounded": int(semantic_state["maximum_depth"])
<= int(semantic_state["capacity"]),
"semantic_accounting": int(semantic_state["consumed"])
+ int(semantic_state["dropped_overflow"])
== scheduled_semantic,
"semantic_minimum_effective_fps": semantic_fps
>= float(acceptance["semantic_minimum_effective_fps"]),
"semantic_maximum_drop_fraction": semantic_drop_fraction
<= float(acceptance["semantic_maximum_drop_fraction"]),
"semantic_maximum_p95_completion_age_ms": float(
semantic_percentiles["completion_age_ms"]["p95"]
)
<= float(acceptance["semantic_maximum_p95_completion_age_ms"]),
"minimum_fresh_semantic_coverage": fresh_coverage
>= float(acceptance["minimum_fresh_semantic_coverage"]),
"zero_failures": detector_failures == 0 and not semantic_errors,
}
accepted = all(checks.values())
identity = {
"schema_version": IDENTITY_SCHEMA,
"job_id": job["job_id"],
"input_sha256": job["input_sha256"],
"session_id": job["input"]["session_id"],
"source_id": job["input"]["source_id"],
"selection": {
"frame_count": len(frame_paths),
"source_start_frame_index": timeline_rows[0]["source_frame_index"],
"source_end_frame_index": timeline_rows[-1]["source_frame_index"],
"timeline_start_seconds": timeline_rows[0]["session_seconds"],
"timeline_end_seconds": timeline_rows[-1]["session_seconds"],
"timeline_sha256": _sha256(timeline_path),
},
"configuration": {
"pipeline": PIPELINE_ID,
"profile": profile,
"profile_sha256": profile_sha256,
"detector_profile_sha256": detector_profile_sha256,
"semantic_profile_sha256": semantic_profile_sha256,
"runner_sha256": _sha256(Path(__file__).resolve(strict=True)),
"orchestrator_sha256": args.orchestrator_sha256,
"container_image": args.container_image,
"valid_fov": valid_fov,
},
"models": {
"detector": detector_profile["model"],
"detector_files": detector_files,
"semantic": semantic_profile["model"],
"semantic_files": semantic_files,
},
}
identity_sha256 = hashlib.sha256(_canonical_json(identity)).hexdigest()
result_id = f"e9-multirate-perception-{identity_sha256}"
metrics = {
"source_span_seconds": round(source_span, 6),
"replay_wall_seconds": round(replay_wall, 6),
"detector": {
"frames_expected": len(frame_paths),
"frames_processed": detector_state["consumed"],
"frames_dropped": detector_state["dropped_overflow"],
"drop_fraction": round(detector_drop_fraction, 9),
"effective_frames_per_second": round(detector_fps, 6),
"queue": detector_state,
"latency_ms": detector_percentiles,
"detections": int(sum(detector_labels.values())),
"unique_confirmed_tracks": len(unique_tracks),
"track_observations": int(sum(track_labels.values())),
"same_class_duplicate_pairs_iou_ge_0_8": duplicate_pairs,
},
"semantic": {
"frames_scheduled": scheduled_semantic,
"frames_processed": semantic_state["consumed"],
"frames_dropped": semantic_state["dropped_overflow"],
"drop_fraction": round(semantic_drop_fraction, 9),
"effective_frames_per_second": round(semantic_fps, 6),
"queue": semantic_state,
"latency_ms": semantic_percentiles,
"binding_status_counts": dict(sorted(semantic_status.items())),
"fresh_coverage": round(fresh_coverage, 9),
},
"gpu_telemetry": gpu_telemetry.summary(),
"process_peak_rss_mib": round(resource.getrusage(resource.RUSAGE_SELF).ru_maxrss / 1024, 3),
"cuda_peak_memory_allocated_mib": round(torch.cuda.max_memory_allocated() / 2**20, 3),
"cuda_peak_memory_reserved_mib": round(torch.cuda.max_memory_reserved() / 2**20, 3),
"disk": {
"free_bytes_before_replay": disk_before,
"free_bytes_after_replay": shutil.disk_usage(output).free,
"free_bytes_floor": args.free_bytes_floor,
},
}
report = {
"schema_version": REPORT_SCHEMA,
"result_id": result_id,
"created_at_utc": datetime.now(UTC)
.isoformat(timespec="milliseconds")
.replace("+00:00", "Z"),
"state": "accepted" if accepted else "rejected",
"ground_truth": False,
"identity": identity,
"runtime": {
"hostname": platform.node(),
"platform": platform.platform(),
"python": platform.python_version(),
"numpy": np.__version__,
"torch": torch.__version__,
"transformers": transformers.__version__,
"scipy": importlib.metadata.version("scipy"),
"gpu": torch.cuda.get_device_name(),
},
"metrics": metrics,
"acceptance": {
"accepted": accepted,
"checks": checks,
"navigation_or_safety_accepted": False,
},
"limitations": [
"Recorded source-paced replay, not live K1 transport.",
(
"Semantic masks are measured in memory; this gate stores hashes and "
"class totals, not mask images."
),
"Generic Cityscapes and COCO models are not forest-domain or safety validated.",
"LiDAR fusion and 3D world-state publication remain downstream gates.",
],
}
report_path = output / "run-report.json"
_write_json(report_path, report)
artifacts = [
_artifact(
detector_path,
"multirate-detector-frames",
"application/x-ndjson",
DETECTOR_FRAME_SCHEMA,
),
_artifact(
semantic_path,
"multirate-semantic-frames",
"application/x-ndjson",
SEMANTIC_FRAME_SCHEMA,
),
_artifact(
merged_path, "multirate-merged-frames", "application/x-ndjson", MERGED_FRAME_SCHEMA
),
_artifact(gpu_path, "worker-gpu-telemetry", "application/x-ndjson"),
_artifact(report_path, "multirate-run-report", "application/json", REPORT_SCHEMA),
]
result = {
"schema_version": RESULT_SCHEMA,
"result_id": result_id,
"identity_sha256": identity_sha256,
"identity": identity,
"created_at_utc": report["created_at_utc"],
"acceptance_state": report["state"],
"ground_truth": False,
"publication_scope": "recorded-multirate-qualification-only",
"frames_processed": detector_state["consumed"],
"artifacts": artifacts,
}
_write_json(output / "result.json", result)
print(
json.dumps(
{
"result_id": result_id,
"accepted": accepted,
"detector_fps": round(detector_fps, 6),
"detector_dropped": detector_state["dropped_overflow"],
"detector_result_age_p95_ms": detector_percentiles["result_age_ms"]["p95"],
"semantic_fps": round(semantic_fps, 6),
"semantic_dropped": semantic_state["dropped_overflow"],
"semantic_completion_age_p95_ms": semantic_percentiles["completion_age_ms"]["p95"],
"fresh_semantic_coverage": round(fresh_coverage, 6),
},
sort_keys=True,
),
flush=True,
)
# A completed rejected qualification is still immutable diagnostic evidence.
# The manifest state, not the process exit code, carries acceptance.
return 0
def _assert_disk_floor(path: Path, floor: int, frame: int) -> None:
if floor < 0:
raise RuntimeError("LAB E9 disk floor is invalid")
free = shutil.disk_usage(path).free
if floor and free < floor:
raise RuntimeError(f"LAB E9 crossed the D-backed free-space floor at frame {frame}")
def main() -> int:
args = _arguments()
if args.command == "preflight":
return _preflight(args)
return _run(args)
if __name__ == "__main__":
raise SystemExit(main())
@@ -0,0 +1,698 @@
#!/usr/bin/env python3
"""Generate review-only E2 prelabels from the exact E0 model generations."""
from __future__ import annotations
import argparse
import hashlib
import json
import os
import platform
import resource
import time
from collections import Counter
from datetime import UTC, datetime
from pathlib import Path, PurePosixPath
from typing import Any
from run_recorded_perception_epoch import (
INSTANCE_MASK_THRESHOLD,
INSTANCE_SCORE_THRESHOLD,
SEMANTIC_MODEL_ID,
SEMANTIC_REVISION,
_canonical_json,
_GpuTelemetry,
_model_files,
_palette,
_percentiles,
_read_object,
_sha256,
_valid_sha256,
_write_json,
_write_png,
)
PACK_SCHEMA = "missioncore.perception-evaluation-pack/v1"
PACK_IDENTITY_SCHEMA = "missioncore.perception-evaluation-pack-identity/v1"
CONTRACT_SCHEMA = "missioncore.perception-annotation-contract/v1"
VALID_FOV_SCHEMA = "missioncore.k1-valid-fov-mask/v1"
RESULT_SCHEMA = "missioncore.perception-evaluation-prelabels/v1"
RESULT_IDENTITY_SCHEMA = "missioncore.perception-evaluation-prelabels-identity/v1"
REPORT_SCHEMA = "missioncore.perception-evaluation-prelabels-report/v1"
FRAME_SCHEMA = "missioncore.perception-evaluation-prelabel-frame/v1"
MAPPING_PROFILE = "e0-coco-ade-to-e2-taxonomy/v1"
PREVIEW_COUNT = 16
TARGET_NAMES = {
0: "outside_valid_fov",
1: "person",
2: "bicycle",
3: "motorcycle",
4: "car",
5: "heavy_vehicle",
6: "building_structure",
7: "paved_road",
8: "sidewalk_curb",
9: "ground_dirt",
10: "grass_low_vegetation",
11: "tree_woody_vegetation",
12: "sky",
13: "static_obstacle",
14: "animal",
15: "other_background",
}
INSTANCE_MAPPING = {
"person": 1,
"bicycle": 2,
"motorcycle": 3,
"car": 4,
"bus": 5,
"truck": 5,
"cat": 14,
"dog": 14,
"horse": 14,
"sheep": 14,
"cow": 14,
"elephant": 14,
"bear": 14,
"zebra": 14,
"giraffe": 14,
"bench": 13,
"fire hydrant": 13,
"stop sign": 13,
"parking meter": 13,
"chair": 13,
"potted plant": 13,
}
SEMANTIC_MAPPING = {
"person": 1,
"bicycle": 2,
"minibike": 3,
"car": 4,
"bus": 5,
"truck": 5,
"van": 5,
"building": 6,
"house": 6,
"skyscraper": 6,
"wall": 6,
"door": 6,
"windowpane": 6,
"hovel": 6,
"awning": 6,
"road": 7,
"runway": 7,
"path": 7,
"sidewalk": 8,
"stairs": 8,
"stairway": 8,
"step": 8,
"earth": 9,
"sand": 9,
"field": 9,
"land": 9,
"dirt track": 9,
"grass": 10,
"plant": 10,
"flower": 10,
"tree": 11,
"palm": 11,
"sky": 12,
"animal": 14,
}
def _arguments() -> argparse.Namespace:
parser = argparse.ArgumentParser()
parser.add_argument("--evaluation-pack", type=Path, required=True)
parser.add_argument("--valid-fov-root", type=Path, required=True)
parser.add_argument("--output", type=Path, required=True)
parser.add_argument("--cache", type=Path, required=True)
parser.add_argument("--telemetry-interval-seconds", type=float, default=1.0)
return parser.parse_args()
def _safe_artifact(root: Path, encoded: object) -> Path:
if not isinstance(encoded, str):
raise RuntimeError("evaluation artifact path is not a string")
relative = PurePosixPath(encoded)
if relative.is_absolute() or ".." in relative.parts or not relative.parts:
raise RuntimeError("evaluation artifact path is unsafe")
path = root.joinpath(*relative.parts).resolve(strict=True)
if not path.is_file() or not path.is_relative_to(root):
raise RuntimeError("evaluation artifact escapes the pack")
return path
def _validate_pack(root: Path) -> tuple[dict[str, Any], list[dict[str, Any]]]:
resolved = root.resolve(strict=True)
manifest = _read_object(resolved / "manifest.json")
identity = manifest.get("identity")
identity_sha256 = manifest.get("identity_sha256")
if (
manifest.get("schema_version") != PACK_SCHEMA
or not isinstance(identity, dict)
or identity.get("schema_version") != PACK_IDENTITY_SCHEMA
or not _valid_sha256(identity_sha256)
or hashlib.sha256(_canonical_json(identity)).hexdigest() != identity_sha256
or manifest.get("generation_id") != f"evaluation-pack-{identity_sha256}"
or identity.get("preprocessing_profile") != "fixed-valid-fov-fill/v1"
):
raise RuntimeError("evaluation pack identity is invalid")
artifacts = manifest.get("artifacts")
if not isinstance(artifacts, list) or not artifacts:
raise RuntimeError("evaluation pack artifacts are unavailable")
seen: set[str] = set()
for artifact in artifacts:
if not isinstance(artifact, dict) or not isinstance(artifact.get("path"), str):
raise RuntimeError("evaluation artifact descriptor is invalid")
encoded = str(artifact["path"])
if encoded in seen:
raise RuntimeError("evaluation artifact descriptor is duplicated")
path = _safe_artifact(resolved, encoded)
if (
artifact.get("byte_length") != path.stat().st_size
or not _valid_sha256(artifact.get("sha256"))
or _sha256(path) != artifact["sha256"]
):
raise RuntimeError(f"evaluation artifact changed: {encoded}")
seen.add(encoded)
contract = _read_object(resolved / "annotation-contract.json")
if (
contract.get("schema_version") != CONTRACT_SCHEMA
or contract.get("evaluation_identity_sha256") != identity_sha256
or [row.get("id") for row in contract.get("categories", [])]
!= list(range(1, 16))
):
raise RuntimeError("evaluation annotation contract is invalid")
frames = identity.get("frames")
if not isinstance(frames, list) or len(frames) != 64:
raise RuntimeError("evaluation frame set is invalid")
for expected_image_id, frame in enumerate(frames, start=1):
if not isinstance(frame, dict):
raise RuntimeError("evaluation frame descriptor is invalid")
image_id = frame.get("image_id")
frame_index = frame.get("frame_index")
if (
image_id != expected_image_id
or not isinstance(frame_index, int)
or isinstance(frame_index, bool)
):
raise RuntimeError("evaluation frame order changed")
name = f"image-{image_id:03d}-frame-{frame_index:06d}.png"
expected_paths = {
f"images/raw/{name}",
f"images/valid-fov-fill/{name}",
}
if not expected_paths <= seen:
raise RuntimeError("evaluation frame artifacts are incomplete")
return manifest, frames
def _load_valid_fov(root: Path, pack: dict[str, Any]) -> Any:
import numpy as np
from PIL import Image
resolved = root.resolve(strict=True)
manifest = _read_object(resolved / "manifest.json")
identity = manifest.get("identity")
identity_sha256 = manifest.get("identity_sha256")
artifact = manifest.get("artifact")
pack_identity = pack["identity"]
if (
manifest.get("schema_version") != VALID_FOV_SCHEMA
or not isinstance(identity, dict)
or not _valid_sha256(identity_sha256)
or hashlib.sha256(_canonical_json(identity)).hexdigest() != identity_sha256
or manifest.get("generation_id") != f"valid-fov-mask-{identity_sha256}"
or manifest.get("generation_id") != pack_identity["valid_fov_generation_id"]
or identity.get("calibration_sha256") != pack_identity["calibration_sha256"]
or identity.get("calibration_slot") != pack_identity["calibration_slot"]
or identity.get("source_id") != pack_identity["source_id"]
or identity.get("admitted_resolution") != [800, 600]
or not isinstance(artifact, dict)
or artifact.get("path") != "mask.png"
or not _valid_sha256(artifact.get("sha256"))
):
raise RuntimeError("valid-FOV binding is invalid")
mask_path = (resolved / "mask.png").resolve(strict=True)
if mask_path.parent != resolved or _sha256(mask_path) != artifact["sha256"]:
raise RuntimeError("valid-FOV artifact changed")
with Image.open(mask_path) as opened:
mask = np.asarray(opened, dtype=np.uint8)
if mask.shape != (600, 800) or not np.isin(mask, (0, 255)).all():
raise RuntimeError("valid-FOV mask pixels are invalid")
return mask > 0
def _resource_snapshot() -> dict[str, float]:
usage = resource.getrusage(resource.RUSAGE_SELF)
result = {
"user_cpu_seconds": float(usage.ru_utime),
"system_cpu_seconds": float(usage.ru_stime),
"minor_page_faults": float(usage.ru_minflt),
"major_page_faults": float(usage.ru_majflt),
"voluntary_context_switches": float(usage.ru_nvcsw),
"involuntary_context_switches": float(usage.ru_nivcsw),
}
try:
for line in Path("/proc/self/io").read_text(encoding="ascii").splitlines():
name, value = line.split(":", 1)
if name in {"read_bytes", "write_bytes", "rchar", "wchar"}:
result[f"proc_io_{name}"] = float(value.strip())
except (OSError, UnicodeDecodeError, ValueError):
pass
return result
def _resource_delta(before: dict[str, float], after: dict[str, float]) -> dict[str, float]:
return {
name: round(value - before[name], 6)
for name, value in after.items()
if name in before
}
def _semantic_target_map(labels: dict[int, str]) -> Any:
import numpy as np
mapping = np.full(256, 15, dtype=np.uint8)
for source_id, name in labels.items():
mapping[source_id] = SEMANTIC_MAPPING.get(name.strip().lower(), 15)
return mapping
def _preview_indices(count: int) -> set[int]:
admitted = min(PREVIEW_COUNT, count)
if admitted == 1:
return {0}
return {
(position * (count - 1) + (admitted - 1) // 2) // (admitted - 1)
for position in range(admitted)
}
def _preview(image: Any, semantic: Any, instance_map: Any, instances: list[dict[str, Any]]) -> Any:
import numpy as np
from PIL import Image, ImageDraw
colors = np.zeros_like(image)
for category_id in range(1, 16):
colors[semantic == category_id] = _palette(category_id)
blended = np.clip(
image.astype(np.float32) * 0.52 + colors.astype(np.float32) * 0.48,
0,
255,
).astype(np.uint8)
canvas = Image.fromarray(blended)
draw = ImageDraw.Draw(canvas)
for instance in instances:
instance_id = int(instance["instance_id"])
color = _palette(500 + instance_id)
x1, y1, x2, y2 = (int(round(value)) for value in instance["box_xyxy"])
draw.rectangle((x1, y1, x2, y2), outline=color, width=2)
label = f"{instance['draft_category']} {float(instance['score']):.0%}"
draw.text((x1, max(0, y1 - 13)), label, fill=color)
if not np.any(instance_map == instance_id):
raise RuntimeError("preview instance lost its mask")
return np.asarray(canvas, dtype=np.uint8)
def _artifact(path: Path, root: Path) -> dict[str, Any]:
return {
"path": path.relative_to(root).as_posix(),
"byte_length": path.stat().st_size,
"sha256": _sha256(path),
}
def _run(args: argparse.Namespace) -> int:
pack_root = args.evaluation_pack.resolve(strict=True)
output_root = args.output.resolve()
cache_root = args.cache.resolve(strict=True)
if output_root.exists():
raise RuntimeError("prelabel output must be absent")
pack, frames = _validate_pack(pack_root)
valid_mask = _load_valid_fov(args.valid_fov_root, pack)
import numpy as np
import torch
import torch.nn.functional as functional
import torchvision
import transformers
from huggingface_hub import snapshot_download
from PIL import Image
from torchvision.models.detection import (
MaskRCNN_ResNet50_FPN_V2_Weights,
maskrcnn_resnet50_fpn_v2,
)
from transformers import AutoImageProcessor, BeitForSemanticSegmentation
if not torch.cuda.is_available():
raise RuntimeError("CUDA is required for E2 prelabels")
output_root.mkdir(mode=0o700, parents=True, exist_ok=False)
instance_root = output_root / "instance-prelabels"
semantic_root = output_root / "semantic-prelabels"
preview_root = output_root / "previews"
instance_root.mkdir(mode=0o700)
semantic_root.mkdir(mode=0o700)
preview_root.mkdir(mode=0o700)
telemetry_path = output_root / "gpu-telemetry.jsonl"
metadata_path = output_root / "frames.jsonl"
device = torch.device("cuda:0")
frame_paths = []
for frame in frames:
name = f"image-{int(frame['image_id']):03d}-frame-{int(frame['frame_index']):06d}.png"
frame_paths.append(pack_root / "images" / "valid-fov-fill" / name)
resource_before = _resource_snapshot()
wall_started = time.perf_counter()
instance_latencies: list[float] = []
semantic_latencies: list[float] = []
instances_by_frame: list[list[dict[str, Any]]] = []
instance_counts: Counter[str] = Counter()
ignored_instance_counts: Counter[str] = Counter()
preview_indices = _preview_indices(len(frames))
torch.cuda.reset_peak_memory_stats()
with telemetry_path.open("x", encoding="utf-8", newline="\n") as telemetry_stream:
with _GpuTelemetry(telemetry_stream, args.telemetry_interval_seconds) as telemetry:
instance_weights = MaskRCNN_ResNet50_FPN_V2_Weights.DEFAULT
instance_model = maskrcnn_resnet50_fpn_v2(weights=instance_weights).to(device).eval()
instance_labels = list(instance_weights.meta["categories"])
with Image.open(frame_paths[0]) as opened:
warm_image = opened.convert("RGB")
with torch.inference_mode():
warm_tensor = instance_weights.transforms()(warm_image).to(device)
_ = instance_model([warm_tensor])[0]
torch.cuda.synchronize()
del warm_tensor
with torch.inference_mode():
for order, path in enumerate(frame_paths, start=1):
with Image.open(path) as opened:
image = np.asarray(opened.convert("RGB"), dtype=np.uint8)
tensor = instance_weights.transforms()(Image.fromarray(image)).to(device)
torch.cuda.synchronize()
started = time.perf_counter()
prediction = instance_model([tensor])[0]
torch.cuda.synchronize()
instance_latencies.append((time.perf_counter() - started) * 1000.0)
scores = prediction["scores"].detach().cpu().numpy()
keep = np.flatnonzero(scores >= INSTANCE_SCORE_THRESHOLD)
index_map = np.zeros(valid_mask.shape, dtype=np.uint16)
instances: list[dict[str, Any]] = []
for output_index in keep:
source_id = int(prediction["labels"][output_index].item())
source_name = instance_labels[source_id].strip().lower()
target_id = INSTANCE_MAPPING.get(source_name)
if target_id is None:
ignored_instance_counts[source_name] += 1
continue
mask = prediction["masks"][output_index, 0].detach().cpu().numpy()
mask = np.logical_and(mask >= INSTANCE_MASK_THRESHOLD, valid_mask)
admitted_mask = np.logical_and(mask, index_map == 0)
mask_pixels = int(np.count_nonzero(admitted_mask))
if mask_pixels < 8:
continue
instance_id = len(instances) + 1
index_map[admitted_mask] = instance_id
box = [
round(float(value), 6)
for value in prediction["boxes"][output_index]
.detach()
.cpu()
.tolist()
]
instance = {
"instance_id": instance_id,
"draft_category_id": target_id,
"draft_category": TARGET_NAMES[target_id],
"source_model_category_id": source_id,
"source_model_category": source_name,
"score": round(float(scores[output_index]), 9),
"box_xyxy": box,
"mask_pixels": mask_pixels,
"review_state": "unreviewed-model-draft",
}
instances.append(instance)
instance_counts[TARGET_NAMES[target_id]] += 1
_write_png(instance_root / f"image-{order:03d}.png", index_map)
instances_by_frame.append(instances)
del tensor, prediction
if order % 16 == 0 or order == len(frames):
print(
json.dumps(
{"phase": "instance", "processed": order, "total": len(frames)},
sort_keys=True,
),
flush=True,
)
checkpoint = Path(instance_weights.url).name
checkpoint_path = Path(torch.hub.get_dir()) / "checkpoints" / checkpoint
del instance_model
torch.cuda.empty_cache()
semantic_snapshot = Path(
snapshot_download(
repo_id=SEMANTIC_MODEL_ID,
revision=SEMANTIC_REVISION,
cache_dir=cache_root / "huggingface",
allow_patterns=("config.json", "preprocessor_config.json", "pytorch_model.bin"),
)
)
processor = AutoImageProcessor.from_pretrained(
semantic_snapshot,
local_files_only=True,
use_fast=False,
)
semantic_model, loading = BeitForSemanticSegmentation.from_pretrained(
semantic_snapshot,
local_files_only=True,
output_loading_info=True,
)
load_problems = {
name: loading.get(name, [])
for name in ("missing_keys", "unexpected_keys", "mismatched_keys", "error_msgs")
if loading.get(name)
}
if load_problems:
raise RuntimeError(
"semantic checkpoint did not load exactly: " + json.dumps(load_problems)
)
semantic_model = semantic_model.to(device).eval()
semantic_labels = {
int(key): str(value) for key, value in semantic_model.config.id2label.items()
}
semantic_mapping = _semantic_target_map(semantic_labels)
with Image.open(frame_paths[0]) as opened:
warm_image = opened.convert("RGB")
warm_inputs = processor(images=warm_image, return_tensors="pt")
warm_inputs = {name: value.to(device) for name, value in warm_inputs.items()}
with torch.inference_mode():
_ = semantic_model(**warm_inputs).logits
torch.cuda.synchronize()
del warm_inputs
target_pixels: Counter[str] = Counter()
with metadata_path.open("x", encoding="utf-8", newline="\n") as metadata_stream:
with torch.inference_mode():
for order, (frame, path, instances) in enumerate(
zip(frames, frame_paths, instances_by_frame, strict=True),
start=1,
):
with Image.open(path) as opened:
image = np.asarray(opened.convert("RGB"), dtype=np.uint8)
inputs = processor(images=Image.fromarray(image), return_tensors="pt")
inputs = {name: value.to(device) for name, value in inputs.items()}
torch.cuda.synchronize()
started = time.perf_counter()
logits = semantic_model(**inputs).logits
resized = functional.interpolate(
logits,
size=image.shape[:2],
mode="bilinear",
align_corners=False,
)
source_semantic = (
resized.argmax(dim=1)[0].detach().cpu().numpy().astype(np.uint8)
)
torch.cuda.synchronize()
semantic_latencies.append((time.perf_counter() - started) * 1000.0)
semantic = semantic_mapping[source_semantic]
semantic = semantic.copy()
semantic[~valid_mask] = 0
instance_map = np.asarray(
Image.open(instance_root / f"image-{order:03d}.png"),
dtype=np.uint16,
)
for instance in instances:
semantic[instance_map == int(instance["instance_id"])] = int(
instance["draft_category_id"]
)
labels, counts = np.unique(semantic[valid_mask], return_counts=True)
for label_id, count in zip(labels, counts, strict=True):
target_pixels[TARGET_NAMES[int(label_id)]] += int(count)
_write_png(semantic_root / f"image-{order:03d}.png", semantic)
if order - 1 in preview_indices:
_write_png(
preview_root / f"image-{order:03d}.png",
_preview(image, semantic, instance_map, instances),
)
metadata_stream.write(
json.dumps(
{
"schema_version": FRAME_SCHEMA,
"image_id": frame["image_id"],
"frame_index": frame["frame_index"],
"session_seconds": frame["session_seconds"],
"role": frame["role"],
"group_id": frame["group_id"],
"instances": instances,
"review_state": "unreviewed-model-draft",
},
ensure_ascii=False,
sort_keys=True,
separators=(",", ":"),
allow_nan=False,
)
+ "\n"
)
del inputs, logits, resized
if order % 16 == 0 or order == len(frames):
print(
json.dumps(
{
"phase": "semantic",
"processed": order,
"total": len(frames),
},
sort_keys=True,
),
flush=True,
)
metadata_stream.flush()
os.fsync(metadata_stream.fileno())
model_files = _model_files(semantic_snapshot, checkpoint_path)
del semantic_model
torch.cuda.empty_cache()
telemetry_summary = telemetry.summary()
wall_seconds = time.perf_counter() - wall_started
resource_after = _resource_snapshot()
identity = {
"schema_version": RESULT_IDENTITY_SCHEMA,
"evaluation_pack_id": pack["generation_id"],
"evaluation_identity_sha256": pack["identity_sha256"],
"valid_fov_generation_id": pack["identity"]["valid_fov_generation_id"],
"pipeline": "maskrcnn-beit-e2-prelabels/v1",
"mapping_profile": MAPPING_PROFILE,
# String keys make the content identity stable across a JSON round trip.
"target_categories": {str(category_id): name for category_id, name in TARGET_NAMES.items()},
"instance_mapping": INSTANCE_MAPPING,
"semantic_mapping": SEMANTIC_MAPPING,
"instance_score_threshold": INSTANCE_SCORE_THRESHOLD,
"instance_mask_threshold": INSTANCE_MASK_THRESHOLD,
"runner_sha256": _sha256(Path(__file__).resolve(strict=True)),
"models": {
"instance": {
"id": "torchvision/maskrcnn_resnet50_fpn_v2",
"weights": str(instance_weights),
},
"semantic": {"id": SEMANTIC_MODEL_ID, "revision": SEMANTIC_REVISION},
"files": model_files,
},
}
identity_sha256 = hashlib.sha256(_canonical_json(identity)).hexdigest()
result_id = f"evaluation-prelabels-{identity_sha256}"
report = {
"schema_version": REPORT_SCHEMA,
"result_id": result_id,
"created_at_utc": datetime.now(UTC)
.isoformat(timespec="milliseconds")
.replace("+00:00", "Z"),
"state": "completed-unreviewed-model-draft",
"identity": identity,
"warning": (
"These outputs are model-assisted prelabels, not ground truth and not an accuracy "
"measurement. Every accepted label requires human review."
),
"metrics": {
"frames": len(frames),
"instances": sum(instance_counts.values()),
"instances_by_target": dict(instance_counts.most_common()),
"ignored_instances_by_source": dict(ignored_instance_counts.most_common()),
"semantic_pixels_by_target_inside_valid_fov": dict(target_pixels.most_common()),
"instance_forward_ms": _percentiles(instance_latencies),
"semantic_forward_ms": _percentiles(semantic_latencies),
"combined_forward_mean_ms": round(
_percentiles(instance_latencies)["mean"]
+ _percentiles(semantic_latencies)["mean"],
6,
),
"wall_seconds": round(wall_seconds, 6),
},
"runtime": {
"hostname": platform.node(),
"platform": platform.platform(),
"python": platform.python_version(),
"torch": torch.__version__,
"torchvision": torchvision.__version__,
"transformers": transformers.__version__,
"cuda_runtime": torch.version.cuda,
"gpu": torch.cuda.get_device_name(),
"gpu_compute_capability": list(torch.cuda.get_device_capability()),
"cuda_peak_memory_allocated_mib": round(
torch.cuda.max_memory_allocated() / 2**20,
3,
),
"cuda_peak_memory_reserved_mib": round(
torch.cuda.max_memory_reserved() / 2**20,
3,
),
"process_peak_rss_mib": round(
resource.getrusage(resource.RUSAGE_SELF).ru_maxrss / 1024,
3,
),
"resource_delta": _resource_delta(resource_before, resource_after),
"gpu_telemetry": telemetry_summary,
},
}
_write_json(output_root / "run-report.json", report)
artifacts = [
_artifact(path, output_root)
for path in sorted(output_root.rglob("*"))
if path.is_file()
]
result = {
"schema_version": RESULT_SCHEMA,
"result_id": result_id,
"identity_sha256": identity_sha256,
"identity": identity,
"review_state": "unreviewed-model-draft",
"artifacts": artifacts,
}
_write_json(output_root / "result.json", result)
print(
json.dumps(
{
"state": "completed-unreviewed-model-draft",
"result_id": result_id,
"frames": len(frames),
"wall_seconds": round(wall_seconds, 6),
},
sort_keys=True,
),
flush=True,
)
return 0
def main() -> int:
return _run(_arguments())
if __name__ == "__main__":
raise SystemExit(main())
@@ -0,0 +1,875 @@
#!/usr/bin/env python3
"""Benchmark E1 valid-FOV preprocessing variants on one sealed frame slice."""
from __future__ import annotations
import argparse
import hashlib
import json
import os
import resource
import time
from collections import Counter
from datetime import UTC, datetime
from pathlib import Path
from typing import Any
from run_recorded_perception_epoch import (
INSTANCE_MASK_THRESHOLD,
INSTANCE_SCORE_THRESHOLD,
SEMANTIC_MODEL_ID,
SEMANTIC_REVISION,
_canonical_json,
_GpuTelemetry,
_instance_overlay,
_model_files,
_percentiles,
_read_object,
_read_timeline,
_semantic_overlay,
_sha256,
_valid_sha256,
_validate_job,
_write_json,
_write_png,
)
QUALIFICATION_SCHEMA = "missioncore.recorded-qualification-slice/v1"
QUALIFICATION_IDENTITY_SCHEMA = "missioncore.recorded-qualification-slice-identity/v1"
VALID_FOV_SCHEMA = "missioncore.k1-valid-fov-mask/v1"
VALID_FOV_IDENTITY_SCHEMA = "missioncore.k1-valid-fov-mask-identity/v1"
REPORT_SCHEMA = "missioncore.perception-preprocessing-qualification-report/v1"
RESULT_SCHEMA = "missioncore.perception-preprocessing-qualification-result/v1"
RESULT_IDENTITY_SCHEMA = "missioncore.perception-preprocessing-qualification-identity/v1"
VARIANTS = ("baseline", "valid-fov-fill", "valid-fov-crop")
PREVIEW_FRAME_COUNT = 12
def _arguments() -> argparse.Namespace:
parser = argparse.ArgumentParser()
parser.add_argument("--job", type=Path, required=True)
parser.add_argument("--frames", type=Path, required=True)
parser.add_argument("--timeline", type=Path, required=True)
parser.add_argument("--qualification", type=Path, required=True)
parser.add_argument("--valid-fov-root", type=Path, required=True)
parser.add_argument("--output", type=Path, required=True)
parser.add_argument("--cache", type=Path, required=True)
parser.add_argument("--calibration-sha256", required=True)
parser.add_argument("--calibration-slot", required=True)
parser.add_argument("--telemetry-interval-seconds", type=float, default=1.0)
return parser.parse_args()
def _load_qualification(path: Path, job: dict[str, Any]) -> tuple[dict[str, Any], list[int]]:
manifest = _read_object(path.resolve(strict=True))
identity = manifest.get("identity")
identity_sha256 = manifest.get("identity_sha256")
input_document = job["input"]
if (
manifest.get("schema_version") != QUALIFICATION_SCHEMA
or not isinstance(identity, dict)
or identity.get("schema_version") != QUALIFICATION_IDENTITY_SCHEMA
or not _valid_sha256(identity_sha256)
or hashlib.sha256(_canonical_json(identity)).hexdigest() != identity_sha256
or manifest.get("generation_id") != f"qualification-slice-{identity_sha256}"
or identity.get("job_id") != job["job_id"]
or identity.get("input_sha256") != job["input_sha256"]
or identity.get("source_id") != input_document["source_id"]
or identity.get("codec_epoch") != input_document["codec_epoch"]
or identity.get("source_frame_count") != input_document["segment_count"]
or identity.get("policy") != "uniform-frame-index-full-epoch/v1"
):
raise RuntimeError("qualification slice identity is invalid")
rows = manifest.get("frames")
selected = identity.get("selected_frames")
if not isinstance(rows, list) or not isinstance(selected, list) or len(rows) != len(selected):
raise RuntimeError("qualification slice frame set is invalid")
indices: list[int] = []
previous = -1
for row, selected_row in zip(rows, selected, strict=True):
if not isinstance(row, dict) or not isinstance(selected_row, dict):
raise RuntimeError("qualification frame descriptor is invalid")
frame_index = row.get("frame_index")
sequence = row.get("sequence")
digest = row.get("segment_sha256")
if (
not isinstance(frame_index, int)
or isinstance(frame_index, bool)
or not previous < frame_index < int(input_document["segment_count"])
or sequence != frame_index + 1
or not _valid_sha256(digest)
or selected_row
!= {
"frame_index": frame_index,
"sequence": sequence,
"segment_sha256": digest,
}
):
raise RuntimeError("qualification frame binding is invalid")
indices.append(frame_index)
previous = frame_index
if not indices:
raise RuntimeError("qualification slice is empty")
return manifest, indices
def _load_valid_fov(
root: Path,
*,
job: dict[str, Any],
calibration_sha256: str,
calibration_slot: str,
) -> tuple[dict[str, Any], Any, tuple[int, int, int, int]]:
import numpy as np
from PIL import Image
resolved = root.resolve(strict=True)
manifest = _read_object(resolved / "manifest.json")
identity = manifest.get("identity")
identity_sha256 = manifest.get("identity_sha256")
artifact = manifest.get("artifact")
geometry = manifest.get("geometry")
if (
manifest.get("schema_version") != VALID_FOV_SCHEMA
or not isinstance(identity, dict)
or identity.get("schema_version") != VALID_FOV_IDENTITY_SCHEMA
or not _valid_sha256(identity_sha256)
or hashlib.sha256(_canonical_json(identity)).hexdigest() != identity_sha256
or manifest.get("generation_id") != f"valid-fov-mask-{identity_sha256}"
or identity.get("calibration_sha256") != calibration_sha256
or identity.get("calibration_slot") != calibration_slot
or identity.get("source_id") != job["input"]["source_id"]
or identity.get("admitted_resolution") != [800, 600]
or not isinstance(artifact, dict)
or artifact.get("path") != "mask.png"
or artifact.get("media_type") != "image/png"
or not _valid_sha256(artifact.get("sha256"))
or not isinstance(geometry, dict)
):
raise RuntimeError("valid-FOV identity is invalid")
mask_path = (resolved / "mask.png").resolve(strict=True)
if mask_path.parent != resolved or _sha256(mask_path) != artifact["sha256"]:
raise RuntimeError("valid-FOV mask artifact changed")
with Image.open(mask_path) as opened:
if opened.mode != "L" or opened.size != (800, 600):
raise RuntimeError("valid-FOV mask format changed")
mask = np.asarray(opened, dtype=np.uint8)
if not np.isin(mask, (0, 255)).all():
raise RuntimeError("valid-FOV mask is not binary")
crop_value = geometry.get("crop_xyxy_exclusive")
if (
not isinstance(crop_value, list)
or len(crop_value) != 4
or not all(isinstance(value, int) and not isinstance(value, bool) for value in crop_value)
):
raise RuntimeError("valid-FOV crop is invalid")
crop = tuple(int(value) for value in crop_value)
left, top, right, bottom = crop
if not 0 <= left < right <= 800 or not 0 <= top < bottom <= 600:
raise RuntimeError("valid-FOV crop escapes the image")
if int(np.count_nonzero(mask)) != geometry.get("valid_pixel_count"):
raise RuntimeError("valid-FOV pixel count changed")
return manifest, mask > 0, crop
def _variant_image(
image: Any,
valid_mask: Any,
crop: tuple[int, int, int, int],
variant: str,
) -> Any:
import numpy as np
if variant == "baseline":
return image
masked = np.where(valid_mask[..., None], image, 0).astype(np.uint8, copy=False)
if variant == "valid-fov-fill":
return masked
if variant == "valid-fov-crop":
left, top, right, bottom = crop
return masked[top:bottom, left:right]
raise RuntimeError(f"unknown preprocessing variant: {variant}")
def _full_mask(
local_mask: Any,
*,
variant: str,
valid_mask: Any,
crop: tuple[int, int, int, int],
) -> Any:
import numpy as np
if variant != "valid-fov-crop":
result = np.asarray(local_mask, dtype=bool)
else:
result = np.zeros(valid_mask.shape, dtype=bool)
left, top, right, bottom = crop
if local_mask.shape != (bottom - top, right - left):
raise RuntimeError("cropped instance mask shape changed")
result[top:bottom, left:right] = local_mask
if variant != "baseline":
result = np.logical_and(result, valid_mask)
return result
def _full_box(
box_xyxy: list[float],
*,
variant: str,
crop: tuple[int, int, int, int],
) -> list[float]:
if variant == "valid-fov-crop":
left, top, _right, _bottom = crop
return [
box_xyxy[0] + left,
box_xyxy[1] + top,
box_xyxy[2] + left,
box_xyxy[3] + top,
]
return box_xyxy
def _full_semantic(
local: Any,
*,
variant: str,
valid_mask: Any,
crop: tuple[int, int, int, int],
) -> Any:
import numpy as np
if variant != "valid-fov-crop":
result = np.asarray(local, dtype=np.uint8)
else:
result = np.full(valid_mask.shape, 255, dtype=np.uint8)
left, top, right, bottom = crop
if local.shape != (bottom - top, right - left):
raise RuntimeError("cropped semantic mask shape changed")
result[top:bottom, left:right] = local
if variant != "baseline":
result = result.copy()
result[~valid_mask] = 255
return result
def _resource_snapshot() -> dict[str, float]:
usage = resource.getrusage(resource.RUSAGE_SELF)
result = {
"user_cpu_seconds": float(usage.ru_utime),
"system_cpu_seconds": float(usage.ru_stime),
"minor_page_faults": float(usage.ru_minflt),
"major_page_faults": float(usage.ru_majflt),
"voluntary_context_switches": float(usage.ru_nvcsw),
"involuntary_context_switches": float(usage.ru_nivcsw),
}
try:
for line in Path("/proc/self/io").read_text(encoding="ascii").splitlines():
name, value = line.split(":", 1)
if name in {"read_bytes", "write_bytes", "rchar", "wchar"}:
result[f"proc_io_{name}"] = float(value.strip())
except (OSError, UnicodeDecodeError, ValueError):
pass
return result
def _resource_delta(before: dict[str, float], after: dict[str, float]) -> dict[str, float]:
return {
name: round(value - before.get(name, value), 6)
for name, value in after.items()
if name in before
}
def _metric_state() -> dict[str, Any]:
return {
"instance_source_decode_ms": [],
"instance_preprocess_ms": [],
"instance_host_to_device_ms": [],
"instance_forward_ms": [],
"instance_postprocess_ms": [],
"semantic_source_decode_ms": [],
"semantic_preprocess_ms": [],
"semantic_host_to_device_ms": [],
"semantic_forward_ms": [],
"semantic_postprocess_ms": [],
"instances": 0,
"instance_scores": [],
"instance_labels": Counter(),
"huge_masks_over_half_valid_fov": 0,
"huge_boxes_over_half_full_frame": 0,
"predicted_mask_pixels": 0,
"predicted_mask_pixels_outside_valid_fov": 0,
"frames_with_outside_valid_fov_instance_pixels": 0,
"semantic_labels": Counter(),
"semantic_disagreement_with_baseline": [],
}
def _latency_document(state: dict[str, Any]) -> dict[str, Any]:
return {
branch: {
name: _percentiles(
[float(value) for value in state[f"{branch}_{name}"]]
)
for name in (
"source_decode_ms",
"preprocess_ms",
"host_to_device_ms",
"forward_ms",
"postprocess_ms",
)
}
for branch in ("instance", "semantic")
}
def _metric_document(state: dict[str, Any], frame_count: int) -> dict[str, Any]:
scores = [float(value) for value in state["instance_scores"]]
outside = int(state["predicted_mask_pixels_outside_valid_fov"])
total = int(state["predicted_mask_pixels"])
disagreements = [float(value) for value in state["semantic_disagreement_with_baseline"]]
return {
"frames": frame_count,
"latency_ms": _latency_document(state),
"instances": int(state["instances"]),
"instances_per_frame": round(int(state["instances"]) / frame_count, 6),
"instance_score": _percentiles(scores),
"instance_labels": dict(state["instance_labels"].most_common()),
"huge_masks_over_half_valid_fov": int(state["huge_masks_over_half_valid_fov"]),
"huge_boxes_over_half_full_frame": int(state["huge_boxes_over_half_full_frame"]),
"predicted_mask_pixels": total,
"predicted_mask_pixels_outside_valid_fov": outside,
"predicted_mask_outside_fraction": round(outside / total, 9) if total else 0.0,
"frames_with_outside_valid_fov_instance_pixels": int(
state["frames_with_outside_valid_fov_instance_pixels"]
),
"semantic_labels_inside_valid_fov": dict(state["semantic_labels"].most_common()),
"semantic_disagreement_with_baseline_inside_valid_fov": _percentiles(disagreements),
}
def _preview_indices(indices: list[int]) -> set[int]:
admitted = min(PREVIEW_FRAME_COUNT, len(indices))
if admitted == 1:
return {indices[len(indices) // 2]}
positions = {
(position * (len(indices) - 1) + (admitted - 1) // 2) // (admitted - 1)
for position in range(admitted)
}
return {indices[position] for position in positions}
def _run(args: argparse.Namespace) -> int:
if not _valid_sha256(args.calibration_sha256):
raise RuntimeError("calibration SHA-256 is invalid")
job_root = args.job.resolve(strict=True)
frames_root = args.frames.resolve(strict=True)
timeline_path = args.timeline.resolve(strict=True)
output_root = args.output.resolve()
cache_root = args.cache.resolve(strict=True)
if output_root.exists() or not frames_root.is_dir():
raise RuntimeError("output must be absent and frames must be a directory")
job = _validate_job(job_root)
input_document = job["input"]
frame_count = int(input_document["segment_count"])
timeline = input_document["timeline"]
timestamps = _read_timeline(
timeline_path,
frame_count,
float(timeline["start_seconds"]),
float(timeline["end_seconds"]),
)
qualification, selected_indices = _load_qualification(args.qualification, job)
valid_fov, valid_mask, crop = _load_valid_fov(
args.valid_fov_root,
job=job,
calibration_sha256=args.calibration_sha256,
calibration_slot=args.calibration_slot,
)
frame_paths = [frames_root / f"frame-{index + 1:06d}.png" for index in selected_indices]
if not all(path.is_file() for path in frame_paths):
raise RuntimeError("qualification decoded frame set is incomplete")
import numpy as np
import torch
import torch.nn.functional as functional
import torchvision
import transformers
from huggingface_hub import snapshot_download
from PIL import Image
from torchvision.models.detection import (
MaskRCNN_ResNet50_FPN_V2_Weights,
maskrcnn_resnet50_fpn_v2,
)
from transformers import AutoImageProcessor, BeitForSemanticSegmentation
if not torch.cuda.is_available():
raise RuntimeError("CUDA is required for preprocessing qualification")
device = torch.device("cuda:0")
output_root.mkdir(mode=0o700, parents=True, exist_ok=False)
previews_root = output_root / "previews"
previews_root.mkdir(mode=0o700)
for variant in VARIANTS:
(previews_root / variant).mkdir(mode=0o700)
telemetry_path = output_root / "gpu-telemetry.jsonl"
metrics = {variant: _metric_state() for variant in VARIANTS}
preview_frame_indices = _preview_indices(selected_indices)
preview_instances: dict[tuple[str, int], tuple[Any, list[dict[str, Any]]]] = {}
valid_pixel_count = int(np.count_nonzero(valid_mask))
total_pixel_count = int(valid_mask.size)
resource_before = _resource_snapshot()
wall_started = time.perf_counter()
with telemetry_path.open("x", encoding="utf-8", newline="\n") as telemetry_stream:
with _GpuTelemetry(telemetry_stream, args.telemetry_interval_seconds) as telemetry:
instance_weights = MaskRCNN_ResNet50_FPN_V2_Weights.DEFAULT
instance_model = maskrcnn_resnet50_fpn_v2(weights=instance_weights).to(device).eval()
instance_labels = list(instance_weights.meta["categories"])
with Image.open(frame_paths[0]) as opened:
warm_image = opened.convert("RGB")
with torch.inference_mode():
warm_tensor = instance_weights.transforms()(warm_image).to(device)
_ = instance_model([warm_tensor])[0]
torch.cuda.synchronize()
del warm_tensor
torch.cuda.reset_peak_memory_stats()
with torch.inference_mode():
for order, (frame_index, path) in enumerate(
zip(selected_indices, frame_paths, strict=True),
start=1,
):
decode_started = time.perf_counter()
with Image.open(path) as opened:
image = np.asarray(opened.convert("RGB"), dtype=np.uint8)
decode_ms = (time.perf_counter() - decode_started) * 1000.0
for variant in VARIANTS:
state = metrics[variant]
state["instance_source_decode_ms"].append(decode_ms)
preprocess_started = time.perf_counter()
variant_image = _variant_image(image, valid_mask, crop, variant)
tensor = instance_weights.transforms()(Image.fromarray(variant_image))
state["instance_preprocess_ms"].append(
(time.perf_counter() - preprocess_started) * 1000.0
)
torch.cuda.synchronize()
transfer_started = time.perf_counter()
tensor = tensor.to(device)
torch.cuda.synchronize()
state["instance_host_to_device_ms"].append(
(time.perf_counter() - transfer_started) * 1000.0
)
torch.cuda.synchronize()
forward_started = time.perf_counter()
prediction = instance_model([tensor])[0]
torch.cuda.synchronize()
state["instance_forward_ms"].append(
(time.perf_counter() - forward_started) * 1000.0
)
post_started = time.perf_counter()
scores = prediction["scores"].detach().cpu().numpy()
keep = np.flatnonzero(scores >= INSTANCE_SCORE_THRESHOLD)
index_map = np.zeros(valid_mask.shape, dtype=np.uint16)
instances: list[dict[str, Any]] = []
frame_outside = 0
for output_index in keep:
local_mask = (
prediction["masks"][output_index, 0].detach().cpu().numpy()
>= INSTANCE_MASK_THRESHOLD
)
full_mask = _full_mask(
local_mask,
variant=variant,
valid_mask=valid_mask,
crop=crop,
)
mask_pixels = int(np.count_nonzero(full_mask))
if mask_pixels < 8:
continue
original_full_mask = _full_mask(
local_mask,
variant="baseline" if variant != "valid-fov-crop" else variant,
valid_mask=np.ones_like(valid_mask),
crop=crop,
)
outside_pixels = int(
np.count_nonzero(np.logical_and(original_full_mask, ~valid_mask))
)
frame_outside += outside_pixels
label_id = int(prediction["labels"][output_index].item())
score = float(scores[output_index])
box_values = (
prediction["boxes"][output_index].detach().cpu().tolist()
)
box = _full_box(
[float(value) for value in box_values],
variant=variant,
crop=crop,
)
instance_id = len(instances) + 1
index_map[np.logical_and(full_mask, index_map == 0)] = instance_id
instances.append(
{
"instance_id": instance_id,
"class_id": label_id,
"label": instance_labels[label_id],
"score": round(score, 9),
"box_xyxy": [round(value, 6) for value in box],
"mask_pixels": mask_pixels,
"outside_valid_fov_pixels": outside_pixels,
}
)
state["instances"] += 1
state["instance_scores"].append(score)
state["instance_labels"][instance_labels[label_id]] += 1
state["predicted_mask_pixels"] += int(
np.count_nonzero(original_full_mask)
)
state["predicted_mask_pixels_outside_valid_fov"] += outside_pixels
if mask_pixels / valid_pixel_count > 0.5:
state["huge_masks_over_half_valid_fov"] += 1
box_area = max(0.0, box[2] - box[0]) * max(0.0, box[3] - box[1])
if box_area / total_pixel_count > 0.5:
state["huge_boxes_over_half_full_frame"] += 1
if frame_outside:
state["frames_with_outside_valid_fov_instance_pixels"] += 1
if frame_index in preview_frame_indices:
preview_instances[(variant, frame_index)] = (index_map, instances)
state["instance_postprocess_ms"].append(
(time.perf_counter() - post_started) * 1000.0
)
del tensor, prediction
if order % 32 == 0 or order == len(selected_indices):
print(
json.dumps(
{
"phase": "instance",
"qualification_frames_processed": order,
"qualification_frames_total": len(selected_indices),
},
sort_keys=True,
),
flush=True,
)
checkpoint = Path(instance_weights.url).name
checkpoint_path = Path(torch.hub.get_dir()) / "checkpoints" / checkpoint
del instance_model
torch.cuda.empty_cache()
semantic_snapshot = Path(
snapshot_download(
repo_id=SEMANTIC_MODEL_ID,
revision=SEMANTIC_REVISION,
cache_dir=cache_root / "huggingface",
allow_patterns=(
"config.json",
"preprocessor_config.json",
"pytorch_model.bin",
),
)
)
processor = AutoImageProcessor.from_pretrained(
semantic_snapshot,
local_files_only=True,
use_fast=False,
)
semantic_model, loading = BeitForSemanticSegmentation.from_pretrained(
semantic_snapshot,
local_files_only=True,
output_loading_info=True,
)
load_problems = {
name: loading.get(name, [])
for name in ("missing_keys", "unexpected_keys", "mismatched_keys", "error_msgs")
if loading.get(name)
}
if load_problems:
raise RuntimeError(
"semantic checkpoint did not load exactly: " + json.dumps(load_problems)
)
semantic_model = semantic_model.to(device).eval()
semantic_labels = {
int(key): str(value) for key, value in semantic_model.config.id2label.items()
}
with Image.open(frame_paths[0]) as opened:
warm_image = opened.convert("RGB")
warm_inputs = processor(images=warm_image, return_tensors="pt")
warm_inputs = {name: value.to(device) for name, value in warm_inputs.items()}
with torch.inference_mode():
_ = semantic_model(**warm_inputs).logits
torch.cuda.synchronize()
del warm_inputs
preview_sequence = {
frame_index: sequence
for sequence, frame_index in enumerate(sorted(preview_frame_indices), start=1)
}
with torch.inference_mode():
for order, (frame_index, path) in enumerate(
zip(selected_indices, frame_paths, strict=True),
start=1,
):
decode_started = time.perf_counter()
with Image.open(path) as opened:
image = np.asarray(opened.convert("RGB"), dtype=np.uint8)
decode_ms = (time.perf_counter() - decode_started) * 1000.0
semantic_by_variant: dict[str, Any] = {}
for variant in VARIANTS:
state = metrics[variant]
state["semantic_source_decode_ms"].append(decode_ms)
preprocess_started = time.perf_counter()
variant_image = _variant_image(image, valid_mask, crop, variant)
inputs = processor(
images=Image.fromarray(variant_image),
return_tensors="pt",
)
state["semantic_preprocess_ms"].append(
(time.perf_counter() - preprocess_started) * 1000.0
)
torch.cuda.synchronize()
transfer_started = time.perf_counter()
inputs = {name: value.to(device) for name, value in inputs.items()}
torch.cuda.synchronize()
state["semantic_host_to_device_ms"].append(
(time.perf_counter() - transfer_started) * 1000.0
)
torch.cuda.synchronize()
forward_started = time.perf_counter()
logits = semantic_model(**inputs).logits
resized = functional.interpolate(
logits,
size=variant_image.shape[:2],
mode="bilinear",
align_corners=False,
)
local_semantic = (
resized.argmax(dim=1)[0].detach().cpu().numpy().astype(np.uint8)
)
torch.cuda.synchronize()
state["semantic_forward_ms"].append(
(time.perf_counter() - forward_started) * 1000.0
)
post_started = time.perf_counter()
semantic = _full_semantic(
local_semantic,
variant=variant,
valid_mask=valid_mask,
crop=crop,
)
semantic_by_variant[variant] = semantic
labels, counts = np.unique(semantic[valid_mask], return_counts=True)
for label_id, count in zip(labels, counts, strict=True):
state["semantic_labels"][
semantic_labels.get(int(label_id), f"class-{int(label_id)}")
] += int(count)
if frame_index in preview_frame_indices:
display_image = _variant_image(image, valid_mask, crop, variant)
if variant == "valid-fov-crop":
full_display = np.zeros_like(image)
left, top, right, bottom = crop
full_display[top:bottom, left:right] = display_image
display_image = full_display
display_semantic = semantic.copy()
display_semantic[display_semantic == 255] = 0
semantic_overlay, _classes = _semantic_overlay(
display_image,
display_semantic,
semantic_labels,
)
instance_map, instances = preview_instances[(variant, frame_index)]
overlay = _instance_overlay(
semantic_overlay,
instance_map,
instances,
)
sequence = preview_sequence[frame_index]
_write_png(
previews_root / variant / f"frame-{sequence:03d}.png",
overlay,
)
state["semantic_postprocess_ms"].append(
(time.perf_counter() - post_started) * 1000.0
)
del inputs, logits, resized
baseline_semantic = semantic_by_variant["baseline"]
for variant in VARIANTS:
selected_semantic = semantic_by_variant[variant][valid_mask]
disagreement = float(
np.mean(selected_semantic != baseline_semantic[valid_mask])
)
metrics[variant]["semantic_disagreement_with_baseline"].append(
disagreement
)
if order % 32 == 0 or order == len(selected_indices):
print(
json.dumps(
{
"phase": "semantic",
"qualification_frames_processed": order,
"qualification_frames_total": len(selected_indices),
},
sort_keys=True,
),
flush=True,
)
del semantic_model
torch.cuda.empty_cache()
wall_seconds = time.perf_counter() - wall_started
resource_after = _resource_snapshot()
model_files = _model_files(semantic_snapshot, checkpoint_path)
metric_documents = {
variant: _metric_document(metrics[variant], len(selected_indices))
for variant in VARIANTS
}
identity = {
"schema_version": RESULT_IDENTITY_SCHEMA,
"job_id": job["job_id"],
"input_sha256": job["input_sha256"],
"qualification_generation_id": qualification["generation_id"],
"qualification_identity_sha256": qualification["identity_sha256"],
"valid_fov_generation_id": valid_fov["generation_id"],
"valid_fov_identity_sha256": valid_fov["identity_sha256"],
"calibration_sha256": args.calibration_sha256,
"calibration_slot": args.calibration_slot,
"configuration": {
"pipeline": "recorded-preprocessing-ab-mask-crop/v1",
"variants": list(VARIANTS),
"precision": "fp32",
"batch_size": 1,
"execution": "same-model-load-interleaved-variants-per-frame",
"instance_score_threshold": INSTANCE_SCORE_THRESHOLD,
"instance_mask_threshold": INSTANCE_MASK_THRESHOLD,
"runner_sha256": _sha256(Path(__file__).resolve(strict=True)),
"preview_frame_count": len(preview_frame_indices),
},
"models": {
"instance": {
"id": "torchvision/maskrcnn_resnet50_fpn_v2",
"weights": str(instance_weights),
},
"semantic": {
"id": SEMANTIC_MODEL_ID,
"revision": SEMANTIC_REVISION,
"checkpoint_load": "exact-no-missing-unexpected-or-mismatched-keys",
},
"files": model_files,
},
}
identity_sha256 = hashlib.sha256(_canonical_json(identity)).hexdigest()
result_id = f"qualification-result-{identity_sha256}"
report = {
"schema_version": REPORT_SCHEMA,
"result_id": result_id,
"created_at_utc": datetime.now(UTC)
.isoformat(timespec="milliseconds")
.replace("+00:00", "Z"),
"state": "completed",
"identity": identity,
"input": {
"job_id": job["job_id"],
"input_sha256": job["input_sha256"],
"session_id": input_document["session_id"],
"source_id": input_document["source_id"],
"codec_epoch": input_document["codec_epoch"],
"source_frame_count": frame_count,
"qualification_frame_count": len(selected_indices),
"selected_frame_indices": selected_indices,
"selected_session_seconds": [timestamps[index] for index in selected_indices],
},
"valid_fov": {
"generation_id": valid_fov["generation_id"],
"calibration_sha256": args.calibration_sha256,
"calibration_slot": args.calibration_slot,
"geometry": valid_fov["geometry"],
},
"metrics": metric_documents,
"runtime": {
"wall_seconds": round(wall_seconds, 6),
"variant_model_evaluations": len(selected_indices) * len(VARIANTS) * 2,
"gpu": torch.cuda.get_device_name(),
"torch": torch.__version__,
"torchvision": torchvision.__version__,
"transformers": transformers.__version__,
"cuda_runtime": torch.version.cuda,
"cuda_peak_memory_allocated_mib": round(
torch.cuda.max_memory_allocated() / 2**20,
3,
),
"cuda_peak_memory_reserved_mib": round(
torch.cuda.max_memory_reserved() / 2**20,
3,
),
"process_peak_rss_mib": round(
resource.getrusage(resource.RUSAGE_SELF).ru_maxrss / 1024,
3,
),
"resource_delta": _resource_delta(resource_before, resource_after),
"system_load_average": [round(value, 6) for value in os.getloadavg()],
"gpu_telemetry": telemetry.summary(),
},
"quality_status": {
"ground_truth": "absent",
"decision_scope": "preprocessing proxy comparison only",
"not_accepted": [
"2D mIoU/AP",
"3D geometry",
"distance accuracy",
"tracking",
"safety",
],
},
}
_write_json(output_root / "run-report.json", report)
preview_artifacts = []
for path in sorted(previews_root.glob("*/*.png")):
preview_artifacts.append(
{
"path": path.relative_to(output_root).as_posix(),
"byte_length": path.stat().st_size,
"sha256": _sha256(path),
}
)
result = {
"schema_version": RESULT_SCHEMA,
"result_id": result_id,
"identity_sha256": identity_sha256,
"identity": identity,
"artifacts": {
"run_report": {
"path": "run-report.json",
"byte_length": (output_root / "run-report.json").stat().st_size,
"sha256": _sha256(output_root / "run-report.json"),
},
"gpu_telemetry": {
"path": "gpu-telemetry.jsonl",
"byte_length": telemetry_path.stat().st_size,
"sha256": _sha256(telemetry_path),
},
"previews": preview_artifacts,
},
}
_write_json(output_root / "result.json", result)
print(
json.dumps(
{
"state": "completed",
"result_id": result_id,
"qualification_frames": len(selected_indices),
"wall_seconds": round(wall_seconds, 6),
},
sort_keys=True,
),
flush=True,
)
return 0
def main() -> int:
return _run(_arguments())
if __name__ == "__main__":
raise SystemExit(main())
@@ -0,0 +1,824 @@
#!/usr/bin/env python3
"""Run and seal a complete recorded panoptic-perception camera epoch."""
from __future__ import annotations
import argparse
import hashlib
import importlib.metadata
import json
import os
import platform
import resource
import statistics
import subprocess
import threading
import time
from datetime import UTC, datetime
from pathlib import Path, PurePosixPath
from typing import Any, TextIO
INSTANCE_SCORE_THRESHOLD = 0.5
INSTANCE_MASK_THRESHOLD = 0.5
SEMANTIC_ALPHA = 0.46
INSTANCE_ALPHA = 0.58
SEMANTIC_MODEL_ID = "microsoft/beit-base-finetuned-ade-640-640"
SEMANTIC_REVISION = "a8b6f5ef4acb2ea55d882989deaa02d39401e2b2"
RESULT_SCHEMA = "missioncore.recorded-perception-result/v2"
REPORT_SCHEMA = "missioncore.perception-run-report/v1"
FRAME_SCHEMA = "missioncore.panoptic-frame/v1"
SAFE_SHA256 = set("0123456789abcdef")
def _arguments() -> argparse.Namespace:
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers(dest="command", required=True)
preflight = subparsers.add_parser("preflight")
preflight.add_argument("--job", type=Path, required=True)
preflight.add_argument("--cache", type=Path, required=True)
run = subparsers.add_parser("run")
run.add_argument("--job", type=Path, required=True)
run.add_argument("--frames", type=Path, required=True)
run.add_argument("--timeline", type=Path, required=True)
run.add_argument("--output", type=Path, required=True)
run.add_argument("--cache", type=Path, required=True)
run.add_argument("--calibration-sha256", required=True)
run.add_argument("--calibration-slot", required=True)
run.add_argument("--telemetry-interval-seconds", type=float, default=1.0)
finalize = subparsers.add_parser("finalize")
finalize.add_argument("--output", type=Path, required=True)
finalize.add_argument("--video", type=Path, required=True)
finalize.add_argument("--masks", type=Path, required=True)
finalize.add_argument("--extract-seconds", type=float, required=True)
finalize.add_argument("--encode-seconds", type=float, required=True)
finalize.add_argument("--wall-seconds", type=float, required=True)
finalize.add_argument("--encoder", required=True)
return parser.parse_args()
def _sha256(path: Path) -> str:
digest = hashlib.sha256()
with path.open("rb") as stream:
for chunk in iter(lambda: stream.read(1024 * 1024), b""):
digest.update(chunk)
return digest.hexdigest()
def _canonical_json(value: object) -> bytes:
return json.dumps(
value,
ensure_ascii=False,
sort_keys=True,
separators=(",", ":"),
allow_nan=False,
).encode("utf-8")
def _read_object(path: Path) -> dict[str, Any]:
value = json.loads(path.read_text(encoding="utf-8-sig"))
if not isinstance(value, dict):
raise RuntimeError(f"{path.name} is not a JSON object")
return value
def _write_json(path: Path, value: object) -> None:
temporary = path.with_name(f".{path.name}.{os.getpid()}.tmp")
with temporary.open("x", encoding="utf-8", newline="\n") as stream:
json.dump(value, stream, ensure_ascii=False, sort_keys=True, indent=2, allow_nan=False)
stream.write("\n")
stream.flush()
os.fsync(stream.fileno())
os.replace(temporary, path)
def _valid_sha256(value: object) -> bool:
return isinstance(value, str) and len(value) == 64 and set(value) <= SAFE_SHA256
def _safe_job_path(root: Path, encoded: object) -> Path:
if not isinstance(encoded, str):
raise RuntimeError("job artifact path is not a string")
relative = PurePosixPath(encoded)
if relative.is_absolute() or ".." in relative.parts or not relative.parts:
raise RuntimeError("job artifact path is unsafe")
path = root.joinpath(*relative.parts).resolve(strict=True)
if not path.is_file() or not path.is_relative_to(root):
raise RuntimeError("job artifact escapes the job root")
return path
def _validate_job(job_root: Path) -> dict[str, Any]:
root = job_root.resolve(strict=True)
job = _read_object(root / "job.json")
input_document = job.get("input")
if (
job.get("schema_version") != "missioncore.compute-job/v1"
or not isinstance(input_document, dict)
or hashlib.sha256(_canonical_json(input_document)).hexdigest() != job.get("input_sha256")
or job.get("job_id") != f"recorded-camera-{str(job.get('input_sha256'))[:24]}"
):
raise RuntimeError("compute job identity is invalid")
files = input_document.get("files")
if not isinstance(files, list) or not files:
raise RuntimeError("compute job has no files")
seen: set[str] = set()
total_bytes = 0
for artifact in files:
if not isinstance(artifact, dict):
raise RuntimeError("compute job artifact descriptor is invalid")
encoded = artifact.get("path")
if not isinstance(encoded, str) or encoded in seen:
raise RuntimeError("compute job artifact descriptor is duplicated")
seen.add(encoded)
path = _safe_job_path(root, encoded)
byte_length = artifact.get("byte_length")
digest = artifact.get("sha256")
if (
not isinstance(byte_length, int)
or byte_length < 1
or path.stat().st_size != byte_length
or not _valid_sha256(digest)
or _sha256(path) != digest
):
raise RuntimeError(f"compute job artifact changed: {encoded}")
total_bytes += byte_length
if total_bytes != input_document.get("byte_length"):
raise RuntimeError("compute job byte length changed")
return job
def _read_timeline(path: Path, expected_count: int, start: float, end: float) -> list[float]:
timestamps: list[float] = []
with path.open("r", encoding="utf-8") as stream:
for expected_index, line in enumerate(stream):
value = json.loads(line)
if not isinstance(value, dict) or value.get("frame_index") != expected_index:
raise RuntimeError("decoded frame timeline index changed")
session_seconds = value.get("session_seconds")
if not isinstance(session_seconds, (int, float)):
raise RuntimeError("decoded frame timestamp is invalid")
timestamp = float(session_seconds)
if timestamps and timestamp <= timestamps[-1]:
raise RuntimeError("decoded frame timestamps are not increasing")
timestamps.append(timestamp)
if len(timestamps) != expected_count:
raise RuntimeError("decoded frame count differs from the camera job")
if timestamps[0] < start - 0.001 or timestamps[-1] > end + 0.001:
raise RuntimeError("decoded frame timeline escapes the camera epoch")
return timestamps
def _palette(index: int) -> tuple[int, int, int]:
digest = hashlib.sha256(f"mission-core-segment-{index}".encode()).digest()
return (64 + digest[0] % 176, 64 + digest[1] % 176, 64 + digest[2] % 176)
def _blend(image: Any, colors: Any, alpha: float) -> Any:
import numpy as np
return np.clip(
image.astype(np.float32) * (1.0 - alpha) + colors.astype(np.float32) * alpha,
0,
255,
).astype(np.uint8)
def _semantic_overlay(
image: Any,
index_map: Any,
labels: dict[int, str],
) -> tuple[Any, list[dict[str, Any]]]:
import numpy as np
colors = np.zeros_like(image)
counts = np.bincount(index_map.reshape(-1), minlength=max(labels) + 1)
present = np.flatnonzero(counts)
for index in present:
colors[index_map == index] = _palette(int(index))
total = int(index_map.size)
classes = [
{
"id": int(index),
"label": labels.get(int(index), f"class-{int(index)}"),
"pixels": int(counts[index]),
"fraction": round(float(counts[index]) / total, 9),
}
for index in sorted(present, key=lambda value: int(counts[value]), reverse=True)
]
return _blend(image, colors, SEMANTIC_ALPHA), classes
def _instance_overlay(image: Any, index_map: Any, instances: list[dict[str, Any]]) -> Any:
import numpy as np
from PIL import Image, ImageDraw
result = image.copy()
for item in instances:
instance_id = int(item["instance_id"])
mask = index_map == instance_id
color = np.asarray(_palette(500 + instance_id), dtype=np.uint8)
if bool(mask.any()):
result[mask] = _blend(
result[mask],
np.broadcast_to(color, result[mask].shape),
INSTANCE_ALPHA,
)
canvas = Image.fromarray(result)
draw = ImageDraw.Draw(canvas)
for item in instances:
color = _palette(500 + int(item["instance_id"]))
x1, y1, x2, y2 = (int(round(value)) for value in item["box_xyxy"])
draw.rectangle((x1, y1, x2, y2), outline=color, width=2)
label = f"{item['label']} {float(item['score']):.0%}"
text_box = draw.textbbox((x1, max(0, y1 - 13)), label)
draw.rectangle(text_box, fill=(7, 8, 10))
draw.text((x1, max(0, y1 - 13)), label, fill=color)
return np.asarray(canvas, dtype=np.uint8)
def _write_png(path: Path, array: Any) -> None:
from PIL import Image
Image.fromarray(array).save(path, format="PNG", optimize=False)
def _percentiles(values: list[float]) -> dict[str, float]:
if not values:
return {"mean": 0.0, "p50": 0.0, "p95": 0.0, "max": 0.0}
ordered = sorted(values)
def percentile(fraction: float) -> float:
index = min(len(ordered) - 1, max(0, round((len(ordered) - 1) * fraction)))
return round(ordered[index], 6)
return {
"mean": round(statistics.fmean(values), 6),
"p50": percentile(0.5),
"p95": percentile(0.95),
"max": round(max(values), 6),
}
class _GpuTelemetry:
def __init__(self, stream: TextIO, interval_seconds: float) -> None:
if not 0.25 <= interval_seconds <= 60:
raise RuntimeError("telemetry interval is outside bounds")
self._stream = stream
self._interval = interval_seconds
self._stop = threading.Event()
self._thread = threading.Thread(target=self._run, name="gpu-telemetry", daemon=True)
self.samples: list[dict[str, float]] = []
def __enter__(self) -> _GpuTelemetry:
self._thread.start()
return self
def __exit__(self, *_: object) -> None:
self._stop.set()
self._thread.join(timeout=self._interval + 5)
def _run(self) -> None:
query = (
"timestamp,utilization.gpu,utilization.memory,memory.used,memory.total,"
"temperature.gpu,power.draw"
)
while not self._stop.is_set():
before = time.time()
try:
completed = subprocess.run(
[
"nvidia-smi",
f"--query-gpu={query}",
"--format=csv,noheader,nounits",
],
capture_output=True,
check=True,
text=True,
timeout=5,
)
values = [item.strip() for item in completed.stdout.splitlines()[0].split(",")]
sample = {
"epoch_seconds": round(before, 6),
"gpu_utilization_percent": float(values[1]),
"gpu_memory_utilization_percent": float(values[2]),
"gpu_memory_used_mib": float(values[3]),
"gpu_memory_total_mib": float(values[4]),
"gpu_temperature_c": float(values[5]),
"gpu_power_w": float(values[6]),
}
self.samples.append(sample)
self._stream.write(json.dumps(sample, sort_keys=True) + "\n")
self._stream.flush()
except (OSError, subprocess.SubprocessError, ValueError, IndexError):
pass
self._stop.wait(max(0.0, self._interval - (time.time() - before)))
def summary(self) -> dict[str, object]:
fields = (
"gpu_utilization_percent",
"gpu_memory_utilization_percent",
"gpu_memory_used_mib",
"gpu_temperature_c",
"gpu_power_w",
)
return {
"sample_count": len(self.samples),
"interval_seconds": self._interval,
**{
field: _percentiles([float(sample[field]) for sample in self.samples])
for field in fields
},
}
def _model_files(semantic_snapshot: Path, checkpoint_path: Path) -> list[dict[str, object]]:
files = [
{"name": f"beit/{path.name}", "bytes": path.stat().st_size, "sha256": _sha256(path)}
for path in sorted(semantic_snapshot.iterdir())
if path.is_file()
]
files.append(
{
"name": f"torchvision/{checkpoint_path.name}",
"bytes": checkpoint_path.stat().st_size,
"sha256": _sha256(checkpoint_path),
}
)
return files
def _preflight(args: argparse.Namespace) -> int:
job = _validate_job(args.job.resolve(strict=True))
cache_root = args.cache.resolve(strict=True)
import torch
import torchvision # noqa: F401
import transformers # noqa: F401
from huggingface_hub import snapshot_download
from torchvision.models.detection import MaskRCNN_ResNet50_FPN_V2_Weights
if not torch.cuda.is_available() or torch.cuda.device_count() < 1:
raise RuntimeError("CUDA device 0 is unavailable")
cuda_probe = torch.zeros(1, device="cuda:0")
torch.cuda.synchronize()
del cuda_probe
checkpoint = Path(MaskRCNN_ResNet50_FPN_V2_Weights.DEFAULT.url).name
checkpoint_path = Path(torch.hub.get_dir()) / "checkpoints" / checkpoint
if not checkpoint_path.is_file() or checkpoint_path.stat().st_size < 1:
raise RuntimeError("cached instance checkpoint is unavailable")
semantic_snapshot = Path(
snapshot_download(
repo_id=SEMANTIC_MODEL_ID,
revision=SEMANTIC_REVISION,
cache_dir=cache_root / "huggingface",
allow_patterns=("config.json", "preprocessor_config.json", "pytorch_model.bin"),
)
)
required = ("config.json", "preprocessor_config.json", "pytorch_model.bin")
if any(not (semantic_snapshot / name).is_file() for name in required):
raise RuntimeError("cached semantic checkpoint is incomplete")
print(
json.dumps(
{
"state": "preflight-ready",
"job_id": job["job_id"],
"cuda_device": torch.cuda.get_device_name(),
},
sort_keys=True,
),
flush=True,
)
return 0
def _run(args: argparse.Namespace) -> int:
if not _valid_sha256(args.calibration_sha256):
raise RuntimeError("calibration SHA-256 is invalid")
job_root = args.job.resolve(strict=True)
frames_root = args.frames.resolve(strict=True)
timeline_path = args.timeline.resolve(strict=True)
output_root = args.output.resolve()
cache_root = args.cache.resolve()
if output_root.exists() or not frames_root.is_dir():
raise RuntimeError("output must be absent and frames must be a directory")
job = _validate_job(job_root)
input_document = job["input"]
timeline = input_document["timeline"]
segment_count = int(input_document["segment_count"])
frame_paths = [frames_root / f"frame-{index:06d}.png" for index in range(1, segment_count + 1)]
if not all(path.is_file() for path in frame_paths):
raise RuntimeError("decoded frame set is incomplete")
if len(list(frames_root.glob("frame-*.png"))) != segment_count:
raise RuntimeError("decoded frame set contains unexpected files")
timestamps = _read_timeline(
timeline_path,
segment_count,
float(timeline["start_seconds"]),
float(timeline["end_seconds"]),
)
import numpy as np
import torch
import torch.nn.functional as functional
import torchvision
import transformers
from huggingface_hub import snapshot_download
from PIL import Image
from torchvision.models.detection import (
MaskRCNN_ResNet50_FPN_V2_Weights,
maskrcnn_resnet50_fpn_v2,
)
from transformers import AutoImageProcessor, BeitForSemanticSegmentation
if not torch.cuda.is_available():
raise RuntimeError("CUDA is required for a perception epoch run")
cuda_index = 0
device = torch.device(f"cuda:{cuda_index}")
cache_root.mkdir(mode=0o700, parents=True, exist_ok=True)
output_root.mkdir(mode=0o700, parents=True, exist_ok=False)
instance_root = output_root / "instance-masks"
semantic_root = output_root / "semantic-masks"
overlay_root = output_root / "overlay-frames"
instance_root.mkdir(mode=0o700)
semantic_root.mkdir(mode=0o700)
overlay_root.mkdir(mode=0o700)
telemetry_path = output_root / "gpu-telemetry.jsonl"
started = time.perf_counter()
instance_latencies: list[float] = []
semantic_latencies: list[float] = []
instances_by_frame: list[list[dict[str, Any]]] = []
total_instances = 0
with telemetry_path.open("x", encoding="utf-8", newline="\n") as telemetry_stream:
with _GpuTelemetry(telemetry_stream, args.telemetry_interval_seconds) as telemetry:
instance_weights = MaskRCNN_ResNet50_FPN_V2_Weights.DEFAULT
instance_model = maskrcnn_resnet50_fpn_v2(weights=instance_weights).to(device).eval()
instance_labels = list(instance_weights.meta["categories"])
with torch.inference_mode():
for frame_index, path in enumerate(frame_paths):
with Image.open(path) as opened:
image = np.asarray(opened.convert("RGB"), dtype=np.uint8)
tensor = instance_weights.transforms()(Image.fromarray(image)).to(device)
torch.cuda.synchronize()
before = time.perf_counter()
prediction = instance_model([tensor])[0]
torch.cuda.synchronize()
instance_latencies.append((time.perf_counter() - before) * 1000.0)
scores = prediction["scores"].detach().cpu().numpy()
keep = np.flatnonzero(scores >= INSTANCE_SCORE_THRESHOLD)
index_map = np.zeros(image.shape[:2], dtype=np.uint16)
instances: list[dict[str, Any]] = []
for output_index in keep:
mask = (
prediction["masks"][output_index, 0].detach().cpu().numpy()
>= INSTANCE_MASK_THRESHOLD
)
mask_pixels = int(mask.sum())
if mask_pixels < 8:
continue
label_id = int(prediction["labels"][output_index].item())
instance_id = len(instances) + 1
index_map[np.logical_and(mask, index_map == 0)] = instance_id
instances.append(
{
"instance_id": instance_id,
"class_id": label_id,
"label": instance_labels[label_id],
"score": round(float(scores[output_index]), 9),
"box_xyxy": [
round(float(value), 6)
for value in prediction["boxes"][output_index]
.detach()
.cpu()
.tolist()
],
"mask_pixels": mask_pixels,
}
)
_write_png(instance_root / f"frame-{frame_index + 1:06d}.png", index_map)
instances_by_frame.append(instances)
total_instances += len(instances)
if (frame_index + 1) % 100 == 0 or frame_index + 1 == segment_count:
print(
json.dumps(
{
"phase": "instance",
"frames_processed": frame_index + 1,
"frames_total": segment_count,
},
sort_keys=True,
),
flush=True,
)
checkpoint = Path(instance_weights.url).name
checkpoint_path = Path(torch.hub.get_dir()) / "checkpoints" / checkpoint
del instance_model
torch.cuda.empty_cache()
semantic_snapshot = Path(
snapshot_download(
repo_id=SEMANTIC_MODEL_ID,
revision=SEMANTIC_REVISION,
cache_dir=cache_root / "huggingface",
allow_patterns=("config.json", "preprocessor_config.json", "pytorch_model.bin"),
)
)
processor = AutoImageProcessor.from_pretrained(
semantic_snapshot,
local_files_only=True,
use_fast=False,
)
semantic_model, loading = BeitForSemanticSegmentation.from_pretrained(
semantic_snapshot,
local_files_only=True,
output_loading_info=True,
)
load_problems = {
name: loading.get(name, [])
for name in ("missing_keys", "unexpected_keys", "mismatched_keys", "error_msgs")
if loading.get(name)
}
if load_problems:
raise RuntimeError(
"semantic checkpoint did not load exactly: "
+ json.dumps(load_problems)
)
semantic_model = semantic_model.to(device).eval()
semantic_labels = {
int(key): str(value)
for key, value in semantic_model.config.id2label.items()
}
frame_metadata = output_root / "frames.jsonl"
with frame_metadata.open("x", encoding="utf-8", newline="\n") as metadata_stream:
with torch.inference_mode():
for frame_index, (path, session_seconds) in enumerate(
zip(frame_paths, timestamps, strict=True)
):
with Image.open(path) as opened:
image = np.asarray(opened.convert("RGB"), dtype=np.uint8)
inputs = processor(images=Image.fromarray(image), return_tensors="pt")
inputs = {name: value.to(device) for name, value in inputs.items()}
torch.cuda.synchronize()
before = time.perf_counter()
logits = semantic_model(**inputs).logits
resized = functional.interpolate(
logits,
size=image.shape[:2],
mode="bilinear",
align_corners=False,
)
semantic = resized.argmax(dim=1)[0].detach().cpu().numpy().astype(np.uint8)
torch.cuda.synchronize()
semantic_latencies.append((time.perf_counter() - before) * 1000.0)
semantic_overlay, classes = _semantic_overlay(
image,
semantic,
semantic_labels,
)
instance_map = np.asarray(
Image.open(instance_root / f"frame-{frame_index + 1:06d}.png"),
dtype=np.uint16,
)
overlay = _instance_overlay(
semantic_overlay,
instance_map,
instances_by_frame[frame_index],
)
_write_png(semantic_root / f"frame-{frame_index + 1:06d}.png", semantic)
_write_png(overlay_root / f"frame-{frame_index + 1:06d}.png", overlay)
metadata_stream.write(
json.dumps(
{
"schema_version": FRAME_SCHEMA,
"frame_index": frame_index,
"sequence": frame_index + 1,
"session_seconds": round(session_seconds, 9),
"instances": instances_by_frame[frame_index],
"semantic_classes": classes,
},
ensure_ascii=False,
sort_keys=True,
separators=(",", ":"),
allow_nan=False,
)
+ "\n"
)
if (frame_index + 1) % 100 == 0 or frame_index + 1 == segment_count:
print(
json.dumps(
{
"phase": "semantic",
"frames_processed": frame_index + 1,
"frames_total": segment_count,
},
sort_keys=True,
),
flush=True,
)
metadata_stream.flush()
os.fsync(metadata_stream.fileno())
del semantic_model
torch.cuda.empty_cache()
inference_elapsed = time.perf_counter() - started
model_files = _model_files(semantic_snapshot, checkpoint_path)
report = {
"schema_version": REPORT_SCHEMA,
"run_id": f"{job['job_id']}-panoptic-v1",
"created_at_utc": datetime.now(UTC)
.isoformat(timespec="milliseconds")
.replace("+00:00", "Z"),
"state": "inference-complete-awaiting-publication",
"input": {
"job_id": job["job_id"],
"input_sha256": job["input_sha256"],
"session_id": input_document["session_id"],
"source_id": input_document["source_id"],
"codec_epoch": input_document["codec_epoch"],
"segment_count": segment_count,
"byte_length": input_document["byte_length"],
"timeline_start_seconds": timeline["start_seconds"],
"timeline_end_seconds": timeline["end_seconds"],
"frame_timeline_sha256": _sha256(timeline_path),
},
"calibration": {
"content_identity_sha256": args.calibration_sha256,
"camera_slot": args.calibration_slot,
},
"configuration": {
"pipeline": "recorded-panoptic-maskrcnn-beit/v1",
"instance_score_threshold": INSTANCE_SCORE_THRESHOLD,
"instance_mask_threshold": INSTANCE_MASK_THRESHOLD,
"semantic_alpha": SEMANTIC_ALPHA,
"instance_alpha": INSTANCE_ALPHA,
"batch_size": 1,
"frame_policy": "all-frames-no-sampling",
"runner_sha256": _sha256(Path(__file__).resolve(strict=True)),
},
"models": {
"instance": {
"id": "torchvision/maskrcnn_resnet50_fpn_v2",
"weights": str(instance_weights),
"score_threshold": INSTANCE_SCORE_THRESHOLD,
},
"semantic": {
"id": SEMANTIC_MODEL_ID,
"revision": SEMANTIC_REVISION,
"checkpoint_load": "exact-no-missing-unexpected-or-mismatched-keys",
},
"files": model_files,
},
"runtime": {
"hostname": platform.node(),
"platform": platform.platform(),
"python": platform.python_version(),
"torch": torch.__version__,
"torchvision": torchvision.__version__,
"transformers": transformers.__version__,
"cuda_runtime": torch.version.cuda,
"gpu": torch.cuda.get_device_name(),
"gpu_compute_capability": list(torch.cuda.get_device_capability()),
},
"metrics": {
"frames_expected": segment_count,
"frames_processed": segment_count,
"frames_failed": 0,
"frames_skipped": 0,
"instances": total_instances,
"inference_wall_seconds": round(inference_elapsed, 6),
"inference_frames_per_second": round(segment_count / inference_elapsed, 6),
"instance_latency_ms": _percentiles(instance_latencies),
"semantic_latency_ms": _percentiles(semantic_latencies),
"cuda_peak_memory_allocated_mib": round(
torch.cuda.max_memory_allocated() / 2**20,
3,
),
"cuda_peak_memory_reserved_mib": round(
torch.cuda.max_memory_reserved() / 2**20,
3,
),
"process_peak_rss_mib": round(
resource.getrusage(resource.RUSAGE_SELF).ru_maxrss / 1024,
3,
),
"system_load_average": [round(value, 6) for value in os.getloadavg()],
"gpu_telemetry": telemetry.summary(),
},
"versions": {
name: importlib.metadata.version(name)
for name in ("numpy", "pillow", "torch", "torchvision", "transformers")
},
}
_write_json(output_root / "run-report.partial.json", report)
print(json.dumps({"state": "inference-complete", "frames": segment_count}, sort_keys=True))
return 0
def _artifact(
path: Path,
kind: str,
media_type: str,
schema_version: str | None = None,
) -> dict[str, object]:
result: dict[str, object] = {
"kind": kind,
"path": path.name,
"media_type": media_type,
"byte_length": path.stat().st_size,
"sha256": _sha256(path),
}
if schema_version is not None:
result["schema_version"] = schema_version
return result
def _finalize(args: argparse.Namespace) -> int:
output_root = args.output.resolve(strict=True)
video = args.video.resolve(strict=True)
masks = args.masks.resolve(strict=True)
if video.parent != output_root or masks.parent != output_root:
raise RuntimeError("published artifacts must be direct result children")
partial_path = output_root / "run-report.partial.json"
frames_path = output_root / "frames.jsonl"
telemetry_path = output_root / "gpu-telemetry.jsonl"
partial = _read_object(partial_path)
if partial.get("schema_version") != REPORT_SCHEMA:
raise RuntimeError("partial run report is incompatible")
input_document = partial["input"]
configuration = partial["configuration"]
models = partial["models"]
identity = {
"schema_version": "missioncore.recorded-perception-identity/v2",
"job_id": input_document["job_id"],
"input_sha256": input_document["input_sha256"],
"calibration": partial["calibration"],
"configuration": configuration,
"models": models,
"publication": {
"video_encoder": args.encoder,
"video_media_type": "video/mp4",
"mask_archive_media_type": "application/gzip",
},
}
identity_sha256 = hashlib.sha256(_canonical_json(identity)).hexdigest()
result_id = f"result-{identity_sha256}"
final_report = {
**partial,
"state": "published",
"result_id": result_id,
"publication": {
"extract_seconds": round(args.extract_seconds, 6),
"encode_seconds": round(args.encode_seconds, 6),
"wall_seconds": round(args.wall_seconds, 6),
"end_to_end_frames_per_second": round(
int(partial["metrics"]["frames_processed"]) / args.wall_seconds,
6,
),
"encoder": args.encoder,
},
}
report_path = output_root / "run-report.json"
_write_json(report_path, final_report)
artifacts = [
_artifact(video, "panoptic-overlay-video", "video/mp4"),
_artifact(masks, "panoptic-mask-archive", "application/gzip"),
_artifact(frames_path, "panoptic-frame-metadata", "application/x-ndjson", FRAME_SCHEMA),
_artifact(telemetry_path, "worker-gpu-telemetry", "application/x-ndjson"),
_artifact(report_path, "perception-run-report", "application/json", REPORT_SCHEMA),
]
result = {
"schema_version": RESULT_SCHEMA,
"result_id": result_id,
"identity_sha256": identity_sha256,
"identity": identity,
"created_at_utc": final_report["created_at_utc"],
"job_id": input_document["job_id"],
"input_sha256": input_document["input_sha256"],
"session_id": input_document["session_id"],
"source_id": input_document["source_id"],
"codec_epoch": input_document["codec_epoch"],
"timestamp_basis": "session-time-seconds",
"timeline_start_seconds": input_document["timeline_start_seconds"],
"timeline_end_seconds": input_document["timeline_end_seconds"],
"frames_processed": final_report["metrics"]["frames_processed"],
"artifacts": artifacts,
}
_write_json(output_root / "result.json", result)
partial_path.unlink()
print(json.dumps({"result_id": result_id, "identity_sha256": identity_sha256}, sort_keys=True))
return 0
def main() -> int:
args = _arguments()
if args.command == "preflight":
return _preflight(args)
if args.command == "run":
return _run(args)
return _finalize(args)
if __name__ == "__main__":
raise SystemExit(main())
@@ -0,0 +1,425 @@
#!/usr/bin/env python3
"""Run a bounded, recorded-only segmentation probe on an external GPU worker."""
from __future__ import annotations
import argparse
import hashlib
import importlib.metadata
import json
import os
import platform
import shutil
import statistics
import time
from datetime import UTC, datetime
from pathlib import Path
from typing import Any
MAX_INPUT_IMAGES = 16
MAX_INPUT_BYTES = 32 * 1024 * 1024
MAX_DIMENSION = 4096
INSTANCE_SCORE_THRESHOLD = 0.5
SEMANTIC_MODEL_ID = "microsoft/beit-base-finetuned-ade-640-640"
SEMANTIC_REVISION = "a8b6f5ef4acb2ea55d882989deaa02d39401e2b2"
RESULT_SCHEMA = "missioncore.recorded-segmentation-experiment/v1"
def _arguments() -> argparse.Namespace:
parser = argparse.ArgumentParser()
parser.add_argument("--input", type=Path, required=True)
parser.add_argument("--output", type=Path, required=True)
parser.add_argument("--cache", type=Path, required=True)
return parser.parse_args()
def _sha256(path: Path) -> str:
digest = hashlib.sha256()
with path.open("rb") as stream:
for chunk in iter(lambda: stream.read(1024 * 1024), b""):
digest.update(chunk)
return digest.hexdigest()
def _canonical_json(value: object) -> bytes:
return json.dumps(
value,
ensure_ascii=False,
sort_keys=True,
separators=(",", ":"),
allow_nan=False,
).encode("utf-8")
def _palette(index: int) -> tuple[int, int, int]:
digest = hashlib.sha256(f"mission-core-segment-{index}".encode()).digest()
return (64 + digest[0] % 176, 64 + digest[1] % 176, 64 + digest[2] % 176)
def _blend(image: Any, colors: Any, alpha: float) -> Any:
import numpy as np
return np.clip(
image.astype(np.float32) * (1.0 - alpha) + colors.astype(np.float32) * alpha,
0,
255,
).astype(np.uint8)
def _semantic_overlay(
image: Any, index_map: Any, labels: dict[int, str]
) -> tuple[Any, list[dict[str, Any]]]:
import numpy as np
colors = np.zeros_like(image)
counts = np.bincount(index_map.reshape(-1), minlength=max(labels) + 1)
present = np.flatnonzero(counts)
for index in present:
colors[index_map == index] = _palette(int(index))
total = int(index_map.size)
classes = [
{
"id": int(index),
"label": labels.get(int(index), f"class-{int(index)}"),
"pixels": int(counts[index]),
"fraction": round(float(counts[index]) / total, 9),
}
for index in sorted(present, key=lambda value: int(counts[value]), reverse=True)
]
return _blend(image, colors, 0.46), classes
def _instance_overlay(image: Any, instances: list[dict[str, Any]], masks: list[Any]) -> Any:
import numpy as np
result = image.copy()
for index, (instance, mask) in enumerate(zip(instances, masks, strict=True), start=1):
color = np.asarray(_palette(500 + index), dtype=np.uint8)
result[mask] = _blend(result[mask], np.broadcast_to(color, result[mask].shape), 0.56)
x1, y1, x2, y2 = (int(round(value)) for value in instance["box_xyxy"])
result[max(0, y1) : min(result.shape[0], y1 + 2), max(0, x1) : min(result.shape[1], x2)] = (
color
)
result[max(0, y2 - 2) : min(result.shape[0], y2), max(0, x1) : min(result.shape[1], x2)] = (
color
)
result[max(0, y1) : min(result.shape[0], y2), max(0, x1) : min(result.shape[1], x1 + 2)] = (
color
)
result[max(0, y1) : min(result.shape[0], y2), max(0, x2 - 2) : min(result.shape[1], x2)] = (
color
)
return result
def _write_png(path: Path, array: Any) -> None:
from PIL import Image
Image.fromarray(array).save(path, format="PNG", optimize=False)
def _artifact(path: Path) -> dict[str, object]:
return {"name": path.name, "bytes": path.stat().st_size, "sha256": _sha256(path)}
def main() -> int:
args = _arguments()
input_root = args.input.expanduser().resolve(strict=True)
output_root = args.output.expanduser().resolve()
cache_root = args.cache.expanduser().resolve()
if not input_root.is_dir() or output_root.exists():
raise RuntimeError("input must be a directory and output must not exist")
images = sorted(input_root.glob("camera-*.png"))
if not images or len(images) > MAX_INPUT_IMAGES:
raise RuntimeError("input image count is outside the recorded probe bound")
for path in images:
if not path.is_file() or path.stat().st_size > MAX_INPUT_BYTES:
raise RuntimeError("input image is missing or too large")
import numpy as np
import torch
import torch.nn.functional as functional
import torchvision
import transformers
from huggingface_hub import snapshot_download
from PIL import Image
from torchvision.models.detection import (
MaskRCNN_ResNet50_FPN_V2_Weights,
maskrcnn_resnet50_fpn_v2,
)
from transformers import AutoImageProcessor, BeitForSemanticSegmentation
if not torch.cuda.is_available():
raise RuntimeError("CUDA is required for this worker experiment")
device = torch.device("cuda:0")
cache_root.mkdir(mode=0o700, parents=True, exist_ok=True)
staging = output_root.with_name(f".{output_root.name}.incomplete")
staging.mkdir(mode=0o700, parents=True, exist_ok=False)
started = time.perf_counter()
try:
decoded: list[tuple[Path, Any]] = []
width: int | None = None
height: int | None = None
for path in images:
with Image.open(path) as opened:
opened.verify()
with Image.open(path) as opened:
rgb = opened.convert("RGB")
if max(rgb.size) > MAX_DIMENSION:
raise RuntimeError("input image dimension is outside the probe bound")
if width is None:
width, height = rgb.size
elif rgb.size != (width, height):
raise RuntimeError("input images do not share one physical epoch resolution")
decoded.append((path, np.asarray(rgb, dtype=np.uint8)))
instance_weights = MaskRCNN_ResNet50_FPN_V2_Weights.DEFAULT
instance_model = maskrcnn_resnet50_fpn_v2(weights=instance_weights).to(device).eval()
instance_labels = list(instance_weights.meta["categories"])
instance_results: dict[str, dict[str, Any]] = {}
instance_latencies: list[float] = []
with torch.inference_mode():
for path, image in decoded:
tensor = instance_weights.transforms()(Image.fromarray(image)).to(device)
torch.cuda.synchronize()
before = time.perf_counter()
prediction = instance_model([tensor])[0]
torch.cuda.synchronize()
latency_ms = (time.perf_counter() - before) * 1000.0
instance_latencies.append(latency_ms)
scores = prediction["scores"].detach().cpu().numpy()
keep = np.flatnonzero(scores >= INSTANCE_SCORE_THRESHOLD)
masks: list[Any] = []
instances: list[dict[str, Any]] = []
index_map = np.zeros(image.shape[:2], dtype=np.uint16)
for output_index in keep:
mask = prediction["masks"][output_index, 0].detach().cpu().numpy() >= 0.5
if int(mask.sum()) < 8:
continue
label_id = int(prediction["labels"][output_index].item())
instance_id = len(instances) + 1
index_map[np.logical_and(mask, index_map == 0)] = instance_id
masks.append(mask)
instances.append(
{
"instance_id": instance_id,
"class_id": label_id,
"label": instance_labels[label_id],
"score": round(float(scores[output_index]), 9),
"box_xyxy": [
round(float(value), 6)
for value in prediction["boxes"][output_index]
.detach()
.cpu()
.tolist()
],
"mask_pixels": int(mask.sum()),
}
)
stem = path.stem
_write_png(staging / f"{stem}.instances.png", index_map)
_write_png(
staging / f"{stem}.instance-overlay.png",
_instance_overlay(image, instances, masks),
)
instance_results[stem] = {
"latency_ms": round(latency_ms, 6),
"instances": instances,
}
del instance_model
torch.cuda.empty_cache()
semantic_snapshot = Path(
snapshot_download(
repo_id=SEMANTIC_MODEL_ID,
revision=SEMANTIC_REVISION,
cache_dir=cache_root / "huggingface",
allow_patterns=(
"config.json",
"preprocessor_config.json",
"pytorch_model.bin",
),
)
)
processor = AutoImageProcessor.from_pretrained(
semantic_snapshot,
local_files_only=True,
use_fast=False,
)
semantic_model, semantic_loading = BeitForSemanticSegmentation.from_pretrained(
semantic_snapshot,
local_files_only=True,
output_loading_info=True,
)
semantic_load_problems = {
name: semantic_loading.get(name, [])
for name in ("missing_keys", "unexpected_keys", "mismatched_keys", "error_msgs")
if semantic_loading.get(name)
}
if semantic_load_problems:
raise RuntimeError(
"semantic checkpoint did not load exactly: "
+ json.dumps(semantic_load_problems, sort_keys=True)
)
semantic_model = semantic_model.to(device).eval()
semantic_labels = {
int(key): str(value) for key, value in semantic_model.config.id2label.items()
}
semantic_results: dict[str, dict[str, Any]] = {}
semantic_latencies: list[float] = []
with torch.inference_mode():
for path, image in decoded:
inputs = processor(images=Image.fromarray(image), return_tensors="pt")
inputs = {name: value.to(device) for name, value in inputs.items()}
torch.cuda.synchronize()
before = time.perf_counter()
logits = semantic_model(**inputs).logits
resized = functional.interpolate(
logits,
size=image.shape[:2],
mode="bilinear",
align_corners=False,
)
semantic = resized.argmax(dim=1)[0].detach().cpu().numpy().astype(np.uint8)
torch.cuda.synchronize()
latency_ms = (time.perf_counter() - before) * 1000.0
semantic_latencies.append(latency_ms)
overlay, classes = _semantic_overlay(image, semantic, semantic_labels)
stem = path.stem
_write_png(staging / f"{stem}.semantic.png", semantic)
_write_png(staging / f"{stem}.semantic-overlay.png", overlay)
semantic_results[stem] = {
"latency_ms": round(latency_ms, 6),
"classes": classes,
}
del semantic_model
torch.cuda.empty_cache()
rows = []
for path, image in decoded:
stem = path.stem
instance_overlay = np.asarray(Image.open(staging / f"{stem}.instance-overlay.png"))
semantic_overlay = np.asarray(Image.open(staging / f"{stem}.semantic-overlay.png"))
rows.append(np.concatenate((image, instance_overlay, semantic_overlay), axis=1))
_write_png(staging / "segmentation-mosaic.png", np.concatenate(rows, axis=0))
checkpoint = Path(instance_weights.url).name
checkpoint_path = Path(torch.hub.get_dir()) / "checkpoints" / checkpoint
model_files = [
{
"name": f"beit/{path.name}",
"bytes": path.stat().st_size,
"sha256": _sha256(path),
}
for path in sorted(semantic_snapshot.iterdir())
if path.is_file()
]
model_files.append(
{
"name": f"torchvision/{checkpoint}",
"bytes": checkpoint_path.stat().st_size,
"sha256": _sha256(checkpoint_path),
}
)
inputs_manifest = [
{"name": path.name, "bytes": path.stat().st_size, "sha256": _sha256(path)}
for path in images
]
identity = {
"inputs": inputs_manifest,
"instance_model": "torchvision/maskrcnn_resnet50_fpn_v2/default",
"instance_threshold": INSTANCE_SCORE_THRESHOLD,
"semantic_model": SEMANTIC_MODEL_ID,
"semantic_revision": SEMANTIC_REVISION,
"model_files": model_files,
}
manifest: dict[str, Any] = {
"schema_version": RESULT_SCHEMA,
"created_at_utc": datetime.now(UTC)
.isoformat(timespec="milliseconds")
.replace("+00:00", "Z"),
"classification": "private-derived-recorded-perception-experiment",
"generation_sha256": hashlib.sha256(_canonical_json(identity)).hexdigest(),
"input": inputs_manifest,
"models": {
"instance": {
"id": "torchvision/maskrcnn_resnet50_fpn_v2",
"weights": str(instance_weights),
"weights_url": instance_weights.url,
"score_threshold": INSTANCE_SCORE_THRESHOLD,
"license": "BSD-3-Clause (TorchVision code/weight distribution)",
},
"semantic": {
"id": SEMANTIC_MODEL_ID,
"revision": SEMANTIC_REVISION,
"dataset": "ADE20K scene_parse_150",
"license": "Apache-2.0 (model-card metadata)",
"checkpoint_load": "exact-no-missing-unexpected-or-mismatched-keys",
},
"files": model_files,
},
"runtime": {
"base_image": os.environ.get("MISSION_CORE_BASE_IMAGE", "unknown"),
"python": platform.python_version(),
"torch": torch.__version__,
"torchvision": torchvision.__version__,
"transformers": transformers.__version__,
"cuda_runtime": torch.version.cuda,
"cudnn": torch.backends.cudnn.version(),
"gpu": torch.cuda.get_device_name(0),
"packages": sorted(
(
{
"name": distribution.metadata["Name"],
"version": distribution.version,
}
for distribution in importlib.metadata.distributions()
if distribution.metadata["Name"]
),
key=lambda item: str(item["name"]).lower(),
),
},
"metrics": {
"frame_count": len(decoded),
"instance_latency_ms": {
"mean": round(statistics.fmean(instance_latencies), 6),
"max": round(max(instance_latencies), 6),
},
"semantic_latency_ms": {
"mean": round(statistics.fmean(semantic_latencies), 6),
"max": round(max(semantic_latencies), 6),
},
"elapsed_seconds": round(time.perf_counter() - started, 6),
},
"frames": {
stem: {
"instance": instance_results[stem],
"semantic": semantic_results[stem],
}
for stem in sorted(instance_results)
},
"acceptance": {
"recorded_segmentation_artifact": "generated",
"quality": "operator-review-required",
"live": "not-tested",
"safety": "not-accepted",
},
}
artifacts = sorted(staging.glob("*.png"))
manifest["outputs"] = [_artifact(path) for path in artifacts]
(staging / "manifest.redacted.json").write_bytes(
json.dumps(manifest, ensure_ascii=False, indent=2, sort_keys=True).encode("utf-8")
+ b"\n"
)
os.rename(staging, output_root)
except BaseException:
shutil.rmtree(staging, ignore_errors=True)
raise
print(
json.dumps({"output": output_root.name, "generation_sha256": manifest["generation_sha256"]})
)
return 0
if __name__ == "__main__":
raise SystemExit(main())