Visualizzazione post con etichetta Qt. Mostra tutti i post
Visualizzazione post con etichetta Qt. Mostra tutti i post

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ì 19 novembre 2020

PCL Library e Visual Studio 2019

 Per installare ed usare PCL su Windows la cosa piu' comoda e' utilizzare il pacchetto PCL-1.11.1-AllInOne-msvc2019-win64 

Una volta installato il file exe per esempio in C:\Program Files\PCL 1.11.1


Per creare un progetto in QT con le PCL si devono aggiungere nella path OpenNI2 (stranamente l'installer non la ha aggiunta nella PATH)

Ho sostituito la versione di CMAKE da quella di default di QT con l'installer di CMake  (modificabile dai Kit di Qt) ed come compilatore ho selezionato MSVC2019



il file CMAKE e' il seguente

===============================================

cmake_minimum_required(VERSION 3.5)


project(t3 LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

find_package(PCL 1.3 REQUIRED COMPONENTS common io features)
include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})


add_executable(t3 main.cpp)
target_link_libraries(t3 ${PCL_LIBRARIES})

===============================================

mentre un programma di esempio e' 
===============================================
#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>

#include <pcl/features/normal_3d.h>

using namespace std;

int main()
{
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);

     if (pcl::io::loadPCDFile<pcl::PointXYZ> ("c://gabriele.pcd", *cloud) == -1) //* load the file
     {
       PCL_ERROR ("Couldn't read file test_pcd.pcd \n");
       return (-1);
     }
     //std::cout << "Loaded " << cloud->width * cloud->height << " data points from test_pcd.pcd with the following fields: " << std::endl;
     /*for (size_t i = 0; i < cloud->points.size (); ++i)
       std::cout << "    " << cloud->points[i].x << " "    << cloud->points[i].y << " "    << cloud->points[i].z << std::endl;
    */
     // Create the normal estimation class, and pass the input dataset to it

     pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> ne;
     ne.setInputCloud (cloud);
    // Create an empty kdtree representation, and pass it to the normal estimation object.
       // Its content will be filled inside the object, based on the given input dataset (as no other search surface is given).
       pcl::search::KdTree<pcl::PointXYZ>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZ> ());
       ne.setSearchMethod (tree);

       // Output datasets
       pcl::PointCloud<pcl::Normal>::Ptr cloud_normals (new pcl::PointCloud<pcl::Normal>);

       // Use all neighbors in a sphere of radius 3cm
       ne.setRadiusSearch (0.03);

       // Compute the features
       ne.compute (*cloud_normals);

       //std::cout << endl << cloud_normals->size() << endl;


       // cloud_normals->size () should have the same size as the input cloud->size ()*

       int i = 0;
       for (pcl::Normal n : *cloud_normals) {
           //std::cerr << i << " n = " << n.normal_x << ", " << n.normal_y << ", " << n.normal_z << "\n";
           std::cout << n.normal_x << "," << n.normal_y << "," << n.normal_z << "\n";
           i++;
       }



    return 0;
}


lunedì 2 novembre 2020

Primi passi con Point Cloud Library

Con l'arrivo del sensore lidar sugli IPhone (rip Project Tango) forse e' il caso di ritirare fuori le librerie per trattare le nuvole di punti come PCL 

Per installare la liberia su Debian e' sufficiente

apt-get install libpcl-dev

che si porta dietro un po' di dipendenze come boost

I primi passi sono ovviamente quelli di inserire la libreria in un progetto. Per questo sono partito da QTCreator con le varie opzioni di Make

Compilazione con CMake

per la compilazione si devono aggiungere le righe in giallo al file CMakeLists.txt. Attenzione che in PCL le funzioni sono distribuite in vari moduli che devono essere specificati in REQUIRED COMPONENTS

cmake_minimum_required(VERSION 3.5)

project(nuvola LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

find_package(PCL 1.3 REQUIRED COMPONENTS common io features)
include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})

add_executable(nuvola main.cpp)

target_link_libraries(nuvola ${PCL_LIBRARIES})

Compilazione con QMake

Usando qmake, come prima, si devono modificare le righe in giallo.  Si deve anche specificare  c++14 

TEMPLATE = app
CONFIG += console c++14
CONFIG -= app_bundle
CONFIG -= qt
CONFIG += link_pkgconfig
PKGCONFIG += eigen3
INCLUDEPATH += /usr/include/pcl-1.11
LIBS += -L/usr/lib/x86_64-linux-gnu -lpcl_common -lpcl_io -lpcl_features -lpcl_search
QT += widgets

SOURCES += \
        main.cpp

Compilazione con Make

