├── media
└── demo_01.gif
├── cfg
└── cvc_ros.cfg
├── launch
└── run_rviz.launch
├── CMakeLists.txt
├── package.xml
├── README.md
├── config
└── semantic-kitti-all.yaml
├── rviz
└── cvc_rviz.rviz
├── src
├── cvc.hpp
└── cvc_ros_node.cpp
└── include
├── tools
└── utils.hpp
└── ground_truth.hpp
/media/demo_01.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/morte2025/CVC-ROS/HEAD/media/demo_01.gif
--------------------------------------------------------------------------------
/cfg/cvc_ros.cfg:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | PACKAGE = "cvc_ros"
4 |
5 | from dynamic_reconfigure.parameter_generator_catkin import *
6 |
7 | gen = ParameterGenerator()
8 |
9 | gen.add("delta_a", double_t, 0, "Default: 0.4", 0.4, 0.1, 3.0)
10 | gen.add("delta_p", double_t, 0, "Default: 1.2", 1.2, 1.0, 12)
11 | gen.add("delta_r", double_t, 0, "Default: 0.2", 0.2, 0.1, 2)
12 |
13 | exit(gen.generate(PACKAGE, "cvc_ros", "cvc_ros_"))
--------------------------------------------------------------------------------
/launch/run_rviz.launch:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.0.2)
2 | project(cvc_ros)
3 |
4 | add_compile_options(-std=c++17)
5 | set(CMAKE_BUILD_TYPE "Release")
6 |
7 | set(CMAKE_CXX_STANDARD 14)
8 | set(CMAKE_CXX_STANDARD_REQUIRED ON)
9 | set(CMAKE_CXX_EXTENSIONS OFF)
10 |
11 | find_package(catkin REQUIRED COMPONENTS
12 | roscpp
13 | rospy
14 | std_msgs
15 | pcl_ros
16 | tf2_ros
17 | tf2_geometry_msgs
18 | dynamic_reconfigure
19 | autoware_msgs
20 | jsk_recognition_msgs
21 | )
22 |
23 | find_package(OpenCV REQUIRED)
24 |
25 | set(CMAKE_CXX_FLAGS "-O2 -Wall ${CMAKE_CXX_FLAGS}")
26 |
27 | generate_dynamic_reconfigure_options(
28 | cfg/cvc_ros.cfg
29 | )
30 |
31 | catkin_package(
32 | INCLUDE_DIRS include
33 | LIBRARIES cvc_ros
34 | CATKIN_DEPENDS roscpp std_msgs
35 | )
36 |
37 | include_directories(
38 | include
39 | ${catkin_INCLUDE_DIRS}
40 | ${dynamic_reconfigure_PACKAGE_PATH}/cmake/cfgbuild.cmake
41 | ${OpenCV_INCLUDE_DIRS}
42 | )
43 |
44 | link_directories(${OpenCV_LIBRARY_DIRS})
45 |
46 | add_executable(cvc_ros_node
47 | src/cvc_ros_node.cpp
48 | )
49 |
50 | add_dependencies(cvc_ros_node
51 | ${${PROJECT_NAME}_EXPORTED_TARGETS}
52 | ${catkin_EXPORTED_TARGETS}
53 | )
54 |
55 | target_link_libraries(cvc_ros_node
56 | ${OpenCV_LIBRARIES}
57 | ${catkin_LIBRARIES}
58 | )
--------------------------------------------------------------------------------
/package.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | cvc_ros
4 | 1.0.0
5 | The cvc_ros package
6 | hmx
7 | TODO
8 |
9 |
10 | catkin
11 | roscpp
12 | rospy
13 | std_msgs
14 | pcl_ros
15 | tf2_ros
16 | tf2_geometry_msgs
17 | dynamic_reconfigure
18 | autoware_msgs
19 | jsk_recognition_msgs
20 |
21 | roscpp
22 | rospy
23 | std_msgs
24 | pcl_ros
25 | tf2_ros
26 | tf2_geometry_msgs
27 | dynamic_reconfigure
28 | autoware_msgs
29 | jsk_recognition_msgs
30 |
31 | roscpp
32 | rospy
33 | std_msgs
34 | pcl_ros
35 | tf2_ros
36 | tf2_geometry_msgs
37 | dynamic_reconfigure
38 | autoware_msgs
39 | jsk_recognition_msgs
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # CVC ROS
2 | An ROS implementation of paper "Curved-Voxel Clustering for Accurate Segmentation of 3D LiDAR Point Clouds with Real-Time Performance"
3 |
4 | 
5 | 
6 | 
7 |
8 | 
9 |
10 | ## Features
11 | * New Spatial Primitive. curved-voxel, a LiDAR-optimized spatial unit reflecting distinct characteristics of 3D LiDAR point clouds.
12 | * Algorithm. an efficient method for segmenting 3D LiDAR point clouds by utilizing LiDAR-optimized curved-voxels and efficient hashbased data structure.
13 | * ROS dynamic reconfigure, you can tune the parameters easily.
14 |
15 | ## Reference
16 | * Curved-Voxel Clustering for Accurate Segmentation of 3D LiDAR Point Clouds with Real-Time Performance. (IROS) 2019
17 | * https://github.com/wangx1996/Lidar-Segementation
18 | * https://github.com/SS47816/lidar_obstacle_detector
19 |
20 | **TODOs**
21 | * imporove the efficiency of algorithm
22 | * imporove the segmentation accuracy
23 |
24 | **Known Issues**
25 | * the segementation result is not very ideal.
26 |
27 | ## Dependencies
28 | * ground cloud filter: https://github.com/HMX2013/patchwork-VLP16
29 | * sudo apt-get install ros-melodic-jsk-rviz-plugins
30 |
31 | ## How to use
32 | # clone the repo
33 | mkdir -p catkin_ws/src
34 | cd catkin_ws/src
35 | git clone https://github.com/HMX2013/SemanticKITTI_loader
36 | git clone https://github.com/HMX2013/CVC-ROS
37 | download obsdet_msgs from
38 | "https://drive.google.com/file/d/1ztLk9Slm656CV-WJieUpBJPlz-Iw14Bk/view?usp=share_link"
39 | cd ../
40 | catkin_make
41 | roslaunch semantic_kitti run_semantic.launch
42 | roslaunch cvc_ros run_rviz.launch
43 |
44 |
45 | ## Contribution
46 | You are welcome contributing to the package by opening a pull-request
47 |
48 | We are following:
49 | [Google C++ Style Guide](https://google.github.io/styleguide/cppguide.html),
50 | [C++ Core Guidelines](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#main),
51 | and [ROS C++ Style Guide](http://wiki.ros.org/CppStyleGuide)
52 |
53 | ## License
54 | MIT License
55 |
--------------------------------------------------------------------------------
/config/semantic-kitti-all.yaml:
--------------------------------------------------------------------------------
1 | # This file is covered by the LICENSE file in the root of this project.
2 | labels:
3 | 0 : "unlabeled"
4 | 1 : "outlier"
5 | 10: "car"
6 | 11: "bicycle"
7 | 13: "bus"
8 | 15: "motorcycle"
9 | 16: "on-rails"
10 | 18: "truck"
11 | 20: "other-vehicle"
12 | 30: "person"
13 | 31: "bicyclist"
14 | 32: "motorcyclist"
15 | 40: "road"
16 | 44: "parking"
17 | 48: "sidewalk"
18 | 49: "other-ground"
19 | 50: "building"
20 | 51: "fence"
21 | 52: "other-structure"
22 | 60: "lane-marking"
23 | 70: "vegetation"
24 | 71: "trunk"
25 | 72: "terrain"
26 | 80: "pole"
27 | 81: "traffic-sign"
28 | 99: "other-object"
29 | 252: "moving-car"
30 | 253: "moving-bicyclist"
31 | 254: "moving-person"
32 | 255: "moving-motorcyclist"
33 | 256: "moving-on-rails"
34 | 257: "moving-bus"
35 | 258: "moving-truck"
36 | 259: "moving-other-vehicle"
37 | color_map: # bgr
38 | 0 : [0, 0, 0]
39 | 1 : [0, 0, 255]
40 | 10: [245, 150, 100]
41 | 11: [245, 230, 100]
42 | 13: [250, 80, 100]
43 | 15: [150, 60, 30]
44 | 16: [255, 0, 0]
45 | 18: [180, 30, 80]
46 | 20: [255, 0, 0]
47 | 30: [30, 30, 255]
48 | 31: [200, 40, 255]
49 | 32: [90, 30, 150]
50 | 40: [255, 0, 255]
51 | 44: [255, 150, 255]
52 | 48: [75, 0, 75]
53 | 49: [75, 0, 175]
54 | 50: [0, 200, 255]
55 | 51: [50, 120, 255]
56 | 52: [0, 150, 255]
57 | 60: [170, 255, 150]
58 | 70: [0, 175, 0]
59 | 71: [0, 60, 135]
60 | 72: [80, 240, 150]
61 | 80: [150, 240, 255]
62 | 81: [0, 0, 255]
63 | 99: [255, 255, 50]
64 | 252: [245, 150, 100]
65 | 256: [255, 0, 0]
66 | 253: [200, 40, 255]
67 | 254: [30, 30, 255]
68 | 255: [90, 30, 150]
69 | 257: [250, 80, 100]
70 | 258: [180, 30, 80]
71 | 259: [255, 0, 0]
72 | content: # as a ratio with the total number of points
73 | 0: 0.018889854628292943
74 | 1: 0.0002937197336781505
75 | 10: 0.040818519255974316
76 | 11: 0.00016609538710764618
77 | 13: 2.7879693665067774e-05
78 | 15: 0.00039838616015114444
79 | 16: 0.0
80 | 18: 0.0020633612104619787
81 | 20: 0.0016218197275284021
82 | 30: 0.00017698551338515307
83 | 31: 1.1065903904919655e-08
84 | 32: 5.532951952459828e-09
85 | 40: 0.1987493871255525
86 | 44: 0.014717169549888214
87 | 48: 0.14392298360372
88 | 49: 0.0039048553037472045
89 | 50: 0.1326861944777486
90 | 51: 0.0723592229456223
91 | 52: 0.002395131480328884
92 | 60: 4.7084144280367186e-05
93 | 70: 0.26681502148037506
94 | 71: 0.006035012012626033
95 | 72: 0.07814222006271769
96 | 80: 0.002855498193863172
97 | 81: 0.0006155958086189918
98 | 99: 0.009923127583046915
99 | 252: 0.001789309418528068
100 | 253: 0.00012709999297008662
101 | 254: 0.00016059776092534436
102 | 255: 3.745553104802113e-05
103 | 256: 0.0
104 | 257: 0.00011351574470342043
105 | 258: 0.00010157861367183268
106 | 259: 4.3840131989471124e-05
107 | # classes that are indistinguishable from single scan or inconsistent in
108 | # ground truth are mapped to their closest equivalent
109 | learning_map:
110 | 0 : 0 # "unlabeled"
111 | 1 : 0 # "outlier" mapped to "unlabeled" --------------------------mapped
112 | 10: 1 # "car"
113 | 11: 2 # "bicycle"
114 | 13: 5 # "bus" mapped to "other-vehicle" --------------------------mapped
115 | 15: 3 # "motorcycle"
116 | 16: 5 # "on-rails" mapped to "other-vehicle" ---------------------mapped
117 | 18: 4 # "truck"
118 | 20: 5 # "other-vehicle"
119 | 30: 6 # "person"
120 | 31: 7 # "bicyclist"
121 | 32: 8 # "motorcyclist"
122 | 40: 9 # "road"
123 | 44: 10 # "parking"
124 | 48: 11 # "sidewalk"
125 | 49: 12 # "other-ground"
126 | 50: 13 # "building"
127 | 51: 14 # "fence"
128 | 52: 0 # "other-structure" mapped to "unlabeled" ------------------mapped
129 | 60: 9 # "lane-marking" to "road" ---------------------------------mapped
130 | 70: 15 # "vegetation"
131 | 71: 16 # "trunk"
132 | 72: 17 # "terrain"
133 | 80: 18 # "pole"
134 | 81: 19 # "traffic-sign"
135 | 99: 0 # "other-object" to "unlabeled" ----------------------------mapped
136 | 252: 20 # "moving-car"
137 | 253: 21 # "moving-bicyclist"
138 | 254: 22 # "moving-person"
139 | 255: 23 # "moving-motorcyclist"
140 | 256: 24 # "moving-on-rails" mapped to "moving-other-vehicle" ------mapped
141 | 257: 24 # "moving-bus" mapped to "moving-other-vehicle" -----------mapped
142 | 258: 25 # "moving-truck"
143 | 259: 24 # "moving-other-vehicle"
144 | learning_map_inv: # inverse of previous map
145 | 0: 0 # "unlabeled", and others ignored
146 | 1: 10 # "car"
147 | 2: 11 # "bicycle"
148 | 3: 15 # "motorcycle"
149 | 4: 18 # "truck"
150 | 5: 20 # "other-vehicle"
151 | 6: 30 # "person"
152 | 7: 31 # "bicyclist"
153 | 8: 32 # "motorcyclist"
154 | 9: 40 # "road"
155 | 10: 44 # "parking"
156 | 11: 48 # "sidewalk"
157 | 12: 49 # "other-ground"
158 | 13: 50 # "building"
159 | 14: 51 # "fence"
160 | 15: 70 # "vegetation"
161 | 16: 71 # "trunk"
162 | 17: 72 # "terrain"
163 | 18: 80 # "pole"
164 | 19: 81 # "traffic-sign"
165 | 20: 252 # "moving-car"
166 | 21: 253 # "moving-bicyclist"
167 | 22: 254 # "moving-person"
168 | 23: 255 # "moving-motorcyclist"
169 | 24: 259 # "moving-other-vehicle"
170 | 25: 258 # "moving-truck"
171 | learning_ignore: # Ignore classes
172 | 0: True # "unlabeled", and others ignored
173 | 1: False # "car"
174 | 2: False # "bicycle"
175 | 3: False # "motorcycle"
176 | 4: False # "truck"
177 | 5: False # "other-vehicle"
178 | 6: False # "person"
179 | 7: False # "bicyclist"
180 | 8: False # "motorcyclist"
181 | 9: False # "road"
182 | 10: False # "parking"
183 | 11: False # "sidewalk"
184 | 12: False # "other-ground"
185 | 13: False # "building"
186 | 14: False # "fence"
187 | 15: False # "vegetation"
188 | 16: False # "trunk"
189 | 17: False # "terrain"
190 | 18: False # "pole"
191 | 19: False # "traffic-sign"
192 | 20: False # "moving-car"
193 | 21: False # "moving-bicyclist"
194 | 22: False # "moving-person"
195 | 23: False # "moving-motorcyclist"
196 | 24: False # "moving-other-vehicle"
197 | 25: False # "moving-truck"
198 | split: # sequence numbers
199 | train:
200 | - 0
201 | - 1
202 | - 2
203 | - 3
204 | - 4
205 | - 5
206 | - 6
207 | - 7
208 | - 9
209 | - 10
210 | valid:
211 | - 8
212 | test:
213 | - 11
214 | - 12
215 | - 13
216 | - 14
217 | - 15
218 | - 16
219 | - 17
220 | - 18
221 | - 19
222 | - 20
223 | - 21
224 |
--------------------------------------------------------------------------------
/rviz/cvc_rviz.rviz:
--------------------------------------------------------------------------------
1 | Panels:
2 | - Class: rviz/Displays
3 | Help Height: 138
4 | Name: Displays
5 | Property Tree Widget:
6 | Expanded:
7 | - /Global Options1
8 | - /Status1
9 | - /TF1/Frames1
10 | - /TF1/Tree1
11 | - /Ground Cloud1
12 | Splitter Ratio: 0.6185566782951355
13 | Tree Height: 897
14 | - Class: rviz/Selection
15 | Name: Selection
16 | - Class: rviz/Tool Properties
17 | Expanded:
18 | - /2D Pose Estimate1
19 | - /2D Nav Goal1
20 | - /Publish Point1
21 | Name: Tool Properties
22 | Splitter Ratio: 0.5886790156364441
23 | - Class: rviz/Views
24 | Expanded:
25 | - /Current View1
26 | Name: Views
27 | Splitter Ratio: 0.5
28 | - Class: rviz/Time
29 | Name: Time
30 | SyncMode: 0
31 | SyncSource: segamented_color
32 | Preferences:
33 | PromptSaveOnExit: true
34 | Toolbars:
35 | toolButtonStyle: 2
36 | Visualization Manager:
37 | Class: ""
38 | Displays:
39 | - Alpha: 0.5
40 | Cell Size: 1
41 | Class: rviz/Grid
42 | Color: 160; 160; 164
43 | Enabled: false
44 | Line Style:
45 | Line Width: 0.029999999329447746
46 | Value: Lines
47 | Name: Grid
48 | Normal Cell Count: 0
49 | Offset:
50 | X: 0
51 | Y: 0
52 | Z: 0
53 | Plane: XY
54 | Plane Cell Count: 10
55 | Reference Frame:
56 | Value: false
57 | - Class: rviz/TF
58 | Enabled: true
59 | Frame Timeout: 15
60 | Frames:
61 | All Enabled: false
62 | Marker Alpha: 1
63 | Marker Scale: 1
64 | Name: TF
65 | Show Arrows: true
66 | Show Axes: true
67 | Show Names: true
68 | Tree:
69 | {}
70 | Update Interval: 0
71 | Value: true
72 | - Alpha: 1
73 | Autocompute Intensity Bounds: true
74 | Autocompute Value Bounds:
75 | Max Value: 4.370005130767822
76 | Min Value: -1.7799855470657349
77 | Value: true
78 | Axis: Z
79 | Channel Name: intensity
80 | Class: rviz/PointCloud2
81 | Color: 255; 255; 255
82 | Color Transformer: FlatColor
83 | Decay Time: 0
84 | Enabled: true
85 | Invert Rainbow: false
86 | Max Color: 255; 255; 255
87 | Min Color: 0; 0; 0
88 | Name: raw_pc
89 | Position Transformer: XYZ
90 | Queue Size: 10
91 | Selectable: true
92 | Size (Pixels): 3
93 | Size (m): 0.009999999776482582
94 | Style: Flat Squares
95 | Topic: /semi_kitti/cloud
96 | Unreliable: false
97 | Use Fixed Frame: true
98 | Use rainbow: true
99 | Value: true
100 | - Alpha: 1
101 | Autocompute Intensity Bounds: true
102 | Autocompute Value Bounds:
103 | Max Value: 10
104 | Min Value: -10
105 | Value: true
106 | Axis: Z
107 | Channel Name: intensity
108 | Class: rviz/PointCloud2
109 | Color: 125; 125; 125
110 | Color Transformer: FlatColor
111 | Decay Time: 0
112 | Enabled: true
113 | Invert Rainbow: false
114 | Max Color: 255; 255; 255
115 | Min Color: 0; 0; 0
116 | Name: Ground Cloud
117 | Position Transformer: XYZ
118 | Queue Size: 10
119 | Selectable: true
120 | Size (Pixels): 3
121 | Size (m): 0.019999999552965164
122 | Style: Flat Squares
123 | Topic: /semi_kitti/ground_pc
124 | Unreliable: false
125 | Use Fixed Frame: true
126 | Use rainbow: true
127 | Value: true
128 | - Alpha: 1
129 | Autocompute Intensity Bounds: true
130 | Autocompute Value Bounds:
131 | Max Value: 10
132 | Min Value: -10
133 | Value: true
134 | Axis: Z
135 | Channel Name: intensity
136 | Class: rviz/PointCloud2
137 | Color: 255; 255; 255
138 | Color Transformer: Intensity
139 | Decay Time: 0
140 | Enabled: true
141 | Invert Rainbow: false
142 | Max Color: 255; 255; 255
143 | Min Color: 0; 0; 0
144 | Name: segamented_color
145 | Position Transformer: XYZ
146 | Queue Size: 10
147 | Selectable: true
148 | Size (Pixels): 3
149 | Size (m): 0.029999999329447746
150 | Style: Flat Squares
151 | Topic: /segmentation/segmented_cloud_color
152 | Unreliable: false
153 | Use Fixed Frame: true
154 | Use rainbow: true
155 | Value: true
156 | - Buffer length: 100
157 | Class: jsk_rviz_plugin/Plotter2D
158 | Enabled: true
159 | Name: cvc took [ms]
160 | Show Value: true
161 | Topic: /cvc/time_cvc
162 | Value: true
163 | auto color change: false
164 | auto scale: true
165 | background color: 0; 0; 0
166 | backround alpha: 0
167 | border: true
168 | foreground alpha: 0.699999988079071
169 | foreground color: 25; 255; 240
170 | height: 100
171 | left: 60
172 | linewidth: 1
173 | max color: 255; 0; 0
174 | max value: 1
175 | min value: -1
176 | show caption: true
177 | text size: 12
178 | top: 50
179 | update interval: 0.03999999910593033
180 | width: 150
181 | - Class: jsk_rviz_plugin/BoundingBoxArray
182 | Enabled: true
183 | Name: BoundingBoxArray
184 | Queue Size: 10
185 | Topic: /pca_fitting/jsk_bboxs_array
186 | Unreliable: false
187 | Value: true
188 | alpha: 0.800000011920929
189 | color: 25; 255; 0
190 | coloring: Auto
191 | line width: 0.10000000149011612
192 | only edge: true
193 | show coords: false
194 | - Alpha: 1
195 | Autocompute Intensity Bounds: true
196 | Autocompute Value Bounds:
197 | Max Value: 10
198 | Min Value: -10
199 | Value: true
200 | Axis: Z
201 | Channel Name: intensity
202 | Class: rviz/PointCloud2
203 | Color: 255; 255; 255
204 | Color Transformer: Intensity
205 | Decay Time: 0
206 | Enabled: false
207 | Invert Rainbow: false
208 | Max Color: 255; 255; 255
209 | Min Color: 0; 0; 0
210 | Name: PointCloud2
211 | Position Transformer: XYZ
212 | Queue Size: 10
213 | Selectable: true
214 | Size (Pixels): 3
215 | Size (m): 0.029999999329447746
216 | Style: Flat Squares
217 | Topic: /segmentation/gt_pc
218 | Unreliable: false
219 | Use Fixed Frame: true
220 | Use rainbow: true
221 | Value: false
222 | Enabled: true
223 | Global Options:
224 | Background Color: 0; 0; 0
225 | Default Light: true
226 | Fixed Frame: map
227 | Frame Rate: 30
228 | Name: root
229 | Tools:
230 | - Class: rviz/Interact
231 | Hide Inactive Objects: true
232 | - Class: rviz/MoveCamera
233 | - Class: rviz/Select
234 | - Class: rviz/FocusCamera
235 | - Class: rviz/Measure
236 | - Class: rviz/SetInitialPose
237 | Theta std deviation: 0.2617993950843811
238 | Topic: /initialpose
239 | X std deviation: 0.5
240 | Y std deviation: 0.5
241 | - Class: rviz/SetGoal
242 | Topic: /move_base_simple/goal
243 | - Class: rviz/PublishPoint
244 | Single click: true
245 | Topic: /clicked_point
246 | Value: true
247 | Views:
248 | Current:
249 | Class: rviz/Orbit
250 | Distance: 29.867748260498047
251 | Enable Stereo Rendering:
252 | Stereo Eye Separation: 0.05999999865889549
253 | Stereo Focal Distance: 1
254 | Swap Stereo Eyes: false
255 | Value: false
256 | Field of View: 0.7853981852531433
257 | Focal Point:
258 | X: -0.457008957862854
259 | Y: 3.3725626468658447
260 | Z: -3.368089199066162
261 | Focal Shape Fixed Size: false
262 | Focal Shape Size: 0.05000000074505806
263 | Invert Z Axis: false
264 | Name: Current View
265 | Near Clip Distance: 0.009999999776482582
266 | Pitch: 1.039797067642212
267 | Target Frame:
268 | Yaw: 4.270313739776611
269 | Saved: ~
270 | Window Geometry:
271 | Displays:
272 | collapsed: false
273 | Height: 1308
274 | Hide Left Dock: false
275 | Hide Right Dock: true
276 | QMainWindow State: 000000ff00000000fd00000004000000000000029600000448fc0200000008fb0000001200530065006c0065006300740069006f006e00000001e10000009b0000005c00fffffffb0000001e0054006f006f006c002000500072006f007000650072007400690065007302000001ed000001df00000185000000b0fb000000120056006900650077007300200054006f006f02000001df000002110000018500000122fb000000200054006f006f006c002000500072006f0070006500720074006900650073003203000002880000011d000002210000017afb000000100044006900730070006c006100790073010000003d00000448000000c900fffffffb0000002000730065006c0065006300740069006f006e00200062007500660066006500720200000138000000aa0000023a00000294fb00000014005700690064006500530074006500720065006f02000000e6000000d2000003ee0000030bfb0000000c004b0069006e0065006300740200000186000001060000030c00000261000000010000010f00000342fc0200000003fb0000001e0054006f006f006c002000500072006f00700065007200740069006500730100000041000000780000000000000000fb0000000a00560069006500770073000000003d00000342000000a400fffffffb0000001200530065006c0065006300740069006f006e010000025a000000b200000000000000000000000200000490000000a9fc0100000001fb0000000a00560069006500770073030000004e00000080000002e10000019700000003000009b600000074fc0100000002fb0000000800540069006d00650100000000000009b6000003bc00fffffffb0000000800540069006d006501000000000000045000000000000000000000071a0000044800000004000000040000000800000008fc0000000100000002000000010000000a0054006f006f006c00730100000000ffffffff0000000000000000
277 | Selection:
278 | collapsed: false
279 | Time:
280 | collapsed: false
281 | Tool Properties:
282 | collapsed: false
283 | Views:
284 | collapsed: true
285 | Width: 2486
286 | X: 72
287 | Y: 27
288 |
--------------------------------------------------------------------------------
/src/cvc.hpp:
--------------------------------------------------------------------------------
1 | #ifndef CVC_CLUSTER_H
2 | #define CVC_CLUSTER_H
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 |
23 | #include
24 | #include
25 | #include
26 | #include
27 | #include
28 | #include "tools/utils.hpp"
29 | using PointType = PointXYZIRLICO;
30 |
31 | template
32 | std::string toString(const T &t)
33 | {
34 | std::ostringstream oss;
35 | oss << t;
36 | return oss.str();
37 | }
38 |
39 | struct PointAPR
40 | {
41 | float azimuth;
42 | float polar_angle;
43 | float range;
44 | float range_horizon;
45 | };
46 |
47 | struct Voxel
48 | {
49 | bool haspoint = false;
50 | int cluster = -1;
51 | std::vector index;
52 | };
53 |
54 | class CVC
55 | {
56 | public:
57 |
58 | void set_deltaA(float deltaA)
59 | {
60 | deltaA_ = deltaA;
61 | }
62 |
63 | void set_deltaR(float deltaR)
64 | {
65 | deltaR_ = deltaR;
66 | }
67 |
68 | void set_deltaP(float deltaP)
69 | {
70 | deltaP_ = deltaP;
71 | }
72 |
73 | void calculateAPR(const pcl::PointCloud &cloud_in, std::vector &vapr);
74 | void build_hash_table(const std::vector &vapr, std::unordered_map &map_out);
75 | void find_neighbors(int azimuth, int range, int polar, std::vector &neighborindex);
76 | bool most_frequent_value(std::vector values, std::vector &cluster_index);
77 | void mergeClusters(std::vector &cluster_indices, int idx1, int idx2);
78 | std::vector cluster(std::unordered_map &map_in, const std::vector &vapr);
79 | void process();
80 |
81 | private:
82 | //azimuth angle
83 | float deltaA_ = 0.4;
84 |
85 | //cvc range
86 | float deltaR_ = 0.3;
87 |
88 | //polar angle
89 | float deltaP_ = 4.0;
90 |
91 | float min_range_ = std::numeric_limits::max();
92 | float max_range_ = std::numeric_limits::min();
93 | float min_polar_ = -25.0 * M_PI / 180;
94 | float max_polar_ = 3.0 * M_PI / 180;
95 |
96 | int length_ = 0;
97 | int width_ = 0;
98 | int height_ = 0;
99 | };
100 |
101 |
102 | bool compare_cluster(std::pair a,std::pair b){
103 | return a.second>b.second;
104 | }//upper sort
105 |
106 | float azimuth_angle_cal(float x, float y)
107 | {
108 | float temp_tangle = 0;
109 | if (x == 0 && y == 0)
110 | {
111 | temp_tangle = 0;
112 | }
113 | else if (y >= 0)
114 | {
115 | temp_tangle = (float)atan2(y, x);
116 | }
117 | else if (y < 0)
118 | {
119 | temp_tangle = (float)atan2(y, x) + 2 * M_PI;
120 | }
121 | return temp_tangle;
122 | }
123 |
124 | void CVC::calculateAPR(const pcl::PointCloud& cloud_in, std::vector& vapr){
125 | for (int i =0; i max_range_){
136 | max_range_ = parp.range;
137 | }
138 | vapr.push_back(parp);
139 | }
140 |
141 | length_ = int((max_range_ - min_range_)/deltaR_)+1;
142 | width_ = round(360/deltaA_);
143 | height_ = int(((max_polar_ - min_polar_)*180/M_PI)/deltaP_)+1;
144 | }
145 |
146 | void CVC::build_hash_table(const std::vector& vapr, std::unordered_map &map_out)
147 | {
148 | for(int i =0; i< vapr.size(); ++i){
149 | int azimuth_index = int(vapr[i].azimuth*180/M_PI/deltaA_);
150 | int range_index = int((vapr[i].range - min_range_)/deltaR_);
151 | int polar_index = int(((vapr[i].polar_angle-min_polar_)*180/M_PI)/deltaP_);
152 | int voxel_index = (azimuth_index*(length_)+range_index)+polar_index*(length_)*(width_);
153 |
154 | std::unordered_map::iterator it_find;
155 | it_find = map_out.find(voxel_index);
156 | if (it_find != map_out.end())
157 | {
158 | it_find->second.index.push_back(i);
159 | }
160 | else
161 | {
162 | Voxel vox;
163 | vox.haspoint = true;
164 | vox.index.push_back(i);
165 | vox.index.swap(vox.index);
166 | map_out.insert(std::make_pair(voxel_index, vox));
167 | }
168 | }
169 | }
170 |
171 | void CVC::find_neighbors(int azimuth, int range, int polar, std::vector &neighborindex)
172 | {
173 | for (int z = polar - 1; z <= polar + 1; z++)
174 | {
175 | if (z < 0 || z > (height_ - 1))
176 | {
177 | continue;
178 | }
179 |
180 | for (int y = range - 1; y <= range + 1; y++)
181 | {
182 | if (y < 0 || y > (length_ - 1))
183 | {
184 | continue;
185 | }
186 | for (int x = azimuth - 1; x <= azimuth + 1; x++)
187 | {
188 | int px = x;
189 | if (x < 0)
190 | {
191 | px = width_ - 1;
192 | }
193 | if (x > (width_ - 1))
194 | {
195 | px = 0;
196 | }
197 | neighborindex.push_back((px * (length_) + y) + z * (length_) * (width_));
198 | }
199 | }
200 | }
201 | }
202 |
203 | std::vector CVC::cluster(std::unordered_map &map_in, const std::vector &vapr)
204 | {
205 | int current_cluster = 0;
206 |
207 | std::vector cluster_indices = std::vector(vapr.size(), -1);
208 |
209 | for (int i = 0; i < vapr.size(); ++i)
210 | {
211 | if (cluster_indices[i] != -1)
212 | continue;
213 |
214 | int azimuth_index = int(vapr[i].azimuth * 180 / M_PI / deltaA_);
215 | int range_index = int((vapr[i].range - min_range_) / deltaR_);
216 | int polar_index = int(((vapr[i].polar_angle - min_polar_) * 180 / M_PI) / deltaP_);
217 | int voxel_index = (azimuth_index * (length_) + range_index) + polar_index * (length_) * (width_);
218 |
219 | std::unordered_map::iterator it_find;
220 | std::unordered_map::iterator it_find2;
221 |
222 | it_find = map_in.find(voxel_index);
223 | std::vector neightbors;
224 |
225 | if (it_find != map_in.end())
226 | {
227 | std::vector neighborid;
228 | find_neighbors(azimuth_index, range_index, polar_index, neighborid);
229 | for (int k = 0; k < neighborid.size(); ++k)
230 | {
231 | it_find2 = map_in.find(neighborid[k]);
232 |
233 | if (it_find2 != map_in.end())
234 | {
235 | for (int j = 0; j < it_find2->second.index.size(); ++j)
236 | {
237 | neightbors.push_back(it_find2->second.index[j]);
238 | }
239 | }
240 | }
241 | }
242 |
243 | neightbors.swap(neightbors);
244 |
245 | if (neightbors.size() > 0)
246 | {
247 | for (int j = 0; j < neightbors.size(); ++j)
248 | {
249 | int oc = cluster_indices[i];
250 | int nc = cluster_indices[neightbors[j]];
251 | if (oc != -1 && nc != -1)
252 | {
253 | if (oc != nc)
254 | mergeClusters(cluster_indices, oc, nc);
255 | }
256 | else
257 | {
258 | if (nc != -1)
259 | {
260 | cluster_indices[i] = nc;
261 | }
262 | else
263 | {
264 | if (oc != -1)
265 | {
266 | cluster_indices[neightbors[j]] = oc;
267 | }
268 | }
269 | }
270 | }
271 | }
272 |
273 | if (cluster_indices[i] == -1)
274 | {
275 | current_cluster++;
276 | cluster_indices[i] = current_cluster;
277 | for (int s = 0; s < neightbors.size(); ++s)
278 | {
279 | cluster_indices[neightbors[s]] = current_cluster;
280 | }
281 | }
282 | }
283 | return cluster_indices;
284 | }
285 |
286 | void CVC::mergeClusters(std::vector& cluster_indices, int idx1, int idx2)
287 | {
288 | for (int i = 0; i < cluster_indices.size(); i++) {
289 | if (cluster_indices[i] == idx1) {
290 | cluster_indices[i] = idx2;
291 | }
292 | }
293 | }
294 |
295 | bool CVC::most_frequent_value(std::vector values, std::vector &cluster_index)
296 | {
297 | std::unordered_map histcounts;
298 | for (int i = 0; i < values.size(); i++)
299 | {
300 | if (histcounts.find(values[i]) == histcounts.end())
301 | {
302 | histcounts[values[i]] = 1;
303 | }
304 | else
305 | {
306 | histcounts[values[i]] += 1;
307 | }
308 | }
309 | int max = 0, maxi;
310 | std::vector> tr(histcounts.begin(), histcounts.end());
311 | sort(tr.begin(), tr.end(), compare_cluster);
312 | for (int i = 0; i < tr.size(); ++i)
313 | {
314 | if (tr[i].second > 10)
315 | {
316 | cluster_index.push_back(tr[i].first);
317 | }
318 | }
319 | return true;
320 | }
321 |
322 | #endif
--------------------------------------------------------------------------------
/include/tools/utils.hpp:
--------------------------------------------------------------------------------
1 | #ifndef COMMON_H
2 | #define COMMON_H
3 |
4 | #include "math.h"
5 | #include
6 | #include
7 | #include