Apollo 11.0
自动驾驶开放平台
mlf_motion_refiner.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
22#include "cyber/common/file.h"
25
26namespace apollo {
27namespace perception {
28namespace lidar {
29
31 std::string config_file = "mlf_motion_refiner.conf";
32 if (!options.config_file.empty()) {
33 config_file = options.config_file;
34 }
35 config_file = GetConfigFile(options.config_path, config_file);
38 // read from proto config
44 return true;
45}
46
48 TrackedObjectPtr new_object) {
49 auto latest_object_pair = track_data->GetLatestObject();
50 const TrackedObjectConstPtr& latest_object = latest_object_pair.second;
51
52 // 1. keep motion if acceleration of filter is greater than a threshold
53 double time_diff = new_object->object_ptr->latest_tracked_time -
54 latest_object->object_ptr->latest_tracked_time;
55 Eigen::Vector3d filter_velocity_gain = new_object->belief_velocity_gain;
56 double filter_acceleration_gain = 0.0;
57 if (fabs(time_diff) < EPSION_TIME) {
58 filter_acceleration_gain = 0.0;
59 } else {
60 filter_acceleration_gain = filter_velocity_gain.norm() / time_diff;
61 }
62 bool need_keep_motion =
63 filter_acceleration_gain > claping_acceleration_threshold_;
64 // use tighter threshold for pedestrian
65 if (filter_acceleration_gain > claping_acceleration_threshold_ / 2 &&
66 new_object->type == base::ObjectType::PEDESTRIAN) {
67 need_keep_motion = true;
68 }
69
70 if (need_keep_motion && (!new_object->converged)) {
71 Eigen::Vector3d current_velocity = Eigen::Vector3d::Zero();
72 current_velocity = latest_object->output_velocity;
73 new_object->output_velocity = current_velocity;
74 // new_object->output_velocity = Eigen::Vector3d::Zero();
75 // new_object->state.tail<2>().setZero();
76 // new_object->belief_velocity = Eigen::Vector3d::Zero();
77 // new_object->state.head<2>().setZero();
78 AINFO << "[Velocity-Refine] track_id: " << track_data->track_id_
79 << " KEEP MOTION because of extraodinary acceleration.";
80 return true;
81 }
82
83 // 2. motion state check
84 bool need_assign_movable_obj_speed =
85 NeedAssignMovableObjectSpeed(latest_object, new_object);
86 if (use_movable_state_check_ && need_assign_movable_obj_speed) {
87 if (new_object->belief_velocity.head(2).norm() > 0) {
88 new_object->output_velocity = new_object->belief_velocity;
89 } else if (new_object->measured_barycenter_velocity.head(2).norm() > 0) {
90 new_object->output_velocity = new_object->measured_barycenter_velocity;
91 } else {
92 new_object->output_velocity = new_object->measured_center_velocity;
93 }
94 return true;
95 }
96
97 // 3. static hypothesis check
98 bool is_static_hypothesis =
99 CheckStaticHypothesisByState(latest_object, new_object);
100
101 if (is_static_hypothesis) {
102 new_object->output_velocity = Eigen::Vector3d::Zero();
103 new_object->state.tail<2>().setZero();
104 AINFO << "[Velocity-Refine] track_id: " << track_data->track_id_
105 << " set velocity to zero because of static_hypothesis.";
106 return true;
107 }
108 return false;
109}
110
112 const TrackedObjectConstPtr& latest_object,
113 const TrackedObjectConstPtr& new_object) const {
114 // Check whether track is static or not
115 // evaluate speed noise level, the less the level is the
116 // greater the probability of noise is
117 double speed = new_object->output_velocity.head(2).norm();
118
119 // TypeBasedThreshold
120 bool velocity_noise_level_0 = false;
121 bool velocity_noise_level_1 = false;
122 bool velocity_noise_level_2 = false;
123 auto type_select = new_object->type;
124 // for pedestrian we give loose threshold
125 if (type_select == base::ObjectType::PEDESTRIAN ||
126 type_select == base::ObjectType::UNKNOWN) {
127 velocity_noise_level_0 = speed < (claping_speed_threshold_ / 4.0);
128 velocity_noise_level_1 = speed < (claping_speed_threshold_ / 2.0);
129 velocity_noise_level_2 = speed < (claping_speed_threshold_ / 1.0);
130 } else if (type_select == base::ObjectType::BICYCLE) {
131 velocity_noise_level_0 = speed < (cyc_refine_speed_ / 6.0);
132 velocity_noise_level_1 = speed < (cyc_refine_speed_ / 4.0);
133 velocity_noise_level_2 = speed < (cyc_refine_speed_ / 2.0);
134 } else if (type_select == base::ObjectType::VEHICLE) {
135 velocity_noise_level_0 = speed < (car_refine_speed_ / 8.0);
136 velocity_noise_level_1 = speed < (car_refine_speed_ / 4.0);
137 velocity_noise_level_2 = speed < (car_refine_speed_ / 2.0);
138 }
139
140 // believe track is static if speed_level 0 is so small
141 if (velocity_noise_level_0) {
142 ADEBUG << "type: " << static_cast<size_t>(type_select)
143 << " speed is " << speed << " so small";
144 return true;
145 }
146
147 double velocity_change_angle = M_PI, velocity_heading_angle = M_PI;
148 if (CalculateVelocityAngleChange(latest_object, new_object,
149 &velocity_change_angle, &velocity_heading_angle)) {
150 ADEBUG << " velocity_change_angle: " << velocity_change_angle
151 << " velocity_heading_angle: " << velocity_heading_angle;
152 }
153
154 // believe track is static
155 // speed_level 1 and velocity-change or velocity-heading change > PI/6
156 bool dir_change_level_0 = (fabs(velocity_change_angle) > M_PI / 6 ||
157 fabs(velocity_heading_angle) > M_PI / 6);
158 if (velocity_noise_level_1 && dir_change_level_0) {
159 ADEBUG << "type: " << static_cast<size_t>(type_select) << " speed is "
160 << speed << " velocity_change is " << velocity_change_angle
161 << " velocity_heading is " << velocity_heading_angle
162 << " bigger than PI/6";
163 return true;
164 }
165
166 // believe track is static
167 // speed_level 2 and velocity-change or velocity-heading change is > PI/4
168 bool dir_change_level_1 = (fabs(velocity_change_angle) > M_PI / 4 ||
169 fabs(velocity_heading_angle) > M_PI / 4);
170 if (velocity_noise_level_2 && dir_change_level_1) {
171 ADEBUG << "type: " << static_cast<size_t>(type_select) << " speed is "
172 << speed << " velocity_change is " << velocity_change_angle
173 << " velocity_heading is " << velocity_heading_angle
174 << " bigger than PI/4";
175 return true;
176 }
177 return false;
178}
179
181 const TrackedObjectConstPtr& latest_object,
182 const TrackedObjectConstPtr& new_object,
183 double* vel_change_angle,
184 double* velocity_heading_angle) const {
185 Eigen::Vector3d pre_velocity = latest_object->output_velocity;
186 Eigen::Vector3d cur_velocity = new_object->output_velocity;
187 Eigen::Vector3d pre_direction = latest_object->output_direction;
188 constexpr double kEpsilon = std::numeric_limits<double>::epsilon();
189
190 if (pre_velocity.norm() < kEpsilon || cur_velocity.norm() < kEpsilon) {
191 return false;
192 }
193 *vel_change_angle = algorithm::CalculateTheta2DXY<double>(
194 pre_velocity, cur_velocity);
195
196 double velocity_heading_angle_1 = algorithm::CalculateTheta2DXY<double>(
197 pre_direction, cur_velocity);
198 pre_direction *= -1;
199 double velocity_heading_angle_2 = algorithm::CalculateTheta2DXY<double>(
200 pre_direction, cur_velocity);
201 *velocity_heading_angle = std::min(fabs(velocity_heading_angle_1),
202 fabs(velocity_heading_angle_2));
203 return true;
204}
205
207 const TrackedObjectConstPtr& latest_object,
208 const TrackedObjectConstPtr& new_object,
209 double reasonable_angle_change_maximum) const {
210 // note reasonable_angle_change_maximum should be within [0, M_PI]
211 // believe angle change is obvious if one of estimation pair is
212 // extrodinary small
213 Eigen::Vector3d previous_velocity = latest_object->output_velocity;
214 Eigen::Vector3d current_velocity = new_object->output_velocity;
215 constexpr double kEpsilon = std::numeric_limits<double>::epsilon();
216 if (previous_velocity.norm() < kEpsilon) {
217 // return false; // without motion score, this should be true
218 return true;
219 }
220 if (current_velocity.norm() < kEpsilon) {
221 return true;
222 }
223 // believe angle change is obvious if it is greater than threshold
224
225 double velocity_angle_change =
226 algorithm::CalculateTheta2DXY(previous_velocity, current_velocity);
227 if (fabs(velocity_angle_change) > reasonable_angle_change_maximum) {
228 return true;
229 }
230 // Let track be static if angle change of current velocity
231 // & previous heading is larger
232 // than given reasonable maximum.
233 Eigen::Vector3d previous_direction = latest_object->output_direction;
234 double velocity_heading_angle_change_1 =
235 algorithm::CalculateTheta2DXY(previous_direction, current_velocity);
236 previous_direction *= -1;
237 double velocity_heading_angle_change_2 =
238 algorithm::CalculateTheta2DXY<double>(
239 previous_direction, current_velocity);
240 velocity_angle_change = std::min(fabs(velocity_heading_angle_change_1),
241 fabs(velocity_heading_angle_change_2));
242 if (fabs(velocity_angle_change) > reasonable_angle_change_maximum) {
243 return true;
244 }
245 return false;
246}
247
249 const TrackedObjectConstPtr& latest_object,
250 const TrackedObjectConstPtr& new_object) const {
251 base::ObjectPtr obj = new_object->object_ptr;
252 // moving object and have no speed
253 if (obj->motion_state == base::MotionState::MOVING &&
254 new_object->output_velocity.head(2).norm() < 1e-6) {
255 return true;
256 }
257
258 return false;
259}
260
261} // namespace lidar
262} // namespace perception
263} // namespace apollo
bool CheckStaticHypothesisByState(const TrackedObjectConstPtr &latest_object, const TrackedObjectConstPtr &new_object) const
Check whether new observed object is static or not
bool Init(const MlfMotionRefinerInitOptions &options=MlfMotionRefinerInitOptions())
Init motion refiner
bool Refine(const MlfTrackDataConstPtr &track_data, TrackedObjectPtr new_object)
Refine velocity of new object
bool NeedAssignMovableObjectSpeed(const TrackedObjectConstPtr &latest_object, const TrackedObjectConstPtr &new_object) const
bool CheckStaticHypothesisByVelocityAngleChange(const TrackedObjectConstPtr &latest_object, const TrackedObjectConstPtr &new_object, double reasonable_angle_change_maximum) const
Check whether new observed object is static or not via considering the angle velocity change
bool CalculateVelocityAngleChange(const TrackedObjectConstPtr &latest_object, const TrackedObjectConstPtr &new_object, double *vel_change_angle, double *velocity_heading_angle) const
#define ACHECK(cond)
Definition log.h:80
#define ADEBUG
Definition log.h:41
#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
T CalculateTheta2DXY(const Eigen::Matrix< T, 3, 1 > &v1, const Eigen::Matrix< T, 3, 1 > &v2)
Definition basic.h:92
std::shared_ptr< Object > ObjectPtr
Definition object.h:127
std::shared_ptr< const MlfTrackData > MlfTrackDataConstPtr
std::shared_ptr< const TrackedObject > TrackedObjectConstPtr
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