25 const double cam_coord_pre[3],
26 const double cam_coord_pre_pre[3],
float *yaw_rate,
28 assert(yaw_rate !=
nullptr);
29 assert(velocity !=
nullptr);
33 *velocity =
static_cast<float>(dist * time_diff_r);
35 double offset_cur[2] = {
36 cam_coord_cur[0] - cam_coord_pre[0],
37 cam_coord_cur[1] - cam_coord_pre[1],
39 double offset_pre[2] = {
40 cam_coord_pre[0] - cam_coord_pre_pre[0],
41 cam_coord_pre[1] - cam_coord_pre_pre[1],
43 double yaw_cur = atan2(offset_cur[1], offset_cur[0]);
44 double yaw_pre = atan2(offset_pre[1], offset_pre[0]);
45 double yaw_rate_db = (yaw_cur - yaw_pre) * time_diff_r;
46 *yaw_rate =
static_cast<float>(yaw_rate_db);
98 assert(image_width_ > 0);
99 assert(image_height_ > 0);
102 k_mat_[2] = options.
cx;
103 k_mat_[5] = options.
cy;
104 k_mat_[1] = k_mat_[3] = k_mat_[6] = k_mat_[7] = 0.0f;
107 if (params !=
nullptr) {
115 pitch_histogram_.
Clear();
118 memset(k_mat_, 0.0f,
sizeof(
float) * 9);
120 pitch_estimation_ = 0.0f;
121 vanishing_row_ = 0.0f;
122 accumulated_straight_driving_in_meter_ = 0.0f;
126 const float &yaw_rate,
127 const float &time_diff) {
128 float distance_traveled_in_meter = velocity * time_diff;
129 float vehicle_yaw_changed = yaw_rate * time_diff;
136 if (!IsTravelingStraight(vehicle_yaw_changed)) {
137 AINFO <<
"Do not calibate if not moving straight: "
138 <<
"yaw angle changed " << vehicle_yaw_changed;
147 if (!GetVanishingPoint(lane, &vp_cur)) {
148 AINFO <<
"Lane is not valid for calibration.";
155 PushVanishingPoint(vp_cur);
156 if (!PopVanishingPoint(&vp_work)) {
157 AINFO <<
"Driving distance is not long enough";
163 if (!GetPitchFromVanishingPoint(vp_work, &pitch_cur_)) {
164 AINFO <<
"Failed to estimate pitch from vanishing point.";
171 if (!AddPitchToHistogram(pitch_cur_)) {
172 AINFO <<
"Calculated pitch is out-of-range.";
176 accumulated_straight_driving_in_meter_ += distance_traveled_in_meter;
178 if (accumulated_straight_driving_in_meter_ >
182 const float cy = k_mat_[5];
183 const float fy = k_mat_[4];
184 vanishing_row_ = tanf(pitch_estimation_) * fy + cy;
185 accumulated_straight_driving_in_meter_ = 0.0f;
191void LaneBasedCalibrator::PushVanishingPoint(
const VanishingPoint &v_point) {
192 int nr_vps =
static_cast<int>(vp_buffer_.size());
194 vp_buffer_.push_back(v_point);
196 vp_buffer_.pop_front();
197 vp_buffer_.push_back(v_point);
201bool LaneBasedCalibrator::PopVanishingPoint(VanishingPoint *v_point) {
202 float accumulated_distance = 0.0f;
203 for (
const auto &vp : vp_buffer_) {
204 accumulated_distance += vp.distance_traveled;
206 if (accumulated_distance <
210 *v_point = vp_buffer_.back();
211 vp_buffer_.pop_back();
215bool LaneBasedCalibrator::AddPitchToHistogram(
float pitch) {
216 return pitch_histogram_.
Push(pitch);
219bool LaneBasedCalibrator::GetPitchFromVanishingPoint(
const VanishingPoint &vp,
220 float *pitch)
const {
221 assert(pitch !=
nullptr);
222 const float cx = k_mat_[2];
223 const float cy = k_mat_[5];
224 const float fx = k_mat_[0];
225 const float fy = k_mat_[4];
226 float yaw_check =
static_cast<float>(atan2(vp.pixel_pos[0] - cx, fx));
230 *pitch =
static_cast<float>(atan2(vp.pixel_pos[1] - cy, fy));
234bool LaneBasedCalibrator::GetVanishingPoint(
const EgoLane &lane,
235 VanishingPoint *v_point) {
236 assert(v_point !=
nullptr);
237 float line_seg_l[4] = {0};
238 float line_seg_r[4] = {0};
241 bool get_line_seg_left =
242 SelectTwoPointsFromLineForVanishingPoint(lane.left_line, line_seg_l);
243 if (!get_line_seg_left) {
244 AINFO <<
"Left lane is too short.";
248 bool get_line_seg_right =
249 SelectTwoPointsFromLineForVanishingPoint(lane.right_line, line_seg_r);
250 if (!get_line_seg_right) {
251 AINFO <<
"Right lane is too short.";
256 return GetIntersectionFromTwoLineSegments(line_seg_l, line_seg_r, v_point);
259int LaneBasedCalibrator::GetCenterIndex(
const Eigen::Vector2f *points,
261 assert(points !=
nullptr);
265 float center_x = 0.0f;
266 float center_y = 0.0f;
267 for (
int i = 0; i < nr_pts; ++i) {
268 center_x += points[i](0);
269 center_y += points[i](1);
271 center_x /=
static_cast<float>(nr_pts);
272 center_y /=
static_cast<float>(nr_pts);
274 float dist_min =
static_cast<float>(fabs(points[0](0) - center_x) +
275 fabs(points[0](1) - center_y));
276 int center_index = 0;
277 for (
int i = 1; i < nr_pts; ++i) {
278 dist =
static_cast<float>(fabs(points[i](0) - center_x) +
279 fabs(points[i](1) - center_y));
280 if (dist < dist_min) {
285 return is_in_image(points[center_index]) ? center_index : -1;
288bool LaneBasedCalibrator::SelectTwoPointsFromLineForVanishingPoint(
289 const LaneLine &line,
float line_seg[4]) {
290 int nr_pts =
static_cast<int>(line.lane_point.size());
296 int offset_end = nr_pts - nr_samples - 1;
297 int sampled_start = GetCenterIndex(line.lane_point.data(), nr_samples);
300 GetCenterIndex(line.lane_point.data() + offset_end, nr_samples);
302 if (sampled_start >= 0 && sampled_end >= 0) {
303 line_seg[0] = line.lane_point[sampled_start](0);
304 line_seg[1] = line.lane_point[sampled_start](1);
305 line_seg[2] = line.lane_point[sampled_end](0);
306 line_seg[3] = line.lane_point[sampled_end](1);
308 line_seg[0] = line.lane_point.front()(0);
309 line_seg[1] = line.lane_point.front()(1);
310 line_seg[2] = line.lane_point.back()(0);
311 line_seg[3] = line.lane_point.back()(1);
315 if (line_seg[3] > line_seg[1]) {
316 std::swap(line_seg[0], line_seg[2]);
317 std::swap(line_seg[1], line_seg[3]);
322bool LaneBasedCalibrator::GetIntersectionFromTwoLineSegments(
323 const float line_seg_l[4],
const float line_seg_r[4],
324 VanishingPoint *v_point) {
325 assert(v_point !=
nullptr);
346 float left_start_x = line_seg_l[0];
347 float left_start_y = line_seg_l[1];
348 float left_end_x = line_seg_l[2];
349 float left_end_y = line_seg_l[3];
351 float right_start_x = line_seg_r[0];
352 float right_start_y = line_seg_r[1];
353 float right_end_x = line_seg_r[2];
354 float right_end_y = line_seg_r[3];
356 float v10[2] = {left_end_x - left_start_x, left_end_y - left_start_y};
357 float v32[2] = {right_end_x - right_start_x, right_end_y - right_start_y};
358 float dn = v10[0] * v32[1] - v10[1] * v32[0];
361 if (fabs(dn) < 1e-5) {
365 float v13[2] = {left_start_x - right_start_x, left_start_y - right_start_y};
366 float t = v32[0] * v13[1] - v32[1] * v13[0];
369 v_point->pixel_pos[0] = left_start_x + t * v10[0];
370 v_point->pixel_pos[1] = left_start_y + t * v10[1];
void Init(const HistogramEstimatorParams *params=nullptr)
float get_val_estimation() const
bool Process(const EgoLane &lane, const float &velocity, const float &yaw_rate, const float &time_diff)
void Init(const LocalCalibratorInitOptions &options, const CalibratorParams *params=nullptr)
static const int kMaxNrHistoryFrames
float IDegreeToRadians(float d)
T ISquaresumDiffU2(const T x[2], const T y[2])
void GetYawVelocityInfo(const float &time_diff, const double cam_coord_cur[3], const double cam_coord_pre[3], const double cam_coord_pre_pre[3], float *yaw_rate, float *velocity)
float min_required_straight_driving_distance_in_meter
float sampling_lane_point_rate
float max_allowed_yaw_angle_in_radian
HistogramEstimatorParams hist_estimator_params
float min_distance_to_update_calibration_in_meter
std::vector< uint32_t > smooth_kernel
uint32_t histogram_mass_limit