获取深度图后要对目标抓取位姿进行估计,在机器人抓取(六)—— 平面抓取位姿估计( gqcnn代码测试与解读) 中对抓取位姿估计项目 gqcnn 的源码做了详细解读。
为方便应用,本文用 FullyConvolutionalGraspingPolicyParallelJaw 模型重写了抓取位姿服务器节点 grasp_planner_node.py。代码如下
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Original author Vishal Satish & Jeff Mahler
Adaptor zxxRobot-2021-03-22
"""
import json
import os
import matplotlib.pyplot as plt
import numpy as np
import rospy
import ros_numpy
from visualization import Visualizer2D
from autolab_core import YamlConfig
from gqcnn.grasping import (RgbdImageState, FullyConvolutionalGraspingPolicyParallelJaw)
from perception import (CameraIntrinsics, ColorImage, DepthImage, RgbdImage)
import utils
from pick_place.msg import GQCNNGrasp
from pick_place.srv import GQCNNGraspPlanner
class GetGraspPose:
"""Calculate the grasping pose and q_value from the depth image"""
def __init__(self,
model_path="/home/ur/ur5/src/gqcnn/models/FC-GQCNN-4.0-PJ", # 抓取模型存储路径
config_filename="/home/ur/ur5/src/gqcnn/cfg/examples/fc_gqcnn_ur5.yaml",
camera_intr_filename="/home/ur/ur5/src/gqcnn/data/calib/k4a/k4a_depth.intr", # 相机内参
camera_external_filename="/home/ur/.ros/easy_handeye/ur5_k4a_handeyecalibration_eye_on_base.yaml", # 相机外参,通过手眼标定获得
):
# 1. Get model configs.
self.model_config = json.load(open(os.path.join(model_path, "config.json"), "r"))
try:
gqcnn_config = self.model_config["gqcnn"]
# gripper_mode = gqcnn_config["gripper_mode"]
except KeyError as e:
print('except:', e)
# 2.Read config.
self.config = YamlConfig(config_filename)
self.policy_config = self.config["policy"]
# Confirm that the model_path is absolute
if "gqcnn_model" in self.policy_config["metric"]:
assert os.path.isabs(self.policy_config["metric"]["gqcnn_model"]), "the model_path must be an absolute path"
self.policy_config["metric"]["gqcnn_model"] = model_path
# 3. Setup depth camera.
self.camera_intr = CameraIntrinsics.load(camera_intr_filename)
# Set input sizes for fully-convolutional policy.
self.policy_config["metric"]["fully_conv_gqcnn_config"][
"im_height"] = self.camera_intr.height # depth_im.shape[0]
self.policy_config["metric"]["fully_conv_gqcnn_config"][
"im_width"] = self.camera_intr.width # depth_im.shape[1]
# 4. read camera external parameter
self.camera_extr = utils.read_camera_external_parameter(camera_external_filename)
self.grasp_approach_dir = np.array([0, 0, 1]) # = self.transform_world_to_camera([0.707106781, -0.707106781, 0])
# 5. setup policy
if self.policy_config["type"] == "fully_conv_pj":
self.policy = FullyConvolutionalGraspingPolicyParallelJaw(self.policy_config)
else:
raise ValueError( "Invalid fully-convolutional policy type: {}".format(
self.policy_config["type"]))
# def __call__(self, depth_data):
# return self.get_grasp_pose(depth_data)
def transform_world_to_camera(self, vector):
"""transform direction vector from world_frame to camera_frame"""
trans44 = utils.pose_to_mat44(self.camera_extr)
rot33 = np.transpose(trans44[:3][:, :3]) # 旋转逆变换
return np.dot(rot33, np.array(vector))
def get_grasp_pose(self, rqe):
# Read depth_images. Depth images only support float arrays
depth = ros_numpy.numpify(rqe.depth_image)
depth_im = DepthImage(depth, frame=self.camera_intr.frame)
# color_im = ColorImage(color, frame=self.camera_intr.frame)
color_im = ColorImage(np.zeros([depth_im.height, depth_im.width,3]).astype(np.uint8),
frame=self.camera_intr.frame)
segmask = depth_im.invalid_pixel_mask().inverse()
# Inpaint.
depth_im = depth_im.inpaint(rescale_factor=self.config["inpaint_rescale_factor"]) # 0.5
# Create state (RGB-D). In fact, color images are not used
rgbd_im = RgbdImage.from_color_and_depth(color_im, depth_im)
state = RgbdImageState(rgbd_im, self.camera_intr, segmask=segmask)
grasp_action = self.policy(state)
grasp_pose_cameraframe = grasp_action.grasp.pose(self.grasp_approach_dir).pose_msg
# transform grasp_pose from camera_frame to robot_frame
grasp_pose_robotframe = utils.transform_pose(grasp_pose_cameraframe, self.camera_extr)
gqcnn_grasp = GQCNNGrasp()
gqcnn_grasp.pose = grasp_pose_robotframe
gqcnn_grasp.q_value = grasp_action.q_value
# # Vis final grasp.
if self.policy_config["vis"]["final_grasp"]:
Visualizer2D.figure(size=(10, 10))
Visualizer2D.imshow(rgbd_im.depth,
vmin=self.policy_config["vis"]["vmin"],
vmax=self.policy_config["vis"]["vmax"])
Visualizer2D.grasp(grasp_action.grasp, scale=2.5, show_center=False, show_axis=True)
Visualizer2D.title("Planned grasp at depth {0:.3f}m with Q={1:.3f}".format(
grasp_action.grasp.depth, grasp_action.q_value))
Visualizer2D.show("depth")
plt.pause(2)
plt.close("all")
return gqcnn_grasp
if __name__ == "__main__":
rospy.init_node("Grasp_Sampler_Server")
camera_intr_filename = "/home/ur/ur5/src/gqcnn/data/calib/k4a/k4a_resize.intr" # 图片太大了会拖慢推理速度甚至超出 jetson AGX Xavier的负载,所以做了 resize
grasp_planner = GetGraspPose(camera_intr_filename=camera_intr_filename)
grasp_planning_service = rospy.Service("grasp_planner", GQCNNGraspPlanner,
grasp_planner.get_grasp_pose)
rospy.loginfo("Grasping Policy Initialized")
# Spin forever.
rospy.spin()
grasp_plannning_service.launch 内容如下,启动相机服务器和抓取位姿估计服务器两个节点。
<launch>
<!-- Namespace for the node and services -->
<arg name="ns" default="gqcnn" />
<node name="get_depth_image" pkg="pick_place" type="camera_server_node.py" ns="$(arg ns)" output="screen" />
<node name="grasp_planner" pkg="pick_place" type="grasp_planner_node.py" ns="$(arg ns)" output="screen" >
</node>
</launch>
在客户端节点调用 grasp_planner 服务即可获取抓取位姿。主要代码节选如下:
...
rospy.init_node('pick_and_place', anonymous=True)
print("wait for get_depth_image service and create service proxy......")
rospy.wait_for_service("gqcnn/get_depth_image")
get_depth = rospy.ServiceProxy("gqcnn/get_depth_image", Depth)
print("wait for grasp planning service and create service proxy......")
rospy.wait_for_service("gqcnn/grasp_planner")
plan_grasp = rospy.ServiceProxy("gqcnn/grasp_planner", GQCNNGraspPlanner)
...
while not rospy.is_shutdown():
print("=========== Press 'Enter to get grasp pose ===========")
raw_input()
print("The program is planning grasp pose, Please wait a moment.....")
depth_msg = get_depth().depth_image
grasp = plan_grasp(depth_msg).grasp
grasp_pose = grasp.pose # 目标位姿
q_value = grasp.q_value # 位姿估计质量
...
得到目标位姿后,就可以规划机器人运动轨迹,控制机器人抓取目标物体了。
评论(1)
您还未登录,请登录后发表或查看评论