執(zhí)行手眼標(biāo)定(eye in hand)步驟:
-
收集數(shù)據(jù):使用相機(jī)拍攝多張不同角度的標(biāo)定板圖像,并記錄相機(jī)和機(jī)械臂的位姿數(shù)據(jù)。
-
提取標(biāo)定板角點(diǎn):使用OpenCV庫(kù)中的函數(shù)cv2.findChessboardCorners()提取標(biāo)定板圖像中的角點(diǎn)坐標(biāo)。
-
計(jì)算相機(jī)內(nèi)參矩陣:使用OpenCV庫(kù)中的函數(shù)cv2.calibrateCamera()計(jì)算相機(jī)的內(nèi)參矩陣,包括焦距、主點(diǎn)和畸變系數(shù)等。
-
計(jì)算相機(jī)外參矩陣:對(duì)于每張標(biāo)定板圖像,使用OpenCV庫(kù)中的函數(shù)cv2.solvePnP()計(jì)算相機(jī)的外參矩陣,即相機(jī)在世界坐標(biāo)系中的位姿。
-
計(jì)算機(jī)械臂末端在世界坐標(biāo)系中的位姿:對(duì)于每個(gè)機(jī)械臂的位姿數(shù)據(jù),使用機(jī)械臂的運(yùn)動(dòng)學(xué)模型計(jì)算機(jī)械臂末端在世界坐標(biāo)系中的位姿。
-
計(jì)算相機(jī)和機(jī)械臂之間的變換矩陣:將相機(jī)在世界坐標(biāo)系中的位姿和機(jī)械臂末端在世界坐標(biāo)系中的位姿作為輸入,使用OpenCV庫(kù)中的函數(shù)cv2.solvePnP()計(jì)算相機(jī)和機(jī)械臂之間的變換矩陣。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-595698.html
-
應(yīng)用手眼標(biāo)定結(jié)果計(jì)算目標(biāo)世界坐標(biāo):對(duì)于每個(gè)目標(biāo)點(diǎn)的像素坐標(biāo),使用相機(jī)的內(nèi)參矩陣將其轉(zhuǎn)換為相機(jī)坐標(biāo)系下的坐標(biāo),然后使用相機(jī)和機(jī)械臂之間的變換矩陣將其轉(zhuǎn)換為機(jī)械臂末端坐標(biāo)系下的坐標(biāo),最后使用機(jī)械臂的逆運(yùn)動(dòng)學(xué)模型計(jì)算機(jī)械臂需要運(yùn)動(dòng)到的關(guān)節(jié)角度,從而實(shí)現(xiàn)目標(biāo)點(diǎn)的定位。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-595698.html
import cv2
import numpy as np
import rospy
from sensor_msgs.msg import Image, CameraInfo
from cv_bridge import CvBridge
# 訂閱相機(jī)圖像和相機(jī)信息
def image_callback(image_msg):
global cv_image
bridge = CvBridge()
cv_image = bridge.imgmsg_to_cv2(image_msg, desired_encoding='bgr8')
def camera_info_callback(info_msg):
global camera_info
camera_info = info_msg
rospy.init_node('handeye_calibration')
# 訂閱相機(jī)圖像和相機(jī)信息
rospy.Subscriber('/camera/image_raw', Image, image_callback)
rospy.Subscriber('/camera/camera_info', CameraInfo, camera_info_callback)
# 獲取標(biāo)定板參數(shù)
pattern_size = (9, 6) # 內(nèi)部角點(diǎn)數(shù)量
square_size = 0.0254 # 標(biāo)定板方塊大小
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)
# 定義物體點(diǎn)和圖像點(diǎn)數(shù)組
object_points = []
image_points = []
# 檢測(cè)標(biāo)定板并提取角點(diǎn)
while len(image_points) < 20:
if cv_image is not None and camera_info is not None:
gray = cv2.cvtColor(cv_image, cv2.COLOR_BGR2GRAY)
ret, corners = cv2.findChessboardCorners(gray, pattern_size, None)
if ret:
object_point = np.zeros((pattern_size[0] * pattern_size[1], 3), np.float32)
object_point[:, :2] = np.mgrid[0:pattern_size[0], 0:pattern_size[1]].T.reshape(-1, 2)
object_point *= square_size
corners_refined = cv2.cornerSubPix(gray, corners, (11, 11), (-1, -1), criteria)
object_points.append(object_point)
image_points.append(corners_refined)
cv2.drawChessboardCorners(cv_image, pattern_size, corners_refined, ret)
cv2.imshow('image', cv_image)
cv2.waitKey(100)
# 計(jì)算相機(jī)和機(jī)械臂姿態(tài)之間的變換
camera_matrix = np.array(camera_info.K).reshape((3, 3))
dist_coeffs = np.array(camera_info.D)[:4]
object_points_array = np.array(object_points)
rvecs_camera = []
tvecs_camera = []
rvecs_robot = []
tvecs_robot = []
for i in range(len(image_points)):
# 計(jì)算相機(jī)姿態(tài)
success, rvec, tvec = cv2.solvePnP(
object_points_array[i],
image_points[i],
camera_matrix,
dist_coeffs)
rvecs_camera.append(rvec)
tvecs_camera.append(tvec)
# 獲取機(jī)械臂姿態(tài),這里假設(shè)機(jī)械臂已經(jīng)正確標(biāo)定,因此可以直接使用機(jī)械臂末端執(zhí)行器的位姿作為機(jī)械臂姿態(tài)
robot_pos = get_robot_pos()
rvecs_robot.append(robot_pos[:3])
tvecs_robot.append(robot_pos[3:])
# 執(zhí)行手眼標(biāo)定
ret, H = cv2.calibrateHandEye(
np.array(rvecs_robot),
np.array(tvecs_robot),
np.array(rvecs_camera),
np.array(tvecs_camera),
method=cv2.CALIB_HAND_EYE_TSAI)
print(f'Hand-eye transformation:\n{H}')
cv2.destroyAllWindows()
到了這里,關(guān)于機(jī)械臂進(jìn)行手眼標(biāo)定(眼在手上)python代碼的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!