Skip to content

Commit

Permalink
Merge branch 'master' into feature/migrate-ccd-simulator
Browse files Browse the repository at this point in the history
  • Loading branch information
naheedsa committed Feb 29, 2024
2 parents c19932b + 97b1ebf commit 9dfc96d
Show file tree
Hide file tree
Showing 4 changed files with 369 additions and 341 deletions.
224 changes: 112 additions & 112 deletions drivers/ccd/guide_simulator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ GuideSim::GuideSim()
bool GuideSim::SetupParms()
{
int nbuf;
SetCCDParams(SimulatorSettingsN[0].value, SimulatorSettingsN[1].value, 16, SimulatorSettingsN[2].value,
SimulatorSettingsN[3].value);
SetCCDParams(SimulatorSettingsNP[SIM_XRES].getValue(), SimulatorSettingsNP[SIM_YRES].getValue(), 16, SimulatorSettingsNP[SIM_XSIZE].getValue(),
SimulatorSettingsNP[SIM_YRES].getValue());

if (HasCooler())
{
Expand All @@ -58,20 +58,20 @@ bool GuideSim::SetupParms()
}

// Kwiq
maxnoise = SimulatorSettingsN[8].value;
skyglow = SimulatorSettingsN[9].value;
maxval = SimulatorSettingsN[4].value;
bias = SimulatorSettingsN[5].value;
limitingmag = SimulatorSettingsN[7].value;
saturationmag = SimulatorSettingsN[6].value;
OAGoffset = SimulatorSettingsN[10].value; // An oag is offset this much from center of scope position (arcminutes);
polarError = SimulatorSettingsN[11].value;
polarDrift = SimulatorSettingsN[12].value;
rotationCW = SimulatorSettingsN[13].value;
maxnoise = SimulatorSettingsNP[SIM_NOISE].getValue();
skyglow = SimulatorSettingsNP[SIM_SKYGLOW].getValue();
maxval = SimulatorSettingsNP[SIM_MAXVAL].getValue();
bias = SimulatorSettingsNP[SIM_BIAS].getValue();
limitingmag = SimulatorSettingsNP[SIM_BIAS].getValue();
saturationmag = SimulatorSettingsNP[SIM_SATURATION].getValue();
OAGoffset = SimulatorSettingsNP[SIM_OAGOFFSET].getValue(); // An oag is offset this much from center of scope position (arcminutes);
polarError = SimulatorSettingsNP[SIM_POLAR].getValue();
polarDrift = SimulatorSettingsNP[SIM_POLARDRIFT].getValue();
rotationCW = SimulatorSettingsNP[SIM_ROTATION].getValue();
// Kwiq++
king_gamma = SimulatorSettingsN[14].value * 0.0174532925;
king_theta = SimulatorSettingsN[15].value * 0.0174532925;
TimeFactor = SimulatorSettingsN[16].value;
king_gamma = SimulatorSettingsNP[SIM_KING_GAMMA].getValue() * 0.0174532925;
king_theta = SimulatorSettingsNP[SIM_KING_THETA].getValue() * 0.0174532925;
TimeFactor = SimulatorSettingsNP[SIM_TIME_FACTOR].getValue();

nbuf = PrimaryCCD.getXRes() * PrimaryCCD.getYRes() * PrimaryCCD.getBPP() / 8;
//nbuf += 512;
Expand Down Expand Up @@ -117,47 +117,47 @@ bool GuideSim::initProperties()
CaptureFormat format = {"INDI_MONO", "Mono", 16, true};
addCaptureFormat(format);

IUFillNumber(&SimulatorSettingsN[0], "SIM_XRES", "CCD X resolution", "%4.0f", 0, 8192, 0, 1280);
IUFillNumber(&SimulatorSettingsN[1], "SIM_YRES", "CCD Y resolution", "%4.0f", 0, 8192, 0, 1024);
IUFillNumber(&SimulatorSettingsN[2], "SIM_XSIZE", "CCD X Pixel Size", "%4.2f", 0, 60, 0, 2.4);
IUFillNumber(&SimulatorSettingsN[3], "SIM_YSIZE", "CCD Y Pixel Size", "%4.2f", 0, 60, 0, 2.4);
IUFillNumber(&SimulatorSettingsN[4], "SIM_MAXVAL", "CCD Maximum ADU", "%4.0f", 0, 65000, 0, 65000);
IUFillNumber(&SimulatorSettingsN[5], "SIM_BIAS", "CCD Bias", "%4.0f", 0, 6000, 0, 10);
IUFillNumber(&SimulatorSettingsN[6], "SIM_SATURATION", "Saturation Mag", "%4.1f", 0, 20, 0, 1.0);
IUFillNumber(&SimulatorSettingsN[7], "SIM_LIMITINGMAG", "Limiting Mag", "%4.1f", 0, 20, 0, 17.0);
IUFillNumber(&SimulatorSettingsN[8], "SIM_NOISE", "CCD Noise", "%4.0f", 0, 6000, 0, 10);
IUFillNumber(&SimulatorSettingsN[9], "SIM_SKYGLOW", "Sky Glow (magnitudes)", "%4.1f", 0, 6000, 0, 19.5);
IUFillNumber(&SimulatorSettingsN[10], "SIM_OAGOFFSET", "Oag Offset (arcminutes)", "%4.1f", 0, 6000, 0, 0);
IUFillNumber(&SimulatorSettingsN[11], "SIM_POLAR", "PAE (arcminutes)", "%4.1f", -600, 600, 0,
0); /* PAE = Polar Alignment Error */
IUFillNumber(&SimulatorSettingsN[12], "SIM_POLARDRIFT", "PAE Drift (minutes)", "%4.1f", 0, 6000, 0, 0);
IUFillNumber(&SimulatorSettingsN[13], "SIM_ROTATION", "Rotation CW (degrees)", "%4.1f", -360, 360, 0, 0);
IUFillNumber(&SimulatorSettingsN[14], "SIM_KING_GAMMA", "(CP,TCP), deg", "%4.1f", 0, 10, 0, 0);
IUFillNumber(&SimulatorSettingsN[15], "SIM_KING_THETA", "hour hangle, deg", "%4.1f", 0, 360, 0, 0);
IUFillNumber(&SimulatorSettingsN[16], "SIM_TIME_FACTOR", "Time Factor (x)", "%.2f", 0.01, 100, 0, 1);

IUFillNumberVector(&SimulatorSettingsNP, SimulatorSettingsN, 17, getDeviceName(), "SIMULATOR_SETTINGS",
"Config", SIMULATOR_TAB, IP_RW, 60, IPS_IDLE);
SimulatorSettingsNP[SIM_XRES].fill("SIM_XRES", "CCD X resolution", "%4.0f", 0, 8192, 0, 1280);
SimulatorSettingsNP[SIM_YRES].fill("SIM_YRES", "CCD Y resolution", "%4.0f", 0, 8192, 0, 1024);
SimulatorSettingsNP[SIM_XSIZE].fill("SIM_XSIZE", "CCD X Pixel Size", "%4.2f", 0, 60, 0, 2.4);
SimulatorSettingsNP[SIM_YSIZE].fill("SIM_YSIZE", "CCD Y Pixel Size", "%4.2f", 0, 60, 0, 2.4);
SimulatorSettingsNP[SIM_MAXVAL].fill("SIM_MAXVAL", "CCD Maximum ADU", "%4.0f", 0, 65000, 0, 65000);
SimulatorSettingsNP[SIM_BIAS].fill("SIM_BIAS", "CCD Bias", "%4.0f", 0, 6000, 0, 10);
SimulatorSettingsNP[SIM_SATURATION].fill("SIM_SATURATION", "Saturation Mag", "%4.1f", 0, 20, 0, 1.0);
SimulatorSettingsNP[SIM_LIMITINGMAG].fill("SIM_LIMITINGMAG", "Limiting Mag", "%4.1f", 0, 20, 0, 17.0);
SimulatorSettingsNP[SIM_NOISE].fill("SIM_NOISE", "CCD Noise", "%4.0f", 0, 6000, 0, 10);
SimulatorSettingsNP[SIM_SKYGLOW].fill("SIM_SKYGLOW", "Sky Glow (magnitudes)", "%4.1f", 0, 6000, 0, 19.5);
SimulatorSettingsNP[SIM_OAGOFFSET].fill("SIM_OAGOFFSET", "Oag Offset (arcminutes)", "%4.1f", 0, 6000, 0, 0);
SimulatorSettingsNP[SIM_POLAR].fill("SIM_POLAR", "PAE (arcminutes)", "%4.1f", -600, 600, 0,
0); /* PAE = Polar Alignment Error */
SimulatorSettingsNP[SIM_POLARDRIFT].fill("SIM_POLARDRIFT", "PAE Drift (minutes)", "%4.1f", 0, 6000, 0, 0);
SimulatorSettingsNP[SIM_ROTATION].fill("SIM_ROTATION", "Rotation CW (degrees)", "%4.1f", -360, 360, 0, 0);
SimulatorSettingsNP[SIM_KING_GAMMA].fill("SIM_KING_GAMMA", "(CP,TCP), deg", "%4.1f", 0, 10, 0, 0);
SimulatorSettingsNP[SIM_KING_THETA].fill("SIM_KING_THETA", "hour hangle, deg", "%4.1f", 0, 360, 0, 0);
SimulatorSettingsNP[SIM_TIME_FACTOR].fill("SIM_TIME_FACTOR", "Time Factor (x)", "%.2f", 0.01, 100, 0, 1);

SimulatorSettingsNP.fill(getDeviceName(), "SIMULATOR_SETTINGS",
"Config", SIMULATOR_TAB, IP_RW, 60, IPS_IDLE);

// RGB Simulation
IUFillSwitch(&SimulateRgbS[0], "SIMULATE_YES", "Yes", ISS_OFF);
IUFillSwitch(&SimulateRgbS[1], "SIMULATE_NO", "No", ISS_ON);
IUFillSwitchVector(&SimulateRgbSP, SimulateRgbS, 2, getDeviceName(), "SIMULATE_RGB", "Simulate RGB",
SimulateRgbSP[SIMULATE_YES].fill("SIMULATE_YES", "Yes", ISS_OFF);
SimulateRgbSP[SIMULATE_NO].fill("SIMULATE_NO", "No", ISS_ON);
SimulateRgbSP.fill(getDeviceName(), "SIMULATE_RGB", "Simulate RGB",
SIMULATOR_TAB, IP_RW, ISR_1OFMANY, 60, IPS_IDLE);

IUFillSwitch(&CoolerS[0], "COOLER_ON", "ON", ISS_OFF);
IUFillSwitch(&CoolerS[1], "COOLER_OFF", "OFF", ISS_ON);
IUFillSwitchVector(&CoolerSP, CoolerS, 2, getDeviceName(), "CCD_COOLER", "Cooler", MAIN_CONTROL_TAB, IP_WO,
ISR_1OFMANY, 0, IPS_IDLE);
CoolerSP[COOLER_ON].fill("COOLER_ON", "ON", ISS_OFF);
CoolerSP[COOLER_OFF].fill("COOLER_OFF", "OFF", ISS_ON);
CoolerSP.fill(getDeviceName(), "CCD_COOLER", "Cooler", MAIN_CONTROL_TAB, IP_WO,
ISR_1OFMANY, 0, IPS_IDLE);

// CCD Gain
IUFillNumber(&GainN[0], "GAIN", "Gain", "%.f", 0, 100, 10, 50);
IUFillNumberVector(&GainNP, GainN, 1, getDeviceName(), "CCD_GAIN", "Gain", MAIN_CONTROL_TAB, IP_RW, 60, IPS_IDLE);
GainNP[0].fill("GAIN", "Gain", "%.f", 0, 100, 10, 50);
GainNP.fill(getDeviceName(), "CCD_GAIN", "Gain", MAIN_CONTROL_TAB, IP_RW, 60, IPS_IDLE);

IUFillNumber(&EqPEN[0], "RA_PE", "RA (hh:mm:ss)", "%010.6m", 0, 24, 0, 0);
IUFillNumber(&EqPEN[1], "DEC_PE", "DEC (dd:mm:ss)", "%010.6m", -90, 90, 0, 0);
IUFillNumberVector(&EqPENP, EqPEN, 2, getDeviceName(), "EQUATORIAL_PE", "EQ PE", SIMULATOR_TAB, IP_RW, 60,
IPS_IDLE);
EqPENP[RA_PE].fill("RA_PE", "RA (hh:mm:ss)", "%010.6m", 0, 24, 0, 0);
EqPENP[DEC_PE].fill("DEC_PE", "DEC (dd:mm:ss)", "%010.6m", -90, 90, 0, 0);
EqPENP.fill(getDeviceName(), "EQUATORIAL_PE", "EQ PE", SIMULATOR_TAB, IP_RW, 60,
IPS_IDLE);

// Timeout
ToggleTimeoutSP[INDI_ENABLED].fill("INDI_ENABLED", "Enabled", ISS_OFF);
Expand Down Expand Up @@ -215,9 +215,9 @@ void GuideSim::ISGetProperties(const char * dev)
{
INDI::CCD::ISGetProperties(dev);

defineProperty(&SimulatorSettingsNP);
defineProperty(&EqPENP);
defineProperty(&SimulateRgbSP);
defineProperty(SimulatorSettingsNP);
defineProperty(EqPENP);
defineProperty(SimulateRgbSP);
defineProperty(ToggleTimeoutSP);
}

Expand All @@ -228,9 +228,9 @@ bool GuideSim::updateProperties()
if (isConnected())
{
if (HasCooler())
defineProperty(&CoolerSP);
defineProperty(CoolerSP);

defineProperty(&GainNP);
defineProperty(GainNP);

SetupParms();

Expand All @@ -243,9 +243,9 @@ bool GuideSim::updateProperties()
else
{
if (HasCooler())
deleteProperty(CoolerSP.name);
deleteProperty(CoolerSP.getName());

deleteProperty(GainNP.name);
deleteProperty(GainNP.getName());
}

return true;
Expand All @@ -260,10 +260,10 @@ int GuideSim::SetTemperature(double temperature)
return 1;
}

CoolerS[0].s = ISS_ON;
CoolerS[1].s = ISS_OFF;
CoolerSP.s = IPS_BUSY;
IDSetSwitch(&CoolerSP, nullptr);
CoolerSP[COOLER_ON].setState(ISS_ON);
CoolerSP[COOLER_OFF].setState(ISS_OFF);
CoolerSP.setState(IPS_BUSY);
CoolerSP.apply();
return 0;
}

Expand Down Expand Up @@ -369,10 +369,10 @@ void GuideSim::TimerHit()
// Above 20, cooler is off
if (TemperatureN[0].value >= 20)
{
CoolerS[0].s = ISS_OFF;
CoolerS[0].s = ISS_ON;
CoolerSP.s = IPS_IDLE;
IDSetSwitch(&CoolerSP, nullptr);
CoolerSP[COOLER_ON].setState(ISS_OFF);
CoolerSP[COOLER_OFF].setState(ISS_ON);
CoolerSP.setState(IPS_IDLE);
CoolerSP.apply();
}
}