Per verificare quali sono gli switch di compilazione necessari per usare make si puo'usare

pkg-config --cflags --libs pcl_commons-1.7

anche in questo caso si deve ripetere l'operazione per ogni modulo utilizzato

Di seguito un semplice esempio di come leggere un file PCD, calcolare le normali e stampare i dati a schermo

===========================================

#include <iostream>

#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>

#include <pcl/features/normal_3d.h>

using namespace std;

int main()
{
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);

     if (pcl::io::loadPCDFile<pcl::PointXYZ> ("/home/luca/gabriele.pcd", *cloud) == -1) //* load the file
     {
       PCL_ERROR ("Couldn't read file test_pcd.pcd \n");
       return (-1);
     }
     //std::cout << "Loaded " << cloud->width * cloud->height << " data points from test_pcd.pcd with the following fields: " << std::endl;
     /*for (size_t i = 0; i < cloud->points.size (); ++i)
       std::cout << "    " << cloud->points[i].x << " "    << cloud->points[i].y << " "    << cloud->points[i].z << std::endl;
    */
     // Create the normal estimation class, and pass the input dataset to it

     pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> ne;
     ne.setInputCloud (cloud);
    // Create an empty kdtree representation, and pass it to the normal estimation object.
       // Its content will be filled inside the object, based on the given input dataset (as no other search surface is given).
       pcl::search::KdTree<pcl::PointXYZ>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZ> ());
       ne.setSearchMethod (tree);

       // Output datasets
       pcl::PointCloud<pcl::Normal>::Ptr cloud_normals (new pcl::PointCloud<pcl::Normal>);

       // Use all neighbors in a sphere of radius 3cm
       ne.setRadiusSearch (0.03);

       // Compute the features
       ne.compute (*cloud_normals);

       //std::cout << endl << cloud_normals->size() << endl;


       // cloud_normals->size () should have the same size as the input cloud->size ()*

       int i = 0;
       for (pcl::Normal n : *cloud_normals) {
           //std::cerr << i << " n = " << n.normal_x << ", " << n.normal_y << ", " << n.normal_z << "\n";
           std::cout << n.normal_x << "," << n.normal_y << "," << n.normal_z << "\n";
           i++;
       }



    return 0;
}




domenica 19 aprile 2020

QTCustomPlot da dati CSV

Un progettino semplice per graficare dati derivanti da un file CSV (si tratta di un progetto satellite di un progetto Android con cui, tramite applicazione, vengono salvati i dati di accelerazione)



Come libreria per plottare i dati ho usato QTCustomPlot per la semplicita' di zoom/pan mentre per la lettura di CSV e' stata impiegata QtCSV

Il codice e' disponibile su GitHub. E' possibile zoom/pan ed avere le coordinate del puntatore

Per impostare QTCustomPlot su QtCreator si devono imporate i file qtcustomplot.cpp/ qtcustomplot.h, si aggiunge al file .pro  QT += printsupport, si trascina sul form un QWidget, tasto destro Promote To e si fa il promote a QtCustomPlot (il metodo e' cambiato rispetto al precedente post https://debiaonoldcomputers.blogspot.com/2013/11/software-per-progetto-force-gauge.html)

======================================================
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "qcustomplot.h"

#include "variantdata.h"
#include "reader.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    QString filePath = "/home/luca/ss/7.csv";

    QList<QStringList> readData = QtCSV::Reader::readToList(filePath,";");

    QVector<double> x(readData.size()), y(readData.size());

    //l.resize(readData.size());

  for ( int i = 0; i < readData.size(); ++i )
  {
      x[i] = readData.at(i).value(1).toDouble()-1587149254484;
      y[i] = readData.at(i).value(2).toDouble();

  }
   //Abilita Drag e Zoom
    ui->customPlot->setInteraction(QCP::iRangeDrag,true);
    ui->customPlot->setInteraction(QCP::iRangeZoom,true);


    ui->customPlot->addGraph();
    ui->customPlot->graph(0)->setData(x,y);
    ui->customPlot->graph(0)->setBrush(QBrush(QColor(0, 0, 255, 20)));
    ui->customPlot->graph(0)->setPen(QPen(Qt::blue));
    connect(ui->customPlot,SIGNAL(mousePress(QMouseEvent *)),SLOT (clickedGraph(QMouseEvent*)));
    connect(ui->customPlot,SIGNAL(mouseMove(QMouseEvent *)),SLOT (MouseGraph(QMouseEvent*)));

    ui->customPlot->addGraph();

    ui->customPlot->xAxis->setLabel("Time");
    ui->customPlot->yAxis->setLabel("Acc");

    //double x_min = *std::min_element(x.constBegin(), x.constEnd());
    //double x_max = *std::max_element(x.constBegin(), x.constEnd());
    //double y_min = *std::min_element(y.constBegin(), y.constEnd());
    //double y_max = *std::max_element(y.constBegin(), y.constEnd());
    //ui->customPlot->xAxis->setRange(x_min, x_max);
    //ui->customPlot->yAxis->setRange(y_min, y_max);

    ui->customPlot->rescaleAxes();
    ui->customPlot->replot();
    //qDebug() << ui->customPlot->xAxis->pixelToCoord(mouseEvent->pos().x()) << ui->customPlot->yAxis->pixelToCoord(mouseEvent->pos().y());
}

