4.7 KiB
- Implemented core alignment utilities in aruco/alignment.py.
- Used Rodrigues' rotation formula for vector alignment with explicit handling for parallel and anti-parallel cases.
- Implemented
FACE_MARKER_MAPandget_face_normal_from_geometryto support multi-marker face normal averaging. - Implemented
detect_ground_faceusing dot-product scoring against camera up-vector withlogurudebug logging. - Integrated ground-plane alignment into
calibrate_extrinsics.pywith CLI-toggled heuristic and explicit face/marker selection.
SVO Directory Expansion
- Implemented directory expansion for
--svoargument. - Iterates through provided paths, checks if directory, and finds
.svoand.svo2files. - Maintains backward compatibility for single file paths.
- Sorts found files to ensure deterministic processing order.
ArUco Dictionary Selection
- Added
--aruco-dictionaryCLI option mapping string names tocv2.arucoconstants. - Defaults to
DICT_4X4_50but supports all standard dictionaries including AprilTags. - Passed to
create_detectorto allow flexibility for different marker sets.
Minimum Markers Configuration
- Added
--min-markersCLI option (default 1). - Passed to
estimate_pose_from_detectionsto filter out poses with insufficient marker support. - Useful for improving robustness or allowing single-marker poses when necessary.
Logging Improvements
- Added
logurudebug logs for:- Number of detected markers per frame.
- Pose acceptance/rejection with specific reasons (reprojection error, marker count).
Dynamic Face Mapping
- Implemented
load_face_mappinginaruco/marker_geometry.pyto read face definitions from parquet metadata. - Parquet file must contain
name(string) andids(list of ints) columns. calibrate_extrinsics.pynow loads this map at runtime and passes it to alignment functions.aruco/alignment.pyfunctions (get_face_normal_from_geometry,detect_ground_face) now accept an optionalface_marker_mapargument.
Strict Data-Driven Alignment
-
Removed implicit fallback to
FACE_MARKER_MAPinaruco/alignment.py. -
calibrate_extrinsics.pynow explicitly checks for loaded face mapping. -
If mapping is missing (e.g., old parquet without
name/ids), alignment is skipped with a warning instead of using hardcoded defaults. -
This enforces the requirement that ground alignment configuration must come from the marker definition file.
-
Alignment tests verify that
rotation_align_vectorscorrectly handles identity, 90-degree, and anti-parallel cases. -
detect_ground_faceandget_face_normal_from_geometryare now data-driven, requiring an explicitface_marker_mapat runtime. -
Unit tests use mock geometry to verify normal computation and face selection logic without requiring real SVO/parquet data.
-
Parquet Schema: The marker configuration parquet file (
standard_box_markers_600mm.parquet) uses a schema withname(string),ids(list), andcorners(list<list<list>>). -
Dual Loading Strategy: The system loads this single file in two ways:
load_marker_geometry: Flattensidsandcornersto build a global map of Marker ID -> 3D Corners.load_face_mapping: Usesnameandidsto group markers by face (e.g., "bottom"), which is critical for ground plane alignment.
Runtime Stability
- Fixed
AttributeError: 'FrameData' object has no attribute 'confidence_map'by explicitly adding it to the dataclass and populating it inSVOReader. - Added
--debugflag to control log verbosity, defaulting to cleaner INFO level output.
Consistency Hardening
- Removed "using default fallback" messaging from
calibrate_extrinsics.pyto align with the strict data-driven requirement.
Fast Iteration
- Added
--max-samplesCLI option tocalibrate_extrinsics.pyto allow processing a limited number of samples (e.g., 1 or 3) instead of the full SVO.
Test Configuration
- Configured
pytestinpyproject.tomlto explicitly target thetests/directory and ignoreloguru,tmp, andlibs.
Debug Visibility
Documentation
Type Annotation Hardening
- Integrated
jaxtypingfor shape-aware array annotations (e.g.,Float[np.ndarray, "4 4"]). - Used
TYPE_CHECKINGblocks to define these aliases, ensuring they are available for static analysis (likebasedpyright) while falling back to standardnp.ndarrayat runtime ifjaxtypingbackends are missing.
Depth Units
- ZED SDK
retrieve_measure(sl.MEASURE.DEPTH)returns values in the unit defined inInitParameters.coordinate_units. - The default unit is
MILLIMETER. - Since our extrinsics and marker geometry are in meters, we must explicitly convert the retrieved depth map to meters (divide by 1000.0) to avoid massive scale mismatches during verification and refinement.