20221021_backup1
This commit is contained in:
parent
209c16a00a
commit
441fd1107c
|
@ -0,0 +1,434 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from copy import deepcopy
|
||||||
|
import os
|
||||||
|
import rospy
|
||||||
|
import math
|
||||||
|
import cmath
|
||||||
|
import cv2
|
||||||
|
import numpy as np
|
||||||
|
from geometry_msgs.msg import Twist
|
||||||
|
from std_msgs.msg import String
|
||||||
|
from sensor_msgs.msg import Image,LaserScan
|
||||||
|
from cv_bridge import CvBridge, CvBridgeError
|
||||||
|
from spark_carry_object.msg import *
|
||||||
|
from matplotlib import pyplot as plt
|
||||||
|
|
||||||
|
|
||||||
|
class GraspObject():
|
||||||
|
'''
|
||||||
|
监听主控,用于物品抓取功能
|
||||||
|
'''
|
||||||
|
image_last_time = None
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
'''
|
||||||
|
初始化
|
||||||
|
'''
|
||||||
|
self.xc = 0
|
||||||
|
self.yc = 0
|
||||||
|
self.xc_prev = 0
|
||||||
|
self.yc_prev = 0
|
||||||
|
self.found_count = 0
|
||||||
|
self.is_have_object = False
|
||||||
|
self.is_found_object = False
|
||||||
|
self.can_grasp = True
|
||||||
|
self.def_object_union = {
|
||||||
|
'p': [],
|
||||||
|
'theta': [],
|
||||||
|
'w': [],
|
||||||
|
'h': [],
|
||||||
|
'size': [],
|
||||||
|
'x': [],
|
||||||
|
'y': [],
|
||||||
|
}
|
||||||
|
self.object_union = deepcopy(self.def_object_union)
|
||||||
|
|
||||||
|
filename = os.environ['HOME'] + "/thefile.txt"
|
||||||
|
with open(filename, 'r') as f:
|
||||||
|
s = f.read()
|
||||||
|
arr = s.split()
|
||||||
|
self.x_kb = [float(arr[0]), float(arr[1])]
|
||||||
|
self.y_kb = [float(arr[2]), float(arr[3])]
|
||||||
|
rospy.logwarn('X axia k and b value: ' + str(self.x_kb))
|
||||||
|
rospy.logwarn('X axia k and b value: ' + str(self.y_kb))
|
||||||
|
|
||||||
|
self.sub = rospy.Subscriber("/camera/rgb/image_raw", Image, self.image_cb, queue_size=1)
|
||||||
|
# 订阅机械臂抓取指令
|
||||||
|
self.sub2 = rospy.Subscriber(
|
||||||
|
'/grasp', String, self.grasp_cp, queue_size=1)
|
||||||
|
# 发布机械臂位姿
|
||||||
|
self.pub1 = rospy.Publisher(
|
||||||
|
'position_write_topic', position, queue_size=10)
|
||||||
|
# 发布机械臂吸盘
|
||||||
|
self.pub2 = rospy.Publisher('pump_topic', status, queue_size=1)
|
||||||
|
# 发布机械臂状态
|
||||||
|
self.grasp_status_pub = rospy.Publisher(
|
||||||
|
'grasp_status', String, queue_size=1)
|
||||||
|
# 发布TWist消息控制机器人底盘
|
||||||
|
self.cmd_vel_pub = rospy.Publisher('/cmd_vel', Twist, queue_size=1)
|
||||||
|
self.arm_to_home()
|
||||||
|
|
||||||
|
# CV检测部分,负责返回识别出的方块位置
|
||||||
|
def image_cb(self, data):
|
||||||
|
xc = -1
|
||||||
|
yc = -1
|
||||||
|
# change to opencv
|
||||||
|
try:
|
||||||
|
cv_image1 = CvBridge().imgmsg_to_cv2(data, "bgr8")
|
||||||
|
except CvBridgeError as e:
|
||||||
|
print('error')
|
||||||
|
|
||||||
|
# 转化成HSV格式
|
||||||
|
cv_image2 = cv2.cvtColor(cv_image1, cv2.COLOR_BGR2HSV)
|
||||||
|
# 蓝色物体颜色检测范围
|
||||||
|
LowerBlue = np.array([95, 90, 80])
|
||||||
|
UpperBlue = np.array([130, 255, 255])
|
||||||
|
# 阈值处理,蓝色部分变为白色,其他部分变为黑色
|
||||||
|
mask = cv2.inRange(cv_image2, LowerBlue, UpperBlue)
|
||||||
|
# 与运算,将白色部分与原来图片的蓝色部分结合
|
||||||
|
cv_image3 = cv2.bitwise_and(cv_image2, cv_image2, mask=mask)
|
||||||
|
# 取三维数组的第一维所有的数据
|
||||||
|
cv_image4 = cv_image3[:, :, 0]
|
||||||
|
# 低通滤波器,9*9滤波
|
||||||
|
blurred = cv2.blur(cv_image4, (9, 9))
|
||||||
|
# 简单阈值函数,处理图像灰度值,大于90的都归为255,其他归0
|
||||||
|
(_, thresh) = cv2.threshold(blurred, 90, 255, cv2.THRESH_BINARY)
|
||||||
|
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
|
||||||
|
cv_image5 = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)
|
||||||
|
cv_image5 = cv2.erode(cv_image5, None, iterations=4)
|
||||||
|
cv_image5 = cv2.dilate(cv_image5, None, iterations=4)
|
||||||
|
|
||||||
|
# 找出轮廓
|
||||||
|
contours, hier = cv2.findContours(cv_image5, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
|
||||||
|
# 将识别出的轮廓画出来,显示在原图中
|
||||||
|
# cv2.drawContours(cv_image1, contours, 0, (0, 255, 0), 2)
|
||||||
|
# cv2.imshow("test",cv_image1)
|
||||||
|
self.object_union = deepcopy(self.def_object_union)
|
||||||
|
# if find contours, pick the biggest box
|
||||||
|
if len(contours) == 0:
|
||||||
|
self.is_have_object = False
|
||||||
|
self.is_found_object = False
|
||||||
|
self.found_count = 0
|
||||||
|
else:
|
||||||
|
self.is_have_object = True
|
||||||
|
index = -1
|
||||||
|
p_min = 10000
|
||||||
|
for i, c in enumerate(contours):
|
||||||
|
rect = cv2.minAreaRect(c)
|
||||||
|
box = cv2.boxPoints(rect)
|
||||||
|
box = np.int0(box)
|
||||||
|
cv2.drawContours(cv_image1, [box], 0, (0, 255, 0), 2)
|
||||||
|
|
||||||
|
x_mid = (box[0][0] + box[2][0] + box[1][0] + box[3][0]) / 4
|
||||||
|
y_mid = (box[0][1] + box[2][1] + box[1][1] + box[3][1]) / 4
|
||||||
|
|
||||||
|
w = math.sqrt((box[0][0] - box[1][0]) ** 2 + (box[0][1] - box[1][1]) ** 2)
|
||||||
|
h = math.sqrt((box[0][0] - box[3][0]) ** 2 + (box[0][1] - box[3][1]) ** 2)
|
||||||
|
|
||||||
|
size = w * h
|
||||||
|
|
||||||
|
p, theta = cmath.polar(complex(x_mid - 320, 480 - y_mid))
|
||||||
|
cn = cmath.rect(p, theta)
|
||||||
|
|
||||||
|
if p > 350:
|
||||||
|
continue
|
||||||
|
|
||||||
|
self.object_union['p'].append(p)
|
||||||
|
self.object_union['theta'].append(theta)
|
||||||
|
self.object_union['size'].append(size)
|
||||||
|
self.object_union['w'].append(w)
|
||||||
|
self.object_union['h'].append(h)
|
||||||
|
self.object_union['x'].append(x_mid)
|
||||||
|
self.object_union['y'].append(y_mid)
|
||||||
|
|
||||||
|
if p < p_min:
|
||||||
|
index = index + 1
|
||||||
|
p_min = p
|
||||||
|
xc = x_mid
|
||||||
|
yc = y_mid
|
||||||
|
|
||||||
|
# if box is not moving for 20 times
|
||||||
|
# print found_count
|
||||||
|
if self.found_count >= 30:
|
||||||
|
self.found_count = 0
|
||||||
|
self.is_found_object = True
|
||||||
|
self.xc = xc
|
||||||
|
self.yc = yc
|
||||||
|
else:
|
||||||
|
# if box is not moving
|
||||||
|
if index == -1:
|
||||||
|
# rospy.logwarn("No object eligible for grasp")
|
||||||
|
self.found_count = 0
|
||||||
|
self.is_found_object = False
|
||||||
|
elif abs(xc - self.xc_prev) <= 4 and abs(yc - self.yc_prev) <= 4:
|
||||||
|
# print(xc, " ", yc)
|
||||||
|
cn = cmath.rect(self.object_union['p'][index], self.object_union['theta'][index])
|
||||||
|
# cv2.line(cv_image1, (320, 480), (int(320 + cn.real), int(480 - cn.imag)), (255, 0, 0), 2)
|
||||||
|
self.found_count = self.found_count + 1
|
||||||
|
else:
|
||||||
|
self.found_count = 0
|
||||||
|
self.xc_prev = xc
|
||||||
|
self.yc_prev = yc
|
||||||
|
|
||||||
|
cv2.imshow("source", cv_image1)
|
||||||
|
# cv2.imshow("gray", cv_image5)
|
||||||
|
cv2.waitKey(1)
|
||||||
|
|
||||||
|
self.image_last_time = rospy.get_rostime()
|
||||||
|
|
||||||
|
def grasp_cp(self, msg):
|
||||||
|
# 判断收到的抓取或放的信息
|
||||||
|
if msg.data == '1':
|
||||||
|
print("收到抓取信号")
|
||||||
|
times=0
|
||||||
|
steps=0
|
||||||
|
if self.is_found_object:
|
||||||
|
if self.can_grasp:
|
||||||
|
print("现在允许抓取")
|
||||||
|
if self.grasp():
|
||||||
|
print("已成功抓取")
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
# 抓取不成功,将允许重新抓取
|
||||||
|
self.can_grasp = True
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
print("抓取执行中,不允许重复抓取")
|
||||||
|
return
|
||||||
|
|
||||||
|
# 转一圈没有发现可抓取物体,退出抓取
|
||||||
|
else:
|
||||||
|
vel = Twist()
|
||||||
|
vel.angular.z = 0.2
|
||||||
|
rate = rospy.Rate(10)
|
||||||
|
|
||||||
|
# 判断视野范围内有无方块
|
||||||
|
while not self.is_have_object:
|
||||||
|
rate.sleep()
|
||||||
|
times = times + 1
|
||||||
|
if (times > math.pi * 2 / vel.angular.z * 10):
|
||||||
|
rospy.logerr("can not found object!!! Waiting next clicked_point...")
|
||||||
|
# self.grasp_status_pub.publish(String('0'))
|
||||||
|
return
|
||||||
|
self.cmd_vel_pub.publish(vel)
|
||||||
|
|
||||||
|
times = 0
|
||||||
|
while not self.is_found_object:
|
||||||
|
rate.sleep()
|
||||||
|
times = times + 1
|
||||||
|
if (times > 30):
|
||||||
|
rospy.logerr("object founded but can not location it!!! Waiting next clicked_point...")
|
||||||
|
# self.grasp_status_pub.publish(String('0'))
|
||||||
|
return
|
||||||
|
|
||||||
|
# print("unregisting sub\n")
|
||||||
|
# self.sub.unregister()
|
||||||
|
|
||||||
|
# 抓取检测到的物体
|
||||||
|
if self.grasp():
|
||||||
|
print("已成功抓取")
|
||||||
|
else:
|
||||||
|
# 抓取不成功,将允许重新抓取
|
||||||
|
self.can_grasp = True
|
||||||
|
|
||||||
|
elif msg.data=='0':
|
||||||
|
# 放下物体
|
||||||
|
self.is_found_object = False
|
||||||
|
self.release_object(1)
|
||||||
|
elif msg.data=='2':
|
||||||
|
# 放下物体
|
||||||
|
self.is_found_object = False
|
||||||
|
self.release_object(2)
|
||||||
|
elif msg.data=='3':
|
||||||
|
# 放下物体
|
||||||
|
self.is_found_object = False
|
||||||
|
self.release_object(3)
|
||||||
|
|
||||||
|
# 执行抓取
|
||||||
|
def grasp(self):
|
||||||
|
# 设置是否允许抓取值为False,避免抓取过程中重复收到抓取的信号
|
||||||
|
self.can_grasp = False
|
||||||
|
print("现在开始抓取\n")
|
||||||
|
# 设置睡眠时间
|
||||||
|
r1 = rospy.Rate(0.1)
|
||||||
|
r2 = rospy.Rate(10)
|
||||||
|
|
||||||
|
pos = position()
|
||||||
|
|
||||||
|
# 物体所在坐标+标定误差
|
||||||
|
# 先到目标位置上方
|
||||||
|
pos.x = self.x_kb[0] * self.yc + self.x_kb[1]
|
||||||
|
pos.y = self.y_kb[0] * self.xc + self.y_kb[1]
|
||||||
|
pos.z = 20
|
||||||
|
self.pub1.publish(pos)
|
||||||
|
r2.sleep()
|
||||||
|
|
||||||
|
# 开始往下放
|
||||||
|
pos.z = -50
|
||||||
|
self.pub1.publish(pos)
|
||||||
|
r2.sleep()
|
||||||
|
|
||||||
|
# 开始吸取物体,pub2 1为吸取,0为释放
|
||||||
|
self.pub2.publish(1)
|
||||||
|
r2.sleep()
|
||||||
|
|
||||||
|
# 提起物体到检查位置
|
||||||
|
pos.x = 250
|
||||||
|
pos.y = 0
|
||||||
|
pos.z = 70
|
||||||
|
self.pub1.publish(pos)
|
||||||
|
r2.sleep()
|
||||||
|
|
||||||
|
# 利用雷达检查是否有方块
|
||||||
|
if self.check_grasp_state():
|
||||||
|
print("检测到抓取成功")
|
||||||
|
pos.x = 220 #160
|
||||||
|
pos.y = 0
|
||||||
|
pos.z = 160
|
||||||
|
self.pub1.publish(pos)
|
||||||
|
r2.sleep()
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
print("检测到抓取失败")
|
||||||
|
self.arm_to_home()
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def arm_to_home(self):
|
||||||
|
pos = position()
|
||||||
|
|
||||||
|
pos.x = 140
|
||||||
|
pos.y = 0
|
||||||
|
pos.z = 60
|
||||||
|
self.pub1.publish(pos)
|
||||||
|
rospy.sleep(1)
|
||||||
|
|
||||||
|
pos.x = 120
|
||||||
|
pos.y = 0
|
||||||
|
pos.z = 35
|
||||||
|
self.pub1.publish(pos)
|
||||||
|
rospy.sleep(2)
|
||||||
|
|
||||||
|
|
||||||
|
# 检查是否成功抓取,成功返回True,反之返回False
|
||||||
|
def check_grasp_state(self):
|
||||||
|
|
||||||
|
self.success_grasp_num = 0
|
||||||
|
scan_num = 0
|
||||||
|
# 读十次雷达数据,10hz
|
||||||
|
while scan_num < 60:
|
||||||
|
|
||||||
|
scan_msg = rospy.wait_for_message("/scan",LaserScan,timeout=None)
|
||||||
|
|
||||||
|
# 计算激光束数量,num值为1817
|
||||||
|
num = int((scan_msg.angle_max-scan_msg.angle_min)/scan_msg.angle_increment)
|
||||||
|
|
||||||
|
# 输入想要检测的角度与范围,机器人正后方为起始点
|
||||||
|
expect_angle = 180
|
||||||
|
ranges = 20
|
||||||
|
test_direction = int(expect_angle/360*num)
|
||||||
|
|
||||||
|
detect_num = 0 # 已经检测的次数
|
||||||
|
sum = 0 # 数据总和
|
||||||
|
|
||||||
|
# 计算检测区域的距离值
|
||||||
|
for i in range(test_direction-ranges,test_direction+ranges):
|
||||||
|
# 排除检测距离值有出现0值的情况
|
||||||
|
if scan_msg.ranges[i] != 0:
|
||||||
|
sum = scan_msg.ranges[i]+sum
|
||||||
|
detect_num +=1
|
||||||
|
# print("scan_msg.ranges[",i,"]=",scan_msg.ranges[i])
|
||||||
|
|
||||||
|
# 避免检测距离值出现均为0导致计算报错
|
||||||
|
if detect_num == 0:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# 取距离值,抓取成功值约为0.26——0.32,单位为米
|
||||||
|
averlaser = sum/detect_num
|
||||||
|
print("averlaser=",averlaser)
|
||||||
|
|
||||||
|
# 判断是否成功抓取
|
||||||
|
if averlaser < 0.35:
|
||||||
|
self.success_grasp_num += 1
|
||||||
|
# 判断成功抓取次数超过3次,返回true
|
||||||
|
if self.success_grasp_num >= 3:
|
||||||
|
self.success_grasp_num = 0
|
||||||
|
return True
|
||||||
|
print("scan_num=",scan_num)
|
||||||
|
scan_num += 1
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# 释放物体
|
||||||
|
def release_object(self,height):
|
||||||
|
r1 = rospy.Rate(1) # 1s
|
||||||
|
pos = position()
|
||||||
|
# go forward
|
||||||
|
if height == 1:
|
||||||
|
pos.x = 220
|
||||||
|
pos.y = 0
|
||||||
|
pos.z = -40 #-80
|
||||||
|
self.pub1.publish(pos)
|
||||||
|
r1.sleep()
|
||||||
|
|
||||||
|
if height == 2:
|
||||||
|
pos.x = 220
|
||||||
|
pos.y = 0
|
||||||
|
pos.z = 80 #-80
|
||||||
|
self.pub1.publish(pos)
|
||||||
|
r1.sleep()
|
||||||
|
|
||||||
|
if height == 3:
|
||||||
|
pos.x = 220
|
||||||
|
pos.y = 0
|
||||||
|
pos.z = 160 #-80
|
||||||
|
self.pub1.publish(pos)
|
||||||
|
r1.sleep()
|
||||||
|
|
||||||
|
# stop pump
|
||||||
|
self.pub2.publish(0)
|
||||||
|
rospy.sleep(1)
|
||||||
|
|
||||||
|
if height == 3:
|
||||||
|
pos.x = 220
|
||||||
|
pos.y = 80
|
||||||
|
pos.z = 160
|
||||||
|
print("避开第三层方块")
|
||||||
|
self.pub1.publish(pos)
|
||||||
|
rospy.sleep(2)
|
||||||
|
|
||||||
|
pos.x = 120
|
||||||
|
pos.y = 150
|
||||||
|
pos.z = 35
|
||||||
|
self.pub1.publish(pos)
|
||||||
|
rospy.sleep(1)
|
||||||
|
|
||||||
|
self.arm_to_home()
|
||||||
|
# 释放后,修改成能够成功抓取
|
||||||
|
self.can_grasp = True
|
||||||
|
|
||||||
|
return 'succeeded'
|
||||||
|
|
||||||
|
# 转动机器人到一定角度
|
||||||
|
def turn_body(self):
|
||||||
|
cmd_vel = Twist()
|
||||||
|
cmd_vel.angular.z = 0.25
|
||||||
|
rate = rospy.Rate(10)
|
||||||
|
for i in range(40):
|
||||||
|
self.cmd_vel_pub.publish(cmd_vel)
|
||||||
|
rate.sleep()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
try:
|
||||||
|
rospy.init_node('GraspObject', anonymous=False)
|
||||||
|
rospy.loginfo("Init GraspObject main")
|
||||||
|
GraspObject()
|
||||||
|
rospy.spin()
|
||||||
|
except rospy.ROSInterruptException:
|
||||||
|
rospy.loginfo("End spark GraspObject main")
|
||||||
|
|
|
@ -208,6 +208,7 @@ class GraspObject():
|
||||||
# cv2.imshow("win1", cv_image1)
|
# cv2.imshow("win1", cv_image1)
|
||||||
# cv2.imshow("win2", cv_image5)
|
# cv2.imshow("win2", cv_image5)
|
||||||
# cv2.waitKey(1)
|
# cv2.waitKey(1)
|
||||||
|
|
||||||
contours, hier = cv2.findContours(cv_image4, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
|
contours, hier = cv2.findContours(cv_image4, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
|
||||||
|
|
||||||
# if find contours, pick the biggest box
|
# if find contours, pick the biggest box
|
||||||
|
@ -261,6 +262,13 @@ class GraspObject():
|
||||||
found_count = 0
|
found_count = 0
|
||||||
xc_prev = xc
|
xc_prev = xc
|
||||||
yc_prev = yc
|
yc_prev = yc
|
||||||
|
|
||||||
|
# cv2.imshow("source", cv_image1)
|
||||||
|
# cv2.waitKey(1)
|
||||||
|
|
||||||
|
# self.image_last_time = rospy.get_rostime()
|
||||||
|
|
||||||
|
|
||||||
# 释放物体
|
# 释放物体
|
||||||
def release_object(self):
|
def release_object(self):
|
||||||
r1 = rospy.Rate(0.15) # 5s
|
r1 = rospy.Rate(0.15) # 5s
|
||||||
|
|
Loading…
Reference in New Issue