算法更新: delivery v1.2.1、平整度v1.5、测距v2.2、整车配准v1.3 适配器: vehicle-registration 新增、各算法 manifest 和 adapter 更新 后端: taskCadFiles/source 字段迁移、derivedPointClouds 注册、取消任务联动 前端: ElapsedTime 时长显示、两步算法流程、canRun 逻辑修复 文档: 新增5份算法性能分析报告
200 lines
6.2 KiB
Python
200 lines
6.2 KiB
Python
"""Command-line entry point installed by ``pyproject.toml``.
|
|
|
|
The DEFAULT mode is single-beam measurement: the ROI(s) already isolate one
|
|
beam each, the cloud is cropped and measured directly (no registration, no
|
|
dual-beam tracking). Provide ``--roi`` for one beam, or ``--left-roi`` and
|
|
``--right-roi`` to measure both in one invocation.
|
|
|
|
The legacy dual-beam pipeline (registration + left/right tracking on a
|
|
car-bottom slab) is still available via ``--mode dual``.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
|
|
|
|
def parse_args() -> argparse.Namespace:
|
|
parser = argparse.ArgumentParser(
|
|
description="Measure underframe longitudinal beam deflection from a point cloud.",
|
|
)
|
|
parser.add_argument(
|
|
"--mode",
|
|
default="single",
|
|
choices=["single", "dual"],
|
|
help="'single' (default): ROI isolates one beam, measure directly. "
|
|
"'dual': legacy car-bottom slab with left+right tracking + registration.",
|
|
)
|
|
parser.add_argument(
|
|
"--input-cloud",
|
|
required=True,
|
|
help="Path to input scan point cloud (.ply or .xyz). Large binary PLYs "
|
|
"are stream-cropped by the ROI in single mode.",
|
|
)
|
|
parser.add_argument(
|
|
"--out-dir",
|
|
required=True,
|
|
help="Output directory for report.json/.xlsx, CSV, and PNG.",
|
|
)
|
|
# --- single mode ---
|
|
parser.add_argument(
|
|
"--roi",
|
|
default=None,
|
|
help="Single mode: ROI JSON isolating ONE beam (native frame "
|
|
"x=length, y=height, z=width).",
|
|
)
|
|
parser.add_argument(
|
|
"--left-roi",
|
|
default=None,
|
|
help="Single mode: ROI JSON for the left beam (use with --right-roi).",
|
|
)
|
|
parser.add_argument(
|
|
"--right-roi",
|
|
default=None,
|
|
help="Single mode: ROI JSON for the right beam (use with --left-roi).",
|
|
)
|
|
parser.add_argument(
|
|
"--side",
|
|
default=None,
|
|
help="Single mode label for --roi (left/right); inferred from the ROI's "
|
|
"lateral z (x-forward: z>0 left, z<0 right) if omitted.",
|
|
)
|
|
parser.add_argument(
|
|
"--tolerance",
|
|
type=float,
|
|
default=None,
|
|
help="Single mode --roi: pass/fail tolerance in mm. Default by side "
|
|
"(left 7, right 12).",
|
|
)
|
|
parser.add_argument(
|
|
"--left-tolerance",
|
|
type=float,
|
|
default=None,
|
|
help="Both-beam mode: left-beam tolerance in mm (default 7).",
|
|
)
|
|
parser.add_argument(
|
|
"--right-tolerance",
|
|
type=float,
|
|
default=None,
|
|
help="Both-beam mode: right-beam tolerance in mm (default 12).",
|
|
)
|
|
parser.add_argument(
|
|
"--enable-registration",
|
|
action="store_true",
|
|
help="Single mode: rigidly align the cloud to --cad before measuring. "
|
|
"Default OFF (cloud assumed already registered). Requires --cad as a "
|
|
"sampled .ply/.stl/.obj (.stp must be converted first).",
|
|
)
|
|
# --- shared ---
|
|
parser.add_argument(
|
|
"--config",
|
|
default=None,
|
|
help="Optional JSON config override file.",
|
|
)
|
|
parser.add_argument(
|
|
"--skip-excel",
|
|
action="store_true",
|
|
help="Skip writing the .xlsx report.",
|
|
)
|
|
parser.add_argument(
|
|
"--skip-plot",
|
|
action="store_true",
|
|
help="Single mode: skip the PNG plot.",
|
|
)
|
|
# --- dual (legacy) mode ---
|
|
parser.add_argument(
|
|
"--cad",
|
|
default=None,
|
|
help="Dual mode: CAD reference (.ply/.xyz/.stl/.obj) for registration.",
|
|
)
|
|
parser.add_argument(
|
|
"--profile",
|
|
default="auto",
|
|
choices=["auto", "M", "TC", "TP", "custom"],
|
|
help="Dual mode: profile for scale-related tuning.",
|
|
)
|
|
parser.add_argument(
|
|
"--skip-registration",
|
|
action="store_true",
|
|
help="Dual mode: bypass ICP even when --cad is supplied.",
|
|
)
|
|
parser.add_argument(
|
|
"--no-bilateral",
|
|
action="store_true",
|
|
help="Dual mode: disable bilateral denoising.",
|
|
)
|
|
parser.add_argument(
|
|
"--input-axis",
|
|
default="y_up",
|
|
choices=["z_up", "y_up"],
|
|
help="Dual mode: height axis convention (default y_up).",
|
|
)
|
|
return parser.parse_args()
|
|
|
|
|
|
def _load_config(path):
|
|
if not path:
|
|
return None
|
|
import json
|
|
from pathlib import Path
|
|
return json.loads(Path(path).read_text(encoding="utf-8"))
|
|
|
|
|
|
def main() -> None:
|
|
args = parse_args()
|
|
|
|
if args.mode == "single":
|
|
from .single_beam_pipeline import run_single_beam_pipeline, run_both_beams
|
|
config = _load_config(args.config)
|
|
if args.left_roi and args.right_roi:
|
|
run_both_beams(
|
|
input_cloud=args.input_cloud,
|
|
left_roi=args.left_roi,
|
|
right_roi=args.right_roi,
|
|
out_dir=args.out_dir,
|
|
config=config,
|
|
cad_path=args.cad,
|
|
enable_registration=args.enable_registration,
|
|
left_tolerance_mm=args.left_tolerance,
|
|
right_tolerance_mm=args.right_tolerance,
|
|
skip_excel=args.skip_excel,
|
|
skip_plot=args.skip_plot,
|
|
)
|
|
elif args.roi:
|
|
run_single_beam_pipeline(
|
|
input_cloud=args.input_cloud,
|
|
roi_path=args.roi,
|
|
out_dir=args.out_dir,
|
|
side=args.side,
|
|
tolerance_mm=args.tolerance,
|
|
config=config,
|
|
cad_path=args.cad,
|
|
enable_registration=args.enable_registration,
|
|
skip_excel=args.skip_excel,
|
|
skip_plot=args.skip_plot,
|
|
)
|
|
else:
|
|
raise SystemExit(
|
|
"single mode requires --roi (one beam) or both --left-roi and --right-roi."
|
|
)
|
|
return
|
|
|
|
# dual (legacy) mode
|
|
from .pipeline import run_measurement_pipeline
|
|
run_measurement_pipeline(
|
|
input_cloud=args.input_cloud,
|
|
out_dir=args.out_dir,
|
|
config_path=args.config,
|
|
profile=args.profile,
|
|
cad_path=args.cad,
|
|
roi_path=args.roi,
|
|
skip_registration=args.skip_registration,
|
|
enable_bilateral=not args.no_bilateral,
|
|
skip_excel=args.skip_excel,
|
|
input_axis=args.input_axis,
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|