venerdì 9 agosto 2024

Compilare RTKLib Base5 QT su Linux

La libreria RTKLib che si scarica tramite apt e' obsoleta ed anche il github originale e' in abbandono. Attualmente e' piu' interessante il fork presente in https://github.com/rtklibexplorer/RTKLIB ma distribuisce solo versioni compilate per Windows

La ricetta per compilare su Linux e' la seguente

sudo apt install qt5base-dev
sudo apt-get install libqt5serialport5 
sudo apt-get install libqt5serialport5-dev

Per prima cosa si compila prima la libreria

cd src
mkdir build & cd build
qmake ../src.pro
make

si passa quindi a compilare le applicazione da consolle e qt

Queste si trovano in  app/consapp e in app/qtapp

Per le app da console si entra nel subfolder gcc e poi si digita

make

e' disponibile il make file per bcc ed nel caso di rnx2rtkp anche il makefile per gcc_mkl (le librerie Intel di calcolo matriciale. Istruzioni qui)

Attenzione: la compilazione genera un errore in rn2rtkp.c alla linea 76 perche' non e' terminata una stringa con il carattere doppio apice. Si risolve semplicemente editando 

Per le app Qt si deve cercare il subfolder gcc e lanciare make 

mkdir build
cd build
qmake ../rtklaunch_qt.pro (si seleziona il file .pro)
make

giovedì 8 agosto 2024

M8T e Ntrip

 Ho ripreso il vecchio Ublox M8T per provare il servizio NTrip di EUREF 

 Come client Ntrip ho usato RTKNav

Le impostazioni sono riportate nell'immagine sottostante. Ho impostato l'antenna per esporre i dati Raw UBX ed ho impostato la connessione di rete con EUREF via ASI (le credenziali sono gratuite e si ottengono in un paio di giorni). Attenzione ad impostare il formato RTCM a livello 3

Soluzioni per PPP Static
 

Considerando che si tratta di un GPS singola frequenza un posizionamento realtime xy di circca +/- 20 cm non e' per niente male

RTKLib e GPS L1/L5 Pixel 6

Aggiornamento

Questo e' il migliore risultato dopo alcune prove





Visto il servizio EUREF che distribuisce dati GNSS sia in formato Rinex che NTRIP (RTCM 3) ho voluto provare ad usare la app Geo++ RINEX su un Google Pixel 6 per vedere come funziona la banda L5 in accoppiata  alla classica L1

I dati della stazione di base che ho preso a rifeirmento derivano dalla stazione

https://epncb.oma.be/_networkdata/siteinfo4onestation.php?station=IGMI00ITA

che si trova a Firenze. 

     City or Town             : Firenze
     State or Province        : TOSCANA
     Country or Region        : ITA
     Tectonic Plate           : EURASIAN
     Approximate Position (ITRF)
       X coordinate (m)       : 4523251.085
       Y coordinate (m)       : 896760.233
       Z coordinate (m)       : 4391796.488
       Latitude (N is +)      : +434744.34
       Longitude (E is +)     : +0111249.69
       Elevation (m,ellips.)  : 95.1
in Rtkpost Options/Positions si devono le coordinate ECEF della stazione riprese dalla tabella soprastante
 

