28 const std::vector<float> &k_mat,
29 const std::vector<float> &ground3,
30 std::vector<float> *ground4) {
31 CHECK_GT(baseline, 0.0f);
32 CHECK_EQ(k_mat.size(), 9U);
33 CHECK_EQ(ground3.size(), 3U);
34 CHECK_NOTNULL(ground4);
35 CHECK_EQ(ground4->size(), 4U);
36 const float &b = baseline;
37 const float &fx = k_mat[0];
38 const float &fy = k_mat[4];
39 const float &cy = k_mat[5];
40 ground4->data()[0] = 0.0f;
41 ground4->data()[1] = ground3[0] * fy;
42 ground4->data()[2] = ground3[0] * cy + ground3[2];
43 ground4->data()[3] = ground3[1] * b * fx;
49 const std::vector<float> &k_mat,
50 const std::vector<float> &ground4,
51 std::vector<float> *ground3) {
52 CHECK_GT(baseline, 0.0f);
53 CHECK_EQ(k_mat.size(), 9U);
54 CHECK_EQ(ground4.size(), 4U);
55 CHECK_NOTNULL(ground3);
56 CHECK_EQ(ground3->size(), 3U);
58 float p[4] = {ground4[0], ground4[1], ground4[2], ground4[3]};
62 AERROR <<
"Have roll in the ground plane: " << p[0];
63 ground3->assign(3, 0.f);
67 const float &b = baseline;
68 const float &fx = k_mat[0];
69 const float &fy = k_mat[4];
70 const float &cy = k_mat[5];
73 ground3->data()[2] = p[2] - ground3->data()[0] * cy;
78 const std::vector<float> &k_mat,
79 const std::vector<float> &ground3,
float *pitch,
81 CHECK_GT(baseline, 0.0f);
82 CHECK_EQ(k_mat.size(), 9U);
83 CHECK_EQ(ground3.size(), 3U);
85 CHECK_NOTNULL(cam_height);
86 std::vector<float> ground4(4, 0.0f);
88 if (ground4[3] > 0.0f) {
91 *cam_height = -ground4[3];
92 double cos_pitch = ground4[1];
93 double sin_pitch = -ground4[2];
94 *pitch =
static_cast<float>(atan2(sin_pitch, cos_pitch));
98 const float &baseline,
const float &pitch,
99 const float &cam_height,
100 std::vector<float> *ground3) {
101 CHECK_EQ(k_mat.size(), 9U);
102 CHECK_GT(baseline, 0.0f);
103 CHECK_GT(cam_height, 0.0f);
104 CHECK_NOTNULL(ground3);
105 CHECK_EQ(ground3->size(), 3U);
106 float sin_pitch =
static_cast<float>(sin(pitch));
107 float cos_pitch =
static_cast<float>(cos(pitch));
108 std::vector<float> ground4 = {0, cos_pitch, -sin_pitch, -cam_height};
113 if (track_length <= 0) {
114 AERROR <<
"track_length, " << track_length <<
", should be positive";
116 pitch_height_inlier_tracks_.resize(track_length * 3);
117 const_weight_temporal_.resize(track_length, 0.0f);
119 weight_.resize(track_length, 0.0f);
120 for (
int i = track_length - 1; i >= 0; --i) {
121 const_weight_temporal_.at(i) =
126 float accm_sum =
algorithm::ISum(const_weight_temporal_.data(), track_length);
130 head_ = track_length;
134 const float &inlier_ratio) {
135 CHECK_EQ(ph.size(), 2U);
137 int length =
static_cast<int>(pitch_height_inlier_tracks_.size());
140 for (i = length - 1; i >= 3; i--) {
141 pitch_height_inlier_tracks_[i] = pitch_height_inlier_tracks_[i - 3];
149 int head3 = head_ * 3;
150 pitch_height_inlier_tracks_[head3] = ph[0];
151 pitch_height_inlier_tracks_[head3 + 1] = ph[1];
152 pitch_height_inlier_tracks_[head3 + 2] = inlier_ratio;
156 CHECK_NOTNULL(pitch);
157 CHECK_NOTNULL(cam_height);
159 int length =
static_cast<int>(pitch_height_inlier_tracks_.size() / 3);
161 *pitch = *cam_height = 0.0f;
163 }
else if (length == 1) {
164 *pitch = pitch_height_inlier_tracks_[0];
165 *cam_height = pitch_height_inlier_tracks_[1];
171 for (i = head_; i < length; i++) {
172 w = pitch_height_inlier_tracks_.at(i * 3 + 2);
173 weight_.at(i) = const_weight_temporal_.at(i) * w;
177 float accm_wei =
algorithm::ISum(weight_.data() + head_, (length - head_));
179 ph[0] = ph[1] = 0.0f;
180 for (i = head_; i < length; i++) {
183 ph[0] += pitch_height_inlier_tracks_.at(i3) * w;
184 ph[1] += pitch_height_inlier_tracks_.at(i3 + 1) * w;
193 unsigned int track_length =
194 static_cast<unsigned int>(pitch_height_inlier_tracks_.size() / 3);
195 auto &data = pitch_height_inlier_tracks_;
197 for (; i < track_length; ++i) {
199 data.at(i3) = data.at(i3 + 1) = data.at(i3 + 2) = 0.0f;
200 weight_.at(i) = 0.0f;
202 head_ = track_length;
218 float *vd,
int count_vd,
219 const std::vector<float> &plane) {
220 ground_is_valid_ =
false;
222 std::vector<float> ground3(l_, l_ + 3);
223 std::vector<float> k_mat(k_mat_, k_mat_ + 9);
225 if (!plane.empty()) {
229 FillGroundModel(ground3);
230 AINFO <<
"set ground plane from outside: " << plane[0] <<
", " << plane[1]
231 <<
", " << plane[2] <<
", " << plane[3];
232 ground_is_valid_ =
true;
235 bool success =
false;
236 float inlier_ratio = 0.0f;
237 std::vector<float> ph(2, 0);
238 if (CameraGroundPlaneDetector::DetectGroundFromSamples(vd, count_vd,
240 ADEBUG <<
"l: " << l_[0] <<
", " << l_[1] <<
", " << l_[2];
241 ground3.assign(l_, l_ + 3);
243 ADEBUG <<
"ph: " << ph[0] <<
", " << ph[1];
247 ground_plane_tracker_->
Push(ph, inlier_ratio);
248 ground_plane_tracker_->
GetGround(&ph[0], &ph[1]);
250 FillGroundModel(ground3);
251 ADEBUG <<
"l tracked: " << l_[0] <<
", " << l_[1] <<
", " << l_[2];
252 ADEBUG <<
"ph tracked: " << ph[0] <<
", " << ph[1];
257 ADEBUG <<
"succeed with inlier ratio: " << inlier_ratio;
258 ground_is_valid_ =
true;
264 ground_plane_tracker_->
GetGround(&ph[0], &ph[1]);
266 FillGroundModel(ground3);
270 CHECK_GT(camera_height, 0.f);
273 FillGroundModel(ground3);
275 ground_plane_tracker_->
Restart();
280bool CameraGroundPlaneDetector::DetectGroundFromSamples(
float *vd,
int count_vd,
281 float *inlier_ratio) {
283 AERROR <<
"vd is nullptr";
286 if (inlier_ratio ==
nullptr) {
287 AERROR <<
"inlier_ratio is nullptr";
290 *inlier_ratio = 0.0f;
292 l_[0] = l_[1] = l_[2] = 0.0f;
299 float *vs = ss_flt_.data();
300 float *ds = vs + count_vd;
301 for (
int i = 0; i < count_vd; ++i) {
307 int *inliers = ss_int_.data();
308 memset(inliers, 0,
sizeof(
int) * count_vd * 2);
312 GroundHypoGenFunc<float>,
313 GroundFittingCostFunc<float>,
nullptr>(
314 vs, ds, count_vd, p, &nr_inliers, inliers, kThresInlier,
false,
true,
315 0.99f, kMinInlierRatio)) {
316 memset(l_, 0,
sizeof(
float) * 3);
319 *inlier_ratio =
static_cast<float>(nr_inliers) *
323 if (*inlier_ratio < kMinInlierRatio) {
324 *inlier_ratio = 0.0f;
325 memset(l_, 0,
sizeof(
float) * 3);
331 for (
int i = 0; i < nr_inliers; ++i) {
332 int i2 = inliers[i] << 1;
333 int count2 = count << 1;
334 std::swap(vd[i2], vd[count2]);
335 std::swap(vd[i2 + 1], vd[count2 + 1]);
338 float l_best[3] = {0};
340 memcpy(l_, l_best,
sizeof(
float) * 3);
bool DetetGround(float pitch, float camera_height, float *vd, int count_vd, const std::vector< float > &plane={})
GroundPlaneTracker(int track_length)
void GetGround(float *pitch, float *cam_height)
void Push(const std::vector< float > &ph, const float &inlier_ratio)
float IDegreeToRadians(float d)
void ILineFit2dTotalLeastSquare(T *x, T *l, int n)
float IDiv(float a, float b)
T ISquaresum3(const T x[3])
void IScale(T *x, int n, T sf)
T ISum(const T *x, int n)
float IPow(float a, float b)
bool RobustBinaryFitRansac(T *x, T *xp, int n, T *model, int *consensus_size, int *inliers, T error_tol, bool re_est_model_w_inliers=false, bool adaptive_trial_count=false, double confidence=0.99, double inlierprob=0.5, int min_nr_inliers=s, bool random_shuffle_inputs=false)
void IScale4(T x[4], T sf)
bool ConvertGround4ToGround3(const float &baseline, const std::vector< float > &k_mat, const std::vector< float > &ground4, std::vector< float > *ground3)
void GetGroundPlanePitchHeight(const float &baseline, const std::vector< float > &k_mat, const std::vector< float > &ground3, float *pitch, float *cam_height)
void ConvertGround3ToGround4(const float &baseline, const std::vector< float > &k_mat, const std::vector< float > &ground3, std::vector< float > *ground4)
void GetGround3FromPitchHeight(const std::vector< float > &k_mat, const float &baseline, const float &pitch, const float &cam_height, std::vector< float > *ground3)
float max_camera_ground_height
float thres_inlier_plane_fitting