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" )
0 commit comments