diff --git a/drivers/ccd/ccd_simulator.cpp b/drivers/ccd/ccd_simulator.cpp index eb8a321597..6c3bacc679 100644 --- a/drivers/ccd/ccd_simulator.cpp +++ b/drivers/ccd/ccd_simulator.cpp @@ -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); @@ -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); @@ -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); @@ -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); @@ -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(); @@ -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"); diff --git a/drivers/ccd/ccd_simulator.h b/drivers/ccd/ccd_simulator.h index d2caeee077..c4fedcb6aa 100644 --- a/drivers/ccd/ccd_simulator.h +++ b/drivers/ccd/ccd_simulator.h @@ -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 }; diff --git a/drivers/telescope/scopesim_helper.cpp b/drivers/telescope/scopesim_helper.cpp index db598cdc6e..b09f7ef7dc 100644 --- a/drivers/telescope/scopesim_helper.cpp +++ b/drivers/telescope/scopesim_helper.cpp @@ -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 @@ -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 @@ -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; } @@ -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()); } @@ -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()); } @@ -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 @@ -306,28 +320,34 @@ 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() ); } @@ -335,7 +355,7 @@ void Alignment::apparentRaDecToMount(Angle apparentRa, Angle apparentDec, Angle* { 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()); } diff --git a/drivers/telescope/scopesim_helper.h b/drivers/telescope/scopesim_helper.h index 60021725d2..39bce9a9dd 100644 --- a/drivers/telescope/scopesim_helper.h +++ b/drivers/telescope/scopesim_helper.h @@ -31,6 +31,8 @@ * */ +/// The transformations are based on the paper "Matrix Method for Coordinates Transformation" written by Toshimi Taki + #pragma once #include @@ -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 { @@ -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); @@ -311,6 +316,8 @@ class Axis /// AXIS_TRACK_RATE TrackRate(); + double getTrackingRateDegSec(); + /// /// \brief TrackingRateDegSec /// diff --git a/drivers/telescope/telescope_simulator.cpp b/drivers/telescope/telescope_simulator.cpp index a141c05c73..929fac10db 100644 --- a/drivers/telescope/telescope_simulator.cpp +++ b/drivers/telescope/telescope_simulator.cpp @@ -48,10 +48,28 @@ ScopeSim::ScopeSim(): GI(this) /* initialize random seed: */ srand(static_cast(time(nullptr))); - // initialise axis positions, for GEM pointing at pole, counterweight down - axisPrimary.setDegrees(90.0); - axisPrimary.TrackRate(Axis::SIDEREAL); - axisSecondary.setDegrees(90.0); + // initialise axis positions + // Note: Primary and secondary axes are always perpendicular + switch (m_MountType) + { + // ALTAZ pointing at northern zenith + case Alignment::MOUNT_TYPE::ALTAZ: + // Primary instrument axis: looking at zenith, angle form negative PA-system, *origin HA-like*! + axisPrimary.setDegrees(0.0); + axisPrimary.TrackRate(Axis::SIDEREAL); + // Secondary instrument axis: looking at east, angle form negative PA-system, origin opposite DEC-like! + axisSecondary.setDegrees(90.0); + axisSecondary.TrackRate(Axis::SIDEREAL); + break; + //EQ_XXX pointing at NCP (counterweight down) + default: + // Primary instrument axis: looking at SCP, angle form negative PA-system, origin opposite HA! + axisPrimary.setDegrees(0.0); + axisPrimary.TrackRate(Axis::SIDEREAL); + // Secondary instrument axis: looling at east, angle form negative PA-system, origin opposite DEC! + axisSecondary.setDegrees(90.0); + axisSecondary.TrackRate(Axis::OFF); + } } const char *ScopeSim::getDefaultName() @@ -145,6 +163,11 @@ void ScopeSim::ISGetProperties(const char *dev) defineProperty(flipHourAngleNP); flipHourAngleNP.load(); #endif + double Latitude = LocationNP[LOCATION_LATITUDE].getValue(); + m_sinLat = std::sin(Latitude * 0.0174533); + m_cosLat = std::cos(Latitude * 0.0174533); + m_currentAz = 180 + axisPrimary.position.Degrees(); // Primary to Azm + m_currentAlt = axisSecondary.position.Degrees(); } bool ScopeSim::updateProperties() @@ -157,21 +180,20 @@ bool ScopeSim::updateProperties() { defineProperty(GuideRateNP); GuideRateNP.load(); - //defineProperty(HomeSP); - if (InitPark()) { if (isParked()) { // at this point there is a valid ParkData.xml available - alignment.latitude = Angle(LocationNP[LOCATION_LATITUDE].getValue()); alignment.longitude = Angle(LocationNP[LOCATION_LONGITUDE].getValue()); - currentRA = (alignment.lst() - Angle(ParkPositionNP[AXIS_RA].getValue(), Angle::ANGLE_UNITS::HOURS)).Hours(); - currentDEC = ParkPositionNP[AXIS_DE].getValue(); - Sync(currentRA, currentDEC); - + // RA-parkposition in Ha full circle!! + m_currentRA = (alignment.lst() - Angle(ParkPositionNP[AXIS_RA].getValue(), Angle::ANGLE_UNITS::HOURS)).Hours(); + m_currentDEC = ParkPositionNP[AXIS_DE].getValue(); + Sync(m_currentRA, m_currentDEC); + m_currentAz = 180 + axisPrimary.position.Degrees(); // ALTAZ-Primary to Azm + m_currentAlt = axisSecondary.position.Degrees(); } // If loading parking data is successful, we just set the default parking values. SetAxis1ParkDefault(-6.); @@ -213,18 +235,34 @@ bool ScopeSim::Disconnect() return true; } + +/// ALTAZ: The tracking rates of the mechanical axes vary with the angle positions. +/// (See "Deriving Field Rotation Rate for an Alt-Az Mounted Telescope" by Russell P. Patera1) bool ScopeSim::ReadScopeStatus() { - // new axis control + if (m_MountType == Alignment::MOUNT_TYPE::ALTAZ && TrackState == SCOPE_TRACKING) + { + double sinAz = std::sin(DEG_TO_RAD(m_currentAz)); + double cosAz = std::cos(DEG_TO_RAD(m_currentAz)); + double sinAlt = std::sin(DEG_TO_RAD(m_currentAlt)); + double cosAlt = std::cos(DEG_TO_RAD(m_currentAlt)); + SetTrackRate((m_sinLat - ((cosAz * sinAlt * m_cosLat) / cosAlt)) * TRACKRATE_SIDEREAL, + m_cosLat * sinAz * TRACKRATE_SIDEREAL); + } + + // SetTrackRate(TrackRateNP[AXIS_RA].getValue(), TrackRateNP[AXIS_DE].getValue()); + + // new mechanical angle calculation axisPrimary.update(); axisSecondary.update(); + // transform to new RA & DEC Angle ra, dec; alignment.mountToApparentRaDec(axisPrimary.position, axisSecondary.position, &ra, &dec); - - // move both axes - currentRA = ra.Hours(); - currentDEC = dec.Degrees(); + m_currentRA = ra.Hours(); + m_currentDEC = dec.Degrees(); + m_currentAz = 180 + axisPrimary.position.Degrees(); // ALTAZ-Primary to Azm + m_currentAlt = axisSecondary.position.Degrees(); // update properties from the axis if (alignment.mountType == Alignment::MOUNT_TYPE::EQ_GEM) @@ -263,8 +301,8 @@ bool ScopeSim::ReadScopeStatus() LOG_INFO("Telescope slew is complete. Tracking..."); // check the slew accuracy - auto dRa = targetRA - currentRA; - auto dDec = targetDEC - currentDEC; + auto dRa = m_targetRA - m_currentRA; + auto dDec = m_targetDEC - m_currentDEC; LOGF_DEBUG("slew accuracy %f, %f", dRa * 15 * 3600, dDec * 3600); } break; @@ -289,28 +327,28 @@ bool ScopeSim::ReadScopeStatus() } #ifdef USE_SIM_TAB - double axisRA = axisPrimary.position.Degrees(); - double axisDE = axisSecondary.position.Degrees(); + double PrimaryAngle = axisPrimary.position.Degrees(); + double SecondaryAngle = axisSecondary.position.Degrees(); // No need to spam log until we have some actual changes. - if (std::fabs(mountAxisNP[AXIS_RA].getValue() - axisRA) > 0.0001 || - std::fabs(mountAxisNP[AXIS_DE].getValue() - axisDE) > 0.0001) + if (std::fabs(mountAxisNP[PRIMARY].getValue() - PrimaryAngle) > 0.0001 || + std::fabs(mountAxisNP[SECONDARY].getValue() - SecondaryAngle) > 0.0001) { - mountAxisNP[AXIS_RA].setValue(axisRA); - mountAxisNP[AXIS_DE].setValue(axisDE); + mountAxisNP[PRIMARY].setValue(PrimaryAngle); + mountAxisNP[SECONDARY].setValue(SecondaryAngle); - LOGF_EXTRA1("%s: %f, ra %f", axisPrimary.axisName, axisPrimary.position.Degrees(), ra.Hours()); - LOGF_EXTRA1("%s: %f, dec %f", axisSecondary.axisName, axisSecondary.position.Degrees(), dec.Degrees()); + LOGF_EXTRA1("new %s: %f, ra %f", axisPrimary.axisName, PrimaryAngle, ra.Hours()); + LOGF_EXTRA1("new %s: %f, dec %f", axisSecondary.axisName, SecondaryAngle, dec.Degrees()); mountAxisNP.apply(); } #endif char RAStr[64], DecStr[64]; - fs_sexa(RAStr, currentRA, 2, 3600); - fs_sexa(DecStr, currentDEC, 2, 3600); + fs_sexa(RAStr, m_currentRA, 2, 3600); + fs_sexa(DecStr, m_currentDEC, 2, 3600); DEBUGF(DBG_SCOPE, "Current RA: %s Current DEC: %s", RAStr, DecStr); - NewRaDec(currentRA, currentDEC); + NewRaDec(m_currentRA, m_currentDEC); return true; } @@ -332,14 +370,14 @@ bool ScopeSim::Sync(double ra, double dec) Angle r, d; alignment.mountToApparentRaDec(a1, a2, &r, &d); LOGF_DEBUG("sync to %f, %f, reached %f, %f", ra, dec, r.Hours(), d.Degrees()); - currentRA = r.Hours(); - currentDEC = d.Degrees(); + m_currentRA = r.Hours(); + m_currentDEC = d.Degrees(); LOG_INFO("Sync is successful."); EqNP.setState(IPS_OK); - NewRaDec(currentRA, currentDEC); + NewRaDec(m_currentRA, m_currentDEC); return true; } @@ -360,12 +398,12 @@ void ScopeSim::StartSlew(double ra, double dec, TelescopeStatus status) axisPrimary.StartSlew(primary); axisSecondary.StartSlew(secondary); - targetRA = ra; - targetDEC = dec; + m_targetRA = ra; + m_targetDEC = dec; char RAStr[64], DecStr[64]; - fs_sexa(RAStr, targetRA, 2, 3600); - fs_sexa(DecStr, targetDEC, 2, 3600); + fs_sexa(RAStr, m_targetRA, 2, 3600); + fs_sexa(DecStr, m_targetDEC, 2, 3600); const char * statusStr; switch (status) @@ -476,7 +514,7 @@ bool ScopeSim::ISNewSwitch(const char *dev, const char *name, ISState *states, c } } - // Nobody has claimed this, so, ignore it + // Nobody has claimed this, so pass it over return INDI::Telescope::ISNewSwitch(dev, name, states, names, n); } @@ -564,9 +602,9 @@ IPState ScopeSim::GuideWest(uint32_t ms) bool ScopeSim::SetCurrentPark() { - double ha = (alignment.lst() - Angle(currentRA, Angle::ANGLE_UNITS::HOURS)).Hours(); + double ha = (alignment.lst() - Angle(m_currentRA, Angle::ANGLE_UNITS::HOURS)).Hours(); SetAxis1Park(ha); - SetAxis2Park(currentDEC); + SetAxis2Park(m_currentDEC); return true; } @@ -666,8 +704,8 @@ bool ScopeSim::updateMountAndPierSide() #endif if ( mountType == Alignment::MOUNT_TYPE::ALTAZ) { - LOG_INFO("AltAz mount type not implemented yet"); - return false; + LOG_INFO("AltAz mount type experimental"); + // return false; } alignment.mountType = static_cast(mountType); diff --git a/drivers/telescope/telescope_simulator.h b/drivers/telescope/telescope_simulator.h index 65db52d6b1..d157af8f14 100644 --- a/drivers/telescope/telescope_simulator.h +++ b/drivers/telescope/telescope_simulator.h @@ -87,10 +87,13 @@ class ScopeSim : public INDI::Telescope, public INDI::GuiderInterface virtual bool saveConfigItems(FILE *fp) override; private: - double currentRA { 0 }; - double currentDEC { 90 }; - double targetRA { 0 }; - double targetDEC { 0 }; + double m_currentRA { 0 }; + double m_currentDEC { 90 }; + double m_currentAz { 180 }; + double m_currentAlt { 0 }; + double m_targetRA { 0 }; + double m_targetDEC { 0 }; + double m_sinLat, m_cosLat; /// used by GoTo and Park void StartSlew(double ra, double dec, TelescopeStatus status); @@ -115,8 +118,8 @@ class ScopeSim : public INDI::Telescope, public INDI::GuiderInterface double m_Home[2] = {0, 0}; - Axis axisPrimary { "HaAxis" }; // hour angle mount axis - Axis axisSecondary { "DecAxis" }; // declination mount axis + Axis axisPrimary { "Primary Axis" }; // entails angle of mount for primary axis + Axis axisSecondary { "Secondary Axis" }; // entails angle of mount for secondary axis ("mechanical DEC") int m_PierSide {-1}; int m_MountType {-1}; diff --git a/libs/indibase/indiccd.cpp b/libs/indibase/indiccd.cpp index b5abca1b2d..d68fb66f00 100644 --- a/libs/indibase/indiccd.cpp +++ b/libs/indibase/indiccd.cpp @@ -366,10 +366,11 @@ bool CCD::initProperties() WorldCoordSP.fill(getDeviceName(), "WCS_CONTROL", "WCS", WCS_TAB, IP_RW, ISR_1OFMANY, 0, IPS_IDLE); - // Camera Rotation E of N in degrees + // Camera Rotation E of N in degrees following Astrometry notation with row order Down - Top + // TS 06-2025: Has to be transformed accordingly for KSTARS Top - Down, see KSUtils::rotationToPositionAngle(orientation) // @INDI_STANDARD_PROPERTY@ - CCDRotationNP[0].fill("CCD_ROTATION_VALUE", "Rotation", "%g", -360, 360, 1, 0); - CCDRotationNP.fill(getDeviceName(), "CCD_ROTATION", "CCD FOV", WCS_TAB, IP_RW, 60, + CCDRotationNP[0].fill("CCD_ROTATION_VALUE", "Angle", "%.2f", -360, 360, 1, 0); + CCDRotationNP.fill(getDeviceName(), "CCD_ROTATION", "Orientation", WCS_TAB, IP_RW, 60, IPS_IDLE); // Scope focal length and aperture @@ -1503,7 +1504,7 @@ bool CCD::ISNewNumber(const char * dev, const char * name, double values[], char CCDRotationNP.apply(); m_ValidCCDRotation = true; - LOGF_INFO("CCD FOV rotation updated to %g degrees.", CCDRotationNP[0].getValue()); + LOGF_INFO("Camera Orientation updated to %.2f degrees.", CCDRotationNP[0].getValue()); return true; } diff --git a/libs/indibase/indiccd.h b/libs/indibase/indiccd.h index efc7c9c028..22f56b8e70 100644 --- a/libs/indibase/indiccd.h +++ b/libs/indibase/indiccd.h @@ -716,7 +716,6 @@ class CCD : public DefaultDevice, GuiderInterface APERTURE }; - // WCS INDI::PropertySwitch WorldCoordSP{2}; enum