#include #include #include #include #include #include #include #include "QmlCustomPlot.h" #include // #include int main( int argc, char *argv[]) { // qputenv("QT_SCALE_FACTOR", "1.5"); QApplication app(argc, argv); qDebug() << qgetenv("QT_QUICK_CONTROLS_MATERIAL_VARIANT"); auto font = app.font(); // font.setPointSize(font.pointSize() / 1.5); app.setFont(font); QQmlApplicationEngine engine; qmlRegisterType("QmlCustomPlot", 1, 0, "QmlCustomPlot"); auto pixelsPlot = new QCustomPlot(); #ifdef QCUSTOMPLOT_USE_OPENGL pixelsPlot->setOpenGl(true); #endif uint32_t pixelsPacketCounter{0}; uint32_t profilePacketCounter{0}; auto profilePlot = new QCustomPlot(); #ifdef QCUSTOMPLOT_USE_OPENGL profilePlot->setOpenGl(true); #endif engine.rootContext()->setContextProperty("pixelsPlot", pixelsPlot); engine.rootContext()->setContextProperty("profilePlot", profilePlot); engine.rootContext()->setContextProperty("max_diff", 0.0); engine.rootContext()->setContextProperty("avg_diff", 0.0); engine.rootContext()->setContextProperty("median_diff", 0.0); QVector x_pixels; QVector y_pixels; QVector prev_y_profile; constexpr int img_width = 704; constexpr int img_height = 544; for (int x = -img_width / 2; x < img_width / 2; ++x) { double y = double(QRandomGenerator::global()->bounded(0, 80000)) / 100.; x_pixels << x; y_pixels << y; } prev_y_profile = y_pixels; const auto sensorRect = new QCPItemRect{pixelsPlot}; sensorRect->setPen(QPen{QColor{Qt::green}, 1}); const auto srt = QCPItemPosition::ptPlotCoords; sensorRect->topLeft->setType(srt); sensorRect->topLeft->setCoords(QPointF{-img_width / 2, img_height}); sensorRect->bottomRight->setType(srt); sensorRect->bottomRight->setCoords(QPointF{img_width / 2, 0}); sensorRect->setBrush(QColor(255, 0, 0, 18)); sensorRect->setVisible(true); sensorRect->setSelectable(false); auto pixelsGraph = pixelsPlot->addGraph(); pixelsGraph->setPen(QPen(QBrush(Qt::red), 2)); pixelsGraph->setLineStyle(QCPGraph::lsNone); pixelsGraph->setScatterStyle(QCPScatterStyle::ssDot); pixelsGraph->setData(x_pixels, y_pixels); auto profileGraph = profilePlot->addGraph(); profileGraph->setPen(QPen(QBrush(Qt::red), 2)); profileGraph->setLineStyle(QCPGraph::lsNone); profileGraph->setScatterStyle(QCPScatterStyle::ssDot); profileGraph->setData(x_pixels, y_pixels); // QNetworkRequest pixelsRequest(QUrl("http://rpi5:8081/v1/pixels")); // QNetworkRequest profileRequest(QUrl("http://rpi5:8081/v1/profile")); // QNetworkRequest pixelsRequest(QUrl("http://rpizero:8081/v1/pixels")); // QNetworkRequest profileRequest(QUrl("http://rpizero:8081/v1/profile")); // QNetworkRequest pixelsRequest(QUrl("http://radxa:8081/v1/pixels")); QNetworkRequest pixelsRequest(QUrl("http://radxa:8080/v1/pixels")); QNetworkRequest profileRequest(QUrl("http://radxa:8081/v1/profile")); auto manager = new QNetworkAccessManager(&app); QTimer pixelsAutoRestartTimer(&app); pixelsAutoRestartTimer.setInterval(500); pixelsAutoRestartTimer.setSingleShot(false); QObject::connect(&pixelsAutoRestartTimer, &QTimer::timeout, [&]() { manager->get(pixelsRequest); }); QTimer profileAutoRestartTimer(&app); profileAutoRestartTimer.setInterval(500); profileAutoRestartTimer.setSingleShot(false); QObject::connect(&profileAutoRestartTimer, &QTimer::timeout, [&]() { manager->get(profileRequest); }); QTimer fpsTimer(&app); fpsTimer.setInterval(1000); fpsTimer.setSingleShot(false); QObject::connect(&fpsTimer, &QTimer::timeout, [&]() { engine.rootContext()->setContextProperty( "pixelsPacketCounter", pixelsPacketCounter ); engine.rootContext()->setContextProperty( "profilePacketCounter", profilePacketCounter ); pixelsPacketCounter = 0; profilePacketCounter = 0; }); fpsTimer.start(); QObject::connect( manager, &QNetworkAccessManager::finished, [&](QNetworkReply* reply) { // qDebug() << "replyFinished"; // QElapsedTimer t; // t.start(); if (reply->error()) { // qDebug() << "replyFinished with error:" << reply->errorString(); // qDebug() << "url was:" << reply->request().url(); reply->deleteLater(); return; } if (reply->url().toString().endsWith("pixels")) { // qDebug() << "got pixels"; ++pixelsPacketCounter; const auto ra = reply->readAll(); const auto doc = QJsonDocument::fromJson(ra); auto json = doc.object(); auto jsonPixels = json["pixels"].toArray(); auto encoderPosition = json["encoderPosition"].toInteger(); auto measurementCounter = json["measurementCounter"].toInteger(); auto timestampUs = json["timestampUs"].toInteger(); // y_profile.clear(); // qDebug() << "pc" << jsonPixels.count() << json.isEmpty() // << doc.isObject(); // qDebug().noquote() << QString::fromUtf8(ra); qDebug() << "pixels reply size:" << ra.size(); for (int i = 0; i < jsonPixels.count(); ++i) { y_pixels[i] = jsonPixels.at(i).toDouble(); } QVector y_diff(y_pixels.count()); qreal max_diff{0.}; qreal min_diff{1000000.}; size_t max_diff_idx = 0; size_t min_diff_idx = 0; qreal avg_diff{0.}; for (size_t i = 0; i < y_pixels.count(); ++i) { y_diff[i] = y_pixels.at(i) - prev_y_profile.at(i); if (y_diff.at(i) > max_diff) { max_diff = y_diff.at(i); max_diff_idx = i; } if (y_diff.at(i) < min_diff) { min_diff = y_diff.at(i); min_diff_idx = i; } avg_diff += fabs(y_diff.at(i)); } avg_diff /= y_diff.size(); std::sort(y_diff.begin(), y_diff.end()); const auto median_diff = y_diff.at(y_diff.size() * 3 / 4); pixelsGraph->setData(x_pixels, y_pixels); auto jsonLines = json["lines"].toArray(); QList lines(jsonLines.count()); // FIXME: validate // WARNING // AHTUNG // DANGER std::transform( // std::execution::par_unseq jsonLines.cbegin(), jsonLines.cend(), lines.begin(), [](const auto &jsonLine) -> QLineF { const auto jsonPoints = jsonLine.toArray(); const auto jsonPoint0 = jsonPoints.at(0).toArray(); const auto jsonPoint1 = jsonPoints.at(1).toArray(); return {{jsonPoint0.at(0).toDouble(), jsonPoint0.at(1).toDouble()}, {jsonPoint1.at(0).toDouble(), jsonPoint1.at(1).toDouble()}}; }); // lines.append({{6,780},{38,787}}); auto pixelsCustomPlot = engine.rootObjects().first()->findChild( "pixelsCustomPlot"); if (!pixelsCustomPlot) { qWarning() << "no pixelsCustomPlot"; } else { // qDebug() << "set lines. count is" << lines.count(); // pixelsCustomPlot->setLines(lines); } // 6 780 // 38 787 engine.rootContext()->setContextProperty("max_diff", max_diff); engine.rootContext()->setContextProperty("max_diff_idx", int(max_diff_idx)); engine.rootContext()->setContextProperty("min_diff", min_diff); engine.rootContext()->setContextProperty("min_diff_idx", int(min_diff_idx)); engine.rootContext()->setContextProperty("avg_diff", avg_diff); engine.rootContext()->setContextProperty("median_diff", median_diff); engine.rootContext()->setContextProperty("encoderPosition", encoderPosition); engine.rootContext()->setContextProperty("measurementCounter", measurementCounter); engine.rootContext()->setContextProperty("timestampUs", timestampUs); manager->get(pixelsRequest); pixelsAutoRestartTimer.start(); prev_y_profile = y_pixels; } else if (reply->url().toString().endsWith("profile")) { ++profilePacketCounter; auto json = QJsonDocument::fromJson(reply->readAll()).object(); auto jsonProfile = json["profile"].toObject(); auto jsonPointsMm = jsonProfile["pointsMm"].toArray(); QList x_profile(size_t(img_width), 0.); QList y_profile(size_t(img_width), 0.); for (int i = 0; i < jsonPointsMm.count(); ++i) { const auto x = jsonPointsMm.at(i).toArray()[0].toDouble(); const auto z = jsonPointsMm.at(i).toArray()[1].toDouble(); if (qFuzzyIsNull(z) || std::isnan(z)) { // x_profile[i] = 0; y_profile[i] = 0; continue; } x_profile[i] = x; y_profile[i] = z; } profileGraph->setData(x_profile, y_profile); // pixelsGraph->setData(x_profile, y_profile); manager->get(profileRequest); profileAutoRestartTimer.start(); } else { qDebug() << "unknown reply type"; } reply->deleteLater(); // qDebug() << "reply processed for" << t.nsecsElapsed() / 1000 << "(us)"; } ); manager->get(pixelsRequest); pixelsAutoRestartTimer.start(); manager->get(profileRequest); // profileAutoRestartTimer.start(); // auto pixelsRequestFuture = QtConcurrent::run([&](){ // QThread::sleep(1); // // x_profile.clear(); // y_profile.clear(); // for(int x = -640; x < 640; ++x) // { // double y = double(QRandomGenerator::global()->bounded(0, 80000)) / 100.; // // x_profile << x; // y_profile << y; // } // graph->setData(x_profile, y_profile); // }); QObject::connect( &engine, &QQmlApplicationEngine::objectCreationFailed, &app, []() { QCoreApplication::exit(-1); }, Qt::QueuedConnection); engine.loadFromModule("eurydice", "Main"); return app.exec(); }