Skip to content

fix(autoware_multi_object_tracker): tracker update path, shape gating, and association data structure#12560

Draft
technolojin wants to merge 7 commits intoautowarefoundation:mainfrom
technolojin:fix/mot/tracker-update-process
Draft

fix(autoware_multi_object_tracker): tracker update path, shape gating, and association data structure#12560
technolojin wants to merge 7 commits intoautowarefoundation:mainfrom
technolojin:fix/mot/tracker-update-process

Conversation

@technolojin
Copy link
Copy Markdown
Contributor

@technolojin technolojin commented May 8, 2026

Description

Bug Fixes

1. shapes.cppconvertConvexHullToBoundingBox zeroed every object's height

convertConvexHullToBoundingBox was tracking min_z/max_z over the footprint points and writing max_z - min_z into dimensions.z.
Footprint points are 2D (z = 0 always), so this silently set every converted object's height to zero.

Fix: Removed the z-axis scan entirely. The output dimensions.z is now left untouched so the caller's upstream value is preserved.

2. vehicle_tracker.cppmeasureWithPose gradually shrank tracked vehicle length for cluster inputs

Shape update was gated only on shape.type == BOUNDING_BOX. Cluster measurements with trust_extension = false are converted to bounding boxes in baselink frame with unreliable dimensions. These were being fed into the EKF length update, causing the tracked vehicle length to drift smaller over time.

Fix: Added can_update_shape = channel_info.trust_extension && is_bbox guard. When can_update_shape is false, shape update is skipped and the EKF length input is taken from motion_model_.getLength() (the current state estimate) rather than the noisy measurement.

3. vehicle_tracker.cppdetermineUpdateStrategy alignment threshold was too tight for large vehicles and asymmetric for size-mismatched objects

The alignment threshold was 0.09 * predicted_length (ratio-only). For a 12 m truck the tolerance was ~1.1 m, which caused spurious WEAK_UPDATE fallbacks when the vehicle was decelerating. Additionally, comparing against predicted_length alone was asymmetric when measurement and prediction sizes differed.

Fix:

  • Ratio raised from 9 % to 20 % (ALIGNMENT_RATIO_THRESHOLD = 0.2).
  • Reference length changed from predicted_length to max(predicted_length, measured_length) so that size-mismatched cases are handled symmetrically.
  • Added a 1.0 m absolute floor (ALIGNMENT_ABSOLUTE_THRESHOLD = 1.0) to prevent the threshold from collapsing for small objects.
  • Combined formula: threshold = max(0.2 * max_length, 1.0).

4. vehicle_tracker.cppconditionedUpdate computed wrong edge gaps for cluster inputs

Cluster bounding boxes arrive in baselink frame (orientation ≈ ego heading). The edge-alignment logic in determineUpdateStrategy assumed the measurement is oriented in the tracker's heading frame, so near-face distances were computed incorrectly.

Fix: Added alignClusterToTrackerOrientation(). Before calling determineUpdateStrategy, the cluster's polygon footprint is re-projected onto the tracker's current yaw. The aligned object has its pose and dimensions expressed in the tracker's heading frame, so all edge-center calculations become frame-consistent.


Refactoring

1. UpdatePath enum + selectUpdatePath() virtual dispatch (tracker_base, vehicle_tracker, multiple_vehicle_tracker)

updateWithMeasurement in tracker_base.cpp previously selected between update strategies with an opaque if (!has_significant_shape_change) / else tree. The branch structure conflated two independent decisions (shape stability and channel trust), making the logic hard to follow and override in subclasses.

Change: Introduced enum class UpdatePath { NORMAL, TRY_EXTENSION, CONDITIONED } and a virtual selectUpdatePath(trust_extension, has_significant_shape_change) method on Tracker. The base implementation returns NORMAL. VehicleTracker and MultipleVehicleTracker override to return CONDITIONED when !trust_extension (clusters always skip the shape filter) and TRY_EXTENSION when has_significant_shape_change. The updateWithMeasurement body becomes a clean three-branch dispatch.

2. TrackerBevEntry struct (bev_association.hpp / bev_association.cpp)

PreparationData previously held four parallel vectors (tracked_objects, tracker_labels, tracker_types, tracker_inverse_covariances). Keeping these in sync was fragile; the inverse-covariance vector was also filled in a second loop over tracked_objects.

Change: Introduced struct TrackerBevEntry { object, label, type, inv_cov } and collapsed PreparationData to a single std::vector<TrackerBevEntry> trackers. The preparation loop now fills all four fields in one pass (inverse covariance is computed immediately after the object is extracted), eliminating both the second loop and the parallel-index bookkeeping.

3. ScoringResult struct (scoring_types.hpp, bev_assignment_scoring.hpp/.cpp)

calculateBevAssignmentScore returned the score as a double and communicated has_significant_shape_change via a non-const reference output parameter — an error-prone calling convention.

