Skip to content

Commit 7f4c232

Browse files
committed
plane_determination
1 parent c28c66f commit 7f4c232

File tree

6 files changed

+122
-50
lines changed

6 files changed

+122
-50
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
## Efficient and Consistent Bundle Adjustment on Lidar Point Clouds
44

5+
**Notation**: If your initial pose error is too large in real-world datasets, the plane detection module may not find enough planes (point association) to BA optimization. Our plane determination criteria may be strict for huge initial pose errors. So before optimization, **please to check the planes** (which are displayed in our implementation). If you really cannot provide better initial poses and want to get accurate results, you can try the process of "**coarse-to-fine**", namely from **large voxel size** and **loose plane determination criteria**, to **small voxel size** and **strict plane determination criteria**, using multiple optimization with different point associations.
6+
57
**BALM 2.0** is a basic and simple system to use bundle adjustment (BA) in lidar mapping. It includes three experiments in the paper. We try to keep the code as concise as possible, to avoid confusing the readers. It is notable that this package does not include the application experiments, which will be open-sourced in other projects. The paper is available on Arxiv and more experiments details can be found in the [video](https://youtu.be/MDrIAyhQ-9E).
68

79
<div align="center">

launch/benchmark_realworld.launch

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<launch>
22
<arg name="rviz" default="true" />
33

4-
<param name="voxel_size" type="double" value="1" />
4+
<param name="voxel_size" type="double" value="2" />
55
<param name="file_path" type="string" value="$(find balm2)" />
66
<node pkg="balm2" type="benchmark_realworld" name="benchmark_realworld" output="screen" />
77

rviz_cfg/back.rviz

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ Panels:
88
- /full1/Autocompute Value Bounds1
99
- /full__curr1/Autocompute Value Bounds1
1010
- /Test1/Autocompute Value Bounds1
11-
- /show1
1211
- /show1/Autocompute Value Bounds1
12+
- /cute1
1313
Splitter Ratio: 0.49705880880355835
1414
Tree Height: 865
1515
- Class: rviz/Selection
@@ -225,6 +225,34 @@ Visualization Manager:
225225
Topic: /poseAray
226226
Unreliable: false
227227
Value: true
228+
- Alpha: 1
229+
Autocompute Intensity Bounds: true
230+
Autocompute Value Bounds:
231+
Max Value: 10
232+
Min Value: -10
233+
Value: true
234+
Axis: Z
235+
Channel Name: intensity
236+
Class: rviz/PointCloud2
237+
Color: 255; 255; 255
238+
Color Transformer: Intensity
239+
Decay Time: 0
240+
Enabled: true
241+
Invert Rainbow: false
242+
Max Color: 255; 255; 255
243+
Min Color: 0; 0; 0
244+
Name: cute
245+
Position Transformer: XYZ
246+
Queue Size: 10
247+
Selectable: true
248+
Size (Pixels): 1
249+
Size (m): 0.009999999776482582
250+
Style: Points
251+
Topic: /map_cute
252+
Unreliable: false
253+
Use Fixed Frame: true
254+
Use rainbow: true
255+
Value: true
228256
Enabled: true
229257
Global Options:
230258
Background Color: 0; 0; 0
@@ -253,25 +281,25 @@ Visualization Manager:
253281
Views:
254282
Current:
255283
Class: rviz/Orbit
256-
Distance: 62.94883728027344
284+
Distance: 51.05740737915039
257285
Enable Stereo Rendering:
258286
Stereo Eye Separation: 0.05999999865889549
259287
Stereo Focal Distance: 1
260288
Swap Stereo Eyes: false
261289
Value: false
262290
Field of View: 0.7853981852531433
263291
Focal Point:
264-
X: -11.844158172607422
265-
Y: -2.3019261360168457
266-
Z: -10.72812271118164
292+
X: -3.909618616104126
293+
Y: -3.380894660949707
294+
Z: -1.017249584197998
267295
Focal Shape Fixed Size: false
268296
Focal Shape Size: 0.05000000074505806
269297
Invert Z Axis: false
270298
Name: Current View
271299
Near Clip Distance: 0.009999999776482582
272-
Pitch: 1.3403979539871216
300+
Pitch: 1.285398006439209
273301
Target Frame: <Fixed Frame>
274-
Yaw: 1.5653976202011108
302+
Yaw: 2.7353944778442383
275303
Saved: ~
276304
Window Geometry:
277305
Displays:

src/benchmark/bavoxel.hpp

Lines changed: 54 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
int layer_limit = 2;
99
int layer_size[] = {30, 30, 30, 30};
1010
// float eigen_value_array[] = {1.0/4.0, 1.0/4.0, 1.0/4.0};
11-
float eigen_value_array[4] = {1.0/36, 1.0/25, 1.0/25, 1.0/25};
11+
float eigen_value_array[4] = {1.0/16, 1.0/16, 1.0/16, 1.0/16};
1212
int min_ps = 15;
1313
double one_three = (1.0 / 3.0);
1414

@@ -665,34 +665,34 @@ class OCTO_TREE_NODE
665665
decision = saes.eigenvalues()[0] / saes.eigenvalues()[1];
666666
// decision = saes.eigenvalues()[0];
667667

668-
double eva0 = saes.eigenvalues()[0];
669-
center += 3 * sqrt(eva0) * direct;
670-
vector<PointCluster> covMats(8);
671-
for(int i=0; i<win_count; i++)
672-
{
673-
for(Eigen::Vector3d &pvec: vec_tran[i])
674-
{
675-
int xyz[3] = {0, 0, 0};
676-
for(int k=0; k<3; k++)
677-
if(pvec[k] > center[k])
678-
xyz[k] = 1;
679-
int leafnum = 4*xyz[0] + 2*xyz[1] + xyz[2];
680-
covMats[leafnum].push(pvec);
681-
}
682-
}
668+
// double eva0 = saes.eigenvalues()[0];
669+
// center += 3 * sqrt(eva0) * direct;
670+
// vector<PointCluster> covMats(8);
671+
// for(int i=0; i<win_count; i++)
672+
// {
673+
// for(Eigen::Vector3d &pvec: vec_tran[i])
674+
// {
675+
// int xyz[3] = {0, 0, 0};
676+
// for(int k=0; k<3; k++)
677+
// if(pvec[k] > center[k])
678+
// xyz[k] = 1;
679+
// int leafnum = 4*xyz[0] + 2*xyz[1] + xyz[2];
680+
// covMats[leafnum].push(pvec);
681+
// }
682+
// }
683683

684-
double ratios[2] = {1.0/(3.0*3.0), 2.0*2.0};
685-
int num_all = 0, num_qua = 0;
686-
for(int i=0; i<8; i++)
687-
{
688-
if(covMats[i].N < 10) continue;
689-
Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d> saes(covMats[i].cov());
690-
double child_eva0 = (saes.eigenvalues()[0]);
691-
if(child_eva0 > ratios[0]*eva0 && child_eva0 < ratios[1]*eva0)
692-
num_qua++;
693-
num_all++;
694-
}
695-
double prop = 1.0 * num_qua / num_all;
684+
// double ratios[2] = {1.0/(3.0*3.0), 2.0*2.0};
685+
// int num_all = 0, num_qua = 0;
686+
// for(int i=0; i<8; i++)
687+
// {
688+
// if(covMats[i].N < 10) continue;
689+
// Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d> saes(covMats[i].cov());
690+
// double child_eva0 = (saes.eigenvalues()[0]);
691+
// if(child_eva0 > ratios[0]*eva0 && child_eva0 < ratios[1]*eva0)
692+
// num_qua++;
693+
// num_all++;
694+
// }
695+
// double prop = 1.0 * num_qua / num_all;
696696

697697
return (decision < eigen_value_array[layer]);
698698
// return (decision < eigen_value_array[layer] && prop > 0.5);
@@ -826,8 +826,8 @@ class OCTO_TREE_NODE
826826
{
827827
if(octo_state != 1)
828828
{
829-
// if(push_state != 1)
830-
// return;
829+
if(push_state != 1)
830+
return;
831831

832832
PointType ap;
833833
ap.intensity = ref;
@@ -844,10 +844,10 @@ class OCTO_TREE_NODE
844844
// ap.normal_x = sqrt(value_vector[1] / value_vector[0]);
845845
// ap.normal_y = sqrt(value_vector[2] / value_vector[0]);
846846
// ap.normal_z = sqrt(value_vector[0]);
847-
ap.normal_x = voxel_center[0];
848-
ap.normal_y = voxel_center[1];
849-
ap.normal_z = voxel_center[2];
850-
ap.curvature = quater_length * 4;
847+
// ap.normal_x = voxel_center[0];
848+
// ap.normal_y = voxel_center[1];
849+
// ap.normal_z = voxel_center[2];
850+
// ap.curvature = quater_length * 4;
851851

852852
pl_feat.push_back(ap);
853853
}
@@ -1032,6 +1032,22 @@ class BALM2
10321032

10331033
void damping_iter(vector<IMUST> &x_stats, VOX_HESS &voxhess)
10341034
{
1035+
vector<int> planes(x_stats.size(), 0);
1036+
for(int i=0; i<voxhess.plvec_voxels.size(); i++)
1037+
{
1038+
for(int j=0; j<voxhess.plvec_voxels[i]->size(); j++)
1039+
if(voxhess.plvec_voxels[i]->at(j).N != 0)
1040+
planes[j]++;
1041+
}
1042+
sort(planes.begin(), planes.end());
1043+
if(planes[0] < 20)
1044+
{
1045+
printf("Initial error too large.\n");
1046+
printf("Please loose plane determination criteria for more planes.\n");
1047+
printf("The optimization is terminated.\n");
1048+
exit(0);
1049+
}
1050+
10351051
double u = 0.01, v = 2;
10361052
Eigen::MatrixXd D(6*win_size, 6*win_size), Hess(6*win_size, 6*win_size);
10371053
Eigen::VectorXd JacT(6*win_size), dxi(6*win_size);
@@ -1092,7 +1108,10 @@ class BALM2
10921108
}
10931109

10941110
// if(iter_stop(dxi2, 1e-4))
1095-
if(iter_stop(dxi, 1e-6))
1111+
// if(iter_stop(dxi, 1e-6))
1112+
// break;
1113+
1114+
if(fabs(residual1-residual2)/residual1 < 1e-6)
10961115
break;
10971116
}
10981117

src/benchmark/benchmark_realworld.cpp

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ void pub_pl_func(T &pl, ros::Publisher &pub)
2626
pub.publish(output);
2727
}
2828

