Skip to content

Commit ed6c20a

Browse files
committed
added python wrapper
1 parent fc14aa9 commit ed6c20a

File tree

5 files changed

+161
-18
lines changed

5 files changed

+161
-18
lines changed

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
*.pyc
22
*.bkp
33
*.orig
4-
.idea
4+
.idea*
5+
.vscode*
6+
*.egg-info
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
from .parameter import Parameter
2+
from .elevation_mapping import ElevationMap

elevation_mapping_cupy/script/elevation_mapping_cupy/elevation_mapping.py

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,19 @@
99
import threading
1010
import subprocess
1111

12-
from .traversability_filter import get_filter_chainer, get_filter_torch
13-
from .parameter import Parameter
14-
from .custom_kernels import add_points_kernel, add_color_kernel, color_average_kernel
15-
from .custom_kernels import sum_kernel
16-
from .custom_kernels import error_counting_kernel
17-
from .custom_kernels import average_map_kernel
18-
from .custom_kernels import dilation_filter_kernel
19-
from .custom_kernels import normal_filter_kernel
20-
from .custom_kernels import polygon_mask_kernel
21-
from .map_initializer import MapInitializer
22-
from .plugins.plugin_manager import PluginManager
23-
from .semantic_map import SemanticMap
24-
25-
from .traversability_polygon import (
12+
from elevation_mapping_cupy.traversability_filter import get_filter_chainer, get_filter_torch
13+
from elevation_mapping_cupy.parameter import Parameter
14+
from elevation_mapping_cupy.custom_kernels import add_points_kernel, add_color_kernel, color_average_kernel
15+
from elevation_mapping_cupy.custom_kernels import sum_kernel
16+
from elevation_mapping_cupy.custom_kernels import error_counting_kernel
17+
from elevation_mapping_cupy.custom_kernels import average_map_kernel
18+
from elevation_mapping_cupy.custom_kernels import dilation_filter_kernel
19+
from elevation_mapping_cupy.custom_kernels import normal_filter_kernel
20+
from elevation_mapping_cupy.custom_kernels import polygon_mask_kernel
21+
from elevation_mapping_cupy.map_initializer import MapInitializer
22+
from elevation_mapping_cupy.plugins.plugin_manager import PluginManager
23+
from elevation_mapping_cupy.semantic_map import SemanticMap
24+
from elevation_mapping_cupy.traversability_polygon import (
2625
get_masked_traversability,
2726
is_traversable,
2827
calculate_area,
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
from elevation_mapping_cupy import ElevationMap
2+
from elevation_mapping_cupy import Parameter
3+
4+
# General
5+
import os
6+
import numpy as np
7+
8+
# ROS
9+
import rospy
10+
import ros_numpy
11+
from tf.transformations import quaternion_matrix
12+
from sensor_msgs.msg import PointCloud2
13+
import tf2_ros
14+
import rospkg
15+
16+
class ElevationMapWrapper():
17+
def __init__(self):
18+
rospack = rospkg.RosPack()
19+
self.root = rospack.get_path("elevation_mapping_cupy")
20+
self.initalize_elevation_mapping()
21+
22+
# ROS
23+
self.initalize_ros()
24+
self.register_subscribers()
25+
self.register_publishers()
26+
self.register_timers()
27+
28+
def initalize_elevation_mapping(self):
29+
weight_file = os.path.join(self.root, "config/weights.dat")
30+
plugin_config_file = os.path.join(self.root, "config/plugin_config.yaml")
31+
param = Parameter( use_chainer=False, weight_file=weight_file, plugin_config_file=plugin_config_file )
32+
self._pointcloud_process_counter = 0
33+
self._map = ElevationMap(param)
34+
self._map_data = np.zeros((self._map.cell_n - 2, self._map.cell_n - 2), dtype=np.float32)
35+
36+
def initalize_ros(self):
37+
rospy.init_node("elevation_mapping", anonymous=False)
38+
self._tf_buffer = tf2_ros.Buffer()
39+
self._listener = tf2_ros.TransformListener(self._tf_buffer)
40+
self.get_ros_params()
41+
42+
def register_subscribers(self):
43+
pointcloud_subs = {}
44+
for config in self.subscribers.values():
45+
self.subscribers
46+
rospy.Subscriber(config["topic_name"], PointCloud2, self.pointcloud_callback, (config["channels"], config["fusion"]))
47+
48+
def register_publishers(self):
49+
# TODO publishers
50+
print(self.publishers)
51+
52+
def register_timers(self):
53+
self.timer_variance = rospy.Timer(rospy.Duration(1/self.update_variance_fps), self.update_variance)
54+
self.timer_pose = rospy.Timer(rospy.Duration(1/self.update_pose_fps), self.update_pose)
55+
self.timer_time = rospy.Timer(rospy.Duration(self.time_interval), self.update_time)
56+
57+
def pointcloud_callback(self, data, config):
58+
# convert pcd into numpy array
59+
points = ros_numpy.numpify(data)
60+
out = np.copy( np.frombuffer(points.tobytes(), np.dtype(np.float32) ))
61+
out = out.reshape(out.shape[0],-1)[:,:3]
62+
points = points.astype(np.float32)
63+
64+
# get pose of pointcloud
65+
t = rospy.Time(secs=data.header.stamp.secs, nsecs=data.header.stamp.nsecs)
66+
try:
67+
transform = self._tf_buffer.lookup_transform(self.map_frame, data.header.frame_id, t, rospy.Duration(1.0))
68+
except (tf2_ros.LookupException, tf2_ros.ConnectivityException, tf2_ros.ExtrapolationException) as e:
69+
print(e)
70+
return
71+
72+
t = transform.transform.translation
73+
t = np.array( [t.x, t.y, t.z] )
74+
q = transform.transform.rotation
75+
R = quaternion_matrix([q.w, q.x, q.y, q.z])
76+
77+
# process pointcloud
78+
self._map.input(points, 0, R, t, 0, 0)
79+
self._map.update_normal(self._map.elevation_map[0])
80+
self._pointcloud_process_counter += 1
81+
82+
def update_pose(self, t):
83+
# get pose of base
84+
t = rospy.Time.now()
85+
try:
86+
transform = self._tf_buffer.lookup_transform(self.map_frame, self.base_frame, t, rospy.Duration(1.0))
87+
except (tf2_ros.LookupException, tf2_ros.ConnectivityException, tf2_ros.ExtrapolationException) as e:
88+
print(e)
89+
return
90+
t = transform.transform.translation
91+
trans = np.array( [t.x, t.y, t.z] )
92+
q = transform.transform.rotation
93+
rot = quaternion_matrix([q.w, q.x, q.y, q.z])
94+
self._map.move_to(trans, rot)
95+
96+
def update_variance(self, t):
97+
self._map.update_variance()
98+
99+
def update_time(self, t):
100+
self._map.update_time()
101+
102+
def get_ros_params(self):
103+
# TODO fix this here when later launching with launch-file
104+
# This is currently {p} elevation_mapping")
105+
para = os.path.join(self.root, "config/parameters.yaml")
106+
sens = os.path.join(self.root, "config/sensor_parameter.yaml")
107+
os.system(f"rosparam load {para} elevation_mapping")
108+
os.system(f"rosparam load {sens} elevation_mapping")
109+
110+
self.subscribers = rospy.get_param("~subscribers")
111+
self.publishers = rospy.get_param("~publishers")
112+
self.initialize_frame_id = rospy.get_param("~initialize_frame_id", "base")
113+
self.initialize_tf_offset = rospy.get_param("~initialize_tf_offset", 0.0)
114+
self.pose_topic = rospy.get_param("~pose_topic", "pose")
115+
self.map_frame = rospy.get_param("~map_frame", "map")
116+
self.base_frame = rospy.get_param("~base_frame", "base")
117+
self.corrected_map_frame = rospy.get_param("~corrected_map_frame", "corrected_map")
118+
self.initialize_method = rospy.get_param("~initialize_method", "cubic")
119+
self.position_lowpass_alpha = rospy.get_param("~position_lowpass_alpha", 0.2)
120+
self.orientation_lowpass_alpha = rospy.get_param("~orientation_lowpass_alpha", 0.2)
121+
self.recordable_fps = rospy.get_param("~recordable_fps", 3.0)
122+
self.update_variance_fps = rospy.get_param("~update_variance_fps", 1.0)
123+
self.time_interval = rospy.get_param("~time_interval", 0.1)
124+
self.update_pose_fps = rospy.get_param("~update_pose_fps", 10.0)
125+
self.initialize_tf_grid_size = rospy.get_param("~initialize_tf_grid_size", 0.5)
126+
self.map_acquire_fps = rospy.get_param("~map_acquire_fps", 5.0)
127+
self.publish_statistics_fps = rospy.get_param("~publish_statistics_fps", 1.0)
128+
self.enable_pointcloud_publishing = rospy.get_param("~enable_pointcloud_publishing", False)
129+
self.enable_normal_arrow_publishing = rospy.get_param("~enable_normal_arrow_publishing", False)
130+
self.enable_drift_corrected_TF_publishing = rospy.get_param("~enable_drift_corrected_TF_publishing", False)
131+
self.use_initializer_at_start = rospy.get_param("~use_initializer_at_start", False)
132+
133+
if __name__ == '__main__':
134+
emw = ElevationMapWrapper()
135+
136+
while not rospy.is_shutdown():
137+
try:
138+
rospy.spin()
139+
except rospy.ROSInterruptException:
140+
print("Error")

elevation_mapping_cupy/script/elevation_mapping_cupy/parameter.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@
66
import pickle
77
import numpy as np
88
from simple_parsing.helpers import Serializable
9-
9+
from dataclasses import field
1010

1111
@dataclass
1212
class Parameter(Serializable):
1313
resolution: float = 0.02
14-
additional_layers: list = ['feat_0'].copy
15-
fusion_algorithms: list = ['average'].copy
14+
additional_layers: list = field(default_factory=lambda: ["feat_0"])
15+
fusion_algorithms: list = field(default_factory=lambda: ["average"])
1616
cell_n: int = None
1717

1818
map_length: float = 10.0

0 commit comments

Comments
 (0)