hjsx.py 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. import numpy as np
  2. import os
  3. import rospy
  4. from math import acos, degrees
  5. def calculate_distance(point1, point2):
  6. return np.linalg.norm(np.array(point1) - np.array(point2))
  7. def calculate_angle_with_xy_plane(point1,point2):
  8. # 计算方向向量
  9. dir_vector = np.array([point2[0] - point1[0], point2[1] - point1[1], point2[2] - point1[2]])
  10. # 计算方向向量在 xy 平面上的投影
  11. proj_vector = np.array([point2[0] - point1[0], point2[1] - point1[1], 0])
  12. # 计算夹角
  13. angle = acos(np.dot(dir_vector, proj_vector) / (np.linalg.norm(dir_vector) * np.linalg.norm(proj_vector)))
  14. angle_deg = degrees(angle)
  15. return angle_deg
  16. def read_points_from_file(file_path):
  17. """从文件中读取焊缝数据"""
  18. with open(file_path, 'r') as file:
  19. lines = file.readlines()
  20. data = [line.strip().split('/') for line in lines]
  21. points_list = [[tuple(map(float, pair.split(','))) for pair in line] for line in data]
  22. return points_list
  23. ########
  24. # 从文件中读取焊缝起点和终点,并计算两点构成的向量
  25. def get_hanfeng(file_path):
  26. data_ping, data_shu = [],[]
  27. with open(file_path, 'r') as file:
  28. # 逐行读取文件内容
  29. lines = file.readlines()
  30. flag_sequence = 0
  31. for line in lines:
  32. flag_sequence += 1
  33. # 去除行尾的换行符并按'/'分割每一行
  34. points_str = line.strip().split('/')
  35. point1_str = points_str[0].split(',')
  36. point2_str = points_str[1].split(',')
  37. # 转换字符串为浮点数列表,构造三维点
  38. point1 = [float(coord) for coord in point1_str]
  39. point2 = [float(coord) for coord in point2_str]
  40. angle = calculate_angle_with_xy_plane(point1,point2)
  41. if abs(angle) < 30: #与xy平面夹角小于30度
  42. data_ping.append([point1, point2, flag_sequence])
  43. else:
  44. data_shu.append([*sorted([point1, point2], key=lambda p: p[2]), flag_sequence])
  45. data = data_ping + data_shu
  46. # midpoint = [(p2 + p1)/2 for p1, p2 in zip(point1, point2)]
  47. # vector = [p2 - p1 for p1, p2 in zip(point1, point2)]
  48. # start_points.append(point1)
  49. # end_points.append(point2)
  50. # midpoints.append(midpoint)
  51. # hanfeng.append(vector)
  52. # return start_points, end_points, midpoints, hanfeng
  53. return data_ping, data_shu, data
  54. ################################################################################################################
  55. ################################################################################################################
  56. def sort_welds_by_distance_ping(data_ping, reference_point):
  57. """根据与参考点的距离对焊缝进行排序"""
  58. sorted_data_ping = []
  59. for i in range(len(data_ping)):
  60. # 计算起点到参考点的距离并排序
  61. data_with_distances = [[calculate_distance(start, reference_point),calculate_distance(end, reference_point), start, end,flag_sequence] for start, end,flag_sequence in data_ping]
  62. for i in range(len(data_with_distances)):
  63. if data_with_distances[i][0] > data_with_distances[i][1]:
  64. data_with_distances[i][0] = data_with_distances[i][1]
  65. tem = data_with_distances[i][2]
  66. data_with_distances[i][2] = data_with_distances[i][3]
  67. data_with_distances[i][3] = tem
  68. data_with_distances.sort(key=lambda x: x[0])
  69. # 初始化结果和当前终点
  70. sorted_data_ping.append(data_with_distances.pop(0)[-3:])
  71. reference_point = sorted_data_ping[-1][1]
  72. data_ping = [[start, end,flag_sequence] for distances1,distances2, start,end,flag_sequence in data_with_distances]
  73. #将起始点位置交换回来,保证平缝焊接方向一致
  74. for i in range(len(sorted_data_ping)):
  75. sorted_data_ping[i][0], sorted_data_ping[i][1] = sorted_data_ping[i][1], sorted_data_ping[i][0]
  76. return sorted_data_ping
  77. def sort_welds_by_distance_shu(data_shu, reference_point):
  78. """根据与参考点的距离对焊缝进行排序"""
  79. sorted_data_shu = []
  80. for i in range(len(data_shu)):
  81. # 计算起点到参考点的距离并排序
  82. data_with_distances = [[calculate_distance(start, reference_point), start, end ,flag_sequence] for start, end ,flag_sequence in data_shu]
  83. data_with_distances.sort(key=lambda x: x[0])
  84. # 初始化结果和当前终点
  85. sorted_data_shu.append(data_with_distances.pop(0)[-3:])
  86. reference_point = sorted_data_shu[-1][1]
  87. data_shu = [[start, end ,flag_sequence] for distances, start,end ,flag_sequence in data_with_distances]
  88. return sorted_data_shu
  89. def run():
  90. # 定义参考点,排序
  91. reference_point = (1172.85077147, -1.50259925, 668.30298144)
  92. # file_path = '/home/chen/catkin_ws/src/publish_pointcloud/data/pointclouddata/20240520r'
  93. file_path = rospy.get_param("folder_path")
  94. file_path_pointcloud = os.path.join(file_path, 'pointcloud.txt')
  95. file_path_points = os.path.join(file_path, 'points.txt')
  96. file_path_result = os.path.join(file_path, 'result.txt')
  97. file_path_points_guihua = os.path.join(file_path, 'points_guihua.txt')
  98. data_ping, data_shu, data = get_hanfeng(file_path_points)
  99. # 对焊缝排序
  100. sorted_data_ping = sort_welds_by_distance_ping(data_ping, reference_point)
  101. if len(data_ping) > 0:
  102. a = tuple(sorted_data_ping[-1][1])
  103. else:
  104. a = reference_point
  105. sorted_welds_shu = sort_welds_by_distance_shu(data_shu, a)
  106. sorted_welds = sorted_data_ping + sorted_welds_shu
  107. flag_sequence = [flag_sequence for start,end ,flag_sequence in sorted_welds]
  108. #传递焊接顺序
  109. rospy.set_param('welding_sequence',flag_sequence)
  110. sorted_welds_withnoflag = [[start,end]for start,end ,flag_sequence in sorted_welds]
  111. with open(file_path_points_guihua, "w") as file:
  112. for start, end in sorted_welds_withnoflag:
  113. # 将每一对起点和终点转换为字符串,并用逗号连接,最后以换行符分隔不同的焊缝对
  114. line = "{},{},{}".format(start[0], start[1], start[2]) + "/" + "{},{},{}".format(end[0], end[1], end[2]) + "\n"
  115. file.write(line)
  116. rospy.loginfo("Welding sequence calculation completed")
  117. if __name__ == '__main__':
  118. run()