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