opt 280AR visual tracking case

This commit is contained in:
wangWking 2025-07-08 13:37:31 +08:00
parent f80d7bd698
commit ba7b7b749f
3 changed files with 131 additions and 67 deletions

View file

@ -36,8 +36,10 @@ class camera_detect:
self.camera = UVCCamera(self.camera_id, self.mtx, self.dist) self.camera = UVCCamera(self.camera_id, self.mtx, self.dist)
self.camera_open() self.camera_open()
self.origin_mycbot_horizontal = [0,60,-60,0,0,-40] self.origin_mycbot_horizontal = [-90, -35.85, -52.91, 88.59, 0, 0.0]
self.origin_mycbot_level = [0, 5, -104, 14, 0, -40] self.origin_mycbot_level = [-90, 5, -104, 14, 0, 0]
self.IDENTIFY_LEN = 300
# Initialize EyesInHand_matrix to None or load from a document if available # Initialize EyesInHand_matrix to None or load from a document if available
self.EyesInHand_matrix = None self.EyesInHand_matrix = None
@ -117,33 +119,36 @@ class camera_detect:
return target_coords return target_coords
def eyes_in_hand_calculate(self, pose, tbe1, Mc1, tbe2, Mc2, tbe3, Mc3, Mr): def eyes_in_hand_calculate(self, pose, tbe, Mc, Mr):
tbe1, Mc1, tbe2, Mc2, tbe3, Mc3, Mr = map(np.array, [tbe1, Mc1, tbe2, Mc2, tbe3, Mc3, Mr]) pose,Mr = map(np.array, [pose,Mr])
# Convert pose from degrees to radians # 将角度从度数转换为弧度
euler = np.array(pose) * np.pi / 180 euler = pose * np.pi / 180
Rbe = self.CvtEulerAngleToRotationMatrix(euler) Rbe = self.CvtEulerAngleToRotationMatrix(euler)
print("Rbe", Rbe)
Reb = Rbe.T Reb = Rbe.T
A = np.hstack([(Mc2 - Mc1).reshape(-1, 1), A = np.empty((3, 0))
(Mc3 - Mc1).reshape(-1, 1), b_comb = np.empty((3, 0))
(Mc3 - Mc2).reshape(-1, 1)])
b = Reb @ np.hstack([(tbe1 - tbe2).reshape(-1, 1), r = tbe.shape[0]
(tbe1 - tbe3).reshape(-1, 1),
(tbe2 - tbe3).reshape(-1, 1)])
print("A = ", A) for i in range(1, r):
print("B = ", b) A = np.hstack((A, (Mc[i, :].reshape(3, 1) - Mc[0, :].reshape(3, 1))))
U, S, Vt = svd(A @ b.T) b_comb = np.hstack((b_comb, (tbe[0, :].reshape(3, 1) - tbe[i, :].reshape(3, 1))))
b = Reb @ b_comb
U, _, Vt = svd(A @ b.T)
Rce = Vt.T @ U.T Rce = Vt.T @ U.T
tce = Reb @ (Mr - (1/3)*(tbe1 + tbe2 + tbe3) - (1/3)*(Rbe @ Rce @ (Mc1 + Mc2 + Mc3))) tbe_sum = np.sum(tbe, axis=0)
Mc_sum = np.sum(Mc, axis=0)
eyes_in_hand_matrix = np.vstack([np.hstack([Rce, tce.reshape(-1, 1)]), np.array([0, 0, 0, 1])]) tce = Reb @ (Mr.reshape(3, 1) - (1/r) * tbe_sum.reshape(3, 1) - (1/r) * (Rbe @ Rce @ Mc_sum.reshape(3, 1)))
tce[2] -= self.IDENTIFY_LEN #用于保持识别距离
return eyes_in_hand_matrix EyesInHand_matrix = np.vstack((np.hstack((Rce, tce)), np.array([0, 0, 0, 1])))
print("EyesInHand_matrix = ", EyesInHand_matrix)
return EyesInHand_matrix
# 读取Camera坐标单次 # 读取Camera坐标单次
def stag_identify(self): def stag_identify(self):
@ -156,13 +161,13 @@ class camera_detect:
stag.drawDetectedMarkers(frame, rejected_corners, border_color=(255, 0, 0)) stag.drawDetectedMarkers(frame, rejected_corners, border_color=(255, 0, 0))
marker_pos_pack = self.calc_markers_base_position(corners, ids) # 获取物的坐标(相机系) marker_pos_pack = self.calc_markers_base_position(corners, ids) # 获取物的坐标(相机系)
if(len(marker_pos_pack) == 0): if(len(marker_pos_pack) == 0):
marker_pos_pack = self.stag_identify() marker_pos_pack, ids = self.stag_identify()
# print("Camera coords = ", marker_pos_pack) # print("Camera coords = ", marker_pos_pack)
# cv2.imshow("rrrr", frame) # cv2.imshow("rrrr", frame)
# cv2.waitKey(1) # cv2.waitKey(1)
return marker_pos_pack return marker_pos_pack, ids
def Eyes_in_hand_calibration(self, ml): def Matrix_identify(self, ml):
ml.send_angles(self.origin_mycbot_level, 50) # 移动到观测点 ml.send_angles(self.origin_mycbot_level, 50) # 移动到观测点
self.wait() self.wait()
input("make sure camera can observe the stag, enter any key quit") input("make sure camera can observe the stag, enter any key quit")
@ -170,15 +175,40 @@ class camera_detect:
pose = coords[3:6] pose = coords[3:6]
print(pose) print(pose)
# self.camera_open_loop() # self.camera_open_loop()
Mc1,tbe1 = self.reg_get(ml) Mc1,tbe1,pos1 = self.reg_get(ml)
ml.send_coord(1, coords[0] + 30, 30) ml.send_coord(1, coords[0] + 50, 30)
self.wait()
Mc2,tbe2 = self.reg_get(ml)
ml.send_coord(1, coords[0] - 10, 30)
self.wait() self.wait()
Mc2,tbe2,pos2 = self.reg_get(ml)
ml.send_coord(3, coords[2] + 20, 30) ml.send_coord(3, coords[2] + 20, 30)
self.wait() self.wait()
Mc3,tbe3 = self.reg_get(ml) Mc3,tbe3,pos3 = self.reg_get(ml)
ml.send_coord(2, coords[1] + 20, 30)
self.wait()
Mc4,tbe4,pos4 = self.reg_get(ml)
ml.send_coord(1, coords[0] + 20, 30)
self.wait()
Mc5,tbe5,pos5 = self.reg_get(ml)
tbe = np.vstack([tbe1, tbe2, tbe3, tbe4, tbe5])
Mc = np.vstack([Mc1, Mc2, Mc3, Mc4, Mc5])
state = None
if self.EyesInHand_matrix is not None:
state = True
pos = np.vstack([pos1, pos2, pos3, pos4, pos5])
r = pos.shape[0]
for i in range(1, r):
for j in range(3):
err = abs(pos[i][j] - pos[0][j])
if(err > 10):
state = False
# print("matrix error")
return pose, tbe, Mc, state
def Eyes_in_hand_calibration(self, ml):
ml.set_end_type(0)
pose, tbe, Mc, state = self.Matrix_identify(ml)
if(state == True):
print("Calibration Complete EyesInHand_matrix = ", self.EyesInHand_matrix)
return
input("Move the end of the robot arm to the calibration point, press any key to release servo") input("Move the end of the robot arm to the calibration point, press any key to release servo")
ml.release_all_servos() ml.release_all_servos()
@ -191,23 +221,54 @@ class camera_detect:
Mr = coords[0:3] Mr = coords[0:3]
print(Mr) print(Mr)
self.EyesInHand_matrix = self.eyes_in_hand_calculate(pose, tbe1, Mc1, tbe2, Mc2, tbe3, Mc3, Mr) self.EyesInHand_matrix = self.eyes_in_hand_calculate(pose, tbe, Mc, Mr)
print("EyesInHand_matrix = ", self.EyesInHand_matrix) print("EyesInHand_matrix = ", self.EyesInHand_matrix)
self.save_matrix() # Save the matrix to a file after calculating it self.save_matrix() # Save the matrix to a file after calculating it
print("save successe") print("save successe, wait to verify")
pose, tbe, Mc, state = self.Matrix_identify(ml)
if state != True:
self.EyesInHand_matrix = self.eyes_in_hand_calculate(pose, tbe, Mc, Mr)
def Eyes_in_hand(self, coord, camera, Matrix_TC):
Position_Camera = np.transpose(camera[:3]) # 相机坐标
Matrix_BT = self.Transformation_matrix(coord) # 机械臂坐标矩阵
Position_Camera = np.append(Position_Camera, 1) # 物体坐标(相机系)
Position_B = Matrix_BT @ Matrix_TC @ Position_Camera # 物体坐标(基坐标系)
return Position_B
def stag_robot_identify(self, ml):
marker_pos_pack,ids = self.stag_identify()
target_coords = ml.get_coords() # 获取机械臂当前坐标
while (target_coords is None):
target_coords = ml.get_coords()
# print("current_coords", target_coords)
cur_coords = np.array(target_coords.copy())
cur_coords[-3:] *= (np.pi / 180) # 将角度值转为弧度值
fact_bcl = self.Eyes_in_hand(cur_coords, marker_pos_pack, self.EyesInHand_matrix) # 通过矩阵变化将物体坐标(相机系)转成(基坐标系)
for i in range(3):
target_coords[i] = fact_bcl[i]
return target_coords,ids
def reg_get(self, ml): def reg_get(self, ml):
for i in range(50): target_coords = None
Mc_all = self.stag_identify() for i in range(30):
Mc_all,_ = self.stag_identify()
if self.EyesInHand_matrix is not None:
target_coords,_ = self.stag_robot_identify(ml)
tbe_all = ml.get_coords() # 获取机械臂当前坐标 tbe_all = ml.get_coords() # 获取机械臂当前坐标
while (tbe_all is None): while (tbe_all is None):
tbe_all = ml.get_coords() tbe_all = ml.get_coords()
tbe = tbe_all[0:3] tbe = np.array(tbe_all[0:3])
Mc = Mc_all[0:3] Mc = np.array(Mc_all[0:3])
print("tbe = ", tbe) print("tbe = ", tbe)
print("Mc = ", Mc) print("Mc = ", Mc)
return Mc,tbe return Mc,tbe,target_coords
if __name__ == "__main__": if __name__ == "__main__":
@ -216,9 +277,9 @@ if __name__ == "__main__":
camera_params = np.load("camera_params.npz") # 相机配置文件 camera_params = np.load("camera_params.npz") # 相机配置文件
mtx, dist = camera_params["mtx"], camera_params["dist"] mtx, dist = camera_params["mtx"], camera_params["dist"]
m = camera_detect(0, 32, mtx, dist) m = camera_detect(0, 32, mtx, dist)
tool_len = 20 # tool_len = 20
mc.set_tool_reference([0, 0, tool_len, 0, 0, 0]) # mc.set_tool_reference([0, 0, tool_len, 0, 0, 0])
mc.set_end_type(1) # mc.set_end_type(0)
m.Eyes_in_hand_calibration(mc) #手眼标定 m.Eyes_in_hand_calibration(mc) #手眼标定

