Skip to content

Commit 189609e

Browse files
committed
changed to float32, added the color plugin for the classes and added first plugin tests
1 parent 7c0de6a commit 189609e

File tree

14 files changed

+207
-110
lines changed

14 files changed

+207
-110
lines changed

elevation_mapping_cupy/config/parameters.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ publishers:
8181
basic_layers: ['elevation', 'traversability']
8282
fps: 2.0
8383
elevation_map_filter:
84-
layers: ['min_filter', 'smooth', 'inpaint', 'upper_bound','rgb','person']
84+
layers: ['min_filter', 'smooth', 'inpaint', 'upper_bound','rgb','sem_fil']
8585
basic_layers: ['min_filter']
8686
fps: 3.0
8787

elevation_mapping_cupy/config/plugin_config.yaml

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ smooth_filter:
1818
extra_params:
1919
input_layer_name: "min_filter"
2020
# Apply inpainting using opencv
21-
inpainting:
21+
inpainting:
2222
enable: True
2323
fill_nan: False
2424
is_height_layer: True
@@ -34,3 +34,14 @@ smooth_filter_1:
3434
layer_name: "smooth_1"
3535
extra_params:
3636
input_layer_name: "inpaint"
37+
38+
semantic_filter:
39+
type: "semantic_filter"
40+
enable: False
41+
fill_nan: False
42+
is_height_layer: False
43+
layer_name: "sem_fil"
44+
extra_params:
45+
# TODO make a better link between classes and color
46+
classes: ['grass','tree','fence','person']
47+
colors: [[0,255,0],[120,120,0],[170,0,20],[0,0,255],[255,0,0]]

elevation_mapping_cupy/config/sensor_parameter.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ subscribers:
44
# fusion: ['average','average']
55
# topic_name: '/elevation_mapping/pointcloud_semantic'
66
front_cam:
7-
channels: []
8-
fusion: []
7+
channels: ['rgb','feat_0','feat_1','grass','tree','fence','person']
8+
fusion: ['color','average','average','class_average','class_average','class_average','class_average']
99
topic_name: '/elvation_mapping/pointcloud_semantic'
1010
semantic_segmentation: False
1111
segmentation_model: 'detectron_coco_panoptic_fpn_R_101_3x'

elevation_mapping_cupy/rviz/lonomy_single.rviz

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,8 @@ Visualization Manager:
5555
Autocompute Intensity Bounds: true
5656
Class: grid_map_rviz_plugin/GridMap
5757
Color: 200; 200; 200
58-
Color Layer: person
59-
Color Transformer: IntensityLayer
58+
Color Layer: rgb
59+
Color Transformer: ColorLayer
6060
Enabled: true
6161
Height Layer: smooth
6262
Height Transformer: GridMapLayer
@@ -449,9 +449,9 @@ Visualization Manager:
449449
Invert Z Axis: false
450450
Name: Current View
451451
Near Clip Distance: 0.009999999776482582
452-
Pitch: 0.5547983050346375
452+
Pitch: 0.6447982788085938
453453
Target Frame: base_footprint
454-
Yaw: 1.4138503074645996
454+
Yaw: 1.8688498735427856
455455
Saved: ~
456456
Window Geometry:
457457
Displays:

elevation_mapping_cupy/script/elevation_mapping_cupy/custom_kernels.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -665,7 +665,7 @@ def sum_kernel(
665665
# input the list of layers, amount of channels can slo be input through kernel
666666
sum_kernel = cp.ElementwiseKernel(
667667
in_params="raw U p, raw U R, raw U t, raw W pcl_chan, raw W map_lay, raw W pcl_channels",
668-
out_params="raw U map, raw T newmap",
668+
out_params="raw U map, raw U newmap",
669669
preamble=string.Template(
670670
"""
671671
__device__ int get_map_idx(int idx, int layer_n) {
@@ -681,7 +681,7 @@ def sum_kernel(
681681
U inside = p[i * pcl_channels[0] + 2];
682682
if (valid) {
683683
if (inside) {
684-
for ( int it=0;it<pcl_channels[1];it++){
684+
for ( W it=0;it<pcl_channels[1];it++){
685685
U feat = p[i * pcl_channels[0] + pcl_chan[it]];
686686
atomicAdd(&newmap[get_map_idx(idx, map_lay[it])], feat);
687687
}
@@ -864,7 +864,8 @@ def color_average_kernel(
864864
// unsigned int b = prev_b/2 + color_map[get_map_idx(i, it*3+2)]/(2*cnt);
865865
//}
866866
unsigned int rgb = (r<<16) + (g << 8) + b;
867-
map[get_map_idx(i, map_lay[it])] = rgb;
867+
float rgb_ = __uint_as_float(rgb);
868+
map[get_map_idx(i, map_lay[it])] = rgb_;
868869
}
869870
}
870871
"""

elevation_mapping_cupy/script/elevation_mapping_cupy/elevation_mapping.py

Lines changed: 22 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@
3636
pool = cp.cuda.MemoryPool(cp.cuda.malloc_managed)
3737
cp.cuda.set_allocator(pool.malloc)
3838

39-
4039
class ElevationMap:
4140
"""
4241
Core elevation mapping class.
@@ -49,16 +48,16 @@ def __init__(self, param: Parameter):
4948
param (elevation_mapping_cupy.parameter.Parameter):
5049
"""
5150
self.param = param
52-
51+
self.data_type = self.param.data_type
5352
self.resolution = param.resolution
54-
self.center = xp.array([0, 0, 0], dtype=float)
53+
self.center = xp.array([0, 0, 0], dtype=self.data_type)
5554
self.map_length = param.map_length
5655
self.cell_n = param.cell_n
5756

5857
self.map_lock = threading.Lock()
5958
self.additional_layers = dict(zip(self.param.additional_layers, self.param.fusion_algorithms))
6059
self.semantic_map = SemanticMap(self.param, self.additional_layers)
61-
self.elevation_map = xp.zeros((7, self.cell_n, self.cell_n))
60+
self.elevation_map = xp.zeros((7, self.cell_n, self.cell_n),dtype=self.data_type)
6261
self.layer_names = [
6362
"elevation",
6463
"variance",
@@ -71,7 +70,7 @@ def __init__(self, param: Parameter):
7170

7271
# buffers
7372
self.traversability_buffer = xp.full((self.cell_n, self.cell_n), xp.nan)
74-
self.normal_map = xp.zeros((3, self.cell_n, self.cell_n))
73+
self.normal_map = xp.zeros((3, self.cell_n, self.cell_n),dtype=self.data_type)
7574
# Initial variance
7675
self.initial_variance = param.initial_variance
7776
self.elevation_map[1] += self.initial_variance
@@ -223,12 +222,12 @@ def compile_kernels(self):
223222
224223
"""
225224
# Compile custom cuda kernels.
226-
self.new_map = cp.zeros((self.elevation_map.shape[0], self.cell_n, self.cell_n))
227-
self.traversability_input = cp.zeros((self.cell_n, self.cell_n))
228-
self.traversability_mask_dummy = cp.zeros((self.cell_n, self.cell_n))
229-
self.min_filtered = cp.zeros((self.cell_n, self.cell_n))
230-
self.min_filtered_mask = cp.zeros((self.cell_n, self.cell_n))
231-
self.mask = cp.zeros((self.cell_n, self.cell_n))
225+
self.new_map = cp.zeros((self.elevation_map.shape[0], self.cell_n, self.cell_n),dtype=self.data_type)
226+
self.traversability_input = cp.zeros((self.cell_n, self.cell_n),dtype=self.data_type)
227+
self.traversability_mask_dummy = cp.zeros((self.cell_n, self.cell_n),dtype=self.data_type)
228+
self.min_filtered = cp.zeros((self.cell_n, self.cell_n),dtype=self.data_type)
229+
self.min_filtered_mask = cp.zeros((self.cell_n, self.cell_n),dtype=self.data_type)
230+
self.mask = cp.zeros((self.cell_n, self.cell_n),dtype=self.data_type)
232231
self.add_points_kernel = add_points_kernel(
233232
self.resolution,
234233
self.cell_n,
@@ -302,8 +301,8 @@ def update_map_with_kernel(self, points_all, channels, R, t, position_noise, ori
302301
self.error_counting_kernel(
303302
self.elevation_map,
304303
points,
305-
cp.array([0.0]),
306-
cp.array([0.0]),
304+
cp.array([0.0],dtype=self.data_type),
305+
cp.array([0.0],dtype=self.data_type),
307306
R,
308307
t,
309308
self.new_map,
@@ -324,8 +323,8 @@ def update_map_with_kernel(self, points_all, channels, R, t, position_noise, ori
324323
if np.abs(self.mean_error) < self.param.max_drift:
325324
self.elevation_map[0] += self.mean_error * self.param.drift_compensation_alpha
326325
self.add_points_kernel(
327-
cp.array([0.0]),
328-
cp.array([0.0]),
326+
cp.array([0.0],dtype=self.data_type),
327+
cp.array([0.0],dtype=self.data_type),
329328
R,
330329
t,
331330
self.normal_map,
@@ -337,7 +336,7 @@ def update_map_with_kernel(self, points_all, channels, R, t, position_noise, ori
337336
self.average_map_kernel(self.new_map, self.elevation_map, size=(self.cell_n * self.cell_n))
338337

339338
# self.update_additional_layers(additional_fusion, points_all, channels, R, t)
340-
self.semantic_map.update_layers(points_all, channels, R, t,self.new_map)
339+
self.semantic_map.update_layers(points_all, channels, R, t, self.new_map)
341340

342341
if self.param.enable_overlap_clearance:
343342
self.clear_overlap_map(t)
@@ -405,10 +404,10 @@ def input(self, raw_points: cp._core.core.ndarray, channels: List[str], R: cp._c
405404
None:
406405
"""
407406
# Update elevation map using point cloud input.
408-
raw_points = cp.asarray(raw_points)
407+
raw_points = cp.asarray(raw_points, dtype=self.data_type)
409408
additional_channels = channels[3:]
410409
raw_points = raw_points[~cp.isnan(raw_points).any(axis=1)]
411-
self.update_map_with_kernel(raw_points, additional_channels, cp.asarray(R), cp.asarray(t), position_noise, orientation_noise)
410+
self.update_map_with_kernel(raw_points, additional_channels, cp.asarray(R,dtype=self.data_type), cp.asarray(t,dtype=self.data_type), position_noise, orientation_noise)
412411

413412
def update_normal(self, dilated_map):
414413
""" Clear the normal map and then apply the normal kernel with dilated map as input.
@@ -561,7 +560,7 @@ def get_map_with_name_ref(self, name, data):
561560
elif name in self.additional_layers.keys():
562561
m = self.semantic_map.get_map_with_name(name)
563562
elif name in self.plugin_manager.layer_names:
564-
self.plugin_manager.update_with_name(name, self.elevation_map, self.layer_names)
563+
self.plugin_manager.update_with_name(name, self.elevation_map, self.layer_names, self.semantic_map)
565564
m = self.plugin_manager.get_map_with_name(name)
566565
p = self.plugin_manager.get_param_with_name(name)
567566
xp = self.xp_of_array(m)
@@ -607,7 +606,7 @@ def get_polygon_traversability(self, polygon, result):
607606
"""
608607
polygon = xp.asarray(polygon)
609608
area = calculate_area(polygon)
610-
polygon = polygon.astype(np.float64)
609+
polygon = polygon.astype(self.data_type)
611610
pmin = self.center[:2] - self.map_length / 2 + self.resolution
612611
pmax = self.center[:2] + self.map_length / 2 - self.resolution
613612
polygon[:, 0] = polygon[:, 0].clip(pmin[0], pmax[0])
@@ -630,7 +629,7 @@ def get_polygon_traversability(self, polygon, result):
630629
if masked_isvalid.sum() > 0:
631630
t = masked.sum() / masked_isvalid.sum()
632631
else:
633-
t = cp.asarray(0.0)
632+
t = cp.asarray(0.0,dtype=self.data_type)
634633
is_safe, un_polygon = is_traversable(
635634
masked, self.param.safe_thresh, self.param.safe_min_thresh, self.param.max_unsafe_n
636635
)
@@ -662,7 +661,7 @@ def initialize_map(self, points, method="cubic"):
662661
"""
663662
self.clear()
664663
with self.map_lock:
665-
points = cp.asarray(points)
664+
points = cp.asarray(points,dtype=self.data_type)
666665
indices = transform_to_map_index(points[:, :2], self.center[:2], self.cell_n, self.resolution)
667666
points[:, :2] = indices.astype(points.dtype)
668667
points[:, 2] -= self.center[2]
@@ -708,7 +707,7 @@ def initialize_map(self, points, method="cubic"):
708707
for layer in layers:
709708
elevation.get_map_with_name_ref(layer, data)
710709
print(i)
711-
polygon = cp.array([[0, 0], [2, 0], [0, 2]], dtype=np.float64)
710+
polygon = cp.array([[0, 0], [2, 0], [0, 2]], dtype=param.data_type)
712711
result = np.array([0, 0, 0])
713712
elevation.get_polygon_traversability(polygon, result)
714713
print(result)

elevation_mapping_cupy/script/elevation_mapping_cupy/parameter.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ class Parameter(Serializable):
1414
additional_layers: list = ['feat_0'].copy
1515
fusion_algorithms: list = ['average'].copy
1616
cell_n: int = None
17+
data_type: str = np.float32
1718

1819
map_length: float = 10.0
1920
sensor_noise_factor: float = 0.05

elevation_mapping_cupy/script/elevation_mapping_cupy/plugins/plugin_manager.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,9 @@ def init(self, plugin_params: List[PluginParams], extra_params: List[Dict]):
8989
# Add cell_n to params
9090
extra_param["cell_n"] = self.cell_n
9191
self.plugins.append(obj(**extra_param))
92-
93-
self.layers = cp.zeros((len(self.plugins), self.cell_n, self.cell_n))
92+
self.layers = cp.zeros(
93+
(len(self.plugins), self.cell_n, self.cell_n), dtype=cp.float32
94+
)
9495
self.layer_names = self.get_layer_names()
9596
self.plugin_names = self.get_plugin_names()
9697

@@ -212,7 +213,8 @@ def get_param_with_name(self, name: str) -> PluginParams:
212213
elevation_map[0] = cp.random.randn(200, 200)
213214
elevation_map[2] = cp.abs(cp.random.randn(200, 200))
214215
print("map", elevation_map[0])
215-
print("layer map ", manager.layers[0])
216+
print("layer map ", manager.layers)
216217
manager.update_with_name("min_filter", elevation_map, layer_names)
217-
manager.update_with_name("smooth", elevation_map, layer_names)
218+
manager.update_with_name("smooth_filter", elevation_map, layer_names)
219+
# manager.update_with_name("sem_fil", elevation_map, layer_names, semantic_map=semantic_map)
218220
print(manager.get_map_with_name("smooth"))
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
#
2+
# Copyright (c) 2022, Takahiro Miki. All rights reserved.
3+
# Licensed under the MIT license. See LICENSE file in the project root for details.
4+
#
5+
import cupy as cp
6+
import numpy as np
7+
from typing import List
8+
9+
from elevation_mapping_cupy.plugins.plugin_manager import PluginBase
10+
11+
12+
class SemanticFilter(PluginBase):
13+
"""This is a filter to create colors
14+
15+
...
16+
17+
Attributes
18+
----------
19+
cell_n: int
20+
width and height of the elevation map.
21+
"""
22+
23+
def __init__(
24+
self,
25+
cell_n: int = 100,
26+
classes: list = ["person", "grass"],
27+
colors: list = [
28+
[0, 255, 0],
29+
[0, 255, 255],
30+
[0, 0, 255],
31+
[255, 255, 0],
32+
[255, 0, 0],
33+
],
34+
**kwargs,
35+
):
36+
super().__init__()
37+
self.indices = []
38+
self.classes = classes
39+
color_classes = np.array(colors)
40+
self.color_encoding = self.transform_color(color_classes)
41+
42+
def transform_color(self, color_classes):
43+
r = np.asarray(color_classes[:, 0], dtype=np.uint32)
44+
g = np.asarray(color_classes[:, 1], dtype=np.uint32)
45+
b = np.asarray(color_classes[:, 2], dtype=np.uint32)
46+
rgb_arr = np.array((r << 16) | (g << 8) | (b << 0), dtype=np.uint32)
47+
rgb_arr.dtype = np.float32
48+
return cp.asarray(rgb_arr)
49+
50+
def __call__(
51+
self,
52+
elevation_map: cp.ndarray,
53+
layer_names: List[str],
54+
plugin_layers: cp.ndarray,
55+
plugin_layer_names: List[str],
56+
semantic_map,
57+
**kwargs,
58+
) -> cp.ndarray:
59+
# get indices of all layers that
60+
layer_indices = cp.array([], dtype=cp.int32)
61+
for it, fusion_alg in enumerate(semantic_map.param.fusion_algorithms):
62+
if fusion_alg == "class_average" and (
63+
semantic_map.param.additional_layers[it] in self.classes
64+
):
65+
layer_indices = cp.append(layer_indices, it).astype(cp.int32)
66+
67+
# check which has the highest value
68+
class_map = cp.argmax(semantic_map.map[layer_indices], axis=0)
69+
# create color coding
70+
enc = self.color_encoding[class_map]
71+
return enc

elevation_mapping_cupy/script/elevation_mapping_cupy/plugins/semantic_map.py

Lines changed: 0 additions & 53 deletions
This file was deleted.

0 commit comments

Comments
 (0)