Change: Added a new header scoring_types.hpp with struct ScoringResult { double score; bool has_significant_shape_change; }. calculateBevAssignmentScore now returns ScoringResult by value. All early-return gates return {INVALID_SCORE, false}. Call sites read result.score and result.has_significant_shape_change directly.


Files Changed

File Change
lib/object_model/shapes.cpp Bug fix: remove spurious z-dim computation in convertConvexHullToBoundingBox
lib/tracker/model/vehicle_tracker.cpp Bug fix: can_update_shape guard, alignClusterToTrackerOrientation, updated alignment thresholds
lib/tracker/model/tracker_base.cpp Refactor: updateWithMeasurement → named UpdatePath dispatch
lib/association/bev_association.cpp Refactor: PreparationData → single-pass TrackerBevEntry vector
lib/association/scoring/bev_assignment_scoring.cpp Refactor: return ScoringResult instead of bool & out-param
include/.../tracker_base.hpp Add UpdatePath enum, selectUpdatePath virtual
include/.../vehicle_tracker.hpp Add selectUpdatePath override, updated thresholds, alignClusterToTrackerOrientation
include/.../multiple_vehicle_tracker.hpp Add selectUpdatePath override
include/.../bev_association.hpp Add TrackerBevEntry; collapse PreparationData
include/.../bev_assignment_scoring.hpp Change return type to ScoringResult
include/.../scoring_types.hpp New file: ScoringResult struct

Related links

#12475 will base this PR

Parent Issue:

  • Link

How was this PR tested?

using modified perception pipeline https://github.com/technolojin/autoware_launch/tree/feat/mot/association-polar to input polygon shape detections.

Notes for reviewers

None.

Interface changes

None.

Effects on system behavior

None.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 8, 2026

Thank you for contributing to the Autoware project!

🚧 If your pull request is in progress, switch it to draft mode.

Please ensure:

@github-actions github-actions Bot added the component:perception Advanced sensor data processing and environment understanding. (auto-assigned) label May 8, 2026
@technolojin technolojin added the run:build-and-test-differential Mark to enable build-and-test-differential workflow. (used-by-ci) label May 8, 2026
@codecov
Copy link
Copy Markdown

codecov Bot commented May 8, 2026

Codecov Report

❌ Patch coverage is 40.65934% with 54 lines in your changes missing coverage. Please review.
✅ Project coverage is 42.30%. Comparing base (54af299) to head (b69ebd7).

Files with missing lines Patch % Lines
...ject_tracker/lib/tracker/model/vehicle_tracker.cpp 27.27% 29 Missing and 3 partials ⚠️
...object_tracker/lib/association/bev_association.cpp 40.00% 0 Missing and 12 partials ⚠️
..._object_tracker/lib/tracker/model/tracker_base.cpp 28.57% 4 Missing and 1 partial ⚠️
...i_object_tracker/tracker/model/vehicle_tracker.hpp 0.00% 3 Missing ⚠️
...lti_object_tracker/association/bev_association.hpp 0.00% 0 Missing and 1 partial ⚠️
...tracker/tracker/model/multiple_vehicle_tracker.hpp 66.66% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##             main   #12560       +/-   ##
===========================================
+ Coverage   18.64%   42.30%   +23.66%     
===========================================
  Files        1918       58     -1860     
  Lines      131362     3477   -127885     
  Branches    44502     1218    -43284     
===========================================
- Hits        24489     1471    -23018     
+ Misses      86760     1622    -85138     
+ Partials    20113      384    -19729     
Flag Coverage Δ
daily ?
full-suite 42.30% <40.65%> (+23.66%) ⬆️

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

… and scoring logic

- Introduced `TrackerBevEntry` struct to bundle precomputed data for each tracker, simplifying the `PreparationData` structure.
- Updated `calculateBevAssignmentScore` to return a `ScoringResult` struct, encapsulating both score and shape change status.
- Refactored `BevAssociation` to utilize the new structures, improving clarity and maintainability.
- Enhanced `selectUpdatePath` logic in tracker models to streamline update strategies based on shape change and trust conditions.

This refactor aims to improve the organization of data and scoring mechanisms within the multi-object tracking system.

Signed-off-by: Taekjin LEE <taekjin.lee@tier4.jp>
…method

- Clarified comments in the `selectUpdatePath` method of `tracker_base.hpp` to enhance understanding of the update path selection logic based on shape change and trust conditions.
- Adjusted formatting for better readability and consistency with existing documentation.

This change aims to improve code maintainability and facilitate easier onboarding for new developers.

Signed-off-by: Taekjin LEE <taekjin.lee@tier4.jp>
…arity and consistency

- Refactored the `selectUpdatePath` method in `multiple_vehicle_tracker.hpp`, `vehicle_tracker.hpp`, and `tracker_base.hpp` to use `trust_extension` instead of `channel_info.trust_extension`, improving clarity in the update path selection logic.
- Adjusted the logic to return `TRY_EXTENSION` based on the `has_significant_shape_change` condition, enhancing the decision-making process for update paths.
- Removed the old implementation of `selectUpdatePath` in `tracker_base.cpp` to streamline the codebase.

