-
Notifications
You must be signed in to change notification settings - Fork 0
/
photo_running_base.py
358 lines (315 loc) · 13.6 KB
/
photo_running_base.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
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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
import time
import cv2
import sys
import numpy as np
import take
#import im920sl2
import bmx055
#from other import #print_im920sl
import motor
import stuck2
import calibration
import other
import gps_running1
# 写真内の赤色面積で進時間を決める用 調整必要
area_short = 59.9
area_middle = 6
area_long = 1
def get_center(contour):
"""
輪郭の中心を取得する。
"""
# 輪郭のモーメントを計算する。
M = cv2.moments(contour)
# モーメントから重心を計算する。
if M["m00"] != 0:
cx = int(M["m10"] / M["m00"])
cy = int(M["m01"] / M["m00"])
else:
# set values as what you need in the situation
cx, cy = 0, 0
return cx, cy
def mosaic(src, ratio):
small = cv2.resize(src, None, fx=ratio, fy=ratio,
interpolation=cv2.INTER_NEAREST)
return cv2.resize(small, src.shape[:2][::-1], interpolation=cv2.INTER_NEAREST)
# def detect_red():
# img_original = cv2.imread('元画像のパス')
# img_mosaic = mosaic(img_original, ratio=0.3)
# img_hsv = cv2.cvtColor(img_mosaic, cv2.COLOR_BGR2HSV)
#
# red_min = np.array([120, 120, 100], np.uint8)
# red_max = np.array([255, 255, 255], np.uint8)
# red_img = cv2.inRange(img_hsv, red_min, red_max)
# red_img_gry = cv2.cvtColor(red_img, cv2.COLOR_GRAY2RGB)
#
# cv2.imwrite(path_detection, red_img_gry)
def goal_detection(imgpath: str, G_thd: float):
try:
img = cv2.imread(imgpath)
hig, wid, _ = img.shape
img_mosaic = mosaic(img, ratio=0.3)
img_hsv = cv2.cvtColor(img_mosaic, cv2.COLOR_BGR2HSV)
# 最小外接円を描いた写真の保存先
path_detection = other.filename(
'/home/dendenmushi/cansat2023/sequence/photo_imageguide/photo_imageguide_detected/Detected-', 'jpg')
red_min = np.array([0, 64, 0], np.uint8) #赤色検知最小値
red_max = np.array([30, 255, 255], np.uint8) #赤色検知最大値
mask1 = cv2.inRange(img_hsv, red_min, red_max)
red_min = np.array([150, 64, 0], np.uint8) #赤色検知最小値
red_max = np.array([179, 255, 255], np.uint8) #赤色検知最大値
mask2 = cv2.inRange(img_hsv, red_min, red_max)
mask = mask1 + mask2
# red_min = np.array([120, 120, 120], np.uint8) #赤色検知最小値
# red_max = np.array([255, 255, 255], np.uint8) #赤色検知最大値
# mask = cv2.inRange(img_hsv, red_min, red_max)
#red_min = np.array([0, 150, 70], np.uint8) #赤色検知最小値
#red_max = np.array([15, 255, 255], np.uint8) #赤色検知最大値
#mask = cv2.inRange(img_hsv, red_min, red_max)
#red_min = np.array([150, 64, 0], np.uint8) #赤色検知最小値
#red_max = np.array([179, 255, 255], np.uint8) #赤色検知最大値
#mask2 = cv2.inRange(img_hsv, red_min, red_max)
contours, hierarchy = cv2.findContours(
mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
max_area = 0
max_area_contour = -1
if len(contours) > 0:
radius_frame = ()
for (i, cnt) in zip(range(0, len(contours)), contours):
#print_im920sl(f'i:{i}')
print(f'i:{i}')
# 赤色検知した部分に最小外接円を書く
(x, y), radius = cv2.minEnclosingCircle(cnt)
center = (int(x), int(y))
radius = int(radius)
radius_frame = cv2.circle(img, center, radius, (0, 0, 255), 2)
#print_im920sl(radius_frame)
print(radius_frame)
# 検知した赤色の面積の中で最大のものを探す
area = cv2.contourArea(contours[i])
if max_area < area:
max_area = area
max_area_contour = i #新しく検知した時の赤色面積が元々より大きければカウント
cv2.imwrite(path_detection, radius_frame)
else:
cv2.imwrite(path_detection, img)
max_area /= hig * wid
max_area *= 100 #(赤色面積/画面全体) * 100 %
centers = get_center(contours[max_area_contour])
if max_area_contour == -1:
return (-1, 0, 1000, imgpath, path_detection)
elif max_area <= 0.1:
return (-1, max_area, 1000000, imgpath, path_detection)
elif max_area >= G_thd:
GAP = (centers[0] - wid / 2) / (wid / 2) * 100 #(重心-(画面の幅/2))/(画面の幅/2)) * 100
return (1, max_area, GAP, imgpath, path_detection)
else: # -1 < max_area <= G_thd
GAP = (centers[0] - wid / 2) / (wid / 2) * 100
return (0, max_area, GAP, imgpath, path_detection)
except:
return (1000, 1000, 1000, imgpath, path_detection)
def adjustment_mag(strength, t, magx_off, magy_off):
print("1")
magdata = bmx055.mag_dataRead()
mag_x_old = magdata[0]
mag_y_old = magdata[1]
theta_old = calibration.angle(mag_x_old, mag_y_old, magx_off, magy_off)
t_start = time.time()
while time.time() - t_start <= t:
print("4")
strength_adj = strength
magdata = bmx055.mag_dataRead()
mag_x = magdata[0]
mag_y = magdata[1]
theta = calibration.angle(mag_x, mag_y, magx_off, magy_off)
angle_relative = theta_old - theta
if angle_relative >= 0:
angle_relative = angle_relative if angle_relative <= 180 else angle_relative - 360
else:
angle_relative = angle_relative if angle_relative >= -180 else angle_relative + 360
if angle_relative >= 10:
if angle_relative <= 15:
adj = 0
elif angle_relative <= 90:
adj = strength_adj * 0.25
else:
adj = strength_adj * 0.4
#モータの出力調整
strength_l, strength_r, t_motor_output = strength_adj + adj, -(strength_adj + adj), 0.1
print("右回転しまーす笑")
elif angle_relative <= -10:
if angle_relative >= -15:
adj = 0
elif angle_relative >= -90:
adj = strength * 0.25
else:
adj = strength_adj * 0.4
#モータの出力調整
strength_l, strength_r, t_motor_output = -(strength_adj + adj), strength_adj + adj, 0.1
print("左回転しなさいっ!")
else:
#直進させる
strength_l, strength_r, t_motor_output = 30, 30, 0.5
print("直進しまっせ")
#print_im920sl(f'angle ----- {angle_relative}')
print(f'angle ----- {angle_relative}')
print("3#)")
#strength_l, strength_r = strength_adj + adj, -(strength_adj + adj)
#print_im920sl(f'motor power:\t{strength_l}\t{strength_r}')
print(f'motor power:\t{strength_l}\t{strength_r}')
motor.move(strength_l, strength_r, t_motor_output)
time.sleep(0.1)
mag_x_old = mag_x
mag_y_old = mag_y
theta_old = calibration.angle(mag_x_old, mag_y_old, magx_off, magy_off)
print("123")
strength_l, strength_r = 20, 20
motor.deceleration(strength_l, strength_r)
def image_guided_driving(log_photorunning, G_thd, magx_off, magy_off, lon2, lat2, thd_distance, t_adj_gps, gpsrun=False):
try:
t_start = time.time()
count_short_l = 0
count_short_r = 0
adj_short = 0
auto_count = 0
nogoal_count = 0
chosei = 0
while 1:
stuck2.ue_jug()
path_photo = '/home/dendenmushi/cansat2023/sequence/photo_imageguide/ImageGuide-'
photoName = take.picture(path_photo)
goalflug, goalarea, gap, imgname, imgname2 = goal_detection(
photoName, 50)
#print_im920sl(f'goalflug:{goalflug}\tgoalarea:{goalarea}%\tgap:{gap}\timagename:{imgname}\timagename2:{imgname2}')
print(f'goalflug:{goalflug}\tgoalarea:{goalarea}%\tgap:{gap}\timagename:{imgname}\timagename2:{imgname2}')
other.log(log_photorunning, t_start - time.time(),
goalflug, goalarea, gap, imgname, imgname2)
if auto_count >= 8 and goalarea >= 0.005 and goalarea != 1000 and goalflug == -1:
##赤色が見つからなかった時用に##
#print_im920sl("small red found run")
print("small red found run")
print(goalarea)
adjustment_mag(40, 1.5, magx_off, magy_off)
auto_count = 0
if goalflug == -1 or goalflug == 1000:
#print_im920sl('Nogoal detected')
print('Nogoal detected')
motor.move(30, -30, 0.1)
auto_count += 1
elif goalarea <= area_long:
auto_count = 0
if -100 <= gap and gap <= -65:
#print_im920sl('Turn left')
print('Turn left')
motor.move(-30, 30, 0.2)
elif 65 <= gap and gap <= 100:
#print_im920sl('Turn right')
print('Turn right')
motor.move(30, -30, 0.2)
else:
#print_im920sl('Go straight long')
print('Go straight long')
motor.move(30, 30, 0.3)
#adjustment_mag(40, 3, magx_off, magy_off)
elif goalarea <= area_middle:
auto_count = 0
if -100 <= gap and gap <= -65:
#print_im920sl('Turn left')
print('Turn left')
motor.move(-30, 30, 0.1)
elif 65 <= gap and gap <= 100:
#print_im920sl('Turn right')
print('Turn right')
motor.move(30, -30, 1)
else:
#print_im920sl('Go straight middle')
print('Go straight middle')
motor.move(25, 25, 0.2)
#adjustment_mag(40, 1, magx_off, magy_off)
elif goalarea <= area_short:
auto_count = 0
count_short_l = 1
count_short_r = 1
adj_short = 0
if -100 <= gap and gap <= -65:
#print_im920sl('Turn left')
print('Turn left')
if count_short_l % 4 == 0: #4の倍数ごとに出力を上げていくっ!
adj_short += 3 #モーターの出力+3
#print_im920sl('#-Power up-#')
print('#-Power up-#')
motor.move(-(20 + adj_short), 20 + adj_short, 0.2)
count_short_l += 1
elif 65 <= gap and gap <= 100:
#print_im920sl('Turn right')
print('Turn right')
if count_short_r % 4 == 0: #4の倍数ごとに出力を上げていくっ!
adj_short += 3 #モーターの出力+3
#print_im920sl('#-Power up-#')
print('#-Power up-#')
motor.move(20 + adj_short, -(20 + adj_short), 0.2)
count_short_r += 1
else:
#print_im920sl('Go stright short')
print('Go stright short')
motor.move(20, 20, 0.1)
#adjustment_mag(40, 0.6, magx_off, magy_off)
count_short_l = 0
count_short_r = 0
adj_short = 0
elif goalarea >= G_thd:
#print_im920sl('###---Goal---###')
#print_im920sl('###---Goal---###')
print("Goal")
break
# ゴールから離れた場合GPS誘導に移行
if gpsrun:
direction = calibration.calculate_direction(lon2, lat2)
goal_distance = direction['distance']
if goal_distance >= thd_distance + 2:
gps_running1.drive(lon2, lat2, thd_distance, t_adj_gps,
logpath='/home/dendenmushi/cansat2023/log/gpsrunning(image)Log', t_start=0)
except KeyboardInterrupt:
#print_im920sl('stop')
print("A")
except Exception as e:
tb = sys.exc_info()[2]
#print_im920sl("message:{0}".format(e.with_traceback(tb)))
print("B")
if __name__ == "__main__":
try:
# Initialize
#lat2 = 35.9192621
#lon2 = 139.9085065
#lat2 = 35.91818718
#lon2 = 139.90814829
#12号館前
#lat2 = 35.91896917
#lon2 = 139.90859362
#グランドのゴール前
lat2 = 35.9239389
lon2 = 139.9122408
#lat2 = 35.9243426
#lon2 = 139.9112739
#中庭の芝生
# lat2 = 35.91817415
# lon2 = 139.90825559
G_thd = 60
log_photorunning = '/home/dendenmushi/cansat2023/log/photorunning_practice.txt'
motor.setup()
# calibration
#print_im920sl('##--calibration Start--##\n')
magx_off, magy_off = calibration.cal(40,-40, 30)
#print_im920sl(f'magx_off: {magx_off}\tmagy_off: {magy_off}\n')
#print_im920sl('##--calibration end--##')
# Image Guide
image_guided_driving(log_photorunning, G_thd, magx_off,
magy_off, lon2, lat2, thd_distance=5, t_adj_gps=10)
except KeyboardInterrupt:
#print_im920sl('stop')
print('stop')
#im920sl2.off()
except Exception as e:
#im920sl2.off()
tb = sys.exc_info()[2]
#print_im920sl("message:{0}".format(e.with_traceback(tb)))