MAClient/src/cameras.cpp
uvos b9b4b0fc2a fix various bugs
add commandline parser for various options
allow cameras to be operated in serial fashion
allow disabeling of quirks
allow changing of Photonfocus quirk timeings
2021-07-08 11:24:19 +02:00

337 lines
7.2 KiB
C++

#include "cameras.h"
#include <QRandomGenerator>
#include <string>
#include <functional>
#include <QDebug>
#include <unistd.h>
#include <QTimer>
Cameras::Cameras(uvosled* led, bool quirks, bool serial):
led_(led), quirks_(quirks), serial_(serial)
{
ledTimer.setSingleShot(true);
cameraFailureTimer.setSingleShot(true);
connect(&ledTimer, &QTimer::timeout, this, &Cameras::lightOff);
connect(&cameraFailureTimer, &QTimer::timeout, this, &Cameras::reloadCameras);
}
Cameras::~Cameras()
{
lightOff();
}
bool Cameras::setCameras(const std::vector<cam::Camera::Description>& descriptions)
{
clear();
bool ret = true;
for(auto& camera : descriptions)
{
if(!addCamera(camera))
ret = false;
}
return ret;
}
void Cameras::reloadCameras()
{
setCameras(getCameras());
}
void Cameras::clear()
{
free_ = false;
for(auto& camera : cameras_)
cameraRemoved(camera);
cameras_.clear();
if(led_)
uvosled_set_current(led_, 0xFF, 0);
}
std::vector<cam::Camera::Description> Cameras::getCameras()
{
std::vector<cam::Camera::Description> desc;
desc.reserve(cameras_.size());
for(std::shared_ptr<Camera> camera : cameras_)
desc.push_back(camera->cam()->getDescription());
return desc;
}
std::shared_ptr<Camera> Cameras::getCamera(size_t id)
{
std::vector<cam::Camera::Description> desc = getCameras();
for(size_t i = 0; i < desc.size(); ++i)
{
if(desc[i].getId() == id)
return cameras_[i];
}
return std::shared_ptr<Camera>(nullptr);
}
bool Cameras::addCamera(const cam::Camera::Description& desc)
{
cameras_.push_back(std::shared_ptr<Camera>(new Camera(desc)));
if(!cameras_.back()->cam()->isOpen())
{
cameras_.pop_back();
return false;
}
enableCapture(false);
blockCaptureId_ = cameras_.back()->id();
cameras_.back()->cam()->setExposureTime(exposrueTime_);
if(quirks_ && desc.getVendor().find("Photonfocus") != std::string::npos)
{
qDebug()<<"Mitiagting broken PhotonFocus single shot mode";
std::shared_ptr<Camera> camera = cameras_.back();
camera->cam()->setTriggerMode(cam::Camera::TRIGGER_FREE);
camera->cam()->setAcquisitionMode(cam::Camera::MODE_FREE);
camera->cam()->setFrameRate(10);
camera->cam()->startAcquisition();
std::this_thread::sleep_for (std::chrono::milliseconds(200));
camera->cam()->stopAcquisition();
cameras_.pop_back();
camera = nullptr;
std::this_thread::sleep_for (std::chrono::milliseconds(200));
cameras_.push_back(std::shared_ptr<Camera>(new Camera(desc)));
if(!cameras_.back()->cam()->isOpen())
{
cameras_.pop_back();
return false;
}
camera = cameras_.back();
cameraAdded(camera);
camera->cam()->setTriggerMode(cam::Camera::TRIGGER_FREE);
camera->cam()->setAcquisitionMode(cam::Camera::MODE_FREE);
camera->cam()->setFrameRate(10);
camera->cam()->startAcquisition();
if(!serial_)
QTimer::singleShot(quirkTime, this, [this, camera](){finishAddCamera(camera);});
else
{
std::this_thread::sleep_for(std::chrono::microseconds(static_cast<long>(quirkTime*1000)));
finishAddCamera(camera);
}
}
else
{
finishAddCamera(cameras_.back());
}
return true;
}
void Cameras::finishAddCamera(std::shared_ptr<Camera> camera)
{
camera->cam()->setTriggerMode(cam::Camera::TRIGGER_SOFTWARE);
setFree(free_);
connect(camera.get(), &Camera::newImage, this, &Cameras::imageRecived);
if(blockCaptureId_ == camera->id())
enableCapture(true);
qDebug()<<"Using camera"<<camera->id();
}
bool Cameras::lightFor(const LightingSetup& lighting, double time)
{
int ret = 0;
if(led_)
{
ret = uvosled_set_current(led_, lighting.mask, lighting.brightness);
ledTimer.start(time*1000);
}
return ret == 0;
}
void Cameras::lightOff()
{
if(led_)
uvosled_set_current(led_, 0xff, 0);
ledTimer.stop();
}
void Cameras::trigger()
{
if(serial_)
{
if(captureingCamera == 0)
lightFor(lighting_, exposrueTime_*1.5*cameras_.size());
cameras_[captureingCamera]->cam()->trigger();
++captureingCamera;
if(captureingCamera < cameras_.size())
QTimer::singleShot(exposrueTime_*1000, this, &Cameras::trigger);
else
captureingCamera = 0;
}
else
{
lightFor(lighting_, exposrueTime_*1.5);
for(auto& camera : cameras_)
camera->cam()->trigger();
}
}
bool Cameras::start()
{
bool ret = true;
for(auto& camera : cameras_)
{
if(!camera->cam()->startAcquisition())
ret = false;
}
if(free_)
uvosled_set_current(led_, lighting_.mask, lighting_.brightness);
return ret;
}
bool Cameras::stop()
{
bool ret = true;
for(auto& camera : cameras_)
{
if(!camera->cam()->stopAcquisition())
ret = false;
}
lightOff();
return ret;
}
void Cameras::disable(bool disable)
{
disable_ = disable;
}
bool Cameras::setFree(bool free)
{
stop();
free_ = free;
bool ret = true;
for(auto& camera : cameras_)
{
if(!camera->cam()->setAcquisitionMode(free ? cam::Camera::MODE_FREE : cam::Camera::MODE_SINGLE))
{
qDebug()<<"failed to set acquisition mode on camera"<<camera->id();
ret = false;
}
if(ret)
camera->cam()->setTriggerMode(free ? cam::Camera::TRIGGER_FREE : cam::Camera::TRIGGER_SOFTWARE);
}
return ret;
}
bool Cameras::setExposureTime(double exposureTime)
{
stop();
exposrueTime_ = exposureTime;
bool ret = true;
for(auto& camera : cameras_)
{
if(!camera->cam()->setExposureTime(exposrueTime_*1000000))
{
qDebug()<<"failed to set exposure on camera"<<camera->id();
ret = false;
}
}
return ret;
}
void Cameras::imageRecived(Camera::Image img)
{
if(!disable_)
{
qDebug()<<"free"<<free_;
bool allreadyUpdated = false;
for(auto& image : images_)
{
if(image.cameraId == img.cameraId)
{
allreadyUpdated = true;
break;
}
}
if(!allreadyUpdated)
images_.push_back(img);
qDebug()<<"Recived"<<images_.size()<<"of"<<cameras_.size()<<"images";
if(images_.size() == 1)
{
if(!serial_)
cameraFailureTimer.start(exposrueTime_*1000+1000);
else
cameraFailureTimer.start(exposrueTime_*1000*(cameras_.size()+1)+2000);
}
if(images_.size() == cameras_.size())
{
cameraFailureTimer.stop();
newImages(images_);
images_.clear();
}
}
}
double Cameras::getMeanTemp()
{
double mean = 0;
bool failure = false;
for(auto& camera : cameras_)
{
double temp;
if(camera->cam()->getTemperature(temp))
mean+=temp;
else
failure = true;
}
if(!failure)
return mean/cameras_.size();
else
return NAN;
}
void Cameras::setSetup(const std::vector<CameraSetup>& setups)
{
for(auto& camera : cameras_)
for(auto& setup : setups)
if(camera->id() == setup.id)
camera->cam()->setBayerMode(setup.bayerMode);
}
void Cameras::store(QSettings &settings)
{
std::vector<cam::Camera::Description> available = cam::Camera::getAvailableCameras();
settings.beginWriteArray(GROUP, cameras_.size());
for(size_t i = 0; i < cameras_.size(); ++i)
{
settings.setArrayIndex(i);
settings.setValue("id", static_cast<unsigned long long>(cameras_[i]->id()));
}
settings.endArray();
}
void Cameras::load(QSettings &settings)
{
std::vector<cam::Camera::Description> available = cam::Camera::getAvailableCameras();
int size = settings.beginReadArray(GROUP);
for(int i = 0; i < size; ++i)
{
settings.setArrayIndex(i);
size_t hash = settings.value("id", 0).toULongLong();
for(auto& camera : available)
{
if(camera.getId() == hash)
addCamera(camera);
}
}
settings.endArray();
}