29-
ros::Publisher pub_path, pub_test, pub_show;
29+
ros::Publisher pub_path, pub_test, pub_show, pub_cute;
3030

3131
int read_pose(vector<double> &tims, PLM(3) &rots, PLV(3) &poss, string prename)
3232
{
@@ -148,6 +148,7 @@ int main(int argc, char **argv)
148148
pub_test = n.advertise<sensor_msgs::PointCloud2>("/map_test", 100);
149149
pub_path = n.advertise<sensor_msgs::PointCloud2>("/map_path", 100);
150150
pub_show = n.advertise<sensor_msgs::PointCloud2>("/map_show", 100);
151+
pub_cute = n.advertise<sensor_msgs::PointCloud2>("/map_cute", 100);
151152

152153
string prename, ofname;
153154
vector<IMUST> x_buf;
@@ -169,6 +170,11 @@ int main(int argc, char **argv)
169170
win_size = x_buf.size();
170171
printf("The size of poses: %d\n", win_size);
171172

173+
data_show(x_buf, pl_fulls);
174+
printf("Check the point cloud with the initial poses.\n");
175+
printf("If no problem, input '1' to continue or '0' to exit...\n");
176+
int a; cin >> a; if(a==0) exit(0);
177+
172178
pcl::PointCloud<PointType> pl_full, pl_surf, pl_path, pl_send;
173179
for(int iterCount=0; iterCount<1; iterCount++)
174180
{
@@ -177,19 +183,33 @@ int main(int argc, char **argv)
177183
for(int i=0; i<win_size; i++)
178184
cut_voxel(surf_map, *pl_fulls[i], x_buf[i], i);
179185

186+
pcl::PointCloud<PointType> pl_send;
187+
pub_pl_func(pl_send, pub_show);
188+
180189
pcl::PointCloud<PointType> pl_cent; pl_send.clear();
181190
VOX_HESS voxhess;
182191
for(auto iter=surf_map.begin(); iter!=surf_map.end() && n.ok(); iter++)
183192
{
184193
iter->second->recut(win_size);
185194
iter->second->tras_opt(voxhess, win_size);
195+
iter->second->tras_display(pl_send, win_size);
186196
}
187197

188-
data_show(x_buf, pl_fulls);
189-
printf("Initial point cloud is published.\n");
190-
printf("Input '1' to start optimization...\n");
198+
pub_pl_func(pl_send, pub_cute);
199+
printf("\nThe planes (point association) cut by adaptive voxelization.\n");
200+
printf("If the planes are too few, the optimization will be degenerated and fail.\n");
201+
printf("If no problem, input '1' to continue or '0' to exit...\n");
191202
int a; cin >> a; if(a==0) exit(0);
192-
203+
pl_send.clear(); pub_pl_func(pl_send, pub_cute);
204+
205+
if(voxhess.plvec_voxels.size() < 3 * x_buf.size())
206+
{
207+
printf("Initial error too large.\n");
208+
printf("Please loose plane determination criteria for more planes.\n");
209+
printf("The optimization is terminated.\n");
210+
exit(0);
211+
}
212+
193213
BALM2 opt_lsv;
194214
opt_lsv.damping_iter(x_buf, voxhess);
195215

@@ -203,9 +223,10 @@ int main(int argc, char **argv)
203223
malloc_trim(0);
204224
}
205225

226+
printf("\nRefined point cloud is publishing...\n");
206227
malloc_trim(0);
207228
data_show(x_buf, pl_fulls);
208-
printf("Refined point cloud is published.\n");
229+
printf("\nRefined point cloud is published.\n");
209230

210231
ros::spin();
211232
return 0;

src/benchmark/benchmark_virtual.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -449,7 +449,9 @@ class BALM2
449449
is_calc_hess = false;
450450
}
451451

452-
if(iter_stop(dxi, 1e-6))
452+
// if(iter_stop(dxi, 1e-6))
453+
// break;
454+
if(fabs((residual1-residual2))/ residual1 < 1e-6)
453455
break;
454456
}
455457
double tt2 = ros::Time::now().toSec();

0 commit comments

Comments
 (0)