Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 32 additions & 5 deletions drivers/ccd/ccd_simulator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,14 @@ bool CCDSim::setupParameters()
m_PEPeriod = SimulatorSettingsNP[SIM_PE_PERIOD].getValue();
m_PEMax = SimulatorSettingsNP[SIM_PE_MAX].getValue();
m_TimeFactor = SimulatorSettingsNP[SIM_TIME_FACTOR].getValue();
RotatorAngle = SimulatorSettingsNP[SIM_ROTATION].getValue();
// This is the rotation of the simulated camera respective to North.
// Because the simulated star field is calculated with their RA/DEC-coordinates
// (see DrawCcdFrame()) the origin angle of star field points north. So this value
// for EQ mounts normally simulate a certain camera offset and is a constant.
// For ALTAZ-mount this variable is altered consecutively by the value of the parallactic
// angle (transfered through a signal from KStars/skymapdrawabstract.cpp) and this way used
// to simulate the deviation of the camera orientation from N.
m_CameraRotation = SimulatorSettingsNP[SIM_ROTATION].getValue();

uint32_t nbuf = PrimaryCCD.getXRes() * PrimaryCCD.getYRes() * PrimaryCCD.getBPP() / 8;
PrimaryCCD.setFrameBufferSize(nbuf);
Expand Down Expand Up @@ -137,6 +144,9 @@ bool CCDSim::initProperties()

SimulatorSettingsNP.fill(getDeviceName(), "SIMULATOR_SETTINGS",
"Settings", SIMULATOR_TAB, IP_RW, 60, IPS_IDLE);
// load() is important to fill all editfields with saved values also, so ISNewNumber() of one field
// doesn't update the other fields of the group with the "old" contents.
SimulatorSettingsNP.load();

// RGB Simulation
SimulateBayerSP[INDI_ENABLED].fill("INDI_ENABLED", "Enabled", ISS_OFF);
Expand Down Expand Up @@ -607,15 +617,18 @@ int CCDSim::DrawCcdFrame(INDI::CCDChip * targetChip)
"pprx: %g pixels per radian ppry: %g pixels per radian ScaleX: %g arcsecs/pixel ScaleY: %g arcsecs/pixel",
pprx, ppry, Scalex, Scaley);
#endif

double theta = 270;
m_CameraRotation = SimulatorSettingsNP[SIM_ROTATION].getValue();
double theta = m_CameraRotation;
if (!std::isnan(RotatorAngle))
theta += RotatorAngle;
if (pierSide == 1)
theta -= 180; // rotate 180 if on East
theta = range360(theta);
LOGF_DEBUG("Rotator Angle: %f, Camera Rotation: %f", RotatorAngle, m_CameraRotation);

// JM: 2015-03-17: Next we do a rotation assuming CW for angle theta
// TS: 2025-06-09: Below we have "Invert horizontally" and in the end
// this produces a rotation CCW with origin N (TODO: adjust matrix?)
pa = pprx * cos(theta * M_PI / 180.0);
pb = ppry * sin(theta * M_PI / 180.0);

Expand Down Expand Up @@ -778,7 +791,7 @@ int CCDSim::DrawCcdFrame(INDI::CCDChip * targetChip)
ccdx = pa * sx + pb * sy + pc;
ccdy = pd * sx + pe * sy + pf;

// Invert horizontally
// Invert horizontally and transform CW to CCW (see above)
ccdx = ccdW - ccdx;

