sabato 29 ottobre 2022

StreamDesk DIY ESP32

 Tempo fa avevo gia' fatto un sistema a pulsanti per comandare Youtube...questa volta e' la versione definitiva. Pulsantiera collegata ad un ESP32 alimentato da 4 batterie AAA che emula la tastiera





Per l'alimentazione il pacco batterie e' collegata al VIN che e' un ingresso per tensione non regolata. Attenzione, non tutte le schede ESP32 hanno VIN ed al suo posto si trova un VOut a 5 V collegato direttamente alla USB

Per rendere i collegamenti semplici i pulsanti sono collegati direttamente all'ingresso digitale dell'ESP32 utilizzando l'impostazione PULLUP nel codice




#include <BleKeyboard.h>
BleKeyboard bleKeyboard;

#define BUTTON4 4 
#define BUTTON5 5 
#define BUTTON21 21 
#define BUTTON23 23 
int lState4 = HIGH; 
int cState4;   
int lState5 = HIGH; 
int cState5;   
int lState21 = HIGH; 
int cState21;   
int lState23 = HIGH; 
int cState23;   
void setup() {
  Serial.begin(9600);
  pinMode(BUTTON4, INPUT_PULLUP);
  pinMode(BUTTON5, INPUT_PULLUP);
  pinMode(BUTTON21, INPUT_PULLUP);
  pinMode(BUTTON23, INPUT_PULLUP);
  bleKeyboard.begin();
  
}
void loop() {
  if (bleKeyboard.isConnected()) {
  // read the state of the switch/button:
  cState4 = digitalRead(BUTTON4);
  cState5 = digitalRead(BUTTON5);
  cState21 = digitalRead(BUTTON21);
  cState23 = digitalRead(BUTTON23);
  if(lState4 == LOW && cState4 == HIGH)
      {
      Serial.println("DS4");
      bleKeyboard.print("K");
      }
      
  if(lState5 == LOW && cState5 == HIGH)
      {
      Serial.println("DS5");
      bleKeyboard.print("J");
      }
  if(lState21 == LOW && cState21 == HIGH)
      {
      Serial.println("DS21");
      bleKeyboard.print("F");
      }
  if(lState23 == LOW && cState23 == HIGH)
      {
      Serial.println("DS23");
      bleKeyboard.write(KEY_LEFT_ARROW);
      }
  
  lState4 = cState4;
  lState5 = cState5;
  lState21 = cState21;
  lState23 = cState23;
  delay(10);
  }
  else
  {
    Serial.println("In attesa di connessione");
    delay(5000);
  }
}

Distanza ed angoli relativi tra due tag Aruco

 La distanza reale centro centro tra i due tags e' di 35 cm



'''
Sample Command:-
python detect_aruco_video.py --type DICT_5X5_100 --camera True
python detect_aruco_video.py --type DICT_5X5_100 --camera False --video test_video.mp4 -a 25 -k ./calibration_matrix.npy -d ./distortion_coefficients.npy
'''

from turtle import delay
import numpy as np
from utils import ARUCO_DICT, aruco_display
import argparse
import time
import cv2
import sys
import math
import time

def isRotationMatrix(R):
Rt = np.transpose(R)
shouldBeIdentity = np.dot(Rt, R)
I = np.identity(3, dtype=R.dtype)
n = np.linalg.norm(I - shouldBeIdentity)
return n < 1e-6

def rotationMatrixToEulerAngles(R):
assert (isRotationMatrix(R))

sy = math.sqrt(R[0, 0] * R[0, 0] + R[1, 0] * R[1, 0])

singular = sy < 1e-6

if not singular:
x = math.atan2(R[2, 1], R[2, 2])
y = math.atan2(-R[2, 0], sy)
z = math.atan2(R[1, 0], R[0, 0])
else:
x = math.atan2(-R[1, 2], R[1, 1])
y = math.atan2(-R[2, 0], sy)
z = 0

return np.array([x, y, z])

R_flip = np.zeros((3,3), dtype=np.float32)
R_flip[0,0] = 1.0
R_flip[1,1] =-1.0
R_flip[2,2] =-1.0

ap = argparse.ArgumentParser()
ap.add_argument("-i", "--camera", help="Set to True if using webcam")
ap.add_argument("-v", "--video", help="Path to the video file")
ap.add_argument("-t", "--type", type=str, default="DICT_ARUCO_ORIGINAL", help="Type of ArUCo tag to detect")
ap.add_argument("-k", "--K_Matrix", required=True, help="Path to calibration matrix (numpy file)")
ap.add_argument("-d", "--D_Coeff", required=True, help="Path to distortion coefficients (numpy file)")
ap.add_argument("-a", "--aruco_dim", required=True, help="ArUco tag dimension")
args = vars(ap.parse_args())


if args["camera"].lower() == "true":
video = cv2.VideoCapture(0)
time.sleep(2.0)
else:
if args["video"] is None:
print("[Error] Video file location is not provided")
sys.exit(1)

