Apollo 11.0
自动驾驶开放平台
dst_existence_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 <limits>
19
20#include <boost/format.hpp>
21
22#include "modules/perception/multi_sensor_fusion/proto/dst_existence_fusion_config.pb.h"
23
24#include "cyber/common/file.h"
29
30namespace apollo {
31namespace perception {
32namespace fusion {
33
35
36const char *DstExistenceFusion::name_ = "DstExistenceFusion";
37const char *DstExistenceFusion::toic_name_ = "DstToicFusion";
38ExistenceDstMaps DstExistenceFusion::existence_dst_maps_;
39ToicDstMaps DstExistenceFusion::toic_dst_maps_;
40DstExistenceFusionOptions DstExistenceFusion::options_;
41
43 : BaseExistenceFusion(track),
44 fused_toic_(toic_name_),
45 fused_existence_(name_) {}
46
48 std::string config_file =
49 GetConfigFile(options.config_path, options.config_file);
50
52 if (!cyber::common::GetProtoFromFile(config_file, &params)) {
53 AERROR << "Read config failed: " << config_file;
54 return false;
55 }
56 for (auto valid_dist : params.camera_valid_dist()) {
57 std::string camera_id = valid_dist.camera_name();
58 options_.camera_max_valid_dist_[camera_id] = valid_dist.valid_dist();
59 AINFO << "dst existence fusion params: " << camera_id
60 << " max valid dist: " << options_.camera_max_valid_dist_[camera_id];
61 }
62
65 AINFO << "dst existence fusion params: "
66 << " track_object_max_match_distance: "
68
69 DstManager::Instance()->AddApp(name_, existence_dst_maps_.fod_subsets_,
70 existence_dst_maps_.subset_names_);
71
72 DstManager::Instance()->AddApp(toic_name_, toic_dst_maps_.fod_subsets_,
73 toic_dst_maps_.subset_names_);
74
75 return DstManager::Instance()->IsAppAdded(name_) &&
76 DstManager::Instance()->IsAppAdded(toic_name_);
77}
78
80 const SensorObjectPtr measurement, double target_timestamp,
81 double match_dist) {
82 std::string sensor_id = measurement->GetSensorId();
83 double timestamp = measurement->GetTimestamp();
84 double max_match_distance = options_.track_object_max_match_distance_;
85 double association_prob = 1 - match_dist / max_match_distance;
86 if (IsCamera(measurement)) {
87 association_prob = 1.0;
88 }
89 base::ObjectConstPtr obj = measurement->GetBaseObject();
90 double exist_factor = GetExistReliability(measurement);
91 double decay = ComputeDistDecay(obj, sensor_id, timestamp);
92 if (IsRadar(measurement)) {
93 decay = ComputeFeatureInfluence(measurement);
94 }
95 double obj_exist_prob = exist_factor * decay;
96 Dst existence_evidence(fused_existence_.Name());
97 existence_evidence.SetBba(
98 {{ExistenceDstMaps::EXIST, obj_exist_prob},
99 {ExistenceDstMaps::EXISTUNKNOWN, 1 - obj_exist_prob}});
100 // TODO(all) hard code for fused exist bba
101 const double exist_fused_w = 1.0;
102 ADEBUG << " before update exist prob: " << GetExistenceProbability();
103 fused_existence_ =
104 fused_existence_ + existence_evidence * exist_fused_w * association_prob;
105 ADEBUG << " update with, EXIST prob: " << GetExistenceProbability()
106 << " obj_id " << measurement->GetBaseObject()->track_id
107 << " association_prob: " << association_prob << " decay: " << decay
108 << " exist_prob: " << obj_exist_prob
109 << " sensor_id: " << measurement->GetSensorId()
110 << " track_id: " << track_ref_->GetTrackId();
111 if (IsCamera(measurement)) {
112 UpdateToicWithCameraMeasurement(measurement, match_dist);
113 }
114 UpdateExistenceState();
115}
116
117void DstExistenceFusion::UpdateWithoutMeasurement(const std::string &sensor_id,
118 double measurement_timestamp,
119 double target_timestamp,
120 double min_match_dist) {
121 SensorObjectConstPtr camera_object = nullptr;
122 if (algorithm::SensorManager::Instance()->IsCamera(sensor_id)) {
123 camera_object = track_ref_->GetSensorObject(sensor_id);
124 UpdateToicWithoutCameraMeasurement(sensor_id, measurement_timestamp,
125 min_match_dist);
126 }
127 SensorObjectConstPtr lidar_object = track_ref_->GetLatestLidarObject();
128 SensorObjectConstPtr camera_object_latest =
129 track_ref_->GetLatestCameraObject();
130 SensorObjectConstPtr radar_object = track_ref_->GetLatestRadarObject();
131 if ((lidar_object != nullptr && lidar_object->GetSensorId() == sensor_id) ||
132 (camera_object_latest != nullptr &&
133 camera_object_latest->GetSensorId() == sensor_id) ||
134 (radar_object != nullptr && radar_object->GetSensorId() == sensor_id &&
135 lidar_object == nullptr && camera_object_latest == nullptr)) {
136 Dst existence_evidence(fused_existence_.Name());
137 double unexist_factor = GetUnexistReliability(sensor_id);
138 base::ObjectConstPtr obj = track_ref_->GetFusedObject()->GetBaseObject();
139 double dist_decay = ComputeDistDecay(obj, sensor_id, measurement_timestamp);
140 double obj_unexist_prob = unexist_factor * dist_decay;
141 existence_evidence.SetBba(
142 {{ExistenceDstMaps::NEXIST, obj_unexist_prob},
143 {ExistenceDstMaps::EXISTUNKNOWN, 1 - obj_unexist_prob}});
144 // TODO(all) hard code for fused exist bba
145 const double unexist_fused_w = 1.0;
146 double min_match_dist_score = min_match_dist;
147 // if (!sensor_manager->IsCamera(sensor_id)) {
148 // min_match_dist_score = std::max(1 - min_match_dist /
149 // options_.track_object_max_match_distance_, 0.0);
150 // }
151 ADEBUG << " before update exist prob: " << GetExistenceProbability()
152 << " min_match_dist: " << min_match_dist
153 << " min_match_dist_score: " << min_match_dist_score;
154 fused_existence_ = fused_existence_ + existence_evidence * unexist_fused_w *
155 (1 - min_match_dist_score);
156 ADEBUG << " update without, EXIST prob: " << GetExistenceProbability()
157 << " 1 - match_dist_score: " << 1 - min_match_dist_score
158 << " sensor_id: " << sensor_id << " dist_decay: " << dist_decay
159 << " track_id: " << track_ref_->GetTrackId();
160 }
161 UpdateExistenceState();
162}
163
164double DstExistenceFusion::ComputeDistDecay(base::ObjectConstPtr obj,
165 const std::string &sensor_id,
166 double timestamp) {
167 double distance = std::numeric_limits<float>::max();
168 double dist_decay = 1.0;
169 Eigen::Affine3d sensor2world_pose;
170 bool status = SensorDataManager::Instance()->GetPose(sensor_id, timestamp,
171 &sensor2world_pose);
172 if (!status) {
173 AERROR << "Failed to get pose";
174 return dist_decay;
175 }
176 Eigen::Matrix4d world2sensor_pose = sensor2world_pose.matrix().inverse();
177 if (!world2sensor_pose.allFinite()) {
178 AERROR << boost::format(
179 "The obtained camera pose is invalid. sensor_id : %s"
180 " timestamp %16.6f") %
181 sensor_id % timestamp;
182 return dist_decay;
183 }
184 Eigen::Vector3d obj_ct = obj->center;
185 Eigen::Vector3d obj_ct_local =
186 (world2sensor_pose * obj_ct.homogeneous()).head(3);
187 distance = std::sqrt(obj_ct_local.cwiseProduct(obj_ct_local).sum());
188 if (distance > 60) {
189 dist_decay = 0.8;
190 }
191 return dist_decay;
192}
193
194double DstExistenceFusion::ComputeFeatureInfluence(
195 const SensorObjectPtr measurement) {
196 double velocity = measurement->GetBaseObject()->velocity.norm();
197 auto sigmoid_fun = [](double velocity) {
198 return 1.0 / (1.0 + exp(-velocity));
199 };
200 double velocity_fact = sigmoid_fun(velocity);
201 velocity_fact = velocity > 4.0 ? velocity_fact : 0.0;
202 double confidence = measurement->GetBaseObject()->confidence;
203 ADEBUG << " sensor_id: " << measurement->GetSensorId()
204 << " velocity: " << velocity << " velocity_fact: " << velocity_fact
205 << " confidence: " << confidence;
206 return velocity_fact * confidence;
207}
208
209double DstExistenceFusion::GetExistReliability(
210 const SensorObjectPtr measurement) {
211 bool unknown =
212 (measurement->GetBaseObject()->type == base::ObjectType::UNKNOWN ||
213 measurement->GetBaseObject()->type == base::ObjectType::UNKNOWN_MOVABLE);
214 double unknown_ratio = unknown ? 0.6 : 1.0;
215 algorithm::SensorManager *sensor_manager =
216 algorithm::SensorManager::Instance();
217 CHECK_NOTNULL(sensor_manager);
218 if (sensor_manager->IsCamera(measurement->GetSensorId())) {
219 return 0.8 * unknown_ratio;
220 }
221 if (sensor_manager->IsLidar(measurement->GetSensorId())) {
222 return 0.9 * unknown_ratio;
223 }
224 return 0.6;
225}
226
227double DstExistenceFusion::GetUnexistReliability(const std::string &sensor_id) {
228 algorithm::SensorManager *sensor_manager =
229 algorithm::SensorManager::Instance();
230 CHECK_NOTNULL(sensor_manager);
231 if (sensor_manager->IsCamera(sensor_id)) {
232 return 0.8;
233 }
234 if (sensor_manager->IsLidar(sensor_id)) {
235 return 0.9;
236 }
237 return 0.6;
238}
239
240void DstExistenceFusion::UpdateToicWithoutCameraMeasurement(
241 const std::string &sensor_id, double measurement_timestamp,
242 double min_match_dist) {
243 double dist_score = min_match_dist;
244 double in_view_ratio = 0.0;
245 // 1.get camera intrinsic and pose
246 SensorDataManager *sensor_manager = SensorDataManager::Instance();
247 ACHECK(sensor_manager != nullptr) << "Failed to get sensor manager";
248
249 base::BaseCameraModelPtr camera_model =
250 sensor_manager->GetCameraIntrinsic(sensor_id);
251 ACHECK(camera_model != nullptr)
252 << "Failed to get camera intrinsic for " << sensor_id;
253
254 Eigen::Affine3d sensor2world_pose;
255 bool status = sensor_manager->GetPose(sensor_id, measurement_timestamp,
256 &sensor2world_pose);
257 auto max_dist_it = options_.camera_max_valid_dist_.find(sensor_id);
258 if (max_dist_it == options_.camera_max_valid_dist_.end()) {
259 AWARN << boost::format(
260 "There is no pre-defined max valid camera"
261 " dist for sensor type: %s") %
262 sensor_id;
263 }
264 if (status && max_dist_it != options_.camera_max_valid_dist_.end()) {
265 SensorObjectConstPtr lidar_object = track_ref_->GetLatestLidarObject();
266 SensorObjectConstPtr radar_object = track_ref_->GetLatestRadarObject();
267 double camera_max_dist = max_dist_it->second;
268 if (lidar_object != nullptr) {
269 in_view_ratio = ObjectInCameraView(
270 lidar_object, camera_model, sensor2world_pose, measurement_timestamp,
271 camera_max_dist, true, false);
272 } else if (radar_object != nullptr) {
273 in_view_ratio = ObjectInCameraView(
274 radar_object, camera_model, sensor2world_pose, measurement_timestamp,
275 camera_max_dist, false, false);
276 }
277 }
278
279 Dst toic_evidence(fused_toic_.Name());
280 toic_evidence.SetBba({{ToicDstMaps::NTOIC, 1 - dist_score},
281 {ToicDstMaps::TOICUNKNOWN, dist_score}});
282 // TODO(yuantingrong): hard code for fused toic bba
283 const double toic_fused_w = 1.0;
284 fused_toic_ = fused_toic_ + toic_evidence * in_view_ratio * toic_fused_w;
285}
286
287void DstExistenceFusion::UpdateToicWithCameraMeasurement(
288 const SensorObjectPtr &camera_obj, double match_dist) {
289 std::string sensor_id = camera_obj->GetSensorId();
290 double timestamp = camera_obj->GetTimestamp();
291 double in_view_ratio = 0.0;
292 // 1.get camera intrinsic and pose
293 SensorDataManager *sensor_manager = SensorDataManager::Instance();
294
295 base::BaseCameraModelPtr camera_model =
296 sensor_manager->GetCameraIntrinsic(sensor_id);
297 ACHECK(camera_model != nullptr)
298 << "Failed to get camera intrinsic for " << sensor_id;
299
300 Eigen::Affine3d sensor2world_pose;
301 bool status =
302 sensor_manager->GetPose(sensor_id, timestamp, &sensor2world_pose);
303 auto max_dist_it = options_.camera_max_valid_dist_.find(sensor_id);
304 if (max_dist_it == options_.camera_max_valid_dist_.end()) {
305 AWARN << boost::format(
306 "There is no pre-defined max valid camera"
307 " dist for sensor type: %s") %
308 sensor_id;
309 } else {
310 ADEBUG << "camera dist: " << sensor_id << " " << max_dist_it->second;
311 }
312 if (status && max_dist_it != options_.camera_max_valid_dist_.end()) {
313 SensorObjectConstPtr lidar_object = track_ref_->GetLatestLidarObject();
314 SensorObjectConstPtr radar_object = track_ref_->GetLatestRadarObject();
315 double camera_max_dist = max_dist_it->second;
316 if (lidar_object != nullptr) {
317 in_view_ratio =
318 ObjectInCameraView(lidar_object, camera_model, sensor2world_pose,
319 timestamp, camera_max_dist, true, false);
320 } else if (radar_object != nullptr) {
321 in_view_ratio =
322 ObjectInCameraView(radar_object, camera_model, sensor2world_pose,
323 timestamp, camera_max_dist, false, false);
324 }
325 }
326
327 double max_match_distance = options_.track_object_max_match_distance_;
328 double association_prob = 1 - match_dist / max_match_distance;
329
330 Dst toic_evidence(fused_toic_.Name());
331 toic_evidence.SetBba({{ToicDstMaps::TOIC, association_prob},
332 {ToicDstMaps::TOICUNKNOWN, 1 - association_prob}});
333 // TODO(yuantingrong): hard code for fused toic bba
334 const double toic_fused_w = 0.7;
335 fused_toic_ = fused_toic_ + toic_evidence * toic_fused_w * in_view_ratio;
336}
337
338std::string DstExistenceFusion::Name() const { return name_; }
339
341 size_t toic_ind = DstManager::Instance()->FodSubsetToInd(
342 fused_existence_.Name(), ExistenceDstMaps::EXIST);
343 fused_existence_.ComputeProbability();
344 const std::vector<double> &existence_probs_vec =
345 fused_existence_.GetProbabilityVec();
346 return existence_probs_vec[toic_ind];
347}
348
349double DstExistenceFusion::GetToicProbability() const {
350 size_t toic_ind = DstManager::Instance()->FodSubsetToInd(fused_toic_.Name(),
352 fused_toic_.ComputeProbability();
353 const std::vector<double> &toic_probs_vec = fused_toic_.GetProbabilityVec();
354 return toic_probs_vec[toic_ind];
355}
356
357void DstExistenceFusion::UpdateExistenceState() {
358 double toic_p = GetToicProbability();
359 track_ref_->SetToicProb(toic_p);
360 double existence_p = GetExistenceProbability();
361 track_ref_->SetExistenceProb(existence_p);
362 // note, here max_p > 0.5, min_p < 0.5
363 auto scale_probability = [](double p, double max_p, double min_p) {
364 if (p > 0.5) {
365 p = 0.5 + (p - 0.5) * (max_p - 0.5) / 0.5;
366 } else {
367 p = 0.5 - (0.5 - p) * (0.5 - min_p) / 0.5;
368 }
369 return p;
370 };
371 // TODO(yuantingrong): hard code
372 const double max_p = 0.8;
373 const double min_p = 0.2;
374 double toic_score = scale_probability(toic_p, max_p, min_p);
375 // when this fused object have lidar object, just return 1.0
376 // which means wen do not want introducing historical information
377 // to affect the association, but when this fused object have just
378 // radar object, we want using the historical information to filter
379 // large amount of false positive
380 if (!(track_ref_->GetLidarObjects()).empty()) {
381 toic_score_ = 0.5;
382 } else if (!track_ref_->GetRadarObjects().empty()) {
383 toic_score_ = toic_score;
384 } else if (!track_ref_->GetCameraObjects().empty()) {
385 toic_score_ = 0.5;
386 } else {
387 AERROR << boost::format("this fused object: %d has no sensor objects") %
388 track_ref_->GetTrackId();
389 toic_score_ = 0.5;
390 }
391}
392
393} // namespace fusion
394} // namespace perception
395} // namespace apollo
void UpdateWithMeasurement(const SensorObjectPtr measurement, double target_timestamp, double match_dist) override
update track existence state with measurement
double GetExistenceProbability() const
Get existence probability
static bool Init(const ExistenceFusionInitOptions &options)
add dst application
void UpdateWithoutMeasurement(const std::string &sensor_id, double measurement_timestamp, double target_timestamp, double min_match_dist) override
update track state without measurement
bool IsAppAdded(const std::string &app_name)
Whether app added
size_t FodSubsetToInd(const std::string &app_name, const uint64_t &fod_subset)
bool AddApp(const std::string &app_name, const std::vector< uint64_t > &fod_subsets, const std::vector< std::string > &fod_subset_names=std::vector< std::string >())
const std::vector< double > & GetProbabilityVec() const
Get the Probability Vec object
bool SetBba(const std::map< uint64_t, double > &bba_map)
Set the Bba object, strictly require the fod in bba_map is valid
#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
#define AWARN
Definition log.h:43
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< BaseCameraModel > BaseCameraModelPtr
Definition camera.h:75
std::shared_ptr< const Object > ObjectConstPtr
Definition object.h:128
std::shared_ptr< const SensorObject > SensorObjectConstPtr
std::shared_ptr< SensorObject > SensorObjectPtr
bool IsCamera(const SensorObjectConstPtr &obj)
float ObjectInCameraView(SensorObjectConstPtr sensor_object, base::BaseCameraModelPtr camera_model, const Eigen::Affine3d &camera_sensor2world_pose, double camera_ts, double camera_max_dist, bool motion_compensation, bool all_in)
std::shared_ptr< Track > TrackPtr
Definition track.h:397
bool IsRadar(const SensorObjectConstPtr &obj)
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