FPVcar

项目概况

使用的是上一个项目Ball Tracer的底盘,硬件方面基本没变。这次主要是想尝试一下用python实现socket通信。

Socket简介

Socket又称”套接字”,应用程序通常通过”套接字”向网络发出请求或者应答网络请求,使主机间或者一台计算机上的进程间可以通讯。Socket是应用层与传输层间的一个抽象层,是个编程接口。

拓展阅读:计算机网络层级

在协议组学到的一些东西。

架构

网络

电脑和树莓派连接同一个路由器,处于一个局域网内。使用ifconfig/ipconfig查看ip地址,便于后续连接的建立。

socket

使用了两个socket,socket0负责传输图像,socket1负责传输操控指令。socket0从树莓派发往PC,socket1从PC发往树莓派。都是PC做服务器,树莓派做客户端。使用的是udp传输协议,延迟更低,丢包对视频传输的影响也不大。

操控

使用键盘操控,w前进,s后退,a左转,d右转。

代码

PC端

camera.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import cv2
import numpy
import socket
import struct
HOST='192.168.1.101'
PORT=9999
buffSize=65535

server=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
server.bind((HOST,PORT))

print('now waiting for frames')
while True:
data,address=server.recvfrom(buffSize)
if len(data)==1 and data[0]==1:
server.close()
cv2.destroyAllWindows()
exit()
try:
data=bytearray(data)
print('have recevied one frame',address)
data=numpy.array(data)
imgdecode=cv2.imdecode(data,1)
cv2.imshow('frames',imgdecode)
keycode=cv2.waitKey(10)&0xff
if keycode==ord('q'):
break
except:
continue
server.close()
cv2.destroyAllWindows()

control.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import cv2
import socket
HOST='192.168.1.101'
PORT=8888
buffSize=65535

server=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
server.bind((HOST,PORT))

print('now waiting for connection')

background=cv2.imread('background.jpg')

while True:
data,address=server.recvfrom(buffSize)
if len(data)==1 and data[0]==1:
server.close()
exit()
if data==b'hello':
print('start',address)

while True:
cv2.imshow('background',background)
c=cv2.waitKey(100)&0xff
if c==ord('q'):
server.close()
exit()
c=chr(c)
server.sendto(c.encode('utf-8'),address)
try:

print('have recevied one msg:',data,address)

except:
continue
server.close()
exit()

树莓派

camera.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
buffSize=65535
server=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)

cap = cv2.VideoCapture(0)
while True:
ret, frame= cap.read()
frame=cv2.flip(frame,-1,dst=None)
if ret is False:
print 'f'
continue
cv2.imshow('the frame',frame)
keycode=cv2.waitKey(10)&0xff
if keycode==ord('q'):
break

ret,imgencode=cv2.imencode('.jpg',frame,[cv2.IMWRITE_JPEG_QUALITY,50])
server.sendto(imgencode,(HOST,PORT))

control.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
import socket
import time
import RPi.GPIO as GPIO
import gpiotest as gp

GPIO.setmode(GPIO.BOARD)
INT1=11
INT2=12
INT3=13
INT4=15

GPIO.setup(INT1,GPIO.OUT)
GPIO.setup(INT2,GPIO.OUT)
GPIO.setup(INT3,GPIO.OUT)
GPIO.setup(INT4,GPIO.OUT)

HOST='192.168.1.101'
PORT=8888
buffSize=65535
server=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)

server.sendto('hello',(HOST,PORT))
while True:
c,addr=server.recvfrom(buffSize)
c=c.decode('utf-8')
c=c.encode('ascii','ignore')
print(c,type(c))


if c=='w':
gp.f(0.05)
print('w'*100)
elif c==u's':
gp.b(0.05)
elif c==u'a':
gp.t_l(0.05)
elif c==u'd':
gp.t_r(0.05)
elif c==u'q':
server.close()
exit()

gpiotest.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
import cv2
import RPi.GPIO as GPIO
import time
import random

GPIO.setmode(GPIO.BOARD)

INT1=11
INT2=12
INT3=13
INT4=15

GPIO.setup(INT1,GPIO.OUT)
GPIO.setup(INT2,GPIO.OUT)
GPIO.setup(INT3,GPIO.OUT)
GPIO.setup(INT4,GPIO.OUT)

def b(time_):
GPIO.output(INT2,GPIO.HIGH)
GPIO.output(INT1,GPIO.LOW)
GPIO.output(INT3,GPIO.HIGH)
GPIO.output(INT4,GPIO.LOW)
time.sleep(time_)
GPIO.output(INT1,GPIO.LOW)
GPIO.output(INT2,GPIO.LOW)
GPIO.output(INT3,GPIO.LOW)
GPIO.output(INT4,GPIO.LOW)

def f(time_):
GPIO.output(INT2,GPIO.LOW)
GPIO.output(INT1,GPIO.HIGH)
GPIO.output(INT3,GPIO.LOW)
GPIO.output(INT4,GPIO.HIGH)
time.sleep(time_)
GPIO.output(INT1,GPIO.LOW)
GPIO.output(INT2,GPIO.LOW)
GPIO.output(INT3,GPIO.LOW)
GPIO.output(INT4,GPIO.LOW)

def t_l(time_):
GPIO.output(INT2,GPIO.HIGH)
GPIO.output(INT1,GPIO.LOW)
GPIO.output(INT3,GPIO.LOW)
GPIO.output(INT4,GPIO.HIGH)
time.sleep(time_)
GPIO.output(INT1,GPIO.LOW)
GPIO.output(INT2,GPIO.LOW)
GPIO.output(INT3,GPIO.LOW)
GPIO.output(INT4,GPIO.LOW)

def t_r(time_):
GPIO.output(INT2,GPIO.LOW)
GPIO.output(INT1,GPIO.HIGH)
GPIO.output(INT3,GPIO.HIGH)
GPIO.output(INT4,GPIO.LOW)
time.sleep(time_)
GPIO.output(INT1,GPIO.LOW)
GPIO.output(INT2,GPIO.LOW)
GPIO.output(INT3,GPIO.LOW)
GPIO.output(INT4,GPIO.LOW)