一、服务器

(1)简单讲解

C/S结构实现控制,树莓派运行服务器,中断通过访问网页实现控制小车,使用UDP通信。其中使用多线程控制小车的自动避障功能,写的不好的地方请批评指正。

(2)代码实现

创建server.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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
from http.server import BaseHTTPRequestHandler,HTTPServer
import time
import socket
import urllib
from carCtrl import CAR
from camera_control import Camera
from threading import Thread

global loop
global direction
loop =True

class CarServer(BaseHTTPRequestHandler):

carControl = CAR()
cameraControler = Camera()
i=0

def get_host_ip(self):
'''
This method is used for getting local ip address
The car server will deploy on this ip
'''

try:
serverSocket = socket.socket(socket.AF_INET
,socket.SOCK_DGRAM)
serverSocket.connect(("192.168.0.12",80))
localIP = serverSocket.getsockname()[0]
finally:
return localIP


def do_GET(self):
'''
Define the car control GUI for client
For the first deition, it will only return direction control GUI
'''
localIP = CarServer.get_host_ip(self)

#when this GET method is called,then should init the car
self.carControl.reset()

#read control page html file from control.html
controlPageFile = open("control.html")
controlPageGUI = controlPageFile.read()
controlPageFile.close()
controlPageGUI = controlPageGUI.replace(
"requestAddress","http://"+ localIP +":9090/")
controlPageGUI = controlPageGUI.replace(
"cameraAddress","http://"+ localIP +":8080/")

self.send_response(200)
self.send_header("Content-type","text/html")
self.end_headers()
self.wfile.write(controlPageGUI.encode())



def do_POST(self):
length = int(self.headers['Content-Length'])
qs = self.rfile.read(length)
global direction
direction = 'S'
direction = qs.decode()
print(direction)

cameraDirection = ['HR','HL','VU','VD','GL','GF','GR','GU','GD','RESET']
if direction in cameraDirection:
#control camera
self.cameraControler.cameraRotation(direction)
elif direction =="Auto":
if self.i == 0:
thread = Thread(target = self.auto)
self.i = 2
if self.i == 2:
thread.start()
self.i = 1
else:
#control car move
# self.carControl.CarMove(direction)
loop = False
if self.i== 1:
stop_thread(thread)
self.i = 2
self.carControl.CarMove(direction,loop)

self.send_response(200)


def auto(self):
global loop
global direction
loop = True
while loop:
self.carControl.CarMove(direction,loop)





if __name__ == "__main__":

raspCarServer = CarServer
hostIP = raspCarServer.get_host_ip(raspCarServer)
hostPort = 9090
myServer = HTTPServer((hostIP,hostPort),raspCarServer)

print(time.asctime(),"Server Starts - %s:%s" %(hostIP,hostPort))
try:
myServer.serve_forever()
except KeyboardInterrupt:
pass

二、网页

(1)简单讲解

网页视频的框体大小设计是需要和树莓派中改的分辨率一致,不然无法铺满视频框体。
在网页中添加了点击和触摸两种操控方式,手机和电脑均可使用。不过在手机上进行点击操作时,会产生两次指令,请批评指正。

(2)代码

创建control.html

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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
<html>
<script>
function directionBtnDown(direction) {
var url = "requestAddress"
var request = new XMLHttpRequest();
request.open("POST", url);

request.send(direction)
}

function directionBtnUp() {
var url = "requestAddress"
var request = new XMLHttpRequest();
request.open("POST", url);
request.send("S")
}

</script>
<style type="text/css">
span.car {

-webkit-touch-callout:none; /*系统默认菜单被禁用*/
-webkit-user-select:none; /*webkit浏览器*/
-khtml-user-select:none; /*早期浏览器*/
-moz-user-select:none;/*火狐*/
-ms-user-select:none; /*IE10*/
user-select:none;

position: absolute;
margin-top: 30%;
height: 480px;
}

span.camera {
position: absolute;
margin-top: 5%;
margin-left: 300px;
height: 480px;
width: 640px;
background-color: blue
}

span.camera_control {
position: absolute;
margin-top: 30%;
margin-left: 950px;
height: 480px;
background-color: blue
}


