仓库配送
1.简介
随着电子商务的出现,对产品的需求增加,公司需要大量库存并需要每天处理大量货物。这包括许多劳动密集型任务,如存储、移动、扫描、检查、交付等等。为了提高效率,越来越多的仓库和配送中心正在根据需求不同程度地转向自动化,从半自主系统到完全自主系统。
机器人搬运系统越来越多地用于仓库和配送中心,因为它们可以灵活地管理不同的需求要求,并且可以 24/7 全天候工作。
在这个项目中,机械臂用于从传送带上传送包裹,并将其装载到内部运输机器人上进行库存。
图>二。工作
这是一个自动拾取和运输系统,其中 2 DOF 机械臂(如图 图
2 ) 可以绕 z 轴和 x 轴旋转,并有一个夹具。运输机器人(显示在
图 1 ) 上安装了一个超声波传感器,用于检测它与扩展坞的距离。一旦接近车站,车辆就会转动 180 度,同时向手臂发送通知,告知到达。在接收时,手臂最初与 z 轴对齐,朝向传送带旋转 90 度,在抓手的帮助下从传送带上捡起货物。一旦它捡起货物,手臂就会旋转 -90 度,使其与 z 轴对齐(抓手向上)。然后,在使用 OpenCV 和 PiCamera 搜索运输车辆时,手臂开始绕 z 轴旋转。一旦它发现位于传送带对面的运输机器人,该臂将进一步旋转臂 -90 度,朝向机器人,围绕 x 将抓手放置在拾取机器人的顶部。稍后,夹具打开以将货物放置在机器人上,然后在它移回初始位置时向其发出(蓝牙)信号以指示装载。运输车辆收到此通知后,开始从停靠站向所需的库存位置移动。
图>三。低通滤波器
我们使用低通巴特沃斯滤波器过滤掉相机读取 x-y-z 数据中的高频变化。我们正在创建一个向量输出 x-y-z 值并将此过滤器应用于它。应用滤波器后,我们取向量的最后 20 个元素的平均值,以减少噪声并平滑图形,从而从 PiCam 获得更准确的球位置。
图>在图 3 ,橙色线为原始数据(噪声很大,波动很大),蓝色线为平滑的滤波bata。
四。电子产品
伺服: 项目共使用5台伺服电机。 2 用于驱动运输车辆(差速驱动)。 3 用于控制机械臂的关节。
超声波传感器: 超声波传感器使用超声波测量到物体的距离。传感器中的发射器以固定间隔发射短的高频声脉冲,这些脉冲在空气中传播,并在撞击物体时作为回波信号反射回接收器。通过测量发射信号和接收回波之间的时间跨度(称为飞行时间)来计算距离。安装在移动机器人上,用于路径规划和检测蓝牙:安装在Arduino上的HC06用于与树莓派内置的蓝牙模块进行串行通信。
Pi-Camera:安装在机械臂一个关节上的摄像头,用于跟踪停靠在停靠站某处的运输车辆。
V。电路
图>正如我们在图中所见 4 我们在树莓派中使用了三个舵机。
树莓派只有两个PWM管脚,所以我们自己写了PWM舵机代码让三个舵机跑起来,
Pi cam 连接到树莓派,如上图所示。相机使用OpenCV找到球并锁定手臂的位置。
如上图所示,Arduino 总共连接了四个组件。两个舵机,一个超声波传感器和一个 HC-06 蓝牙模块。哪个用于运行货物机器人?
V。 代码
VI.I. Arduino 代码:
#include
伺服左;
伺服右;
const int GNND =4; const int GNDD =35; const int echo =37; const int 触发 =39; const int VCCC =41;
浮动 invcmCosnt =(2*1000000)/(100*344.8); //cmDist=rawTime/invcmCosnt void setup() {
Serial.begin(9600); Serial3.begin(9600);
left.attach(3); // 将引脚 9 上的伺服连接到伺服对象 right.attach(5);
pinMode(触发,输出); pinMode(回声,输入); pinMode(GNND,输出); pinMode(GNDD,输出); pinMode(VCCC, OUTPUT);
数字写入(VCCC,高);数字写入(GNND,低);数字写入(GNDD,低); pinMode(LED_BUILTIN, OUTPUT);
左写(114); right.write(74);
}
void loop() {
浮动原始时间,cmDist;数字写入(触发,低);延迟微秒(2);数字写入(触发,高);延迟微秒(5);数字写入(触发,低);原始时间 =脉冲输入(回声,高); cmDist =100;
而(cmDist> 4){ digitalWrite(trig, LOW);延迟微秒(2);数字写入(触发,高);延迟微秒(5);数字写入(触发,低);原始时间 =脉冲输入(回声,高); cmDist =rawTime/invcmCosnt; Serial.println(cmDist);
}
Serial.println(“出”); Serial3.println(“s”);左写(94);正确的写(94);延迟(1000);左写(114);正确的写(114);延迟(1700); Serial.println(“转”);左写(94);正确的写(94); Serial.println(“停止”);而(1){
if(Serial3.read()=='f'){ break;
}
}
左写(114);正确的写(74);延迟(2500);左写(94);正确的写(94);而(1){
}
}
VI.II.覆盆子
在树莓派端,需要先将树莓派连接到HC-06蓝牙模块,使用以下命令先找到,
$ hcitool scan #如果蓝牙的MAC ID已知且可用,可以跳过
然后使用正确的 MAC ID 连接到所需的蓝牙:
$ sudo rfcomm 连接 hci0 xx:xx:xx:xx:xx:xx
如果执行成功,则蓝牙已连接。
从 collections import deque 导入必要的包
from imutils.video import VideoStream import numpy as np
import argparse import cv2 import imutils import time import timeit
from scipy import signal import matplotlib.pyplot as plt
将 RPi.GPIO 导入为 GPIO
导入序列
GPIO.setmode(GPIO.BCM) GPIO.setup(12, GPIO.OUT) #Gripper GPIO.setup(13, GPIO.OUT) # Rot_x GPIO.setup(16, GPIO.OUT) # Rot_z
rotz =16
rotx =GPIO.PWM(13, 50) gr =GPIO.PWM(12, 50)
blue =serial.Serial(“/dev/rfcomm0”, baudrate=9600) 打印(“蓝牙连接”)
def duty(angle):
返回角度* 5 / 90 + 2.5
def search(angle=90, add=1):servo_pwm(rotz, duty(angle), 50) ap =argparse.ArgumentParser() ap.add_argument(“-v”, “–video”,
help=“(可选)视频文件的路径”) ap.add_argument(“-b”, “–buffer”, type=int, default=64,
help=”max buffer size”) args =vars(ap .parse_args())
xn =np.zeros([500]) xm =np.zeros([1])
greenLower =(20, 20, 53)
greenUpper =(64) , 255, 255)
pts =deque(maxlen=args[“buffer”])
如果未提供视频路径,请获取网络摄像头的引用 #
如果不是 args.get(“video”, False):
vs =VideoStream(src=0).start()
否则,获取对其他视频文件的引用:
vs =cv2.VideoCapture(args[“视频”])
允许相机或视频文件预热 time.sleep(2.0)
while True:
if angle ==125:
add =-5
elif angle ==35:
add =5 angle +=add
servo_pwm(rotz,职责(角度),10)时间。睡眠(0.01)
抓取当前帧 frame =vs.read()
处理来自 VideoCapture 或 VideoStream 的帧 frame =frame[1] if args.get(“video”, False) else frame
如果我们正在观看视频并且没有抓取一帧,#那么我们已经到了视频的结尾
如果框架为无:
break
调整框架的大小,对其进行模糊处理,然后将其转换为 HSV # 颜色空间
frame =imutils.resize(frame, width=600) blurred =cv2.GaussianBlur(frame, (11, 11), 0)
hsv =cv2.cvtColor(blurred, cv2.COLOR_BGR2HSV)
为“绿色”颜色构建一个蒙版,然后执行 # 一系列膨胀和腐蚀以去除蒙版中留下的任何小 # 斑点
掩码 =cv2.inRange(hsv, greenLower, greenUpper) 掩码 =cv2.erode(掩码,无,迭代=2)
掩码 =cv2.dilate(掩码,无,迭代=2)
在mask中找到轮廓并初始化球的当前#(x,y)中心
cnts =cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts =imutils.grab_contours(cnts) center =None
如果 len(cnts)> 0,则仅在找到至少一个轮廓时才继续:
找到掩码中最大的轮廓,然后使用
它计算最小封闭圆和#centroid
c =max(cnts, key=cv2.contourArea)
((x, y), radius) =cv2.minEnclosureCircle(c) M =cv2.moments(c)
center =(int(M) [“m10”] / M[“m00”]), int(M[“m01”] / M[“m00”])) # 只有在半径满足最小尺寸时才继续
如果半径> 10:
在框架上绘制圆和质心,#然后更新跟踪点列表 cv2.circle(frame, (int(x), int(y)), int(radius),
(0, 255, 255), 2)
cv2.circle(frame, center, 5, (0, 0, 255), -1)
xn =np.delete(xn, 0) xn =np.append(xn, x) fs =300
fc =1 x_old =x
w =fc / (fs / 2)
b, a =signal.butter(5, w, 'low') output =signal.filtfilt(b, a, xn) x =np.average(xn[480:500]) print(x, x_old)
xm =np.append(xm, x) if abs(x – 300) <20:
break
更新点队列 pts.appendleft(center)
对于范围内的 i(1, len(pts)):
如果任何一个跟踪点都为 None,则忽略 # 他们
如果 pts[i – 1] 为 None 或 pts[i] 为 None:
continue
否则,计算线的粗细并#绘制连接线
厚度 =int(np.sqrt(args[“buffer”] / float(i + 1)) * 2.5) cv2.line(frame, pts[i – 1], pts[i], (0, 0, 255) , 厚度)
将框架显示到我们的屏幕上 cv2.imshow(“Frame”, frame) key =cv2.waitKey(1) &0xFF
如果按下“q”键,则停止循环 if key ==ord(“q”):
打印(xn) 打印(xn.shape) plt.plot(xm, label='x') plt.show()
break
如果不是 args.get(“video”, False):vs.stop()
否则,松开相机否则:
vs.release()
关闭所有窗口 cv2.destroyAllWindows() return x, add
defservo_pwm(pin, duty, pulse):on =20 * duty / 100000
off =-on + 20 / 1000 for i in range(pulse):
GPIO.output(pin, GPIO.HIGH ) time.sleep(on) GPIO.output(pin, GPIO.LOW) time.sleep(off)
def 抓地力(角度=90):
servo_pwm(rotz, duty(angle), 100) rotx.start(duty(90)) gr.start(duty(100))
time.sleep(1) ) rotx.ChangeDutyCycle(duty(0)) time.sleep(1) gr.ChangeDutyCycle(duty(180)) time.sleep(0.5) rotx.ChangeDutyCycle(duty(90)) time.sleep(0.5)
def drop():rotx.ChangeDutyCycle(duty(180))
time.sleep(1) gr.ChangeDutyCycle(duty(100)) time.sleep(1) rotx.ChangeDutyCycle(duty(90)) time.sleep(0.5)
def done():
done =“f”
done =done.encode() blue.write(done)
try:
while True:
data =blue.readline() # data =data.decode()
打印(类型(数据),数据)#如果数据!=“s”:
打印(“没有”)#继续
否则:打印(“发现 s”)抓地力(80)
x, add =search(80, 5) drop()
done()
除了键盘中断:GPIO.cleanup() 打印(“退出”)
七。结论
在这个项目中,我们为仓库自动化实施了一个货物处理系统。机械臂从传送带上拾取物品,使用安装在其上的摄像头搜索运输车辆,将订单加载到车辆上,然后运输车辆将货物带到所需位置进行进一步处理。由于客户需求的增长和电子商务的发展,仓库自动化在大小公司中变得越来越普遍。货到人 (GTP) 是一种较新的趋势,其中货物被转移到工人手中,而不是工人到物品。根据 Bastian Solutions Inc. 的助理咨询工程师 Nathan Busch 的说法,“GTP 系统的吞吐率通常比传统的手动操作高很多。这使公司能够降低整体运营和订单履行成本,同时提高吞吐量和服务水平。”随着物品被搜索、拾取,然后被带到各自的处理地点,移动机器人现在已成为其中的关键部分。该项目的未来范围被广泛考虑用于完全自主的仓库系统,其中要储存的物品可以由另一个系统分开,并且上述系统可以将货物从输送机转移到储存机器人,这进一步发现到达所需库存位置和库存货物的最佳路径。该演示表明,为了小型企业的利益,可以部分实施上述系统;因此,结合手动和机器人操作以提高吞吐量和性能。
资料来源:仓库分销
制造工艺