rc = DrawImageStar(targetChip, mag, ccdx, ccdy, exposure_time);
Expand Down Expand Up @@ -1312,7 +1325,7 @@ bool CCDSim::ISSnoopDevice(XMLEle * root)
if (!strcmp(name, "FOCUS_ABSOLUTE_POSITION"))
{
FocuserPos = atol(pcdataXMLEle(ep));

LOGF_DEBUG("Snooped FocuserPosition %g", FocuserPos);
// calculate FWHM
double focus = FocusSimulationNP[SIM_FOCUS_POSITION].getValue();
double max = FocusSimulationNP[SIM_FOCUS_MAX].getValue();
Expand All @@ -1326,6 +1339,20 @@ bool CCDSim::ISSnoopDevice(XMLEle * root)
}
}
}
else if (!strcmp(propName, "ABS_ROTATOR_ANGLE"))
{
for (ep = nextXMLEle(root, 1); ep != nullptr; ep = nextXMLEle(root, 0))
{
const char * name = findXMLAttValu(ep, "name");

if (!strcmp(name, "ANGLE"))
{
RotatorAngle = atof(pcdataXMLEle(ep));
LOGF_DEBUG("Snooped RotatorAngle %f", RotatorAngle);
return true;
}
}
}
// We try to snoop EQPEC first, if not found, we snoop regular EQNP
#ifdef USE_EQUATORIAL_PE
const char * propName = findXMLAttValu(root, "name");
Expand Down
1 change: 1 addition & 0 deletions drivers/ccd/ccd_simulator.h
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ class CCDSim : public INDI::CCD, public INDI::FilterInterface
float m_OAGOffset { 0 };
float m_RotationCW { 0 };
float m_TimeFactor { 1 };
double m_CameraRotation { 0 };

bool m_SimulateBayer { false };

Expand Down
66 changes: 43 additions & 23 deletions drivers/telescope/scopesim_helper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,11 @@ Axis::AXIS_TRACK_RATE Axis::TrackRate()
return trackingRate;
}

double Axis::getTrackingRateDegSec()
{
return TrackingRateDegSec.Degrees();
}

