Skip to content

Commit ac41b12

Browse files
committed
updated python wrapper
1 parent 7b3fb08 commit ac41b12

File tree

2 files changed

+80
-27
lines changed

2 files changed

+80
-27
lines changed

elevation_mapping_cupy/config/parameters.yaml

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,9 @@ max_unsafe_n: 10 # if the number of cells under s
4040
overlap_clear_range_xy: 4.0 # xy range [m] for clearing overlapped area. this defines the valid area for overlap clearance. (used for multi floor setting)
4141
overlap_clear_range_z: 2.0 # z range [m] for clearing overlapped area. cells outside this range will be cleared. (used for multi floor setting)
4242

43-
map_frame: 'enu' # The map frame where the odometry source uses.
44-
base_frame: 'base_footprint' # The robot's base frame. This frame will be a center of the map.
45-
corrected_map_frame: 'enu'
43+
map_frame: 'odom' # The map frame where the odometry source uses.
44+
base_frame: 'base' # The robot's base frame. This frame will be a center of the map.
45+
corrected_map_frame: 'odom_corrected'
4646

4747
#### Feature toggles ########
4848
enable_edge_sharpen: true
@@ -76,14 +76,14 @@ publishers:
7676
layers: ['elevation', 'traversability', 'variance']
7777
basic_layers: ['elevation', 'traversability']
7878
fps: 5.0
79-
elevation_map_recordable:
80-
layers: ['elevation', 'traversability']
81-
basic_layers: ['elevation', 'traversability']
82-
fps: 2.0
83-
elevation_map_filter:
84-
layers: ['min_filter', 'smooth', 'inpaint', 'upper_bound','rgb']
85-
basic_layers: ['min_filter']
86-
fps: 3.0
79+
# elevation_map_recordable:
80+
# layers: ['elevation', 'traversability']
81+
# basic_layers: ['elevation', 'traversability']
82+
# fps: 2.0
83+
# elevation_map_filter:
84+
# layers: ['min_filter', 'smooth', 'inpaint', 'upper_bound','rgb']
85+
# basic_layers: ['min_filter']
86+
# fps: 3.0
8787

8888
#### Initializer ########
8989
initialize_method: 'linear' # Choose one from 'nearest', 'linear', 'cubic'

elevation_mapping_cupy/script/elevation_mapping_cupy/elevation_mapping_ros.py

Lines changed: 69 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,21 @@
99
import rospy
1010
import ros_numpy
1111
from tf.transformations import quaternion_matrix
12-
from sensor_msgs.msg import PointCloud2
1312
import tf2_ros
1413
import rospkg
1514

15+
from sensor_msgs.msg import PointCloud2
16+
from grid_map_msgs.msg import GridMap
17+
from std_msgs.msg import Float32MultiArray
18+
from std_msgs.msg import MultiArrayLayout as MAL
19+
from std_msgs.msg import MultiArrayDimension as MAD
20+
1621
class ElevationMapWrapper():
1722
def __init__(self):
1823
rospack = rospkg.RosPack()
1924
self.root = rospack.get_path("elevation_mapping_cupy")
2025
self.initalize_elevation_mapping()
21-
26+
self.node_name = "elevation_mapping"
2227
# ROS
2328
self.initalize_ros()
2429
self.register_subscribers()
@@ -29,12 +34,15 @@ def initalize_elevation_mapping(self):
2934
weight_file = os.path.join(self.root, "config/weights.dat")
3035
plugin_config_file = os.path.join(self.root, "config/plugin_config.yaml")
3136
param = Parameter( use_chainer=False, weight_file=weight_file, plugin_config_file=plugin_config_file )
37+
param.update()
3238
self._pointcloud_process_counter = 0
3339
self._map = ElevationMap(param)
3440
self._map_data = np.zeros((self._map.cell_n - 2, self._map.cell_n - 2), dtype=np.float32)
41+
self._map_q = None
42+
self._map_t = None
3543

3644
def initalize_ros(self):
37-
rospy.init_node("elevation_mapping", anonymous=False)
45+
rospy.init_node(self.node_name, anonymous=False)
3846
self._tf_buffer = tf2_ros.Buffer()
3947
self._listener = tf2_ros.TransformListener(self._tf_buffer)
4048
self.get_ros_params()
@@ -47,37 +55,79 @@ def register_subscribers(self):
4755

4856
def register_publishers(self):
4957
# TODO publishers
50-
print(self.publishers)
58+
self._publishers = {}
59+
self._publishers_timers = []
60+
for k, v in self.publishers.items():
61+
print(f"Register Publisher: {k}")
62+
self._publishers[k] = rospy.Publisher(f"/{self.node_name}/{k}", GridMap, queue_size=10)
63+
self._publishers_timers.append( rospy.Timer(rospy.Duration(1/v["fps"]), lambda x: self.publish_map(x, k)))
64+
65+
def publish_map(self, t, k):
66+
print(k)
67+
if self._map_q is None:
68+
return
5169

