|
@@ -78,71 +78,85 @@ def check_x_axis_direction(rotation_matrix):
|
|
|
def load_point_cloud_from_txt(file_path):
|
|
|
"""导入点云数据"""
|
|
|
points = []
|
|
|
- with open(file_path, 'r') as file:
|
|
|
- for line in file:
|
|
|
- # 假设每一行是“x y z”格式,没有多余空格
|
|
|
- coordinates = line.strip().split()
|
|
|
- if len(coordinates) == 3: # 检查是否为有效的三维点
|
|
|
- point = [float(coord) for coord in coordinates]
|
|
|
- points.append(point)
|
|
|
-
|
|
|
- return np.array(points)
|
|
|
+ try:
|
|
|
+ with open(file_path, 'r') as file:
|
|
|
+ for line in file:
|
|
|
+ # 假设每一行是“x y z”格式,没有多余空格
|
|
|
+ coordinates = line.strip().split()
|
|
|
+ if len(coordinates) == 3: # 检查是否为有效的三维点
|
|
|
+ point = [float(coord) for coord in coordinates]
|
|
|
+ points.append(point)
|
|
|
+
|
|
|
+ return np.array(points)
|
|
|
+ except FileNotFoundError:
|
|
|
+ print(f"Error: The file '{file_path}' was not found.")
|
|
|
+
|
|
|
def load_point_cloud_from_binary_txt(file_path):
|
|
|
- with open(file_path, 'rb') as f:
|
|
|
- binary_data = f.read()
|
|
|
+ try:
|
|
|
+ with open(file_path, 'rb') as f:
|
|
|
+ binary_data = f.read()
|
|
|
+
|
|
|
+ # 将二进制数据转换为 NumPy 数组,(固定3列x,y,z,行数自动计算)
|
|
|
+ point_cloud = np.frombuffer(binary_data, dtype=np.float64).reshape(-1, 3)
|
|
|
+ return point_cloud
|
|
|
+ except FileNotFoundError:
|
|
|
+ print(f"Error: The file '{file_path}' was not found.")
|
|
|
|
|
|
- # 将二进制数据转换为 NumPy 数组
|
|
|
- point_cloud = np.frombuffer(binary_data, dtype=np.float64).reshape(-1, 3)
|
|
|
- return point_cloud
|
|
|
|
|
|
def get_hanfeng(file_path):
|
|
|
"""从文件中读取焊缝起点、终点和中间点,并计算两点构成的向量"""
|
|
|
- with open(file_path, 'r') as file:
|
|
|
- # 逐行读取文件内容
|
|
|
- lines = file.readlines()
|
|
|
- start_points, end_points, midpoints , hanfeng = [],[],[],[]
|
|
|
- for line in lines:
|
|
|
- # 去除行尾的换行符并按'/'分割每一行
|
|
|
- points_str = line.strip().split('/')
|
|
|
-
|
|
|
- # 确保每一行都正确地分为两部分
|
|
|
- if len(points_str) == 2:
|
|
|
- point1_str = points_str[0].split(',')
|
|
|
- point2_str = points_str[1].split(',')
|
|
|
+ try:
|
|
|
+ with open(file_path, 'r') as file:
|
|
|
+ # 逐行读取文件内容
|
|
|
+ lines = file.readlines()
|
|
|
+ start_points, end_points, midpoints , hanfeng = [],[],[],[]
|
|
|
+ for line in lines:
|
|
|
+ # 去除行尾的换行符并按'/'分割每一行
|
|
|
+ points_str = line.strip().split('/')
|
|
|
|
|
|
- # 转换字符串为浮点数列表,构造三维点
|
|
|
- point1 = [float(coord) for coord in point1_str]
|
|
|
- point2 = [float(coord) for coord in point2_str]
|
|
|
-
|
|
|
- midpoint = [(p2 + p1)/2 for p1, p2 in zip(point1, point2)]
|
|
|
- vector = [p2 - p1 for p1, p2 in zip(point1, point2)]
|
|
|
-
|
|
|
- start_points.append(point1)
|
|
|
- end_points.append(point2)
|
|
|
- midpoints.append(midpoint)
|
|
|
- hanfeng.append(vector)
|
|
|
-
|
|
|
- return start_points, end_points, midpoints, hanfeng
|
|
|
+ # 确保每一行都正确地分为两部分
|
|
|
+ if len(points_str) == 2:
|
|
|
+ point1_str = points_str[0].split(',')
|
|
|
+ point2_str = points_str[1].split(',')
|
|
|
+
|
|
|
+ # 转换字符串为浮点数列表,构造三维点
|
|
|
+ point1 = [float(coord) for coord in point1_str]
|
|
|
+ point2 = [float(coord) for coord in point2_str]
|
|
|
+
|
|
|
+ midpoint = [(p2 + p1)/2 for p1, p2 in zip(point1, point2)] #焊缝的中间点
|
|
|
+ vector = [p2 - p1 for p1, p2 in zip(point1, point2)] #焊缝的方向向量
|
|
|
+
|
|
|
+ start_points.append(point1)
|
|
|
+ end_points.append(point2)
|
|
|
+ midpoints.append(midpoint)
|
|
|
+ hanfeng.append(vector)
|
|
|
+
|
|
|
+ return start_points, end_points, midpoints, hanfeng
|
|
|
+ except FileNotFoundError:
|
|
|
+ print(f"Error: The file '{file_path}' was not found.")
|
|
|
|
|
|
def compute_Rc2w_tc2w(file_path_Tw2c):
|
|
|
"""相机和基底坐标系的转换关系"""
|
|
|
+ try:
|
|
|
# 读取文件
|
|
|
- with open(file_path_Tw2c, 'r') as file:
|
|
|
- lines = file.readlines()
|
|
|
-
|
|
|
- lines = [line.strip().replace('[', '').replace(']', '').split() for line in lines]
|
|
|
- data = [[float(num) for num in line] for line in lines]
|
|
|
- data = np.array(data)
|
|
|
- # 提取Rw2c和tw2c
|
|
|
- Rw2c = data[:3,:3]
|
|
|
- tw2c = data[:3,-1]
|
|
|
-
|
|
|
- Rc2w = Rw2c.T
|
|
|
- tc2w = -np.matmul(Rc2w, tw2c)
|
|
|
- return Rc2w,tc2w
|
|
|
+ with open(file_path_Tw2c, 'r') as file:
|
|
|
+ lines = file.readlines()
|
|
|
+
|
|
|
+ lines = [line.strip().replace('[', '').replace(']', '').split() for line in lines]
|
|
|
+ data = [[float(num) for num in line] for line in lines] #将每行的字符串转换为浮点数
|
|
|
+ data = np.array(data)
|
|
|
+ # 提取Rw2c和tw2c
|
|
|
+ Rw2c = data[:3,:3] #前3行的前3列
|
|
|
+ tw2c = data[:3,-1] #前3行的最后一列
|
|
|
+
|
|
|
+ Rc2w = Rw2c.T # 旋转矩阵的转置
|
|
|
+ tc2w = -np.matmul(Rc2w, tw2c) #Rc2w乘tw2c,负号表示平移方向是从相机指向基底
|
|
|
+ return Rc2w,tc2w
|
|
|
+ except FileNotFoundError:
|
|
|
+ print(f"Error: The file '{file_path_Tw2c}' was not found.")
|
|
|
|
|
|
def compute_pose_R(fangxiang, hanfeng,start_point, end_point):
|
|
|
- """根据计算出的焊接时z轴负方向的向量和由起(fangxiang)点指向终点的向量(hanfeng)计算旋转矩阵"""
|
|
|
+ """根据计算出的焊接时z轴负方向的向量和由起点(fangxiang)指向终点的向量(hanfeng)计算旋转矩阵"""
|
|
|
x, y, z = fangxiang
|
|
|
|
|
|
# 计算旋转角度
|
|
@@ -176,7 +190,7 @@ def compute_pose_R(fangxiang, hanfeng,start_point, end_point):
|
|
|
|
|
|
return R_mat, ispingfeng
|
|
|
|
|
|
-def get_quaternion(data, midpoint, hanfeng, start_point, end_point,result_ping,result_shu,result_wai,file_path_Tw2c):
|
|
|
+def get_quaternion(data, midpoint, hanfeng, start_point, end_point, result_ping, result_shu, result_wai, file_path_Tw2c):
|
|
|
|
|
|
# 构建KDTree索引
|
|
|
tree = KDTree(data)
|
|
@@ -203,7 +217,7 @@ def get_quaternion(data, midpoint, hanfeng, start_point, end_point,result_ping,r
|
|
|
v = P - midpoint
|
|
|
anglecos = np.dot(v, hanfeng) / (np.linalg.norm(v) * np.linalg.norm(hanfeng))
|
|
|
|
|
|
- if abs(anglecos) <= 0.015:
|
|
|
+ if abs(anglecos) <= 0.015: #余弦值接近0,即角度接近90度
|
|
|
# print(anglecos)
|
|
|
data_shu.append(P)
|
|
|
data_shu = np.array(data_shu)
|
|
@@ -215,7 +229,7 @@ def get_quaternion(data, midpoint, hanfeng, start_point, end_point,result_ping,r
|
|
|
##################################################
|
|
|
##################################################
|
|
|
random_point = data_shu[np.random.randint(0, len(data_shu))]
|
|
|
- # 与midpoint一起定义直线向量
|
|
|
+ # data_shu中随机一点与midpoint一起定义直线向量
|
|
|
nohanfeng = random_point - midpoint #data_shu中任意一点midpoint构成的向量,计算所有点和该向量的距离判断是否是外缝(只拍到一面)
|
|
|
|
|
|
distances_to_line = []
|
|
@@ -225,31 +239,31 @@ def get_quaternion(data, midpoint, hanfeng, start_point, end_point,result_ping,r
|
|
|
A = midpoint
|
|
|
u = nohanfeng
|
|
|
v = P - A
|
|
|
- distance = np.linalg.norm(np.cross(u, v)) / np.linalg.norm(u)
|
|
|
+ distance = np.linalg.norm(np.cross(u, v)) / np.linalg.norm(u) #计算点P到nohanfeng距离
|
|
|
distances_to_line.append(distance)
|
|
|
|
|
|
distances_to_line = np.array(distances_to_line)
|
|
|
|
|
|
- all_distances_less_than_10 = np.all(distances_to_line < 5)#都小于10为true,也就是data_shu只有一列,侧着拍得外缝
|
|
|
+ all_distances_less_than_10 = np.all(distances_to_line < 5)#都小于5为true,也就是data_shu只有一列,侧着拍得外缝
|
|
|
|
|
|
if all_distances_less_than_10:
|
|
|
|
|
|
# 随机选取data_shu中的第一个点
|
|
|
random_index = np.random.randint(0, data_shu.shape[0])
|
|
|
vector1 = data_shu[random_index] - midpoint
|
|
|
- vector1 /= np.linalg.norm(vector1) # 单位化vector1
|
|
|
- fa_xian = np.cross(vector1, hanfeng)
|
|
|
- fa_xian /= np.linalg.norm(fa_xian)
|
|
|
+ vector1 /= np.linalg.norm(vector1) # 单位化vector1,向量除以其模长
|
|
|
+ fa_xian = np.cross(vector1, hanfeng) # 计算叉积,得到法向量
|
|
|
+ fa_xian /= np.linalg.norm(fa_xian) # 单位化法向量
|
|
|
|
|
|
point = []
|
|
|
- point1 = midpoint + 50 * fa_xian
|
|
|
+ point1 = midpoint + 50 * fa_xian #沿法线方向偏移50个单位
|
|
|
point2 = midpoint - 50 * fa_xian
|
|
|
|
|
|
Rc2w,tc2w = compute_Rc2w_tc2w(file_path_Tw2c)
|
|
|
|
|
|
point1_c = np.matmul(Rc2w, point1) + tc2w
|
|
|
point2_c = np.matmul(Rc2w, point2) + tc2w
|
|
|
- a = np.linalg.norm(point1_c)
|
|
|
+ a = np.linalg.norm(point1_c) #到原点的距离
|
|
|
b = np.linalg.norm(point2_c)
|
|
|
|
|
|
if a < b:
|
|
@@ -430,7 +444,7 @@ def run():
|
|
|
file_path_result = os.path.join(file_path, 'result.txt')
|
|
|
file_path_Tw2c = os.path.join(file_path, 'Tw2c.txt')
|
|
|
|
|
|
- # 获取数据
|
|
|
+ # 获取数据(点云和焊缝信息)
|
|
|
data = load_point_cloud_from_binary_txt(file_path_pointcloud)
|
|
|
start_points, end_points, midpoints, hanfeng = get_hanfeng(file_path_points)
|
|
|
|
|
@@ -449,6 +463,7 @@ def run():
|
|
|
file.write(line)
|
|
|
|
|
|
rospy.loginfo("Welding Angle calculation completed")
|
|
|
+
|
|
|
if __name__ == '__main__':
|
|
|
|
|
|
run()
|