forked from Duckietown-Chile/capacitaciones_2020
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathemergency_stop.py
152 lines (123 loc) · 4.61 KB
/
emergency_stop.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
#!/usr/bin/env python
"""
Este programa implementa un freno de emergencia para evitar accidentes en Duckietown.
"""
import sys
import argparse
import gym
import gym_duckietown
from gym_duckietown.envs import DuckietownEnv
import numpy as np
import cv2
def mov_duckiebot(key):
# La acción de Duckiebot consiste en dos valores:
# velocidad lineal y velocidad de giro
actions = {ord('w'): np.array([1.0, 0.0]),
ord('s'): np.array([-1.0, 0.0]),
ord('a'): np.array([0.0, 1.0]),
ord('d'): np.array([0.0, -1.0]),
ord('q'): np.array([0.3, 1.0]),
ord('e'): np.array([0.3, -1.0])
}
action = actions.get(key, np.array([0.0, 0.0]))
return action
def det_duckie(obs):
### DETECTOR HECHO EN LA MISIÓN ANTERIOR
dets = list()
lower_yellow = np.array([18, 180, 160])
upper_yellow = np.array([39, 255, 255])
img_hsv = cv2.cvtColor(obs, cv2.COLOR_RGB2HSV)
mask = cv2.inRange(img_hsv, lower_yellow, upper_yellow)
img_mask = cv2.bitwise_and(obs, obs, mask = mask)
kernel = np.ones((5,5),np.uint8)
contours, hierarchy = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
for cnt in contours:
#lower_yellow = np.array([18, 180, 160])
#upper_yellow = np.array([39, 255, 255])
min_area = 4000
x, y, w, h = cv2.boundingRect(cnt)
if h*w > min_area:
x2 = x + w
y2 = y + w
# En lugar de dibujar, se agrega a la lista
dets.append((x,y,w,h))
return dets
def draw_dets(obs, dets):
for d in dets:
x1, y1 = d[0], d[1]
x2 = x1 + d[2]
y2 = y1 + d[3]
cv2.rectangle(obs, (int(x1), int(y1)), (int(x2),int(y2)), (0,255,0), 3)
return obs
def red_alert(obs):
red_img = np.zeros((480, 640, 3), dtype = np.uint8)
red_img[:,:,0] = 255
blend = cv2.addWeighted(obs, 0.5, red_img, 0.5, 0)
return blend
if __name__ == '__main__':
# Se leen los argumentos de entrada
parser = argparse.ArgumentParser()
parser.add_argument('--env-name', default="Duckietown-udem1-v1")
parser.add_argument('--map-name', default='udem1')
args = parser.parse_args()
# Definición del environment
if args.env_name and args.env_name.find('Duckietown') != -1:
env = DuckietownEnv(
map_name = args.map_name,
domain_rand = False,
)
else:
env = gym.make(args.env_name)
# Se reinicia el environment
env.reset()
# Inicialmente no hay alerta
alert = False
# Posición del pato en el mapa (fija)
duck_pos = np.array([2,0,2])
# Constante que se debe calcular
f = 790
C = f*0.08 # f * dr (f es constante, dr es conocido)
while True:
# Captura la tecla que está siendo apretada y almacena su valor en key
key = cv2.waitKey(0)
# Si la tecla es Esc, se sale del loop y termina el programa
if key == 27:
break
# Se define la acción dada la tecla presionada
action = mov_duckiebot(key)
# Si hay alerta evitar que el Duckiebot avance
if alert:
action[0]=np.minimum(0,action[0])
# Se ejecuta la acción definida anteriormente y se retorna la observación (obs),
# la evaluación (reward), etc
obs, reward, done, info = env.step(action)
# Detección de patos, retorna lista de detecciones
dets=det_duckie(obs)
# Dibuja las detecciones
draw_dets(obs, dets)
# Obtener posición del duckiebot
dbot_pos = env.cur_pos
# Calcular distancia real entre posición del duckiebot y pato
# esta distancia se utiliza para calcular la constante
dist = ((dbot_pos[0]-2)**2+(dbot_pos[2]-2)**2)**0.5
# La alerta se desactiva (opción por defecto)
alert = False
for d in dets:
# Alto de la detección en pixeles
p = d[3]
# La aproximación se calcula según la fórmula mostrada en la capacitación
d_aprox = C/p
# Muestra información relevante
print('p:', p)
print('Da:', d_aprox)
print('Dr:', dist)
# Si la distancia es muy pequeña activa alerta
if d_aprox < 0.3:
# Activar alarma
alert = True
# Muestra ventana en rojo
obs = red_alert(obs)
# Se muestra en una ventana llamada "patos" la observación del simulador
cv2.imshow('patos', cv2.cvtColor(obs, cv2.COLOR_RGB2BGR))
# Se cierra el environment y termina el programa
env.close()