Apollo 11.0
自动驾驶开放平台
mlf_motion_filter.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 <algorithm>
20#include <limits>
21#include <vector>
22
23#include "cyber/common/file.h"
26#include "modules/perception/lidar_tracking/tracker/multi_lidar_fusion/proto/multi_lidar_fusion_config.pb.h"
27
28namespace apollo {
29namespace perception {
30namespace lidar {
31
33 std::string config_file = "mlf_motion_filter.conf";
34 if (!options.config_file.empty()) {
35 config_file = options.config_file;
36 }
37 config_file = GetConfigFile(
38 options.config_path, config_file);
40 ACHECK(cyber::common::GetProtoFromFile(config_file, &config));
41 use_adaptive_ = config.use_adaptive();
53
55
57 MlfMotionRefinerInitOptions mlf_motion_refiner_options;
58 mlf_motion_refiner_options.config_path = options.config_path;
59 ACHECK(motion_refiner_->Init(mlf_motion_refiner_options));
60 return true;
61}
62
64 const MlfTrackDataConstPtr& track_data,
65 TrackedObjectPtr new_object) {
66 if (track_data->age_ == 0) {
67 InitializeTrackState(new_object);
68 return;
69 }
70 if (new_object->is_background) {
71 InitializeTrackState(new_object);
72 return;
73 }
74 // 1. compute measurement
75 motion_measurer_->ComputeMotionMeasurment(track_data, new_object);
76 if (!use_adaptive_) {
77 new_object->update_quality = 1.0;
78 }
79 TrackedObjectConstPtr latest_object = track_data->GetLatestObject().second;
80 // 2. kalman filter update
81 KalmanFilterUpdateWithPartialObservation(track_data, latest_object,
82 new_object);
83 StateToBelief(new_object);
84 // 3. boostup state and static object velocity clapping
86 ConvergenceEstimationAndBoostUp(track_data, latest_object, new_object);
87 }
88 ClipingState(new_object);
89 StateToBelief(new_object);
90 // 4. online covariance estimation
91 BeliefToOutput(new_object);
92 // 5. post refine and recompute online covariance if necessary
93 if (motion_refiner_->Refine(track_data, new_object)) {
94 // use output velocity to recompute convergence confidence
95 ComputeConvergenceConfidence(track_data, new_object, false);
96 UpdateConverged(track_data, new_object);
97 }
98 OnlineCovarianceEstimation(track_data, new_object);
99}
100
102 double timestamp,
103 MlfTrackDataPtr track_data) {}
104
106 new_object->boostup_need_history_size =
107 static_cast<int>(boostup_history_size_minimum_);
108 new_object->convergence_confidence = use_convergence_boostup_ ? 0.0 : 1.0;
109 new_object->converged = !use_convergence_boostup_;
110 new_object->update_quality = 1.0;
111 new_object->selected_measured_velocity = Eigen::Vector3d::Zero();
112 new_object->selected_measured_acceleration = Eigen::Vector3d::Zero();
113 new_object->belief_anchor_point = new_object->anchor_point;
114 new_object->belief_velocity = Eigen::Vector3d::Zero();
115 new_object->belief_acceleration = Eigen::Vector3d::Zero();
116 new_object->belief_velocity_gain = Eigen::Vector3d::Zero();
117 new_object->state = Eigen::Vector4d::Zero();
118 new_object->measurement_covariance = Eigen::Matrix4d();
119 new_object->state_covariance = Eigen::Matrix4d();
120
121 // covariances initialize
122 new_object->velocity_covariance =
123 Eigen::Matrix3d::Identity() * init_velocity_variance_;
124 new_object->belief_velocity_online_covariance =
125 new_object->velocity_covariance;
126
127 new_object->state_covariance = Eigen::Matrix4d::Identity();
128 new_object->state_covariance.block<2, 2>(0, 0) *= init_velocity_variance_;
129 new_object->state_covariance.block<2, 2>(2, 2) *= init_acceleration_variance_;
130
131 StateToBelief(new_object);
132 BeliefToOutput(new_object);
133}
134
136 const MlfTrackDataConstPtr& track_data,
137 const TrackedObjectConstPtr& latest_object, TrackedObjectPtr new_object) {
138 double range = new_object->object_ptr->center.norm();
139
140 const Eigen::Vector4d& last_state = latest_object->state;
141 const Eigen::Matrix4d& last_state_covariance =
142 latest_object->state_covariance;
143
144 double time_diff = new_object->object_ptr->latest_tracked_time -
145 latest_object->object_ptr->latest_tracked_time;
146 if (time_diff < EPSION_TIME) { // Very small time than assign
147 time_diff = DEFAULT_FPS;
148 }
149 Eigen::Matrix4d transition = Eigen::Matrix4d::Identity();
150 transition(0, 2) = transition(1, 3) = time_diff;
151
152 // composition with rotation
153 if (new_object->type != base::ObjectType::PEDESTRIAN &&
154 range < trust_orientation_range_) {
155 Eigen::Vector2d cur_dir = new_object->direction.head<2>();
156 Eigen::Vector2d pre_dir = latest_object->direction.head<2>();
157 cur_dir.normalize();
158 pre_dir.normalize();
159 double cos_theta = cur_dir.dot(pre_dir);
160 double sin_theta = pre_dir(0) * cur_dir(1) - pre_dir(1) * cur_dir(0);
161 Eigen::Matrix2d rot;
162 rot << cos_theta, -sin_theta, sin_theta, cos_theta;
163 Eigen::Matrix4d rot_extend = Eigen::Matrix4d::Zero();
164 rot_extend.block<2, 2>(0, 0) = rot;
165 rot_extend.block<2, 2>(2, 2) = rot;
166 transition = rot_extend * transition;
167 }
168
169 auto& state = new_object->state;
170 auto& state_covariance = new_object->state_covariance;
171 auto measurement_covariance =
172 new_object->measurement_covariance.block<2, 2>(0, 0);
173 // 1. prediction stage
174 Eigen::Matrix4d predict_covariance = Eigen::Matrix4d::Identity() *
176 time_diff * time_diff;
177 state = transition * last_state;
178 state_covariance =
179 transition * last_state_covariance * transition.transpose() +
180 predict_covariance;
181
182 // 2. measurement update stage
183 Eigen::Vector2d measurement;
184 measurement << new_object->selected_measured_velocity.head<2>();
185
186 Eigen::Vector2d direction = new_object->direction.head<2>();
187 direction.normalize();
188 Eigen::Vector2d odirection(direction(1), -direction(0));
189 if (new_object->type == base::ObjectType::PEDESTRIAN &&
190 range < trust_orientation_range_) {
191 measurement_covariance = Eigen::Matrix2d::Identity();
192 measurement_covariance *= measured_velocity_variance_;
193 } else {
194 const double kVarianceAmplifier = 9.0;
195 measurement_covariance =
196 measured_velocity_variance_ * direction * direction.transpose() +
198 fabs(measurement.dot(odirection)) * kVarianceAmplifier) *
199 odirection * odirection.transpose();
200 }
201 // when association_cost is larger, we scale measurement for protect
202 float scale = pow(1 + new_object->association_score, 2) * 1.1;
203 measurement_covariance *= scale;
204
205 Eigen::Matrix<double, 2, 4> observation_transform;
206 observation_transform.block<2, 2>(0, 0).setIdentity();
207 observation_transform.block<2, 2>(0, 2).setZero();
208 Eigen::Matrix<double, 4, 2> kalman_gain_matrix =
209 static_cast<Eigen::Matrix<double, 4, 2, 0, 4, 2>>(
210 state_covariance * observation_transform.transpose() *
211 (observation_transform * state_covariance *
212 observation_transform.transpose() +
213 measurement_covariance)
214 .inverse());
215 Eigen::Vector4d state_gain =
216 static_cast<Eigen::Matrix<double, 4, 1, 0, 4, 1>>(
217 kalman_gain_matrix * (measurement - observation_transform * state));
218
219 // 3. gain adjustment and estimate posterior
220 StateGainAdjustment(track_data, latest_object, new_object, &state_gain);
221
222 state = state + state_gain;
223 state_covariance = (Eigen::Matrix4d::Identity() -
224 kalman_gain_matrix * observation_transform) *
225 state_covariance;
226
227 // 4. finally, state to belief and output to keep consistency
228 new_object->belief_velocity_gain << state_gain.head<2>(), 0;
229}
230
232 const MlfTrackDataConstPtr& track_data,
233 const TrackedObjectConstPtr& latest_object,
234 const TrackedObjectConstPtr& new_object, Eigen::Vector4d* gain) {
235 // 1 quality penalize and gain break down
236 if (use_adaptive_) {
237 *gain *= new_object->update_quality;
238 }
239 // 2 breakdown the constrained the max allowed change of state
240 if (use_breakdown_) {
241 // velocity breakdown threshold
242 double velocity_breakdown_threshold = 10.0 - (track_data->age_ - 1) * 2;
243 velocity_breakdown_threshold = std::max(velocity_breakdown_threshold, 0.3);
244 double velocity_gain = gain->head<2>().norm();
245 if (velocity_gain > velocity_breakdown_threshold) {
246 gain->head<2>() *= velocity_breakdown_threshold / velocity_gain;
247 }
248 // acceleration breakdown threshold
249 double acceleration_breakdown_threshold = 2.0;
250 double acceleration_gain = gain->tail<2>().norm();
251 if (acceleration_gain > acceleration_breakdown_threshold) {
252 gain->tail<2>() *= acceleration_breakdown_threshold / acceleration_gain;
253 }
254 }
255}
256
258 object->belief_velocity << object->state.head<2>(), 0;
259 object->belief_acceleration << object->state.tail<2>(), 0;
260}
261
263 object->output_velocity = object->belief_velocity;
264 object->output_velocity_uncertainty =
265 object->belief_velocity_online_covariance;
266}
267
269 if (object->state.head<2>().norm() < noise_maximum_) {
270 object->state.setZero();
271 object->belief_velocity_gain.setZero();
272 object->state_covariance.block<2, 2>(0, 2).setZero();
273 object->state_covariance.block<2, 2>(2, 0).setZero();
274 }
275}
276
278 const MlfTrackDataConstPtr& track_data, TrackedObjectPtr object) {
279 object->belief_velocity_online_covariance = Eigen::Matrix3d::Zero();
280 size_t evaluate_window =
281 std::min(track_data->history_objects_.size(),
282 static_cast<size_t>(object->boostup_need_history_size));
283 if (evaluate_window == 0) {
284 // a default large covariance
285 object->belief_velocity_online_covariance = Eigen::Matrix3d::Identity() *
288 return;
289 }
290 // compute online covariance
291 auto cur_obj_pair = track_data->history_objects_.rbegin();
292 for (size_t i = 0; i < evaluate_window; ++i) {
293 Eigen::Vector3d velocity_resisual =
294 cur_obj_pair->second->selected_measured_velocity -
295 object->output_velocity;
296 if (velocity_resisual.head(2).norm() <
297 std::numeric_limits<double>::epsilon()) {
298 velocity_resisual =
299 Eigen::Vector3d::Identity() * noise_maximum_ * noise_maximum_;
300 }
301 ++cur_obj_pair;
302 object->belief_velocity_online_covariance.block<2, 2>(0, 0) +=
303 velocity_resisual.head<2>() * velocity_resisual.head<2>().transpose();
304 }
305 object->belief_velocity_online_covariance /=
306 static_cast<double>(evaluate_window);
307 object->belief_velocity_online_covariance +=
308 Eigen::Matrix3d::Identity() * noise_maximum_ * noise_maximum_;
309 object->output_velocity_uncertainty =
310 object->belief_velocity_online_covariance;
311}
312
314 const MlfTrackDataConstPtr& track_data,
315 const TrackedObjectConstPtr& latest_object, TrackedObjectPtr new_object) {
316 new_object->boostup_need_history_size =
317 latest_object->boostup_need_history_size;
318 new_object->converged = latest_object->converged;
319 new_object->convergence_confidence = latest_object->convergence_confidence;
320
321 // +1 means new object measure velocity
322 // -1 means first object without measure velocity not considered
323 size_t window_size = 1 + track_data->history_objects_.size() - 1;
324
325 // Boostup convergence when its confidence is small than minimum
326 ComputeConvergenceConfidence(track_data, new_object, true);
327 UpdateConverged(track_data, new_object);
328
329 // do not boostup belief if usable measure velocity is not enough
330 if (window_size <
331 static_cast<size_t>(new_object->boostup_need_history_size)) {
332 return;
333 }
334 // boostup belief if not converged yet
335 if (!new_object->converged) {
336 BoostupState(track_data, new_object);
337 ComputeConvergenceConfidence(track_data, new_object, true);
338 UpdateConverged(track_data, new_object);
339 }
340}
341
343 const MlfTrackDataConstPtr& track_data, TrackedObjectPtr new_object,
344 bool velocity_source_is_belief) {
345 // Compute convergence score list
346 std::vector<double> convergence_score_list;
347 int boostup_need_history_size = new_object->boostup_need_history_size;
348 auto& history_objects = track_data->history_objects_;
349
350 convergence_score_list.resize(boostup_need_history_size, 0.0);
351 double base_convergence_noise = 2 * measured_velocity_variance_;
352
353 // new object score
354 Eigen::Vector3d velocity_residual =
355 new_object->selected_measured_velocity -
356 (velocity_source_is_belief ? new_object->belief_velocity
357 : new_object->output_velocity);
358 convergence_score_list[0] =
359 base_convergence_noise /
360 std::max(base_convergence_noise, velocity_residual.norm());
361
362 // history objects score
363 size_t visible_obj_idx = 1;
364 for (auto cur_object_pair = history_objects.rbegin();
365 cur_object_pair != history_objects.rend(); ++cur_object_pair) {
366 TrackedObjectPtr cur_object = cur_object_pair->second;
367 if (visible_obj_idx >= convergence_score_list.size() ||
368 visible_obj_idx >= history_objects.size()) {
369 break;
370 }
371 velocity_residual =
372 cur_object->selected_measured_velocity -
373 (velocity_source_is_belief ? new_object->belief_velocity
374 : new_object->output_velocity);
375 convergence_score_list[visible_obj_idx] =
376 base_convergence_noise /
377 std::max(base_convergence_noise, velocity_residual.norm());
378 ++visible_obj_idx;
379 }
380 // Compute convergence confidence
381 if (!new_object->converged) {
382 double min_convergence_confidence_score = 1.0; // maximum
383 for (size_t i = 0; i < static_cast<size_t>(boostup_need_history_size);
384 ++i) {
385 if (min_convergence_confidence_score > convergence_score_list[i]) {
386 min_convergence_confidence_score = convergence_score_list[i];
387 }
388 }
389 new_object->convergence_confidence =
390 static_cast<float>(min_convergence_confidence_score);
391 } else {
392 double mean_convergence_confidence_score = 0; // mean
393 for (size_t i = 0; i < static_cast<size_t>(boostup_need_history_size);
394 ++i) {
395 mean_convergence_confidence_score += convergence_score_list[i];
396 }
397 mean_convergence_confidence_score /= boostup_need_history_size;
398 new_object->convergence_confidence =
399 static_cast<float>(mean_convergence_confidence_score);
400 }
401}
402
404 TrackedObjectPtr new_object) {
405 // Compute min & max boosted velocity
406 Eigen::Vector3d& new_obj_belief_velocity = new_object->belief_velocity;
407 Eigen::Vector3d min_boosted_velocity = new_obj_belief_velocity;
408 constexpr double kDoubleMax = std::numeric_limits<double>::max();
409 double min_boosted_velocity_norm = kDoubleMax;
410 Eigen::Vector3d max_boosted_velocity = new_obj_belief_velocity;
411 double max_boosted_velocity_norm = kDoubleMax;
412 Eigen::Vector3d project_dir = min_boosted_velocity;
413 project_dir(2) = 0.0;
414 project_dir.normalize();
415
416 int boostup_need_history_size = new_object->boostup_need_history_size;
417 int actual_boostup_history_size =
418 static_cast<size_t>(boostup_need_history_size) >
419 track_data->history_objects_.size()
420 ? static_cast<int>(track_data->history_objects_.size())
421 : boostup_need_history_size;
422 int boostup_used_history_size = 0;
423 auto& history_objects = track_data->history_objects_;
424 auto cur_object_pair = history_objects.rbegin();
425 TrackedObjectPtr cur_object = new_object;
426 while (boostup_used_history_size < actual_boostup_history_size &&
427 cur_object_pair != history_objects.rend()) {
428 ++boostup_used_history_size;
429 Eigen::Vector3d measured_velocity = cur_object->selected_measured_velocity;
430 Eigen::Vector3d measured_velocity_on_project_dir =
431 algorithm::Calculate2DXYProjectVector<double>(measured_velocity,
432 new_obj_belief_velocity);
433 if (measured_velocity_on_project_dir.dot(new_obj_belief_velocity) <= 0) {
434 measured_velocity_on_project_dir = Eigen::Vector3d::Zero();
435 }
436 double measured_velocity_norm_on_project_dir =
437 measured_velocity_on_project_dir.norm();
438 if (measured_velocity_norm_on_project_dir < min_boosted_velocity_norm) {
439 min_boosted_velocity = measured_velocity_on_project_dir;
440 min_boosted_velocity_norm = measured_velocity_norm_on_project_dir;
441 }
442 if (measured_velocity_norm_on_project_dir > max_boosted_velocity_norm) {
443 max_boosted_velocity = measured_velocity_on_project_dir;
444 max_boosted_velocity_norm = measured_velocity_norm_on_project_dir;
445 }
446 if (boostup_used_history_size > 1) {
447 ++cur_object_pair;
448 }
449 if (cur_object_pair != history_objects.rend()) {
450 cur_object = cur_object_pair->second;
451 }
452 }
453 // Increase belief when belief less than min boosted velocity
454 // Decrease belief when belief greater than max boosted velocity
455 // now boosted_acceleration not used in original version, maybe use later
456 if (min_boosted_velocity_norm > new_obj_belief_velocity.norm()) {
457 // Eigen::Vector3d boosted_acceleration =
458 // (min_boosted_velocity - new_obj_belief_velocity)/new_latest_time_diff_;
459 new_obj_belief_velocity = min_boosted_velocity;
460 } else if (max_boosted_velocity_norm < new_obj_belief_velocity.norm()) {
461 // Eigen::Vector3d boosted_acceleration =
462 // (max_boosted_velocity - new_obj_belief_velocity)/new_latest_time_diff_;
463 new_obj_belief_velocity = max_boosted_velocity;
464 }
465 new_object->state.head<2>() = new_obj_belief_velocity.head<2>();
466}
467
469 TrackedObjectPtr object) {
470 if (object->convergence_confidence > converged_confidence_minimum_) {
471 // set converged true
472 object->converged = true;
473 // increase cached history size if necessary
474 if (track_data->history_objects_.size() <
475 static_cast<size_t>(object->boostup_need_history_size)) {
476 return;
477 }
478 if (static_cast<size_t>(object->boostup_need_history_size) <
480 object->boostup_need_history_size += 1;
481 }
482 } else {
483 object->converged = false;
484 }
485}
486
488
489} // namespace lidar
490} // namespace perception
491} // namespace apollo
void UpdateWithObject(const MlfFilterOptions &options, const MlfTrackDataConstPtr &track_data, TrackedObjectPtr new_object) override
Updating motion filter with object
void KalmanFilterUpdateWithPartialObservation(const MlfTrackDataConstPtr &track_data, const TrackedObjectConstPtr &latest_object, TrackedObjectPtr new_object)
Update state with kalman filter, constant acceleration motion model, only velocity measurement is obs...
void StateToBelief(TrackedObjectPtr object)
Synchronize state to belief to keep consistency
void ConvergenceEstimationAndBoostUp(const MlfTrackDataConstPtr &track_data, const TrackedObjectConstPtr &latest_object, TrackedObjectPtr new_object)
Estimate convergence confidence and boost up state
void UpdateConverged(const MlfTrackDataConstPtr &track_data, TrackedObjectPtr object)
Update convergence confidence
void UpdateWithoutObject(const MlfFilterOptions &options, double timestamp, MlfTrackDataPtr track_data) override
Updating motion filter without object
void ComputeConvergenceConfidence(const MlfTrackDataConstPtr &track_data, TrackedObjectPtr new_object, bool velocity_source_is_belief=true)
Compute convergence confidence
void StateGainAdjustment(const MlfTrackDataConstPtr &track_data, const TrackedObjectConstPtr &latest_object, const TrackedObjectConstPtr &new_object, Eigen::Vector4d *gain)
Adjust kalman state gain with several strategies
void BeliefToOutput(TrackedObjectPtr object)
Copy belief to output
void InitializeTrackState(TrackedObjectPtr new_object)
Initialize track state and store in the new object
std::shared_ptr< MlfMotionRefiner > motion_refiner_
void ClipingState(TrackedObjectPtr object)
Cliping state if is within noise level
bool Init(const MlfFilterInitOptions &options=MlfFilterInitOptions()) override
Init mlf fitler
std::shared_ptr< MlfMotionMeasurement > motion_measurer_
void BoostupState(const MlfTrackDataConstPtr &track_data, TrackedObjectPtr new_object)
Boost up state considering track history
void OnlineCovarianceEstimation(const MlfTrackDataConstPtr &track_data, TrackedObjectPtr object)
Estimate covariance considering history measurment
#define ACHECK(cond)
Definition log.h:80
#define PERCEPTION_REGISTER_MLFFILTER(name)
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::shared_ptr< const MlfTrackData > MlfTrackDataConstPtr
std::shared_ptr< const TrackedObject > TrackedObjectConstPtr
std::shared_ptr< MlfTrackData > MlfTrackDataPtr
std::shared_ptr< TrackedObject > TrackedObjectPtr
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