void Axis::StartGuide(double rate, uint32_t durationMs)
{
// rate is fraction of sidereal, signed to give the direction
Expand Down Expand Up @@ -149,7 +154,7 @@ void Axis::update() // called about once a second to update the position
{
position += TrackingRateDegSec * interval;
target += TrackingRateDegSec * interval;
//LOGF_EXTRA1("%s: tracking, rate %f, position %f, target %f", axisName, TrackingRateDegSec.Degrees(), position.Degrees(), target.Degrees());
LOGF_EXTRA1("%s: tracking, rate %f, position %f, target %f", axisName, TrackingRateDegSec.Degrees(), position.Degrees(), target.Degrees());
}

// handle the slew
Expand Down Expand Up @@ -230,28 +235,33 @@ Angle Alignment::lst()

void Alignment::mountToApparentHaDec(Angle primary, Angle secondary, Angle * apparentHa, Angle* apparentDec)
{
// Primary instrument axis: "Angle" is negative PA-system looking SCP
// Secondary instrument axis: "Angle" is negative PA-system looking E

Angle prio, seco;
// get instrument place
switch (mountType)
{
case MOUNT_TYPE::ALTAZ:
// Primary instrument axis: Negative PA-system looking down from Zenith:Nadir, origin "HA-like"!!!
// Secondary instrument axis: Positive PA-system looking at E, origin "DEC-like"
case MOUNT_TYPE::EQ_FORK:
// Primary instrument axis: ??
// Secondary instrument axis: ??
seco = (latitude >= 0) ? secondary : -secondary;
prio = primary;
break;
case MOUNT_TYPE::EQ_GEM:
seco = (latitude >= 0) ? secondary : -secondary; // northern : southern hemisphere
if (seco > 90 || seco < -90) // pierside west/looking east (cf. apperentHaDecToMount())
if (seco > 90 || seco < -90) // pierside west/looking east (cf. apparentHaDecToMount())
{
prio = primary + Angle(180.0); // Ha is negative PA-system looking SCP
seco = Angle(180.0) - seco; // Dec is positive PA-system looking E
// Primary instrument axis: Negative PA-system looking down from NCP:SCP, origin opposite HA-like
// Secondary instrument axis: Negative PA-system looking at E, origin opposite DEC-like
prio = primary + Angle(180.0); // Primary to Ha transformation to get negative PA-system with origin HA-like
seco = Angle(180.0) - seco; // Secondary to Dec transformation to get positive PA-system origin DEC-like
}
else
{
prio = primary;
seco = secondary;
prio = primary; // Primary already rotated by 180, so no transformation to get origin HA-like
seco = secondary; // Secondary already rotated by 180, so no transformation to get origin DEC-like
}
break;
}
Expand All @@ -262,13 +272,15 @@ void Alignment::mountToApparentHaDec(Angle primary, Angle secondary, Angle * app
{
Angle rot = latitude - Angle(90);
Vector haDec = Vector(prio, seco).rotateY(rot);
*apparentHa = haDec.primary();
*apparentDec = haDec.secondary();
LOGF_EXTRA1("m2a Azm Alt %f, %f Ha Dec %f, %f rot %f", prio.Degrees(), seco.Degrees(), apparentHa->Degrees(),
// Primary instrument axis: Negative PA-system looking down from Zenith:Nadir, origin "HA-like" ...
*apparentHa = haDec.primary(); // ... so there is no transformation needed!
// Secondary instrument axis: Positive PA-system looking east, origin "DEC-like" ...
*apparentDec = haDec.secondary(); // ... so there is no transformation needed!
LOGF_EXTRA1("ALTAZ to apparent HaDec: pri %f, sec %f to ha %f, dec %f rot %f", prio.Degrees(), seco.Degrees(), apparentHa->Degrees(),
apparentDec->Degrees(), rot.Degrees());
}
else
LOGF_EXTRA1("mountToApparentHaDec: pri %f, sec %f to ha %f, dec %f", prio.Degrees(), seco.Degrees(), apparentHa->Degrees(),
LOGF_EXTRA1("EQ to apparent HaDec: pri %f, sec %f to ha %f, dec %f", prio.Degrees(), seco.Degrees(), apparentHa->Degrees(),
apparentDec->Degrees());
}

Expand All @@ -277,7 +289,7 @@ void Alignment::mountToApparentRaDec(Angle primary, Angle secondary, Angle * app
Angle ha;
mountToApparentHaDec(primary, secondary, &ha, apparentDec);
*apparentRa = lst() - ha;
LOGF_EXTRA1("mountToApparentRaDec: pri %f, sec %f to ha %f, ra %f, dec %f", primary.Degrees(), secondary.Degrees(), ha.Degrees(),
LOGF_EXTRA1("mount to apparent RaDec: pri %f, sec %f to ha %f, ra %f, dec %f", primary.Degrees(), secondary.Degrees(), ha.Degrees(),
apparentRa->Degrees(), apparentDec->Degrees());
}

Expand All @@ -291,12 +303,14 @@ void Alignment::apparentHaDecToMount(Angle apparentHa, Angle apparentDec, Angle*
Vector altAzm = Vector(apparentHa, apparentDec).rotateY(Angle(90) - latitude);
// for now we are making no mount corrections
// this all leaves me wondering if the GEM corrections should be done before the mount model
*primary = altAzm.primary();
*secondary = altAzm.secondary();
LOGF_EXTRA1("a2M haDec %f, %f Azm Alt %f, %f", apparentHa.Degrees(), apparentDec.Degrees(), primary->Degrees(),
// Ha axis: Negative PA-system looking down from Zenith:Nadir, origin "HA-like" ...
*primary = altAzm.primary(); // ... so there is no tranformation needed!
// Dec axis: Positive PA-system looking at east, origin "DEC-like" ...
*secondary = altAzm.secondary(); // ... so there is no tranformation needed!
LOGF_EXTRA1("apparent HaDec to ALTAZ: ha %f, dec %f to pri %f, sec %f", apparentHa.Degrees(), apparentDec.Degrees(), primary->Degrees(),
secondary->Degrees() );
}
// Ha is negative PA-system looking SCP
// Ha is negative PA-system looking down to NCP:SCP
// Dec is positive PA-system looking E
Angle instrumentHa, instrumentDec;
// ignore diurnal aberrations and refractions to get observed ha, dec
Expand All @@ -306,36 +320,42 @@ void Alignment::apparentHaDecToMount(Angle apparentHa, Angle apparentDec, Angle*
switch (mountType)
{
case MOUNT_TYPE::ALTAZ:
// Ha axis: Negative PA-system looking down to Zenith:Nadir pole, origin "HA-like"
// Dec axis: Positive PA-system looking at east, origin "DEC-like"
break;
case MOUNT_TYPE::EQ_FORK:
// Primary instrument axis: ??
// Secondary instrument axis: ??
*primary = instrumentHa;
*secondary = (latitude >= 0) ? instrumentDec : -instrumentDec; // northern : southern hemisphere
break;
case MOUNT_TYPE::EQ_GEM:
if (instrumentHa < flipHourAngle) // pierside west (looking east)
{
*primary = instrumentHa + Angle(180); // Primary instrument axis: "Angle" is negative PA-system looking SCP
*secondary = Angle(180) - instrumentDec; // Secondary instrument axis: "Angle" is negative PA-system looking E
// Ha axis: Negative PA-system looking down from NCP:SCP, origin HA-like
// Dec axis: Positive PA-system looking at E, origin DEC-like
*primary = instrumentHa + Angle(180); // Ha to Primary to get negative PA-system with origin opposite HA-like
*secondary = Angle(180) - instrumentDec; // Dec to Secondary to get positive PA-system with origin DEC-like
}
else
{
*primary = instrumentHa;
*secondary = instrumentDec;
*primary = instrumentHa; // Ha already rotated by 180, so no transformation to get origin opposite HA-like
*secondary = instrumentDec; // Dec already rotated by 180, so no transformation to get origin opposite DEC-like
}
if (latitude < 0) // southern hemisphere
*secondary = -*secondary;
break;
}
if (mountType != MOUNT_TYPE::ALTAZ)
LOGF_EXTRA1("apparentHaDecToMount: ha %f, dec %f to pri %f, sec %f", apparentHa.Degrees(), apparentDec.Degrees(), primary->Degrees(),
LOGF_EXTRA1("apparent HaDec to EQ: ha %f, dec %f to pri %f, sec %f", apparentHa.Degrees(), apparentDec.Degrees(), primary->Degrees(),
secondary->Degrees() );
}

void Alignment::apparentRaDecToMount(Angle apparentRa, Angle apparentDec, Angle* primary, Angle* secondary)
{
Angle ha = lst() - apparentRa;
apparentHaDecToMount(ha, apparentDec, primary, secondary);
LOGF_EXTRA1("apparentRaDecToMount: ra %f, ha %f, dec %f to pri %f, sec %f", apparentRa.Degrees(), ha.Degrees(), apparentDec.Degrees(),
LOGF_EXTRA1("apparent RaDec to mount: ra %f, ha %f, dec %f to pri %f, sec %f", apparentRa.Degrees(), ha.Degrees(), apparentDec.Degrees(),
primary->Degrees(), secondary->Degrees());
}

Expand Down
9 changes: 8 additions & 1 deletion drivers/telescope/scopesim_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
*
*/

/// The transformations are based on the paper "Matrix Method for Coordinates Transformation" written by Toshimi Taki

#pragma once

#include <stdint.h>
Expand Down Expand Up @@ -256,7 +258,10 @@ class Angle
/// Implements a generic Axis which can be used for equatorial or AltAz mounts for both axes.
///
/// For an equatorial mount use the TrackRate to set the standard tracking rates. for the primary axis only.
/// (TS 5.25: Axis entails the angles of the rotation around the mechanical axes of the mount.)
/// For an AltAz mount the TrackingRateDegSec rate must be set for both axes.
/// (TS 5.25: The tracking rates of the mechanical axes vary with the positions.
/// See "Deriving Field Rotation Rate for an Alt-Az Mounted Telescope" by Russell P. Patera1)
///
class Axis
{
Expand All @@ -277,7 +282,7 @@ class Axis
void setDegrees(double degrees);
void setHours(double hours);

Angle position; // current axis position
Angle position; // current angle of the telescope position about axis

void StartSlew(Angle angle);

Expand Down Expand Up @@ -311,6 +316,8 @@ class Axis
///
AXIS_TRACK_RATE TrackRate();

double getTrackingRateDegSec();

///
/// \brief TrackingRateDegSec
///
Expand Down
Loading
Loading