add commandline parser for various options allow cameras to be operated in serial fashion allow disabeling of quirks allow changing of Photonfocus quirk timeings
337 lines
7.2 KiB
C++
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();
|
|
}
|