Skip to content

Commit 8440daf

Browse files
committed
added universal checker
1 parent c50307f commit 8440daf

File tree

8 files changed

+190
-24
lines changed

8 files changed

+190
-24
lines changed

elevation_mapping_cupy/config/plugin_config.yaml

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,16 @@ semantic_filter:
5252
is_height_layer: False
5353
layer_name: "sem_fil"
5454
extra_params:
55-
# TODO make a better link between classes and color
5655
classes: ['grass','tree','fence','person']
57-
colors: [[0,255,0],[120,120,0],[170,0,20],[0,0,255],[255,0,0]]
56+
colors: [[0,255,0],[120,120,0],[170,0,20],[0,0,255],[255,0,0]]
57+
58+
semantic_traversability:
59+
type: "semantic_traversability"
60+
enable: False
61+
fill_nan: False
62+
is_height_layer: False
63+
layer_name: "sem_traversability"
64+
extra_params:
65+
layers: ['traversability','robot_centric_elevation']
66+
thresholds: [0.7,0.5]
67+
type: ['traversability', 'elevation']

elevation_mapping_cupy/script/elevation_mapping_cupy/elevation_mapping.py

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -595,6 +595,22 @@ def get_normal_ref(self, normal_x_data, normal_y_data, normal_z_data):
595595
normal_y_data[...] = xp.asnumpy(maps[1], stream=self.stream)
596596
normal_z_data[...] = xp.asnumpy(maps[2], stream=self.stream)
597597