These changes aim to improve the maintainability and readability of the multi-object tracking system.

Signed-off-by: Taekjin LEE <taekjin.lee@tier4.jp>
…conditionedUpdate

- Updated the logic in the `conditionedUpdate` method to ensure that the bounding box orientation is correctly handled for cluster measurements.
- Improved the condition for aligning the cluster to the tracker's orientation by checking for polygon shape type and non-empty footprint points.

These changes aim to enhance the accuracy of the vehicle tracking system's update strategy.

Signed-off-by: Taekjin LEE <taekjin.lee@tier4.jp>
@technolojin technolojin force-pushed the fix/mot/tracker-update-process branch from a218717 to 335d917 Compare May 8, 2026 07:34
Signed-off-by: Taekjin LEE <taekjin.lee@tier4.jp>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the multi-object tracker’s vehicle update logic and BEV association plumbing to (1) avoid corrupting vehicle shape estimates from untrusted cluster measurements, and (2) simplify/refactor association and update-path handling.

Changes:

  • Fix vehicle EKF/shape update behavior by gating shape updates on trustworthy bbox measurements and adding cluster-to-tracker orientation alignment for conditioned updates.
  • Refactor tracker update flow with a new UpdatePath selection hook and named update paths (NORMAL / TRY_EXTENSION / CONDITIONED).
  • Refactor BEV association preparation/scoring by consolidating tracker-side precomputed data into a single struct and returning a ScoringResult from the scoring function.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
perception/autoware_multi_object_tracker/lib/tracker/model/vehicle_tracker.cpp Shape gating for EKF length input; adds cluster footprint re-projection for conditioned edge alignment; adds absolute alignment threshold.
perception/autoware_multi_object_tracker/lib/tracker/model/tracker_base.cpp Refactors updateWithMeasurement() to use UpdatePath selection and clearer control flow.
perception/autoware_multi_object_tracker/lib/object_model/shapes.cpp Prevents zeroing object height when converting convex hull footprint to bbox.
perception/autoware_multi_object_tracker/lib/association/scoring/bev_assignment_scoring.cpp Changes scoring API to return ScoringResult and removes output parameter.
perception/autoware_multi_object_tracker/lib/association/bev_association.cpp Consolidates per-tracker precomputed data into TrackerBevEntry and adapts to ScoringResult.
perception/autoware_multi_object_tracker/include/autoware/multi_object_tracker/tracker/model/vehicle_tracker.hpp Adds selectUpdatePath() override and alignment threshold constants; declares cluster alignment helper.
perception/autoware_multi_object_tracker/include/autoware/multi_object_tracker/tracker/model/tracker_base.hpp Introduces UpdatePath enum and virtual selectUpdatePath().
perception/autoware_multi_object_tracker/include/autoware/multi_object_tracker/tracker/model/multiple_vehicle_tracker.hpp Adds selectUpdatePath() override consistent with vehicle trackers.
perception/autoware_multi_object_tracker/include/autoware/multi_object_tracker/association/scoring/scoring_types.hpp Adds ScoringResult type for assignment scoring.
perception/autoware_multi_object_tracker/include/autoware/multi_object_tracker/association/scoring/bev_assignment_scoring.hpp Updates scoring API to return ScoringResult and includes new types header.
perception/autoware_multi_object_tracker/include/autoware/multi_object_tracker/association/bev_association.hpp Adds TrackerBevEntry and consolidates PreparationData.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread perception/autoware_multi_object_tracker/lib/tracker/model/vehicle_tracker.cpp Outdated
@technolojin technolojin marked this pull request as draft May 8, 2026 08:19
…rement alignment logic

- Removed the comment regarding the bicycle model's ownership of shape, as it was deemed unnecessary.
- Simplified the logic in the `conditionedUpdate` method to directly check for non-empty footprint points, enhancing clarity in the measurement alignment process.

These changes aim to improve code readability and maintainability in the vehicle tracking system.

Signed-off-by: Taekjin LEE <taekjin.lee@tier4.jp>
…easurement handling

- Increased the alignment ratio threshold from 9% to 15% of the larger object's length to enhance flexibility in alignment checks.
- Reduced the absolute alignment threshold from 3.0m to 1.0m for small objects, allowing for better handling of size-mismatch cases.
- Updated the alignment logic to use the maximum length between predicted and measured dimensions, ensuring symmetrical handling of different object sizes.

Signed-off-by: Taekjin LEE <taekjin.lee@tier4.jp>
@technolojin technolojin requested a review from linick-kang May 8, 2026 08:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

component:perception Advanced sensor data processing and environment understanding. (auto-assigned) run:build-and-test-differential Mark to enable build-and-test-differential workflow. (used-by-ci)

Projects

Status: To Triage

Development

Successfully merging this pull request may close these issues.

2 participants