Advertisement
jarod_reynolds

experimental_lab3_q1_pt2

May 1st, 2021
35
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.14 KB | None | 0 0
  1. #!/usr/bin/python3
  2.  
  3. import matplotlib
  4. import matplotlib.pyplot as plt
  5. import rospy
  6. from sensor_msgs.msg import PointCloud2 as pc2
  7. import sensor_msgs.point_cloud2 as pc2
  8. from sensor_msgs.msg import LaserScan
  9. from nav_msgs.msg import Odometry
  10. from geometry_msgs.msg import Pose
  11. from laser_geometry import LaserProjection
  12. import open3d as o3d
  13. import numpy as np
  14. import collections
  15. import copy
  16. import time
  17.  
  18. # class OdomShiz:
  19. # def __init__(self):
  20. # self.OdomSubscriber = rospy.Subscriber("/odom", Odometry, self.odom_callback)
  21. # self.odom_trajectory = {'x': [], 'y': []}
  22. #
  23. # def odom_callback(self,data):
  24. # # x_pos = data.pose.pose.position.x
  25. # # y_pos = data.pose.pose.position.y
  26. # # z_pos = data.pose.pose.position.z
  27. #
  28. # self.odom_trajectory['x'].append(data.pose.pose.position.x)
  29. # self.odom_trajectory['y'].append(data.pose.pose.position.y)
  30. # self.update_odom_plot()
  31. #
  32. # def update_odom_plot(self):
  33. # odom_plot.plot(self.odom_trajectory['x'], self.odom_trajectory['y'])
  34. # plt.draw()
  35. # plt.pause(0.001)
  36. # plt.show()
  37.  
  38.  
  39. class SickDawgPCz:
  40. def __init__(self):
  41. self.laserProj = LaserProjection()
  42. self.laserSubscriber = rospy.Subscriber("/scan", LaserScan, self.laser_callback)
  43. self.queue = collections.deque()
  44. self.current_pos = np.array([0, 0, 0])
  45. self.vis = o3d.visualization.Visualizer()
  46. self.source_geometry = None
  47. self.target_geometry = None
  48. self.trajectory = {'x': [], 'y': []}
  49. self.scan_count = 0
  50. self.trans_init = None
  51. # Odometry stuff
  52. self.OdomSubscriber = rospy.Subscriber("/odom", Odometry, self.odom_callback)
  53. self.odom_trajectory = {'x': [], 'y': []}
  54. self.tf = np.identity(4)
  55.  
  56. def laser_callback(self, data):
  57. pc = self.laser_scan_to_point_cloud(data)
  58. # o3d.visualization.draw_geometries([pc])
  59.  
  60. # Append cloud to the queue
  61. self.queue.append(pc)
  62. self.scan_count += 1
  63.  
  64. def odom_callback(self, data):
  65. self.odom_trajectory['x'].append(data.pose.pose.position.x)
  66. self.odom_trajectory['y'].append(data.pose.pose.position.y)
  67. # self.update_odom_plot()
  68.  
  69. def laser_scan_to_point_cloud(self, scan):
  70. cloud_out = self.laserProj.projectLaser(scan)
  71.  
  72. # Get cloud data from ros_cloud
  73. # Source: https://github.com/felixchenfy/open3d_ros_pointcloud_conversion/blob/master/lib_cloud_conversion_between_Open3D_and_ROS.py
  74. field_names = [field.name for field in cloud_out.fields]
  75. cloud_data = list(pc2.read_points(cloud_out, skip_nans=True, field_names=field_names))
  76.  
  77. open3d_cloud = o3d.PointCloud()
  78. xyz = [(x, y, z) for x, y, z, intensity, index in cloud_data] # get xyz
  79. open3d_cloud.points = o3d.Vector3dVector(np.array(xyz))
  80.  
  81. return open3d_cloud
  82.  
  83. def icp_registration(self):
  84. # Check for 2 clouds in queue
  85. if len(self.queue) < 2:
  86. return
  87.  
  88. # print("QUEUE LENGTH:" + str(len(self.queue)))
  89. source = self.queue.popleft()
  90. target = self.queue.popleft()
  91. threshold = 0.015
  92.  
  93. if self.trans_init is None:
  94. self.trans_init = np.identity(4)
  95.  
  96. reg_p2l = o3d.registration.registration_icp(
  97. source, target, threshold, self.trans_init,
  98. o3d.registration.TransformationEstimationPointToPoint(),
  99. o3d.registration.ICPConvergenceCriteria(max_iteration=200, relative_fitness=0.000006, relative_rmse=0.000006))
  100.  
  101. # Check for shitty results
  102. if reg_p2l.fitness < 0.5 or reg_p2l.inlier_rmse > 0.01:
  103. print("Found a shitty value")
  104. self.queue.appendleft(target)
  105. return
  106.  
  107. # Save this transformation to use in the next ICP
  108. self.trans_init = reg_p2l.transformation[:]
  109. #self.trans_init = np.identity(4)
  110.  
  111. # print(reg_p2l)
  112. # print(reg_p2l.transformation)
  113. self.draw_registration_result(source, target, reg_p2l.transformation)
  114. self.update_position(reg_p2l.transformation)
  115.  
  116. # Add target back to queue
  117. self.queue.appendleft(target)
  118.  
  119. # Update trajectory
  120. # Plotting is a bottleneck - only update the plot every 50 scans
  121. # so the program can keep up with incoming scans
  122. if self.scan_count % 10 == 0:
  123. # pc_stuff.update_trajectory()
  124. self.update_plots()
  125.  
  126. def update_position(self, transform):
  127. # Extract rotation and translation from transformation matrix
  128. rot = transform[0:3, 0:3]
  129. transl = transform[0:3, 3]
  130. # print(rot)
  131. # print(transl)
  132. # print(self.current_pos)
  133.  
  134. # # Apply transformation to bot's current pose
  135. # new_pos = rot.dot(self.current_pos.T) + transl.T
  136. # self.current_pos = new_pos.T[:]
  137. #
  138. # # Add the new position to the trajectory
  139. # self.trajectory['x'].append(new_pos[0])
  140. # self.trajectory['y'].append(new_pos[1])
  141.  
  142. self.tf = self.tf.dot(transform)
  143. self.trajectory['x'].append(self.tf[0, 3])
  144. self.trajectory['y'].append(self.tf[1, 3])
  145.  
  146.  
  147. def update_plots(self):
  148. pc_plot.plot(self.trajectory['x'], self.trajectory['y'])
  149. odom_plot.plot(self.odom_trajectory['x'], self.odom_trajectory['y'])
  150. plt.draw()
  151. plt.pause(0.001)
  152. plt.show()
  153.  
  154. # Helper visualisation function
  155. # Source: http://www.open3d.org/docs/release/tutorial/pipelines/icp_registration.html
  156. def draw_registration_result(self, source, target, transformation):
  157.  
  158. source_temp = copy.deepcopy(source)
  159. target_temp = copy.deepcopy(target)
  160. source_temp.paint_uniform_color([1, 0.706, 0])
  161. target_temp.paint_uniform_color([0, 0.651, 0.929])
  162. source_temp.transform(transformation)
  163. # o3d.visualization.draw_geometries([source_temp, target_temp]) # Blocking
  164.  
  165. # Non-blocking visualisation
  166. self.vis.remove_geometry(self.source_geometry)
  167. self.vis.remove_geometry(self.target_geometry)
  168. self.source_geometry = source_temp
  169. self.target_geometry = target_temp
  170. self.vis.add_geometry(self.source_geometry)
  171. self.vis.add_geometry(self.target_geometry)
  172. self.vis.poll_events()
  173. self.vis.update_renderer()
  174.  
  175.  
  176. # Press the green button in the gutter to run the script.
  177. if __name__ == '__main__':
  178. rospy.init_node("laser2PointCloud", disable_signals=True)
  179. pc_stuff = SickDawgPCz()
  180. # odomOb = OdomShiz()
  181.  
  182. pc_stuff.vis.create_window()
  183.  
  184. # Initialise a plot for the trajectory
  185. matplotlib.use('TKAgg')
  186. fig,(pc_plot, odom_plot) = plt.subplots(1, 2)
  187. plt.ion()
  188. plt.show()
  189. pc_plot.axis([-3, 3, -3, 3])
  190. # odom_plot.axis([2, 6.5, -1.5, 3])
  191. odom_plot.axis([-5, 5, -5, 5])
  192. # plt.set(xlim=(-3, 1.5), ylim=(-3, 1.5))
  193.  
  194. while True:
  195. try:
  196. pc_stuff.icp_registration()
  197.  
  198. except KeyboardInterrupt as e:
  199. print(e)
  200. break
  201. pc_stuff.vis.destroy_window()
  202.  
  203. rospy.spin()
  204.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement