Apollo 11.0
自动驾驶开放平台
probabilistic_fusion.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 <utility>
20
21#include "modules/perception/multi_sensor_fusion/proto/probabilistic_fusion_config.pb.h"
22
23#include "cyber/common/file.h"
34
35namespace apollo {
36namespace perception {
37namespace fusion {
38
40
42 std::string config_file =
43 GetConfigFile(options.config_path, options.config_file);
45 if (!cyber::common::GetProtoFromFile(config_file, &params)) {
46 AERROR << "Read config failed: " << config_file;
47 return false;
48 }
49
50 params_.use_lidar = params.use_lidar();
51 params_.use_radar = params.use_radar();
52 params_.use_camera = params.use_camera();
53 for (int i = 0; i < params.prohibition_sensors_size(); ++i) {
54 params_.prohibition_sensors.push_back(params.prohibition_sensors(i));
55 }
56
57 // static member initialization from PB config
62
63 scenes_.reset(new Scene());
64
65 // Init data association
66 auto data_association_param = params.data_association_param();
67 AssociationInitOptions association_init_options;
68 association_init_options.config_path = data_association_param.config_path();
69 association_init_options.config_file = data_association_param.config_file();
70 BaseDataAssociation* matcher =
71 BaseDataAssociationRegisterer::GetInstanceByName(
72 data_association_param.name());
73 CHECK_NOTNULL(matcher);
74 matcher_.reset(matcher);
75 ACHECK(matcher_->Init(association_init_options))
76 << "Fusion matcher init error";
77
78 // Init gatekeeper
79 auto gatekeeper_param = params.gatekeeper_param();
80 GatekeeperInitOptions gatekeeper_init_options;
81 gatekeeper_init_options.config_path = gatekeeper_param.config_path();
82 gatekeeper_init_options.config_file = gatekeeper_param.config_file();
83 BaseGatekeeper* gate_keeper =
84 BaseGatekeeperRegisterer::GetInstanceByName(gatekeeper_param.name());
85 CHECK_NOTNULL(gate_keeper);
86 gate_keeper_.reset(gate_keeper);
87 ACHECK(gate_keeper_->Init(gatekeeper_init_options))
88 << "Fusion gate_keeper init error";
89
90 // Init pbftracker
91 auto tracker_param = params.tracker_param();
92 TrackerInitOptions tracker_init_options;
93 // TODO(zero): pbftracker is dynamically created, so only set the name.
94 params_.tracker_method = tracker_param.name();
95 tracker_init_options.config_path = tracker_param.config_path();
96 tracker_init_options.config_file = tracker_param.config_file();
97 bool state = PbfTracker::InitParams(tracker_init_options);
98
99 return state;
100}
101
103 std::vector<base::ObjectPtr>* fused_objects) {
104 if (fused_objects == nullptr) {
105 AERROR << "fusion error: fused_objects is nullptr";
106 return false;
107 }
108
109 auto* sensor_data_manager = SensorDataManager::Instance();
110 // 1. save frame data
111 {
112 std::lock_guard<std::mutex> data_lock(data_mutex_);
113 if (!params_.use_lidar && sensor_data_manager->IsLidar(sensor_frame)) {
114 return true;
115 }
116 if (!params_.use_radar && sensor_data_manager->IsRadar(sensor_frame)) {
117 return true;
118 }
119 if (!params_.use_camera && sensor_data_manager->IsCamera(sensor_frame)) {
120 return true;
121 }
122
123 bool is_publish_sensor = IsPublishSensor(sensor_frame);
124
125 AINFO << "add sensor measurement: " << sensor_frame->sensor_info.name
126 << ", obj_cnt : " << sensor_frame->objects.size() << ", "
127 << FORMAT_TIMESTAMP(sensor_frame->timestamp);
128 sensor_data_manager->AddSensorMeasurements(sensor_frame);
129
130 if (!is_publish_sensor) {
131 return true;
132 }
133 }
134
135 // 2. query related sensor_frames for fusion
136 std::lock_guard<std::mutex> fuse_lock(fuse_mutex_);
137 double fusion_time = sensor_frame->timestamp;
138 std::vector<SensorFramePtr> frames;
139 sensor_data_manager->GetLatestFrames(fusion_time, &frames);
140 AINFO << "Get " << frames.size() << " related frames for fusion";
141
142 // 3. perform fusion on related frames
143 for (const auto& frame : frames) {
144 FuseFrame(frame);
145 }
146
147 // 4. collect fused objects
148 CollectFusedObjects(fusion_time, fused_objects);
149 return true;
150}
151
152bool ProbabilisticFusion::IsPublishSensor(
153 const base::FrameConstPtr& sensor_frame) const {
154 std::string sensor_id = sensor_frame->sensor_info.name;
155 bool is_main_sensor =
156 algorithm::SensorManager::Instance()->IsMainSensor(sensor_id);
157 return is_main_sensor;
158}
159
160void ProbabilisticFusion::FuseFrame(const SensorFramePtr& frame) {
161 AINFO << "Fusing frame: " << frame->GetSensorId()
162 << ", foreground_object_number: "
163 << frame->GetForegroundObjects().size()
164 << ", background_object_number: "
165 << frame->GetBackgroundObjects().size()
166 << ", timestamp: " << FORMAT_TIMESTAMP(frame->GetTimestamp());
167 FuseForegroundTrack(frame);
168 FusebackgroundTrack(frame);
169 RemoveLostTrack();
170}
171
172void ProbabilisticFusion::FuseForegroundTrack(const SensorFramePtr& frame) {
173 AssociationOptions options;
174 AssociationResult association_result;
175 matcher_->Associate(options, frame, scenes_, &association_result);
176
177 const std::vector<TrackMeasurmentPair>& assignments =
178 association_result.assignments;
179 UpdateAssignedTracks(frame, assignments);
180
181 const std::vector<size_t>& unassigned_track_inds =
182 association_result.unassigned_tracks;
183 UpdateUnassignedTracks(frame, unassigned_track_inds);
184
185 const std::vector<size_t>& unassigned_obj_inds =
186 association_result.unassigned_measurements;
187 CreateNewTracks(frame, unassigned_obj_inds);
188}
189
190void ProbabilisticFusion::UpdateAssignedTracks(
191 const SensorFramePtr& frame,
192 const std::vector<TrackMeasurmentPair>& assignments) {
193 // Attention: match_distance should be used
194 // in ExistenceFusion to calculate existence score.
195 // We set match_distance to zero if track and object are matched,
196 // which only has a small difference compared with actural match_distance
197 TrackerOptions options;
198 options.match_distance = 0;
199 std::vector<SensorObjectPtr>& f_ground_objs = frame->GetForegroundObjects();
200 for (size_t i = 0; i < assignments.size(); ++i) {
201 size_t track_ind = assignments[i].first;
202 size_t obj_ind = assignments[i].second;
203 trackers_[track_ind]->UpdateWithMeasurement(options, f_ground_objs[obj_ind],
204 frame->GetTimestamp());
205 }
206}
207
208void ProbabilisticFusion::UpdateUnassignedTracks(
209 const SensorFramePtr& frame,
210 const std::vector<size_t>& unassigned_track_inds) {
211 // Attention: match_distance(min_match_distance) should be used
212 // in ExistenceFusion to calculate toic score.
213 // Due to it hasn't been used(mainly for front radar object pub in
214 // gatekeeper),
215 // we do not set match_distance temporarily.
216 TrackerOptions options;
217 options.match_distance = 0;
218 std::string sensor_id = frame->GetSensorId();
219 for (size_t i = 0; i < unassigned_track_inds.size(); ++i) {
220 size_t track_ind = unassigned_track_inds[i];
221 trackers_[track_ind]->UpdateWithoutMeasurement(
222 options, sensor_id, frame->GetTimestamp(), frame->GetTimestamp());
223 }
224}
225
226void ProbabilisticFusion::CreateNewTracks(
227 const SensorFramePtr& frame,
228 const std::vector<size_t>& unassigned_obj_inds) {
229 // check valid
230 bool prohibition_sensor_flag = false;
231 std::for_each(params_.prohibition_sensors.begin(),
232 params_.prohibition_sensors.end(),
233 [&](const std::string& sensor_name) {
234 if (sensor_name == frame->GetSensorId())
235 prohibition_sensor_flag = true;
236 });
237 if (prohibition_sensor_flag) {
238 return;
239 }
240
241 // add new track
242 std::vector<SensorObjectPtr>& f_ground_objs = frame->GetForegroundObjects();
243 for (const size_t& obj_ind : unassigned_obj_inds) {
244 TrackPtr track = TrackPool::Instance().Get();
245 track->Initialize(f_ground_objs[obj_ind]);
246 scenes_->AddForegroundTrack(track);
247
248 ADEBUG << "object id: " << f_ground_objs[obj_ind]->GetBaseObject()->track_id
249 << ", create new track: " << track->GetTrackId();
250
251 if (params_.tracker_method == "PbfTracker") {
252 std::shared_ptr<BaseTracker> tracker;
253 tracker.reset(new PbfTracker());
254 tracker->Init(track, f_ground_objs[obj_ind]);
255 trackers_.emplace_back(tracker);
256 }
257 }
258}
259
260void ProbabilisticFusion::FusebackgroundTrack(const SensorFramePtr& frame) {
261 // 1. association
262 size_t track_size = scenes_->GetBackgroundTracks().size();
263 size_t obj_size = frame->GetBackgroundObjects().size();
264 std::map<int, size_t> local_id_2_track_ind_map;
265 std::vector<bool> track_tag(track_size, false);
266 std::vector<bool> object_tag(obj_size, false);
267
268 std::vector<TrackPtr>& background_tracks = scenes_->GetBackgroundTracks();
269 for (size_t i = 0; i < track_size; ++i) {
270 const FusedObjectPtr& obj = background_tracks[i]->GetFusedObject();
271 int local_id = obj->GetBaseObject()->track_id;
272 local_id_2_track_ind_map[local_id] = i;
273 }
274
275 std::vector<TrackMeasurmentPair> assignments;
276 std::vector<SensorObjectPtr>& frame_objs = frame->GetBackgroundObjects();
277 for (size_t i = 0; i < obj_size; ++i) {
278 int local_id = frame_objs[i]->GetBaseObject()->track_id;
279 const auto& it = local_id_2_track_ind_map.find(local_id);
280 if (it != local_id_2_track_ind_map.end()) {
281 size_t track_ind = it->second;
282 assignments.push_back(std::make_pair(track_ind, i));
283 track_tag[track_ind] = true;
284 object_tag[i] = true;
285 }
286 }
287
288 // 2. update assigned track
289 for (size_t i = 0; i < assignments.size(); ++i) {
290 size_t track_ind = assignments[i].first;
291 size_t obj_ind = assignments[i].second;
292 background_tracks[track_ind]->UpdateWithSensorObject(frame_objs[obj_ind]);
293 }
294
295 // 3. update unassigned track
296 std::string sensor_id = frame->GetSensorId();
297 for (size_t i = 0; i < track_tag.size(); ++i) {
298 if (!track_tag[i]) {
299 background_tracks[i]->UpdateWithoutSensorObject(sensor_id,
300 frame->GetTimestamp());
301 }
302 }
303
304 // 4. create new track
305 for (size_t i = 0; i < object_tag.size(); ++i) {
306 if (!object_tag[i]) {
307 TrackPtr track = TrackPool::Instance().Get();
308 track->Initialize(frame_objs[i], true);
309 scenes_->AddBackgroundTrack(track);
310 }
311 }
312}
313
314void ProbabilisticFusion::RemoveLostTrack() {
315 // need to remove tracker at the same time
316 size_t f_alive_index = 0;
317 std::vector<TrackPtr>& foreground_tracks = scenes_->GetForegroundTracks();
318 for (size_t i = 0; i < foreground_tracks.size(); ++i) {
319 if (foreground_tracks[i]->IsAlive()) {
320 foreground_tracks[f_alive_index] = foreground_tracks[i];
321 trackers_[f_alive_index] = trackers_[i];
322 ++f_alive_index;
323 }
324 }
325 AINFO << "Remove " << foreground_tracks.size() - f_alive_index
326 << " foreground tracks. " << f_alive_index << " tracks left.";
327 foreground_tracks.resize(f_alive_index);
328 trackers_.resize(f_alive_index);
329
330 // only need to remove frame track
331 size_t b_alive_index = 0;
332 std::vector<TrackPtr>& background_tracks = scenes_->GetBackgroundTracks();
333 for (size_t i = 0; i < background_tracks.size(); ++i) {
334 if (background_tracks[i]->IsAlive()) {
335 background_tracks[b_alive_index] = background_tracks[i];
336 ++b_alive_index;
337 }
338 }
339 AINFO << "Remove " << background_tracks.size() - b_alive_index
340 << " background tracks";
341 background_tracks.resize(b_alive_index);
342}
343
344void ProbabilisticFusion::CollectFusedObjects(
345 double timestamp, std::vector<base::ObjectPtr>* fused_objects) {
346 CHECK_NOTNULL(fused_objects);
347 fused_objects->clear();
348
349 size_t fg_obj_num = 0;
350 const std::vector<TrackPtr>& foreground_tracks =
351 scenes_->GetForegroundTracks();
352 for (const auto& track_ptr : foreground_tracks) {
353 if (gate_keeper_->AbleToPublish(track_ptr)) {
354 CollectObjectsByTrack(timestamp, track_ptr, fused_objects);
355 ++fg_obj_num;
356 }
357 }
358
359 size_t bg_obj_num = 0;
360 const std::vector<TrackPtr>& background_tracks =
361 scenes_->GetBackgroundTracks();
362 for (const auto& track_ptr : background_tracks) {
363 if (gate_keeper_->AbleToPublish(track_ptr)) {
364 CollectObjectsByTrack(timestamp, track_ptr, fused_objects);
365 ++bg_obj_num;
366 }
367 }
368
369 AINFO << "collect objects : fg_obj_cnt = " << fg_obj_num
370 << ", bg_obj_cnt = " << bg_obj_num
371 << ", timestamp = " << FORMAT_TIMESTAMP(timestamp);
372}
373
374void ProbabilisticFusion::CollectObjectsByTrack(
375 double timestamp, const TrackPtr& track,
376 std::vector<base::ObjectPtr>* fused_objects) {
377 CHECK_NOTNULL(track);
378 const FusedObjectPtr& fused_object = track->GetFusedObject();
379 base::ObjectPtr obj = base::ObjectPool::Instance().Get();
380 *obj = *(fused_object->GetBaseObject());
381
382 // create obj->fusion_supplement.measurements
383 const SensorId2ObjectMap& lidar_measurements = track->GetLidarObjects();
384 const SensorId2ObjectMap& camera_measurements = track->GetCameraObjects();
385 const SensorId2ObjectMap& radar_measurements = track->GetRadarObjects();
386
387 size_t num_measurements = lidar_measurements.size() +
388 camera_measurements.size() +
389 radar_measurements.size();
390 obj->fusion_supplement.on_use = true;
391 auto& measurements = obj->fusion_supplement.measurements;
392 measurements.resize(num_measurements);
393
394 // fill measurements
395 size_t m_index = 0;
396 for (const auto& iter : lidar_measurements) {
397 CollectSensorMeasurementFromObject(iter.second, &measurements[m_index++]);
398 }
399 for (const auto& iter : camera_measurements) {
400 CollectSensorMeasurementFromObject(iter.second, &measurements[m_index++]);
401 }
402 for (const auto& iter : radar_measurements) {
403 CollectSensorMeasurementFromObject(iter.second, &measurements[m_index++]);
404 }
405
406 // save to fused_objects
407 obj->track_id = track->GetTrackId();
408 obj->latest_tracked_time = timestamp;
409 obj->tracking_time = track->GetTrackingPeriod();
410 fused_objects->emplace_back(obj);
411
412 ADEBUG << "fusion_reporting..." << obj->track_id << "@"
413 << FORMAT_TIMESTAMP(timestamp) << "@(" << std::setprecision(10)
414 << obj->center(0) << "," << obj->center(1) << ","
415 << obj->center_uncertainty(0, 0) << ","
416 << obj->center_uncertainty(0, 1) << ","
417 << obj->center_uncertainty(1, 0) << ","
418 << obj->center_uncertainty(1, 1) << "," << obj->velocity(0) << ","
419 << obj->velocity(1) << "," << obj->velocity_uncertainty(0, 0) << ","
420 << obj->velocity_uncertainty(0, 1) << ","
421 << obj->velocity_uncertainty(1, 0) << ","
422 << obj->velocity_uncertainty(1, 1) << ")";
423}
424
425void ProbabilisticFusion::CollectSensorMeasurementFromObject(
426 const SensorObjectConstPtr& object,
427 base::SensorObjectMeasurement* measurement) {
428 CHECK_NOTNULL(object);
429 CHECK_NOTNULL(measurement);
430 measurement->sensor_id = object->GetSensorId();
431 measurement->timestamp = object->GetTimestamp();
432 measurement->track_id = object->GetBaseObject()->track_id;
433 measurement->center = object->GetBaseObject()->center;
434 measurement->theta = object->GetBaseObject()->theta;
435 measurement->size = object->GetBaseObject()->size;
436 measurement->velocity = object->GetBaseObject()->velocity;
437 measurement->type = object->GetBaseObject()->type;
438 if (IsCamera(object)) {
439 measurement->box = object->GetBaseObject()->camera_supplement.box;
440 }
441}
442
444
445} // namespace fusion
446} // namespace perception
447} // namespace apollo
#define FUSION_REGISTER_FUSIONSYSTEM(name)
std::shared_ptr< ObjectType > Get() override
static bool InitParams(const TrackerInitOptions &options)
Init params
bool Init(const FusionInitOptions &options) override
Initialization
bool Fuse(const base::FrameConstPtr &sensor_frame, std::vector< base::ObjectPtr > *fused_objects) override
Probabilistic fusion of sensor data, the input is the detection results of different sensors,...
static void SetMaxCachedFrameNumber(size_t number)
Definition sensor.h:67
static void SetMaxRadarInvisiblePeriod(double period)
Set the max radar invisible period
Definition track.h:51
static void SetMaxCameraInvisiblePeriod(double period)
Set the max camera invisible period
Definition track.h:60
static void SetMaxLidarInvisiblePeriod(double period)
Set the max lidar invisible period
Definition track.h:42
#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
std::string GetAbsolutePath(const std::string &prefix, const std::string &relative_path)
Get absolute path by concatenating prefix and relative_path.
Definition file.cc:179
std::shared_ptr< Object > ObjectPtr
Definition object.h:127
std::shared_ptr< const Frame > FrameConstPtr
Definition frame.h:61
std::shared_ptr< const SensorObject > SensorObjectConstPtr
bool IsCamera(const SensorObjectConstPtr &obj)
std::shared_ptr< SensorFrame > SensorFramePtr
std::shared_ptr< Track > TrackPtr
Definition track.h:397
std::shared_ptr< FusedObject > FusedObjectPtr
std::map< std::string, SensorObjectPtr > SensorId2ObjectMap
Definition track.h:30
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
Some string util functions.
#define FORMAT_TIMESTAMP(timestamp)
Definition string_util.h:29