Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simulador web #1

Open
wants to merge 15 commits into
base: simulador-web
Choose a base branch
from
Open
71 changes: 30 additions & 41 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,31 +1,26 @@
# DuckieWeb
# DuckieWeb Simulador

## ¿Qué es DuckieWeb?
DuckieWeb es un proyecto que busca monitorear tanto el estado de Duckietown como de sus Duckiebots representando todos sus datos en una interfaz web que sea simple y agradable visualmente para el usuario.
DuckieWeb es un proyecto que busca monitorear el estado de Duckietown en el simulador representando todos sus datos en una interfaz web que sea simple y agradable visualmente para el usuario.

Este repositorio pretende guiar el proceso para poner en funcionamiento el monitoreo web de la ciudad Duckietown.

# Requisitos para tu PC

### [Anaconda](https://www.anaconda.com/products/individual#windows)
Anaconda es una distribución de Python que cuenta con un gestor de paquetes y un
sistema de gestión de entornos virtuales llamado Conda. Esto permite manejar distintas
versiones de softwares y librerías sin que interfieran con las demás cosas que contenga el PC de trabajo.

### [Instalar Gym-Duckietown](https://www.yumpu.com/en/document/read/65121377/guia-instalacion-duckietown)
Pasos a seguir para instalar conda y crear el enviroment de **gym-duckietown**.

### [Jekyll](https://jekyllrb.com/docs/installation/)
Jekyll sirve para montar sitios web estáticos en nuestro propio servidor local. Lo usamos para montar la web que se encuentra en este repositorio.

# Cómo empezar

La versión ROS utilizada por los duckiebots es **kinetic** por lo que en la terminal de tu bot deberás instalar esta versión de ROS Bridge mediante el comando:
```bash
sudo apt-get install ros-kinetic-rosbridge-suite
```
Esto permitirá a la interfaz escuchar los tópicos de ROS de tu duckiebot, los cuales serán publicados en el puerto 8080 de tu servidor local cuando ejecutes:
```bash
roslaunch rosbridge_server rosbridge_websocket.launch
sudo apt-get update
```
Este comando debe usarse en la terminal de tu duckiebot, procurando que roscore esté iniciado.
Una vez instalado ROS Bridge y los requisitos, hacer un pull de este repositorio en la carpeta que desees de tu PC.

```bash
git clone https://github.com/KratoSeba/duckieweb
git clone https://github.com/NicolasIsla/duckieweb-simulador.git
```