View file

@ -20,7 +20,8 @@ class UVCCamera:
self.capture_size = capture_size self.capture_size = capture_size
def capture(self): def capture(self):
self.cap = cv2.VideoCapture(self.cam_index) #windows # self.cap = cv2.VideoCapture(self.cam_index, cv2.CAP_DSHOW) #windows
self.cap = cv2.VideoCapture(self.cam_index) #linux
width, height = self.capture_size width, height = self.capture_size
self.cap.set(cv2.CAP_PROP_FRAME_WIDTH, width) self.cap.set(cv2.CAP_PROP_FRAME_WIDTH, width)
self.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, height) self.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, height)

View file

@ -23,7 +23,7 @@ class STAGRecognizer:
self.tool_len = 20 self.tool_len = 20
self.marker_size = 32 self.marker_size = 32
self.origin_mycbot_horizontal = [0,60,-60,0,0,-40] self.origin_mycbot_horizontal = [-90, -35.85, -52.91, 88.59, 0, 0.0]
self.EyesInHand_matrix = None self.EyesInHand_matrix = None
# 订阅摄像头话题 # 订阅摄像头话题
@ -60,8 +60,7 @@ class STAGRecognizer:
self.current_coords = None self.current_coords = None
self.current_angles = None self.current_angles = None
self.lock = threading.Lock() self.lock = threading.Lock()
self.set_tool_reference([0, 0, self.tool_len, 0, 0, 0]) self.set_end_type(0)
self.set_end_type(1)
# init a node and a publisher # init a node and a publisher
# rospy.init_node("marker", anonymous=True) # rospy.init_node("marker", anonymous=True)
@ -347,18 +346,18 @@ class STAGRecognizer:
# 获取当前帧 # 获取当前帧
frame = self.current_frame frame = self.current_frame
# 获取画面中二维码的角度和id # 获取画面中二维码的角度和id
corners, ids, rejected_corners = stag.detectMarkers(frame, 11) (corners, ids, rejected_corners) = stag.detectMarkers(frame, 11)
# 获取物的坐标(相机系) # 获取物的坐标(相机系)
marker_pos_pack = self.calc_markers_base_position(corners, ids) marker_pos_pack = self.calc_markers_base_position(corners, ids)
if len(marker_pos_pack) == 0 and not rospy.is_shutdown(): if len(marker_pos_pack) == 0 and not rospy.is_shutdown():
# rospy.logwarn("No markers detected") # rospy.logwarn("No markers detected")
marker_pos_pack = self.stag_identify() # 递归调用 marker_pos_pack, ids = self.stag_identify() # 递归调用
# print("Camera coords = ", marker_pos_pack) # print("Camera coords = ", marker_pos_pack)
return marker_pos_pack return marker_pos_pack, ids
except RecursionError: except RecursionError:
# rospy.logerr("Recursion depth exceeded in marker detection") # rospy.logerr("Recursion depth exceeded in marker detection")
return [0, 0, 0, 0] # 返回默认值 return [0, 0, 0, 0], 0 # 返回默认值
def vision_trace(self, mode, ml): def vision_trace(self, mode, ml):
sp = 40 sp = 40
@ -380,26 +379,27 @@ class STAGRecognizer:
self.waitl(ml) self.waitl(ml)
def stag_robot_identify(self): def stag_robot_identify(self):
marker_pos_pack = self.stag_identify() marker_pos_pack, ids = self.stag_identify()
# 如果返回的是默认值,直接退出函数,不返回任何数据 # 如果返回的是默认值,直接退出函数,不返回任何数据
# if marker_pos_pack == [0, 0, 0, 0]: # if marker_pos_pack == [0, 0, 0, 0]:
if np.array_equal(marker_pos_pack, [0, 0, 0, 0]): if np.array_equal(marker_pos_pack, [0, 0, 0, 0]):
rospy.logwarn("No markers detected, skipping processing") rospy.logwarn("No markers detected, skipping processing")
return None # 直接返回 None return None # 直接返回 None
target_coords = self.get_coords() target_coords = self.get_coords()
while len(target_coords)==0: while target_coords is None or len(target_coords) != 6:
target_coords = self.get_coords() target_coords = self.get_coords()
# print("Current coords:", target_coords) # print("Current coords:", target_coords)
cur_coords = np.array(target_coords.copy()) cur_coords = np.array(target_coords.copy())
cur_coords[-3:] *= (np.pi / 180) cur_coords[-3:] *= (np.pi / 180)
fact_bcl = self.Eyes_in_hand(cur_coords, marker_pos_pack, self.EyesInHand_matrix) fact_bcl = self.Eyes_in_hand(cur_coords, marker_pos_pack, self.EyesInHand_matrix)
for i in range(3): for i in range(3):
target_coords[i] = fact_bcl[i] target_coords[i] = fact_bcl[i]
return target_coords return target_coords, ids
def coord_limit(self, coords): def coord_limit(self, coords):
min_coord = [100, -150, 0] min_coord = [-350, -350, 300]
max_coord = [400, 150, 400] max_coord = [350, 350, 500]
for i in range(3): for i in range(3):
if(coords[i] < min_coord[i]): if(coords[i] < min_coord[i]):
coords[i] = min_coord[i] coords[i] = min_coord[i]
@ -415,21 +415,23 @@ class STAGRecognizer:
self.send_angles(self.origin_mycbot_horizontal, 50) self.send_angles(self.origin_mycbot_horizontal, 50)
time.sleep(3) time.sleep(3)
origin = self.get_coords() origin = self.get_coords()
while origin is None:
origin = self.get_coords()
rate = rospy.Rate(30) rate = rospy.Rate(30)
while not rospy.is_shutdown(): while not rospy.is_shutdown():
target_coords = self.stag_robot_identify() _ ,ids = self.stag_identify()
# 如果没有返回目标坐标,跳过本次循环 if ids[0] == 0:
if target_coords is None: target_coords,_ = self.stag_robot_identify()
continue # 跳过这次循环,等下次识别 # 如果没有返回目标坐标,跳过本次循环
target_coords[0] -= 300 self.coord_limit(target_coords)
rospy.loginfo('Target Coords: %s', target_coords) rospy.loginfo('Target Coords: %s', target_coords)
self.coord_limit(target_coords) for i in range(3):
for i in range(3): target_coords[i+3] = origin[i+3]
target_coords[i+3] = origin[i+3] self.pub_marker(target_coords[0]/1000.0, target_coords[1]/1000.0, target_coords[2]/1000.0)
self.pub_marker(target_coords[0]/1000.0, target_coords[1]/1000.0, target_coords[2]/1000.0) self.send_coords(target_coords, 30, 0) # 机械臂移动到二维码前方
self.send_coords(target_coords, 30, 0) # 机械臂移动到二维码前方 rate.sleep()
rate.sleep() elif ids[0] == 1:
self.send_angles(self.origin_mycbot_horizontal, 50)
if __name__ == '__main__': if __name__ == '__main__':