Apollo 10.0
自动驾驶开放平台
target.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 <algorithm>
19#include <map>
20
21#include "cyber/common/log.h"
25
26namespace apollo {
27namespace perception {
28namespace camera {
29
30int Target::global_track_id = 0;
31int Target::Size() const { return static_cast<int>(tracked_objects.size()); }
32
33void Target::Clear() { tracked_objects.clear(); }
34
35TrackObjectPtr Target::operator[](int index) const { return get_object(index); }
37 CHECK_GT(static_cast<int>(tracked_objects.size()), 0);
38 CHECK_LT(index, static_cast<int>(tracked_objects.size()));
39 CHECK_GE(index, -static_cast<int>(tracked_objects.size()));
40 return tracked_objects[(index + tracked_objects.size()) %
41 tracked_objects.size()];
42}
44 if (tracked_objects.empty()) {
45 start_ts = object->timestamp;
46 id = Target::global_track_id++;
47 type = object->object->sub_type;
48 }
49 object->object->track_id = id;
50 object->object->tracking_time = object->timestamp - start_ts;
51 object->object->latest_tracked_time = object->timestamp;
52 latest_object = object;
53 lost_age = 0;
54 tracked_objects.push_back(object);
55}
56void Target::RemoveOld(int frame_id) {
57 size_t index = 0;
58 while (index < tracked_objects.size() &&
59 tracked_objects[index]->indicator.frame_id < frame_id) {
60 ++index;
61 }
62 tracked_objects.erase(tracked_objects.begin(),
63 tracked_objects.begin() + index);
64}
65void Target::Init(const TargetParam &param) {
66 target_param_ = param;
67 id = -1;
68 lost_age = 0;
69
73 // TODO(gaohan) should update variance when predict and update
82
83 type_probs.assign(static_cast<int>(base::ObjectSubType::MAX_OBJECT_TYPE),
84 0.0f);
87
88 // record history state after kalman filter
89 history_world_states_.set_capacity(param.world_state_history());
90
91 // record orientation of displacement
94 // Init constant position Kalman Filter
95 world_center_const.covariance_.setIdentity();
100 // Init object template
101 object_template_manager_ = ObjectTemplateManager::Instance();
102}
103Target::Target(const TargetParam &param) { Init(param); }
104
106 auto delta_t =
107 static_cast<float>(frame->timestamp - latest_object->timestamp);
108 if (delta_t < 0) {
109 return;
110 }
111 image_center.Predict(delta_t);
112 float acc_variance = target_param_.world_center().process_variance();
113 float delta_t_2 = delta_t * delta_t;
114 float pos_variance = 0.25f * acc_variance * delta_t_2 * delta_t_2;
115 float vel_variance = acc_variance * delta_t_2;
116 world_center.process_noise_(0, 0) = pos_variance;
117 world_center.process_noise_(1, 1) = pos_variance;
118 world_center.process_noise_(2, 2) = vel_variance;
119 world_center.process_noise_(3, 3) = vel_variance;
120 world_center.Predict(delta_t);
121
122 // const position kalman predict
124 world_center_const.process_noise_(0, 0) = vel_variance * delta_t_2;
128}
129
131 // measurements
132 auto obj = latest_object->object;
133 float width = static_cast<float>(frame->data_provider->src_width());
134 float height = static_cast<float>(frame->data_provider->src_height());
135 base::RectF rect(latest_object->projected_box);
136 base::Point2DF center = rect.Center();
137
138 if (!isLost()) {
139 Eigen::Vector2d measurement;
140 measurement << rect.width, rect.height;
141 image_wh.AddMeasure(measurement);
142 measurement << center.x, center.y;
143 image_center.Correct(measurement);
144
145 // update 2d bbox size
146 Eigen::Vector4d state;
147 state = image_center.get_state();
148 center.x = static_cast<float>(state(0));
149 center.y = static_cast<float>(state(1));
150 ADEBUG << "2d move:" << id << " " << state(2) << " " << state(3);
151
152 auto shape = image_wh.get_state();
153 rect.width = static_cast<float>(shape(0));
154 rect.height = static_cast<float>(shape(1));
155 rect.SetCenter(center);
156 RefineBox(rect, width, height, &rect);
157 latest_object->projected_box = rect;
158 }
159}
160
162 auto object = latest_object->object;
163 if (!isLost()) {
164 // camera coordinate
165 Eigen::Vector2d z;
166 z << std::sin(object->theta), std::cos(object->theta);
168 z = direction.get_state();
169 float theta = static_cast<float>(std::atan2(z[0], z[1]));
170 AINFO << "dir " << id << " " << object->theta << " " << theta;
171 object->theta = theta;
172 object->direction[0] = static_cast<float>(cos(object->theta));
173 object->direction[1] = static_cast<float>(sin(object->theta));
174 object->direction[2] = 0;
175
176 z << object->center(0), object->center(1);
177 if (object->type == base::ObjectType::UNKNOWN_UNMOVABLE) {
179 } else {
180 // Eigen::Vector4d x = world_center.get_state();
181 float obj_2_car_x = object->camera_supplement.local_center[0];
182 float obj_2_car_z = object->camera_supplement.local_center[2];
183 float obj_distance_to_main_car =
184 obj_2_car_x * obj_2_car_x + obj_2_car_z * obj_2_car_z;
185 float dis_err = target_param_.world_center().measure_variance() *
186 obj_distance_to_main_car;
187 world_center.measure_noise_.setIdentity();
188 world_center.measure_noise_ *= dis_err;
190 ADEBUG << "Velocity: " << id << " " << z.transpose() << " "
191 << world_center.get_state().transpose();
192
193 // const position kalman correct
197 pos_measure << object->center(0), object->center(1);
199 }
200 }
201
202 if (object->type == base::ObjectType::UNKNOWN_UNMOVABLE) {
203 const Eigen::VectorXd &x = world_center_for_unmovable.get_state();
204 const Eigen::MatrixXd &var = world_center_for_unmovable.get_variance();
205 object->center(0) = x(0);
206 object->center(1) = x(1);
207 object->center_uncertainty(0) = static_cast<float>(var(0));
208 object->center_uncertainty(1) = static_cast<float>(var(1));
209 object->velocity(0) = 0;
210 object->velocity(1) = 0;
211 object->velocity(2) = 0;
212 } else {
213 Eigen::Vector4d x = world_center.get_state();
214 // TODO(gaohan02): refactor
215 if (tracked_objects.size() > 10) {
216 auto pose1 = get_object(-2)->object->center;
217 auto pose2 = get_object(-10)->object->center;
218 double ts1 = get_object(-2)->timestamp;
219 double ts2 = get_object(-10)->timestamp;
220 Eigen::Vector3d vel = (pose1 - pose2) / (ts1 - ts2);
221 double speed1 = std::sqrt(vel(0) * vel(0) + vel(1) * vel(1));
222 double speed2 = std::sqrt(x(2) * x(2) + x(3) * x(3));
223 double ratio = (Equal(speed1, 0)) ? 0 : speed2 / speed1;
224 ADEBUG << "Target: " << id << " " << vel.transpose() << " , "
225 << x.block<2, 1>(2, 0).transpose();
228 ADEBUG << "Velocity too large";
229 } else if (ratio > target_param_.large_velocity_ratio()) {
230 vel(0) = (x(2) + vel(0)) / 2;
231 vel(1) = (x(3) + vel(1)) / 2;
233 ADEBUG << "Velocity large";
234 } else {
235 ADEBUG << "Velocity normal";
236 }
237 }
238
240 double speed = std::sqrt(x(2) * x(2) + x(3) * x(3));
241 const std::map<base::ObjectSubType, float> &kTypeSpeedLimit =
243 if (speed > kTypeSpeedLimit.at(object->sub_type)) {
244 double ratio = kTypeSpeedLimit.at(object->sub_type) / speed;
245 Eigen::Vector2d vel;
246 vel << x(2) * ratio, x(3) * ratio;
249 }
250 object->center(0) = x(0);
251 object->center(1) = x(1);
252 object->center_uncertainty.setConstant(0);
253 object->center_uncertainty(0, 0) =
254 static_cast<float>(world_center.variance_(0, 0));
255 object->center_uncertainty(1, 1) =
256 static_cast<float>(world_center.variance_(1, 1));
257 object->velocity(0) = static_cast<float>(x(2));
258 object->velocity(1) = static_cast<float>(x(3));
259 object->velocity(2) = 0;
260 world_velocity.AddMeasure(object->velocity.cast<double>());
261 object->velocity_uncertainty = world_velocity.get_variance().cast<float>();
262 if (speed > target_param_.velocity_threshold()) {
263 object->direction(0) = static_cast<float>(x(2) / speed);
264 object->direction(1) = static_cast<float>(x(3) / speed);
265 object->direction(2) = 0;
266 object->theta = static_cast<float>(std::atan2(x(3), x(2)));
267 }
268 }
269
270 if (object->type != base::ObjectType::UNKNOWN_UNMOVABLE &&
272 // check displacement orientation
273 bool stable_moving = false;
274 double avg_vel_norm = world_velocity.get_state().norm();
275 if (avg_vel_norm > target_param_.stable_moving_speed()) {
276 stable_moving = true;
277 } else if (tracked_objects.size() > 1) {
278 auto prev_pos = get_object(-2)->object->center;
279 auto displacement = object->center - prev_pos;
280 Eigen::VectorXd measured_theta(1);
281 measured_theta << std::atan2(displacement[1], displacement[0]);
282 displacement_theta.AddMeasure(measured_theta);
283 // if an object is moving, its displacement orientation should be
284 // consistent
285 stable_moving = displacement_theta.get_variance()(0, 0) <
287 }
288
289 // check const position kalman residuals
290 const auto &residual = world_center_const.residual_;
291 if (!stable_moving &&
292 residual(0) * residual(0) <
294 residual(1) * residual(1) <
296 object->velocity(0) = 0;
297 object->velocity(1) = 0;
298 }
299
300 // check history states
301 history_world_states_.push_back(object);
302 ClappingTrackVelocity(object);
303 }
304
305 // debug velocity
306 ADEBUG << "obj_speed--id: " << id << " " << object->velocity.head(2).norm();
307}
308
310 auto object = latest_object->object;
311 if (!isLost()) {
312 // todo(zero): need to fix alpha
313 float alpha = 0.01f;
314
315 Eigen::Vector4d size_measurement;
316 size_measurement << alpha, object->size(0), object->size(1),
317 object->size(2);
318 world_lwh.AddMeasure(size_measurement);
319 world_lwh_for_unmovable.AddMeasure(size_measurement);
320 // update 3d object size
321 if (object->type == base::ObjectType::UNKNOWN_UNMOVABLE) {
322 object->size =
323 world_lwh_for_unmovable.get_state().block<3, 1>(1, 0).cast<float>();
324 } else {
325 object->size = world_lwh.get_state().block<3, 1>(1, 0).cast<float>();
326 }
327 ADEBUG << " size is " << world_lwh.get_state().transpose();
328 }
329
330 Update3D(frame);
331}
332
334 auto object = latest_object->object;
335 if (!isLost()) {
336 base::RectF rect(object->camera_supplement.box);
337 // 1. 6mm: reliable z is 40. intrinsic is approximate 2000
338 // 2. 12mm: reliable z is 80. intrinsic is approximate 4000
339 // hf = H * f/z = H * 50
340 const TemplateMap &kMidTemplateHWL =
342 float alpha = gaussian(
343 rect.height /
344 (50 * (kMidTemplateHWL.at(object->sub_type).at(0) + 0.01f)),
346 alpha = std::max(0.01f, alpha);
347
348 type_probs[static_cast<int>(object->sub_type)] += alpha;
349 auto max_prob = std::max_element(type_probs.begin(), type_probs.end());
350 auto index = static_cast<int>(std::distance(type_probs.begin(), max_prob));
351 type = static_cast<base::ObjectSubType>(index);
352 ADEBUG << "Target " << id << " change type from "
353 << static_cast<int>(object->sub_type) << " to "
354 << static_cast<int>(type);
355 object->sub_type = type;
356
357 Eigen::Vector4d size_measurement;
358 size_measurement << alpha, object->size(0), object->size(1),
359 object->size(2);
360 world_lwh.AddMeasure(size_measurement);
361 world_lwh_for_unmovable.AddMeasure(size_measurement);
362 // update 3d object size
363 if (object->type == base::ObjectType::UNKNOWN_UNMOVABLE) {
364 object->size =
365 world_lwh_for_unmovable.get_state().block<3, 1>(1, 0).cast<float>();
366 } else {
367 object->size = world_lwh.get_state().block<3, 1>(1, 0).cast<float>();
368 }
369 ADEBUG << " size is " << world_lwh.get_state().transpose();
370 }
371}
372
373void Target::ClappingTrackVelocity(const base::ObjectPtr &obj) {
374 // check angle between velocity and heading(orientation)
375 if (obj->type == base::ObjectType::VEHICLE) {
376 Eigen::Vector3f obj_dir = obj->direction;
377 Eigen::Vector3f obj_vel = obj->velocity;
378 double vel_heading_angle_change_1 =
379 algorithm::CalculateTheta2DXY(obj_dir, obj_vel);
380 obj_dir *= -1; // obj's heading may flip
381 double vel_heading_angle_change_2 =
382 algorithm::CalculateTheta2DXY(obj_dir, obj_vel);
383 double vel_heading_angle_change =
384 std::min(std::fabs(vel_heading_angle_change_1),
385 std::fabs(vel_heading_angle_change_2));
386 ADEBUG << "obj_id: " << obj->track_id
387 << " vel_heading_angle, 1: " << vel_heading_angle_change_1
388 << " 2: " << vel_heading_angle_change_2
389 << " final: " << vel_heading_angle_change;
390 if (vel_heading_angle_change >
392 ADEBUG << "omt set zero velocity because vel_heading_angle_change >"
393 " abnormal_velocity_heading_angle_threshold : "
395 obj->velocity = Eigen::Vector3f::Zero();
396 return;
397 }
398 }
399
400 // check static
401 if (CheckStatic()) {
402 ADEBUG << "omt set zero velocity because of small speed.";
403 obj->velocity = Eigen::Vector3f::Zero();
404 return;
405 }
406}
407
408/*
409 * 1. check small speed
410 * 2. check moved distance
411 * 3. check velocity theta's variance
412 */
413bool Target::CheckStatic() {
414 if (static_cast<int>(history_world_states_.size()) <
416 return false;
417 }
418
419 // 1. Check small speed
420 bool small_speed = false;
421 const int min_vel_size =
422 std::min(static_cast<int>(history_world_states_.size()),
424 // calculate average velocity
425 std::shared_ptr<base::Object> tmp_obj_vel_avg = nullptr;
426 tmp_obj_vel_avg.reset(new base::Object);
427 tmp_obj_vel_avg->velocity = Eigen::Vector3f(0, 0, 0);
428 tmp_obj_vel_avg =
429 std::accumulate(history_world_states_.begin() +
430 history_world_states_.size() - min_vel_size,
431 history_world_states_.end(), tmp_obj_vel_avg,
432 [](const std::shared_ptr<base::Object> obj1,
433 const std::shared_ptr<base::Object> obj2) {
434 std::shared_ptr<base::Object> ret_obj = nullptr;
435 ret_obj.reset(new base::Object);
436 ret_obj->velocity = obj1->velocity + obj2->velocity;
437 return ret_obj;
438 });
439 tmp_obj_vel_avg->velocity /= static_cast<float>(min_vel_size);
440 double speed_avg = tmp_obj_vel_avg->velocity.head(2).norm();
441 const auto &obj_type = history_world_states_.back()->type;
442 // check speed by type
443 if (obj_type == base::ObjectType::PEDESTRIAN) {
444 small_speed = speed_avg < target_param_.static_speed_threshold_ped();
445 } else {
446 small_speed = speed_avg < target_param_.static_speed_threshold();
447 }
448 if (small_speed) {
449 return true;
450 }
451
452 // 2. Check small moved distance
453 bool not_move = false;
454 if (static_cast<int>(history_world_states_.size()) >=
457 double move_distance = 0.0;
458 Eigen::Vector3d start_position(0.0, 0.0, 0.0);
459 Eigen::Vector3d end_position(0.0, 0.0, 0.0);
460 const int start_idx =
461 static_cast<int>(history_world_states_.size()) -
462 static_cast<int>(target_param_.min_cached_position_size());
463 const int end_idx = static_cast<int>(history_world_states_.size()) - 1;
464 // calculate window-averaged start and end positions
465 // and calculate moved distance
466 if (end_idx - start_idx >= target_param_.calc_avg_position_window_size() &&
468 static_cast<int>(history_world_states_.size()) &&
469 end_idx - target_param_.calc_avg_position_window_size() + 1 >= 0) {
470 for (int i = 0; i < target_param_.calc_avg_position_window_size(); ++i) {
471 start_position += history_world_states_[start_idx + i]->center;
472 end_position += history_world_states_[end_idx - i]->center;
473 }
474 double time_diff = history_world_states_[end_idx]->latest_tracked_time -
475 history_world_states_[start_idx]->latest_tracked_time;
476 // do not consider moved distance when time_diff is small
477 if (std::fabs(time_diff) > 1e-3) {
480 move_distance = (end_position - start_position).head(2).norm();
481 // check moving speed by type
482 double avg_speed = move_distance / time_diff;
483 if (obj_type == base::ObjectType::PEDESTRIAN) {
484 not_move = avg_speed < target_param_.min_moving_avg_speed_ped();
485 } else {
486 not_move = avg_speed < target_param_.min_moving_avg_speed();
487 }
488 }
489 }
490 }
491 if (not_move) {
492 return true;
493 }
494
495 // 3. Check velocity theta's variance
496 std::vector<double> theta_vec(min_vel_size);
497 std::transform(history_world_states_.begin() + history_world_states_.size() -
498 min_vel_size,
499 history_world_states_.end(), theta_vec.begin(),
500 [](const std::shared_ptr<base::Object> obj) -> double {
501 return std::atan2(obj->velocity[1], obj->velocity[0]);
502 });
503 double mean = 0.0;
504 double var = 0.0;
505 CalculateMeanAndVariance(theta_vec, &mean, &var);
506 double stddev = std::sqrt(var);
507 if (stddev > target_param_.velocity_theta_var()) { // 28.64 degree
508 return true;
509 }
510 return false;
511}
512
513bool Target::isTracked() const {
514 return Size() >= target_param_.tracked_life();
515}
516bool Target::isLost() const { return lost_age > 0; }
517
518} // namespace camera
519} // namespace perception
520} // namespace apollo
void Correct(const VectorNd &measurement)
void AddMeasure(const Eigen::VectorXd &z)
void AddMeasure(const Eigen::VectorXd &z)
const Eigen::MatrixXd & get_variance() const
const Eigen::VectorXd & get_state() const
const std::map< base::ObjectSubType, float > & TypeSpeedLimit()
#define ADEBUG
Definition log.h:41
#define AINFO
Definition log.h:42
T CalculateTheta2DXY(const Eigen::Matrix< T, 3, 1 > &v1, const Eigen::Matrix< T, 3, 1 > &v2)
Definition basic.h:92
Rect< float > RectF
Definition box.h:160
std::shared_ptr< Object > ObjectPtr
Definition object.h:127
bool Equal(double x, double target, double eps)
Definition util.cc:24
void CalculateMeanAndVariance(const std::vector< T > &data, T *mean, T *variance)
Definition util.h:150
Dtype gaussian(Dtype x, Dtype mu, Dtype sigma)
std::shared_ptr< TrackObject > TrackObjectPtr
void RefineBox(const base::Rect< T > &box_in, const T width, const T height, base::Rect< T > *box_out)
Definition util.h:92
std::map< base::ObjectSubType, std::vector< float > > TemplateMap
class register implement
Definition arena_queue.h:37
std::shared_ptr< camera::DataProvider > data_provider
optional KalmanParam world_center
Definition omt.proto:28
optional float abnormal_velocity_heading_angle_threshold
Definition omt.proto:49
optional int32 calc_avg_position_window_size
Definition omt.proto:39
optional KalmanParam image_center
Definition omt.proto:29
optional int32 min_cached_world_state_history_size
Definition omt.proto:36
TrackObjectPtr operator[](int index) const
Definition target.cc:35
void Clear()
clear tracked_objects
Definition target.cc:33
int Size() const
return the size of tracked_objects
Definition target.cc:31
void Predict(CameraTrackingFrame *frame)
using kalman filter to predict the tracked_objects
Definition target.cc:105
bool isLost() const
return whether the target is lost
Definition target.cc:516
base::ObjectSubType type
Definition target.h:137
void Add(TrackObjectPtr object)
add object to tracked_objects
Definition target.cc:43
void Update3D(CameraTrackingFrame *frame)
update 3d
Definition target.cc:161
bool isTracked() const
return whether the target is tracked
Definition target.cc:513
void Update2D(CameraTrackingFrame *frame)
update 2d
Definition target.cc:130
void Update(CameraTrackingFrame *frame)
using kalman filter to correct the tracked_objects todo(zero): update world in bev
Definition target.cc:309
KalmanFilterConstVelocity image_center
Definition target.h:154
ObjectTemplateManager * object_template_manager_
Definition target.h:167
KalmanFilterConstVelocity world_center
Definition target.h:138
KalmanFilterConstState< 2 > world_center_const
Definition target.h:142
void RemoveOld(int frame_id)
remove objects older than frame_id
Definition target.cc:56
TrackObjectPtr get_object(int index) const
Get the object accoding to index
Definition target.cc:36
Target(const TargetParam &param)
Definition target.cc:103
std::vector< float > type_probs
Definition target.h:150
FirstOrderRCLowPassFilter image_wh
Definition target.h:153
FirstOrderRCLowPassFilter direction
Definition target.h:135
TrackObjectPtrs tracked_objects
Definition target.h:156
void UpdateType(CameraTrackingFrame *frame)
update type
Definition target.cc:333
void Init(const TargetParam &param)
init Target
Definition target.cc:65