i file delle osservazioni della stazione base dell'IGM vengono forniti in formato CRX e RNX 
Per utilizzare il formato CRX in RTKLIB si puo' usare il tool CRX2RNX (https://terras.gsi.go.jp/ja/crx2rnx.html) che dal file CRX porta ad un file OBS. Per quanto riguarda il file RNX basta rinominarlo (dentro c'e' il NAV in formato Rinex)
 
 Queste sono le impostazioni delle Options di RTKLib (per un corretto funzionamento ho dovuto usare i files di RTKLIB Demo5 http://rtkexplorer.com/downloads/rtklib-code/ , Le librerie RTKLib che si scaricano in APT da Debian sono obsolete e non riconoscono i nuovi formati dati ed i nuovi sensori

questo il riultato di una acquisizione speditiva

Ho provato a seguire le istruzioni https://rtklibexplorer.wordpress.com/2021/02/27/another-look-at-l1-l5-cellphone-ppk-with-rtklib/ dove l'autore scende a circa +/-10 cm di precisione m


Io non sono sceso sotto al metro

Proiezione isometrica Esercizio GoNum Golang

 Per esercizio ho provato ad implementare la proiezione isometrica in GO partendo dalle istruzioni su Wikipedia


i calcoli matriciali sono i seguenti (in questo caso e' gia' impostata una rotazione di alfa di circa 35 gradi e beta di 45 gradi





package main
import (
"fmt"
"math"
"gonum.org/v1/gonum/mat"
)
func format(matrix mat.Matrix) {
formatted := mat.Formatted(matrix, mat.Prefix(""), mat.Squeeze())
fmt.Println(formatted)
}


func isometrica(x,y,z float64) (float64,float64) {
xs := mat.NewDense(3, 3, []float64{math.Sqrt(3), 0, -math.Sqrt(3),
1, 2, 1,
math.Sqrt(2),  -math.Sqrt(2),  math.Sqrt(2)})
//format(xs)
w := mat.NewDense(3, 3,nil)
w.Scale(1/math.Sqrt(6),xs)
coordinate := mat.NewVecDense(3, []float64{x,y,z}) // e' gia' un vettore colonna
c := mat.NewVecDense(3,  make([]float64, 3))
c.MulVec(w,coordinate)
pr := mat.NewDense(3, 3, []float64{1,0,0,0,1,0,0,0,1})
d := mat.NewVecDense(3,  make([]float64, 3))
d.MulVec(pr,c)
return d.AtVec(1),d.AtVec(2)
}
func main() {
xi,yi := isometrica(0.0,0.0,0.0)
fmt.Printf("data: %f,%f\n", xi,yi)
xi,yi = isometrica(1.0,0.0,0.0)
fmt.Printf("data: %f,%f\n", xi,yi)
xi,yi = isometrica(0.0,1.0,0.0)
fmt.Printf("data: %f,%f\n", xi,yi)
xi,yi = isometrica(1.0,1.0,0.0)
fmt.Printf("data: %f,%f\n", xi,yi)
xi,yi = isometrica(0.0,0.0,2.0)
fmt.Printf("data: %f,%f\n", xi,yi)
xi,yi = isometrica(1.0,0.0,2.0)
fmt.Printf("data: %f,%f\n", xi,yi)
xi,yi = isometrica(0.0,1.0,2.0)
fmt.Printf("data: %f,%f\n", xi,yi)
xi,yi = isometrica(1.0,1.0,2.0)
fmt.Printf("data: %f,%f\n", xi,yi)

}


venerdì 26 luglio 2024

ODMNode

 Un metodo per automatizzare ODM e' quello di utilizzare NodeODM

 


 In estrema sintesi si mette in esecuzione su un server il docker con la seguente sintassi

 

 docker run -p 3000:3000 opendronemap/nodeodm

 In seguito da un client si puo' usare il seguente script Python per effettuare l'upload automatico di tutte le immagini in un folder e per impostare i parametri di lavoro. Al termine del task sul server i dati saranno reinviati in automatico al client

 

import os
import sys
sys.path.append('..')
from pprint import pprint

from pyodm import Node, exceptions

node = Node("192.168.1.125", 3000)

files = []
for dirname, dirnames, filenames in os.walk('./images/'):
for subdirname in dirnames:
files.append(os.path.join(dirname, subdirname))
for filename in filenames:
files.append(os.path.join(dirname, filename))

pprint(files)
try:
# Start a task
print("Uploading images...")
task = node.create_task(files,{'dsm': True, 'orthophoto-resolution': 4})
print(task.info())


try:
# This will block until the task is finished
# or will raise an exception
task.wait_for_completion()

print("Task completed, downloading results...")

# Retrieve results
task.download_assets("./results")

print("Assets saved in ./results (%s)" % os.listdir("./results"))

# Restart task and this time compute dtm
task.restart({'dtm': True})
task.wait_for_completion()

print("Task completed, downloading results...")

task.download_assets("./results_with_dtm")

print("Assets saved in ./results_with_dtm (%s)" % os.listdir("./results_with_dtm"))
except exceptions.TaskFailedError as e:
print("\n".join(task.output()))

except exceptions.NodeConnectionError as e:
print("Cannot connect: %s" % e)
except exceptions.NodeResponseError as e:
print("Error: %s" % e)


 

sabato 20 luglio 2024

Ciclismo antico 2

 Maglia Magniflex, cappello Gemeaz Zor preso alla partenza del Giro Italia Firenze 




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...