video = cv2.VideoCapture(args["video"])

if ARUCO_DICT.get(args["type"], None) is None:
print(f"ArUCo tag type '{args['type']}' is not supported")
sys.exit(0)

arucoDict = cv2.aruco.Dictionary_get(ARUCO_DICT[args["type"]])
calibration_matrix_path = args["K_Matrix"]
distortion_coefficients_path = args["D_Coeff"]
k = np.load(calibration_matrix_path)
d = np.load(distortion_coefficients_path)
arucoParams = cv2.aruco.DetectorParameters_create()

while True:
ret, frame = video.read()
time.sleep(0.05)
if ret is False:
break


h, w, _ = frame.shape

width=1000
height = int(width*(h/w))
frame = cv2.resize(frame, (width, height), interpolation=cv2.INTER_CUBIC)
corners, ids, rejected = cv2.aruco.detectMarkers(frame, arucoDict, parameters=arucoParams)

detected_markers = aruco_display(corners, ids, rejected, frame)
if len(corners) > 0:
#print(corners) #posizione degli angoli del marker
#print(len(ids))
if (len(ids) == 2):
for i in range(0, len(ids)):
rvec, tvec, markerPoints = cv2.aruco.estimatePoseSingleMarkers(corners[i], float(args["aruco_dim"]), k,d)
if (i == 0):
print("Vettore 1")
tvec0 = tvec
R_ct = np.matrix(cv2.Rodrigues(rvec)[0])
R_ct = R_ct.T
roll, pitch, yaw = rotationMatrixToEulerAngles(R_flip*R_ct)
A = ([math.cos(roll),math.cos(pitch),math.cos(yaw)])
print(tvec0)
print(A)
if (i==1):
print("Vettore 2")
tvec1 = tvec
#B = ([rvec[0][0][0],rvec[0][0][1],rvec[0][0][2]])
R_ct = np.matrix(cv2.Rodrigues(rvec)[0])
R_ct = R_ct.T
roll, pitch, yaw = rotationMatrixToEulerAngles(R_flip*R_ct)
B = ([math.cos(roll),math.cos(pitch),math.cos(yaw)])
print(tvec1)
print(B)

# primo metodo per il calcolo della distanza
tvec0_x = tvec0[0][0][0]
tvec0_y = tvec0[0][0][1]
tvec0_z = tvec0[0][0][2]
tvec1_x = tvec1[0][0][0]
tvec1_y = tvec1[0][0][1]
tvec1_z = tvec1[0][0][2]
dist1 = math.sqrt(pow((tvec0_x-tvec1_x),2)+pow((tvec0_y-tvec1_y),2)+pow((tvec0_z-tvec1_z),2))
distanza1= "Dist=%4.0f"%(dist1)
#secondo metodo per il calcolo della distanza
#
distanza= "Dist=%4.0f"%(np.linalg.norm(tvec1-tvec0))
cv2.putText(frame, distanza1,(50, 100),cv2.FONT_HERSHEY_SIMPLEX, 1,(0, 0, 255), 2, cv2.LINE_4)
dot_product = np.dot(A,B,out=None)
normA = (np.linalg.norm(A))
normB = (np.linalg.norm(B))
cos_angolo = dot_product/(normA*normB)
angolo_rad = np.arccos(cos_angolo)
angolo_deg = np.rad2deg(angolo_rad)
if (angolo_deg > 90):
angolo_deg = 180 - angolo_deg
ang = "Ang=%4.1f"%(angolo_deg)
cv2.putText(frame,ang ,(50, 150),cv2.FONT_HERSHEY_SIMPLEX, 1,(0, 0, 255), 2, cv2.LINE_4)


cv2.imshow("Image", detected_markers)
key = cv2.waitKey(1) & 0xFF
if key == ord("q"):
break

cv2.destroyAllWindows()
video.release()

mercoledì 26 ottobre 2022

Calcolo di angolo tra vettori con NumPy

Calcolo di angolo tra due vettori con numpy secondo la formuale sottostante (prodotto scalare tra i due vettori diviso il prodotto delle norme dei vettori)

https://www.wikihow.it/Calcolare-l%27Angolo-tra-Due-Vettori
https://www.wikihow.it/Calcolare-l%27Angolo-tra-Due-Vettori


import numpy as np
A = np.array([3,3])
B = np.array([2,1])
dot_product = np.dot(A,B)
normA = (np.linalg.norm(A))
normB = (np.linalg.norm(B))
cos_angolo = dot_product/(normA*normB)
angolo_rad = np.arccos(cos_angolo)
print(np.rad2deg(angolo_rad))

martedì 25 ottobre 2022

Eclisse solare 25 Ottobre

 Ovviamente giornata nuvolosa che ha permesso pochi minuti di osservazione e mai in condizioni ottimali





Eth0 su LuckFox Pico Mini A

 Le schede Luckfox Pico Mini A (a differenza delle sorelle maggiori) non hanno un connettore RJ45 e nonostante i pin da saldare non sembrano...