Apollo 11.0
自动驾驶开放平台
hm_tracks_objects_match.cc
浏览该文件的文档.
1/******************************************************************************
2 * Copyright 2018 The Apollo Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *****************************************************************************/
17
18#include <map>
19#include <numeric>
20#include <utility>
21
23
24namespace apollo {
25namespace perception {
26namespace fusion {
27
28double HMTrackersObjectsAssociation::s_match_distance_thresh_ = 4.0;
29double HMTrackersObjectsAssociation::s_match_distance_bound_ = 100.0;
30/* this is a slack threshold for camera 2 lidar/radar association.
31 * consider the ave 2d-to-3d error is 7%, 30m is 15% of 200m, which
32 * is 2 times of ave error around 200m. */
33double HMTrackersObjectsAssociation::s_association_center_dist_threshold_ =
34 30.0;
35
36template <typename T>
37void extract_vector(const std::vector<T>& vec,
38 const std::vector<size_t>& subset_inds,
39 std::vector<T>* sub_vec) {
40 sub_vec->reserve(subset_inds.size());
41 sub_vec->clear();
42 for (auto subset_ind : subset_inds) {
43 sub_vec->push_back(vec[subset_ind]);
44 }
45}
46
48 const AssociationOptions& options, SensorFramePtr sensor_measurements,
49 ScenePtr scene, AssociationResult* association_result) {
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;
54
55 if (fusion_tracks.empty() || sensor_objects.empty()) {
56 association_result->unassigned_tracks.resize(fusion_tracks.size());
57 association_result->unassigned_measurements.resize(sensor_objects.size());
58 std::iota(association_result->unassigned_tracks.begin(),
59 association_result->unassigned_tracks.end(), 0);
60 std::iota(association_result->unassigned_measurements.begin(),
61 association_result->unassigned_measurements.end(), 0);
62 return true;
63 }
64
65 std::string measurement_sensor_id = sensor_objects[0]->GetSensorId();
66 double measurement_timestamp = sensor_objects[0]->GetTimestamp();
67 track_object_distance_.ResetProjectionCache(measurement_sensor_id,
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,
72 &association_result->unassigned_tracks,
73 &association_result->unassigned_measurements, do_nothing, false);
74
75 Eigen::Affine3d pose;
76 sensor_measurements->GetPose(&pose);
77 Eigen::Vector3d ref_point = pose.translation();
78
79 ADEBUG << "association_measurement_timestamp@" << measurement_timestamp;
80 ComputeAssociationDistanceMat(fusion_tracks, sensor_objects, ref_point,
81 association_result->unassigned_tracks,
82 association_result->unassigned_measurements,
83 &association_mat);
84
85 int num_track = static_cast<int>(fusion_tracks.size());
86 int num_measurement = static_cast<int>(sensor_objects.size());
87 association_result->track2measurements_dist.assign(num_track, 0);
88 association_result->measurement2track_dist.assign(num_measurement, 0);
89 std::vector<int> track_ind_g2l;
90 track_ind_g2l.resize(num_track, -1);
91 for (size_t i = 0; i < association_result->unassigned_tracks.size(); ++i) {
92 track_ind_g2l[association_result->unassigned_tracks[i]] =
93 static_cast<int>(i);
94 }
95 std::vector<int> measurement_ind_g2l;
96 measurement_ind_g2l.resize(num_measurement, -1);
97 std::vector<size_t> measurement_ind_l2g =
98 association_result->unassigned_measurements;
99 for (size_t i = 0; i < association_result->unassigned_measurements.size();
100 ++i) {
101 measurement_ind_g2l[association_result->unassigned_measurements[i]] =
102 static_cast<int>(i);
103 }
104 std::vector<size_t> track_ind_l2g = association_result->unassigned_tracks;
105
106 if (association_result->unassigned_tracks.empty() ||
107 association_result->unassigned_measurements.empty()) {
108 return true;
109 }
110
111 bool state = MinimizeAssignment(
112 association_mat, track_ind_l2g, measurement_ind_l2g,
113 &association_result->assignments, &association_result->unassigned_tracks,
114 &association_result->unassigned_measurements);
115
116 // start do post assign
117 std::vector<TrackMeasurmentPair> post_assignments;
118 PostIdAssign(fusion_tracks, sensor_objects,
119 association_result->unassigned_tracks,
120 association_result->unassigned_measurements, &post_assignments);
121 association_result->assignments.insert(association_result->assignments.end(),
122 post_assignments.begin(),
123 post_assignments.end());
124
125 GenerateUnassignedData(fusion_tracks.size(), sensor_objects.size(),
126 association_result->assignments,
127 &association_result->unassigned_tracks,
128 &association_result->unassigned_measurements);
129
130 ComputeDistance(fusion_tracks, sensor_objects,
131 association_result->unassigned_tracks, track_ind_g2l,
132 measurement_ind_g2l, measurement_ind_l2g, association_mat,
133 association_result);
134
135 AINFO << "association: measurement_num = " << sensor_objects.size()
136 << ", track_num = " << fusion_tracks.size()
137 << ", assignments = " << association_result->assignments.size()
138 << ", unassigned_tracks = "
139 << association_result->unassigned_tracks.size()
140 << ", unassigned_measuremnets = "
141 << association_result->unassigned_measurements.size();
142
143 return state;
144}
145
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());
154 // only camera track
155 auto is_valid_track = [](const TrackPtr& fusion_track) {
156 SensorObjectConstPtr camera_obj = fusion_track->GetLatestCameraObject();
157 return camera_obj != nullptr &&
158 fusion_track->GetLatestLidarObject() == nullptr &&
159 fusion_track->GetLatestRadarObject() == nullptr;
160 };
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);
164 }
165 }
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,
172 true);
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];
176 }
177}
178
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) {
188 algorithm::SecureMat<float>* global_costs = optimizer_.mutable_global_costs();
189 int rows = static_cast<int>(unassigned_tracks->size());
190 int cols = static_cast<int>(unassigned_measurements->size());
191
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]);
196 }
197 }
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]));
208 }
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]);
213 }
214 for (auto un_mea : local_unassigned_measurements) {
215 unassigned_measurements->push_back(measurement_ind_l2g[un_mea]);
216 }
217 return true;
218}
219
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];
240 }
241 }
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];
247 int min_m_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);
254 }
255 }
256 int min_m_ind = static_cast<int>(measurement_ind_l2g[min_m_loc]);
257 const SensorObjectPtr& min_sensor_object = sensor_objects[min_m_ind];
258 const TrackPtr& fusion_track = fusion_tracks[track_ind];
259 SensorObjectConstPtr lidar_object = fusion_track->GetLatestLidarObject();
260 SensorObjectConstPtr radar_object = fusion_track->GetLatestRadarObject();
261 if (IsCamera(min_sensor_object)) {
262 // TODO(linjian) not reasonable,
263 // just for return dist score, the dist score is
264 // a similarity probability [0, 1] 1 is the best
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) {
269 dist_score = track_object_distance_.ComputeLidarCameraSimilarity(
270 lidar_object, sensor_objects[measurement_ind_l2g[j]],
271 IsLidar(sensor_objects[measurement_ind_l2g[j]]));
272 } else if (radar_object != nullptr) {
273 dist_score = track_object_distance_.ComputeRadarCameraSimilarity(
274 radar_object, sensor_objects[measurement_ind_l2g[j]]);
275 }
276 association_result->track2measurements_dist[track_ind] = std::max(
277 association_result->track2measurements_dist[track_ind], dist_score);
278 }
279 }
280 }
281 for (size_t i = 0; i < association_result->unassigned_measurements.size();
282 ++i) {
283 int m_ind =
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];
293 }
294 }
295 }
296}
297
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];
315 const SensorObjectPtr& sensor_object = sensor_objects[sensor_idx];
316 double distance = s_match_distance_thresh_;
317 double center_dist =
318 (sensor_object->GetBaseObject()->center -
319 fusion_track->GetFusedObject()->GetBaseObject()->center).norm();
320 if (center_dist < s_association_center_dist_threshold_) {
321 distance =
322 track_object_distance_.Compute(fusion_track, sensor_object, opt);
323 } else {
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;
329 }
330 (*association_mat)[i][j] = distance;
331 ADEBUG << "track_id: " << fusion_track->GetTrackId()
332 << ", obs_id: " << sensor_object->GetBaseObject()->track_id
333 << ", distance: " << distance;
334 }
335 }
336}
337
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,
344 bool post) {
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);
354 return;
355 }
356
357 const std::string sensor_id = sensor_objects[0]->GetSensorId();
358
359 std::map<int, int> sensor_id_2_track_ind;
360 for (size_t i = 0; i < num_track; ++i) {
361 SensorObjectConstPtr obj = fusion_tracks[i]->GetSensorObject(sensor_id);
362 /* when camera system has sub-fusion of obstacle & narrow, they share
363 * the same track-id sequence. thus, latest camera object is ok for
364 * camera id assign and its information is more up to date. */
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();
368 }
369 if (obj == nullptr) {
370 continue;
371 }
372 sensor_id_2_track_ind[obj->GetBaseObject()->track_id] = static_cast<int>(i);
373 }
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);
379
380 // In id_assign, we don't assign the narrow camera object
381 // with the track which only have narrow camera object
382 // In post id_assign, we do this.
383 if (!post && (sensor_id == "front_6mm" || sensor_id == "front_12mm" ||
384 sensor_id == "camera_rear" || sensor_id == "camera_front")) {
385 continue;
386 }
387
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));
392 }
393 }
394 for (size_t i = 0; i < fusion_used.size(); ++i) {
395 if (!fusion_used[i]) {
396 unassigned_fusion_tracks->push_back(i);
397 }
398 }
399 for (size_t i = 0; i < sensor_used.size(); ++i) {
400 if (!sensor_used[i]) {
401 unassigned_sensor_objects->push_back(i);
402 }
403 }
404}
405
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;
416 }
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);
422 }
423 }
424 for (size_t i = 0; i < objects_num; ++i) {
425 if (!objects_flags[i]) {
426 unassigned_objects->push_back(i);
427 }
428 }
429}
430
431PERCEPTION_REGISTER_ASSOCIATION(HMTrackersObjectsAssociation)
432
433} // namespace fusion
434} // namespace perception
435} // namespace apollo
#define PERCEPTION_REGISTER_ASSOCIATION(name)
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)
#define ADEBUG
Definition log.h:41
#define AINFO
Definition log.h:42
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
Definition track.h:397
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
Definition scene.h:88
class register implement
Definition arena_queue.h:37
std::vector< TrackMeasurmentPair > assignments