feat(perception): integrate native RF-DETR shadow provider
This commit is contained in:
@@ -25,6 +25,7 @@ from k1link.perception.detector import (
|
||||
DetectorFrameTiming,
|
||||
DetectorProviderSnapshot,
|
||||
DetectorWarmupSnapshot,
|
||||
NativeRfDetrShadowDetectorProvider,
|
||||
RfDetrShadowDetectorProvider,
|
||||
)
|
||||
from k1link.perception.geometry import Ravnoves00GeometryAssociationProvider
|
||||
@@ -446,6 +447,7 @@ def main() -> int:
|
||||
all_pipeline_timings: list[dict[str, object]] = []
|
||||
all_decode_timings: list[DecodedFrameTiming] = []
|
||||
all_pacing_timings: list[SourcePacingTiming] = []
|
||||
detector_provider_id: str | None = None
|
||||
with (
|
||||
progress.open("x", encoding="utf-8") as progress_stream,
|
||||
frame_ledger.open("x", encoding="utf-8") as frame_ledger_stream,
|
||||
@@ -478,6 +480,11 @@ def main() -> int:
|
||||
maximum_frames=arguments.maximum_frames,
|
||||
source_rate_hz=arguments.source_rate_hz,
|
||||
) as runtime:
|
||||
current_detector_provider_id = runtime.graph.detector.provider_id
|
||||
if detector_provider_id is None:
|
||||
detector_provider_id = current_detector_provider_id
|
||||
elif detector_provider_id != current_detector_provider_id:
|
||||
raise RuntimeError("detector provider identity changed between loops")
|
||||
for stage_id, attribute in (
|
||||
("geometry", "geometry"),
|
||||
("temporal", "temporal"),
|
||||
@@ -504,7 +511,8 @@ def main() -> int:
|
||||
result = runtime.graph.run()
|
||||
loop_completed_ns = time.monotonic_ns()
|
||||
detector_snapshot = cast(
|
||||
RfDetrShadowDetectorProvider,
|
||||
RfDetrShadowDetectorProvider
|
||||
| NativeRfDetrShadowDetectorProvider,
|
||||
runtime.graph.detector,
|
||||
).snapshot()
|
||||
provider_snapshots = {
|
||||
@@ -582,6 +590,8 @@ def main() -> int:
|
||||
print(json.dumps(progress_row, sort_keys=True), flush=True)
|
||||
|
||||
completed_ns = time.monotonic_ns()
|
||||
if detector_provider_id is None:
|
||||
raise RuntimeError("detector provider identity was not observed")
|
||||
wall_seconds = (completed_ns - started_ns) / 1_000_000_000.0
|
||||
rss_after_kib = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
|
||||
accounting: Counter[str] = Counter()
|
||||
@@ -674,7 +684,7 @@ def main() -> int:
|
||||
"identity": {
|
||||
"worker_id": "worker-006",
|
||||
"graph_id": "reference-perception-graph/v2",
|
||||
"detector_provider_id": "triton-rf-detr-large-coco-risk-fp16-shadow/v0",
|
||||
"detector_provider_id": detector_provider_id,
|
||||
"inputs": _input_digests(paths, arguments.detector_profile),
|
||||
"runtime_artifact_sha256": arguments.runtime_artifact_sha256,
|
||||
"runner_sha256": arguments.runner_sha256,
|
||||
|
||||
@@ -0,0 +1,360 @@
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$ReleaseRoot,
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$CandidateRoot,
|
||||
[Parameter(Mandatory = $true)]
|
||||
[ValidatePattern("^[a-f0-9]{64}$")]
|
||||
[string]$ExpectedWheelSha256,
|
||||
[Parameter(Mandatory = $true)]
|
||||
[ValidatePattern("^[A-Za-z0-9._-]{1,96}$")]
|
||||
[string]$RunId,
|
||||
[ValidateRange(1, 4489)]
|
||||
[int]$MaximumFrames = 300,
|
||||
[ValidateRange(1.0, 120.0)]
|
||||
[double]$SourceRateHz = 10.0,
|
||||
[ValidateRange(0.0, 1.0)]
|
||||
[double]$MinimumDeliveryRatio = 0.999,
|
||||
[ValidateRange(0.1, 120.0)]
|
||||
[double]$MinimumEffectiveWorldStateFps = 9.5,
|
||||
[ValidateRange(1.0, 10000.0)]
|
||||
[double]$MaximumWorldStateCompletionP95Ms = 125.0,
|
||||
[string]$OutputRoot = (
|
||||
"D:\NDC_MISSIONCORE\runtime\results\m48n-native-reference-graph-shadow"
|
||||
)
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
$ProgressPreference = "SilentlyContinue"
|
||||
|
||||
function Assert-LastExitCode([string]$Operation) {
|
||||
if ($LASTEXITCODE -ne 0) { throw "$Operation failed with exit code $LASTEXITCODE" }
|
||||
}
|
||||
|
||||
function Get-Sha256([string]$Path) {
|
||||
return (Get-FileHash -LiteralPath $Path -Algorithm SHA256).Hash.ToLowerInvariant()
|
||||
}
|
||||
|
||||
function Assert-File([string]$Path, [string]$ExpectedSha256, [string]$Label) {
|
||||
$item = Get-Item -LiteralPath (Resolve-Path -LiteralPath $Path).Path -Force
|
||||
if ($item.PSIsContainer -or ($item.Attributes -band [IO.FileAttributes]::ReparsePoint)) {
|
||||
throw "$Label must be a regular file"
|
||||
}
|
||||
if ((Get-Sha256 $item.FullName) -cne $ExpectedSha256) {
|
||||
throw "$Label SHA-256 changed"
|
||||
}
|
||||
return $item.FullName
|
||||
}
|
||||
|
||||
function Resolve-DDirectory([string]$Path, [string]$Label, [bool]$Create) {
|
||||
if ($Create -and -not (Test-Path -LiteralPath $Path)) {
|
||||
$null = New-Item -ItemType Directory -Path $Path
|
||||
}
|
||||
$item = Get-Item -LiteralPath (Resolve-Path -LiteralPath $Path).Path -Force
|
||||
if (
|
||||
-not $item.PSIsContainer -or
|
||||
($item.Attributes -band [IO.FileAttributes]::ReparsePoint) -or
|
||||
[IO.Path]::GetPathRoot($item.FullName).TrimEnd("\") -ine "D:"
|
||||
) {
|
||||
throw "$Label must be a real D: directory"
|
||||
}
|
||||
return $item.FullName
|
||||
}
|
||||
|
||||
function Convert-ToDockerPath([string]$Path) { return $Path.Replace("\", "/") }
|
||||
|
||||
function Get-Container([string]$Name) {
|
||||
$rows = @((& docker inspect $Name) | ConvertFrom-Json)
|
||||
Assert-LastExitCode "Docker inspection for $Name"
|
||||
if ($rows.Count -ne 1) { throw "Container identity for $Name is not unique" }
|
||||
return $rows[0]
|
||||
}
|
||||
|
||||
if ($env:COMPUTERNAME -cne "DESKTOP-OPJ8J04") {
|
||||
throw "M48N native reference graph is pinned to DESKTOP-OPJ8J04"
|
||||
}
|
||||
|
||||
$release = Resolve-DDirectory $ReleaseRoot "M48N release root" $false
|
||||
$candidate = Resolve-DDirectory $CandidateRoot "M48N candidate root" $false
|
||||
$output = Resolve-DDirectory $OutputRoot "M48N output root" $true
|
||||
$runOutput = Join-Path $output $RunId
|
||||
if (Test-Path -LiteralPath $runOutput) { throw "M48N run output already exists" }
|
||||
$null = New-Item -ItemType Directory -Path $runOutput
|
||||
$runOutput = Resolve-DDirectory $runOutput "M48N run output" $false
|
||||
|
||||
$wheel = Assert-File (
|
||||
Join-Path $release "nodedc_mission_core-0.1.0-py3-none-any.whl"
|
||||
) $ExpectedWheelSha256 "M48N wheel"
|
||||
$expectedConfigs = [ordered]@{
|
||||
"m48n-rf-detr-native-reference-graph-shadow-v0.json" = (
|
||||
"336dccb6b64f4fa5def14aae967fd3280cc1720e93fa3ee21885e0c3304cee4d"
|
||||
)
|
||||
"m4-recorded-realtime-baseline-v1.json" = (
|
||||
"ea10359339e6cce31b5780a2710299771cab7cc0c1c2a2b56a1621f786b31fa8"
|
||||
)
|
||||
"rf-detr-large-native-kb4-risk-shadow-v0.json" = (
|
||||
"398b1102943e704b08a033b1d04b6bdb039ecdd73a2b2e370a0a9cbcaff501ec"
|
||||
)
|
||||
"m4-geometry-association-v1.json" = (
|
||||
"cc666c9389a5e221957faddec89584709b66918d14abaf646f1832e001421999"
|
||||
)
|
||||
"m4-temporal-motion-v1.json" = (
|
||||
"7130eaee24a95c7d888bf7598010e03e129e1c3ac5b34bcd8401015ff4244b39"
|
||||
)
|
||||
"m4-rolling-local-map-v1.json" = (
|
||||
"f7e3315eaf6ffaf3aee1e04913933812092cf82bbcc9984c1a6fa2d9250e6784"
|
||||
)
|
||||
"m4-replay-threat-v3.json" = (
|
||||
"8c3a5aa837da1f028f5998fb504a1381f9b2b68de6420a32160410b6dc0887c7"
|
||||
)
|
||||
}
|
||||
foreach ($entry in $expectedConfigs.GetEnumerator()) {
|
||||
$null = Assert-File (Join-Path $release $entry.Key) $entry.Value (
|
||||
"M48N config {0}" -f $entry.Key
|
||||
)
|
||||
}
|
||||
$runner = Get-Item -LiteralPath (
|
||||
Join-Path $release "run_m48s_reference_graph_shadow_worker.py"
|
||||
)
|
||||
if ($runner.PSIsContainer -or ($runner.Attributes -band [IO.FileAttributes]::ReparsePoint)) {
|
||||
throw "M48N graph runner must be a regular file"
|
||||
}
|
||||
$runnerSha256 = Get-Sha256 $runner.FullName
|
||||
$nativeConfig = Assert-File (
|
||||
Join-Path $release "rf_detr_large_native_kb4_config.pbtxt"
|
||||
) "15e100029df92c1390c567517eac6d8bf640591c865bf87a3955289292ba3a22" (
|
||||
"native RF-DETR Triton config"
|
||||
)
|
||||
$nativeEngine = Assert-File (
|
||||
Join-Path $candidate "rf-detr-native-uint8.plan"
|
||||
) "b8a40b3580edff001ec9680de68707242294ff590ab296000fae371f1083f695" (
|
||||
"native RF-DETR TensorRT engine"
|
||||
)
|
||||
|
||||
$modelRoot = Join-Path $runOutput "triton-models"
|
||||
$modelDirectory = Join-Path $modelRoot "rf_detr_large_native_kb4"
|
||||
$modelVersionDirectory = Join-Path $modelDirectory "1"
|
||||
$null = New-Item -ItemType Directory -Path $modelVersionDirectory
|
||||
Copy-Item -LiteralPath $nativeConfig -Destination (Join-Path $modelDirectory "config.pbtxt")
|
||||
Copy-Item -LiteralPath $nativeEngine -Destination (Join-Path $modelVersionDirectory "model.plan")
|
||||
if (
|
||||
(Get-Sha256 (Join-Path $modelVersionDirectory "model.plan")) -cne
|
||||
"b8a40b3580edff001ec9680de68707242294ff590ab296000fae371f1083f695"
|
||||
) {
|
||||
throw "staged native RF-DETR TensorRT engine SHA-256 changed"
|
||||
}
|
||||
|
||||
$source = [ordered]@{
|
||||
CameraIndex = (
|
||||
"D:\NDC_MISSIONCORE\runtime\jobs\recorded-camera-602ac89026ed12978619801d" +
|
||||
"\input\camera\sensor.camera.right\epoch-1\index.jsonl"
|
||||
)
|
||||
SourcePack = (
|
||||
"D:\NDC_MISSIONCORE\runtime\derived" +
|
||||
"\e10-lidar-pack-576c994a6c814e2592dd6240ace3902a5db94843312c759a73ba0c9166157d2b" +
|
||||
"\lidar-pack.npz"
|
||||
)
|
||||
LocalSurface = (
|
||||
"D:\NDC_MISSIONCORE\runtime\derived" +
|
||||
"\k1-local-surface-23762244c8bdb97de26fb721ac957d7a00bc9a63571ac4cfa4be19c4effc7d55" +
|
||||
"\local-surface.npz"
|
||||
)
|
||||
Video = (
|
||||
"D:\NDC_MISSIONCORE\runtime\experiments\e46e\inputs" +
|
||||
"\right-cadd1696ff000904eb78633a0a8418104b8024f178b91f3421789021ccb160e8.mp4"
|
||||
)
|
||||
Mask = (
|
||||
"D:\NDC_MISSIONCORE\runtime\inputs\e2" +
|
||||
"\valid-fov-mask-b4dd8ddf2b87c1d520ee8a0868c4fea062d7c14d1bae73ccabd3abe1f3acbac2" +
|
||||
"\mask.png"
|
||||
)
|
||||
}
|
||||
foreach ($entry in $source.GetEnumerator()) {
|
||||
if (-not (Test-Path -LiteralPath $entry.Value -PathType Leaf)) {
|
||||
throw "M48N source $($entry.Key) is missing"
|
||||
}
|
||||
}
|
||||
if ((Get-Sha256 $source.Video) -cne "cadd1696ff000904eb78633a0a8418104b8024f178b91f3421789021ccb160e8") {
|
||||
throw "RAVNOVES00 video SHA-256 changed"
|
||||
}
|
||||
if ((Get-Sha256 $source.Mask) -cne "a40cee06b7c6f69b6a09a11563dcfd237f3de833b1ccd31459e66692e528ba63") {
|
||||
throw "valid-FOV mask SHA-256 changed"
|
||||
}
|
||||
|
||||
$media = Resolve-DDirectory (
|
||||
"D:\NDC_MISSIONCORE\runtime\derived\perception-e15-media-pyav180-lz445-v1"
|
||||
) "PyAV dependency" $false
|
||||
$opencv = Resolve-DDirectory (
|
||||
"D:\NDC_MISSIONCORE\runtime\derived\perception-e3-opencv413092-v1\packages"
|
||||
) "OpenCV dependency" $false
|
||||
$pillow = Resolve-DDirectory (
|
||||
"D:\NDC_MISSIONCORE\runtime\derived\perception-p0-env-v1"
|
||||
) "Pillow dependency" $false
|
||||
|
||||
$image = (
|
||||
"nvcr.io/nvidia/tritonserver:26.06-py3@" +
|
||||
"sha256:58df7489c3f2276f9591d500a012dee03e23d35543ce3c390b4c001e6bf90794"
|
||||
)
|
||||
& docker image inspect $image *> $null
|
||||
Assert-LastExitCode "pinned M48N image inspection"
|
||||
$canonicalTriton = Get-Container "ndc-mission-core-triton"
|
||||
if (-not $canonicalTriton.State.Running -or $canonicalTriton.State.Health.Status -cne "healthy") {
|
||||
throw "Canonical Triton must remain healthy during M48N shadow"
|
||||
}
|
||||
$canonicalTritonId = [string]$canonicalTriton.Id
|
||||
$tritonName = "ndc-mission-core-m48n-native-reference-graph-triton"
|
||||
$graphName = "ndc-mission-core-m48n-native-reference-graph"
|
||||
foreach ($name in @($tritonName, $graphName)) {
|
||||
if (& docker ps -a --format "{{.Names}}" --filter "name=^/$name$") {
|
||||
throw "M48N candidate container $name already exists"
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
& docker create `
|
||||
--name $tritonName `
|
||||
--label "com.nodedc.product=mission-core" `
|
||||
--label "com.nodedc.stack=ndc-mission-core-compute" `
|
||||
--label "com.nodedc.role=bounded-native-rf-detr-reference-graph-triton" `
|
||||
--label "com.nodedc.managed-by=codex-bounded-experiment" `
|
||||
--read-only `
|
||||
--security-opt "no-new-privileges:true" `
|
||||
--cap-drop ALL `
|
||||
--pids-limit 512 `
|
||||
--shm-size 1g `
|
||||
--gpus all `
|
||||
--tmpfs "/tmp:rw,noexec,nosuid,size=2g" `
|
||||
--health-cmd "curl --fail --silent http://127.0.0.1:8000/v2/health/ready" `
|
||||
--health-interval 5s `
|
||||
--health-timeout 3s `
|
||||
--health-start-period 20s `
|
||||
--health-retries 24 `
|
||||
-v ((Convert-ToDockerPath $modelRoot) + ":/models:ro") `
|
||||
$image `
|
||||
tritonserver `
|
||||
--model-repository=/models `
|
||||
--model-control-mode=explicit `
|
||||
--load-model=rf_detr_large_native_kb4 `
|
||||
--disable-auto-complete-config `
|
||||
--strict-readiness=true `
|
||||
--exit-on-error=true `
|
||||
--allow-http=true `
|
||||
--allow-grpc=false `
|
||||
--allow-metrics=false *> $null
|
||||
Assert-LastExitCode "M48N Triton creation"
|
||||
& docker start $tritonName *> $null
|
||||
Assert-LastExitCode "M48N Triton start"
|
||||
$ready = $false
|
||||
foreach ($attempt in 1..60) {
|
||||
Start-Sleep -Seconds 2
|
||||
$candidateContainer = Get-Container $tritonName
|
||||
if (-not $candidateContainer.State.Running) {
|
||||
& docker logs $tritonName
|
||||
throw "M48N Triton stopped during startup"
|
||||
}
|
||||
if ($candidateContainer.State.Health.Status -ceq "healthy") {
|
||||
$ready = $true
|
||||
break
|
||||
}
|
||||
}
|
||||
if (-not $ready) { throw "M48N Triton did not become healthy" }
|
||||
if (@((Get-Container $tritonName).HostConfig.PortBindings.PSObject.Properties).Count -ne 0) {
|
||||
throw "M48N Triton published a host port"
|
||||
}
|
||||
|
||||
$arguments = @(
|
||||
"run", "--name", $graphName,
|
||||
"--label", "com.nodedc.product=mission-core",
|
||||
"--label", "com.nodedc.stack=ndc-mission-core-compute",
|
||||
"--label", "com.nodedc.role=bounded-native-rf-detr-reference-graph",
|
||||
"--label", "com.nodedc.managed-by=codex-bounded-experiment",
|
||||
"--network", ("container:{0}" -f $tritonName),
|
||||
"--read-only",
|
||||
"--security-opt", "no-new-privileges:true",
|
||||
"--cap-drop", "ALL",
|
||||
"--pids-limit", "256",
|
||||
"--gpus", "all",
|
||||
"--tmpfs", "/tmp:rw,noexec,nosuid,size=2g",
|
||||
"-e", "PYTHONDONTWRITEBYTECODE=1",
|
||||
"-e", (
|
||||
"PYTHONPATH=/release/nodedc_mission_core-0.1.0-py3-none-any.whl:" +
|
||||
"/opt/media:/opt/opencv:/opt/pillow"
|
||||
),
|
||||
"-v", ((Convert-ToDockerPath $release) + ":/release:ro"),
|
||||
"-v", ((Convert-ToDockerPath $runOutput) + ":/output:rw"),
|
||||
"-v", ((Convert-ToDockerPath $media) + ":/opt/media:ro"),
|
||||
"-v", ((Convert-ToDockerPath $opencv) + ":/opt/opencv:ro"),
|
||||
"-v", ((Convert-ToDockerPath $pillow) + ":/opt/pillow:ro"),
|
||||
"-v", ((Convert-ToDockerPath $source.CameraIndex) + ":/source/camera-index.jsonl:ro"),
|
||||
"-v", ((Convert-ToDockerPath $source.SourcePack) + ":/source/source-pack.npz:ro"),
|
||||
"-v", ((Convert-ToDockerPath $source.LocalSurface) + ":/source/local-surface.npz:ro"),
|
||||
"-v", ((Convert-ToDockerPath $source.Video) + ":/source/right.mp4:ro"),
|
||||
"-v", ((Convert-ToDockerPath $source.Mask) + ":/source/mask.png:ro"),
|
||||
"--entrypoint", "python3",
|
||||
$image,
|
||||
"/release/run_m48s_reference_graph_shadow_worker.py",
|
||||
"--graph-config", "/release/m48n-rf-detr-native-reference-graph-shadow-v0.json",
|
||||
"--baseline-profile", "/release/m4-recorded-realtime-baseline-v1.json",
|
||||
"--detector-profile", "/release/rf-detr-large-native-kb4-risk-shadow-v0.json",
|
||||
"--geometry-profile", "/release/m4-geometry-association-v1.json",
|
||||
"--temporal-motion-profile", "/release/m4-temporal-motion-v1.json",
|
||||
"--rolling-map-profile", "/release/m4-rolling-local-map-v1.json",
|
||||
"--threat-profile", "/release/m4-replay-threat-v3.json",
|
||||
"--camera-index", "/source/camera-index.jsonl",
|
||||
"--source-pack", "/source/source-pack.npz",
|
||||
"--local-surface", "/source/local-surface.npz",
|
||||
"--video", "/source/right.mp4",
|
||||
"--valid-fov-mask", "/source/mask.png",
|
||||
"--triton-origin", "http://127.0.0.1:8000",
|
||||
"--loops", "1",
|
||||
"--maximum-frames", ([string]$MaximumFrames),
|
||||
"--source-rate-hz", ([string]::Format(
|
||||
[Globalization.CultureInfo]::InvariantCulture, "{0:R}", $SourceRateHz
|
||||
)),
|
||||
"--minimum-delivery-ratio", ([string]::Format(
|
||||
[Globalization.CultureInfo]::InvariantCulture, "{0:R}", $MinimumDeliveryRatio
|
||||
)),
|
||||
"--minimum-effective-world-state-fps", ([string]::Format(
|
||||
[Globalization.CultureInfo]::InvariantCulture,
|
||||
"{0:R}",
|
||||
$MinimumEffectiveWorldStateFps
|
||||
)),
|
||||
"--maximum-world-state-completion-p95-ms", ([string]::Format(
|
||||
[Globalization.CultureInfo]::InvariantCulture,
|
||||
"{0:R}",
|
||||
$MaximumWorldStateCompletionP95Ms
|
||||
)),
|
||||
"--load-purpose", "production-rate",
|
||||
"--runtime-artifact-sha256", $ExpectedWheelSha256,
|
||||
"--runner-sha256", $runnerSha256,
|
||||
"--output", "/output/result.json",
|
||||
"--progress", "/output/progress.jsonl",
|
||||
"--frame-ledger", "/output/frames.jsonl"
|
||||
)
|
||||
& docker @arguments
|
||||
Assert-LastExitCode "M48N native complete reference graph shadow"
|
||||
foreach ($name in @("result.json", "frames.jsonl", "progress.jsonl")) {
|
||||
if (-not (Test-Path -LiteralPath (Join-Path $runOutput $name) -PathType Leaf)) {
|
||||
throw "M48N graph artifact $name was not written"
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
foreach ($name in @($graphName, $tritonName)) {
|
||||
if (& docker ps -a --format "{{.Names}}" --filter "name=^/$name$") {
|
||||
& docker rm -f $name *> $null
|
||||
}
|
||||
}
|
||||
$canonicalAfter = Get-Container "ndc-mission-core-triton"
|
||||
if (
|
||||
$canonicalAfter.Id -cne $canonicalTritonId -or
|
||||
-not $canonicalAfter.State.Running -or
|
||||
$canonicalAfter.State.Health.Status -cne "healthy"
|
||||
) {
|
||||
throw "Canonical Triton changed during M48N shadow"
|
||||
}
|
||||
}
|
||||
|
||||
Write-Output ("M48N_NATIVE_REFERENCE_GRAPH_RESULT={0}" -f (Join-Path $runOutput "result.json"))
|
||||
Write-Output "CANONICAL_TRITON_ACTION=none"
|
||||
Write-Output "PRODUCTION_ACCEPTED=false"
|
||||
Reference in New Issue
Block a user