File indexing completed on 2024-04-28 03:43:40
0001 /* 0002 SPDX-FileCopyrightText: 2015 Jasem Mutlaq <mutlaqja@ikarustech.com> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #ifndef MOUNT_H 0008 #define MOUNT_H 0009 0010 #include <QQmlContext> 0011 #include "ui_mount.h" 0012 0013 #include "indi/indistd.h" 0014 #include "indi/indifocuser.h" 0015 #include "indi/indimount.h" 0016 0017 class QQuickView; 0018 class QQuickItem; 0019 0020 namespace Ekos 0021 { 0022 /** 0023 *@class Mount 0024 *@short Supports controlling INDI telescope devices including setting/retrieving mount properties, slewing, motion and speed controls, in addition to enforcing altitude limits and parking/unparking. 0025 *@author Jasem Mutlaq 0026 *@version 1.5 0027 */ 0028 0029 class OpticalTrainManager; 0030 class MeridianFlipState; 0031 0032 class Mount : public QWidget, public Ui::Mount 0033 { 0034 Q_OBJECT 0035 Q_CLASSINFO("D-Bus Interface", "org.kde.kstars.Ekos.Mount") 0036 Q_PROPERTY(QString opticalTrain READ opticalTrain WRITE setOpticalTrain) 0037 Q_PROPERTY(ISD::Mount::Status status READ status NOTIFY newStatus) 0038 Q_PROPERTY(ISD::ParkStatus parkStatus READ parkStatus NOTIFY newParkStatus) 0039 Q_PROPERTY(QStringList logText READ logText NOTIFY newLog) 0040 Q_PROPERTY(QList<double> altitudeLimits READ altitudeLimits WRITE setAltitudeLimits) 0041 Q_PROPERTY(bool altitudeLimitsEnabled READ altitudeLimitsEnabled WRITE setAltitudeLimitsEnabled) 0042 Q_PROPERTY(double hourAngleLimit READ hourAngleLimit WRITE setHourAngleLimit) 0043 Q_PROPERTY(bool hourAngleLimitEnabled READ hourAngleLimitEnabled WRITE setHourAngleLimitEnabled) 0044 Q_PROPERTY(bool autoParkEnabled READ autoParkEnabled WRITE setAutoParkEnabled) 0045 Q_PROPERTY(QList<double> equatorialCoords READ equatorialCoords) 0046 Q_PROPERTY(QList<double> horizontalCoords READ horizontalCoords) 0047 Q_PROPERTY(double hourAngle READ hourAngle) 0048 Q_PROPERTY(int slewRate READ slewRate WRITE setSlewRate) 0049 Q_PROPERTY(int slewStatus READ slewStatus) 0050 Q_PROPERTY(bool canPark READ canPark) 0051 Q_PROPERTY(ISD::Mount::PierSide pierSide READ pierSide NOTIFY pierSideChanged) 0052 0053 public: 0054 Mount(); 0055 ~Mount() override; 0056 0057 //typedef enum { PARKING_IDLE, PARKING_OK, UNPARKING_OK, PARKING_BUSY, UNPARKING_BUSY, PARKING_ERROR } ParkingStatus; 0058 0059 /** 0060 * @brief addMount Add a new Mount device 0061 * @param device pointer to mount device 0062 * @return True if added successfully, false if duplicate or failed to add. 0063 */ 0064 bool setMount(ISD::Mount *device); 0065 0066 /** 0067 * @brief addGPS Add a new GPS device 0068 * @param device pointer to gps device 0069 * @return True if added successfully, false if duplicate or failed to add. 0070 */ 0071 bool addGPS(ISD::GPS *device); 0072 0073 void removeDevice(const QSharedPointer<ISD::GenericDevice> &device); 0074 0075 void setupOpticalTrainManager(); 0076 void refreshOpticalTrain(); 0077 QString opticalTrain() const 0078 { 0079 return opticalTrainCombo->currentText(); 0080 } 0081 void setOpticalTrain(const QString &value) 0082 { 0083 opticalTrainCombo->setCurrentText(value); 0084 } 0085 0086 // Log functions 0087 void appendLogText(const QString &); 0088 void clearLog(); 0089 QStringList logText() 0090 { 0091 return m_LogText; 0092 } 0093 QString getLogText() const 0094 { 0095 return m_LogText.join("\n"); 0096 } 0097 0098 ISD::Mount::Status status() const 0099 { 0100 return m_Status; 0101 } 0102 ISD::Mount *activeMount() const 0103 { 0104 return m_Mount; 0105 } 0106 QString statusString(bool translated = true) const 0107 { 0108 if (m_Mount) 0109 return m_Mount->statusString(m_Status, translated); 0110 else 0111 return "NA"; 0112 } 0113 ISD::Mount::PierSide pierSide() const 0114 { 0115 if (m_Mount) 0116 return m_Mount->pierSide(); 0117 else 0118 return ISD::Mount::PIER_UNKNOWN; 0119 } 0120 ISD::ParkStatus parkStatus() const 0121 { 0122 return m_ParkStatus; 0123 } 0124 0125 /** 0126 * @brief getMeridianFlipState 0127 * @return 0128 */ 0129 QSharedPointer<MeridianFlipState> getMeridianFlipState() const 0130 { 0131 return mf_state; 0132 } 0133 0134 /** @defgroup MountDBusInterface Ekos Mount DBus Interface 0135 * Mount interface provides advanced scripting capabilities to control INDI mounts. 0136 */ 0137 0138 /*@{*/ 0139 0140 /** DBUS interface function. 0141 * Returns the mount altitude limits. 0142 * @return Returns array of doubles. First item is minimum altitude in degrees. Second item is maximum altitude limit in degrees. 0143 */ 0144 Q_SCRIPTABLE QList<double> altitudeLimits(); 0145 0146 /** DBUS interface function. 0147 * Sets the mount altitude limits, and whether they are enabled or disabled. 0148 * @param limits is a list of double values. 2 values are expected: minAltitude & maxAltitude 0149 */ 0150 Q_SCRIPTABLE Q_NOREPLY void setAltitudeLimits(QList<double> limits); 0151 0152 /** DBUS interface function. 0153 * Enable or disable mount altitude limits. 0154 */ 0155 Q_SCRIPTABLE void setAltitudeLimitsEnabled(bool enable); 0156 0157 /** DBUS interface function. 0158 * Returns whether the mount limits are enabled or disabled. 0159 * @return True if enabled, false otherwise. 0160 */ 0161 Q_SCRIPTABLE bool altitudeLimitsEnabled(); 0162 0163 /** DBUS interface function. 0164 * Returns the mount hour angle limit. 0165 * @return Returns hour angle limit in hours. 0166 */ 0167 Q_SCRIPTABLE double hourAngleLimit(); 0168 0169 /** DBUS interface function. 0170 * Sets the mount altitude limits, and whether they are enabled or disabled. 0171 * @param limits is a list of double values. 2 values are expected: minAltitude & maxAltitude 0172 */ 0173 Q_SCRIPTABLE Q_NOREPLY void setHourAngleLimit(double limit); 0174 0175 /** DBUS interface function. 0176 * Enable or disable mount hour angle limit. Mount cannot slew and/or track past this 0177 * hour angle distance. 0178 */ 0179 Q_SCRIPTABLE void setHourAngleLimitEnabled(bool enable); 0180 0181 /** DBUS interface function. 0182 * Returns whether the mount limits are enabled or disabled. 0183 * @return True if enabled, false otherwise. 0184 */ 0185 Q_SCRIPTABLE bool hourAngleLimitEnabled(); 0186 0187 /** 0188 * @brief autoParkEnabled Check if auto-park is enabled. 0189 * @return True if enabled. 0190 */ 0191 Q_SCRIPTABLE bool autoParkEnabled(); 0192 0193 /** 0194 * @brief setAutoParkEnabled Toggle Auto Park 0195 * @param enable True to start, false to stop 0196 */ 0197 Q_SCRIPTABLE void setAutoParkEnabled(bool enable); 0198 0199 /** 0200 * @brief setAutoParkDailyEnabled toggles everyday Auto Park 0201 * @param enable true to activate, false to deactivate 0202 */ 0203 Q_SCRIPTABLE void setAutoParkDailyEnabled(bool enabled); 0204 0205 /** 0206 * @brief setAutoParkStartup Set time when automatic parking is activated. 0207 * @param startup Startup time. should not be more than 12 hours away. 0208 */ 0209 Q_SCRIPTABLE void setAutoParkStartup(QTime startup); 0210 0211 Q_SCRIPTABLE bool meridianFlipEnabled(); 0212 Q_SCRIPTABLE double meridianFlipValue(); 0213 0214 /** DBUS interface function. 0215 * Slew the mount to the RA/DEC (JNow). 0216 * @param RA Right ascention is hours. 0217 * @param DEC Declination in degrees. 0218 * @return true if the command is sent successfully, false otherwise. 0219 */ 0220 Q_INVOKABLE Q_SCRIPTABLE bool slew(double RA, double DEC); 0221 0222 /** 0223 @brief Like above but RA and DEC are strings HH:MM:SS and DD:MM:SS 0224 */ 0225 Q_INVOKABLE bool slew(const QString &RA, const QString &DEC); 0226 0227 /** DBUS interface function. 0228 * Slew the mount to the target. Target name must be valid in KStars. 0229 * @param target name 0230 * @return true if the command is sent successfully, false otherwise. 0231 */ 0232 Q_INVOKABLE Q_SCRIPTABLE bool gotoTarget(const QString &target); 0233 0234 /** DBUS interface function. 0235 * Sync the mount to the RA/DEC (JNow). 0236 * @param RA Right ascention is hours. 0237 * @param DEC Declination in degrees. 0238 * @return true if the command is sent successfully, false otherwise. 0239 */ 0240 Q_INVOKABLE Q_SCRIPTABLE bool sync(double RA, double DEC); 0241 0242 /** DBUS interface function. 0243 * Sync the mount to the target. Target name must be valid in KStars. 0244 * @param target name 0245 * @return true if the command is sent successfully, false otherwise. 0246 */ 0247 Q_INVOKABLE Q_SCRIPTABLE bool syncTarget(const QString &target); 0248 0249 /** 0250 @brief Like above but RA and DEC are strings HH:MM:SS and DD:MM:SS 0251 */ 0252 Q_INVOKABLE bool sync(const QString &RA, const QString &DEC); 0253 0254 /** DBUS interface function. 0255 * Get equatorial coords (JNow). An array of doubles is returned. First element is RA in hours. Second elements is DEC in degrees. 0256 */ 0257 Q_SCRIPTABLE QList<double> equatorialCoords(); 0258 0259 /** DBUS interface function. 0260 * Get Horizontal coords. An array of doubles is returned. First element is Azimuth in degrees. Second elements is Altitude in degrees. 0261 */ 0262 Q_SCRIPTABLE QList<double> horizontalCoords(); 0263 0264 /** DBUS interface function. 0265 * Get Horizontal coords. 0266 */ 0267 Q_SCRIPTABLE SkyPoint currentTarget(); 0268 0269 /** DBUS interface function. 0270 * Get mount hour angle in hours (-12 to +12). 0271 */ 0272 Q_SCRIPTABLE double hourAngle(); 0273 0274 /** DBUS interface function. 0275 * Get the hour angle of that time the mount has slewed to the current position. 0276 * This is used to manage the meridian flip for mounts which do not report pier side. 0277 * only one attempt to flip is done. 0278 */ 0279 Q_SCRIPTABLE double initialHA(); 0280 0281 /** DBUS interface function. 0282 * Aborts the mount motion 0283 * @return true if the command is sent successfully, false otherwise. 0284 */ 0285 Q_INVOKABLE Q_SCRIPTABLE bool abort(); 0286 0287 /** DBUS interface function. 0288 * Get the mount slew status ("Idle","Complete", "Busy", "Error") 0289 */ 0290 Q_INVOKABLE Q_SCRIPTABLE IPState slewStatus(); 0291 0292 0293 /** DBUS interface function. 0294 * Get the mount slew rate index 0 to N-1, or -1 if slew rates are not supported. 0295 */ 0296 Q_INVOKABLE Q_SCRIPTABLE int slewRate(); 0297 0298 Q_INVOKABLE Q_SCRIPTABLE bool setSlewRate(int index); 0299 0300 /** DBUS interface function. 0301 * Reset mount model if supported by the mount. 0302 * @return true if the command is executed successfully, false otherwise. 0303 */ 0304 Q_INVOKABLE Q_SCRIPTABLE bool resetModel(); 0305 0306 /** DBUS interface function. 0307 * Can mount park? 0308 */ 0309 Q_INVOKABLE Q_SCRIPTABLE bool canPark(); 0310 0311 /** DBUS interface function. 0312 * Park mount 0313 */ 0314 Q_INVOKABLE Q_SCRIPTABLE bool park(); 0315 0316 /** DBUS interface function. 0317 * Unpark mount 0318 */ 0319 Q_INVOKABLE Q_SCRIPTABLE bool unpark(); 0320 0321 /** DBUS interface function. 0322 * Return parking status of the mount. 0323 */ 0324 //Q_INVOKABLE Q_SCRIPTABLE ParkingStatus getParkingStatus(); 0325 0326 Q_INVOKABLE void setTrackEnabled(bool enabled); 0327 0328 Q_INVOKABLE void setJ2000Enabled(bool enabled); 0329 0330 /** @}*/ 0331 0332 Q_INVOKABLE void findTarget(); 0333 0334 // target coord conversions for displaying 0335 Q_INVOKABLE bool raDecToAzAlt(QString qsRA, QString qsDec); 0336 Q_INVOKABLE bool raDecToHaDec(QString qsRA); 0337 Q_INVOKABLE bool azAltToRaDec(QString qsAz, QString qsAlt); 0338 Q_INVOKABLE bool azAltToHaDec(QString qsAz, QString qsAlt); 0339 Q_INVOKABLE bool haDecToRaDec(QString qsHA); 0340 Q_INVOKABLE bool haDecToAzAlt(QString qsHA, QString qsDec); 0341 0342 // Center mount in Sky Map 0343 Q_INVOKABLE void centerMount(); 0344 0345 Q_INVOKABLE void setUpDownReversed(bool enabled); 0346 Q_INVOKABLE void setLeftRightReversed(bool enabled); 0347 0348 QString meridianFlipStatusDescription() 0349 { 0350 return meridianFlipStatusWidget->getStatus(); 0351 } 0352 0353 // Settings 0354 QVariantMap getAllSettings() const; 0355 void setAllSettings(const QVariantMap &settings); 0356 0357 public slots: 0358 0359 /** 0360 * @brief syncTelescopeInfo Update telescope information to reflect any property changes 0361 */ 0362 void syncTelescopeInfo(); 0363 /** 0364 * @brief updateProperty Update properties under watch in the mount module 0365 * @param prop INDI property 0366 */ 0367 void updateProperty(INDI::Property prop); 0368 0369 /** 0370 * @brief updateLog Update mount module log to include any messages arriving for the telescope driver 0371 * @param messageID ID of the new message 0372 */ 0373 void updateLog(int messageID); 0374 0375 /** 0376 * @brief updateTelescopeCoords is triggered by the ISD::Mount::newCoord() event and updates the displayed 0377 * coordinates of the mount and to ensure mount is within altitude limits if the altitude limits are enabled. 0378 * The frequency of this update depends on the REFRESH parameter of the INDI mount device. 0379 * @param position latest coordinates the mount reports it is pointing to 0380 * @param pierSide pierSide 0381 * @param ha hour angle of the latest coordinates 0382 */ 0383 void updateTelescopeCoords(const SkyPoint &position, ISD::Mount::PierSide pierSide, const dms &ha); 0384 0385 /** 0386 * @brief move Issues motion command to the mount to move in a particular direction based the request NS and WE values 0387 * @param command Either ISD::Mount::MOTION_START (0) or ISD::Mount::MOTION_STOP (1) 0388 * @param NS is either -1 for no direction, or ISD::Mount::MOTION_NORTH (0), or ISD::Mount::MOTION_SOUTH (1) 0389 * @param WE is either -1 for no direction, or ISD::Mount::MOTION_WEST (0), or ISD::Mount::MOTION_EAST (1) 0390 */ 0391 void motionCommand(int command, int NS, int WE); 0392 0393 /** 0394 * @brief Send a guide pulse to the telescope. 0395 * @param ra_dir RA guide direction 0396 * @param ra_msecs duration of the RA guiding pulse in milliseconds 0397 * @param dec_dir dec guide direction 0398 * @param dec_msecs duration of the DEC guiding pulse in milliseconds 0399 */ 0400 void doPulse(GuideDirection ra_dir, int ra_msecs, GuideDirection dec_dir, int dec_msecs); 0401 0402 /** 0403 * @brief saveLimits Saves altitude limit to the user options and updates the INDI telescope driver limits 0404 */ 0405 void saveLimits(); 0406 0407 /** 0408 * @brief Enable or disable altitude limits 0409 * @param enable True to enable, false to disable. 0410 */ 0411 void setAltitudeLimits(bool enable); 0412 0413 /** 0414 * @brief resumeAltLimits calls enableAltitudeLimits(true). This function is mostly used to enable altitude limit after a meridian flip is complete. 0415 */ 0416 void resumeAltLimits(); 0417 0418 /** 0419 * @brief suspendAltLimits calls enableAltitudeLimits(false). This function is mostly used to disable altitude limit once a meridial flip process is started. 0420 */ 0421 void suspendAltLimits(); 0422 0423 /** 0424 * @brief enableHourAngleLimits Enable or disable hour angle limits 0425 * @param enable True to enable, false to disable. 0426 */ 0427 void enableHourAngleLimits(bool enable); 0428 0429 /** 0430 * @brief enableHaLimits calls enableHourAngleLimits(true). This function is mostly used to enable hour angle limit after a meridian flip is complete. 0431 */ 0432 void enableHaLimits(); 0433 0434 /** 0435 * @brief disableAltLimits calls enableHourAngleLimits(false). This function is mostly used to disable altitude limit once a meridial flip process is started. 0436 */ 0437 void disableHaLimits(); 0438 0439 void toggleMountToolBox(); 0440 0441 /** 0442 * @brief set meridian flip activation and hours 0443 * @param activate true iff the meridian flip should be executed 0444 * @param degrees angle past the meridian when the flip should be delayed 0445 */ 0446 void setMeridianFlipValues(bool activate, double degrees); 0447 0448 /** 0449 * @brief React upon status changes of the polar alignment - mainly to 0450 * avoid meridian flips happening during polar alignment. 0451 */ 0452 void paaStageChanged(int stage); 0453 0454 /** 0455 * @brief registerNewModule Register an Ekos module as it arrives via DBus 0456 * and create the appropriate DBus interface to communicate with it. 0457 * @param name of module 0458 */ 0459 void registerNewModule(const QString &name); 0460 0461 /** 0462 * @brief gotoTarget Slew to target coordinates. 0463 * @param target Target 0464 * @return True if slew successful, false otherwise. 0465 */ 0466 bool gotoTarget(const SkyPoint &target); 0467 0468 /** 0469 * @brief syncAxisReversed Update Mount Control GUI on the reverse motion toggled state. 0470 * @param axis RA (left/right) or DE (up/down) 0471 * @param reversed True if reversed, false otherwise. 0472 */ 0473 void syncAxisReversed(INDI_EQ_AXIS axis, bool reversed); 0474 0475 /** 0476 * @brief stopTimers Need to stop update timers when profile is disconnected 0477 * but due to timing and race conditions, the timers can trigger an invalid access 0478 * to INDI device. 0479 */ 0480 void stopTimers(); 0481 0482 private slots: 0483 void startParkTimer(); 0484 void stopParkTimer(); 0485 void startAutoPark(); 0486 0487 signals: 0488 void newLog(const QString &text); 0489 /** 0490 * @brief Update event with the current telescope position 0491 * @param position mount position. Independent from the mount type, 0492 * the EQ coordinates(both JNow and J2000) as well as the alt/az values are filled. 0493 * @param pierside for GEMs report the pier side the scope is currently (PierSide::PIER_WEST means 0494 * the mount is on the western side of the pier pointing east of the meridian). 0495 * @param ha current hour angle 0496 */ 0497 void newCoords(const SkyPoint &position, ISD::Mount::PierSide pierSide, const dms &ha); 0498 /** 0499 * @brief The mount has finished the slew to a new target. 0500 * @param currentCoords exact position where the mount is positioned 0501 */ 0502 void newTarget(SkyPoint ¤tCoord); 0503 0504 /** 0505 * @brief The mount has finished the slew to a new target. 0506 * @param Name Name of object, if any, the mount is positioned at. 0507 */ 0508 void newTargetName(const QString &name); 0509 /** 0510 * @brief Change in the mount status. 0511 */ 0512 void newStatus(ISD::Mount::Status status); 0513 void newParkStatus(ISD::ParkStatus status); 0514 void pierSideChanged(ISD::Mount::PierSide side); 0515 void slewRateChanged(int index); 0516 void ready(); 0517 void newMeridianFlipText(const QString &text); 0518 void autoParkCountdownUpdated(const QString &text); 0519 0520 void settingsUpdated(const QVariantMap &settings); 0521 void trainChanged(); 0522 0523 private: 0524 //////////////////////////////////////////////////////////////////// 0525 /// Settings 0526 //////////////////////////////////////////////////////////////////// 0527 0528 /** 0529 * @brief Connect GUI elements to sync settings once updated. 0530 */ 0531 void connectSettings(); 0532 /** 0533 * @brief Stop updating settings when GUI elements are updated. 0534 */ 0535 void disconnectSettings(); 0536 /** 0537 * @brief loadSettings Load setting from Options and set them accordingly. 0538 */ 0539 void loadGlobalSettings(); 0540 0541 void connectSyncSettings(); 0542 void disconnectSyncSettings(); 0543 0544 /** 0545 * @brief syncSettings When checkboxes, comboboxes, or spin boxes are updated, save their values in the 0546 * global and per-train settings. 0547 */ 0548 void syncSettings(); 0549 0550 /** 0551 * @brief syncControl Sync setting to widget. The value depends on the widget type. 0552 * @param settings Map of all settings 0553 * @param key name of widget to sync 0554 * @param widget pointer of widget to set 0555 * @return True if sync successful, false otherwise 0556 */ 0557 bool syncControl(const QVariantMap &settings, const QString &key, QWidget * widget); 0558 0559 void syncGPS(); 0560 void setScopeStatus(ISD::Mount::Status status); 0561 /* Meridian flip state handling */ 0562 QSharedPointer<MeridianFlipState> mf_state; 0563 void setupParkUI(); 0564 0565 bool hasCaptureInterface { false }; 0566 0567 ISD::Mount *m_Mount {nullptr}; 0568 ISD::GPS *m_GPS {nullptr}; 0569 QList<ISD::GPS*> m_GPSes; 0570 0571 QStringList m_LogText; 0572 SkyPoint telescopeCoord; 0573 SkyPoint *targetPosition {nullptr}; 0574 QString lastNotificationMessage; 0575 0576 // Auto Park 0577 QTimer autoParkTimer; 0578 0579 // Limits 0580 int m_AbortAltDispatch {-1}, m_AbortHADispatch {-1}; 0581 bool m_AltitudeLimitEnabled {false}; 0582 double m_LastAltitude {0}; 0583 bool m_HourAngleLimitEnabled {false}; 0584 double m_LastHourAngle {0}; 0585 0586 // GPS 0587 bool GPSInitialized = {false}; 0588 0589 ISD::Mount::Status m_Status = ISD::Mount::MOUNT_IDLE; 0590 ISD::ParkStatus m_ParkStatus = ISD::PARK_UNKNOWN; 0591 0592 // Settings 0593 QVariantMap m_Settings; 0594 QVariantMap m_GlobalSettings; 0595 0596 QQuickView *m_BaseView = nullptr; 0597 QQuickItem *m_BaseObj = nullptr; 0598 QQmlContext *m_Ctxt = nullptr; 0599 0600 QQuickItem *m_SpeedSlider = nullptr, *m_SpeedLabel = nullptr, 0601 *m_raValue = nullptr, *m_deValue = nullptr, *m_azValue = nullptr, 0602 *m_altValue = nullptr, *m_haValue = nullptr, *m_zaValue = nullptr, 0603 *m_targetText = nullptr, *m_targetRAText = nullptr, 0604 *m_targetDEText = nullptr, *m_Park = nullptr, *m_Unpark = nullptr, 0605 *m_statusText = nullptr, *m_J2000Check = nullptr, 0606 *m_JNowCheck = nullptr, *m_equatorialCheck = nullptr, 0607 *m_horizontalCheck = nullptr, *m_haEquatorialCheck = nullptr, 0608 *m_leftRightCheck = nullptr, *m_upDownCheck = nullptr; 0609 }; 0610 } 0611 0612 0613 #endif // Mount