Hecho esto dirígete a la carpeta mediante la terminal y ejecuta:
Expand All @@ -38,18 +33,17 @@ Una vez corriendo el servidor local, abre [http://localhost:4000/](http://localh

# Demo

Dentro de la ruta */demo* se encuentra un archivo llamado **simulador.py** que busca simular un duckiebot local y así poder visualizar su velocidad linear y angular en tiempo real.
La idea es ejecutar **roscore** y **ROS Bridge** en el PC de igual forma como si de un Duckiebot se tratara.
Luego en la carpeta mencionada escribe:
Dentro de la ruta */demo* se encuentra un archivo llamado **simulador.py** que busca simular un duckiebot local y así poder visualizar su velocidad lineal y angular en tiempo real.

Se debe activar el enviroment de Duckietown.
```bash
python2.7 simulador.py
conda activate gym-duckietown
```
Luego dirigirse a la carpeta de Demo para activar el simulador.
```bash
python simulador.py --env-name Duckietown-udem1-v0
```
Luego puedes deslizar las barras con el programa ejecutado, si logras ver las velocidades y estas se actualizan en tiempo real, estás listo para conectar tu duckiebot.
IMPORTANTE: Asegúrate que estás visualizando localhost en la página.

### Video Demostración

<a href="http://www.youtube.com/watch?feature=player_embedded&v=Gf40fGSc_2g" target="_blank"><img src="http://i3.ytimg.com/vi/Gf40fGSc_2g/maxresdefault.jpg" align="center" target="_blank"></a>
Finalmente en la página clickear en **"Simulador"** para conectarte y **"X"** para desconectarte.

# Ideas a Futuro

Expand All @@ -68,31 +62,26 @@ Bootstrap 4 | https://getbootstrap.com/

jQuery | https://jquery.com/

ROS Kinetic | http://www.ros.org/

Jekyll | https://jekyllrb.com/

A todo el equipo de Duckietown Chile
http://duckietown.cl


## Autores del Monitoreo Web DuckieGym:

**Christopher Marin**

**Joaquín Uribe**

**Nicolás Isla**





<!-- ### Main commands

# Screenshots
| | | |
|:---:|:---:|:---:|
|<img src="http://i.imgur.com/LXSlNVK.jpg" width="275">|<img src="http://i.imgur.com/hqbhwps.jpg" width="275">|<img src="http://i.imgur.com/Z7b1PqC.jpg" width="275">|
|Language|Intro|Help|
|<img src="http://i.imgur.com/k7Y9uhB.jpg" width="275">|<img src="http://i.imgur.com/817Vuys.jpg" width="275">|<img src="http://i.imgur.com/GfKEyTE.jpg" width="275">|
|Champions|Champion's info|Champion's info 2|
|<img src="http://i.imgur.com/ZHOzTZA.jpg" width="275">|<img src="http://i.imgur.com/eYRFMlY.jpg" width="275">|<img src="http://i.imgur.com/jPTRiqJ.jpg" width="275">|
|Champion's extra|Summoner|Skin|
|<img src="http://i.imgur.com/zqq3mBO.jpg" width="275">|<img src="http://i.imgur.com/uHuBn2h.jpg" width="275">|<img src="http://i.imgur.com/ymBSpIG.jpg" width="275">|
|Sales|Match blue team|Match red team|

Screenshots reorganized by [@mathieuzen](https://github.com/mathieuzen/) -->
| https://prnt.sc/wgub9l |
| https://prnt.sc/wgubrk |

173 changes: 140 additions & 33 deletions demo/simulador.py
Original file line number Diff line number Diff line change
@@ -1,48 +1,155 @@
#!/usr/bin/env python
# manual

import cv2
import rospy #importar ros para python
from duckietown_msgs.msg import Twist2DStamped # importar mensajes de ROS tipo String y tipo Int32
"""
This script allows you to manually control the simulator or Duckiebot
using the keyboard arrows.
"""

import time
import websockets
import asyncio
import sys
import argparse
import pyglet
from pyglet.window import key
import numpy as np
import gym
import gym_duckietown
from gym_duckietown.envs import DuckietownEnv
from gym_duckietown.wrappers import UndistortWrapper

class Simulador(object):
def __init__(self, args):
super(Simulador, self).__init__()
self.args = args
self.publisher = rospy.Publisher("/duckiebot/wheels_driver_node/car_cmd", Twist2DStamped, queue_size=10)
self.twist = Twist2DStamped()

nothing = lambda x: x
# from experiments.utils import save_img

cv2.namedWindow('Simulador')
cv2.createTrackbar('Linear','Simulador',100,200,nothing)
cv2.createTrackbar('Angular','Simulador',100,200,nothing)
parser = argparse.ArgumentParser()
parser.add_argument('--env-name', default=None)
parser.add_argument('--map-name', default='udem1')
parser.add_argument('--distortion', default=False, action='store_true')
parser.add_argument('--draw-curve', action='store_true', help='draw the lane following curve')
parser.add_argument('--draw-bbox', action='store_true', help='draw collision detection bounding boxes')
parser.add_argument('--domain-rand', action='store_true', help='enable domain randomization')
parser.add_argument('--frame-skip', default=1, type=int, help='number of frames to skip')
parser.add_argument('--seed', default=1, type=int, help='seed')
args = parser.parse_args()

if args.env_name and args.env_name.find('Duckietown') != -1:
env = DuckietownEnv(
seed = args.seed,
map_name = args.map_name,
draw_curve = args.draw_curve,
draw_bbox = args.draw_bbox,
domain_rand = args.domain_rand,
frame_skip = args.frame_skip,
distortion = args.distortion,
)
else:
env = gym.make(args.env_name)

def actualizar(self):
while 1:
k = cv2.waitKey(1)
if k == 27:
break
env.reset()
env.render()

linear = cv2.getTrackbarPos('Linear','Simulador') - 100
angular = cv2.getTrackbarPos('Angular','Simulador') - 100
@env.unwrapped.window.event
def on_key_press(symbol, modifiers):
"""
This handler processes keyboard commands that
control the simulation
"""

linear = linear / 100.0
angular = angular / -12.5
if symbol == key.BACKSPACE or symbol == key.SLASH:
print('RESET')
env.reset()
env.render()
elif symbol == key.PAGEUP:
env.unwrapped.cam_angle[0] = 0
elif symbol == key.ESCAPE:
env.close()
sys.exit(0)

# Take a screenshot
# UNCOMMENT IF NEEDED - Skimage dependency
# elif symbol == key.RETURN:
# print('saving screenshot')
# img = env.render('rgb_array')
# save_img('screenshot.png', img)

self.twist.v = linear
self.twist.omega = angular

self.publisher.publish(self.twist)
# Register a keyboard handler
key_handler = key.KeyStateHandler()
env.unwrapped.window.push_handlers(key_handler)

def main():
rospy.init_node('simulador') #creacion y registro del nodo!
actionMsg = 'Connected!'
def update():
"""
This function is called at every frame to handle
movement/stepping and redrawing
"""

obj = Simulador('args') # Crea un objeto del tipo Simulador, cuya definicion se encuentra arriba
global actionMsg
action = np.array([0.0, 0.0])

obj.actualizar() #llama al metodo publicar del objeto obj de tipo Simulador
if key_handler[key.UP]:
action = np.array([0.44, 0.0])
if key_handler[key.DOWN]:
action = np.array([-0.44, 0])
if key_handler[key.LEFT]:
action = np.array([0.35, +1])
if key_handler[key.RIGHT]:
action = np.array([0.35, -1])
if key_handler[key.SPACE]:
action = np.array([0, 0])

if __name__ =='__main__':
main()
# Speed boost
if key_handler[key.LSHIFT]:
action *= 1.5

obs, reward, done, info = env.step(action)
print('step_count = %s, reward=%.3f' % (env.unwrapped.step_count, reward))

if key_handler[key.RETURN]:
from PIL import Image
im = Image.fromarray(obs)

im.save('screen.png')

lineal = str(action[0])
angular = str(action[1])
actionMsg = (lineal+","+angular)
if done:
print('done!')
env.reset()
env.render()

env.render()

##Creacion del websocket
async def connect(websocket, path):
delta_time = 1.0 / env.unwrapped.frame_rate
while keepRunning:
start = time.time()
await websocket.send(actionMsg)
spent = time.time() - start
wait = delta_time - spent
await asyncio.sleep(wait)

##funcion main del simulador
async def startSimulator():
delta_time = 1.0 / env.unwrapped.frame_rate

while keepRunning:
start = time.time()
update()
spent = time.time() - start

wait = delta_time - spent
await asyncio.sleep(wait)

loop = asyncio.get_event_loop()
keepRunning = True
start_server = websockets.serve(connect, "localhost", 8765)

##Creacion de los threads del simulador y del websocket
asyncio.ensure_future(start_server)
asyncio.ensure_future(startSimulator())

loop.run_forever()
keepRunning = False
env.close()
34 changes: 7 additions & 27 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,17 @@
<link rel="stylesheet" href="/css/bootstrap.css">
<link rel="stylesheet" href="/css/style.css">
<script src="/js/jquery-3-3-1.js"></script>
<script src="/js/ROSLIB/eventemitter2.min.js"></script>
<script src="/js/ROSLIB/roslib.min.js"></script>
<script src="/js/ros.js"></script>
<script src="/js/main.js"></script>
<script src="/js/bootstrap.js"></script>
<script src="/js/rosnt.js"></script>
</head>


<body>
<div class="container-fluid">
<div class="row">
<div id="lbar" class="width col-md-2">
<div class="row"">
<div class="row">
<div class="col-md-4">
<img id="logopato" src="/img/dtlogo.png"/>
</div>
Expand All @@ -34,37 +32,19 @@
<div class="row">
<div class="col-md-12 barral">
<h5 id="contador" class="text-md-center titulosBarra font-weight-bold">DUCKIEBOTS</h5>
<div id= "cargandoPatos" class="text-md-center">
<p>CARGANDO...</p>
</div>
<div>
<div>
<div class="row">
<ul id="listaPatos"></ul>

</div>
</div>

<hr />

<div>
<h6 class="text-md-center titulosBarra font-weight-bold">AÑADIR PATO</h6>
<form>
<div class="form-group">
<label for="nombrePato">Nombre</label>
<input type="text" class="form-control formulario" id="nombrePato" placeholder="Ingresa un nombre">
</div>
<div class="form-group">
<label for="ip">IP</label>
<input type="text" class="form-control formulario" id="ip" placeholder="Ingresa una IP">
</div>
<button id="addIP" class="btn btn-primary" type="button">Añadir</button>
</form>
</div>
</div>
</div>
</div>

<div id="contenido" class="col-md-10">
<p id="duckiebotN">Duckiebot N</p>
<p id="duckiebotN">Simulador</p>
<hr />

<div class="row">
Expand All @@ -91,7 +71,7 @@ <h6 class="text-md-center titulosBarra font-weight-bold">AÑADIR PATO</h6>
<div class="col-md-2"></div>
<div class="col-md-6 valorBruto">
<p id="quacklometers">?</p>
<p>QUACKLOMETERS</p>
<p>QUACKÓMETROS</p>
</div>
<div class="col-md-1"></div>
</div>
Expand All @@ -102,7 +82,7 @@ <h6 class="text-md-center titulosBarra font-weight-bold">AÑADIR PATO</h6>
<div class="col-md-3"></div>
<div class="col-md-6 valorBruto">
<p id="quackdianes">?</p>
<p>QUACKDIANS</p>
<p>QUACKIANES</p>
</div>
</div>
<div class="row">
Expand Down
1 change: 0 additions & 1 deletion js/ROSLIB/eventemitter2.min.js

This file was deleted.

2 changes: 0 additions & 2 deletions js/ROSLIB/roslib.min.js

This file was deleted.

Loading