husky.py
husky.py
1. xgo.py
Finalment aquest programa només contindrà les dades i funcions de base del robot.
Eliminar el que teniu i substituir-lo per aquest que he penjat a GitHub:
2. husky.py
Totes les dades i funcions relatives a la HuskyLens s'han posat en un nou programa husky.py.
Descarregar i guardar en el dispositiu micro:bit:
3. test.py
Per començar només cal afegir la importació del nou mòdul husky.py i una variable de text mode que ens servirà més endavant.
Per si d'acàs, aquesta és l'estructura bàsica inicial:
# ==== imports ====
from microbit import *
import xgo
import husky # afegir importació del nou mòdul husky.py
import radio
import music
mode = 'A' # nova variable de text. Valor inicial: A
# ==== funció principal cridada des de main.py ====
def executar():
xgo.posicio_inicial_estable() # deixa el robot en estat neutre i estable inicial
while True: # accions condicionades a la recepció de missatges de ràdio
pkt = radio.receive_full()
if pkt:
data = pkt[0]
if data and (b"XGO:C" in data):
accio_1()
elif data and (b"XGO:D" in data):
accio_2()
elif data and (b"XGO:E" in data):
accio_3()
elif data and (b"XGO:F" in data):
accio_4()
elif data and (b"XGO:STOP" in data):
return
sleep(30)
# ==== accions a executar, definides com a funcions ====
def accio_1():
music.pitch (1000, 200)
def accio_2():
music.pitch (1000, 200)
def accio_3():
music.pitch (1000, 200)
def accio_4():
music.pitch (1000, 200)
funcions en husky.py
def knock()
# serveix només per comprovar que la HuskyLens hi és i respon
# retorna: True (tot funciona) / False (alguna cosa falla)
def set_algorithm (algo)
# selecciona mode de visió:
FACE = 0x0000 # Face Recognition
TRACK = 0x0001 # Object Tracking
OBJECT = 0x0002 # Object Recognition
LINE = 0x0003 # Line Tracking
COLOR = 0x0004 # Color Recognition
TAG = 0x0005 # AprilTag Recognition
CLASSIFICATION = 0x0006 # Object Classification
a test.py:
husky.set_algorithm (husky.TRACK)
def get_block()
# serveix per preguntar a la HuskyLens si ara mateix veu alguna cosa que reconeix.
a test.py:
husky.set_algorithm (husky.ALGO_FACE) # dir què mirar (en aquest cas, mode cara)
sleep(300) # esperar
blk = husky.get_block() # preguntar què veu
Per exemple, posar mode cara i saber si veu una cara qualsevol:
husky.set_algorithm(husky.ALGO_FACE)
sleep(400)
if husky.get_block():
display.show(Image.HAPPY) # veu una cara qualsevol
else:
display.show(Image.SAD) # no veu cap cara
def learn (id_num=1)
# activa mode d'aprenentatge. Li passes un ID
learn(1) (per exemple) i aquell objecte/cara queda guardat amb ID=1
1) posar mode cara:
ok = husky.set_algorithm(husky.ALGO_FACE)
2) aprendre ID=1
ok2 = husky.learn(1)
tenir present que l'aprenentatge per codi no és persistent, s'hauria de fer cada cop que es reinicii el robot. potser millor fer-ho des de la huskylens.
def forget()
# oblida el que ha après per l’algorisme actual
a test.py:
ok = husky.set_algorithm(husky.ALGO_FACE)
ok2 = husky.forget()
#test.py . Prova 1: es reconeix la HuskyLens
En rebre C per ràdio, si el sistema detecta la husky, a la pantalla de microbit es veurà una cara sonrient. Si el que surt és una aspa, la husky no es reconeix (potser mala connexió)?
def accio_1(): # husky.knock() serveix per comprovar que la HuskyLens hi és i respon
display.show (Image.HAPPY if husky.knock() else Image.NO)
sleep (500)
display.clear()
#test.py . Prova 2: es reconeix el mode de visió en que volem que treballi la husky
En rebre D per ràdio es definirà automàticament el mode de detecció de cares (o del que volguem). Si la husky es posa en aquest mode, a la pantalla de microbit es veurà una cara sonrient. Si surt una aspa (cosa que no hauria de passar), apaga i vámonos.
def accio_2(): # husky.set_algorithm (husky.FACE) posa la husky en mode detecció de cares
ok = husky.set_algorithm (husky.FACE)
display.show (Image.HAPPY if ok() else Image.NO)
sleep (500)
display.clear()
xuleta. modes de visió:
FACE Face Recognition
TRACK Object Tracking
OBJECT Object Recognition
LINE Line Tracking
COLOR Color Recognition
TAG AprilTag Recognition
CLASSIFICATION Object Classification
#test.py . Prova 3: es reconeix una cara
Aquest és el pas on sempre ens fallava l'execució. Teòricament està solucionat en husky.py.
La idea: en rebre E per ràdio es comprovarà aquest reconeixement. Com que aquesta acció necessita executar-se durant un temps no podem associar-lo a l'esdeveniment instantani de rebuda de mjissatge per ràdio, així que farem un petit canvi a def executar ():
# ==== imports ====
from microbit import *
import xgo
import husky # afegir importació del nou mòdul husky.py
import radio
import music
mode = 'A' # nova variable de text. Valor inicial: A
# ==== funció principal cridada des de main.py ====
def executar():
global mode # cal definir com global aquesta variable per poder-la utilitzar en la funció
xgo.posicio_inicial_estable() # deixa el robot en estat neutre i estable inicial
while True: # accions condicionades a la recepció de missatges de ràdio
pkt = radio.receive_full()
if pkt:
data = pkt[0]
if data and (b"XGO:C" in data):
accio_1()
elif data and (b"XGO:D" in data):
accio_2()
elif data and (b"XGO:E" in data):
#accio_3() # l'execució d'aquesta funció ja no la definirem aqui
mode = 'E' # definim un nou valor per la variable mode
husky.set_algorithm(husky.FACE) # definim el mode visió de la husky
elif data and (b"XGO:F" in data):
accio_4()
elif data and (b"XGO:STOP" in data):
return
# farem que l'acció_3 s'executi quan estigui en mode E
if mode == 'E':
accio_3()
sleep(30)
Ara, l'acció_3, que només s'executarà en mode E, mostrarà cara sonrient si veu una cara qualsevol, i una aspa si no detecta cap cara.
Per sortir caldrà enviar missatge STOP amb el botó B del comandament:
def accio_3():
""" mode E: comprova si HuskyLens veu la cara apresa (ID1).
- Sense cara: mostra 0
- Amb cara (ID1): mostra 1, somriu i surt del mode E """
global mode # cal definir com global la variable per poder utilitzar-la en aquesta funció
b = husky.get_block() # husky.get_block() retorna el que veu
if b: # si veu una cara (qualsevol cara) ...
display.show(Image.HAPPY)
sleep(500)
music.pitch (1000, 200)
display.clear()
else:
display.show(Image.NO)
Si volem que reaccioni a la cara apresa (cal fer l'aprenentatge abans, ID1):
def accio_3():
global mode
b = husky.get_block()
if b and b.get("id", 0) == 1:
display.show(Image.HAPPY)
sleep(500)
music.pitch (1000, 200)
display.clear()
else:
display.show(Image.NO)
Acabem aquí
#test.py. Programa bàsic amb reconeixement de cara
from microbit import *
import xgo
#import radio
import music
i2c.init(freq=100000) # inicialitza I2C (HuskyLens)
xgo.set_algorithm(xgo.FACE) # posa huskylens en mode reconeixement de cares
def executar():
blk = xgo.get_block()
if blk and blk["id"] == 1: # si veu una cara i reconeix ID1 ...
music.pitch (880, 150) # confirmació
# xgo.caminar(0xA0)
# else:
# xgo.stop()
while True:
executar()
sleep(100)
Si aquest codi funciona podem fer que el robot camini en reconèixer la cara i s'aturi quan no la trobi.
GPT: com que enviem les ordes continuament pot haver “tremolors” perquè cada 100 ms el robot comprova si veu la cara correcta i decideix què fer.
Per evitar tremolors podem fer caminar només quan canvia l’estat (de parar a caminar).
Proposta:
El robot només pot estar en dos estats: aturat o caminant.
Només el farem canviar d’estat quan canvia el que veu.
from microbit import *
import xgo
i2c.init(freq=100000)
xgo.set_algorithm(xgo.FACE)
estat = "aturat" # estat inicial. possibles valors: aturat - caminant
def executar():
global estat
blk = xgo.get_block()
# CAS 1: veu la cara correcta
if blk and blk["id"] == 1:
if estat == "aturat":
xgo.caminar(0xA0)
estat = "caminant"
# CAS 2: no veu la cara correcta
else:
if estat == "caminant":
xgo.stop()
estat = "aturat"
while True:
executar()
sleep(100)
Si vull mantenir l'estructura inicial de test.py:
mode = "" # varuable buida
estat = "aturat" # estat del robot
def executar():
global mode
xgo.posicio_inicial_estable() # deixa el robot en estat neutre i estable inicial
while True: # accions condicionades a la recepció de missatges de ràdio
pkt = radio.receive_full()
if pkt:
data = pkt[0]
if data and (b"XGO:C" in data):
mode = 'C'
elif data and (b"XGO:D" in data):
mode = 'D'
elif data and (b"XGO:E" in data):
mode = 'E'
elif data and (b"XGO:F" in data):
mode = 'F'
elif data and (b"XGO:STOP" in data):
mode = 'STOP'
if mode = 'C':
accio_1()
elif mode = 'D':
accio_2()
elif mode = 'E':
accio_3()
elif mode = 'F':
accio_4()
elif mode = 'STOP':
return
sleep(30)
def accio_1():
global estat
blk = xgo.get_block()
# CAS 1: veu la cara correcta
if blk and blk["id"] == 1:
if estat == "aturat":
xgo.caminar(0xA0)
estat = "caminant"
# CAS 2: no veu la cara correcta
else:
if estat == "caminant":
xgo.stop()
estat = "aturat"
Aixó no heu feu!!!
funció per comprovar l'adreça I2C de HuskyLens (a test.py) -> La meva és 0x32
https://github.com/TecnoLogicsIB/XGO/blob/main/utilitats/I2C_scan
Definició i execució des de text.py
def escanejar_i2c():
display.show('I') # I d'I2C
addrs = i2c.scan() # llista d'adreces (DECIMAL)
if not addrs:
display.show(Image.SAD)
sleep(800)
display.clear()
return
# Mostrem la 1a adreça trobada (si n'hi ha més, les fem desfilar)
# Convertim a HEX per pantalla sèrie / debug
# A la pantalla del micro:bit fem scroll de "0x32" etc.
for a in addrs:
s = "0x{:02X}".format(a)
display.scroll(s, delay=70)
sleep(200)
# Feedback final
display.show(Image.HAPPY)
sleep(500)
display.clear()