Expand All @@ -392,7 +392,7 @@ int GuideSim::DrawCcdFrame(INDI::CCDChip * targetChip)
else
exposure_time = ExposureRequest;

exposure_time *= (1 + sqrt(GainN[0].value));
exposure_time *= (1 + sqrt(GainNP[0].getValue()));

auto targetFocalLength = ScopeInfoNP[FocalLength].getValue() > 0 ? ScopeInfoNP[FocalLength].getValue() : snoopedFocalLength;

Expand Down Expand Up @@ -597,15 +597,15 @@ int GuideSim::DrawCcdFrame(INDI::CCDChip * targetChip)
// remember it is the center of the simulated image
double J2_mnt_d_rar = king_gamma * sin(J2decr) * sin(JnHAr - king_theta) / cos(J2decr);
double J2_mnt_rar = rar - J2_mnt_d_rar
; // rad = currentRA * 15.0; rar = rad * 0.0174532925; currentRA = J2000Pos.ra / 15.0;
; // rad = currentRA * 15.0; rar = rad * 0.0174532925; currentRA = J2000Pos.ra / 15.0;

// Imagine the HA axis points to HA=0, dec=89deg, then in the mount's coordinate
// system a star at true dec = 88 is seen at 89 deg in the mount's system
// Or in other words: if one uses the setting circle, that is the mount system,
// and set it to 87 deg then the real location is at 88 deg.
double J2_mnt_d_decr = king_gamma * cos(JnHAr - king_theta);
double J2_mnt_decr = decr + J2_mnt_d_decr
; // decr = cameradec * 0.0174532925; cameradec = currentDE + OAGoffset / 60; currentDE = J2000Pos.dec;
; // decr = cameradec * 0.0174532925; cameradec = currentDE + OAGoffset / 60; currentDE = J2000Pos.dec;
// IDLog("raw mod ra : %8.3f, dec: %8.3f (degree)\n", J2_mnt_rar / 0.0174532925, J2_mnt_decr / 0.0174532925 );
if (J2_mnt_decr > M_PI / 2.)
{
Expand Down Expand Up @@ -1001,54 +1001,54 @@ bool GuideSim::ISNewNumber(const char * dev, const char * name, double values[],
if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
{

if (!strcmp(name, GainNP.name))
if (GainNP.isNameMatch(name))
{
IUUpdateNumber(&GainNP, values, names, n);
GainNP.s = IPS_OK;
IDSetNumber(&GainNP, nullptr);
GainNP.update(values, names, n);
GainNP.setState(IPS_OK);
GainNP.apply();
return true;
}

if (strcmp(name, "SIMULATOR_SETTINGS") == 0)
{
IUUpdateNumber(&SimulatorSettingsNP, values, names, n);
SimulatorSettingsNP.s = IPS_OK;
SimulatorSettingsNP.update(values, names, n);
SimulatorSettingsNP.setState(IPS_OK);

// Reset our parameters now
SetupParms();
IDSetNumber(&SimulatorSettingsNP, nullptr);

maxnoise = SimulatorSettingsN[8].value;
skyglow = SimulatorSettingsN[9].value;
maxval = SimulatorSettingsN[4].value;
bias = SimulatorSettingsN[5].value;
limitingmag = SimulatorSettingsN[7].value;
saturationmag = SimulatorSettingsN[6].value;
OAGoffset = SimulatorSettingsN[10].value;
polarError = SimulatorSettingsN[11].value;
polarDrift = SimulatorSettingsN[12].value;
rotationCW = SimulatorSettingsN[13].value;
SimulatorSettingsNP.apply();

maxnoise = SimulatorSettingsNP[SIM_NOISE].getValue();
skyglow = SimulatorSettingsNP[SIM_SKYGLOW].getValue();
maxval = SimulatorSettingsNP[SIM_MAXVAL].getValue();
bias = SimulatorSettingsNP[SIM_BIAS].getValue();
limitingmag = SimulatorSettingsNP[SIM_LIMITINGMAG].getValue();
saturationmag = SimulatorSettingsNP[SIM_SATURATION].getValue();
OAGoffset = SimulatorSettingsNP[SIM_OAGOFFSET].getValue();
polarError = SimulatorSettingsNP[SIM_POLAR].getValue();
polarDrift = SimulatorSettingsNP[SIM_POLARDRIFT].getValue();
rotationCW = SimulatorSettingsNP[SIM_ROTATION].getValue();
// Kwiq++
king_gamma = SimulatorSettingsN[14].value * 0.0174532925;
king_theta = SimulatorSettingsN[15].value * 0.0174532925;
TimeFactor = SimulatorSettingsN[16].value;
king_gamma = SimulatorSettingsNP[SIM_KING_GAMMA].getValue() * 0.0174532925;
king_theta = SimulatorSettingsNP[SIM_KING_THETA].getValue() * 0.0174532925;
TimeFactor = SimulatorSettingsNP[SIM_TIME_FACTOR].getValue();

return true;
}

// Record PE EQ to simulate different position in the sky than actual mount coordinate
// This can be useful to simulate Periodic Error or cone error or any arbitrary error.
if (!strcmp(name, EqPENP.name))
if (EqPENP.isNameMatch(name))
{
IUUpdateNumber(&EqPENP, values, names, n);
EqPENP.s = IPS_OK;
EqPENP.update(values, names, n);
EqPENP.setState(IPS_OK);

INDI::IEquatorialCoordinates epochPos { EqPEN[AXIS_RA].value, EqPEN[AXIS_DE].value }, J2000Pos { 0, 0 };
INDI::IEquatorialCoordinates epochPos { EqPENP[AXIS_RA].getValue(), EqPENP[AXIS_DE].getValue() }, J2000Pos { 0, 0 };
INDI::ObservedToJ2000(&epochPos, ln_get_julian_from_sys(), &J2000Pos);
currentRA = J2000Pos.rightascension;
currentDE = J2000Pos.declination;
usePE = true;
IDSetNumber(&EqPENP, nullptr);
EqPENP.apply();
return true;
}
}
Expand All @@ -1061,43 +1061,43 @@ bool GuideSim::ISNewSwitch(const char * dev, const char * name, ISState * states
if (dev != nullptr && strcmp(dev, getDeviceName()) == 0)
{

if (!strcmp(name, SimulateRgbSP.name))
if (SimulateRgbSP.isNameMatch(name))
{
IUUpdateSwitch(&SimulateRgbSP, states, names, n);
int index = IUFindOnSwitchIndex(&SimulateRgbSP);
SimulateRgbSP.update(states, names, n);
int index = SimulateRgbSP.findOnSwitchIndex();
if (index == -1)
{
SimulateRgbSP.s = IPS_ALERT;
SimulateRgbSP.setState(IPS_ALERT);
LOG_INFO("Cannot determine whether RGB simulation should be switched on or off.");
IDSetSwitch(&SimulateRgbSP, nullptr);
SimulateRgbSP.apply();
return false;
}

simulateRGB = index == 0;
setRGB(simulateRGB);

SimulateRgbS[0].s = simulateRGB ? ISS_ON : ISS_OFF;
SimulateRgbS[1].s = simulateRGB ? ISS_OFF : ISS_ON;
SimulateRgbSP.s = IPS_OK;
IDSetSwitch(&SimulateRgbSP, nullptr);
SimulateRgbSP[SIMULATE_YES].setState(simulateRGB ? ISS_ON : ISS_OFF);
SimulateRgbSP[SIMULATE_NO].setState(simulateRGB ? ISS_OFF : ISS_ON);
SimulateRgbSP.setState(IPS_OK);
SimulateRgbSP.apply();

return true;
}

if (strcmp(name, CoolerSP.name) == 0)
if (CoolerSP.isNameMatch(name))
{
IUUpdateSwitch(&CoolerSP, states, names, n);
CoolerSP.update(states, names, n);

if (CoolerS[0].s == ISS_ON)
CoolerSP.s = IPS_BUSY;
if (CoolerSP[COOLER_ON].getState() == ISS_ON)
CoolerSP.setState(IPS_BUSY);
else
{
CoolerSP.s = IPS_IDLE;
CoolerSP.setState(IPS_IDLE);
TemperatureRequest = 20;
TemperatureNP.s = IPS_BUSY;
}

IDSetSwitch(&CoolerSP, nullptr);
CoolerSP.apply();

return true;
}
Expand Down Expand Up @@ -1176,13 +1176,13 @@ bool GuideSim::saveConfigItems(FILE * fp)


// Save CCD Simulator Config
IUSaveConfigNumber(fp, &SimulatorSettingsNP);
SimulatorSettingsNP.save(fp);

// Gain
IUSaveConfigNumber(fp, &GainNP);
GainNP.save(fp);

// RGB
IUSaveConfigSwitch(fp, &SimulateRgbSP);
SimulateRgbSP.save(fp);

return true;
}
Expand Down Expand Up @@ -1292,5 +1292,5 @@ void GuideSim::addFITSKeywords(INDI::CCDChip *targetChip, std::vector<INDI::FITS
{
INDI::CCD::addFITSKeywords(targetChip, fitsKeywords);

fitsKeywords.push_back({"GAIN", GainN[0].value, 3, "Gain"});
fitsKeywords.push_back({"GAIN", GainNP[0].getValue(), 3, "Gain"});
}
Loading

0 comments on commit 9dfc96d

Please sign in to comment.