Apollo 11.0
自动驾驶开放平台
mlf_engine.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 *****************************************************************************/
16
18
19#include <utility>
20
21#include "Eigen/Geometry"
22
23#include "modules/perception/lidar_tracking/tracker/multi_lidar_fusion/proto/multi_lidar_fusion_config.pb.h"
24
25#include "cyber/common/file.h"
31
32namespace apollo {
33namespace perception {
34namespace lidar {
35
42
44 std::string config_file =
45 GetConfigFile(options.config_path, options.config_file);
46 MlfEngineConfig config;
47 ACHECK(cyber::common::GetProtoFromFile(config_file, &config));
48
49 Clear();
50
60
62 MlfTrackObjectMatcherInitOptions matcher_init_options;
63 matcher_init_options.config_path = options.config_path;
64 ACHECK(matcher_->Init(matcher_init_options));
65
66 tracker_.reset(new MlfTracker);
67 MlfTrackerInitOptions tracker_init_options;
68 tracker_init_options.config_path = options.config_path;
69 ACHECK(tracker_->Init(tracker_init_options));
70 return true;
71}
72
74 LidarFrame* frame) {
75 // 0. modify objects timestamp if necessary
77 for (auto& object : frame->segmented_objects) {
78 object->latest_tracked_time = frame->timestamp;
79 }
80 }
81 if (print_debug_log_) {
82 ObjectsDebugInfo(frame, true);
83 ObjectsDebugInfo(frame, false);
84 }
85 // 1. add global offset to pose (only when no track exists)
86 if (foreground_track_data_.empty() && background_track_data_.empty()) {
87 global_to_local_offset_ = -frame->lidar2world_pose.translation();
88 }
91 // 2. split fg and bg objects, and transform to tracked objects
93 frame->sensor_info, frame->timestamp);
94 // 3. assign tracked objects to tracks
95 MlfTrackObjectMatcherOptions match_options;
96 TrackObjectMatchAndAssign(match_options, foreground_objects_, "foreground",
98 TrackObjectMatchAndAssign(match_options, background_objects_, "background",
100 // 4. state filter in tracker if is main sensor
101 bool is_main_sensor = algorithm::SensorManager::Instance()->IsMainSensor(
102 frame->sensor_info.name);
103 if (is_main_sensor) {
106 }
107 // 5. track to object if is main sensor
108 if (print_debug_log_) {
109 TrackDebugInfo(frame);
110 }
111 frame->tracked_objects.clear();
112 if (is_main_sensor) {
114 }
115 // 6. remove stale data
118
119 // Startegy: Set velocity and acceleration to ZERO outside hdmap_struct
120 // temporarily located here, best is in mlf_motion_refiner.cc
121 auto roi = frame->hdmap_struct;
122 if (roi == nullptr ||
123 (roi->road_polygons.empty() && roi->junction_polygons.empty() &&
124 roi->road_boundary.empty())) {
125 AINFO << "MlfEngine publish objects: " << frame->tracked_objects.size()
126 << " sensor_name: " << frame->sensor_info.name
127 << " at timestamp: " << frame->timestamp;
128 return true;
129 }
130 std::stringstream sstr;
131 sstr << "Set objects velocity to zero. track_id: ";
132 for (auto obj : frame->tracked_objects) {
133 if (obj->motion_state == base::MotionState::MOVING) {
134 continue;
135 }
136 if (algorithm::IsObjectInRoi(roi, obj) &&
137 obj->lidar_supplement.semantic_type != base::ObjectSemanticType::WALL &&
138 obj->lidar_supplement.semantic_type != base::ObjectSemanticType::FENCE
139 ) {
140 continue;
141 }
142 obj->velocity = Eigen::Vector3f::Zero();
143 obj->acceleration = Eigen::Vector3f::Zero();
144 sstr << obj->track_id << ", ";
145 }
146 AINFO << sstr.str();
147
148 AINFO << "MlfEngine publish objects: " << frame->tracked_objects.size()
149 << " sensor_name: " << frame->sensor_info.name
150 << " at timestamp: " << std::to_string(frame->timestamp);
151 return true;
152}
153
155 const std::vector<base::ObjectPtr>& objects,
156 const base::SensorInfo& sensor_info, double frame_timestamp) {
157 std::vector<TrackedObjectPtr> tracked_objects;
158 TrackedObjectPool::Instance().BatchGet(objects.size(), &tracked_objects);
159 foreground_objects_.clear();
160 background_objects_.clear();
161 for (size_t i = 0; i < objects.size(); ++i) {
162 double tracked_time = objects[i]->latest_tracked_time;
163 double timestamp = use_frame_timestamp_ ? frame_timestamp : tracked_time;
164 tracked_objects[i]->AttachObject(objects[i], sensor_to_local_pose_,
165 global_to_local_offset_, sensor_info, timestamp);
166
168 foreground_objects_.push_back(tracked_objects[i]);
169 } else {
170 if (!objects[i]->lidar_supplement.is_clustered &&
172 tracked_objects[i]->histogram_bin_size = histogram_bin_size_;
173 tracked_objects[i]->ComputeShapeFeatures();
174 }
175
176 if (!objects[i]->lidar_supplement.is_clustered) {
177 foreground_objects_.push_back(tracked_objects[i]);
178 } else {
179 background_objects_.push_back(tracked_objects[i]);
180 }
181 }
182 }
183 AINFO << "MlfEngine: " << sensor_info.name
184 << " foreground: " << foreground_objects_.size()
185 << " background: " << background_objects_.size();
186}
187
189 const MlfTrackObjectMatcherOptions& match_options,
190 const std::vector<TrackedObjectPtr>& objects, const std::string& name,
191 std::vector<MlfTrackDataPtr>* tracks) {
192 std::vector<std::pair<size_t, size_t>> assignments;
193 std::vector<size_t> unassigned_tracks;
194 std::vector<size_t> unassigned_objects;
195 matcher_->Match(match_options, objects, *tracks, &assignments,
196 &unassigned_tracks, &unassigned_objects);
197 AINFO << "MlfEngine: " + name + " assignments " << assignments.size()
198 << " unassigned_tracks " << unassigned_tracks.size()
199 << " unassigned_objects " << unassigned_objects.size();
200 // 1. for assignment, push object to cache of track_data
201 for (auto& pair : assignments) {
202 const size_t track_id = pair.first;
203 const size_t object_id = pair.second;
204 tracks->at(track_id)->PushTrackedObjectToCache(objects[object_id]);
205 }
206 // 2. for unassigned_objects, create new tracks
207 for (auto& id : unassigned_objects) {
209 tracker_->InitializeTrack(track_data, objects[id]);
210 tracks->push_back(track_data);
211 }
212}
213
214void MlfEngine::TrackStateFilter(const std::vector<MlfTrackDataPtr>& tracks,
215 double frame_timestamp) {
216 std::vector<TrackedObjectPtr> objects;
217 for (auto& track_data : tracks) {
218 track_data->GetAndCleanCachedObjectsInTimeInterval(&objects);
219 for (auto& obj : objects) {
220 tracker_->UpdateTrackDataWithObject(track_data, obj);
221 }
222 if (objects.empty()) {
223 tracker_->UpdateTrackDataWithoutObject(frame_timestamp, track_data);
224 }
225 }
226}
227
229 auto& tracked_objects = frame->tracked_objects;
230 tracked_objects.clear();
231 size_t num_objects =
233 base::ObjectPool::Instance().BatchGet(num_objects, &tracked_objects);
234 size_t pos = 0;
235 size_t num_predict = 0;
236 size_t num_delay_output = 0;
237 size_t num_front_critical_reserve = 0;
238 size_t num_blind_trafficcone = 0;
239 auto collect = [&](std::vector<MlfTrackDataPtr>* tracks) {
240 for (auto& track_data : *tracks) {
241 // if (!output_predict_objects_ &&
242 // track_data->is_current_state_predicted_) {
243 // ++num_predict;
244 // } else {
245 // if (!track_data->ToObject(-global_to_local_offset_,
246 // frame->timestamp, tracked_objects[pos], true)) {
247 // AERROR << "Tracking failed";
248 // continue;
249 // }
250 // ++pos;
251 // }
252 if (track_data->age_ <= pub_track_times_) {
253 if (track_data->is_front_critical_track_) {
254 ADEBUG << "[DelayOutput] track_id: " << track_data->track_id_
255 << " time is " << std::to_string(frame->timestamp)
256 << " not output";
257 }
258 ++num_delay_output;
259 continue;
260 }
261 track_data->is_reserve_blind_cone_ = false;
262 // == false -> OUTPUT
263 if (!track_data->is_current_state_predicted_) {
264 if (!track_data->ToObject(-global_to_local_offset_,
265 frame->timestamp, tracked_objects[pos], true)) {
266 AERROR << "Tracking failed";
267 continue;
268 }
269 ++pos;
270 ADEBUG << "track_id: " << track_data->track_id_
271 << " detetcted, obj-time is "
272 << std::to_string(frame->timestamp) << " and output";
273 continue;
274 } else {
275 // == true: output_predict_objects_ == true -> OUTPUT
277 if (!track_data->ToObject(-global_to_local_offset_,
278 frame->timestamp, tracked_objects[pos], true)) {
279 AERROR << "Tracking failed";
280 continue;
281 }
282 ++pos;
283 continue;
284 } else {
285 // output_predict_objects_ == false
286 // should judge front-critical and time
287 TrackedObjectConstPtr latest_object =
288 track_data->GetLatestObject().second;
289 // front-critical and within time -> OUTPUT
290 if (latest_object != nullptr &&
291 track_data->is_front_critical_track_ &&
292 latest_object->output_velocity.head<2>().norm() < 0.01 &&
293 frame->timestamp -
294 track_data->GetLatestObject().first <= delay_output_) {
295 ++num_front_critical_reserve;
296 AINFO << "track_id: " << track_data->track_id_
297 << " missed, obj-time is "
298 << std::to_string(track_data->GetLatestObject().first)
299 << " and predict output";
300 if (!track_data->ToObject(-global_to_local_offset_,
301 frame->timestamp, tracked_objects[pos], false)) {
302 AERROR << "Tracking failed";
303 continue;
304 }
305 ++pos;
306 continue;
307 } else if (JudgeBlindTrafficCone(track_data, frame->timestamp,
309 frame->lidar2novatel_extrinsics)) {
310 ++num_blind_trafficcone;
311 if (!track_data->ToObject(-global_to_local_offset_,
312 frame->timestamp, tracked_objects[pos], false)) {
313 AERROR << "Tracking failed";
314 continue;
315 }
316 track_data->is_reserve_blind_cone_ = true;
317 ++pos;
318 continue;
319 } else {
320 // NO front-critical or beyond time -> NO OUTPUT
321 ++num_predict;
322 continue;
323 }
324 }
325 }
326 }
327 };
328 collect(&foreground_track_data_);
329 collect(&background_track_data_);
330 AINFO << "MlfEngine, num_predict: " << num_predict
331 << " num delay_output: " << num_delay_output
332 << " num front_critical: " << num_front_critical_reserve
333 << " num blind trafficcone: " << num_blind_trafficcone
334 << " num_objects: " << num_objects;
335 if (num_predict > num_objects) {
336 AERROR << "num_predict > num_objects";
337 return;
338 }
339 tracked_objects.resize(num_objects - num_predict - num_delay_output);
340}
341
342void MlfEngine::RemoveStaleTrackData(const std::string& name, double timestamp,
343 std::vector<MlfTrackDataPtr>* tracks) {
344 size_t pos = 0;
345 for (size_t i = 0; i < tracks->size(); ++i) {
346 float reserve_time = reserved_invisible_time_;
347 if (tracks->at(i)->is_front_critical_track_ &&
349 reserve_time = delay_output_;
350 }
351 if (tracks->at(i)->latest_visible_time_ + reserve_time >= timestamp ||
352 tracks->at(i)->is_reserve_blind_cone_) {
353 if (i != pos) {
354 tracks->at(pos) = tracks->at(i);
355 }
356 ++pos;
357 }
358 }
359 AINFO << "MlfEngine: " << name << " remove stale tracks, from "
360 << tracks->size() << " to " << pos;
361 tracks->resize(pos);
362}
363
364void MlfEngine::ObjectsDebugInfo(LidarFrame* frame, bool foreground_log) {
365 size_t objcnt = 0;
366 for (auto obj : frame->segmented_objects) {
367 if (foreground_log && !obj->lidar_supplement.is_background) {
368 objcnt++;
369 }
370 if (!foreground_log && obj->lidar_supplement.is_background) {
371 objcnt++;
372 }
373 }
374 std::stringstream ssstr;
375 if (foreground_log) {
376 ssstr << "[Foreground-objects] timestamp: "
377 << std::to_string(frame->timestamp) << " objs: " << objcnt
378 << std::endl;
379 } else {
380 ssstr << "[Background-objects] timestamp: "
381 << std::to_string(frame->timestamp) << " objs: " << objcnt
382 << std::endl;
383 }
384 for (auto obj : frame->segmented_objects) {
385 if (foreground_log && obj->lidar_supplement.is_background) {
386 continue;
387 }
388 if (!foreground_log && !obj->lidar_supplement.is_background) {
389 continue;
390 }
391 ssstr << "id = " << obj->id << ": " << obj->center(0) << ", "
392 << obj->center(1) << ", " << obj->center(2) << ", "
393 << obj->size(0) << ", " << obj->size(1) << ", "
394 << obj->size(2) << ", " << obj->theta << ", "
395 << static_cast<int>(obj->type) << std::endl;
396 }
397 AINFO << ssstr.str();
398}
399
401 std::stringstream sstr;
402 sstr << "[This frame TrackDataDebugInfo]: timestamp: "
403 << std::to_string(frame->timestamp) << " tracks: "
404 << foreground_track_data_.size() << std::endl;
405 sstr << "lidar2world_pose: " << sensor_to_local_pose_(0, 0) << ", "
406 << sensor_to_local_pose_(0, 1) << ", " << sensor_to_local_pose_(0, 2)
407 << ", " << sensor_to_local_pose_(0, 3) << ", "
408 << sensor_to_local_pose_(1, 0) << ", " << sensor_to_local_pose_(1, 1)
409 << ", " << sensor_to_local_pose_(1, 2) << ", "
410 << sensor_to_local_pose_(1, 3) << ", " << sensor_to_local_pose_(2, 0)
411 << ", " << sensor_to_local_pose_(2, 1) << ", "
412 << sensor_to_local_pose_(2, 2) << ", " << sensor_to_local_pose_(2, 3)
413 << ", "<< sensor_to_local_pose_(3, 0) << ", "
414 << sensor_to_local_pose_(3, 1) << ", " << sensor_to_local_pose_(3, 2)
415 << ", " << sensor_to_local_pose_(3, 3) << ", "
416 << std::to_string(global_to_local_offset_(0)) << ", "
417 << std::to_string(global_to_local_offset_(1)) << ", "
418 << std::to_string(global_to_local_offset_(2)) << std::endl;
419
420 auto debug_info = [&](std::vector<MlfTrackDataPtr>* tracks) {
421 for (auto& track_data : *tracks) {
422 const TrackedObjectConstPtr latest_obj =
423 track_data->GetLatestObject().second;
424 sstr << " track_id = " << track_data->track_id_ << ": "
425 << latest_obj->center(0) << ", " << latest_obj->center(1)
426 << ", " << latest_obj->center(2) << ", "
427 << latest_obj->size(0) << ", " << latest_obj->size(1) << ", "
428 << latest_obj->size(2) << ", "
429 << latest_obj->output_direction(0) << ", "
430 << latest_obj->output_direction(1) << ", "
431 << latest_obj->output_direction(2) << ", "
432 << static_cast<int>(latest_obj->type) << ", "
433 << std::to_string(latest_obj->object_ptr->latest_tracked_time)
434 << std::endl;
435 }
436 };
437 debug_info(&foreground_track_data_);
438 AINFO << sstr.str();
439}
440
442
443} // namespace lidar
444} // namespace perception
445} // namespace apollo
void BatchGet(size_t num, std::vector< std::shared_ptr< ObjectType > > *data) override
std::shared_ptr< ObjectType > Get() override
std::unique_ptr< MlfTracker > tracker_
Definition mlf_engine.h:146
std::vector< MlfTrackDataPtr > foreground_track_data_
Definition mlf_engine.h:140
void RemoveStaleTrackData(const std::string &name, double timestamp, std::vector< MlfTrackDataPtr > *tracks)
Remove stale track data for memory management
void TrackDebugInfo(LidarFrame *frame)
bool Track(const MultiTargetTrackerOptions &options, LidarFrame *frame) override
Track segmented objects from multiple lidar sensors
Definition mlf_engine.cc:73
std::unique_ptr< MlfTrackObjectMatcher > matcher_
Definition mlf_engine.h:148
std::vector< TrackedObjectPtr > foreground_objects_
Definition mlf_engine.h:143
void SplitAndTransformToTrackedObjects(const std::vector< base::ObjectPtr > &objects, const base::SensorInfo &sensor_info, double frame_timestamp)
Split foreground/background objects and attach to tracked objects
std::vector< MlfTrackDataPtr > background_track_data_
Definition mlf_engine.h:141
void ObjectsDebugInfo(LidarFrame *frame, bool foreground_log=true)
Output object-detection-model results and latest track results
void TrackObjectMatchAndAssign(const MlfTrackObjectMatcherOptions &match_options, const std::vector< TrackedObjectPtr > &objects, const std::string &name, std::vector< MlfTrackDataPtr > *tracks)
Match tracks and objets and object-track assignment
void TrackStateFilter(const std::vector< MlfTrackDataPtr > &tracks, double frame_timestamp)
Filter tracks
std::vector< TrackedObjectPtr > background_objects_
Definition mlf_engine.h:144
bool Init(const MultiTargetTrackerInitOptions &options=MultiTargetTrackerInitOptions()) override
Init mlf engine
Definition mlf_engine.cc:43
void CollectTrackedResult(LidarFrame *frame)
Collect track results and store in frame tracked objects
#define PERCEPTION_REGISTER_MULTITARGET_TRACKER(name)
#define ACHECK(cond)
Definition log.h:80
#define ADEBUG
Definition log.h:41
#define AERROR
Definition log.h:44
#define AINFO
Definition log.h:42
bool GetProtoFromFile(const std::string &file_name, google::protobuf::Message *message)
Parses the content of the file specified by the file_name as a representation of protobufs,...
Definition file.cc:132
bool IsObjectInRoi(const HdmapStructConstPtr roi, const ObjectConstPtr obj)
Definition roi_filter.cc:51
std::shared_ptr< const TrackedObject > TrackedObjectConstPtr
std::shared_ptr< MlfTrackData > MlfTrackDataPtr
bool JudgeBlindTrafficCone(const MlfTrackDataConstPtr &track_data, double frame_timestamp, const Eigen::Vector3d &local_to_global_offset, Eigen::Affine3d &lidar2world_pose, Eigen::Affine3d &lidar2novatel_pose)
Definition util.cc:24
std::string GetConfigFile(const std::string &config_path, const std::string &config_file)
Definition util.cc:80
class register implement
Definition arena_queue.h:37
std::shared_ptr< base::HdmapStruct > hdmap_struct
Definition lidar_frame.h:51
std::vector< std::shared_ptr< base::Object > > segmented_objects
Definition lidar_frame.h:53
std::vector< std::shared_ptr< base::Object > > tracked_objects
Definition lidar_frame.h:55