Commit 146c4430 authored by Jasem Mutlaq's avatar Jasem Mutlaq
Browse files

+ Automated flat field with devices with dust cap ready. Need to implement slewing to a wall.

+ Fix issue in shutdown script exist status.
+ Separated sequence job from capture.
+ Ekos capture module now remember job progress and continue where it was last completed by looking at which files were already captured. This option is toggable in the options.
parent 362e9475
......@@ -61,6 +61,7 @@ if (INDI_FOUND)
indi/indidome.cpp
indi/indiweather.cpp
indi/indicap.cpp
indi/indilightbox.cpp
indi/indidbus.cpp
indi/opsindi.cpp
indi/telescopewizardprocess.cpp
......@@ -80,7 +81,7 @@ if (CFITSIO_FOUND)
ekos/opsekos.ui
ekos/ekosmanager.ui
ekos/capture.ui
ekos/flatoptions.ui
ekos/calibrationoptions.ui
ekos/align.ui
ekos/focus.ui
ekos/guide.ui
......@@ -94,6 +95,7 @@ if (CFITSIO_FOUND)
ekos/scheduler.cpp
ekos/ekosmanager.cpp
ekos/capture.cpp
ekos/sequencejob.cpp
ekos/focus.cpp
ekos/guide.cpp
ekos/align.cpp
......
......@@ -53,6 +53,8 @@ Align::Align()
new AlignAdaptor(this);
QDBusConnection::sessionBus().registerObject("/KStars/Ekos/Align", this);
dirPath = QDir::homePath();
currentCCD = NULL;
currentTelescope = NULL;
currentFilter = NULL;
......@@ -1454,11 +1456,13 @@ void Align::getFormattedCoords(double ra, double dec, QString &ra_str, QString &
void Align::loadAndSlew(QUrl fileURL)
{
if (fileURL.isEmpty())
fileURL = QFileDialog::getOpenFileUrl(KStars::Instance(), i18n("Load Image"), QUrl(), "Images (*.fits *.fit *.jpg *.jpeg)");
fileURL = QFileDialog::getOpenFileUrl(KStars::Instance(), i18n("Load Image"), dirPath, "Images (*.fits *.fit *.jpg *.jpeg)");
if (fileURL.isEmpty())
return;
dirPath = fileURL.path().remove(fileURL.fileName());
loadSlewMode = true;
loadSlewState=IPS_BUSY;
......
......@@ -429,6 +429,8 @@ private:
// Track which upload mode the CCD is set to. If set to UPLOAD_LOCAL, then we need to switch it to UPLOAD_CLIENT in order to do focusing, and then switch it back to UPLOAD_LOCAL
ISD::CCD::UploadMode rememberUploadMode;
QString dirPath;
};
......
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>flatOptions</class>
<widget class="QDialog" name="flatOptions">
<class>calibrationOptions</class>
<widget class="QDialog" name="calibrationOptions">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>439</width>
<height>199</height>
<height>213</height>
</rect>
</property>
<property name="windowTitle">
<string>Flat Field Options</string>
<string>Calibration Options</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
......@@ -62,7 +62,7 @@
<string>Light source provided by controllable electronic device</string>
</property>
<property name="text">
<string>Device</string>
<string>Dust Cap</string>
</property>
</widget>
</item>
......@@ -186,6 +186,20 @@
</item>
</layout>
</item>
<item>
<widget class="QCheckBox" name="parkMountC">
<property name="text">
<string>Park Mount</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="parkDomeC">
<property name="text">
<string>Park Dome</string>
</property>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
......@@ -222,7 +236,7 @@
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>flatOptions</receiver>
<receiver>calibrationOptions</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
......@@ -238,7 +252,7 @@
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>flatOptions</receiver>
<receiver>calibrationOptions</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
......
This diff is collapsed.
......@@ -10,8 +10,6 @@
#ifndef CAPTURE_H
#define CAPTURE_H
#include "capture.h"
#include <QTimer>
#include <QUrl>
#include <QtDBus/QtDBus>
......@@ -21,6 +19,9 @@
#include "fitsviewer/fitscommon.h"
#include "indi/indistd.h"
#include "indi/indiccd.h"
#include "indi/indicap.h"
#include "indi/indidome.h"
#include "indi/indilightbox.h"
#include "indi/inditelescope.h"
class QProgressIndicator;
......@@ -57,154 +58,9 @@ class KDirWatch;
*@version 1.1
*/
namespace Ekos
{
class SequenceJob : public QObject
{
Q_OBJECT
public:
typedef enum { JOB_IDLE, JOB_BUSY, JOB_ERROR, JOB_ABORTED, JOB_DONE } JOBStatus;
typedef enum { CAPTURE_OK, CAPTURE_FRAME_ERROR, CAPTURE_BIN_ERROR, CAPTURE_FILTER_BUSY, CAPTURE_FOCUS_ERROR} CAPTUREResult;
typedef enum { SOURCE_MANUAL, SOURCE_DEVICE, SOURCE_WALL, SOURCE_DAWN_DUSK } FlatFieldSource;
typedef enum { DURATION_MANUAL, DURATION_ADU } FlatFieldDuration;
SequenceJob();
CAPTUREResult capture(bool isDark=false);
void reset();
void abort();
void done();
void prepareCapture();
JOBStatus getStatus() { return status; }
const QString & getStatusString() { return statusStrings[status]; }
bool isPreview() { return preview;}
int getDelay() { return delay;}
int getCount() { return count;}
unsigned int getCompleted() { return completed; }
const QString & getPrefix() { return prefix;}
double getExposure() const { return exposure;}
void setActiveCCD(ISD::CCD *ccd) { activeCCD = ccd; }
ISD::CCD *getActiveCCD() { return activeCCD;}
void setActiveFilter(ISD::GDInterface *filter) { activeFilter = filter; }
ISD::GDInterface *getActiveFilter() { return activeFilter;}
void setActiveChip(ISD::CCDChip *chip) { activeChip = chip; }
ISD::CCDChip *getActiveChip() { return activeChip;}
void setFITSDir(const QString &dir) { fitsDir = dir;}
const QString & getFITSDir() { return fitsDir; }
void setTargetFilter(int pos, const QString & name);
int getTargetFilter() { return targetFilter;}
int getCurrentFilter() const;
void setCurrentFilter(int value);
const QString &getFilterName() { return filter; }
void setFrameType(int type, const QString & name);
int getFrameType() { return frameType;}
void setCaptureFilter(FITSScale capFilter) { captureFilter = capFilter; }
void setISOMode(bool mode) { isoMode = mode; }
bool getISOMode() { return isoMode;}
void setPreview(bool enable) { preview = enable; }
void setPrefix(const QString &cprefix) { prefix = cprefix;}
void setFrame(int in_x, int in_y, int in_w, int in_h) { x=in_x; y=in_y; w=in_w; h=in_h; }
int getSubX() { return x;}
int getSubY() { return y;}
int getSubW() { return w;}
int getSubH() { return h;}
void setBin(int xbin, int ybin) { binX = xbin; binY=ybin;}
int getXBin() { return binX; }
int getYBin() { return binY; }
void setDelay(int in_delay) { delay = in_delay; }
void setCount(int in_count) { count = in_count;}
void setImageType(int type) { imageType = type;}
void setExposure(double duration) { exposure = duration;}
void setStatusCell(QTableWidgetItem *cell) { statusCell = cell; }
void setCompleted(unsigned int in_completed) { completed = in_completed;}
int getISOIndex() const;
void setISOIndex(int value);
double getExposeLeft() const;
void setExposeLeft(double value);
void resetStatus();
void setPrefixSettings(const QString &prefix, bool typeEnabled, bool filterEnabled, bool exposureEnabled);
void getPrefixSettings(QString &prefix, bool &typeEnabled, bool &filterEnabled, bool &exposureEnabled);
double getCurrentTemperature() const;
void setCurrentTemperature(double value);
double getTargetTemperature() const;
void setTargetTemperature(double value);
double getTargetADU() const;
void setTargetADU(double value);
int getCaptureRetires() const;
void setCaptureRetires(int value);
FlatFieldSource getFlatFieldSource() const;
void setFlatFieldSource(const FlatFieldSource &value);
FlatFieldDuration getFlatFieldDuration() const;
void setFlatFieldDuration(const FlatFieldDuration &value);
SkyPoint getWallCoord() const;
void setWallCoord(const SkyPoint &value);
signals:
void prepareComplete();
{
private:
QStringList statusStrings;
ISD::CCDChip *activeChip;
ISD::CCD *activeCCD;
ISD::GDInterface *activeFilter;
double exposure;
int frameType;
QString frameTypeName;
int targetFilter;
int currentFilter;
QString filter;
int imageType;
int binX, binY;
int x,y,w,h;
QString prefix;
int count;
int delay;
bool isoMode;
bool preview;
bool filterReady, temperatureReady;
int isoIndex;
int captureRetires;
unsigned int completed;
double exposeLeft;
double currentTemperature, targetTemperature;
FITSScale captureFilter;
QTableWidgetItem *statusCell;
QString fitsDir;
bool typePrefixEnabled, filterPrefixEnabled, expPrefixEnabled;
QString rawPrefix;
JOBStatus status;
// Flat field variables
struct
{
double targetADU;
FlatFieldSource flatFieldSource;
FlatFieldDuration flatFieldDuration;
SkyPoint wallCoord;
} flatSettings;
};
class SequenceJob;
/**
*@class Capture
......@@ -226,7 +82,7 @@ public:
enum { CALIBRATE_NONE, CALIBRATE_START, CALIBRATE_DONE };
typedef enum { MF_NONE, MF_INITIATED, MF_FLIPPING, MF_SLEWING, MF_ALIGNING, MF_GUIDING } MFStage;
typedef enum { FLAT_NONE, FLAT_UNPARK_CAP, FLAT_TURN_ON, FLAT_SLEWING, FLAT_CALIBRATING, FLAT_BUSY } FlatStage;
typedef enum { FLAT_NONE, FLAT_DUSTCAP_PARKING, FLAT_DUSTCAP_PARKED, FLAT_LIGHTBOX_ON, FLAT_SLEWING, FLAT_SLEWING_COMPLETE, FLAT_MOUNT_PARKING, FLAT_MOUNT_PARKED, FLAT_DOME_PARKING, FLAT_DOME_PARKED, FLAT_PRECAPTURE_COMPLETE, FLAT_CALIBRATION, FLAT_CALIBRATION_COMPLETE, FLAT_CAPTURING} FlatStage;
Capture();
~Capture();
......@@ -353,7 +209,9 @@ public:
void addCCD(ISD::GDInterface *newCCD, bool isPrimaryCCD);
void addFilter(ISD::GDInterface *newFilter);
void setFlatFieldDevice(ISD::GDInterface *device) { flatFieldDevice = device; }
void setDome(ISD::GDInterface *device) { dome = dynamic_cast<ISD::Dome*>(device); }
void setDustCap(ISD::GDInterface *device) { dustCap = dynamic_cast<ISD::DustCap*>(device); }
void setLightBox(ISD::GDInterface *device) { lightBox = dynamic_cast<ISD::LightBox*>(device); }
void addGuideHead(ISD::GDInterface *newCCD);
void syncFrameType(ISD::GDInterface *ccd);
void setTelescope(ISD::GDInterface *newTelescope);
......@@ -493,7 +351,8 @@ private slots:
void updateFocusStatus(bool status);
void updateAutofocusStatus(bool status, double HFR);
void updateCaptureProgress(ISD::CCDChip *tChip, double value, IPState state);
void checkSeqBoundary(const QString &path);
void checkSeqBoundary(const QString &path);
void checkSeqFile(const QString &path);
void saveFITSDirectory();
void setGuideChip(ISD::CCDChip* chip) { guideChip = chip; }
......@@ -512,13 +371,15 @@ private slots:
void enableAlignmentFlag();
// Flat field
void openFlatFieldDialog();
void openCalibrationDialog();
IPState processPreCaptureFlatStage();
bool processPostCaptureFlatStage();
signals:
void newLog();
void exposureComplete();
void checkFocus(double);
void telescopeParking();
void mountParking();
void suspendGuiding(bool);
void meridianFlipStarted();
void meridialFlipTracked();
......@@ -530,11 +391,11 @@ private:
void startNextExposure();
void updateFrameProperties();
void prepareJob(SequenceJob *job);
bool processJobInfo(XMLEle *root);
bool processJobInfo(XMLEle *root);
void processJobCompletion();
bool saveSequenceQueue(const QString &path);
void constructPrefix(QString &imagePrefix);
double setCurrentADU(double value);
void processFlatStage();
double setCurrentADU(double value);
/* Meridian Flip */
bool checkMeridianFlip();
......@@ -570,7 +431,9 @@ private:
ISD::Telescope *currentTelescope;
ISD::CCD *currentCCD;
ISD::GDInterface *currentFilter;
ISD::GDInterface *flatFieldDevice;
ISD::DustCap *dustCap;
ISD::LightBox *lightBox;
ISD::Dome *dome;
ITextVectorProperty *filterName;
INumberVectorProperty *filterSlot;
......@@ -609,13 +472,17 @@ private:
double ADUSlope;
double targetADU;
SkyPoint wallCoord;
SequenceJob::FlatFieldDuration flatFieldDuration;
SequenceJob::FlatFieldSource flatFieldSource;
bool preMountPark, preDomePark;
FlatFieldDuration flatFieldDuration;
FlatFieldSource flatFieldSource;
FlatStage flatStage;
bool dustCapLightEnabled, lightBoxLightEnabled;
// File HFR
double fileHFR;
QString dirPath;
};
}
......
......@@ -103,12 +103,20 @@ bool DustCap::hasLight()
return currentDustCap->hasLight();
}
bool DustCap::setLight(uint8_t val)
bool DustCap::setLightEnabled(bool enable)
{
if (currentDustCap == NULL)
return false;
return currentDustCap->SetLight(val);
return currentDustCap->SetLightEnabled(enable);
}
bool DustCap::setBrightness(uint16_t val)
{
if (currentDustCap == NULL)
return false;
return currentDustCap->SetBrightness(val);
}
}
......
......@@ -68,11 +68,17 @@ public:
Q_SCRIPTABLE bool hasLight();
/** DBUS interface function.
* SetLight: Turn on/off flat light and set intensity, if supported.
* setLightEnabled: Turn on/off light box
* @param enable If true, turn light on, otherwise turn light off
* @return True if operation started/successful, false otherwise
*/
Q_SCRIPTABLE bool setLight(uint8_t val);
Q_SCRIPTABLE bool setLightEnabled(bool enable);
/** DBUS interface function.
* SetLight: Set light source brightness level
* @return True if operation started/successful, false otherwise
*/
Q_SCRIPTABLE bool setBrightness(uint16_t val);
/** DBUS interface function.
* Get the dome park status
......
......@@ -72,7 +72,7 @@ EkosManager::EkosManager()
dome = NULL;
weather = NULL;
dustCap = NULL;
flatLight= NULL;
lightBox= NULL;
scope_di = NULL;
ccd_di = NULL;
......@@ -1060,6 +1060,7 @@ bool EkosManager::start()
connect(INDIListener::Instance(), SIGNAL(newDome(ISD::GDInterface*)), this, SLOT(setDome(ISD::GDInterface*)));
connect(INDIListener::Instance(), SIGNAL(newWeather(ISD::GDInterface*)), this, SLOT(setWeather(ISD::GDInterface*)));
connect(INDIListener::Instance(), SIGNAL(newDustCap(ISD::GDInterface*)), this, SLOT(setDustCap(ISD::GDInterface*)));
connect(INDIListener::Instance(), SIGNAL(newLightBox(ISD::GDInterface*)), this, SLOT(setLightBox(ISD::GDInterface*)));
connect(INDIListener::Instance(), SIGNAL(newST4(ISD::ST4*)), this, SLOT(setST4(ISD::ST4*)));
connect(INDIListener::Instance(), SIGNAL(deviceRemoved(ISD::GDInterface*)), this, SLOT(removeDevice(ISD::GDInterface*)), Qt::DirectConnection);
connect(DriverManager::Instance(), SIGNAL(serverTerminated(QString,QString)), this, SLOT(cleanDevices()));
......@@ -1834,6 +1835,7 @@ void EkosManager::setCCD(ISD::GDInterface *ccdDevice)
alignProcess->setTelescope(scope);
captureProcess->setTelescope(scope);
}
}
/*void EkosManager::setCCD(ISD::GDInterface *ccdDevice)
......@@ -1970,6 +1972,17 @@ void EkosManager::setDustCap(ISD::GDInterface *dustCapDevice)
dustCapProcess->setDustCap(dustCap);
appendLogText(i18n("%1 is online.", dustCap->getDeviceName()));
if (captureProcess)
captureProcess->setDustCap(dustCap);
}
void EkosManager::setLightBox(ISD::GDInterface *lightBoxDevice)
{
lightBox = lightBoxDevice;
if (captureProcess)
captureProcess->setLightBox(lightBoxDevice);
}
void EkosManager::removeDevice(ISD::GDInterface* devInterface)
......@@ -2151,13 +2164,6 @@ void EkosManager::processNewProperty(INDI::Property* prop)
return;
}
if (!strcmp(prop->getName(), "FLAT_LIGHT_CONTROL"))
{
flatLight = dynamic_cast<ISD::GDInterface*>(sender());
if (flatLight && captureProcess)
captureProcess->setFlatFieldDevice(flatLight);
}
}
void EkosManager::processTabChange()
......@@ -2265,8 +2271,10 @@ void EkosManager::initCapture()
toolsWidget->tabBar()->setTabToolTip(index, i18nc("Charge-Coupled Device", "CCD"));
connect(captureProcess, SIGNAL(newLog()), this, SLOT(updateLog()));
if (flatLight)
captureProcess->setFlatFieldDevice(flatLight);
if (dustCap)
captureProcess->setDustCap(dustCap);
if (lightBox)
captureProcess->setLightBox(lightBox);
if (focusProcess)
{
......@@ -2420,7 +2428,7 @@ void EkosManager::initGuide()
connect(captureProcess, SIGNAL(exposureComplete()), guideProcess, SLOT(dither()));
// Parking
connect(captureProcess, SIGNAL(telescopeParking()), guideProcess, SLOT(stopGuiding()));
connect(captureProcess, SIGNAL(mountParking()), guideProcess, SLOT(stopGuiding()));
// Guide Head
connect(captureProcess, SIGNAL(suspendGuiding(bool)), guideProcess, SLOT(setSuspended(bool)));
......@@ -2518,7 +2526,7 @@ void EkosManager::removeTabs()
delete (dustCapProcess);
dustCapProcess = NULL;
flatLight = NULL;
lightBox = NULL;
aux1 = NULL;
aux2 = NULL;
......
......@@ -217,6 +217,7 @@ protected slots:
void setDome(ISD::GDInterface *);
void setWeather(ISD::GDInterface *);
void setDustCap(ISD::GDInterface *);
void setLightBox(ISD::GDInterface *);
void setST4(ISD::ST4 *);
private:
......@@ -250,7 +251,7 @@ protected slots:
bool remoteCCDRegistered;
bool remoteGuideRegistered;
ISD::GDInterface *scope, *ccd, *guider, *focuser, *filter, *aux1, *aux2, *aux3, *aux4, *dome, *ao, *weather, *dustCap, *flatLight;
ISD::GDInterface *scope, *ccd, *guider, *focuser, *filter, *aux1, *aux2, *aux3, *aux4, *dome, *ao, *weather, *dustCap, *lightBox;
DriverInfo *scope_di, *ccd_di, *guider_di, *filter_di, *focuser_di, *aux1_di, *aux2_di, *aux3_di,*aux4_di, *ao_di, *dome_di, *weather_di, *remote_indi;
Ekos::Capture *captureProcess;
......
......@@ -6,11 +6,11 @@
<rect>
<x>0</x>
<y>0</y>
<width>462</width>
<height>655</height>
<width>486</width>
<height>583</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_5">
<layout class="QVBoxLayout" name="verticalLayout_6">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
......@@ -130,110 +130,144 @@
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_6">
<property name="title">
<string>Scheduler</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="leadTimeLabel">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Lead time is the minimum time in minutes between jobs. The scheduler starts execution of a job before its scheduled startup time by this lead time. Early execution is useful as focusing, alignment, and guiding procedures may take prolonged periods to time to complete.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Lead Time:</string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="kcfg_LeadTime"/>
</item>
<item>
<widget class="QLabel" name="preDawnLabel">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Do not permit jobs to be scheduled or executed past this many minutes before dawn.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Pre-dawn</string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="kcfg_PreDawnTime"/>
</item>
<item>
<widget class="QLabel" name="label">
<property name="toolTip">
<string>Maximum acceptable difference between requested and measured temperature set point. When the temperature threshold is below this value, the temperature set point request is deemed successful.</string>
</property>
<property name="text">
<string>Temperature Threshold:</string>
</property>
</widget>
</item>
<layout class="QHBoxLayout" name="horizontalLayout_9">
<item>
<widget class="QGroupBox" name="groupBox_6">
<property name="title">
<string>Scheduler</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<widget class="QDoubleSpinBox" name="kcfg_MaxTemperatureDiff">
<property name="minimum">