598+
def get_layer(self,name):
599+
if name in self.layer_names:
600+
idx = self.layer_names.index(name)
601+
map = self.elevation_map[idx]
602+
elif name in self.semantic_map.param.additional_layers:
603+
idx = self.semantic_map.param.additional_layers.index(name)
604+
map= self.semantic_map.map[idx]
605+
elif name in self.plugin_manager.layer_names:
606+
self.plugin_manager.update_with_name(name, self.elevation_map, self.layer_names, self.semantic_map,
607+
self.base_rotation)
608+
map = self.plugin_manager.get_map_with_name(name)
609+
else:
610+
print("Layer {} is not in the map, returning traversabiltiy!".format(name))
611+
return
612+
return map
613+
598614
def get_polygon_traversability(self, polygon, result):
599615
""" Check if input polygons are traversable.
600616
@@ -626,11 +642,12 @@ def get_polygon_traversability(self, polygon, result):
626642
self.mask,
627643
size=(self.cell_n * self.cell_n),
628644
)
629-
masked, masked_isvalid = get_masked_traversability(self.elevation_map, self.mask)
645+
map = self.get_layer(self.param.checker_layer)
646+
masked, masked_isvalid = get_masked_traversability(self.elevation_map, self.mask, map)
630647
if masked_isvalid.sum() > 0:
631648
t = masked.sum() / masked_isvalid.sum()
632649
else:
633-
t = cp.asarray(0.0,dtype=self.data_type)
650+
t = cp.asarray(0.0, dtype=self.data_type)
634651
is_safe, un_polygon = is_traversable(
635652
masked, self.param.safe_thresh, self.param.safe_min_thresh, self.param.max_unsafe_n
636653
)
@@ -697,14 +714,14 @@ def initialize_map(self, points, method="cubic"):
697714
layers = ["elevation", "variance", "traversability", "min_filter", "smooth", "inpaint","rgb"]
698715
points = xp.random.rand(100000, len(layers))
699716

700-
channels = ['x','y','z']+ param.additional_layers
717+
channels = ['x', 'y', 'z'] + param.additional_layers
701718
print(channels)
702719
data = np.zeros((elevation.cell_n - 2, elevation.cell_n - 2), dtype=np.float32)
703720
for i in range(20):
704721
elevation.input(points,channels, R, t, 0, 0)
705722
elevation.update_normal(elevation.elevation_map[0])
706723
pos = np.array([i * 0.01, i * 0.02, i * 0.01])
707-
elevation.move_to(pos,R)
724+
elevation.move_to(pos, R)
708725
for layer in layers:
709726
elevation.get_map_with_name_ref(layer, data)
710727
print(i)

elevation_mapping_cupy/script/elevation_mapping_cupy/parameter.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,13 @@
1010

1111
@dataclass
1212
class Parameter(Serializable):
13-
resolution: float = 0.02
13+
resolution: float = 0.04
1414
additional_layers: list = ['feat_0'].copy
1515
fusion_algorithms: list = ['average'].copy
1616
cell_n: int = None
1717
data_type: str = np.float32
1818

19-
map_length: float = 10.0
19+
map_length: float = 8.0
2020
sensor_noise_factor: float = 0.05
2121
mahalanobis_thresh: float = 2.0
2222
outlier_variance: float = 0.01
@@ -45,6 +45,7 @@ class Parameter(Serializable):
4545
safe_thresh: float = 0.5
4646
safe_min_thresh: float = 0.5
4747
max_unsafe_n: int = 20
48+
checker_layer: str = 'traversability'
4849

4950
min_filter_size: int = 5
5051
min_filter_iteration: int = 3
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 SemanticTraversability(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+
layers: list = ["traversability"],
27+
thresholds: list = [0.5],
28+
type: list = ["traversability"],
29+
**kwargs,
30+
):
31+
super().__init__()
32+
self.layers = layers
33+
self.thresholds = cp.asarray(thresholds)
34+
self.type = type
35+
36+
def __call__(
37+
self,
38+
elevation_map: cp.ndarray,
39+
layer_names: List[str],
40+
plugin_layers: cp.ndarray,
41+
plugin_layer_names: List[str],
42+
semantic_map,
43+
*args,
44+
) -> cp.ndarray:
45+
# get indices of all layers that
46+
map = cp.zeros(elevation_map[2].shape, np.float32)
47+
tempo = cp.zeros(elevation_map[2].shape, np.float32)
48+
for it, name in enumerate(self.layers):
49+
if name in layer_names:
50+
idx = layer_names.index(name)
51+
tempo = elevation_map[idx]
52+
elif name in semantic_map.param.additional_layers:
53+
idx = semantic_map.param.additional_layers.index(name)
54+
tempo = semantic_map.map[idx]
55+
elif name in plugin_layer_names:
56+
idx = plugin_layer_names.index(name)
57+
tempo = plugin_layers[idx]
58+
else:
59+
print(
60+
"Layer {} is not in the map, returning traversabiltiy!".format(name)
61+
)
62+
return
63+
if self.type[it] == "traversability":
64+
tempo = cp.where(tempo <= self.thresholds[it], 1, 0)
65+
map += tempo
66+
else:
67+
tempo = cp.where(tempo >= self.thresholds[it], 1, 0)
68+
map += tempo
69+
map = cp.where(map <= 0.9, 0.1,1)
70+
71+
return map
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# Settings of the plugins. (The plugins should be stored in script/plugins)
2+
3+
# min_filter fills in minimum value around the invalid cell.
4+
min_filter:
5+
enable: True # weather to load this plugin
6+
fill_nan: False # Fill nans to invalid cells of elevation layer.
7+
is_height_layer: True # If this is a height layer (such as elevation) or not (such as traversability)
8+
layer_name: "min_filter" # The layer name.
9+
extra_params: # This params are passed to the plugin class on initialization.
10+
dilation_size: 1 # The patch size to apply
11+
iteration_n: 30 # The number of iterations
12+
# Apply smoothing.
13+
smooth_filter:
14+
enable: True
15+
fill_nan: False
16+
is_height_layer: True
17+
layer_name: "smooth"
18+
extra_params:
19+
input_layer_name: "min_filter"
20+
# Apply inpainting using opencv
21+
inpainting:
22+
enable: True
23+
fill_nan: False
24+
is_height_layer: True
25+
layer_name: "inpaint"
26+
extra_params:
27+
method: "telea" # telea or ns
28+
# Apply smoothing for inpainted layer
29+
smooth_filter_1:
30+
type: "smooth_filter"
31+
enable: True
32+
fill_nan: False
33+
is_height_layer: True
34+
layer_name: "smooth_1"
35+
extra_params:
36+
input_layer_name: "inpaint"
37+
robot_centric_elevation: # Use the same name as your file name.
38+
# type: "robot_centric_elevation"
39+
enable: True # weather to load this plugin
40+
fill_nan: False # Fill nans to invalid cells of elevation layer.
41+
is_height_layer: True # If this is a height layer (such as elevation) or not (such as traversability)
42+
layer_name: "robot_centric_elevation" # The layer name.
43+
extra_params: # This params are passed to the plugin class on initialization.
44+
# add_value: 2.0 # Example param
45+
resolution: 0.04
46+
threshold: 1.1
47+
use_threshold: True
48+
semantic_filter:
49+
type: "semantic_filter"
50+
enable: True
51+
fill_nan: False
52+
is_height_layer: False
53+
layer_name: "sem_fil"
54+
extra_params:
55+
classes: ['grass','tree','fence','person']
56+
colors: [[0,255,0],[120,120,0],[170,0,20],[0,0,255],[255,0,0]]
57+
semantic_traversability:
58+
type: "semantic_traversability"
59+
enable: True
60+
fill_nan: False
61+
is_height_layer: False
62+
layer_name: "sem_traversability"
63+
extra_params:
64+
layers: ['traversability','robot_centric_elevation']
65+
thresholds: [0.7,0.5]
66+
type: ['traversability', 'elevation']

elevation_mapping_cupy/script/elevation_mapping_cupy/tests/test_elevation_mapping.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,6 @@ def test_initialize_map(self, elmap_ex):
9494

9595
def test_plugins(self, elmap_ex):
9696
layers = elmap_ex.plugin_manager.layer_names
97-
data= np.zeros((500,500),dtype=np.float32)
97+
data = np.zeros((200, 200), dtype=np.float32)
9898
for layer in layers:
99-
elmap_ex.get_map_with_name_ref(layer, data)
99+
elmap_ex.get_map_with_name_ref(layer, data)

elevation_mapping_cupy/script/elevation_mapping_cupy/tests/test_plugins.py

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import numpy as np
55
from elevation_mapping_cupy.plugins.plugin_manager import PluginManager, PluginParams
66

7-
plugin_path = "../../../config/plugin_config.yaml"
7+
plugin_path = "plugin_config.yaml"
88

99

1010
@pytest.fixture()
@@ -28,19 +28,19 @@ def semmap_ex(add_lay, fusion_alg):
2828
@pytest.mark.parametrize(
2929
"add_lay, fusion_alg,channels",
3030
[
31-
(["feat_0", "feat_1"], ["average", "average"], ["feat_0"]),
32-
(["feat_0", "feat_1"], ["average", "average"], []),
33-
(
34-
["feat_0", "feat_1", "rgb"],
35-
["average", "average", "color"],
36-
["rgb", "feat_0"],
37-
),
31+
(['grass','tree','fence','person'], ["class_average", "class_average", "class_average", "class_average"], ["grass"]),
32+
(['grass','tree'], ["class_average", "class_average"], ['grass']),
33+
# (
34+
# ["feat_0", "feat_1", "rgb"],
35+
# ["average", "average", "color"],
36+
# ["rgb", "feat_0"],
37+
# ),
3838
],
3939
)
4040
def test_plugin_manager(semmap_ex, channels):
41-
manager = PluginManager(200)
41+
manager = PluginManager(202)
4242
manager.load_plugin_settings(plugin_path)
43-
elevation_map = cp.zeros((7, 200, 200)).astype(cp.float32)
43+
elevation_map = cp.zeros((7, 202, 202)).astype(cp.float32)
4444
rotation = cp.eye(3,dtype=cp.float32)
4545
layer_names = [
4646
"elevation",
@@ -51,13 +51,14 @@ def test_plugin_manager(semmap_ex, channels):
5151
"upper_bound",
5252
"is_upper_bound",
5353
]
54-
elevation_map[0] = cp.random.randn(200, 200)
55-
elevation_map[2] = cp.abs(cp.random.randn(200, 200))
54+
elevation_map[0] = cp.random.randn(202, 202)
55+
elevation_map[2] = cp.abs(cp.random.randn(202, 202))
5656
elevation_map[0]
5757
manager.layers[0]
5858
manager.update_with_name("min_filter", elevation_map, layer_names)
5959
manager.update_with_name("smooth_filter", elevation_map, layer_names)
6060
manager.update_with_name("semantic_filter", elevation_map, layer_names,semmap_ex,rotation)
61+
manager.update_with_name("semantic_traversability", elevation_map, layer_names,semmap_ex)
6162
manager.get_map_with_name("smooth")
6263
for lay in manager.get_layer_names():
6364
manager.update_with_name(lay,elevation_map,layer_names,semmap_ex,rotation)

elevation_mapping_cupy/script/elevation_mapping_cupy/traversability_polygon.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
from shapely.geometry import Polygon, MultiPoint
88

99

10-
def get_masked_traversability(map_array, mask):
11-
traversability = map_array[3][1:-1, 1:-1]
10+
def get_masked_traversability(map_array, mask, traversability):
11+
traversability = traversability[1:-1, 1:-1]
1212
is_valid = map_array[2][1:-1, 1:-1]
1313
mask = mask[1:-1, 1:-1]
1414

0 commit comments

Comments
 (0)