28double HMTrackersObjectsAssociation::s_match_distance_thresh_ = 4.0;
29double HMTrackersObjectsAssociation::s_match_distance_bound_ = 100.0;
33double HMTrackersObjectsAssociation::s_association_center_dist_threshold_ =
38 const std::vector<size_t>& subset_inds,
39 std::vector<T>* sub_vec) {
40 sub_vec->reserve(subset_inds.size());
42 for (
auto subset_ind : subset_inds) {
43 sub_vec->push_back(vec[subset_ind]);
50 const std::vector<SensorObjectPtr>& sensor_objects =
51 sensor_measurements->GetForegroundObjects();
52 const std::vector<TrackPtr>& fusion_tracks = scene->GetForegroundTracks();
53 std::vector<std::vector<double>> association_mat;
55 if (fusion_tracks.empty() || sensor_objects.empty()) {
65 std::string measurement_sensor_id = sensor_objects[0]->GetSensorId();
66 double measurement_timestamp = sensor_objects[0]->GetTimestamp();
68 measurement_timestamp);
69 bool do_nothing = (measurement_sensor_id ==
"radar_front" ||
70 measurement_sensor_id ==
"radar_rear");
71 IdAssign(fusion_tracks, sensor_objects, &association_result->
assignments,
76 sensor_measurements->GetPose(&pose);
77 Eigen::Vector3d ref_point = pose.translation();
79 ADEBUG <<
"association_measurement_timestamp@" << measurement_timestamp;
80 ComputeAssociationDistanceMat(fusion_tracks, sensor_objects, ref_point,
85 int num_track =
static_cast<int>(fusion_tracks.size());
86 int num_measurement =
static_cast<int>(sensor_objects.size());
89 std::vector<int> track_ind_g2l;
90 track_ind_g2l.resize(num_track, -1);
95 std::vector<int> measurement_ind_g2l;
96 measurement_ind_g2l.resize(num_measurement, -1);
97 std::vector<size_t> measurement_ind_l2g =
111 bool state = MinimizeAssignment(
112 association_mat, track_ind_l2g, measurement_ind_l2g,
117 std::vector<TrackMeasurmentPair> post_assignments;
118 PostIdAssign(fusion_tracks, sensor_objects,
122 post_assignments.begin(),
123 post_assignments.end());
125 GenerateUnassignedData(fusion_tracks.size(), sensor_objects.size(),
130 ComputeDistance(fusion_tracks, sensor_objects,
132 measurement_ind_g2l, measurement_ind_l2g, association_mat,
135 AINFO <<
"association: measurement_num = " << sensor_objects.size()
136 <<
", track_num = " << fusion_tracks.size()
137 <<
", assignments = " << association_result->
assignments.size()
138 <<
", unassigned_tracks = "
140 <<
", unassigned_measuremnets = "
146void HMTrackersObjectsAssociation::PostIdAssign(
147 const std::vector<TrackPtr>& fusion_tracks,
148 const std::vector<SensorObjectPtr>& sensor_objects,
149 const std::vector<size_t>& unassigned_fusion_tracks,
150 const std::vector<size_t>& unassigned_sensor_objects,
151 std::vector<TrackMeasurmentPair>* post_assignments) {
152 std::vector<size_t> valid_unassigned_tracks;
153 valid_unassigned_tracks.reserve(unassigned_fusion_tracks.size());
155 auto is_valid_track = [](
const TrackPtr& fusion_track) {
157 return camera_obj !=
nullptr &&
158 fusion_track->GetLatestLidarObject() ==
nullptr &&
159 fusion_track->GetLatestRadarObject() ==
nullptr;
161 for (
auto unassigned_track_id : unassigned_fusion_tracks) {
162 if (is_valid_track(fusion_tracks[unassigned_track_id])) {
163 valid_unassigned_tracks.push_back(unassigned_track_id);
166 std::vector<TrackPtr> sub_tracks;
167 std::vector<SensorObjectPtr> sub_objects;
168 extract_vector(fusion_tracks, valid_unassigned_tracks, &sub_tracks);
169 extract_vector(sensor_objects, unassigned_sensor_objects, &sub_objects);
170 std::vector<size_t> tmp1, tmp2;
171 IdAssign(sub_tracks, sub_objects, post_assignments, &tmp1, &tmp2,
false,
173 for (
auto& post_assignment : *post_assignments) {
174 post_assignment.first = valid_unassigned_tracks[post_assignment.first];
175 post_assignment.second = unassigned_sensor_objects[post_assignment.second];
179bool HMTrackersObjectsAssociation::MinimizeAssignment(
180 const std::vector<std::vector<double>>& association_mat,
181 const std::vector<size_t>& track_ind_l2g,
182 const std::vector<size_t>& measurement_ind_l2g,
183 std::vector<TrackMeasurmentPair>* assignments,
184 std::vector<size_t>* unassigned_tracks,
185 std::vector<size_t>* unassigned_measurements) {
189 int rows =
static_cast<int>(unassigned_tracks->size());
190 int cols =
static_cast<int>(unassigned_measurements->size());
192 global_costs->
Resize(rows, cols);
193 for (
int r_i = 0; r_i < rows; r_i++) {
194 for (
int c_i = 0; c_i < cols; c_i++) {
195 (*global_costs)(r_i, c_i) =
static_cast<float>(association_mat[r_i][c_i]);
198 std::vector<TrackMeasurmentPair> local_assignments;
199 std::vector<size_t> local_unassigned_tracks;
200 std::vector<size_t> local_unassigned_measurements;
201 optimizer_.
Match(
static_cast<float>(s_match_distance_thresh_),
202 static_cast<float>(s_match_distance_bound_), opt_flag,
203 &local_assignments, &local_unassigned_tracks,
204 &local_unassigned_measurements);
205 for (
auto assign : local_assignments) {
206 assignments->push_back(std::make_pair(track_ind_l2g[assign.first],
207 measurement_ind_l2g[assign.second]));
209 unassigned_tracks->clear();
210 unassigned_measurements->clear();
211 for (
auto un_track : local_unassigned_tracks) {
212 unassigned_tracks->push_back(track_ind_l2g[un_track]);
214 for (
auto un_mea : local_unassigned_measurements) {
215 unassigned_measurements->push_back(measurement_ind_l2g[un_mea]);
220void HMTrackersObjectsAssociation::ComputeDistance(
221 const std::vector<TrackPtr>& fusion_tracks,
222 const std::vector<SensorObjectPtr>& sensor_objects,
223 const std::vector<size_t>& unassigned_fusion_tracks,
224 const std::vector<int>& track_ind_g2l,
225 const std::vector<int>& measurement_ind_g2l,
226 const std::vector<size_t>& measurement_ind_l2g,
227 const std::vector<std::vector<double>>& association_mat,
228 AssociationResult* association_result) {
229 for (
size_t i = 0; i < association_result->assignments.size(); ++i) {
230 int track_ind =
static_cast<int>(association_result->assignments[i].first);
231 int measurement_ind =
232 static_cast<int>(association_result->assignments[i].second);
233 int track_ind_loc = track_ind_g2l[track_ind];
234 int measurement_ind_loc = measurement_ind_g2l[measurement_ind];
235 if (track_ind_loc >= 0 && measurement_ind_loc >= 0) {
236 association_result->track2measurements_dist[track_ind] =
237 association_mat[track_ind_loc][measurement_ind_loc];
238 association_result->measurement2track_dist[measurement_ind] =
239 association_mat[track_ind_loc][measurement_ind_loc];
242 for (
size_t i = 0; i < association_result->unassigned_tracks.size(); ++i) {
243 int track_ind =
static_cast<int>(unassigned_fusion_tracks[i]);
244 int track_ind_loc = track_ind_g2l[track_ind];
245 association_result->track2measurements_dist[track_ind] =
246 association_mat[track_ind_loc][0];
248 for (
size_t j = 1; j < association_mat[track_ind_loc].size(); j++) {
249 if (association_result->track2measurements_dist[track_ind] >
250 association_mat[track_ind_loc][j]) {
251 association_result->track2measurements_dist[track_ind] =
252 association_mat[track_ind_loc][j];
253 min_m_loc =
static_cast<int>(j);
256 int min_m_ind =
static_cast<int>(measurement_ind_l2g[min_m_loc]);
258 const TrackPtr& fusion_track = fusion_tracks[track_ind];
265 association_result->track2measurements_dist[track_ind] = 0.0;
266 for (
size_t j = 0; j < association_mat[track_ind_loc].size(); ++j) {
267 double dist_score = 0.0;
268 if (lidar_object !=
nullptr) {
270 lidar_object, sensor_objects[measurement_ind_l2g[j]],
271 IsLidar(sensor_objects[measurement_ind_l2g[j]]));
272 }
else if (radar_object !=
nullptr) {
274 radar_object, sensor_objects[measurement_ind_l2g[j]]);
276 association_result->track2measurements_dist[track_ind] = std::max(
277 association_result->track2measurements_dist[track_ind], dist_score);
281 for (
size_t i = 0; i < association_result->unassigned_measurements.size();
284 static_cast<int>(association_result->unassigned_measurements[i]);
285 int m_ind_loc = measurement_ind_g2l[m_ind];
286 association_result->measurement2track_dist[m_ind] =
287 association_mat[0][m_ind_loc];
288 for (
size_t j = 1; j < association_mat.size(); j++) {
289 if (association_result->measurement2track_dist[m_ind] >
290 association_mat[j][m_ind_loc]) {
291 association_result->measurement2track_dist[m_ind] =
292 association_mat[j][m_ind_loc];
298void HMTrackersObjectsAssociation::ComputeAssociationDistanceMat(
299 const std::vector<TrackPtr>& fusion_tracks,
300 const std::vector<SensorObjectPtr>& sensor_objects,
301 const Eigen::Vector3d& ref_point,
302 const std::vector<size_t>& unassigned_tracks,
303 const std::vector<size_t>& unassigned_measurements,
304 std::vector<std::vector<double>>* association_mat) {
305 TrackObjectDistanceOptions opt;
306 Eigen::Vector3d tmp = Eigen::Vector3d::Zero();
307 opt.ref_point = &tmp;
308 association_mat->resize(unassigned_tracks.size());
309 for (
size_t i = 0; i < unassigned_tracks.size(); ++i) {
310 size_t fusion_idx = unassigned_tracks[i];
311 (*association_mat)[i].resize(unassigned_measurements.size());
312 const TrackPtr& fusion_track = fusion_tracks[fusion_idx];
313 for (
size_t j = 0; j < unassigned_measurements.size(); ++j) {
314 size_t sensor_idx = unassigned_measurements[j];
316 double distance = s_match_distance_thresh_;
318 (sensor_object->GetBaseObject()->center -
319 fusion_track->GetFusedObject()->GetBaseObject()->center).norm();
320 if (center_dist < s_association_center_dist_threshold_) {
322 track_object_distance_.
Compute(fusion_track, sensor_object, opt);
324 ADEBUG <<
"center_distance " << center_dist
325 <<
" exceeds slack threshold "
326 << s_association_center_dist_threshold_
327 <<
", track_id: " << fusion_track->GetTrackId()
328 <<
", obs_id: " << sensor_object->GetBaseObject()->track_id;
330 (*association_mat)[i][j] = distance;
331 ADEBUG <<
"track_id: " << fusion_track->GetTrackId()
332 <<
", obs_id: " << sensor_object->GetBaseObject()->track_id
333 <<
", distance: " << distance;
338void HMTrackersObjectsAssociation::IdAssign(
339 const std::vector<TrackPtr>& fusion_tracks,
340 const std::vector<SensorObjectPtr>& sensor_objects,
341 std::vector<TrackMeasurmentPair>* assignments,
342 std::vector<size_t>* unassigned_fusion_tracks,
343 std::vector<size_t>* unassigned_sensor_objects,
bool do_nothing,
345 size_t num_track = fusion_tracks.size();
346 size_t num_obj = sensor_objects.size();
347 if (num_track == 0 || num_obj == 0 || do_nothing) {
348 unassigned_fusion_tracks->resize(num_track);
349 unassigned_sensor_objects->resize(num_obj);
350 std::iota(unassigned_fusion_tracks->begin(),
351 unassigned_fusion_tracks->end(), 0);
352 std::iota(unassigned_sensor_objects->begin(),
353 unassigned_sensor_objects->end(), 0);
357 const std::string sensor_id = sensor_objects[0]->GetSensorId();
359 std::map<int, int> sensor_id_2_track_ind;
360 for (
size_t i = 0; i < num_track; ++i) {
365 if (sensor_id ==
"front_6mm" || sensor_id ==
"front_12mm" ||
366 sensor_id ==
"camera_rear" || sensor_id ==
"camera_front") {
367 obj = fusion_tracks[i]->GetLatestCameraObject();
369 if (obj ==
nullptr) {
372 sensor_id_2_track_ind[obj->GetBaseObject()->track_id] =
static_cast<int>(i);
374 std::vector<bool> fusion_used(num_track,
false);
375 std::vector<bool> sensor_used(num_obj,
false);
376 for (
size_t i = 0; i < num_obj; ++i) {
377 int track_id = sensor_objects[i]->GetBaseObject()->track_id;
378 auto it = sensor_id_2_track_ind.find(track_id);
383 if (!post && (sensor_id ==
"front_6mm" || sensor_id ==
"front_12mm" ||
384 sensor_id ==
"camera_rear" || sensor_id ==
"camera_front")) {
388 if (it != sensor_id_2_track_ind.end()) {
389 sensor_used[i] =
true;
390 fusion_used[it->second] =
true;
391 assignments->push_back(std::make_pair(it->second, i));
394 for (
size_t i = 0; i < fusion_used.size(); ++i) {
395 if (!fusion_used[i]) {
396 unassigned_fusion_tracks->push_back(i);
399 for (
size_t i = 0; i < sensor_used.size(); ++i) {
400 if (!sensor_used[i]) {
401 unassigned_sensor_objects->push_back(i);
406void HMTrackersObjectsAssociation::GenerateUnassignedData(
407 size_t track_num,
size_t objects_num,
408 const std::vector<TrackMeasurmentPair>& assignments,
409 std::vector<size_t>* unassigned_tracks,
410 std::vector<size_t>* unassigned_objects) {
411 std::vector<bool> track_flags(track_num,
false);
412 std::vector<bool> objects_flags(objects_num,
false);
413 for (
auto assignment : assignments) {
414 track_flags[assignment.first] =
true;
415 objects_flags[assignment.second] =
true;
417 unassigned_tracks->clear(), unassigned_tracks->reserve(track_num);
418 unassigned_objects->clear(), unassigned_objects->reserve(objects_num);
419 for (
size_t i = 0; i < track_num; ++i) {
420 if (!track_flags[i]) {
421 unassigned_tracks->push_back(i);
424 for (
size_t i = 0; i < objects_num; ++i) {
425 if (!objects_flags[i]) {
426 unassigned_objects->push_back(i);
#define PERCEPTION_REGISTER_ASSOCIATION(name)
SecureMat< T > * mutable_global_costs()
void Match(T cost_thresh, OptimizeFlag opt_flag, std::vector< std::pair< size_t, size_t > > *assignments, std::vector< size_t > *unassigned_rows, std::vector< size_t > *unassigned_cols)
void Resize(const size_t resize_height, const size_t resize_width)
bool Associate(const AssociationOptions &options, SensorFramePtr sensor_measurements, ScenePtr scene, AssociationResult *association_result) override
Associate the obstacles measured by the sensor with the obstacles tracked in current scene
void ResetProjectionCache(std::string sensor_id, double timestamp)
float Compute(const TrackPtr &fused_track, const SensorObjectPtr &sensor_object, const TrackObjectDistanceOptions &options)
double ComputeRadarCameraSimilarity(const SensorObjectConstPtr &radar, const SensorObjectConstPtr &camera)
double ComputeLidarCameraSimilarity(const SensorObjectConstPtr &lidar, const SensorObjectConstPtr &camera, const bool measurement_is_lidar)
std::shared_ptr< const SensorObject > SensorObjectConstPtr
std::shared_ptr< SensorObject > SensorObjectPtr
bool IsCamera(const SensorObjectConstPtr &obj)
std::shared_ptr< SensorFrame > SensorFramePtr
std::shared_ptr< Track > TrackPtr
void extract_vector(const std::vector< T > &vec, const std::vector< size_t > &subset_inds, std::vector< T > *sub_vec)
bool IsLidar(const SensorObjectConstPtr &obj)
std::shared_ptr< Scene > ScenePtr
std::vector< size_t > unassigned_measurements
std::vector< size_t > unassigned_tracks
std::vector< double > track2measurements_dist
std::vector< double > measurement2track_dist
std::vector< TrackMeasurmentPair > assignments