Checklist
Description
In perception/autoware_multi_object_tracker/include/autoware/multi_object_tracker/object_model/object_model.hpp, four of the six object models set the initial longitudinal velocity covariance to an effectively unbounded value:
| Object model |
initial_covariance.vel_long |
implied prior stddev |
same model's process_limit.vel_long_max |
GeneralVehicle (line 158) |
sq(kmph2mps(1000.0)) |
277.8 m/s |
38.9 m/s (140 km/h) |
NormalVehicle (line 204) |
sq(kmph2mps(1000.0)) |
277.8 m/s |
38.9 m/s (140 km/h) |
BigVehicle (line 250) |
sq(kmph2mps(1000.0)) |
277.8 m/s |
38.9 m/s (140 km/h) |
Bicycle (line 296) |
sq(kmph2mps(1000.0)) |
277.8 m/s |
33.3 m/s (120 km/h) |
Pedestrian (line 342) |
sq(kmph2mps(120.0)) |
33.3 m/s |
27.8 m/s (100 km/h) |
(Line numbers are against main at 1c93b65555410c8c7b8299dab2f48320d1cb19e4.)
The prior standard deviation on the velocity state of a newly born vehicle or bicycle track is therefore 1000 km/h, roughly 7x to 8x the same model's own hard process_limit.vel_long_max, and far outside anything the motion model will subsequently allow. It is a flat, uninformative prior standing in for "no prior information at all" rather than a plausibility prior.
The Pedestrian model in the same file and the same switch statement already uses a finite prior for the identical field, so a bounded plausibility prior on this state is established design in this file. The vehicle and bicycle models are the outlier, not a new constraint being introduced.
This value is compiled in. There is no parameter in perception/autoware_multi_object_tracker/config/ that overrides initial_covariance, so no deployment can tune around it.
Expected behavior
At track birth, initial_covariance.vel_long for the vehicle and bicycle object models should express a finite, physically plausible prior on the object's longitudinal speed, consistent with each model's own process_limit.vel_long_max and with the Pedestrian model's existing use of the same field. The first measurement update should then be able to move the velocity estimate but not be able to set it to an arbitrary value that the same object model would reject as out of limits one timestep later.
Actual behavior
The prior is unbounded in practice, and the consequence is concentrated entirely in the first update after track creation.
The consumer is perception/autoware_multi_object_tracker/lib/tracker/trackers/vehicle_tracker.cpp, line 134:
double vel_x = 0.0;
double vel_y = 0.0;
double vel_x_cov = object_model_.initial_covariance.vel_long;
double vel_y_cov = object_model_.bicycle_state.init_slip_angle_cov;
if (object.kinematics.has_twist) {
vel_x = object.twist.linear.x;
vel_y = object.twist.linear.y;
}
if (object.kinematics.has_twist_covariance) {
vel_x_cov = object.twist_covariance[XYZRPY_COV_IDX::X_X];
vel_y_cov = object.twist_covariance[XYZRPY_COV_IDX::Y_Y];
}
initial_covariance.vel_long is the fallback used whenever the incoming detection carries no twist covariance, which is the normal case for lidar-only and camera-lidar-fusion detection outputs that report shape and pose but not a measured velocity with uncertainty. All four affected models reach this code path: GeneralVehicle, NormalVehicle, BigVehicle and Bicycle are all constructed as VehicleTracker in src/processor/processor.cpp (lines 177 to 187), and the Bicycle model also covers motorcycles.
The state is therefore initialized at vel_x = 0.0 with a 277.8 m/s prior standard deviation on it. On the first EKF update the Kalman gain for the velocity state scales with P / (P + R). With P five to six orders of magnitude larger than any plausible R on the implied velocity, the gain is indistinguishable from 1: the filter adopts essentially whatever velocity the position innovation implies, and simultaneously collapses the posterior velocity covariance, so the resulting estimate is published as high confidence.
Using only this file's own constants to size the effect: the vehicle models declare measurement_covariance.pos_x = sq(0.4), i.e. a 0.4 m position measurement standard deviation, which is the file's own statement of how far a single-frame centroid can legitimately land from the truth. At a typical detection period on the order of 0.1 s, a position innovation of that declared magnitude corresponds to several m/s of apparent longitudinal speed. With a bounded prior, that innovation is correctly attributed mostly to position noise. With the current prior it is attributed almost entirely to velocity, and a freshly created, genuinely stationary object can be published as moving at several m/s with a small reported velocity covariance on the very first frame it exists.
The behavior is not a transient that self-corrects before it is visible: the first cycle's output is published to /perception/object_recognition/tracking/objects like any other, and downstream consumers have no way to distinguish an estimate whose confidence came from data from one whose confidence came from a flat prior.
Steps to reproduce
This is a design defect visible by inspection of main; no runtime setup is needed to confirm it.
- Open
perception/autoware_multi_object_tracker/include/autoware/multi_object_tracker/object_model/object_model.hpp at main.
- Observe
initial_covariance.vel_long = sq(kmph2mps(1000.0)) at lines 158, 204, 250 and 296, for GeneralVehicle, NormalVehicle, BigVehicle and Bicycle.
- Observe, a few lines above each of those, that the same model sets
process_limit.vel_long_max to kmph2mps(140.0) or kmph2mps(120.0), so the prior is roughly 7x to 8x the model's own hard velocity limit.
- Compare with the
Pedestrian model at line 342 in the same switch, which sets the same field to the finite sq(kmph2mps(120.0)).
- Confirm the fallback is live by reading
lib/tracker/trackers/vehicle_tracker.cpp line 134: initial_covariance.vel_long is used as vel_x_cov for every new track whose detection lacks has_twist_covariance.
- Confirm there is no configuration escape hatch: nothing in
perception/autoware_multi_object_tracker/config/ exposes initial_covariance.
Versions
- Autoware:
autoware_universe @ 1c93b65555410c8c7b8299dab2f48320d1cb19e4 (main); all four values confirmed present and identical at that commit.
- Applies to every ROS 2 distribution and OS, since the constants are compiled in and not configurable.
Possible causes
The value appears to have been carried forward without ever being justified.
kmph2mps(1000) entered the repository in #74 ("feat: add multi_object_tracker package", merged 2021-12-05), which imported the package wholesale. In that commit the constant lived in the individual tracker sources as a standard deviation rather than a variance:
src/tracker/model/normal_vehicle_tracker.cpp: float p0_stddev_vx = autoware_utils::kmph2mps(1000); // object coordinate [m/s]
src/tracker/model/big_vehicle_tracker.cpp: float p0_stddev_vx = autoware_utils::kmph2mps(1000); // [m/s]
src/tracker/model/bicycle_tracker.cpp: float p0_stddev_vx = autoware_utils::kmph2mps(1000); // [m/(s*s)]
Two details in that original commit suggest these were placeholders rather than tuned values:
- In the very same commit,
src/tracker/model/pedestrian_tracker.cpp set float p0_stddev_vx = autoware_utils::kmph2mps(5);, a tight and physically reasoned prior. The same author, in the same commit, chose a considered value for pedestrians and 1000 for everything else.
- The
bicycle_tracker.cpp line annotates the units of a velocity standard deviation as [m/(s*s)], a copy-paste artifact from the adjacent acceleration noise term. The comment was not proofread, which is consistent with the number not having been reasoned about either.
The constant then moved into its present form in #7271 ("feat(multi_object_tracker): tracker refactoring", merged 2024-06-23), which created object_model.hpp and consolidated the per-tracker constants into it. That change and the subsequent restructurings of this package were scoped as refactors, so each one preserved the value by design. No commit in the history of either the original tracker sources or object_model.hpp records a rationale for 1000 specifically.
The Pedestrian entry is the one that was revisited: it is finite today at sq(kmph2mps(120.0)), on the same order as its own process_limit.vel_long_max of kmph2mps(100.0). The vehicle and bicycle entries were never revisited.
Additional context
Suggested direction, kept deliberately narrow: replace the four sq(kmph2mps(1000.0)) priors with finite values in the same sq(kmph2mps(...)) style already used throughout this file, sized from each model's own process_limit.vel_long_max so the prior and the motion model agree on what speeds are possible. The Bicycle model warrants a wider prior than the passenger-vehicle models, since it also covers motorcycles.
This does not reduce the tracker's ability to track fast objects. A genuinely fast object still produces consistent position innovations frame after frame, and the velocity estimate converges within a few cycles. What a bounded prior removes is the filter's willingness to make a large, high-confidence velocity claim from a single frame of evidence, at the one moment in a track's life when it has no evidence at all.
Scope note: this issue is about the initial-covariance prior only. Other constants in this file, such as the process noise and measurement covariance terms, are out of scope here and are not part of the proposed change.
Related but distinct, checked and confirmed not to overlap:
No open issue or pull request currently addresses initial_covariance in this package.
Checklist
Description
In
perception/autoware_multi_object_tracker/include/autoware/multi_object_tracker/object_model/object_model.hpp, four of the six object models set the initial longitudinal velocity covariance to an effectively unbounded value:initial_covariance.vel_longprocess_limit.vel_long_maxGeneralVehicle(line 158)sq(kmph2mps(1000.0))NormalVehicle(line 204)sq(kmph2mps(1000.0))BigVehicle(line 250)sq(kmph2mps(1000.0))Bicycle(line 296)sq(kmph2mps(1000.0))Pedestrian(line 342)sq(kmph2mps(120.0))(Line numbers are against
mainat1c93b65555410c8c7b8299dab2f48320d1cb19e4.)The prior standard deviation on the velocity state of a newly born vehicle or bicycle track is therefore 1000 km/h, roughly 7x to 8x the same model's own hard
process_limit.vel_long_max, and far outside anything the motion model will subsequently allow. It is a flat, uninformative prior standing in for "no prior information at all" rather than a plausibility prior.The
Pedestrianmodel in the same file and the sameswitchstatement already uses a finite prior for the identical field, so a bounded plausibility prior on this state is established design in this file. The vehicle and bicycle models are the outlier, not a new constraint being introduced.This value is compiled in. There is no parameter in
perception/autoware_multi_object_tracker/config/that overridesinitial_covariance, so no deployment can tune around it.Expected behavior
At track birth,
initial_covariance.vel_longfor the vehicle and bicycle object models should express a finite, physically plausible prior on the object's longitudinal speed, consistent with each model's ownprocess_limit.vel_long_maxand with thePedestrianmodel's existing use of the same field. The first measurement update should then be able to move the velocity estimate but not be able to set it to an arbitrary value that the same object model would reject as out of limits one timestep later.Actual behavior
The prior is unbounded in practice, and the consequence is concentrated entirely in the first update after track creation.
The consumer is
perception/autoware_multi_object_tracker/lib/tracker/trackers/vehicle_tracker.cpp, line 134:initial_covariance.vel_longis the fallback used whenever the incoming detection carries no twist covariance, which is the normal case for lidar-only and camera-lidar-fusion detection outputs that report shape and pose but not a measured velocity with uncertainty. All four affected models reach this code path:GeneralVehicle,NormalVehicle,BigVehicleandBicycleare all constructed asVehicleTrackerinsrc/processor/processor.cpp(lines 177 to 187), and theBicyclemodel also covers motorcycles.The state is therefore initialized at
vel_x = 0.0with a 277.8 m/s prior standard deviation on it. On the first EKF update the Kalman gain for the velocity state scales withP / (P + R). WithPfive to six orders of magnitude larger than any plausibleRon the implied velocity, the gain is indistinguishable from 1: the filter adopts essentially whatever velocity the position innovation implies, and simultaneously collapses the posterior velocity covariance, so the resulting estimate is published as high confidence.Using only this file's own constants to size the effect: the vehicle models declare
measurement_covariance.pos_x = sq(0.4), i.e. a 0.4 m position measurement standard deviation, which is the file's own statement of how far a single-frame centroid can legitimately land from the truth. At a typical detection period on the order of 0.1 s, a position innovation of that declared magnitude corresponds to several m/s of apparent longitudinal speed. With a bounded prior, that innovation is correctly attributed mostly to position noise. With the current prior it is attributed almost entirely to velocity, and a freshly created, genuinely stationary object can be published as moving at several m/s with a small reported velocity covariance on the very first frame it exists.The behavior is not a transient that self-corrects before it is visible: the first cycle's output is published to
/perception/object_recognition/tracking/objectslike any other, and downstream consumers have no way to distinguish an estimate whose confidence came from data from one whose confidence came from a flat prior.Steps to reproduce
This is a design defect visible by inspection of
main; no runtime setup is needed to confirm it.perception/autoware_multi_object_tracker/include/autoware/multi_object_tracker/object_model/object_model.hppatmain.initial_covariance.vel_long = sq(kmph2mps(1000.0))at lines 158, 204, 250 and 296, forGeneralVehicle,NormalVehicle,BigVehicleandBicycle.process_limit.vel_long_maxtokmph2mps(140.0)orkmph2mps(120.0), so the prior is roughly 7x to 8x the model's own hard velocity limit.Pedestrianmodel at line 342 in the sameswitch, which sets the same field to the finitesq(kmph2mps(120.0)).lib/tracker/trackers/vehicle_tracker.cppline 134:initial_covariance.vel_longis used asvel_x_covfor every new track whose detection lackshas_twist_covariance.perception/autoware_multi_object_tracker/config/exposesinitial_covariance.Versions
autoware_universe@1c93b65555410c8c7b8299dab2f48320d1cb19e4(main); all four values confirmed present and identical at that commit.Possible causes
The value appears to have been carried forward without ever being justified.
kmph2mps(1000)entered the repository in #74 ("feat: add multi_object_tracker package", merged 2021-12-05), which imported the package wholesale. In that commit the constant lived in the individual tracker sources as a standard deviation rather than a variance:src/tracker/model/normal_vehicle_tracker.cpp:float p0_stddev_vx = autoware_utils::kmph2mps(1000); // object coordinate [m/s]src/tracker/model/big_vehicle_tracker.cpp:float p0_stddev_vx = autoware_utils::kmph2mps(1000); // [m/s]src/tracker/model/bicycle_tracker.cpp:float p0_stddev_vx = autoware_utils::kmph2mps(1000); // [m/(s*s)]Two details in that original commit suggest these were placeholders rather than tuned values:
src/tracker/model/pedestrian_tracker.cppsetfloat p0_stddev_vx = autoware_utils::kmph2mps(5);, a tight and physically reasoned prior. The same author, in the same commit, chose a considered value for pedestrians and1000for everything else.bicycle_tracker.cppline annotates the units of a velocity standard deviation as[m/(s*s)], a copy-paste artifact from the adjacent acceleration noise term. The comment was not proofread, which is consistent with the number not having been reasoned about either.The constant then moved into its present form in #7271 ("feat(multi_object_tracker): tracker refactoring", merged 2024-06-23), which created
object_model.hppand consolidated the per-tracker constants into it. That change and the subsequent restructurings of this package were scoped as refactors, so each one preserved the value by design. No commit in the history of either the original tracker sources orobject_model.hpprecords a rationale for1000specifically.The
Pedestrianentry is the one that was revisited: it is finite today atsq(kmph2mps(120.0)), on the same order as its ownprocess_limit.vel_long_maxofkmph2mps(100.0). The vehicle and bicycle entries were never revisited.Additional context
Suggested direction, kept deliberately narrow: replace the four
sq(kmph2mps(1000.0))priors with finite values in the samesq(kmph2mps(...))style already used throughout this file, sized from each model's ownprocess_limit.vel_long_maxso the prior and the motion model agree on what speeds are possible. TheBicyclemodel warrants a wider prior than the passenger-vehicle models, since it also covers motorcycles.This does not reduce the tracker's ability to track fast objects. A genuinely fast object still produces consistent position innovations frame after frame, and the velocity estimate converges within a few cycles. What a bounded prior removes is the filter's willingness to make a large, high-confidence velocity claim from a single frame of evidence, at the one moment in a track's life when it has no evidence at all.
Scope note: this issue is about the initial-covariance prior only. Other constants in this file, such as the process noise and measurement covariance terms, are out of scope here and are not part of the proposed change.
Related but distinct, checked and confirmed not to overlap:
min_velocity_for_map_based_predictioninmap_based_prediction, a different package and a different stage of the pipeline. It is about that parameter being applied inconsistently between vehicle and crosswalk-pedestrian prediction, and has nothing to do with tracker initial covariance.No open issue or pull request currently addresses
initial_covariancein this package.