martedì 17 ottobre 2023

Small docker for Golang apps

 In ufficio oramai una applicazione non puo' andare in produzione se non e' in in container...anche se e' occupa pochissimo spazio disco...il che vuol dire che si deve cercare di ottimizzare l'occupazione dello spazio disco del container

Nel Dockerfile sottostante viene utilizzato un docker con compilatore per generare un eseguibile che sara' poi copiato in un docker minimale di produzione basato su Alpine



FROM golang as builder
RUN mkdir /app
COPY . /app
WORKDIR /app
RUN https_proxy=http://proxy.toscana.it:8080 go get github.com/go-resty/resty/v2
RUN https_proxy=http://proxy.toscana.it:8080 go get github.com/sijms/go-ora/v2

RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o myapp .

FROM alpine:latest

RUN apk --no-cache add ca-certificates
WORKDIR /root
COPY --from=builder /app/myapp .

lunedì 16 ottobre 2023

NVidia su Debian 12

 Non pensavo che sarei riuscito a montare le librerie NVidia su Debian (di solito usavo Ubuntu per semplicita') ma alla fine con il passare del tempo le cose sono migliorate molto anche in Debian


Come macchina di prova ho utilizzato un Thinkpad 550 con una GeForce 940M (384 cores 1 Gb) 

Per prima cosa si devono modificare i repositories per includere contrib e non-free 

apt install nvidia-driver firmware-misc-nonfree


apt-get install freeglut3-dev build-essential libx11-dev libxmu-dev libxi-dev libgl1-mesa-glx libglu1-mesa libglu1-mesa-dev libglfw3-dev libgles2-mesa-dev

apt -y install nvidia-cuda-toolkit nvidia-cuda-dev

Per testare ho provato a compilare gli esempi delle CUDA libraries

git clone https://github.com/zchee/cuda-sample.git

Per compilare gli esempi si deve modificare il Makefile presente in ogni directory modificando 

CUDA_PATH?=/usr

ed eliminando in SMS ?= tutti i valori ad esclusione di 50 e 52 (20 e 30 sono considerati obsoleti e non compilano piu', i restanti sono indicati come  deprecati)

Si lancia quindi il make aggiungendo prima la GLPATH

GLPATH=/usr/lib make

Il problema finale e' stato che gli esempi che usano le OpenGL non riuscivano ad aprirsi mostrando l'errore code=46(cudaErrorDevicesUnavailable) 

La soluzione e' quella di far precedere al comando le indicazioni

 __NV_PRIME_RENDER_OFFLOAD=1 __GLX_VENDOR_LIBRARY_NAME=nvidia 

per lanciare Mandelbrot si usera' quindi

__NV_PRIME_RENDER_OFFLOAD=1 __GLX_VENDOR_LIBRARY_NAME=nvidia ./Mandelbrot

mercoledì 11 ottobre 2023

Proxy server e Docker

Oramai mi trovo sempre piu' spesso a litigare con il mio proxy a lavoro (telelavorando a casa questo problema nono esiste). Per effettuare il download di una immagine docker da dietro ad un proxy in Linux si deve creare il file 

sudo nano /etc/systemd/system/docker.service.d/http-proxy.conf

inserendo le impostazioni del proxy (settare le variabili di ambiente http_proxy non funziona)

[Service]
Environment="HTTP_PROXY=http://proxy.aaaaa.it:8080"
Environment="HTTPS_PROXY=http://proxy.aaaaa.toscana.it:8080"

e si riavvia il servizio 

sudo systemctl daemon-reload

sudo systemctl restart docker 

venerdì 29 settembre 2023

Olivetti M20 ST con CD sorpresa

 Mi sono comprato un Olivetti M20 perche' e' stato il primo computer (il C64 diciamo era piu' una macchina da gioco quando ero piccolo) su cui ho lavorato in un ufficio

Il modello e' un ST e deve essere una prima serie in quanto la CPU e' sotto la tastiera e le etichette di produzione indicano novembre 1982 (la presentazione della macchina e' stata Marzo 82)




Notare le correzioni fatte a mano sul PCB, simili a quelli che si trovano negli M24




Si tratta di una macchina venduta in Spagna come si vede anche dall'etichetta della manutenzione dell'unita' floppy. A proposito del drive floppy interessante vedere la calibrazione del numero di giri sul motore non a presa diretta ma tramite cinghia



ed il fatto che qualche genio ha inserito un cd rom all'interno dell'unita' floppy stesssa bloccando la meccanica (ho dovuto smontare tutto per estrarlo ma con questi computer si poteva ancora fare)


http://www.z80ne.com/m20/index.php?argument=sections/photos/luca_i/luca_i.inc

giovedì 14 settembre 2023

Europa Clipper

 In viaggio verso Giove




PS4 Stereo Camera su Linux

Visto che oramai si trovano anche a prezzi sui 20 euro ho provato la camera stereo di PS4

PS eye versione 1 e 2

Per usarla su PC si deve avere obbligatoriamente una porta USB3 e il convertitore (che costa in proporzione piu' della camera stessa ma si puo' anche autoprodurre) 


https://github.com/sieuwe1/PS4-eye-camera-for-linux-with-python-and-OpenCV

Dopo la connessione fisica deve essere modificato il firmware per usare il dispositivo come UVC



In fase di calibrazione ho avuto un errore di 0.024 con 40 immagini ed usando i file del pacchetto

Per vedere come funziona la camera ho un po' modificato il file GetDepth.py estraendo i dati di profondita' che sono contenuti nella matrice z_values

Come si vede dall'immagine sottostante c'e' una banda a sinistra che non riporta valori. Inoltre le profondita' variano da 0.3  a 2.6 m (valore massimo di profondita' restituito dal software nonostante le dimensioni della stanza siano ben maggiori)

I dati di profondita' sono molto variabili  ma se si mediano i valori accumulando le immagini (nel mio caso ho accumulato 100 immagini) l'errore si avvicina ad 1 cm

Differenza tra due mappe di profondita' consecutive



import numpy as np
import cv2
from matplotlib import pyplot as plt
import time
from datetime import datetime

#Load camera parameters
ret = np.load('param_ret.npy')
K = np.load('param_K.npy')
dist = np.load('param_dist.npy')
h,w = (800, 1264)
new_camera_matrix, roi = cv2.getOptimalNewCameraMatrix(K,dist,(w,h),1,(w,h))

mapx, mapy = cv2.initUndistortRectifyMap(K,dist, None ,new_camera_matrix,(w, h),cv2.CV_16SC2)

#cap = cv2.VideoCapture("/home/sieuwe/Desktop/vidz/full_2.avi")
#cap = cv2.VideoCapture("/home/sieuwe/Desktop/vidz/full_3.avi")
#cap = cv2.VideoCapture("/home/sieuwe/Desktop/vidz/full_1.avi")
cap = cv2.VideoCapture(2)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 3448)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 808)

kernel= np.ones((13,13),np.uint8)

#Stereo matcher settings
win_size = 5
min_disp = 10
max_disp = 16 * 2 + 10
num_disp = max_disp - min_disp # Needs to be divisible by 16
stereo = cv2.StereoSGBM_create(minDisparity= min_disp,
numDisparities = num_disp,
blockSize = 5,
uniquenessRatio = 10,
speckleWindowSize = 1000,
speckleRange = 10,
disp12MaxDiff = 25,
P1 = 8*3*win_size**2,#8*3*win_size**2,
P2 =32*3*win_size**2) #32*3*win_size**2)

sommatore=np.zeros((400,632),np.float32)
contatore = 0
limite = 100


def decode(frame):
left = np.zeros((800,1264,3), np.uint8)
right = np.zeros((800,1264,3), np.uint8)
for i in range(800):
left[i] = frame[i, 64: 1280 + 48]
right[i] = frame[i, 1280 + 48: 1280 + 48 + 1264]
return (left, right)

def get_distance(d):
return 30 * 10/d

while(1):

ret, frame = cap.read()

start = time.time()

right, left = decode(frame)

#Undistort images
#img_1_undistorted = cv2.undistort(left, K, dist, None, new_camera_matrix)
#img_2_undistorted = cv2.undistort(right, K, dist, None, new_camera_matrix)
#img_1_undistorted= cv2.remap(left,mapx,mapy, cv2.INTER_LANCZOS4, cv2.BORDER_CONSTANT, 0)
#img_2_undistorted= cv2.remap(right,mapx,mapy, cv2.INTER_LANCZOS4, cv2.BORDER_CONSTANT, 0)

#downsample image for higher speed
img_1_downsampled = cv2.pyrDown(cv2.cvtColor(left, cv2.COLOR_BGR2GRAY))
img_2_downsampled = cv2.pyrDown(cv2.cvtColor(right, cv2.COLOR_BGR2GRAY))

new_w, new_h = img_1_downsampled.shape

#compute stereo
disp = stereo.compute(img_1_downsampled,img_2_downsampled)
#denoise step 1
denoised = ((disp.astype(np.float32)/ 16)-min_disp)/num_disp
dispc= (denoised-denoised.min())*255
dispC= dispc.astype(np.uint8)
#denoise step 2
denoised= cv2.morphologyEx(dispC,cv2.MORPH_CLOSE, kernel)
#apply color map
disp_Color= cv2.applyColorMap(denoised,cv2.COLORMAP_OCEAN)
f = 0.3*w # 30cm focal length
Q = np.float32([[1, 0, 0, -0.5*new_w],
[0,-1, 0, 0.5*new_h], # turn points 180 deg around x-axis,
[0, 0, 0, f], # so that y-axis looks up
[0, 0, 1, 0]])
points = cv2.reprojectImageTo3D(disp, Q)

z_values = points[:,:,2]
print(np.size(z_values))
print(z_values.shape)
now = datetime.now()
np.save(now.strftime("%Y%m%d%H%M%S%f"),z_values)

cv2.imshow("Z",z_values)
sommatore = sommatore + z_values
contatore = contatore + 1
if (contatore == limite):
contatore = 0
sommatore = sommatore /limite
now = datetime.now()
np.save(now.strftime("%Y%m%d%H%M%S"),sommatore)
sommatore.fill(0)

z_values = z_values.flatten()
indices = z_values.argsort()

precentage = 25280
min_distance = np.mean(np.take(z_values,indices[0:precentage])) # takes the 30% lowest measuerements and gets the average distance from these.
avg_distance = np.mean(z_values) # averages all distances
max_distance = np.mean(np.take(z_values,indices[z_values.shape[0]-precentage:z_values.shape[0]])) # takes the 30% highest measuerements and gets the average distance from these.
#print(np.take(z_values,indices[z_values.shape[0]-precentage:z_values.shape[0]]))
#print(np.take(z_values,indices[:-100]))

#visualize
cv2.imshow("Depth", disp_Color)
left = cv2.resize(left,(632, 400))
color_depth = cv2.addWeighted(left,0.4,disp_Color,0.4,0)

end = time.time()
fps = 1 / (end-start)

cv2.putText(color_depth, "minimum: " + str(round(min_distance,1)),(5, 20),cv2.FONT_HERSHEY_SIMPLEX,0.5,(0,0,255),2,cv2.LINE_AA)
cv2.putText(color_depth, "average: " + str(round(avg_distance,1)),(5, 40),cv2.FONT_HERSHEY_SIMPLEX,0.5,(0,0,255),2,cv2.LINE_AA)
cv2.putText(color_depth, "maximum: " + str(round(max_distance,1)),(5, 60),cv2.FONT_HERSHEY_SIMPLEX,0.5,(0,0,255),2,cv2.LINE_AA)
cv2.putText(color_depth, "FPS: " + str(round(fps)),(5, 80),cv2.FONT_HERSHEY_SIMPLEX,0.5,(0,0,255),2,cv2.LINE_AA)

cv2.imshow("color & Depth", color_depth)

if cv2.waitKey(1) & 0xFF == ord('q'):
break

cap.release()
cv2.destroyAllWindows()







giovedì 7 settembre 2023

Esp32 idf.py

Per prima cosa un confronto tra un Espressif ESP32-S3 DevKit ed un clone cinese denominato YD-ESP32-S3..li ho comprati pensando che fossero uguali..in realta' oltre al fatto che una monta delle microUSB mentre l'altra USB-C ed il pin del led RGB e' in una GPIO38 e nell'altra in  GPIO47

Inoltre la programmazione nella Espressif e' sul connettore sinistro (UART) mentre in in YD e' sul connettore destro (UART) 




Un altro aspetto che non e' documentato (e che mi ha fatto impazzire fino a quando non ho trovato questo link) e' il led RGB non e' connesso nell YD-ESP32...si devono saldare i due pad con la scritta RGB

. ./export.sh

idf.py create-project pingo

idf.py create-project-from-example "espressif/esp-dsp:basic_math"

idf.py set-target esp32s3

idf.py build

idf.py menuconfig

idf.py -p /dev/ttyACM0 flash

per aggiungere un componente esterno ( https://components.espressif.com/components/espressif/) si puo' il comando sottostante (nello specifico la libreria iqmath)

idf.py add-dependency "espressif/iqmath^1.11.0"

il comando aggiunge solo il riferimento ma non scarica i file della libreria. Si deve lanciare

idf.py reconfigure

e si vefra' aggiungersi la directory managed_components

 
idf.py -p PORT build flash monitor
Ctrl-] per uscire dal monitor

Per effettuare il debug tramite la porta USB i cavi sono posizionati come in foto...si salta il primo pin della fila dal basso poi si inserisce GND/nero, bianco e verde e dal comando lsusb deve comparire Espressif USB JTAG/serial debug unit


Nel momento in cui si usa il cavo Jtag Usb insieme alla USB UART non si deve collegare il 5V (cavo rosso) del cavo del dubugger 

Per lo sviluppo di solo ESP32 e' conveniente usare l'estensione ESP-IDF di Visual Studio al posto di PlatformioIO

Per prima cosa si deve configurare ESP-IDF: Configure ESP-IDF extension


CTRL+E B : effettua la build del progetto

CTRL+E T : apre il terminale IDF

CTRL+E P : seleziona la porta

Per impostare la porta UART CTRL+SHIFT+P ESP-IDF:Device configuration

ESP-IDF : Select OpenOCD Board Configuration


Debugger integrato ESP32S3

Aggiornamento In realta' il Jtag USB funziona anche sui moduli cinesi Il problema risiede  nell'ID USB della porta Jtag. Nel modulo...