button.top {
position: absolute;
height: 50px;
width: 90px;
margin-left: 100px;
}

button.left {
position: absolute;
height: 50px;
width: 90px;
margin-top: 60px;

}
button.center {
position: absolute;
height: 50px;
width: 90px;
margin-top: 60px;
margin-left: 100px;
}

button.right {
position: absolute;
height: 50px;
width: 90px;
margin-top: 60px;
margin-left: 200px;
}

button.bottom {
position: absolute;
height: 50px;
width: 90px;
margin-top: 120px;
margin-left: 100px;
}
button.bleft {
position: absolute;
height: 50px;
width: 90px;
margin-top: 180px;
}
button.bcenter {
position: absolute;
height: 50px;
width: 90px;
margin-top: 180px;
margin-left: 100px;
}
button.bright {
position: absolute;
height: 50px;
width: 90px;
margin-top: 180px;
margin-left: 200px;
}
button.bbottom {
position: absolute;
height: 50px;
width: 90px;
margin-top: 240px;
margin-left: 100px;
}
</style>

<head>
<title>control page</title>
<meta name="viewport"
content="
height = 1080px ,
width = 1920px ,
initial-scale =0.5,
minimum-scale = 0.5 ,
maximum-scale = 1.0 ,
user-scalable = "yes"
" />



</head>

<body>
<span id="car_control" class="car">
<button class="top drectionBtn" id="F" ontouchstart="directionBtnDown('F')" ontouchend="directionBtnUp()"onmousedown="directionBtnDown('F')" onmouseup="directionBtnUp()">F</button>
<button class="left drectionBtn" id="L" ontouchstart="directionBtnDown('L')" ontouchend="directionBtnUp()" onmousedown="directionBtnDown('L')" onmouseup="directionBtnUp()">L</button>
<button class="right drectionBtn" id="R" ontouchstart="directionBtnDown('R')" ontouchend="directionBtnUp()"onmousedown="directionBtnDown('R')" onmouseup="directionBtnUp()">R</button>
<button class="center drectionBtn" id="B" ontouchstart="directionBtnDown('B')" ontouchend="directionBtnUp()"onmousedown="directionBtnDown('B')" onmouseup="directionBtnUp()">B</button>
<button class="bleft drectionBtn" id="AUTO" onmousedown="directionBtnDown('Auto')">Auto</button>
<button class="bcenter drectionBtn" id="S" onmousedown="directionBtnDown('S')">Stop</button>
<button class="bright drectionBtn" id="E" onmousedown="directionBtnDown('E')">exit</button>
</span>
<span id="camera_view" class="camera">
<img id="view" src="cameraAddress?action=stream" />
</span>
<span id="camera_control" class="camera_control">
<button class="top drectionBtn" id="VU" onmousedown="directionBtnDown('VU')">Up</button>
<button class="left drectionBtn" id="HL" onmousedown="directionBtnDown('HL')">Left</button>
<button class="right drectionBtn" id="HR" onmousedown="directionBtnDown('HR')">Right</button>
<button class="center drectionBtn" id="VD" onmousedown="directionBtnDown('VD')">Down</button>
<button class="bleft drectionBtn" id="GL" onmousedown="directionBtnDown('GL')">L_pro</button>
<button class="bcenter drectionBtn" id="GF" onmousedown="directionBtnDown('GF')">F_pro</button>
<button class="bright drectionBtn" id="GR" onmousedown="directionBtnDown('GR')">R_pro</button>
<button class="bottom drectionBtn" id="GU" onmousedown="directionBtnDown('GU')">U_pro</button>
<button class="bbottom drectionBtn" id="GD" onmousedown="directionBtnDown('GD')">D_pro</button>
</span>

</body>

</html>

三、app实现思路

(1)方案——AS

使用AS自己写一个,不过可能耗时久一点,可以通过访问控制页面实现,也可以耗点力气,把功能全部集中在APP中,跳过网页进行控制。

(2)方案——MIT-APP

使用简易创建app的工具,直接嵌入一个浏览器内核,直接访问,在里面将小车的IP写成默认,每次点开即可,无需每次重复输入IP。
下附MIT-APP的链接
MIT-APP,此链接可以直接访问,后续开发需要科学上网