summaryrefslogtreecommitdiff
path: root/main.cpp
diff options
context:
space:
mode:
authorNikita Kostovsky <nikita@kostovsky.me>2025-01-12 11:50:34 +0100
committerNikita Kostovsky <nikita@kostovsky.me>2025-01-12 11:50:34 +0100
commit9dde2ab53c8e2c97647164fce89cf149260fbc8f (patch)
treef428169ce67a93d0532d91883e18892736bb26b4 /main.cpp
parent8630381c7e1fa1527026b9c823790dc3f92c6321 (diff)
implement calibration
Diffstat (limited to 'main.cpp')
-rw-r--r--main.cpp843
1 files changed, 173 insertions, 670 deletions
diff --git a/main.cpp b/main.cpp
index 9304ed9..431e82d 100644
--- a/main.cpp
+++ b/main.cpp
@@ -8,12 +8,15 @@
#include <thread>
#include "LibCamera.h"
+#include "calibration.h"
+#include "dumps.h"
#include "fuck_intel.h"
#include "genetic_algos.h"
#include "httpservice.h"
#include "imagealgos.h"
#include "pigpio.h"
#include "printerclient.h"
+#include "profile.h"
#include "rotaryencoder.h"
#include <QCoreApplication>
@@ -28,47 +31,23 @@
#include <QSerialPort>
#include <QTextStream>
#include <QTimer>
-#include <QtConcurrent/QtConcurrentRun>
+#include <QtConcurrent/QtConcurrent>
-// #define FIRST_COLUMN_ONLY
-
-#define try_apply_config() \
- if (!applyConfig(config)) \
- { \
- camera->release(); \
- cm->stop(); \
- \
- return EXIT_FAILURE; \
+#define try_apply_config() \
+ if (!applyConfig(config)) { \
+ camera->release(); \
+ cm->stop(); \
+\
+ return EXIT_FAILURE; \
}
-const QString exposureTimeKey = "exposureTime";
-const QString laserLevelKey = "laserLevel";
-
-enum ScanningModeFlags : uint8_t
-{
- None = 0,
- Calibration
-};
-
-// ScanningModeFlags operator|(ScanningModeFlags lhs, ScanningModeFlags rhs)
-// {
-// using T = std::underlying_type<ScanningModeFlags>::type;
-// return static_cast<ScanningModeFlags>(static_cast<T>(lhs) |
-// static_cast<T>(rhs));
-// }
-
ScanningModeFlags scanningModeFlags{ScanningModeFlags::None};
QElapsedTimer calibrationTimer;
extern volatile int32_t positionSteps;
-struct requested_params_t
-{
- int32_t exposureTime = {1000};
- int32_t laserLevel = {3000};
- uint32_t stepsPerMm{200};
-} requested_params;
+requested_params_t requested_params;
namespace
{
@@ -78,8 +57,6 @@ std::vector<Pixels> calibrationPixels;
QMutex calibrationPixelsMutex;
} // namespace
-const QString dumpsRoot{QStringLiteral("/home/user/dumps")};
-
using namespace std::chrono_literals;
static std::shared_ptr<libcamera::Camera> camera;
@@ -88,21 +65,10 @@ static std::map<int, std::pair<void*, unsigned int>> mappedBuffers_;
std::vector<std::unique_ptr<libcamera::Request>> requests;
libcamera::ControlList lastControls;
-static QList<Pixels> openDump(const QString& dumpPath = "");
-static std::optional<Pixels> openRawProfile(const QString& filePath);
-constexpr float hardcodedZRangeMm{175.f};
-constexpr size_t calibrationTableHeight{0x4000}; // 16384
-// img_width * calibrationTableHeight
-using CalibrationColumn = std::array<float, calibrationTableHeight>;
-using CalibrationTable = std::array<CalibrationColumn, img_width>;
-constexpr auto calibrationColumnHeight = std::tuple_size<CalibrationColumn>();
-// CalibrationTable* calibrationTable { new CalibrationTable {{ 0 }} };
-
namespace
{
-QSharedPointer<CalibrationTable> calibrationTableZ;
-QSharedPointer<CalibrationTable> calibrationTableX;
-constexpr uint16_t discretesInRage{16384};
+CalibrationTablePtr calibrationTableZ;
+CalibrationTablePtr calibrationTableX;
} // namespace
static bool applyConfig(
@@ -110,21 +76,7 @@ static bool applyConfig(
);
static void onRequestCompleted(libcamera::Request* completed_request);
static void printControls();
-static void dumpCalibrationPixels();
static QList<Pixels> filter(const QList<Pixels>& rawProfiles);
-static QSharedPointer<CalibrationTable> calibrateX(
- const QList<Pixels>& rawProfiles
-);
-static QSharedPointer<CalibrationTable> calibrateZ(
- const QList<Pixels>& rawProfiles
-);
-
-static QImage calibrationTableToImage(
- const QSharedPointer<CalibrationTable>& calibrationTable
-);
-
-static void interpolate(QSharedPointer<CalibrationTable>& table);
-static void interpolate(CalibrationColumn& column);
auto printPixels = [](const auto& pixels) {
for (size_t i = (img_width - 10) / 2;
@@ -142,24 +94,87 @@ int main(int argc, char* argv[])
{
QCoreApplication app(argc, argv);
- if (!initLaser())
- {
- return EXIT_FAILURE;
- }
-
- PrinterClient printerClient;
-
// if (false)
qDebug() << "size of raw profile" << sizeof(Pixels);
if (true)
{
- // auto rawProfiles = openDump("/home/user/dumps/2024.11.24_19.17.32");
- // auto rawProfiles = openDump("/home/user/dumps/2024.11.26_21.53.55");
- // auto rawProfiles =
- // openDump("/home/user/dumps/2024.11.26_21.53.55_small");
+ if (false) {
+ // z
+ // if (!openCalibrationTable(
+ // "/home/user/dumps/binz.calibration_table",
+ // ::calibrationTableZ
+ // ))
+ // {
+ // exit(EXIT_FAILURE);
+ // }
- {
- auto rawProfiles = openDump("/home/user/dumps/2024.12.07_14.09.33");
+ // if (!calibrationTableToImage(::calibrationTableZ)
+ // .save("/home/user/dumps/imageZ.png"))
+ // {
+ // qDebug() << "cannot save imageZ.png";
+ // exit(EXIT_FAILURE);
+ // }
+
+ // interpolate(::calibrationTableZ);
+ // exit(EXIT_SUCCESS);
+
+ // calibrationTableToImage(::calibrationTableZ)
+ // .save("/home/user/dumps/imageZ_interpolated.png");
+
+ auto rawProfiles = openDump("/home/user/dumps/binx");
+ qDebug() << "raw x-profiles count is" << rawProfiles.size();
+ // qDebug() << "height" << calibrationColumnHeight;
+
+ auto filteredRawProfiles = filter(std::move(rawProfiles));
+ qDebug() << "filtered x-profiles count is"
+ << filteredRawProfiles.count();
+
+ ::calibrationTableX = calibrateX(std::move(filteredRawProfiles));
+
+ for (size_t i = 9471; i < 9472; i++) {
+ std::cout << "row #" << i << ": ";
+
+ for (size_t j = 0; j < 1280; ++j) {
+ const auto& p = ::calibrationTableX->at(j).at(i);
+ std::cout << p << ' ';
+ }
+
+ std::cout << std::endl;
+ }
+
+ // x
+ qDebug() << "open x table";
+ if (!openCalibrationTable("/home/user/dumps/binx.calibration_table",
+ ::calibrationTableX)) {
+ exit(EXIT_FAILURE);
+ }
+
+ // if (!calibrationTableToImage(::calibrationTableX)
+ // .save("/home/user/dumps/imageX.png")) {
+ // qDebug() << "cannot save imageX.png";
+ // exit(EXIT_FAILURE);
+ // }
+
+ for (size_t i = 9471; i < 9472; i++) {
+ std::cout << "row #" << i << ": ";
+
+ for (size_t j = 0; j < 1280; ++j) {
+ const auto& p = ::calibrationTableX->at(j).at(i);
+ std::cout << p << ' ';
+ }
+
+ std::cout << std::endl;
+ }
+
+ exit(EXIT_SUCCESS);
+ interpolate(::calibrationTableX);
+
+ // calibrationTableToImage(::calibrationTableX)
+ // .save("/home/user/dumps/imageX_interpolated.png");
+ }
+
+ if (true) {
+ auto rawProfiles = openDump("/home/user/dumps/binz");
// auto rawProfiles = openDump("/home/user/dumps/z");
qDebug() << "raw z-profiles count is" << rawProfiles.size();
// qDebug() << "height" << calibrationColumnHeight;
@@ -168,26 +183,36 @@ int main(int argc, char* argv[])
qDebug() << "filtered z-profiles count is"
<< filteredRawProfiles.count();
- ::calibrationTableZ = calibrateZ(std::move(filteredRawProfiles));
+ ::calibrationTableZ = calibrateZ(std::move(filteredRawProfiles),
+ requested_params.stepsPerMm);
+ // if (!dump(
+ // ::calibrationTableZ,
+ // "/home/user/dumps/binz.calibration_table"
+ // ))
+ // {
+ // qApp->exit(EXIT_FAILURE);
+ // }
- bool ok = calibrationTableToImage(::calibrationTableZ)
- .save("/home/user/dumps/z/imageZ.png");
+ // bool ok = calibrationTableToImage(::calibrationTableZ)
+ // .save("/home/user/dumps/z/imageZ.png");
- if (!ok)
- {
- qDebug() << "cannot save imageZ.png";
- exit(EXIT_FAILURE);
- }
+ // if (!ok)
+ // {
+ // qDebug() << "cannot save imageZ.png";
+ // exit(EXIT_FAILURE);
+ // }
interpolate(::calibrationTableZ);
- calibrationTableToImage(::calibrationTableZ)
- .save("/home/user/dumps/z/imageZ_interpolated.png");
+ // calibrationTableToImage(::calibrationTableZ)
+ // .save("/home/user/dumps/z/imageZ_interpolated.png");
+ // exit(EXIT_SUCCESS);
}
- if (true)
- {
- auto rawProfiles = openDump("/home/user/dumps/2024.12.07_14.51.07");
+ qDebug() << "--------------------------------------------------------";
+
+ if (true) {
+ auto rawProfiles = openDump("/home/user/dumps/binx");
qDebug() << "raw x-profiles count is" << rawProfiles.size();
// qDebug() << "height" << calibrationColumnHeight;
@@ -197,24 +222,39 @@ int main(int argc, char* argv[])
::calibrationTableX = calibrateX(std::move(filteredRawProfiles));
- bool ok = calibrationTableToImage(::calibrationTableX)
- .save("/home/user/dumps/z/imageX.png");
+ // if (!dump(
+ // ::calibrationTableZ,
+ // "/home/user/dumps/binx.calibration_table"
+ // ))
+ // {
+ // qApp->exit(EXIT_FAILURE);
+ // }
- if (!ok)
- {
- qDebug() << "cannot save imageX.png";
- exit(EXIT_FAILURE);
- }
+ // bool ok = calibrationTableToImage(::calibrationTableX)
+ // .save("/home/user/dumps/z/imageX.png");
+
+ // if (!ok)
+ // {
+ // qDebug() << "cannot save imageX.png";
+ // exit(EXIT_FAILURE);
+ // }
interpolate(::calibrationTableX);
- calibrationTableToImage(::calibrationTableX)
- .save("/home/user/dumps/z/imageX_interpolated.png");
+ // calibrationTableToImage(::calibrationTableX)
+ // .save("/home/user/dumps/z/imageX_interpolated.png");
}
}
// exit(EXIT_SUCCESS);
+ if (!initLaser())
+ {
+ return EXIT_FAILURE;
+ }
+
+ // PrinterClient printerClient;
+
QElapsedTimer t;
t.start();
@@ -499,21 +539,31 @@ int main(int argc, char* argv[])
return QHttpServerResponse(QJsonDocument(json).toJson());
});
- qHttpServer.route(
- "/v1/commands/resetEncoder",
- [&](const QHttpServerRequest& request) -> QHttpServerResponse {
- if (request.method() != QHttpServerRequest::Method::Post)
- {
- return QHttpServerResponse::StatusCode::NotFound;
- }
+ qHttpServer.route("/v1/profile", [&]() {
+ std::lock_guard<std::mutex> lg(pgm_image_mtx);
- qDebug() << "reset encoder";
+ const Profile profile(::pixels,
+ ::calibrationTableZ,
+ ::calibrationTableX);
- positionSteps = 0;
+ const QJsonObject json{{"profile", QJsonObject(profile)}};
- return QHttpServerResponse::StatusCode::Ok;
- }
- );
+ return QHttpServerResponse(QJsonDocument(json).toJson());
+ });
+
+ qHttpServer
+ .route("/v1/commands/resetEncoder",
+ [&](const QHttpServerRequest& request) -> QHttpServerResponse {
+ if (request.method() != QHttpServerRequest::Method::Post) {
+ return QHttpServerResponse::StatusCode::NotFound;
+ }
+
+ qDebug() << "reset encoder";
+
+ positionSteps = 0;
+
+ return QHttpServerResponse::StatusCode::Ok;
+ });
qHttpServer.route(
"/v1/commands/startCalibration",
@@ -545,7 +595,7 @@ int main(int argc, char* argv[])
qDebug() << "send gCode:" << command;
- printerClient.sendCommand(command);
+ // printerClient.sendCommand(command);
return QHttpServerResponse::StatusCode::Ok;
}
@@ -563,7 +613,7 @@ int main(int argc, char* argv[])
qDebug() << "send gCode:" << command;
- printerClient.sendCommand(command);
+ // printerClient.sendCommand(command);
return QHttpServerResponse::StatusCode::Ok;
}
@@ -897,8 +947,16 @@ void onRequestCompleted(libcamera::Request* completed_request)
// qDebug() << "stop calibration mode";
scanningModeFlags = ScanningModeFlags::None;
- QFuture<void> dumpCalirationPixelsFuture =
- QtConcurrent::run(&dumpCalibrationPixels);
+ {
+ QMutexLocker l(&calibrationPixelsMutex);
+ // QFuture<void> dumpCalirationPixelsFuture
+ // = QtConcurrent::run(&dumpCalibrationPixels,
+ // calibrationPixels);
+ auto future = QtConcurrent::run([&]() {
+ dumpCalibrationPixels(
+ std::move(::calibrationPixels));
+ });
+ }
}
else
{
@@ -971,9 +1029,9 @@ void onRequestCompleted(libcamera::Request* completed_request)
auto fps{1000.f / msPerFrame};
- qDebug() << "fps ideal/real is" << configFps << "/" << fps
- << "; ms per frame is" << msPerFrame << "counted fps"
- << performanceCounter;
+ // qDebug() << "fps ideal/real is" << configFps << "/" << fps
+ // << "; ms per frame is" << msPerFrame << "counted fps"
+ // << performanceCounter;
elapsedSum = 0;
performanceCounter = 0;
@@ -1048,224 +1106,6 @@ static void printControls()
}
}
-static void dumpCalibrationPixels()
-{
- std::vector<Pixels> rawProfiles;
-
- {
- QMutexLocker l(&calibrationPixelsMutex);
- std::swap(rawProfiles, ::calibrationPixels);
- }
-
- const QString dumpSubdir{
- QDateTime::currentDateTime().toString("yyyy.MM.dd_hh.mm.ss")
- };
- const QDir dumpPath{dumpsRoot + "/" + dumpSubdir};
-
- if (!dumpPath.mkdir(dumpPath.path()))
- {
- qWarning() << "cannot create dir: " << dumpPath.path();
-
- return;
- }
-
- for (const auto& rawProfile : rawProfiles)
- {
- const auto filename =
- QLatin1String("raw_profile_meas_%1_enc_%2")
- .arg(QString::number(rawProfile.counters.measurementCounter))
- .arg(rawProfile.counters.encoderPosition);
- const auto filepath = dumpPath.path() + "/" + filename;
-
- QFile f{filepath};
-
- if (!f.open(QFile::WriteOnly))
- {
- qWarning() << "cannot open dump dump file" << f.fileName();
- qWarning() << "error is:" << f.errorString();
-
- return;
- }
-
- QJsonObject jsonCounters{
- {"timestampUs", qint64(rawProfile.counters.timestampUs)},
- {"measurementCounter",
- qint64(rawProfile.counters.measurementCounter)},
- {"encoderPosition", qint64(rawProfile.counters.encoderPosition)},
- };
-
- QJsonObject json;
-
- json["counters"] = jsonCounters;
-
- QJsonArray jsonPixels;
-
- for (const auto& pixel : rawProfile.pixels)
- {
- jsonPixels << pixel;
- }
-
- json["pixels"] = jsonPixels;
-
- if (!f.write(QJsonDocument(json).toJson()))
- {
- qWarning() << "cannot write file" << f.fileName();
- qWarning() << "error is" << f.errorString();
-
- return;
- }
-
- qDebug() << "file written: " << f.fileName();
- }
-
- qDebug() << "dump finished";
-}
-
-static QList<Pixels> openDump(const QString& dumpPath)
-{
- QString dirToRead{dumpPath};
- qDebug() << "trying to open dump path:" << dirToRead;
-
- if (dirToRead.isEmpty())
- {
- qDebug() << "dumpPath not specified. looking into" << dumpsRoot;
-
- QDir dumpsRootDir{dumpsRoot};
-
- const auto filter = QDir::Dirs | QDir::NoDotAndDotDot | QDir::Readable;
- // there is no battery in my rpi5 for now
- const auto sort = QDir::Name;
- const auto entries = dumpsRootDir.entryList(filter, sort);
-
- if (entries.isEmpty())
- {
- qWarning() << "dumps root" << dumpsRoot << "contains no dumps. "
- << "specify existing dump path";
-
- return {};
- }
-
- dirToRead = dumpsRoot + "/" + entries.last();
- }
-
- QDir dumpDir{dirToRead};
-
- const QStringList nameFilters{"*.bin"};
- const auto filter = QDir::Files;
- const auto sort = QDir::Name;
-
- auto filenames = dumpDir.entryList(filter, sort);
-
- if (filenames.isEmpty())
- {
- qDebug() << "no filenames found in" << dumpDir.path();
- return {};
- }
-
- qDebug() << "create results array" << filenames.size();
- auto resultOptionals =
- QScopedPointer(new QList<std::optional<Pixels>>(filenames.size()));
-
- QElapsedTimer t;
- t.start();
- qDebug() << "open real files";
- std::cout << "here" << std::endl;
-
- std::transform(
- std::execution::par_unseq,
- filenames.begin(),
- filenames.end(),
- resultOptionals->begin(),
- [dirToRead](const auto& filename) {
- // std::cout << '.';
- auto rawProfile = openRawProfile(dirToRead + "/" + filename);
- if (rawProfile.has_value())
- {
- QFile f(dirToRead + "/" + filename + ".bin");
- qDebug() << "save" << dirToRead + "/" + filename << "too"
- << f.fileName();
- f.open(QFile::WriteOnly);
- f.write((const char*)&rawProfile.value(), sizeof(Pixels));
- }
- return rawProfile;
- // return openRawProfile(dirToRead + "/" + filename);
- }
- );
-
- filenames.clear();
- filenames.squeeze();
-
- qDebug() << Q_FUNC_INFO << "open raw profiles: elapsed (ms)" << t.elapsed();
- // std::cout << std::endl;
-
- std::remove_if(
- std::execution::par,
- resultOptionals->begin(),
- resultOptionals->end(),
- [](auto& a) { return !a.has_value(); }
- );
-
- QList<Pixels> result(resultOptionals->size());
-
- std::transform(
- std::execution::par,
- std::make_move_iterator(resultOptionals->begin()),
- std::make_move_iterator(resultOptionals->end()),
- result.begin(),
- [](auto& p) { return p.value(); }
- );
-
- qDebug() << Q_FUNC_INFO << "elapsed (ms)" << t.elapsed();
-
- return result;
-}
-
-static std::optional<Pixels> openRawProfile(const QString& filePath)
-{
- QFile f{filePath};
-
- if (!f.open(QFile::ReadOnly))
- {
- qWarning() << "cannot open file for reading:" << f.fileName();
- qWarning() << "error string:" << f.errorString();
-
- return {};
- }
-
- // TODO: rewrite to remove manual serialization/deserialization
- const auto json = QJsonDocument::fromJson(f.readAll()).object();
- const auto jsonCounters = json["counters"].toObject();
-
- Pixels result;
- result.counters.timestampUs = jsonCounters["timestampUs"].toInteger();
- result.counters.measurementCounter =
- jsonCounters["measurementCounter"].toInteger();
- result.counters.encoderPosition =
- jsonCounters["encoderPosition"].toInteger();
-
- const auto jsonPixels = json["pixels"].toArray();
- // TODO: check json pixels count
-#ifdef FIRST_COLUMN_ONLY
- result.pixels[0] = jsonPixels.at(0).toDouble();
-#else
- std::transform(
- // std::execution::par_unseq,
- jsonPixels.constBegin(),
- jsonPixels.constEnd(),
- result.pixels.begin(),
- [](const auto& jsonPixel) { return jsonPixel.toDouble(); }
- );
-
- // for (size_t i = 0; i < jsonPixels.count() && i < result.pixels.size();
- // ++i)
- // {
- // result.pixels[i] = jsonPixels[i].toDouble();
- // }
-#endif
-
- return result;
-}
-
static QList<Pixels> filter(const QList<Pixels>& rawProfiles)
{
QList<Pixels> result;
@@ -1315,184 +1155,6 @@ static QList<Pixels> filter(const QList<Pixels>& rawProfiles)
return result;
}
-static QSharedPointer<CalibrationTable> calibrateZ(
- const QList<Pixels>& rawProfiles
-)
-{
- QSharedPointer<CalibrationTable> result{new CalibrationTable{{0}}};
-
- for (const auto& rawProfile : rawProfiles)
- {
- // std::cout << "calibration: pos is "
- // << rawProfile.counters.encoderPosition << std::endl;
- const float positionMm{
- float(rawProfile.counters.encoderPosition) /
- float(requested_params.stepsPerMm)
- };
-
- const auto& pixels = rawProfile.pixels;
- // printPixels(pixels);
- // static size_t counter { 0 };
- // qDebug() << "calibrated" << counter++;
- const float pos = rawProfile.counters.encoderPosition;
- const float divider = requested_params.stepsPerMm;
- // std::cout << pos << " " << divider << " " << pos / divider <<
- // std::endl; std::cout << std::setw(5) <<
- // rawProfile.counters.encoderPosition
- // << std::setw(5) << requested_params.stepsPerMm
- // << std::setw(8) << positionMm
- // << std::setw(8) <<
- // float(rawProfile.counters.encoderPosition) /
- // float(requested_params.stepsPerMm)
- // << ": ";
-
- for (size_t columnIdx = 0; columnIdx < pixels.size(); ++columnIdx)
- {
- const auto& pixelValue = pixels.at(columnIdx);
-
- // float[0, img_height] -> uint16_t[0, calibrationColumnHeight]
- const uint16_t discretePixelValue{
- uint16_t(pixelValue * discretesInRage / img_height)
- };
-
- Q_ASSERT_X(
- discretePixelValue > 0 &&
- discretePixelValue < calibrationColumnHeight,
- Q_FUNC_INFO,
- ("got ivalid discrete value " +
- QString::number(discretePixelValue) + ". pixelValues is " +
- QString::number(pixelValue) + ". calc result is " +
- QString::number(pixelValue * discretesInRage / img_height))
- .toStdString()
- .c_str()
- );
-
- // auto& calibrationColumn = result[columnIdx];
- auto& calibrationColumn = (*result)[columnIdx];
- calibrationColumn[discretePixelValue] = positionMm;
-
- // if (columnIdx >= ((img_width - 10) / 2) &&
- // columnIdx < img_width - ((img_width - 10) / 2))
- // {
- // std::cout << discretePixelValue << ";";
- // }
- }
-
- // std::cout << std::endl << std::flush;
- }
-
- return result;
- // TODO: try something interesting
- // return {};
-}
-
-static QSharedPointer<CalibrationTable> calibrateX(
- const QList<Pixels>& rawProfiles
-)
-{
- QSharedPointer<CalibrationTable> result{new CalibrationTable{{0}}};
-
- for (const auto& rawProfile : rawProfiles)
- {
- const auto& pixels = rawProfile.pixels;
- auto lines = pixelsToLines(rawProfile);
-
- Q_ASSERT_X(lines.count() > 2, Q_FUNC_INFO, "no lines");
-
- QList<double> xAnchors(lines.size() + 1);
-
- std::transform(
- std::execution::par_unseq,
- lines.constBegin(),
- lines.constEnd(),
- xAnchors.begin(),
- [](const auto& l) { return l.x1(); }
- );
-
- xAnchors.last() = lines.last().x2();
-
- constexpr double triangleHeightMm{5.};
- constexpr double triangleBaseMm{8.};
-
- auto nearestAnchorToX0 = std::min_element(
- std::execution::par_unseq,
- xAnchors.constBegin(),
- xAnchors.constEnd(),
- [](const auto& a, const auto& b) {
- return std::abs(a) < std::abs(b);
- }
- );
-
- int nearestAnchorToX0Idx = nearestAnchorToX0 - xAnchors.constBegin();
-
- QList<double> xAnchorsMm(xAnchors.count());
-
- for (int i = 0; i < xAnchors.size(); ++i)
- {
- xAnchorsMm[i] = (i - nearestAnchorToX0Idx) * triangleBaseMm / 2.;
- }
-
- auto xAnchorIt = xAnchors.constBegin() + 1;
- auto xAnchorMmIt = xAnchorsMm.constBegin() + 1;
-
- for (size_t columnIdx = 0; columnIdx < pixels.size(); ++columnIdx)
- {
- // skip points with to the left from left line and to the right from
- // right line
- const auto columnX = int(columnIdx) - int(img_width / 2);
- if (columnX < xAnchors.first() || columnX > xAnchors.last())
- {
- continue;
- }
-
- if (columnX > *xAnchorIt)
- {
- ++xAnchorIt;
- ++xAnchorMmIt;
- }
- const auto xLeft = *(xAnchorIt - 1);
- const auto xRight = *(xAnchorIt);
-
- if (columnX < xLeft || columnX > xRight)
- {
- if (rawProfile.counters.encoderPosition >= 0)
- {
- qWarning()
- << "x anchor not found" << xLeft << columnX << xRight;
- continue;
- }
- }
-
- const auto& pixelValue = pixels.at(columnIdx);
- const uint16_t discretePixelValue{
- uint16_t(pixelValue * discretesInRage / img_height)
- };
-
- Q_ASSERT_X(
- discretePixelValue > 0 &&
- discretePixelValue < calibrationColumnHeight,
- Q_FUNC_INFO,
- ("got ivalid discrete value " +
- QString::number(discretePixelValue) + ". pixelValues is " +
- QString::number(pixelValue) + ". calc result is " +
- QString::number(pixelValue * discretesInRage / img_height))
- .toStdString()
- .c_str()
- );
-
- const auto xLineLen = xRight - xLeft;
- const auto xLeftMm = *(xAnchorMmIt - 1);
- const auto xRelative = float(columnX - xLeft) / xLineLen;
- const auto xMmValue = xLeftMm + xRelative * (triangleBaseMm / 2.);
-
- auto& calibrationColumn = (*result)[columnIdx];
- calibrationColumn[discretePixelValue] = xMmValue;
- }
- }
-
- return result;
-}
-
bool initLaser()
{
const QLatin1String pwmChip{"pwmchip2"};
@@ -1568,162 +1230,3 @@ bool initLaser()
return true;
}
-
-static QImage calibrationTableToImage(
- const QSharedPointer<CalibrationTable>& calibrationTable
-)
-{
- QImage result(
- QSize(calibrationTable->size(), calibrationTable->at(0).size()),
- QImage::Format::Format_Indexed8
- );
-
- // QImage image(QSize(imageWidth, imageHeight), QImage::Format_Indexed8);
-
- QColor color(Qt::green);
- auto r = color.redF();
- auto g = color.greenF();
- auto b = color.blueF();
-
- for (int c = 0; c < 256; c++)
- {
- QRgb col = qRgb(int(c * r), int(c * g), int(c * b));
- result.setColor(c, col);
- }
-
- int notNull = 0;
-
- for (size_t columnIdx = 0; columnIdx < calibrationTable->size();
- ++columnIdx)
- {
- const auto& column = calibrationTable->at(columnIdx);
-
- for (size_t rowIdx = 0; rowIdx < column.size(); ++rowIdx)
- {
- // if (!qFuzzyIsNull(column.at(rowIdx)))
- // {
- // qDebug() << "here";
- // }
-
- bool hasValue = !qFuzzyIsNull(column.at(rowIdx));
-
- if (hasValue)
- {
- // qDebug() << "x/y" << columnIdx << rowIdx;
- ++notNull;
- }
-
- result.setPixel(columnIdx, rowIdx, hasValue ? 255 : 0);
- }
- }
- qDebug() << "not null count" << notNull;
-
- return result;
-}
-
-static void interpolate(QSharedPointer<CalibrationTable>& table)
-{
-#ifdef FIRST_COLUMN_ONLY
- interpolate(table->at(0));
-#else
- std::for_each(
- std::execution::par,
- table->begin(),
- table->end(),
- [](auto& column) { interpolate(column); }
- );
-#endif
-}
-
-static void interpolate(CalibrationColumn& column)
-{
- size_t counter = 0;
- // qDebug() << "AZAZA" << 0;
-
-#ifdef FIRST_COLUMN_ONLY
- {
- QFile f("/tmp/column0.csv");
- f.open(QFile::WriteOnly);
-
- for (const auto& p : column)
- {
- f.write(QString::number(p).toUtf8());
- f.write(";\n");
- }
- }
-#endif
- // qDebug() << "AZAZA" << 1;
- auto firstNonZero =
- std::find_if(column.begin(), column.end(), [](const auto& pixel) {
- return !qFuzzyIsNull(pixel);
- });
- // qDebug() << "AZAZA" << 2;
- if (firstNonZero == column.end())
- {
- return;
- }
- // qDebug() << "AZAZA" << 3;
- for (auto it = firstNonZero; it != column.cend(); ++it)
- {
- auto firstZero =
- std::find_if(it + 1, column.end(), [](const auto& pixel) {
- return qFuzzyIsNull(pixel);
- });
-
- if (firstZero == column.end())
- {
- // qDebug() << "AZAZA" << 4;
- return;
- }
-
- auto nextNonZero =
- std::find_if(firstZero + 1, column.end(), [](const auto& pixel) {
- return !qFuzzyIsNull(pixel);
- });
-
- if (nextNonZero == column.end())
- {
- // qDebug() << "AZAZA" << 5 << it - firstNonZero;
- return;
- }
-
- auto prevNonZero = firstZero - 1;
-
- auto diff = *nextNonZero - *prevNonZero;
- auto size = nextNonZero - prevNonZero;
- auto stepDiff = float(diff) / size;
-
- // qDebug) << *prevNonZero << *nextNonZero << size << stepDiff;
-
- for (auto zero = firstZero; zero < nextNonZero; ++zero)
- {
- *zero = (zero - firstZero + 1) * stepDiff;
- // qDebug() << "set zero to" << *zero;
- }
-
- it = nextNonZero;
- }
- // qDebug() << "AZAZA" << 6;
-#ifdef FIRST_COLUMN_ONLY
- {
- QFile f("/tmp/column0_filled.csv");
- if (!f.open(QFile::WriteOnly))
- {
- qDebug() << "AZAZA: cannot open file" << f.fileName();
- qDebug() << "AZAZA" << 7;
- exit(0);
- }
- else
- {
- qDebug() << "AZAZA: ok";
- }
-
- for (const auto& p : column)
- {
- f.write(QString::number(p).toUtf8());
- f.write(";\n");
- }
- }
-#endif
- // qDebug() << "AZAZA" << 8;
-}