完善 LiDAR–双天线 RTK 手眼标定仓库:补充旧式及多传感器数据导出、small_gicp/Open3D GICP 标定、结果复核与3D可视化流程,并整理三批数据和标定结果说明。

This commit is contained in:
lichun.qu
2026-07-23 18:55:50 +08:00
parent 6b7844a977
commit f72fcb71cc
91 changed files with 39561 additions and 503 deletions
+27
View File
@@ -0,0 +1,27 @@
# run
本目录是 PowerShell 运行入口;完整流程、参数解释、验收方法和代码职责统一见仓库根目录 `README.md`
| 脚本 | 使用时机 |
|---|---|
| `export_legacy_stations.ps1` | 第一、第二批式逐站 dlog 导出。 |
| `export_multisensor_stations.ps1` | LiDAR dlog + 独立 RTK/IMU rscap 导出和时间关联。 |
| `prepare_legacy_dataset.ps1` | 旧式导出结果生成 prepared。 |
| `prepare_multisensor_dataset.ps1` | 多传感器 combined 结果生成 prepared。 |
| `run_single_dataset.ps1` | 单批数据运行 small_gicp、Open3D、consensus 和 X 求解。 |
| `run_all.ps1` | 第二批求解、第一批辅助复核的历史流程。 |
| `run_consensus_finish.ps1` | 从已有两个后端 B 重做 consensus。 |
| `run_sensitivity_scan.ps1` | 指定 Pair 的外参角度灵敏度扫描。 |
| `view_result.ps1` | 传入 frames、B、X 查看 3D 配准及增量。 |
最常用的 3D 入口:
```powershell
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".\run\view_result.ps1" `
-Frames "D:\你的数据目录\prepared\frames_all" `
-Pairs "D:\你的结果目录\B_consensus.npz" `
-Extrinsic "D:\你的结果目录\extrinsic.json" `
-PairIndex 0
```
`frames_all` 必须与生成 B 时的站点顺序一致。
+34
View File
@@ -0,0 +1,34 @@
param(
[Parameter(Mandatory = $true)][string]$DataRoot,
[Parameter(Mandatory = $true)][string]$OutputRoot,
[string]$LidarObject = "frontlidar",
[string]$Timezone = "+08:00",
[string[]]$StationNames = @(),
[int]$Stride = 1,
[double]$RtkMaxDtMs = 150.0
)
$ErrorActionPreference = "Stop"
$Repo = Split-Path -Parent $PSScriptRoot
$Exporter = Join-Path $Repo "tools\frontlidar_dlog_export.py"
if (-not (Test-Path -LiteralPath $DataRoot)) { throw "DataRoot does not exist: $DataRoot" }
if ($Stride -lt 1) { throw "Stride must be at least 1" }
if ($StationNames.Count -gt 0) {
$Stations = @($StationNames | ForEach-Object { Get-Item -LiteralPath (Join-Path $DataRoot $_) })
} else {
$Stations = @(Get-ChildItem -LiteralPath $DataRoot -Directory | Where-Object {
(Test-Path -LiteralPath (Join-Path $_.FullName "dobject")) -and
(Test-Path -LiteralPath (Join-Path $_.FullName "dobject_recording"))
} | Sort-Object Name)
}
if ($Stations.Count -eq 0) { throw "No station directory containing dobject and dobject_recording was found" }
New-Item -ItemType Directory -Force -Path $OutputRoot | Out-Null
foreach ($Station in $Stations) {
$Out = Join-Path $OutputRoot $Station.Name
Write-Host "[legacy station $($Station.Name)]"
& python $Exporter --dlog $Station.FullName --out $Out --object $LidarObject --format npz `
--timezone $Timezone --stride $Stride --compress --rtk-sidecars --write-reports --resume `
--rtk-max-dt-ms $RtkMaxDtMs
if ($LASTEXITCODE -ne 0) { throw "Export failed for station $($Station.Name)" }
}
Write-Host "Exported stations: $($Stations.Count)"
+89
View File
@@ -0,0 +1,89 @@
param(
[Parameter(Mandatory = $true)][string]$DataRoot,
[Parameter(Mandatory = $true)][string]$OutputRoot,
[Parameter(Mandatory = $true)][string]$RtkCapture,
[Parameter(Mandatory = $true)][string]$ImuCapture,
[string]$LidarObject = "frontlidar",
[string]$Timezone = "+08:00",
[string[]]$StationNames = @(),
[int]$Stride = 1,
[double]$RtkMaxDtMs = 150.0,
[double]$ImuBeforeMs = 100.0,
[double]$ImuAfterMs = 100.0,
[switch]$SkipLidarExport,
[switch]$SkipSerialParsing
)
$ErrorActionPreference = "Stop"
$RepoRoot = Split-Path -Parent $PSScriptRoot
$Exporter = Join-Path $RepoRoot "tools\frontlidar_dlog_export.py"
$Builder = Join-Path $RepoRoot "tools\build_multisensor_npz.py"
$Parser = Join-Path $RepoRoot "tools\rscap_v2\parse_rtk_imu_v2.py"
$Auditor = Join-Path $RepoRoot "tools\rscap_v2\audit_capture_v2.py"
$ExportRoot = Join-Path $OutputRoot "export"
$ParsedRoot = Join-Path $OutputRoot "parsed"
$CombinedRoot = Join-Path $OutputRoot "combined"
function Run-Python {
param([string]$Stage, [string[]]$Arguments)
Write-Host "[$Stage]"
& python @Arguments
if ($LASTEXITCODE -ne 0) {
throw "$Stage failed with Python exit code $LASTEXITCODE"
}
}
foreach ($Path in @($DataRoot, $RtkCapture, $ImuCapture)) {
if (-not (Test-Path -LiteralPath $Path)) { throw "Input does not exist: $Path" }
}
if ($Stride -lt 1) { throw "Stride must be at least 1" }
if ($StationNames.Count -gt 0) {
$Stations = @($StationNames | ForEach-Object { Get-Item -LiteralPath (Join-Path $DataRoot $_) })
} else {
$Stations = @(Get-ChildItem -LiteralPath $DataRoot -Directory | Where-Object {
(Test-Path -LiteralPath (Join-Path $_.FullName "dobject")) -and
(Test-Path -LiteralPath (Join-Path $_.FullName "dobject_recording"))
} | Sort-Object Name)
}
if ($Stations.Count -eq 0) { throw "No station directory containing dobject and dobject_recording was found" }
New-Item -ItemType Directory -Force -Path $OutputRoot | Out-Null
if (-not $SkipSerialParsing) {
New-Item -ItemType Directory -Force -Path $ParsedRoot | Out-Null
Run-Python "capture audit" @($Auditor, $RtkCapture, $ImuCapture, "--out", (Join-Path $OutputRoot "capture_audit.json"))
Run-Python "RTK/IMU parse" @($Parser, "--rtk", $RtkCapture, "--imu", $ImuCapture, "--out", $ParsedRoot)
}
foreach ($Station in $Stations) {
$StationOut = Join-Path $ExportRoot $Station.Name
if (-not $SkipLidarExport) {
Run-Python "LiDAR station $($Station.Name)" @(
$Exporter, "--dlog", $Station.FullName, "--out", $StationOut,
"--object", $LidarObject, "--format", "npz", "--timezone", $Timezone,
"--stride", "$Stride", "--compress", "--skip-rtk", "--write-reports", "--resume"
)
}
if (-not (Test-Path -LiteralPath (Join-Path $StationOut "frames"))) {
throw "Exported frame directory is absent for station $($Station.Name): $StationOut"
}
}
$BuildArgs = @($Builder)
foreach ($Station in $Stations) {
$Frames = Join-Path (Join-Path $ExportRoot $Station.Name) "frames"
$BuildArgs += @("--lidar", "$($Station.Name)=$Frames")
}
$BuildArgs += @(
"--rtk", (Join-Path $ParsedRoot "rtk.jsonl"),
"--imu", (Join-Path $ParsedRoot "imu.jsonl"),
"--out", $CombinedRoot,
"--rtk-max-dt-ms", "$RtkMaxDtMs",
"--imu-before-ms", "$ImuBeforeMs",
"--imu-after-ms", "$ImuAfterMs",
"--overwrite"
)
Run-Python "LiDAR/RTK/IMU association" $BuildArgs
Write-Host "Completed stations: $($Stations.Count)"
Write-Host "Combined NPZ: $CombinedRoot"
+21
View File
@@ -0,0 +1,21 @@
param(
[Parameter(Mandatory = $true)][string]$ExportRoot,
[Parameter(Mandatory = $true)][string]$Output,
[Parameter(Mandatory = $true)][double]$HeadingOffsetDeg,
[Parameter(Mandatory = $true)][double[]]$AntennaLever,
[int]$MinStations = 30,
[int]$ExpectedStations = 0,
[double]$HeadingStdLimitDeg = [double]::PositiveInfinity,
[switch]$Overwrite
)
$ErrorActionPreference = "Stop"
if ($AntennaLever.Count -ne 3) { throw "AntennaLever must contain X,Y,Z in body coordinates" }
$Repo = Split-Path -Parent $PSScriptRoot
$Args = @((Join-Path $Repo "tools\prepare_station_dataset.py"), "--export-root", $ExportRoot,
"--output", $Output, "--heading-offset-deg", "$HeadingOffsetDeg", "--antenna-lever") +
@($AntennaLever | ForEach-Object { "$_" }) + @("--min-stations", "$MinStations",
"--expected-stations", "$ExpectedStations", "--heading-std-limit-deg", "$HeadingStdLimitDeg")
if ($Overwrite) { $Args += "--overwrite" }
& python @Args
if ($LASTEXITCODE -ne 0) { throw "Legacy dataset preparation failed" }
+21
View File
@@ -0,0 +1,21 @@
param(
[Parameter(Mandatory = $true)][string]$CombinedRoot,
[Parameter(Mandatory = $true)][string]$Output,
[Parameter(Mandatory = $true)][double]$HeadingOffsetDeg,
[Parameter(Mandatory = $true)][double[]]$AntennaLever,
[int]$MinStations = 30,
[int]$ExpectedStations = 0,
[double]$HeadingStdLimitDeg = 0.5,
[switch]$Overwrite
)
$ErrorActionPreference = "Stop"
if ($AntennaLever.Count -ne 3) { throw "AntennaLever must contain X,Y,Z in body coordinates" }
$Repo = Split-Path -Parent $PSScriptRoot
$Args = @((Join-Path $Repo "tools\prepare_multisensor_station_dataset.py"), "--combined-root", $CombinedRoot,
"--output", $Output, "--heading-offset-deg", "$HeadingOffsetDeg", "--antenna-lever") +
@($AntennaLever | ForEach-Object { "$_" }) + @("--min-stations", "$MinStations",
"--expected-stations", "$ExpectedStations", "--heading-std-limit-deg", "$HeadingStdLimitDeg")
if ($Overwrite) { $Args += "--overwrite" }
& python @Args
if ($LASTEXITCODE -ne 0) { throw "Multisensor dataset preparation failed" }
+59 -17
View File
@@ -1,32 +1,74 @@
param(
[string]$Batch1Prepared = "C:\Users\admin\Documents\Codex\2026-07-15\wo\outputs\calibration_20260717\prepared",
[string]$Batch2Prepared = "C:\Users\admin\Documents\Codex\2026-07-15\wo\outputs\calibration_data1_20260720\prepared"
[Parameter(Mandatory = $true)][string]$Batch1Prepared,
[Parameter(Mandatory = $true)][string]$Batch2Prepared,
[string]$OutputRoot = ""
)
$ErrorActionPreference = "Stop"
$Repo = Split-Path -Parent $PSScriptRoot
if ([string]::IsNullOrWhiteSpace($OutputRoot)) {
$OutputRoot = Join-Path $Repo "results\01_previous_two_batches"
}
$Code = Join-Path $Repo "code\rigorous_calibration.py"
$Refine = Join-Path $Repo "code\refine_pairs.py"
$Summary = Join-Path $Repo "code\summarize_results.py"
$R = Join-Path $Repo "results"
$B1Frames = Join-Path $Batch1Prepared "frames_all"
$B2Frames = Join-Path $Batch2Prepared "frames_all"
$B1Body = Join-Path $Batch1Prepared "body_poses_rear_gga_raw_rear_to_front.csv"
$B2Body = Join-Path $Batch2Prepared "body_poses_rear_gga_raw_rear_to_front.csv"
python $Code ground --frames $B2Frames --output "$R\common\ground_planes_batch2.csv"
function Run-Python {
param([string]$Stage, [string[]]$Arguments)
Write-Host "[$Stage]"
& python @Arguments
if ($LASTEXITCODE -ne 0) { throw "$Stage failed with Python exit code $LASTEXITCODE" }
}
python $Code pairs --backend small_gicp --frames $B2Frames --body $B2Body --output "$R\small_gicp\B_batch2_estimation.npz" --quality-json "$R\small_gicp\B_batch2_quality.json" --quality-csv "$R\small_gicp\B_batch2_quality.csv"
python $Code pairs --backend open3d --frames $B2Frames --body $B2Body --output "$R\open3d_gicp\B_batch2_estimation.npz" --quality-json "$R\open3d_gicp\B_batch2_quality.json" --quality-csv "$R\open3d_gicp\B_batch2_quality.csv" --max-gap 3 --multistart 1 --iterations 40
python $Refine --pairs "$R\small_gicp\B_batch2_estimation.npz" --quality-json "$R\small_gicp\B_batch2_quality.json" --output "$R\small_gicp\B_batch2_refined.npz"
python $Refine --pairs "$R\open3d_gicp\B_batch2_estimation.npz" --quality-json "$R\open3d_gicp\B_batch2_quality.json" --output "$R\open3d_gicp\B_batch2_refined.npz"
python $Code calibrate --pairs "$R\small_gicp\B_batch2_refined.npz" --ground-planes "$R\common\ground_planes_batch2.csv" --output "$R\small_gicp\extrinsic_batch2_refined.json"
python $Code calibrate --pairs "$R\open3d_gicp\B_batch2_refined.npz" --ground-planes "$R\common\ground_planes_batch2.csv" --output "$R\open3d_gicp\extrinsic_batch2_refined.json"
foreach ($Path in @($B1Frames, $B2Frames, $B1Body, $B2Body)) {
if (-not (Test-Path -LiteralPath $Path)) { throw "Input does not exist: $Path" }
}
$Common = Join-Path $OutputRoot "common"
$Small = Join-Path $OutputRoot "small_gicp"
$Open = Join-Path $OutputRoot "open3d_gicp"
New-Item -ItemType Directory -Force -Path $Common,$Small,$Open | Out-Null
python $Code pairs --backend small_gicp --frames $B1Frames --body $B1Body --output "$R\small_gicp\B_batch1_auxiliary.npz" --quality-json "$R\small_gicp\B_batch1_quality.json" --quality-csv "$R\small_gicp\B_batch1_quality.csv" --max-gap 3 --multistart 1 --iterations 40
python $Code pairs --backend open3d --frames $B1Frames --body $B1Body --output "$R\open3d_gicp\B_batch1_auxiliary.npz" --quality-json "$R\open3d_gicp\B_batch1_quality.json" --quality-csv "$R\open3d_gicp\B_batch1_quality.csv" --max-gap 3 --multistart 1 --iterations 40
python $Refine --pairs "$R\small_gicp\B_batch1_auxiliary.npz" --quality-json "$R\small_gicp\B_batch1_quality.json" --output "$R\small_gicp\B_batch1_auxiliary_refined.npz"
python $Refine --pairs "$R\open3d_gicp\B_batch1_auxiliary.npz" --quality-json "$R\open3d_gicp\B_batch1_quality.json" --output "$R\open3d_gicp\B_batch1_auxiliary_refined.npz"
python $Code validate --pairs "$R\small_gicp\B_batch1_auxiliary_refined.npz" --extrinsic "$R\small_gicp\extrinsic_batch2_refined.json" --output "$R\small_gicp\batch1_auxiliary_check.json"
python $Code validate --pairs "$R\open3d_gicp\B_batch1_auxiliary_refined.npz" --extrinsic "$R\open3d_gicp\extrinsic_batch2_refined.json" --output "$R\open3d_gicp\batch1_auxiliary_check.json"
Run-Python "batch2 ground planes" @($Code, "ground", "--frames", $B2Frames, "--output", (Join-Path $Common "ground_planes_batch2.csv"))
python $Summary --open3d "$R\open3d_gicp\extrinsic_batch2_refined.json" --small "$R\small_gicp\extrinsic_batch2_refined.json" --open3d-quality "$R\open3d_gicp\B_batch2_quality.json" --small-quality "$R\small_gicp\B_batch2_quality.json" --open3d-check "$R\open3d_gicp\batch1_auxiliary_check.json" --small-check "$R\small_gicp\batch1_auxiliary_check.json" --output "$R\comparison_summary.json" --recommended-output "$R\final_extrinsic_recommended.json"
foreach ($Backend in @("small_gicp", "open3d")) {
$Directory = if ($Backend -eq "small_gicp") { $Small } else { $Open }
$Extra = @()
if ($Backend -eq "open3d") { $Extra = @("--max-gap", "3", "--multistart", "1", "--iterations", "40") }
$B2Raw = Join-Path $Directory "B_batch2_estimation.npz"
$B2QualityJson = Join-Path $Directory "B_batch2_quality.json"
$B2QualityCsv = Join-Path $Directory "B_batch2_quality.csv"
Run-Python "$Backend batch2 pairs" (@($Code, "pairs", "--backend", $Backend, "--frames", $B2Frames, "--body", $B2Body,
"--output", $B2Raw, "--quality-json", $B2QualityJson, "--quality-csv", $B2QualityCsv) + $Extra)
$B2Refined = Join-Path $Directory "B_batch2_refined.npz"
Run-Python "$Backend batch2 refinement" @($Refine, "--pairs", $B2Raw, "--quality-json", $B2QualityJson, "--output", $B2Refined)
$Extrinsic = Join-Path $Directory "extrinsic_batch2_refined.json"
Run-Python "$Backend batch2 calibration" @($Code, "calibrate", "--pairs", $B2Refined,
"--ground-planes", (Join-Path $Common "ground_planes_batch2.csv"), "--output", $Extrinsic)
$B1Raw = Join-Path $Directory "B_batch1_auxiliary.npz"
$B1QualityJson = Join-Path $Directory "B_batch1_quality.json"
$B1QualityCsv = Join-Path $Directory "B_batch1_quality.csv"
Run-Python "$Backend batch1 auxiliary pairs" @($Code, "pairs", "--backend", $Backend, "--frames", $B1Frames, "--body", $B1Body,
"--output", $B1Raw, "--quality-json", $B1QualityJson, "--quality-csv", $B1QualityCsv,
"--max-gap", "3", "--multistart", "1", "--iterations", "40")
$B1Refined = Join-Path $Directory "B_batch1_auxiliary_refined.npz"
Run-Python "$Backend batch1 refinement" @($Refine, "--pairs", $B1Raw, "--quality-json", $B1QualityJson, "--output", $B1Refined)
Run-Python "$Backend batch1 auxiliary check" @($Code, "validate", "--pairs", $B1Refined,
"--extrinsic", $Extrinsic, "--output", (Join-Path $Directory "batch1_auxiliary_check.json"))
}
Run-Python "backend summary" @($Summary,
"--open3d", (Join-Path $Open "extrinsic_batch2_refined.json"),
"--small", (Join-Path $Small "extrinsic_batch2_refined.json"),
"--open3d-quality", (Join-Path $Open "B_batch2_quality.json"),
"--small-quality", (Join-Path $Small "B_batch2_quality.json"),
"--open3d-check", (Join-Path $Open "batch1_auxiliary_check.json"),
"--small-check", (Join-Path $Small "batch1_auxiliary_check.json"),
"--output", (Join-Path $OutputRoot "comparison_summary.json"),
"--recommended-output", (Join-Path $OutputRoot "final_extrinsic_recommended.json"))
Write-Host "Two-batch results: $OutputRoot"
+28 -6
View File
@@ -1,12 +1,34 @@
param([string]$ResultRoot = "")
$ErrorActionPreference = "Stop"
$Repo = Split-Path -Parent $PSScriptRoot
if ([string]::IsNullOrWhiteSpace($ResultRoot)) { $ResultRoot = Join-Path $Repo "results\01_previous_two_batches" }
$Code = Join-Path $Repo "code\rigorous_calibration.py"
$Filter = Join-Path $Repo "code\cross_backend_filter.py"
$Finalize = Join-Path $Repo "code\finalize_consensus.py"
$R = Join-Path $Repo "results"
python $Filter --open3d-pairs "$R\open3d_gicp\B_batch2_refined.npz" --small-pairs "$R\small_gicp\B_batch2_refined.npz" --output "$R\consensus\B_batch2_consensus.npz"
python $Filter --open3d-pairs "$R\open3d_gicp\B_batch1_auxiliary_refined.npz" --small-pairs "$R\small_gicp\B_batch1_auxiliary_refined.npz" --output "$R\consensus\B_batch1_consensus.npz" --min-pairs 15
python $Code calibrate --pairs "$R\consensus\B_batch2_consensus.npz" --ground-planes "$R\common\ground_planes_batch2.csv" --output "$R\consensus\extrinsic_batch2_consensus.json"
python $Code validate --pairs "$R\consensus\B_batch1_consensus.npz" --extrinsic "$R\consensus\extrinsic_batch2_consensus.json" --output "$R\consensus\batch1_auxiliary_check.json"
python $Finalize --consensus-extrinsic "$R\consensus\extrinsic_batch2_consensus.json" --consensus-check "$R\consensus\batch1_auxiliary_check.json" --open3d-extrinsic "$R\open3d_gicp\extrinsic_batch2_refined.json" --small-extrinsic "$R\small_gicp\extrinsic_batch2_refined.json" --output "$R\final_extrinsic_recommended.json" --summary "$R\final_summary.json"
function Run-Python {
param([string[]]$Arguments)
& python @Arguments
if ($LASTEXITCODE -ne 0) { throw "Python failed with exit code $LASTEXITCODE" }
}
Run-Python @($Filter, "--open3d-pairs", (Join-Path $ResultRoot "open3d_gicp\B_batch2_refined.npz"),
"--small-pairs", (Join-Path $ResultRoot "small_gicp\B_batch2_refined.npz"),
"--output", (Join-Path $ResultRoot "consensus\B_batch2_consensus.npz"))
Run-Python @($Filter, "--open3d-pairs", (Join-Path $ResultRoot "open3d_gicp\B_batch1_auxiliary_refined.npz"),
"--small-pairs", (Join-Path $ResultRoot "small_gicp\B_batch1_auxiliary_refined.npz"),
"--output", (Join-Path $ResultRoot "consensus\B_batch1_consensus.npz"), "--min-pairs", "15")
Run-Python @($Code, "calibrate", "--pairs", (Join-Path $ResultRoot "consensus\B_batch2_consensus.npz"),
"--ground-planes", (Join-Path $ResultRoot "common\ground_planes_batch2.csv"),
"--output", (Join-Path $ResultRoot "consensus\extrinsic_batch2_consensus.json"))
Run-Python @($Code, "validate", "--pairs", (Join-Path $ResultRoot "consensus\B_batch1_consensus.npz"),
"--extrinsic", (Join-Path $ResultRoot "consensus\extrinsic_batch2_consensus.json"),
"--output", (Join-Path $ResultRoot "consensus\batch1_auxiliary_check.json"))
Run-Python @($Finalize,
"--consensus-extrinsic", (Join-Path $ResultRoot "consensus\extrinsic_batch2_consensus.json"),
"--consensus-check", (Join-Path $ResultRoot "consensus\batch1_auxiliary_check.json"),
"--open3d-extrinsic", (Join-Path $ResultRoot "open3d_gicp\extrinsic_batch2_refined.json"),
"--small-extrinsic", (Join-Path $ResultRoot "small_gicp\extrinsic_batch2_refined.json"),
"--output", (Join-Path $ResultRoot "final_extrinsic_recommended.json"),
"--summary", (Join-Path $ResultRoot "final_summary.json"))
+20 -13
View File
@@ -1,15 +1,22 @@
param([int]$PairIndex = 0)
param(
[int]$PairIndex = 0,
[string]$ResultRoot = ""
)
$ErrorActionPreference = "Stop"
$Repo = Split-Path -Parent $PSScriptRoot
$Code = "$Repo\code\scan_extrinsic_sensitivity.py"
$X = "$Repo\results\final_extrinsic_recommended.json"
$Ground = "$Repo\results\common\ground_planes_batch2.csv"
$Out = "$Repo\results\diagnostics"
if ([string]::IsNullOrWhiteSpace($ResultRoot)) { $ResultRoot = Join-Path $Repo "results\01_previous_two_batches" }
$Code = Join-Path $Repo "code\scan_extrinsic_sensitivity.py"
$X = Join-Path $ResultRoot "final_extrinsic_recommended.json"
$Ground = Join-Path $ResultRoot "common\ground_planes_batch2.csv"
$Out = Join-Path $ResultRoot "diagnostics"
python $Code --pairs "$Repo\results\open3d_gicp\B_batch2_refined.npz" --extrinsic $X --ground-planes $Ground --pair-index $PairIndex --output "$Out\open3d_refined_pair${PairIndex}_left_rpy_scan.json"
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
python $Code --pairs "$Repo\results\small_gicp\B_batch2_refined.npz" --extrinsic $X --ground-planes $Ground --pair-index $PairIndex --output "$Out\small_gicp_refined_pair${PairIndex}_left_rpy_scan.json"
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
python $Code --pairs "$Repo\results\consensus\B_batch2_consensus.npz" --extrinsic $X --ground-planes $Ground --pair-index $PairIndex --output "$Out\consensus_pair${PairIndex}_left_rpy_scan.json"
exit $LASTEXITCODE
foreach ($Backend in @("open3d_gicp", "small_gicp")) {
$Label = if ($Backend -eq "open3d_gicp") { "open3d_refined" } else { "small_gicp_refined" }
& python $Code --pairs (Join-Path $ResultRoot "$Backend\B_batch2_refined.npz") --extrinsic $X `
--ground-planes $Ground --pair-index $PairIndex --output (Join-Path $Out "${Label}_pair${PairIndex}_left_rpy_scan.json")
if ($LASTEXITCODE -ne 0) { throw "$Backend sensitivity scan failed" }
}
& python $Code --pairs (Join-Path $ResultRoot "consensus\B_batch2_consensus.npz") --extrinsic $X `
--ground-planes $Ground --pair-index $PairIndex --output (Join-Path $Out "consensus_pair${PairIndex}_left_rpy_scan.json")
if ($LASTEXITCODE -ne 0) { throw "Consensus sensitivity scan failed" }
+70
View File
@@ -0,0 +1,70 @@
param(
[Parameter(Mandatory = $true)][string]$Prepared,
[Parameter(Mandatory = $true)][string]$OutputRoot,
[string]$PoseName = "rear_gga_raw_rear_to_front",
[double]$BodyHeight = 0.2335,
[int]$MinPairs = 20,
[int]$Bootstrap = 100
)
$ErrorActionPreference = "Stop"
$Repo = Split-Path -Parent $PSScriptRoot
$Code = Join-Path $Repo "code\rigorous_calibration.py"
$Refine = Join-Path $Repo "code\refine_pairs.py"
$Consensus = Join-Path $Repo "code\cross_backend_filter.py"
$Frames = Join-Path $Prepared "frames_all"
$Body = Join-Path $Prepared "body_poses_$PoseName.csv"
$Common = Join-Path $OutputRoot "common"
$Open = Join-Path $OutputRoot "open3d_gicp"
$Small = Join-Path $OutputRoot "small_gicp"
$ConsensusOut = Join-Path $OutputRoot "consensus"
function Run-Python {
param([string]$Stage, [string[]]$Arguments)
Write-Host "[$Stage]"
& python @Arguments
if ($LASTEXITCODE -ne 0) { throw "$Stage failed with Python exit code $LASTEXITCODE" }
}
foreach ($Path in @($Frames, $Body)) {
if (-not (Test-Path -LiteralPath $Path)) { throw "Input does not exist: $Path" }
}
New-Item -ItemType Directory -Force -Path $Common,$Open,$Small,$ConsensusOut | Out-Null
$Ground = Join-Path $Common "ground_planes.csv"
Run-Python "ground planes" @($Code, "ground", "--frames", $Frames, "--output", $Ground)
foreach ($Backend in @("small_gicp", "open3d")) {
$Directory = if ($Backend -eq "small_gicp") { $Small } else { $Open }
$Raw = Join-Path $Directory "B_estimation.npz"
$QualityJson = Join-Path $Directory "B_quality.json"
$QualityCsv = Join-Path $Directory "B_quality.csv"
$PairArgs = @($Code, "pairs", "--backend", $Backend, "--frames", $Frames, "--body", $Body,
"--output", $Raw, "--quality-json", $QualityJson, "--quality-csv", $QualityCsv,
"--min-pairs", "$MinPairs")
if ($Backend -eq "open3d") { $PairArgs += @("--max-gap", "3", "--multistart", "1", "--iterations", "40") }
Run-Python "$Backend pairs" $PairArgs
Run-Python "$Backend X-independent refinement" @(
$Refine, "--pairs", $Raw, "--quality-json", $QualityJson,
"--output", (Join-Path $Directory "B_refined.npz"), "--min-pairs", "$MinPairs"
)
Run-Python "$Backend calibration" @(
$Code, "calibrate", "--pairs", (Join-Path $Directory "B_refined.npz"),
"--ground-planes", $Ground, "--body-height", "$BodyHeight",
"--bootstrap", "$Bootstrap", "--output", (Join-Path $Directory "extrinsic.json")
)
}
$ConsensusPairs = Join-Path $ConsensusOut "B_consensus.npz"
Run-Python "cross-backend consensus" @(
$Consensus, "--open3d-pairs", (Join-Path $Open "B_refined.npz"),
"--small-pairs", (Join-Path $Small "B_refined.npz"),
"--output", $ConsensusPairs, "--min-pairs", "$MinPairs"
)
Run-Python "consensus calibration" @(
$Code, "calibrate", "--pairs", $ConsensusPairs, "--ground-planes", $Ground,
"--body-height", "$BodyHeight", "--bootstrap", "$Bootstrap",
"--output", (Join-Path $ConsensusOut "extrinsic.json")
)
Write-Host "Calibration results: $OutputRoot"
-14
View File
@@ -1,14 +0,0 @@
param(
[int]$PairIndex = 0,
[string]$Frames = "C:\Users\admin\Documents\Codex\2026-07-15\wo\outputs\calibration_data1_20260720\prepared\frames_all",
[double]$LeftRollDeg = 0.0,
[double]$LeftPitchDeg = 0.0,
[double]$LeftYawDeg = 0.0
)
$Repo = Split-Path -Parent $PSScriptRoot
python "$Repo\code\visualize_pair_3d.py" `
--frames $Frames `
--pairs "$Repo\results\open3d_gicp\B_batch2_refined.npz" `
--extrinsic "$Repo\results\final_extrinsic_recommended.json" `
--pair-index $PairIndex `
--left-rpy-deg $LeftRollDeg $LeftPitchDeg $LeftYawDeg
+19
View File
@@ -0,0 +1,19 @@
param(
[Parameter(Mandatory = $true)][string]$Frames,
[Parameter(Mandatory = $true)][string]$Pairs,
[Parameter(Mandatory = $true)][string]$Extrinsic,
[int]$PairIndex = 0,
[double]$LeftRollDeg = 0.0,
[double]$LeftPitchDeg = 0.0,
[double]$LeftYawDeg = 0.0
)
$ErrorActionPreference = "Stop"
$Repo = Split-Path -Parent $PSScriptRoot
foreach ($Path in @($Frames, $Pairs, $Extrinsic)) {
if (-not (Test-Path -LiteralPath $Path)) { throw "Input does not exist: $Path" }
}
& python (Join-Path $Repo "code\visualize_pair_3d.py") `
--frames $Frames --pairs $Pairs --extrinsic $Extrinsic --pair-index $PairIndex `
--left-rpy-deg $LeftRollDeg $LeftPitchDeg $LeftYawDeg
if ($LASTEXITCODE -ne 0) { throw "Visualization failed with Python exit code $LASTEXITCODE" }
-18
View File
@@ -1,18 +0,0 @@
param(
[int]$PairIndex = 0,
[string]$Frames = "C:\Users\admin\Documents\Codex\2026-07-15\wo\outputs\calibration_data1_20260720\prepared\frames_all",
[string]$Extrinsic = "",
[double]$LeftRollDeg = 0.0,
[double]$LeftPitchDeg = 0.0,
[double]$LeftYawDeg = 0.0
)
$Repo = Split-Path -Parent $PSScriptRoot
if ([string]::IsNullOrWhiteSpace($Extrinsic)) {
$Extrinsic = "$Repo\results\small_gicp\extrinsic_batch2_refined.json"
}
python "$Repo\code\visualize_pair_3d.py" `
--frames $Frames `
--pairs "$Repo\results\small_gicp\B_batch2_refined.npz" `
--extrinsic $Extrinsic `
--pair-index $PairIndex `
--left-rpy-deg $LeftRollDeg $LeftPitchDeg $LeftYawDeg