70+
gm = GridMap()
71+
gm.info.header.frame_id = self.map_frame
72+
gm.info.header.stamp = rospy.Time.now()
73+
gm.info.header.seq = 0
74+
gm.info.resolution = self._map.resolution
75+
gm.info.length_x = self._map.map_length
76+
gm.info.length_y = self._map.map_length
77+
gm.info.pose.position.x = self._map_t.x
78+
gm.info.pose.position.y = self._map_t.y
79+
gm.info.pose.position.z = self._map_t.z
80+
gm.info.pose.orientation.w = 1 # self._map_q.w
81+
gm.info.pose.orientation.x = 0 # self._map_q.x
82+
gm.info.pose.orientation.y = 0 # self._map_q.y
83+
gm.info.pose.orientation.z = 0 # self._map_q.z
84+
gm.layers = self.publishers[k]["layers"]
85+
gm.basic_layers = self.publishers[k]["basic_layers"]
86+
87+
# arr.layout.dim = [int(gm.info.length_x/gm.info.resolution), int(gm.info.length_y/gm.info.resolution)]
88+
89+
for i, layer in enumerate(gm.layers):
90+
self._map.get_map_with_name_ref(layer, self._map_data)
91+
self._map_data = np.nan_to_num(self._map_data, False, 0)
92+
data = self._map_data.copy()
93+
arr = Float32MultiArray()
94+
arr.layout = MAL()
95+
N = self._map_data.shape[0]
96+
arr.layout.dim.append( MAD(label="column_index",size=N,stride=int(N*N)))
97+
arr.layout.dim.append( MAD(label="row_index",size=N,stride=N))
98+
arr.data = tuple(np.ascontiguousarray(data).reshape(-1))
99+
gm.data.append( arr )
100+
101+
self._publishers[k].publish( gm )
102+
52103
def register_timers(self):
53104
self.timer_variance = rospy.Timer(rospy.Duration(1/self.update_variance_fps), self.update_variance)
54105
self.timer_pose = rospy.Timer(rospy.Duration(1/self.update_pose_fps), self.update_pose)
55106
self.timer_time = rospy.Timer(rospy.Duration(self.time_interval), self.update_time)
56107

57-
def pointcloud_callback(self, data, config):
108+
def pointcloud_callback(self, msg, config):
58109
# 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)
110+
channels = config[0]
111+
fusion = config[1]
112+
points = ros_numpy.point_cloud2.pointcloud2_to_xyz_array(msg)
63113

64114
# get pose of pointcloud
65-
t = rospy.Time(secs=data.header.stamp.secs, nsecs=data.header.stamp.nsecs)
115+
t = rospy.Time(secs=msg.header.stamp.secs, nsecs=msg.header.stamp.nsecs)
66116
try:
67-
transform = self._tf_buffer.lookup_transform(self.map_frame, data.header.frame_id, t, rospy.Duration(1.0))
117+
transform = self._tf_buffer.lookup_transform(self.map_frame, msg.header.frame_id, t, rospy.Duration(1.0))
68118
except (tf2_ros.LookupException, tf2_ros.ConnectivityException, tf2_ros.ExtrapolationException) as e:
69119
print(e)
70120
return
71121

72122
t = transform.transform.translation
73123
t = np.array( [t.x, t.y, t.z] )
74124
q = transform.transform.rotation
75-
R = quaternion_matrix([q.w, q.x, q.y, q.z])
125+
R = quaternion_matrix([q.w, q.x, q.y, q.z])[:3,:3]
76126

77127
# process pointcloud
78-
self._map.input(points, 0, R, t, 0, 0)
79-
self._map.update_normal(self._map.elevation_map[0])
128+
self._map.input(points, ['x','y','z']+channels, R, t, 0, 0)
80129
self._pointcloud_process_counter += 1
130+
print(self._pointcloud_process_counter)
81131

82132
def update_pose(self, t):
83133
# get pose of base
@@ -90,9 +140,12 @@ def update_pose(self, t):
90140
t = transform.transform.translation
91141
trans = np.array( [t.x, t.y, t.z] )
92142
q = transform.transform.rotation
93-
rot = quaternion_matrix([q.w, q.x, q.y, q.z])
143+
rot = quaternion_matrix([q.w, q.x, q.y, q.z])[:3,:3]
94144
self._map.move_to(trans, rot)
95145

146+
self._map_t = t
147+
self._map_q = q
148+
96149
def update_variance(self, t):
97150
self._map.update_variance()
98151

@@ -104,9 +157,9 @@ def get_ros_params(self):
104157
# This is currently {p} elevation_mapping")
105158
para = os.path.join(self.root, "config/parameters.yaml")
106159
sens = os.path.join(self.root, "config/sensor_parameter.yaml")
160+
os.system(f"rosparam delete /{self.node_name}")
107161
os.system(f"rosparam load {para} elevation_mapping")
108162
os.system(f"rosparam load {sens} elevation_mapping")
109-
110163
self.subscribers = rospy.get_param("~subscribers")
111164
self.publishers = rospy.get_param("~publishers")
112165
self.initialize_frame_id = rospy.get_param("~initialize_frame_id", "base")

0 commit comments

Comments
 (0)