void MainWindow::clickedGraph(QMouseEvent *event)
{
    QPoint point = event->pos();
    qDebug() << ui->customPlot->xAxis->pixelToCoord(point.x());
    qDebug() << ui->customPlot->yAxis->pixelToCoord(point.y());

}

void MainWindow::MouseGraph(QMouseEvent *event)
{
    QPoint point = event->pos();
    qDebug() << ui->customPlot->xAxis->pixelToCoord(point.x());
    qDebug() << ui->customPlot->yAxis->pixelToCoord(point.y());

    QVariant xi = ui->customPlot->xAxis->pixelToCoord(point.x());
    QVariant yi = ui->customPlot->yAxis->pixelToCoord(point.y());

    ui->xmouse->setText(xi.toString());
    ui->ymouse->setText(yi.toString());


}


MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_horizontalSlider_valueChanged(int value)
{
}

giovedì 21 gennaio 2016

Leggere file XML in Qt

Avevo necessita' di leggere un file xml generato da una mia applicazione mobile e dovendo scrivere un lettore multipiattaforma la mia scelta e' caduta su Qt

Questo e' il file da leggere
----------------------------
<?xml version="1.0" encoding="UTF-8"?>
<frane>
<frana id="1">
<localita>Pino Torinese</localita>
<comune>Torino</comune>
<data>19/01/2016</data>
<ora>1:45 pm</ora>
<compilatore>Luca Innocenti</compilatore>
<annotazioni></annotazioni>
<est></est>
<nord></nord>
<sistema>WGS84</sistema>
<A>4</A>
<EE>1</EE>
<H>2</H>
<ALPHA>3</ALPHA>
<F>2</F>
<V>4</V>
<M>2</M>
<codice>3/<codice>
</frana>
</frane>
----------------------------

e questo e' lo scheletro del codice Qt (piuttosto autoesplicativo). Prima si carica il file come xmlBOM e poi lo di scorre cercando le varie chiavi
Per la compilazione e' necessario aggiungere al progetto
Qt = + xml

----------------------------
#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <iostream>
#include <QtXml>
#include <QFile>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_pushButton_clicked()
{
     QDomDocument xmlBOM;
     QFile f("/Users/lucainnocenti/Triage.xml");
     if (!f.open(QIODevice::ReadOnly ))
     {
         std::cerr << "Error while loading file" << std::endl;
     }
     xmlBOM.setContent(&f);
     f.close();


     QDomElement root=xmlBOM.documentElement();
     QDomElement Component=root.firstChild().toElement();

     while(!Component.isNull())
     {
         if (Component.tagName()=="frana")
         {
           QDomElement Child=Component.firstChild().toElement();
           QString localita,comune,data,ora,compilatore;
           int A;

             while (!Child.isNull())
             {
                 // Read Name and value
                 if (Child.tagName()=="localita") localita=Child.firstChild().toText().data();
                 if (Child.tagName()=="comune") comune=Child.firstChild().toText().data();
                 if (Child.tagName()=="data") data=Child.firstChild().toText().data();
                 if (Child.tagName()=="ora") ora=Child.firstChild().toText().data();
                 if (Child.tagName()=="compilatore") compilatore=Child.firstChild().toText().data();
                 if (Child.tagName()=="A") A=Child.firstChild().toText().data().toInt();

                 Child = Child.nextSibling().toElement();
             }
             std::cout << "Localita = " << localita.toStdString().c_str() << std::endl;
             std::cout << "Comune = " << comune.toStdString().c_str() << std::endl;
             std::cout << "Data = " << data.toStdString().c_str() << std::endl;
             std::cout << "Ora = " << ora.toStdString().c_str() << std::endl;
             std::cout << "Compilatore = " << compilatore.toStdString().c_str() << std::endl;
             std::cout << "A = " << localita.toStdString().c_str() << std::endl;
             std::cout << std::endl;
             ui->label->setText(comune);
         }
         Component = Component.nextSibling().toElement();
     }
}
----------------------------

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