diff options
| -rw-r--r-- | src/calibration.cpp | 36 | ||||
| -rw-r--r-- | src/calibration.h | 16 | ||||
| -rw-r--r-- | src/camera/veyeimx287m.cpp | 29 | ||||
| -rw-r--r-- | src/camera/veyeimx287m.h | 9 | ||||
| -rw-r--r-- | src/constants.h | 3 | ||||
| -rw-r--r-- | src/main.cpp | 111 | ||||
| -rw-r--r-- | src/profile.cpp | 4 | ||||
| -rw-r--r-- | src/protocols/httpserver.cpp | 11 | ||||
| -rw-r--r-- | src/scanner.cpp | 2 |
9 files changed, 125 insertions, 96 deletions
diff --git a/src/calibration.cpp b/src/calibration.cpp index 05aed58..41e6270 100644 --- a/src/calibration.cpp +++ b/src/calibration.cpp @@ -13,8 +13,7 @@ #include "imagealgos.h" -bool openCalibrationTable( - const QString& filename, CalibrationTablePtr& table) +bool openCalibrationTable(const QString &filename, const CalibrationTablePtr table) { QFile f(filename); @@ -25,7 +24,6 @@ bool openCalibrationTable( return false; } - table.reset(new CalibrationTable{{0}}); auto bytes = f.read((char*) table.data(), sizeof(CalibrationTable)); if (bytes != sizeof(CalibrationTable)) { @@ -73,8 +71,7 @@ bool dump( return true; } -void interpolate( - CalibrationTablePtr& table) +void interpolate(const CalibrationTablePtr table) { std::for_each(std::execution::par, table->begin(), @@ -214,8 +211,8 @@ QList<Pixels> filter( && it->counters.encoderPosition == sum.counters.encoderPosition) { sum += *it; ++count; - ++it; qDebug() << "\t\t" << __func__ << "enc pos:" << it->counters.encoderPosition; + ++it; } sum /= float(count); @@ -225,12 +222,11 @@ QList<Pixels> filter( return result; } -CalibrationTablePtr calibrateZ( - const QList<Pixels>& rawProfiles, const uint32_t& stepsPerMm) +bool calibrateZ(const QList<Pixels> &rawProfiles, + const uint32_t &stepsPerMm, + CalibrationTablePtr table) { - CalibrationTablePtr result{new CalibrationTable{{0}}}; - - for (const auto& rawProfile : rawProfiles) { + for (const auto &rawProfile : rawProfiles) { const float positionMm{float(rawProfile.counters.encoderPosition) / float(stepsPerMm)}; @@ -247,25 +243,23 @@ CalibrationTablePtr calibrateZ( << ":/tinvalid discrete value. col: " << columnIdx << ", val: " << pixelValue << std::endl; - return {}; + return false; } - auto& calibrationColumn = (*result)[columnIdx]; + auto &calibrationColumn = (*table)[columnIdx]; calibrationColumn[discretePixelValue] = positionMm; } } - return result; + return true; } -CalibrationTablePtr calibrateX( - const QList<Pixels>& rawProfiles) +bool calibrateX(const QList<Pixels> &rawProfiles, CalibrationTablePtr table) { // TODO: move to settings constexpr double triangleBaseMm{8.}; - CalibrationTablePtr result{new CalibrationTable{{0}}}; - for (const auto& rawProfile : rawProfiles) { + for (const auto &rawProfile : rawProfiles) { const auto& pixels = rawProfile.pixels; auto lines = pixelsToLines(rawProfile); @@ -342,7 +336,7 @@ CalibrationTablePtr calibrateX( std::cerr << __func__ << ":/tinvalid discrete value. col: " << columnIdx << ", val: " << pixelValue << std::endl; - return {}; + return false; } // use value interpolated between line endings (anchors) @@ -351,11 +345,11 @@ CalibrationTablePtr calibrateX( const auto xRelative = float(columnX - xLeft) / xLineLen; const auto xMmValue = xLeftMm + xRelative * (triangleBaseMm / 2.); - (*result)[columnIdx][discretePixelValue] = xMmValue; + (*table)[columnIdx][discretePixelValue] = xMmValue; } } - return result; + return true; } void dumpCalibrationPixels(const std::vector<std::shared_ptr<Pixels> > &calibrationPixels, diff --git a/src/calibration.h b/src/calibration.h index 4eee441..4876c17 100644 --- a/src/calibration.h +++ b/src/calibration.h @@ -14,7 +14,7 @@ using CalibrationTablePtr = QSharedPointer<CalibrationTable>; constexpr auto calibrationColumnHeight = std::tuple_size<CalibrationColumn>(); -bool openCalibrationTable(const QString &filename, CalibrationTablePtr &table); +bool openCalibrationTable(const QString &filename, const CalibrationTablePtr table); // void dumpCalibrationPixels(std::vector<Pixels> &&calibrationPixels); enum class DumpFormat { Json, Binary }; @@ -22,19 +22,21 @@ void dumpCalibrationPixels(const std::vector<std::shared_ptr<Pixels> > &calibrat const DumpFormat format = DumpFormat::Json); bool dump(const CalibrationTablePtr &table, const QString &filename); +// TODO: implement median filter QList<Pixels> filter(const QList<Pixels> &rawProfiles); -CalibrationTablePtr calibrateX(const QList<Pixels> &rawProfiles); -CalibrationTablePtr calibrateZ(const QList<Pixels> &rawProfiles, - const uint32_t &stepsPerMm); +bool calibrateX(const QList<Pixels> &rawProfiles, CalibrationTablePtr table); +bool calibrateZ(const QList<Pixels> &rawProfiles, + const uint32_t &stepsPerMm, + CalibrationTablePtr table); QImage calibrationTableToImage(const CalibrationTablePtr &calibrationTable); -void interpolate(CalibrationTablePtr &table); +void interpolate(const CalibrationTablePtr table); void interpolate(CalibrationColumn &column); // TODO: remove from this file namespace { -static CalibrationTablePtr calibrationTableZ; -static CalibrationTablePtr calibrationTableX; +// static CalibrationTablePtr calibrationTableZ; +// static CalibrationTablePtr calibrationTableX; } // namespace diff --git a/src/camera/veyeimx287m.cpp b/src/camera/veyeimx287m.cpp index 1d64395..0bb0724 100644 --- a/src/camera/veyeimx287m.cpp +++ b/src/camera/veyeimx287m.cpp @@ -242,6 +242,7 @@ VeyeIMX287m::~VeyeIMX287m() void VeyeIMX287m::onMoveFinished() { + qDebug() << "================================================"; qDebug() << __func__; m_isMoving = false; } @@ -647,6 +648,7 @@ void VeyeIMX287m::getFrameLoop(std::stop_token stopToken) const auto image = std::make_shared<Image>(); auto &dst = image->data; Image::copy(dst, src); + image->counters.measurementCounter = m_rawBuffers[bufferIdx].sequence; // image->rotate(); // const auto pixels = image->sharedPixels(); @@ -677,7 +679,7 @@ void VeyeIMX287m::rotateFrameLoop(std::stop_token stopToken) void VeyeIMX287m::calcPixelsLoop(std::stop_token stopToken) { - uint8_t collectedInPos{0}; + constexpr uint32_t neededCount{8}; while (!stopToken.stop_requested()) { // const auto idx = m_sync.rotSemQueue.dequeue(); @@ -695,23 +697,24 @@ void VeyeIMX287m::calcPixelsLoop(std::stop_token stopToken) continue; } else { pixels->counters.encoderPosition = m_stand->posSteps(); - constexpr uint8_t neededCount{8}; - if (collectedInPos < neededCount) { - m_calibrationPixels.push_back(pixels); - ++collectedInPos; + if (m_calibrationPixels[pixels->counters.encoderPosition].size() < neededCount) { + m_calibrationPixels[pixels->counters.encoderPosition].push_back(pixels); + qDebug() << "\tenc:" << pixels->counters.encoderPosition << "in pos:" + << m_calibrationPixels[pixels->counters.encoderPosition].size() + % neededCount; } else { // if (m_stand->posMm() < m_zRangeMm) { if (m_stand->posMm() < debugZRange) { // TODO: dump pixels // dumpCalibrationPixels(m_calibrationPixels); qDebug() << "moveMm:" << m_zRangeMm << ::discretesInRage - << "currPos:" << m_stand->posMm() << "zRange:" << m_zRangeMm + << "\tcurrPos:" << m_stand->posMm() << "zRange:" << m_zRangeMm << m_zRangeMm / ::discretesInRage - << "pos steps:" << pixels->counters.encoderPosition; + << "\tpos steps:" << pixels->counters.encoderPosition + << "\tcollected:" << m_calibrationPixels.size(); m_isMoving = true; - collectedInPos = 0; emit moveMm(m_zRangeMm / ::discretesInRage); // m_stand->moveMm(m_zRangeMm / ::discretesInRage); } else { @@ -723,7 +726,12 @@ void VeyeIMX287m::calcPixelsLoop(std::stop_token stopToken) // m_stand->moveMm(-m_zRangeMm); m_isCalibrating = false; // m_stand.reset(); - const auto tmp = m_calibrationPixels; + // const auto tmp = m_calibrationPixels; + std::vector<std::shared_ptr<Pixels>> tmp; + + for (const auto &[e, p] : m_calibrationPixels) { + tmp.insert(tmp.begin(), p.cbegin(), p.cend()); + } // dumpCalibrationPixels(m_calibrationPixels); dumpCalibrationPixels(tmp, DumpFormat::Binary); m_calibrationPixels.clear(); @@ -809,11 +817,13 @@ bool VeyeIMX287m::dequeueImageBuffer(size_t &imageIndex) if (buf.index < 0 || buf.index >= BUFFER_COUNT) { std::cerr << "invalid buffer index: " << buf.index << std::endl; + m_rawBuffers[imageIndex].sequence = std::numeric_limits<buffer::sequence_t>::max(); return false; } } imageIndex = buf.index; + m_rawBuffers[imageIndex].sequence = buf.sequence; // const auto &image = m_rawBuffers[buf.index].image; // image->height = img_height; @@ -835,6 +845,7 @@ bool VeyeIMX287m::dequeueImageBuffer(size_t &imageIndex) if (ret != 0) { std::cerr << "ioctl(VIDIOC_QBUF) failed: " << errno << " (" << strerror(errno) << ")" << std::endl; + m_rawBuffers[imageIndex].sequence = std::numeric_limits<buffer::sequence_t>::max(); return false; } diff --git a/src/camera/veyeimx287m.h b/src/camera/veyeimx287m.h index bdc57d9..d084788 100644 --- a/src/camera/veyeimx287m.h +++ b/src/camera/veyeimx287m.h @@ -136,6 +136,9 @@ private: struct buffer { void *mem{nullptr}; + using sequence_t = decltype(v4l2_buffer::sequence); + // TODO: think about optional/expected + sequence_t sequence{std::numeric_limits<sequence_t>::max()}; // std::shared_ptr<Image> image{std::make_shared<Image>()}; }; std::vector<buffer> m_rawBuffers; @@ -159,7 +162,7 @@ private: // std::jthread m_getThreads[4]; // TODO: sync all loops somehow to guarantee frames order std::jthread m_rotateThreads[2]; - std::jthread m_calcPixelsThreads[2]; + std::jthread m_calcPixelsThreads[1]; std::mutex m_lastImageMtx; std::shared_ptr<Image> m_lastProcessedImage{}; @@ -170,7 +173,9 @@ private: // TODO: re-organize this logic bool m_isCalibrating{false}; bool m_ignoreFrames{false}; - std::vector<std::shared_ptr<Pixels>> m_calibrationPixels; + // std::vector<std::shared_ptr<Pixels>> m_calibrationPixels; + std::unordered_map<decltype(Counters::encoderPosition), std::vector<std::shared_ptr<Pixels>>> + m_calibrationPixels; std::shared_ptr<IStand> m_stand; double m_zRangeMm{std::numeric_limits<double>::quiet_NaN()}; bool m_isMoving{false}; diff --git a/src/constants.h b/src/constants.h index 6770f5f..b950ede 100644 --- a/src/constants.h +++ b/src/constants.h @@ -39,4 +39,5 @@ const QString user{"radxa"}; const QString dumpsRoot{QStringLiteral("/home/%1/dumps").arg(user)}; -constexpr double debugZRange{5.0}; +// constexpr double debugZRange{10.0}; +constexpr double debugZRange{hardcodedZRangeMm}; diff --git a/src/main.cpp b/src/main.cpp index 2d86dac..c717c7e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -95,6 +95,36 @@ int main(int argc, char *argv[]) qDebug() << "size of raw profile" << sizeof(Pixels); + QElapsedTimer t; + t.start(); + + // FIXME: don't use one var for everything + int ret; + + auto cameras = VeyeIMX287m::search(); + + if (cameras.empty()) { + std::cerr << "No cameras were identified on the system." << std::endl; + + return EXIT_FAILURE; + } + + auto camera = cameras.at(0); + + std::cout << "connect everything" << std::endl; + + for (auto &i : initializers) + i.waitForFinished(); + std::cout << "loaded calibration tables" << std::endl; + + if (!camera->startStream()) { + return EXIT_FAILURE; + } + + // TODO: refactor: scanner and http server depend on each other + const auto scanner = std::make_shared<Scanner>(camera); + auto httpServer = std::make_shared<HttpServer>(scanner); + // Pixels p; // p.counters.encoderPosition = 123; // if (!p.save("/tmp/tmp.pixels")) { @@ -115,7 +145,7 @@ int main(int argc, char *argv[]) if (!openCalibrationTable(QStringLiteral("/home/%1/dumps/binz.calibration_table") .arg(user), // "/tmp/binz.calibration_table", - ::calibrationTableZ)) { + scanner->calibrationTableZ())) { exit(EXIT_FAILURE); } }); @@ -124,7 +154,7 @@ int main(int argc, char *argv[]) if (!openCalibrationTable(QStringLiteral("/home/%1/dumps/binx.calibration_table") .arg(user), // "/tmp/binx.calibration_table", - ::calibrationTableX)) { + scanner->calibrationTableX())) { exit(EXIT_FAILURE); } }); @@ -136,12 +166,11 @@ int main(int argc, char *argv[]) // qDebug() << "height" << calibrationColumnHeight; auto filteredRawProfiles = filter(std::move(rawProfiles)); - qDebug() << "filtered x-profiles count is" - << filteredRawProfiles.count(); + qDebug() << "filtered x-profiles count is" << filteredRawProfiles.count(); - ::calibrationTableX = calibrateX(std::move(filteredRawProfiles)); + calibrateX(std::move(filteredRawProfiles), scanner->calibrationTableX()); - interpolate(::calibrationTableX); + interpolate(scanner->calibrationTableX()); } // load binary calibration dumps and calibrate @@ -154,79 +183,53 @@ int main(int argc, char *argv[]) return EXIT_FAILURE; } + std::sort(rawProfiles.begin(), rawProfiles.end(), [](const auto &a, const auto &b) { + return a.counters.encoderPosition < b.counters.encoderPosition; + }); auto filteredRawProfiles = filter(std::move(rawProfiles)); - qDebug() << "filtered z-profiles count is" - << filteredRawProfiles.count(); + qDebug() << "filtered z-profiles count is" << filteredRawProfiles.count(); - ::calibrationTableZ = calibrateZ(std::move(filteredRawProfiles), - requested_params.stepsPerMm); + if (!calibrateZ(std::move(filteredRawProfiles), + requested_params.stepsPerMm, + scanner->calibrationTableZ())) { + qCritical() << "Z calibration failed, exiting"; + exit(EXIT_FAILURE); + } // DEBUG - ::calibrationTableX = CalibrationTablePtr{new CalibrationTable{{0}}}; - memset(::calibrationTableX.get(), 0, sizeof(CalibrationTable)); - interpolate(::calibrationTableZ); + interpolate(scanner->calibrationTableZ()); - if (!dump(::calibrationTableZ, + if (!dump(scanner->calibrationTableZ(), QStringLiteral("/home/%1/dumps/binz.calibration_table").arg(user))) { qApp->exit(EXIT_FAILURE); } } - qDebug() - << "--------------------------------------------------------"; + qDebug() << "--------------------------------------------------------"; if (false) { auto rawProfiles = openDump(QStringLiteral("/home/%1/dumps/binx").arg(user)); qDebug() << "raw x-profiles count is" << rawProfiles.size(); auto filteredRawProfiles = filter(std::move(rawProfiles)); - qDebug() << "filtered x-profiles count is" - << filteredRawProfiles.count(); + qDebug() << "filtered x-profiles count is" << filteredRawProfiles.count(); - ::calibrationTableX = calibrateX(std::move(filteredRawProfiles)); + if (!calibrateX(std::move(filteredRawProfiles), scanner->calibrationTableX())) { + qCritical() << "X calibration failed, exiting"; + exit(EXIT_FAILURE); + } - interpolate(::calibrationTableX); + interpolate(scanner->calibrationTableX()); - if (!dump(::calibrationTableX, + if (!dump(scanner->calibrationTableX(), QStringLiteral("/home/%1/dumps/binx.calibration_table").arg(user))) { qApp->exit(EXIT_FAILURE); } } } + // exit(EXIT_SUCCESS); } - // exit(EXIT_SUCCESS); - - QElapsedTimer t; - t.start(); - - // FIXME: don't use one var for everything - int ret; - - auto cameras = VeyeIMX287m::search(); - - if (cameras.empty()) { - std::cerr << "No cameras were identified on the system." << std::endl; - - return EXIT_FAILURE; - } - - auto camera = cameras.at(0); - - std::cout << "connect everything" << std::endl; - - for (auto &i : initializers) - i.waitForFinished(); - std::cout << "loaded calibration tables" << std::endl; - - if (!camera->startStream()) { - return EXIT_FAILURE; - } - - // TODO: refactor: scanner and http server depend on each other - const auto scanner = std::make_shared<Scanner>(camera); - auto httpServer = std::make_shared<HttpServer>(scanner); - scanner->startAllProtocols(); httpServer->start(); @@ -242,7 +245,7 @@ int main(int argc, char *argv[]) // if (!::calibrationTableZ || !::calibrationTableX) // return QHttpServerResponse::StatusCode::ServiceUnavailable; - const Profile profile{::pixels, ::calibrationTableZ, ::calibrationTableX}; + const Profile profile{::pixels, scanner->calibrationTableZ(), scanner->calibrationTableX()}; const QJsonObject json{{"profile", QJsonObject(profile)}}; // qDebug() << "profile:" << QJsonDocument(json).toJson(); diff --git a/src/profile.cpp b/src/profile.cpp index 3ed11ba..101ecf3 100644 --- a/src/profile.cpp +++ b/src/profile.cpp @@ -86,7 +86,9 @@ Profile::Profile( continue; } - const auto x = (leftMmX * (1 - fract) + rightMmX * fract); + // const auto x = (leftMmX * (1 - fract) + rightMmX * fract); + // TODO: revert this debug shit + const auto x = static_cast<double>(i) - img_width / 2; m_pointsMm.at(i) = {x, z}; diff --git a/src/protocols/httpserver.cpp b/src/protocols/httpserver.cpp index 3ca1f5c..219bd76 100644 --- a/src/protocols/httpserver.cpp +++ b/src/protocols/httpserver.cpp @@ -185,10 +185,19 @@ QHttpServerResponse HttpServer::GET_profile() { const auto image = m_scanner->camera()->getImage(); const auto pixels = image->sharedPixels(); - const auto profile = Profile{*pixels, ::calibrationTableZ, ::calibrationTableX}; + const auto profile = Profile{*pixels, + m_scanner->calibrationTableZ(), + m_scanner->calibrationTableX()}; const QJsonObject json{profile}; + static bool done{false}; + + if (!done) { + qDebug() << json; + done = true; + } + return QHttpServerResponse{QJsonDocument{json}.toJson()}; } diff --git a/src/scanner.cpp b/src/scanner.cpp index 9012769..4045121 100644 --- a/src/scanner.cpp +++ b/src/scanner.cpp @@ -8,6 +8,8 @@ Scanner::Scanner(std::shared_ptr<ICamera> camera, std::vector<std::shared_ptr<IP , m_calibrationTableZ{new CalibrationTable{}} { // m_protocols.push_back() + memset(m_calibrationTableX.get(), 0, sizeof(CalibrationTable)); + memset(m_calibrationTableZ.get(), 0, sizeof(CalibrationTable)); } bool Scanner::startAllProtocols() |
