summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt9
-rw-r--r--LibCamera.cpp456
-rw-r--r--LibCamera.h131
-rw-r--r--fuck_intel.h9
-rw-r--r--genetic_algos.h2
-rw-r--r--imagealgos.cpp228
-rw-r--r--imagealgos.h10
-rw-r--r--main.cpp430
8 files changed, 910 insertions, 365 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 83ef86c..e07bf77 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -7,7 +7,7 @@ include_guard(GLOBAL)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)
-set(CMAKE_AUTORCC ON)
+set(CMAKE_AUTORCC OFF)
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)
@@ -32,6 +32,7 @@ set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS}")
# ...../rpi-sysroot/usr/lib/qt6/libexec/moc: error while loading shared libraries:
# libpcre2-16.so.0: cannot open shared object file: No such file or directory
#
+# export this path for qtcreator:
# LD_LIBRARY_PATH=/home/nikita/rpi/rpi-sysroot/usr/lib/aarch64-linux-gnu/:$LD_LIBRARY_PATH
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
@@ -59,6 +60,8 @@ set(CMAKE_CXX20_EXTENSION_COMPILE_OPTION "-std:c++latest")
find_package(Qt6 6.4 REQUIRED COMPONENTS Quick HttpServer SerialPort)
+find_package(TBB REQUIRED)
+
qt_standard_project_setup(REQUIRES 6.4)
include_directories(. "${CAMERA_INCLUDE_DIRS}")
@@ -82,6 +85,7 @@ qt_add_executable(apporpheus
rotaryencoder.cpp
printerclient.h
printerclient.cpp
+ fuck_intel.h
)
target_link_libraries(app${PROJECT_NAME}
PRIVATE
@@ -90,6 +94,7 @@ target_link_libraries(app${PROJECT_NAME}
Qt6::HttpServer
Qt6::SerialPort
wiringPi
+ TBB::tbb
)
include(GNUInstallDirs)
@@ -107,4 +112,4 @@ endif()
# add_compile_options(-Wall -Wextra -Wpedantic)
-add_compile_options(-Ofast -fno-unroll-loops)
+add_compile_options(-Ofast -fno-unroll-loops -Wall)
diff --git a/LibCamera.cpp b/LibCamera.cpp
index 945a8ae..1e68228 100644
--- a/LibCamera.cpp
+++ b/LibCamera.cpp
@@ -1,267 +1,267 @@
-#include "LibCamera.h"
+// #include "LibCamera.h"
-using namespace std::placeholders;
+// using namespace std::placeholders;
-int LibCamera::initCamera() {
- int ret;
- cm = std::make_unique<CameraManager>();
- ret = cm->start();
- if (ret){
- std::cout << "Failed to start camera manager: "
- << ret << std::endl;
- return ret;
- }
- cameraId = cm->cameras()[0]->id();
- camera_ = cm->get(cameraId);
- if (!camera_) {
- std::cerr << "Camera " << cameraId << " not found" << std::endl;
- return 1;
- }
+// int LibCamera::initCamera() {
+// int ret;
+// cm = std::make_unique<CameraManager>();
+// ret = cm->start();
+// if (ret){
+// std::cout << "Failed to start camera manager: "
+// << ret << std::endl;
+// return ret;
+// }
+// cameraId = cm->cameras()[0]->id();
+// camera_ = cm->get(cameraId);
+// if (!camera_) {
+// std::cerr << "Camera " << cameraId << " not found" << std::endl;
+// return 1;
+// }
- if (camera_->acquire()) {
- std::cerr << "Failed to acquire camera " << cameraId
- << std::endl;
- return 1;
- }
- camera_acquired_ = true;
- return 0;
-}
+// if (camera_->acquire()) {
+// std::cerr << "Failed to acquire camera " << cameraId
+// << std::endl;
+// return 1;
+// }
+// camera_acquired_ = true;
+// return 0;
+// }
-char * LibCamera::getCameraId(){
- return cameraId.data();
-}
+// char * LibCamera::getCameraId(){
+// return cameraId.data();
+// }
-void LibCamera::configureStill(int width, int height, PixelFormat format, int buffercount, int rotation) {
- printf("Configuring still capture...\n");
- config_ = camera_->generateConfiguration({ StreamRole::StillCapture });
- if (width && height) {
- libcamera::Size size(width, height);
- config_->at(0).size = size;
- }
- config_->at(0).pixelFormat = format;
- if (buffercount)
- config_->at(0).bufferCount = buffercount;
- Transform transform = Transform::Identity;
- bool ok;
- Transform rot = transformFromRotation(rotation, &ok);
- if (!ok)
- throw std::runtime_error("illegal rotation value, Please use 0 or 180");
- transform = rot * transform;
- if (!!(transform & Transform::Transpose))
- throw std::runtime_error("transforms requiring transpose not supported");
- // FIXME: update
- // config_->transform = transform;
+// void LibCamera::configureStill(int width, int height, PixelFormat format, int buffercount, int rotation) {
+// printf("Configuring still capture...\n");
+// config_ = camera_->generateConfiguration({ StreamRole::StillCapture });
+// if (width && height) {
+// libcamera::Size size(width, height);
+// config_->at(0).size = size;
+// }
+// config_->at(0).pixelFormat = format;
+// if (buffercount)
+// config_->at(0).bufferCount = buffercount;
+// Transform transform = Transform::Identity;
+// bool ok;
+// Transform rot = transformFromRotation(rotation, &ok);
+// if (!ok)
+// throw std::runtime_error("illegal rotation value, Please use 0 or 180");
+// transform = rot * transform;
+// if (!!(transform & Transform::Transpose))
+// throw std::runtime_error("transforms requiring transpose not supported");
+// // FIXME: update
+// // config_->transform = transform;
- CameraConfiguration::Status validation = config_->validate();
- if (validation == CameraConfiguration::Invalid)
- throw std::runtime_error("failed to valid stream configurations");
- else if (validation == CameraConfiguration::Adjusted)
- std::cout << "Stream configuration adjusted" << std::endl;
+// CameraConfiguration::Status validation = config_->validate();
+// if (validation == CameraConfiguration::Invalid)
+// throw std::runtime_error("failed to valid stream configurations");
+// else if (validation == CameraConfiguration::Adjusted)
+// std::cout << "Stream configuration adjusted" << std::endl;
- printf("Still capture setup complete\n");
-}
+// printf("Still capture setup complete\n");
+// }
-int LibCamera::startCamera() {
- int ret;
- ret = camera_->configure(config_.get());
- if (ret < 0) {
- std::cout << "Failed to configure camera" << std::endl;
- return ret;
- }
+// int LibCamera::startCamera() {
+// int ret;
+// ret = camera_->configure(config_.get());
+// if (ret < 0) {
+// std::cout << "Failed to configure camera" << std::endl;
+// return ret;
+// }
- camera_->requestCompleted.connect(this, &LibCamera::requestComplete);
+// camera_->requestCompleted.connect(this, &LibCamera::requestComplete);
- allocator_ = std::make_unique<FrameBufferAllocator>(camera_);
+// allocator_ = std::make_unique<FrameBufferAllocator>(camera_);
- return startCapture();
-}
+// return startCapture();
+// }
-int LibCamera::startCapture() {
- int ret;
- unsigned int nbuffers = UINT_MAX;
- for (StreamConfiguration &cfg : *config_) {
- ret = allocator_->allocate(cfg.stream());
- if (ret < 0) {
- std::cerr << "Can't allocate buffers" << std::endl;
- return -ENOMEM;
- }
+// int LibCamera::startCapture() {
+// int ret;
+// unsigned int nbuffers = UINT_MAX;
+// for (StreamConfiguration &cfg : *config_) {
+// ret = allocator_->allocate(cfg.stream());
+// if (ret < 0) {
+// std::cerr << "Can't allocate buffers" << std::endl;
+// return -ENOMEM;
+// }
- unsigned int allocated = allocator_->buffers(cfg.stream()).size();
- nbuffers = std::min(nbuffers, allocated);
- }
+// unsigned int allocated = allocator_->buffers(cfg.stream()).size();
+// nbuffers = std::min(nbuffers, allocated);
+// }
- for (unsigned int i = 0; i < nbuffers; i++) {
- std::unique_ptr<Request> request = camera_->createRequest();
- if (!request) {
- std::cerr << "Can't create request" << std::endl;
- return -ENOMEM;
- }
+// for (unsigned int i = 0; i < nbuffers; i++) {
+// std::unique_ptr<Request> request = camera_->createRequest();
+// if (!request) {
+// std::cerr << "Can't create request" << std::endl;
+// return -ENOMEM;
+// }
- for (StreamConfiguration &cfg : *config_) {
- Stream *stream = cfg.stream();
- const std::vector<std::unique_ptr<FrameBuffer>> &buffers =
- allocator_->buffers(stream);
- const std::unique_ptr<FrameBuffer> &buffer = buffers[i];
+// for (StreamConfiguration &cfg : *config_) {
+// Stream *stream = cfg.stream();
+// const std::vector<std::unique_ptr<FrameBuffer>> &buffers =
+// allocator_->buffers(stream);
+// const std::unique_ptr<FrameBuffer> &buffer = buffers[i];
- ret = request->addBuffer(stream, buffer.get());
- if (ret < 0) {
- std::cerr << "Can't set buffer for request"
- << std::endl;
- return ret;
- }
- for (const FrameBuffer::Plane &plane : buffer->planes()) {
- void *memory = mmap(NULL, plane.length, PROT_READ, MAP_SHARED,
- plane.fd.get(), 0);
- mappedBuffers_[plane.fd.get()] =
- std::make_pair(memory, plane.length);
- }
- }
+// ret = request->addBuffer(stream, buffer.get());
+// if (ret < 0) {
+// std::cerr << "Can't set buffer for request"
+// << std::endl;
+// return ret;
+// }
+// for (const FrameBuffer::Plane &plane : buffer->planes()) {
+// void *memory = mmap(NULL, plane.length, PROT_READ, MAP_SHARED,
+// plane.fd.get(), 0);
+// mappedBuffers_[plane.fd.get()] =
+// std::make_pair(memory, plane.length);
+// }
+// }
- requests_.push_back(std::move(request));
- }
+// requests_.push_back(std::move(request));
+// }
- ret = camera_->start(&this->controls_);
- // ret = camera_->start();
- if (ret) {
- std::cout << "Failed to start capture" << std::endl;
- return ret;
- }
- controls_.clear();
- camera_started_ = true;
- for (std::unique_ptr<Request> &request : requests_) {
- ret = queueRequest(request.get());
- if (ret < 0) {
- std::cerr << "Can't queue request" << std::endl;
- camera_->stop();
- return ret;
- }
- }
- viewfinder_stream_ = config_->at(0).stream();
- return 0;
-}
+// ret = camera_->start(&this->controls_);
+// // ret = camera_->start();
+// if (ret) {
+// std::cout << "Failed to start capture" << std::endl;
+// return ret;
+// }
+// controls_.clear();
+// camera_started_ = true;
+// for (std::unique_ptr<Request> &request : requests_) {
+// ret = queueRequest(request.get());
+// if (ret < 0) {
+// std::cerr << "Can't queue request" << std::endl;
+// camera_->stop();
+// return ret;
+// }
+// }
+// viewfinder_stream_ = config_->at(0).stream();
+// return 0;
+// }
-void LibCamera::StreamDimensions(Stream const *stream, uint32_t *w, uint32_t *h, uint32_t *stride) const
-{
- StreamConfiguration const &cfg = stream->configuration();
- if (w)
- *w = cfg.size.width;
- if (h)
- *h = cfg.size.height;
- if (stride)
- *stride = cfg.stride;
-}
+// void LibCamera::StreamDimensions(Stream const *stream, uint32_t *w, uint32_t *h, uint32_t *stride) const
+// {
+// StreamConfiguration const &cfg = stream->configuration();
+// if (w)
+// *w = cfg.size.width;
+// if (h)
+// *h = cfg.size.height;
+// if (stride)
+// *stride = cfg.stride;
+// }
-Stream *LibCamera::VideoStream(uint32_t *w, uint32_t *h, uint32_t *stride) const
-{
- StreamDimensions(viewfinder_stream_, w, h, stride);
- return viewfinder_stream_;
-}
+// Stream *LibCamera::VideoStream(uint32_t *w, uint32_t *h, uint32_t *stride) const
+// {
+// StreamDimensions(viewfinder_stream_, w, h, stride);
+// return viewfinder_stream_;
+// }
-int LibCamera::queueRequest(Request *request) {
- std::lock_guard<std::mutex> stop_lock(camera_stop_mutex_);
- if (!camera_started_)
- return -1;
- {
- std::lock_guard<std::mutex> lock(control_mutex_);
- request->controls() = std::move(controls_);
- }
- return camera_->queueRequest(request);
-}
+// int LibCamera::queueRequest(Request *request) {
+// std::lock_guard<std::mutex> stop_lock(camera_stop_mutex_);
+// if (!camera_started_)
+// return -1;
+// {
+// std::lock_guard<std::mutex> lock(control_mutex_);
+// request->controls() = std::move(controls_);
+// }
+// return camera_->queueRequest(request);
+// }
-void LibCamera::requestComplete(Request *request) {
- if (request->status() == Request::RequestCancelled)
- return;
- processRequest(request);
-}
+// void LibCamera::requestComplete(Request *request) {
+// if (request->status() == Request::RequestCancelled)
+// return;
+// processRequest(request);
+// }
-void LibCamera::processRequest(Request *request) {
- requestQueue.push(request);
-}
+// void LibCamera::processRequest(Request *request) {
+// requestQueue.push(request);
+// }
-void LibCamera::returnFrameBuffer(LibcameraOutData frameData) {
- uint64_t request = frameData.request;
- Request * req = (Request *)request;
- req->reuse(Request::ReuseBuffers);
- queueRequest(req);
-}
+// void LibCamera::returnFrameBuffer(LibcameraOutData frameData) {
+// uint64_t request = frameData.request;
+// Request * req = (Request *)request;
+// req->reuse(Request::ReuseBuffers);
+// queueRequest(req);
+// }
-bool LibCamera::readFrame(LibcameraOutData *frameData){
- std::lock_guard<std::mutex> lock(free_requests_mutex_);
- // int w, h, stride;
- if (!requestQueue.empty()){
- Request *request = this->requestQueue.front();
+// bool LibCamera::readFrame(LibcameraOutData *frameData){
+// std::lock_guard<std::mutex> lock(free_requests_mutex_);
+// // int w, h, stride;
+// if (!requestQueue.empty()){
+// Request *request = this->requestQueue.front();
- const Request::BufferMap &buffers = request->buffers();
- for (auto it = buffers.begin(); it != buffers.end(); ++it) {
- FrameBuffer *buffer = it->second;
- for (unsigned int i = 0; i < buffer->planes().size(); ++i) {
- const FrameBuffer::Plane &plane = buffer->planes()[i];
- const FrameMetadata::Plane &meta = buffer->metadata().planes()[i];
+// const Request::BufferMap &buffers = request->buffers();
+// for (auto it = buffers.begin(); it != buffers.end(); ++it) {
+// FrameBuffer *buffer = it->second;
+// for (unsigned int i = 0; i < buffer->planes().size(); ++i) {
+// const FrameBuffer::Plane &plane = buffer->planes()[i];
+// const FrameMetadata::Plane &meta = buffer->metadata().planes()[i];
- void *data = mappedBuffers_[plane.fd.get()].first;
- int length = std::min(meta.bytesused, plane.length);
+// void *data = mappedBuffers_[plane.fd.get()].first;
+// int length = std::min(meta.bytesused, plane.length);
- frameData->size = length;
- frameData->imageData = (uint8_t *)data;
- }
- }
- this->requestQueue.pop();
- frameData->request = (uint64_t)request;
- return true;
- } else {
- Request *request = nullptr;
- frameData->request = (uint64_t)request;
- return false;
- }
-}
+// frameData->size = length;
+// frameData->imageData = (uint8_t *)data;
+// }
+// }
+// this->requestQueue.pop();
+// frameData->request = (uint64_t)request;
+// return true;
+// } else {
+// Request *request = nullptr;
+// frameData->request = (uint64_t)request;
+// return false;
+// }
+// }
-void LibCamera::set(ControlList controls){
- std::lock_guard<std::mutex> lock(control_mutex_);
- this->controls_ = std::move(controls);
-}
+// void LibCamera::set(ControlList controls){
+// std::lock_guard<std::mutex> lock(control_mutex_);
+// this->controls_ = std::move(controls);
+// }
-int LibCamera::resetCamera(int width, int height, PixelFormat format, int buffercount, int rotation) {
- stopCamera();
- configureStill(width, height, format, buffercount, rotation);
- return startCamera();
-}
+// int LibCamera::resetCamera(int width, int height, PixelFormat format, int buffercount, int rotation) {
+// stopCamera();
+// configureStill(width, height, format, buffercount, rotation);
+// return startCamera();
+// }
-void LibCamera::stopCamera() {
- if (camera_){
- {
- std::lock_guard<std::mutex> lock(camera_stop_mutex_);
- if (camera_started_){
- if (camera_->stop())
- throw std::runtime_error("failed to stop camera");
- camera_started_ = false;
- }
- }
- camera_->requestCompleted.disconnect(this, &LibCamera::requestComplete);
- }
- while (!requestQueue.empty())
- requestQueue.pop();
+// void LibCamera::stopCamera() {
+// if (camera_){
+// {
+// std::lock_guard<std::mutex> lock(camera_stop_mutex_);
+// if (camera_started_){
+// if (camera_->stop())
+// throw std::runtime_error("failed to stop camera");
+// camera_started_ = false;
+// }
+// }
+// camera_->requestCompleted.disconnect(this, &LibCamera::requestComplete);
+// }
+// while (!requestQueue.empty())
+// requestQueue.pop();
- for (auto &iter : mappedBuffers_)
- {
- std::pair<void *, unsigned int> pair_ = iter.second;
- munmap(std::get<0>(pair_), std::get<1>(pair_));
- }
+// for (auto &iter : mappedBuffers_)
+// {
+// std::pair<void *, unsigned int> pair_ = iter.second;
+// munmap(std::get<0>(pair_), std::get<1>(pair_));
+// }
- mappedBuffers_.clear();
+// mappedBuffers_.clear();
- requests_.clear();
+// requests_.clear();
- allocator_.reset();
+// allocator_.reset();
- controls_.clear();
-}
+// controls_.clear();
+// }
-void LibCamera::closeCamera(){
- if (camera_acquired_)
- camera_->release();
- camera_acquired_ = false;
+// void LibCamera::closeCamera(){
+// if (camera_acquired_)
+// camera_->release();
+// camera_acquired_ = false;
- camera_.reset();
+// camera_.reset();
- cm.reset();
-}
+// cm.reset();
+// }
diff --git a/LibCamera.h b/LibCamera.h
index 2262ab2..89cf835 100644
--- a/LibCamera.h
+++ b/LibCamera.h
@@ -1,19 +1,25 @@
-#include <atomic>
-#include <iomanip>
-#include <iostream>
-#include <signal.h>
-#include <limits.h>
-#include <memory>
-#include <stdint.h>
-#include <string>
-#include <vector>
-#include <unordered_map>
-#include <queue>
-#include <sstream>
-#include <sys/mman.h>
-#include <unistd.h>
-#include <time.h>
-#include <mutex>
+#pragma once
+
+// #include <atomic>
+// #include <iomanip>
+// #include <iostream>
+// #include <signal.h>
+// #include <limits.h>
+// #include <memory>
+// #include <stdint.h>
+// #include <string>
+// #include <vector>
+// #include <unordered_map>
+// #include <queue>
+// #include <sstream>
+// #include <sys/mman.h>
+// #include <unistd.h>
+// #include <time.h>
+// #include <mutex>
+
+#ifdef signals
+#error ("don't include this file after any qt files")
+#endif
#include <libcamera/controls.h>
#include <libcamera/control_ids.h>
@@ -26,61 +32,60 @@
#include <libcamera/stream.h>
#include <libcamera/formats.h>
#include <libcamera/transform.h>
+// using namespace libcamera;
-using namespace libcamera;
-
-typedef struct {
- uint8_t *imageData;
- uint32_t size;
- uint64_t request;
-} LibcameraOutData;
+// typedef struct {
+// uint8_t *imageData;
+// uint32_t size;
+// uint64_t request;
+// } LibcameraOutData;
-class LibCamera {
- public:
- LibCamera(){};
- ~LibCamera(){};
+// class LibCamera {
+// public:
+// LibCamera(){};
+// ~LibCamera(){};
- int initCamera();
- void configureStill(int width, int height, PixelFormat format, int buffercount, int rotation);
- int startCamera();
- int resetCamera(int width, int height, PixelFormat format, int buffercount, int rotation);
- bool readFrame(LibcameraOutData *frameData);
- void returnFrameBuffer(LibcameraOutData frameData);
+// int initCamera();
+// void configureStill(int width, int height, PixelFormat format, int buffercount, int rotation);
+// int startCamera();
+// int resetCamera(int width, int height, PixelFormat format, int buffercount, int rotation);
+// bool readFrame(LibcameraOutData *frameData);
+// void returnFrameBuffer(LibcameraOutData frameData);
- void set(ControlList controls);
- void stopCamera();
- void closeCamera();
+// void set(ControlList controls);
+// void stopCamera();
+// void closeCamera();
- Stream *VideoStream(uint32_t *w, uint32_t *h, uint32_t *stride) const;
- char * getCameraId();
+// Stream *VideoStream(uint32_t *w, uint32_t *h, uint32_t *stride) const;
+// char * getCameraId();
- private:
- int startCapture();
- int queueRequest(Request *request);
- void requestComplete(Request *request);
- void processRequest(Request *request);
+// private:
+// int startCapture();
+// int queueRequest(Request *request);
+// void requestComplete(Request *request);
+// void processRequest(Request *request);
- void StreamDimensions(Stream const *stream, uint32_t *w, uint32_t *h, uint32_t *stride) const;
+// void StreamDimensions(Stream const *stream, uint32_t *w, uint32_t *h, uint32_t *stride) const;
- unsigned int cameraIndex_;
- uint64_t last_;
- std::unique_ptr<CameraManager> cm;
- std::shared_ptr<Camera> camera_;
- bool camera_acquired_ = false;
- bool camera_started_ = false;
- std::unique_ptr<CameraConfiguration> config_;
- std::unique_ptr<FrameBufferAllocator> allocator_;
- std::vector<std::unique_ptr<Request>> requests_;
- // std::map<std::string, Stream *> stream_;
- std::map<int, std::pair<void *, unsigned int>> mappedBuffers_;
+// unsigned int cameraIndex_;
+// uint64_t last_;
+// std::unique_ptr<CameraManager> cm;
+// std::shared_ptr<Camera> camera_;
+// bool camera_acquired_ = false;
+// bool camera_started_ = false;
+// std::unique_ptr<CameraConfiguration> config_;
+// std::unique_ptr<FrameBufferAllocator> allocator_;
+// std::vector<std::unique_ptr<Request>> requests_;
+// // std::map<std::string, Stream *> stream_;
+// std::map<int, std::pair<void *, unsigned int>> mappedBuffers_;
- std::queue<Request *> requestQueue;
+// std::queue<Request *> requestQueue;
- ControlList controls_;
- std::mutex control_mutex_;
- std::mutex camera_stop_mutex_;
- std::mutex free_requests_mutex_;
+// ControlList controls_;
+// std::mutex control_mutex_;
+// std::mutex camera_stop_mutex_;
+// std::mutex free_requests_mutex_;
- Stream *viewfinder_stream_ = nullptr;
- std::string cameraId;
-}; \ No newline at end of file
+// Stream *viewfinder_stream_ = nullptr;
+// std::string cameraId;
+// };
diff --git a/fuck_intel.h b/fuck_intel.h
new file mode 100644
index 0000000..a9fa7d5
--- /dev/null
+++ b/fuck_intel.h
@@ -0,0 +1,9 @@
+#pragma once
+
+#ifdef emit
+#undef emit
+#include <execution>
+#define emit
+#else
+#include <execution>
+#endif
diff --git a/genetic_algos.h b/genetic_algos.h
index 862cd34..8dea732 100644
--- a/genetic_algos.h
+++ b/genetic_algos.h
@@ -3,9 +3,9 @@
// #define _USE_MATH_DEFINES
#include <algorithm>
#include <cmath>
-// #include <execution>
#include <numbers>
#include <random>
+// TODO: <execution>
/*
diff --git a/imagealgos.cpp b/imagealgos.cpp
index 3e84155..b4fba4b 100644
--- a/imagealgos.cpp
+++ b/imagealgos.cpp
@@ -1,5 +1,7 @@
#include "imagealgos.h"
+#include <QDebug>
+
#include <cassert>
#include <cstdint>
#include <cstring>
@@ -14,6 +16,7 @@
// #include <arm_neon.h>
+#include "fuck_intel.h"
#include "genetic_algos.h"
#include "macro.h"
@@ -210,7 +213,7 @@ float process_column(uint16_t (&column)[])
}
result = (y2 != y1) ?
- (img_height - (float(x1) - (float(y1) / (y2 - y1)))) :
+ (float(x1) - (float(y1) / (y2 - y1))) :
std::numeric_limits<float>::quiet_NaN();
@@ -267,11 +270,230 @@ Pixels process_columns(Image &image)
// image.pixels[i] = genetic.run().a;
// if (i == 0) {
- // std::cout << "pixel: " << image.pixels[i] << std::endl;
- // }
+ // std::cout << "pixel: " << image.pixels[i] << std::endl;
+ // }
}
stop_timer(process_columns);
return result;
}
+
+Pixels& Pixels::operator+=(const Pixels& other)
+{
+ std::transform(std::execution::par,
+ pixels.begin(), pixels.end(),
+ other.pixels.begin(),
+ pixels.begin(),
+ // [](auto& toAdd) { return dst += src; });
+ std::plus<>());
+
+ return *this;
+}
+
+Pixels& Pixels::operator/=(const float divider)
+{
+ std::for_each(std::execution::par_unseq,
+ pixels.begin(), pixels.end(),
+ [divider](auto& pixel) { pixel /= divider; });
+
+ return *this;
+}
+
+QList<QLineF> pixelsToLines(const Pixels &rawProfile)
+{
+ const auto& pixels = rawProfile.pixels;
+ QList<QPointF> points { pixels.size() };
+
+ for (int i = 0; i < pixels.size(); ++i)
+ {
+ points[i] = { qreal(i) - img_width / 2, pixels.at(i) };
+ }
+
+ // qDebug() << "mid points" << points.mid(points.count() - 3, 6);
+
+ return pointsToLines(std::move(points));
+}
+
+QList<QLineF> pointsToLines(const QList<QPointF> &points)
+{
+ constexpr double maxDistanceFromLine { 3 };
+ constexpr double minLineLength { 10 };
+
+ QList<int> lineAnchors { 0, points.size() - 1 };
+
+ auto vecLength = [](const QPointF& vector) {
+ return std::hypot(vector.x(), vector.y());
+ };
+
+ auto distanceToLine = [vecLength](const QPointF& point, const QLineF& line) {
+ // const auto d1 = point - line.p1();
+ // const auto d2 = line.p2() - line.p1();
+
+ // const auto norm = vecLength(d2);
+ // qDebug() << "norm" << norm;
+
+ // if (norm <= std::numeric_limits<double>::epsilon())
+ // {
+ // qDebug() << "AAAAAAAAAAAAAAAAAA";
+ // return vecLength(d1);
+ // }
+
+ // const auto result = std::fabs(d1.x() * d2.y() - d1.y() * d2.x()) / norm;
+
+ // if (!qFuzzyIsNull(result))
+ // {
+ // qDebug() << "NOT NULL" << result << point << line;
+ // }
+
+ // return result;
+ // transform to loocal coordinates system (0,0) - (lx, ly)
+ QPointF p1 = line.p1();
+ QPointF p2 = line.p2();
+ const auto& p = point;
+ qreal x = p.x() - p1.x();
+ qreal y = p.y() - p1.y();
+ qreal x2 = p2.x() - p1.x();
+ qreal y2 = p2.y() - p1.y();
+
+ // if line is a point (nodes are the same) =>
+ // just return distance between point and one line node
+ qreal norm = sqrt(x2*x2 + y2*y2);
+ if (norm <= std::numeric_limits<int>::epsilon())
+ return sqrt(x*x + y*y);
+
+ // distance
+ // qDebug() << "dist" << fabs(x*y2 - y*x2) / norm << point << line;
+ return fabs(x*y2 - y*x2) / norm;
+ };
+
+ // for (const auto& p : points)
+ // {
+ // qDebug() << "\t" << p;
+ // }
+
+ for (int i = 0; i < lineAnchors.count() - 1; ++i)
+ {
+ const auto &lineFirst = i;
+ const auto &lineLast = i + 1;
+ const auto& leftPointIdx = lineAnchors.at(lineFirst);
+ const auto& rightPointIdx = lineAnchors.at(lineLast);
+
+ if (rightPointIdx - leftPointIdx < 2)
+ {
+ continue;
+ }
+
+ const QLineF line { points.at(leftPointIdx), points.at(rightPointIdx) };
+
+ const auto farthest = std::max_element(
+ // std::execution::par_unseq,
+ points.cbegin() + leftPointIdx + 1,
+ points.cbegin() + rightPointIdx - 1,
+ [line, distanceToLine](const QPointF& a, const QPointF& b) {
+ return distanceToLine(a, line) < distanceToLine(b, line);
+ });
+
+ // qDebug() << "farthest point" << distanceToLine(*farthest, line);
+ // qDebug() << "farthest dist" << distanceToLine(*farthest, line);
+ // qDebug() << "that's from line" << line;
+
+ if (distanceToLine(*farthest, line) > maxDistanceFromLine)
+ {
+ lineAnchors.insert(i + 1, farthest - points.cbegin());
+ --i;
+ // qDebug() << "I'm here" << i;
+ continue;
+ }
+ }
+
+ struct LineAB
+ {
+ double a { std::numeric_limits<double>::quiet_NaN() };
+ double b { std::numeric_limits<double>::quiet_NaN() };
+
+ LineAB(const QList<QPointF>& points) {
+ if (points.isEmpty())
+ {
+ return;
+ }
+
+ double sumX { 0 };
+ double sumY { 0 };
+ double sumXY { 0 };
+ double sumXX { 0 };
+
+ // FIXME: validate
+ // for (const auto& point : points)
+ const int delta = points.count() * 0.15;
+ for (int i = delta; i < points.count() - delta; ++i)
+ {
+ const auto& point = points.at(i);
+ sumX += point.x();
+ sumY += point.y();
+ sumXY += point.x() * point.y();
+ sumXX += point.x() * point.x();
+ }
+
+ // sumX /= points.count();
+ // sumY /= points.count();
+ // sumXY /= points.count();
+ // sumXX /= points.count();
+
+ const int n = points.count() - delta * 2;
+ Q_ASSERT_X(n > 0, Q_FUNC_INFO, "n <= 0");
+
+ a = (n * sumXY - sumX * sumY) /
+ (n * sumXX - sumX * sumX);
+ b = (sumY - a * sumX) / n;
+ }
+ };
+
+ // auto pointsToLineAB =
+
+ // qDebug() << "line anchors count is" << lineAnchors.count();
+
+ constexpr bool useLsd = true;
+
+ QList<QLineF> result { lineAnchors.length() - 1 };
+
+ for (int i = 0; i < lineAnchors.count() - 1; ++i)
+ {
+ const auto& leftPointIdx = lineAnchors.at(i);
+ const auto& rightPointIdx = lineAnchors.at(i + 1);
+
+ QPointF leftPoint = points.at(leftPointIdx);
+ QPointF rightPoint = points.at(rightPointIdx);
+
+ LineAB lineAB(points.mid(leftPointIdx, rightPointIdx - leftPointIdx));
+
+ leftPoint.setY(lineAB.a * leftPoint.x() + lineAB.b);
+ rightPoint.setY(lineAB.a * rightPoint.x() + lineAB.b);
+
+ if (useLsd)
+ result[i] = QLineF{ std::move(leftPoint), std::move(rightPoint) };
+ else
+ result[i] = QLineF{ points.at(lineAnchors.at(i)), points.at(lineAnchors.at(i + 1)) };
+ }
+
+ if (useLsd)
+ {
+ for (int i = 0; i < result.count() - 1; ++i)
+ {
+ auto& lineA = result[i];
+ auto& lineB = result[i + 1];
+
+ QPointF intersectionPoint {};
+
+ if (lineA.intersects(lineB, &intersectionPoint) != QLineF::NoIntersection)
+ {
+ lineA.setP2(intersectionPoint);
+ lineB.setP1(intersectionPoint);
+ }
+ }
+ }
+
+ // qDebug() << result;
+
+ return result;
+}
diff --git a/imagealgos.h b/imagealgos.h
index 77ac625..12dc8cf 100644
--- a/imagealgos.h
+++ b/imagealgos.h
@@ -6,6 +6,9 @@
#include <libcamera/pixel_format.h>
+#include <QLineF>
+#include <QList>
+
constexpr size_t img_width = 1280;
constexpr size_t img_height = 800;
constexpr uint32_t patternSize = 16;
@@ -37,8 +40,12 @@ struct Pixels
{
Counters counters {};
std::array<float, img_width> pixels { 0.f };
+
+ Pixels& operator+=(const Pixels& other);
+ Pixels& operator/=(const float divider);
};
+
size_t pgm_save(Image *img, FILE *outfile, bool really_save = false);
void unpack_10bit(uint8_t const *src, Image const &image, uint16_t *dest);
@@ -52,3 +59,6 @@ T median3(const T& a, const T& b, const T& c) {
void rotate(Image & image);
Pixels process_columns(Image & image);
+
+QList<QLineF> pixelsToLines(const Pixels& rawProfile);
+QList<QLineF> pointsToLines(const QList<QPointF>& points);
diff --git a/main.cpp b/main.cpp
index 33f94ee..06b7700 100644
--- a/main.cpp
+++ b/main.cpp
@@ -1,13 +1,21 @@
+#include <chrono>
+#include <errno.h>
+#include <iostream>
+#include <iterator>
+#include <fstream>
+#include <string.h>
+#include <thread>
+#include <sys/mman.h>
+#include "LibCamera.h"
+#include "printerclient.h"
#include "httpservice.h"
#include "genetic_algos.h"
-#include "imagealgos.h"
-#include "LibCamera.h"
#include "pigpio.h"
-#include "printerclient.h"
#include "rotaryencoder.h"
+#include "imagealgos.h"
+#include "fuck_intel.h"
-#define QT_NO_KEYWORDS
#include <QCoreApplication>
#include <QDebug>
#include <QDir>
@@ -20,14 +28,6 @@
#include <QTextStream>
#include <QtConcurrent/QtConcurrentRun>
#include <QTimer>
-#undef QT_NO_KEYWORDS
-
-#include <chrono>
-#include <errno.h>
-#include <iostream>
-#include <fstream>
-#include <string.h>
-#include <thread>
#define try_apply_config() \
if(!applyConfig(config)) \
@@ -76,21 +76,83 @@ const QString dumpsRoot { QStringLiteral("/home/user/dumps") };
using namespace std::chrono_literals;
-static std::shared_ptr<Camera> camera;
-std::unique_ptr<CameraConfiguration> config;
+static std::shared_ptr<libcamera::Camera> camera;
+std::unique_ptr<libcamera::CameraConfiguration> config;
static std::map<int, std::pair<void *, unsigned int>> mappedBuffers_;
-std::vector<std::unique_ptr<Request>> requests;
-ControlList lastControls;
+std::vector<std::unique_ptr<libcamera::Request>> requests;
+libcamera::ControlList lastControls;
-static bool applyConfig(const std::unique_ptr<CameraConfiguration> & config);
-static void onRequestCompleted(Request *completed_request);
+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 }} };
+
+static bool applyConfig(const std::unique_ptr<libcamera::CameraConfiguration> & config);
+static void onRequestCompleted(libcamera::Request *completed_request);
static void printControls();
static void dumpCalibrationPixels();
-static std::vector<Pixels> openDump(const QString dumpPath = "");
+static QList<Pixels> filter(const QList<Pixels>& rawProfiles);
+static QSharedPointer<CalibrationTable> calibrate(const QList<Pixels>& rawProfiles);
+
+auto printPixels = [](const auto& pixels) {
+ for (size_t i = (img_width - 10) / 2; i < img_width - ((img_width - 10) / 2); ++i)
+ {
+ std::cout << pixels[i] << " ";
+ }
+ std::cout << std::endl;
+};
+
+bool initLaser();
+
+class A
+{
+public:
+ A(const int var) : m_var{ var } { std::cout << m_var << std::endl; }
+
+private:
+ int m_var { 0 };
+};
+
+class B : public A
+{
+public:
+ B(const int var) : A{var} {}
+};
int main(int argc, char *argv[]) {
QCoreApplication app(argc, argv);
+ // if (!initLaser())
+ // {
+ // return EXIT_FAILURE;
+ // }
+
+ if (false)
+ {
+ // 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");
+ qDebug() << "raw profiles count is" << rawProfiles.size();
+ // qDebug() << "height" << calibrationColumnHeight;
+
+ auto filteredRawProfiles = filter(rawProfiles);
+ qDebug() << "filtered profiles count is" << filteredRawProfiles.count();
+
+ auto calibrationTable = calibrate(filteredRawProfiles);
+ // auto calibrationTable = calibrate(rawProfiles);
+ // CalibrationTable* aaa { new CalibrationTable {{ 0 }} };
+ // (*aaa)[1][0] = 123;
+ // CalibrationTable bbb {{ 0 }};
+ // bbb[1][0] = 123;
+
+ // float* values = new float[calibrationColumnHeight];
+ }
+
QElapsedTimer t;
t.start();
@@ -102,7 +164,7 @@ int main(int argc, char *argv[]) {
qDebug() << "msecs before camera:" << t.elapsed();
// FIXME: don't use one var for everything
int ret;
- std::unique_ptr<CameraManager> cm = std::make_unique<CameraManager>();
+ std::unique_ptr<libcamera::CameraManager> cm = std::make_unique<libcamera::CameraManager>();
cm->start();
const auto cameras = cm->cameras();
@@ -139,7 +201,7 @@ int main(int argc, char *argv[]) {
// FIXME: nullptr
// std::unique_ptr<CameraConfiguration> config = camera->generateConfiguration( { StreamRole::Viewfinder } );
- /*std::unique_ptr<CameraConfiguration> */config = camera->generateConfiguration( { StreamRole::Raw } );
+ /*std::unique_ptr<CameraConfiguration> */config = camera->generateConfiguration( { libcamera::StreamRole::Raw } );
if (config->empty())
{
@@ -162,7 +224,7 @@ int main(int argc, char *argv[]) {
// }
// FIXME: nullptr
- StreamConfiguration &streamConfig = config->at(0);
+ libcamera::StreamConfiguration &streamConfig = config->at(0);
std::cout << "Default viewfinder configuration is: " << streamConfig.toString() << std::endl;
std::cout << "Pixel format is: " << streamConfig.pixelFormat.toString() << std::endl;
std::cout << "Buffer count is: " << streamConfig.bufferCount << std::endl;
@@ -179,7 +241,7 @@ int main(int argc, char *argv[]) {
// streamConfig.pixelFormat = PixelFormat::fromString("Y8_1X8");
// streamConfig.pixelFormat = formats::R8;
- streamConfig.pixelFormat = formats::R16;
+ streamConfig.pixelFormat = libcamera::formats::R16;
streamConfig.bufferCount = 2;
// what is default R10_CSI2P? MONO_PISP_COMP1?
// MONO_PISP_COMP1 - check rpicam-apps sources for decoding algos
@@ -215,7 +277,7 @@ int main(int argc, char *argv[]) {
// TODO: try custom FrameBufferAllocator and compare performance
- auto allocator = std::make_shared<FrameBufferAllocator>(camera);
+ auto allocator = std::make_shared<libcamera::FrameBufferAllocator>(camera);
auto stream = streamConfig.stream();
@@ -232,13 +294,13 @@ int main(int argc, char *argv[]) {
size_t allocated = size_t(ret);
std::cout << "Allocated " << allocated << " buffers for stream" << std::endl;
- const std::vector<std::unique_ptr<FrameBuffer>> &buffers = allocator->buffers(stream);
+ const std::vector<std::unique_ptr<libcamera::FrameBuffer>> &buffers = allocator->buffers(stream);
// for (size_t i = 0; i < buffers.size(); ++i)
static int expOffset = 0;
for (const auto & buffer : buffers)
{
- std::unique_ptr<Request> request = camera->createRequest();
+ std::unique_ptr<libcamera::Request> request = camera->createRequest();
if (!request)
{
@@ -328,7 +390,7 @@ int main(int argc, char *argv[]) {
for (size_t i = 0; i < img_width; ++i) {
// pixels << img_height - img.pixels[i];
- pixels << img_height - ::pixels.pixels[i];
+ pixels << ::pixels.pixels[i];
}
QJsonObject json;
@@ -337,6 +399,22 @@ int main(int argc, char *argv[]) {
json["measurementCounter"] = qint64 { img.counters.measurementCounter };
json["timestampUs"] = qint64(img.counters.timestampUs);
+ const auto lines = pixelsToLines(::pixels);
+
+ qDebug() << "lines count is " << lines.count();
+
+ QJsonArray jsonLines;
+
+ for (const auto& l : lines)
+ {
+ jsonLines << QJsonArray {
+ QJsonArray { l.p1().x(), l.p1().y() },
+ QJsonArray { l.p2().x(), l.p2().y() }
+ };
+ }
+
+ json["lines"] = jsonLines;
+
return QHttpServerResponse(QJsonDocument(json).toJson());
});
@@ -403,14 +481,14 @@ int main(int argc, char *argv[]) {
std::lock_guard<std::mutex> lg(pgm_image_mtx);
QJsonObject json;
- const ControlIdMap & ctrlIdMap = camera->controls().idmap();
+ const libcamera::ControlIdMap & ctrlIdMap = camera->controls().idmap();
qDebug() << "readParams:" << lastControls.size();
qDebug() << request.method();
for (const auto & [id, value]: lastControls)
{
- const ControlId * controlId = ctrlIdMap.at(id);
+ const libcamera::ControlId * controlId = ctrlIdMap.at(id);
auto name = QString::fromStdString(controlId->name());
const auto valueStr = QString::fromStdString(value.toString());
qDebug() << "\t param:"
@@ -611,8 +689,10 @@ int main(int argc, char *argv[]) {
* important not to block the thread for a long time, as this blocks internal
* processing of the camera pipelines, and can affect realtime performance.
*/
-void onRequestCompleted(Request *completed_request)
+void onRequestCompleted(libcamera::Request *completed_request)
{
+ using namespace libcamera;
+
static std::chrono::steady_clock::time_point fpsTimstamp = std::chrono::steady_clock::now();
QElapsedTimer t;
@@ -683,8 +763,7 @@ void onRequestCompleted(Request *completed_request)
// qDebug() << "calibration mode" << scanningModeFlags;
if (scanningModeFlags == ScanningModeFlags::Calibration) {
- constexpr int32_t hardcodedZRangeMm { 175 };
- const int32_t maxEncoderPosition = hardcodedZRangeMm * requested_params.stepsPerMm;
+ const int32_t maxEncoderPosition = int32_t(hardcodedZRangeMm) * requested_params.stepsPerMm;
// qDebug() << "calibration max range" << maxEncoderPosition;
// qDebug() << "calibration encoder pos" << pixels.counters.encoderPosition;
if (pixels.counters.encoderPosition >= 0 &&
@@ -789,12 +868,14 @@ void onRequestCompleted(Request *completed_request)
}
-static bool applyConfig(const std::unique_ptr<CameraConfiguration> & config)
+static bool applyConfig(const std::unique_ptr<libcamera::CameraConfiguration> & config)
{
+ using namespace libcamera;
+
auto status = config->validate();
// WARNING: unsafe
- StreamConfiguration &streamConfig = config->at(0);
+ libcamera::StreamConfiguration &streamConfig = config->at(0);
switch (status) {
case CameraConfiguration::Status::Valid:
@@ -819,7 +900,8 @@ static bool applyConfig(const std::unique_ptr<CameraConfiguration> & config)
static void printControls()
{
- const ControlInfoMap & control_map = camera->controls();
+ using namespace libcamera;
+ const libcamera::ControlInfoMap & control_map = camera->controls();
// for (const auto & [id, info]: control_map)
for (const std::pair<const ControlId *, ControlInfo> & pair : control_map)
@@ -888,10 +970,10 @@ static void dumpCalibrationPixels()
}
QJsonObject jsonCounters {
- { "timestampUs", qint64(rawProfile.counters.timestampUs) },
- { "measurementCounter", qint64(rawProfile.counters.measurementCounter) },
- { "encoderPosition", qint64(rawProfile.counters.encoderPosition) },
- };
+ { "timestampUs", qint64(rawProfile.counters.timestampUs) },
+ { "measurementCounter", qint64(rawProfile.counters.measurementCounter) },
+ { "encoderPosition", qint64(rawProfile.counters.encoderPosition) },
+ };
QJsonObject json;
@@ -920,11 +1002,10 @@ static void dumpCalibrationPixels()
qDebug() << "dump finished";
}
-static std::vector<Pixels> openDump(const QString dumpPath)
+static QList<Pixels> openDump(const QString &dumpPath)
{
- std::vector<Pixels> result;
-
QString dirToRead { dumpPath };
+ qDebug() << "trying to open dump path:" << dirToRead;
if (dirToRead.isEmpty())
{
@@ -945,10 +1026,10 @@ static std::vector<Pixels> openDump(const QString dumpPath)
return {};
}
- dirToRead = entries.last();
+ dirToRead = dumpsRoot + "/" + entries.last();
}
- QDir dumpDir { dumpsRoot + "/" + dirToRead };
+ QDir dumpDir { dirToRead };
const auto filter = QDir::Files;
const auto sort = QDir::Name;
@@ -958,47 +1039,260 @@ static std::vector<Pixels> openDump(const QString dumpPath)
if (filenames.isEmpty())
{
qDebug() << "no filenames found in" << dumpDir.path();
+ return {};
}
- for (const auto& filename : filenames)
+ QList<std::optional<Pixels>> resultOptionals { filenames.size() };
+
+ QElapsedTimer t;
+ t.start();
+
+ std::transform(
+ std::execution::par,
+ filenames.begin(), filenames.end(),
+ resultOptionals.begin(),
+ [dirToRead](const auto& filename) {
+ std::cout << '.';
+ return openRawProfile(dirToRead + "/" + filename);
+ });
+
+ 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))
{
- qDebug() << "raw profile:" << filename;
+ qWarning() << "cannot open file for reading:" << f.fileName();
+ qWarning() << "error string:" << f.errorString();
+
+ return {};
+ }
- QFile f { dumpDir.path() + "/" + filename };
+ // TODO: rewrite to remove manual serialization/deserialization
+ const auto json = QJsonDocument::fromJson(f.readAll()).object();
+ const auto jsonCounters = json["counters"].toObject();
- if (!f.open(QFile::ReadOnly))
+ 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();
+
+ for (size_t i = 0; i < jsonPixels.count() && i < result.pixels.size(); ++i)
+ {
+ result.pixels[i] = jsonPixels[i].toDouble();
+ }
+
+ return result;
+}
+
+static QList<Pixels> filter(const QList<Pixels>& rawProfiles)
+{
+ QList<Pixels> result;
+
+ QList<Pixels>::const_iterator it = rawProfiles.constBegin();
+
+ // for (size_t i = 0; i < 10; ++i)
+ // {
+ // std::cout << "pos - " << rawProfiles.at(i).counters.encoderPosition << std::endl;
+ // }
+
+ // ++it;
+ while (it != rawProfiles.constEnd())
+ {
+ Pixels sum = *it;
+ std::cout << "current pos is " << sum.counters.encoderPosition << std::endl;
+
+ printPixels(sum.pixels);
+
+ size_t count { 1 };
+ ++it;
+
+ std::cout << "here\n";
+ while (it != rawProfiles.constEnd() && it->counters.encoderPosition == sum.counters.encoderPosition)
{
- qWarning() << "cannot open file for reading:" << f.fileName();
- qWarning() << "error string:" << f.errorString();
+ std::cout << "here2\n";
+ std::cout << "\tadd to pos " << it->counters.encoderPosition << std::endl;
+ sum += *it;
+ std::cout << "\tadded" << std::endl;
+ ++count;
+ ++it;
- return {};
}
- // TODO: rewrite to remove manual serialization/deserialization
- const auto json = QJsonDocument::fromJson(f.readAll()).object();
- const auto jsonCounters = json["counters"].toObject();
- qDebug() << jsonCounters;
+ std::cout << "here3\n";
+ sum /= float(count);
+ printPixels(sum.pixels);
- Pixels rawProfile;
+ result << sum;
- rawProfile.counters.timestampUs = jsonCounters["timestampUs"].toInteger();
- rawProfile.counters.measurementCounter = jsonCounters["measurementCounter"].toInteger();
- rawProfile.counters.encoderPosition = jsonCounters["encoderPosition"].toInteger();
+ // return result;
+ }
- const auto jsonPixels = json["pixels"].toArray();
- qDebug() << jsonPixels.count() << rawProfile.pixels.size();
+ return result;
+}
- for (size_t i = 0; i < jsonPixels.count() && i < rawProfile.pixels.size(); ++i)
+static QSharedPointer<CalibrationTable> calibrate(const QList<Pixels>& rawProfiles)
+{
+ QSharedPointer<CalibrationTable> result { new CalibrationTable {{ 0 }} };
+
+ constexpr uint16_t discretesInRage { 16384 };
+
+ 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)
{
- rawProfile.pixels[i] = jsonPixels[i].toDouble();
+ 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 << ";";
+ }
}
- }
- // {
- // QMutexLocker l(&calibrationPixelsMutex);
- // std::swap(result, ::calibrationPixels);
- // }
+ std::cout << std::endl << std::flush;
+ }
return result;
+ // TODO: try something interesting
+ // return {};
+}
+
+bool initLaser()
+{
+ const QLatin1String pwmChip { "pwmchip2" };
+ const uint16_t pwmChannel { 1 };
+ const QLatin1String pwmSystemRoot { "/sys/class/pwm" };
+ const QString pwmChipRoot { pwmSystemRoot + "/" + pwmChip };
+
+ const QString pwmExportFile { pwmChipRoot + "/export" };
+
+ QFile f { pwmExportFile };
+
+ if (!f.open(QFile::WriteOnly))
+ {
+ qWarning() << "cannot open" << f.fileName() << "for writing";
+ qWarning() << "error:" << f.errorString();
+
+ return false;
+ }
+
+ QTextStream s { &f };
+ s << pwmChannel;
+
+ const QString pwm { QLatin1String("pwm%1").arg(QString::number(pwmChannel)) };
+ const QString pwmRoot { pwmChipRoot + "/" + pwm };
+
+ const QString periodFilename { pwmRoot + "/period" };
+ f.close();
+ f.setFileName(periodFilename);
+
+ if (!f.open(QFile::WriteOnly))
+ {
+ qWarning() << "cannot open" << f.fileName() << "for writing";
+ qWarning() << "error:" << f.errorString();
+
+ return false;
+ }
+
+ const unsigned periodHz { 50'000 };
+
+ s << periodHz;
+
+ const QString dutyCycleFilename { pwmRoot + "/duty_cycle" };
+ f.close();
+ f.setFileName(dutyCycleFilename);
+
+ if (!f.open(QFile::WriteOnly))
+ {
+ qWarning() << "cannot open" << f.fileName() << "for writing";
+ qWarning() << "error:" << f.errorString();
+
+ return false;
+ }
+
+ const unsigned dutyCycle { 3'000 };
+
+ s << dutyCycle;
+
+ const QString enableFilename { pwmRoot + "/enable" };
+ f.close();
+ f.setFileName(enableFilename);
+
+ if (!f.open(QFile::WriteOnly))
+ {
+ qWarning() << "cannot open" << f.fileName() << "for writing";
+ qWarning() << "error:" << f.errorString();
+
+ return false;
+ }
+
+ const int enable { 1 };
+
+ s << enable;
+
+ return true;
}