From 4300c8133f07ebf6041c3d71a5b803a0686a0121 Mon Sep 17 00:00:00 2001 From: Edward Emelianov Date: Wed, 24 Jun 2026 17:32:29 +0300 Subject: [PATCH] fixed some stupid errors --- Daemons/10micron_stellarium/angles.c | 85 ++++++-- Daemons/10micron_stellarium/angles.h | 12 +- Daemons/10micron_stellarium/emulation.c | 224 ++++++++++++++++----- Daemons/10micron_stellarium/emulation.h | 11 +- Daemons/10micron_stellarium/mount.c | 119 ++++++++--- Daemons/10micron_stellarium/mount.h | 8 + Daemons/10micron_stellarium/server.c | 241 ++++++++++++++++++++++- Daemons/10micron_stellarium/stellarium.c | 36 +--- 8 files changed, 606 insertions(+), 130 deletions(-) diff --git a/Daemons/10micron_stellarium/angles.c b/Daemons/10micron_stellarium/angles.c index 424d48d..145f321 100644 --- a/Daemons/10micron_stellarium/angles.c +++ b/Daemons/10micron_stellarium/angles.c @@ -72,8 +72,9 @@ bool setPlaceData(double longitude, double latitude, double altitude){ return false; } place.salt = altitude; - place.slat = latitude; - place.slong = longitude; + place.slat = DEG2RAD(latitude); + place.slong = DEG2RAD(longitude); + DBG("Change place data: alt=%gm, lat=%gdeg, long=%gdeg", place.salt, RAD2DEG(place.slat), RAD2DEG(place.slong)); return true; } @@ -106,6 +107,25 @@ char *radec2str(double ra, double dec, char buf[RADEC_STR_MAXLEN]){ return buf; } +// normalize azimuth to [0, 360.) and z.d. to [0, 90] +// if z>90 || z<-90 return false; if z < 0 rotate azimuth to 180 +bool normAZ(double *a, double *z){ + if(a){ + norm_angle180(a); + if(*a < 0.) *a += 360.; + } + if(z){ + norm_angle180(z); + if(*z > 90. || *z < -90.) return false; + if(*z < 0.){ + *z += 90.; + *a += 180.; + if(*a >= 360.) *a -= 360.; + } + } + return true; +} + // normalize RA/DEC to [0..24) for RA and [-90, 90] for DEC void norm_RA(double *ra){ if(!ra) return; @@ -123,11 +143,35 @@ void norm_RADEC(double *ra, double *dec){ // 1: convert to (-180..+180) norm_angle180(dec); // 2: fix dec & ra together - if(*dec > 90.) *dec = 180. - *dec; - else *dec = -180. - *dec; - *ra += 12.; - norm_RA(ra); + if(*dec > 90.){ + *dec = 180. - *dec; + *ra += 12.; + norm_RA(ra); + }else if(*dec < -90.){ + *dec = -180. - *dec; + *ra += 12.; + norm_RA(ra); + } } + +void norm_RADECr(double *ra, double *dec){ + if(!ra || !dec) return; + if(*dec >= -ERFA_DPI/2. && *dec <= ERFA_DPI/2.){ // need only check RA + *ra = eraAnp(*ra); + return; + } + // 1: convert to (-pi..+pi) + *dec = eraAnpm(*dec); + // 2: fix dec & ra together + if(*dec > ERFA_DPI/2.){ + *dec = ERFA_DPI - *dec; + *ra = eraAnp(*ra + ERFA_DPI); + }else if(*dec < -ERFA_DPI/2.){ + *dec = -ERFA_DPI - *dec; + *ra = eraAnp(*ra + ERFA_DPI); + } +} + // normalize angle to (-180, 180] void norm_angle180(double *a){ if(!a) return; @@ -145,8 +189,11 @@ void norm_angle180(double *a){ */ void hor2eq(horizCrds_t *h, polarCrds_t *pc, double sidTime){ if(!h || !pc) return; + DBG("got az=%gdeg, zd=%gdeg; sidtm=%ghrs", RAD2DEG(h->az), RAD2DEG(h->zd), RAD2HRS(sidTime)); eraAe2hd(h->az, ERFA_DPI/2. - h->zd, place.slat, &pc->ha, &pc->dec); // A,H -> HA,DEC; phi - site latitude - pc->ra = sidTime - pc->ha; + pc->ha = eraAnp(pc->ha); // normalize to [0,2pi) + pc->ra = eraAnp(sidTime - pc->ha); + DBG("dec=%gdeg, ha=%gh, ra=%gh", RAD2DEG(pc->dec), RAD2HRS(pc->ha), RAD2HRS(pc->ra)); pc->eo = 0.; } @@ -213,7 +260,7 @@ bool get_MJDt(struct timeval *tval, sMJD_t *MJD){ struct tm tms; double tSeconds; if(!MJD){ - WARNX("get_MJDt(): no input data"); + WARNX("get_MJDt(): no output data"); return false; } if(!tval){ @@ -223,9 +270,11 @@ bool get_MJDt(struct timeval *tval, sMJD_t *MJD){ return false; } gmtime_r(&ts.tv_sec, &tms); + //localtime_r(&ts.tv_sec, &tms); tSeconds = tms.tm_sec + ((double)ts.tv_nsec)/1e9; }else{ gmtime_r(&tval->tv_sec, &tms); + //localtime_r(&tval->tv_sec, &tms); tSeconds = tms.tm_sec + ((double)tval->tv_usec)/1e6; } int y, m, d; @@ -238,10 +287,11 @@ bool get_MJDt(struct timeval *tval, sMJD_t *MJD){ WARNX("get_MJDt(): eraDtf2d() error"); return false; } - MJD->MJD = utc1 - ERFA_DJM0 + utc2; + DBG("y=%d, m=%d, d=%d, H=%d, M=%d, seconds=%g, UTC=%g", y, m, d, tms.tm_hour, tms.tm_min, tSeconds, utc1+utc2); + MJD->MJD = (utc1 - ERFA_DJM0) + utc2; MJD->utc1 = utc1; MJD->utc2 = utc2; - //DBG("UTC(m): %g, %.8f\n", utc1 - 2400000.5, utc2); + DBG("MJD: %g, %.8f", utc1 - ERFA_DJM0, utc2); if(eraUtctai(utc1, utc2, &MJD->tai1, &MJD->tai2)){ WARNX("get_MJDt(): eraUtctai() error"); return false; @@ -263,20 +313,22 @@ bool get_MJDt(struct timeval *tval, sMJD_t *MJD){ * @param LST (o) - local sidereal time (radians) * @return true if all OK */ -bool get_LST(sMJD_t *mjd, double dUT1, double slong, double *LST){ +bool get_LST(sMJD_t *mjd, double *LST){ double ut11, ut12; sMJD_t Mjd; if(!LST) return false; if(!mjd){ if(!get_MJDt(NULL, &Mjd)) return false; }else Mjd = *mjd; - if(eraUtcut1(Mjd.utc1, Mjd.utc2, dUT1, &ut11, &ut12)) return false; + if(eraUtcut1(Mjd.utc1, Mjd.utc2, AlmDut.DUT1, &ut11, &ut12)) return false; double ST = eraGst06a(ut11, ut12, Mjd.tt1, Mjd.tt2); - ST += slong; + DBG("ST0=%gh; longitude=%gh (%gdeg) STl=%gh", RAD2HRS(ST), + RAD2HRS(place.slong), RAD2DEG(place.slong), RAD2HRS(ST+place.slong)); + ST += place.slong; if(ST > ERFA_D2PI) ST -= ERFA_D2PI; else if(ST < 0.) ST += ERFA_D2PI; *LST = ST; - return 0; + return true; } /** @@ -302,14 +354,15 @@ bool get_ObsPlace(struct timeval *tval, polarCrds_t *p2000, polarCrds_t *pnow, h double wl = 0.55; /* ICRS to observed. */ double aob, zob, hob, dob, rob, eo; - double p = 1000., t = 0., h = place.salt; + double p = 1000., t = 0., h = 0.5; weather_data_t weath; if(get_weather_data(&weath)){ WARNX("Can't get weather - use default values"); }else{ p = 1.3332239 * weath.pressure; t = weath.exttemp; - DBG("pressure=%.1fhPa, temperature=%.1fdegC", p, t); + h = weath.humidity / 100.; + DBG("pressure=%.1fhPa, temperature=%.1fdegC, humidity=%.1f%%", p, t, h); } if(eraAtco13(p2000->ra, p2000->dec, pr, pd, px, rv, diff --git a/Daemons/10micron_stellarium/angles.h b/Daemons/10micron_stellarium/angles.h index daa5c98..e03cefb 100644 --- a/Daemons/10micron_stellarium/angles.h +++ b/Daemons/10micron_stellarium/angles.h @@ -23,10 +23,10 @@ #define RADEC_STR_MAXLEN 72 -#define RAD2DEG(angle) (angle * ERFA_DR2D) -#define DEG2RAD(angle) (angle * ERFA_DD2R) -#define RAD2HRS(angle) (angle * 24. / ERFA_DPI) -#define HRS2RAD(hour) (hour * ERFA_DPI / 24.) +#define RAD2DEG(angle) ((angle) * ERFA_DR2D) +#define DEG2RAD(angle) ((angle) * ERFA_DD2R) +#define RAD2HRS(angle) ((angle) * 12. / ERFA_DPI) +#define HRS2RAD(hour) ((hour) * ERFA_DPI / 12.) typedef struct{ double utc1; double utc2; // UTC JD, commonly used MJD = utc1+utc2-2400000.5 @@ -65,8 +65,10 @@ typedef struct{ } almDut_t; char *radec2str(double ra, double dec, char buf[RADEC_STR_MAXLEN]); +bool normAZ(double *a, double *z); void norm_RA(double *ra); void norm_RADEC(double *ra, double *dec); +void norm_RADECr(double *ra, double *dec); void norm_angle180(double *a); void hor2eq(horizCrds_t *h, polarCrds_t *pc, double sidTime); @@ -79,7 +81,7 @@ void hor2eq(horizCrds_t *h, polarCrds_t *pc, double sidTime); void eq2horH(polarCrds_t *pc, horizCrds_t *h); void eq2hor(polarCrds_t *pc, horizCrds_t *h, double sidTime); bool get_MJDt(struct timeval *tval, sMJD_t *MJD); -bool get_LST(sMJD_t *mjd, double dUT1, double slong, double *LST); +bool get_LST(sMJD_t *mjd, double *LST); bool get_ObsPlace(struct timeval *tval, polarCrds_t *p2000, polarCrds_t *pnow, horizCrds_t *hnow); bool setDUT(almDut_t *D); diff --git a/Daemons/10micron_stellarium/emulation.c b/Daemons/10micron_stellarium/emulation.c index edc2b01..c743374 100644 --- a/Daemons/10micron_stellarium/emulation.c +++ b/Daemons/10micron_stellarium/emulation.c @@ -16,25 +16,35 @@ * along with this program. If not, see . */ +#include +#include #include +#include #include #include "angles.h" #include "emulation.h" -// emulation speed over RA & DEC (degr per sec) -#define RA_SPEED (5.) -#define DECL_SPEED (11.) +// emulation speed over any trajectory +#define SPEED (DEG2RAD(5.)) +// limiting Zen.d. +#define ZD_LIMIT (DEG2RAD(80.)) +// pointing tolerance: ~1'' +#define POINTING_TOL (DEG2RAD(0.0003)) -// current coordinates -static double RA = 0., DECL = 0.; -// target coordinates -static double RAtarg = 0., DECLtarg = 0.; -// coordinates @ guiding start -static double RA0 = 0., DECL0 = 0.; -static double raspeed = 0.; -// pointing start time -static double tstart = -1.; +// current emulation status (only MNT_S_STOPPED, MNT_S_TRACKING and MNT_S_SLEWING supported) +static atomic_int emul_status = MNT_S_STOPPED; +// current & target coordinates for stationary process +static horizCrds_t CurAZ = {.az = DEG2RAD(180.), .zd = DEG2RAD(80.)}, TagAZ = {0}; +// pointing to AZ and stop +static bool pointAZ = false; +// current and target Ra/Dec +static polarCrds_t CurRD = {0}, TagRD = {0}; +// last time user asks for coordinates or change something +static double tlast = -1.; +// flipping emulation +static bool flip_in_progress = false; +static polarCrds_t flip_target = {0}; // flipping target when dec>90deg, ra+=12h /** * send coordinates to telescope emulation @@ -43,56 +53,168 @@ static double tstart = -1.; */ bool point_emulation(double ra, double decl){ norm_RADEC(&ra, &decl); - DBG("(emul) Send ra=%g, decl=%g", ra, decl); - LOGMSG("(emul) Send ra=%g, decl=%g", ra, decl); - // TODO: check that Z<90! - RAtarg = ra; DECLtarg = decl; - RA0 = RA; DECL0 = DECL; - raspeed = (RAtarg > RA) ? RA_SPEED : -RA_SPEED; - if(fabs(RAtarg - RA) > 12.){ // go to opposite direction - raspeed = -raspeed; + DBG("(emul) Send ra=%ghrs, decl=%gdeg", ra, decl); + LOGMSG("(emul) Send ra=%ghrs, decl=%gdeg", ra, decl); + double LST; + if(!get_LST(NULL, &LST)){ + DBG("Time error"); + return false; } - tstart = sl_dtime(); + // refresh coordinates + get_emul_coords(NULL, NULL); + TagRD.ra = HRS2RAD(ra); TagRD.dec = DEG2RAD(decl); + horizCrds_t hc; + eq2hor(&TagRD, &hc, LST); + if(hc.zd > ZD_LIMIT){ + LOGWARN("User asks to point to object with ZD=%g", RAD2DEG(hc.zd)); + DBG("Bad zd: %g", RAD2DEG(hc.zd)); + return false; + } + tlast = sl_dtime(); + pointAZ = false; + flip_in_progress = false; + atomic_store(&emul_status, MNT_S_SLEWING); return true; } -static double getradiff(){ - double diff = RAtarg - RA; - if(raspeed < 0.) diff = -diff; - if(diff > 12.) diff -= 24.; - else if(diff < -12.) diff += 24.; - return fabs(diff); +bool pointAZ_emulation(double a, double z){ + if(!normAZ(&a, &z)) return false; + get_emul_coords(NULL, NULL); + TagAZ.az = DEG2RAD(a); + TagAZ.zd = DEG2RAD(z); + pointAZ = true; + tlast = sl_dtime(); + flip_in_progress = false; + atomic_store(&emul_status, MNT_S_SLEWING); + return true; +} + +static void chk_zlim(double LST){ + if(CurAZ.zd > ZD_LIMIT){ + CurAZ.zd = ZD_LIMIT; + emulation_stop(); + hor2eq(&CurAZ, &CurRD, LST); + } +} + +#if 0 +// distance between `a` and `b` on sphere +static double angular_distance(const polarCrds_t *a, const polarCrds_t *b){ + double dRA = a->ra - b->ra; + double sa, sb, ca, cb; + sincos(a->dec, &sa, &ca); + sincos(b->dec, &sb, &cb); + double cd = sa*sb + ca*cb*cos(dRA); + return acos(cd); +} +#endif +// distance by axis moving +static double axdist(const polarCrds_t *a, const polarCrds_t *b){ + // convert to [-pi, pi) + double dra = eraAnpm(b->ra - a->ra), ddec = eraAnpm(b->dec - a->dec); + return sqrt(dra*dra + ddec*ddec); +} + +// calculate flip target (dec>90deg) +static void get_flip_target(const polarCrds_t *src, polarCrds_t *dst){ + dst->ra = src->ra + ERFA_DPI; + if(dst->ra >= ERFA_D2PI) dst->ra -= ERFA_D2PI; + if(src->dec > 0.0) + dst->dec = ERFA_DPI - src->dec; + else + dst->dec = -ERFA_DPI - src->dec; } /** * get coordinates (emulation) */ void get_emul_coords(double *ra, double *decl){ - if(tstart > 0.){ - DBG("RA/DEC: targ: %g/%g, cur: %g/%g, start: %g/%g", RAtarg, DECLtarg, RA, DECL, RA0, DECL0); - // diff < speed? stop - if((fabs(RAtarg - RA) < RA_SPEED && fabs(DECLtarg - DECL) < DECL_SPEED)){ - RA = RAtarg; - DECL = DECLtarg; - tstart = -1.; // "guiding" - DBG("@ target"); - }else{ // calculate new coordinates - double radiff = getradiff(), decldiff = fabs(DECLtarg - DECL); - double tdiff = sl_dtime() - tstart; - RA = RA0 + raspeed * tdiff; - DBG("RA=%g", RA); - if(getradiff() > radiff) RA = RAtarg; - DBG("RA=%g", RA); - if(RA < 0.) RA += 24.; - else if(RA > 24.) RA -= 24.; - DBG("RA=%g", RA); - double sign = (DECLtarg > DECL) ? 1. : -1.; - DECL = DECL0 + sign * DECL_SPEED * tdiff; - if(fabs(DECLtarg - DECL) > decldiff) DECL = DECLtarg; - DBG("RA/DEC: targ: %g/%g, cur: %g/%g, start: %g/%g", RAtarg, DECLtarg, RA, DECL, RA0, DECL0); + mount_status_t curstat = emulation_status(); + double LST, tcur = sl_dtime(); + if(!get_LST(NULL, &LST)) return; + if(curstat == MNT_S_STOPPED){ // just show constant A/Z + DBG("Stopped -> get from a=%gdeg, z=%gdeg", RAD2DEG(CurAZ.az), RAD2DEG(CurAZ.zd)); + hor2eq(&CurAZ, &CurRD, LST); + }else if(curstat == MNT_S_SLEWING){ // slew to target (RA/Dec or ZD/Az) + if(pointAZ){ + hor2eq(&TagAZ, &TagRD, LST); // refresh target coordinates + DBG("Slewing to A/Z: a=%g, z=%g", RAD2DEG(TagAZ.az), RAD2DEG(TagAZ.zd)); } + if(!flip_in_progress){ // check if we need to flip + // distance for direct moving + double dist_direct = axdist(&CurRD, &TagRD); + // new point after flipping + polarCrds_t flip_candidate; + get_flip_target(&TagRD, &flip_candidate); + // distance for moving with flip + double dist_flip = axdist(&CurRD, &flip_candidate); + + if(dist_flip < dist_direct){ + // need to make flip: it's shorter + flip_target = flip_candidate; + flip_in_progress = true; + DBG("Flip chosen: direct=%.3fdeg, flip=%.3fdeg\n\n\n", RAD2DEG(dist_direct), RAD2DEG(dist_flip)); + }else{ + flip_in_progress = false; + DBG("Move directly: direct=%.3fdeg, flip=%.3fdeg\n\n\n", RAD2DEG(dist_direct), RAD2DEG(dist_flip)); + } + } + // flip target is the same as TagRD, but with RA+=12h and dec > 90deg + polarCrds_t *target = flip_in_progress ? &flip_target : &TagRD; + // RA difference over target and last position: [-pi, pi) + double dRA = eraAnpm(target->ra - CurRD.ra); + DBG("RA difference: %gdegr", RAD2DEG(dRA)); + double dDec = eraAnpm(target->dec - CurRD.dec); + DBG("DEC difference: %gdegr", RAD2DEG(dDec)); + double dist = sqrt(dRA*dRA + dDec*dDec); + if(dist < POINTING_TOL){ // on position + if(pointAZ) emulation_stop(); // got A/Z position, stop + else atomic_store(&emul_status, MNT_S_TRACKING); + if(flip_in_progress){ + flip_in_progress = false; + CurRD = TagRD; // fix to dec <=90 + } + }else{ + double dt = tcur - tlast; + double step = SPEED * dt; + if(step > dist) step = dist; + double factor = step / dist; + CurRD.ra += dRA * factor; + CurRD.dec += dDec * factor; + //if(CurRD.dec > ERFA_DPI/2.0) CurRD.dec = ERFA_DPI/2.0; + //else if(CurRD.dec < -ERFA_DPI/2.0) CurRD.dec = -ERFA_DPI/2.0; + if(CurRD.ra < 0.) CurRD.ra += ERFA_D2PI; + else if(CurRD.ra >= ERFA_D2PI) CurRD.ra -= ERFA_D2PI; + } + }else if(curstat == MNT_S_TRACKING){ // tracking -> just show static RA/Dec until Z. */ - #pragma once -bool point_emulation(double ra, double decl); -void get_emul_coords(double *ra, double *decl); +#include "mount.h" // mount status +bool point_emulation(double ra, double decl); +bool pointAZ_emulation(double a, double z); +mount_status_t emulation_status(); + +void get_emul_coords(double *ra, double *decl); +void emulation_stop(); +void emul_start_tracking(); diff --git a/Daemons/10micron_stellarium/mount.c b/Daemons/10micron_stellarium/mount.c index a0fc91a..dfcc48b 100644 --- a/Daemons/10micron_stellarium/mount.c +++ b/Daemons/10micron_stellarium/mount.c @@ -39,6 +39,8 @@ static sl_ringbuffer_t *RBin = NULL; // status static atomic_int mountstatus = MNT_S_ERROR; +// parking coordinates +static horizCrds_t ParkCoords = {.az = 0., .zd = DEG2RAD(80.)}; // input and current target coordinates static polarCrds_t InpCoords = {0}, // input as user give (for epoch InpMJD) TagCoords = {0}; // target for Jnow after command "point to input" @@ -80,18 +82,18 @@ bool mount_setInpHA(double ha){ } /** * @brief mount_setInpRA - set right ascension - * @param ra (DEGREES!) - * @return fale if `ra` isn't in [0, 360) + * @param ra (HOURS!!) + * @return fale if `ra` isn't in [0, 24) */ bool mount_setInpRA(double ra){ - if(ra < 0. || ra >= 360.) return false; - InpCoords.ra = DEG2RAD(ra); + if(ra < 0. || ra >= 24.) return false; + InpCoords.ra = HRS2RAD(ra); InpCTime = sl_dtime(); return true; } /** * @brief mount_setInpDec - set declination - * @param dec (DEGREES!) + * @param dec (DEGREES!!) * @return false if `dec` isn't in [-90, 90] */ bool mount_setInpDec(double dec){ @@ -186,7 +188,7 @@ static const char *statuses[MNT_S_STATAMOUNT] = { * @return statically allocated string with explanation */ const char* mount_status_str(){ - int curst = atomic_load(&mountstatus); + int curst = (isemulated) ? emulation_status() : atomic_load(&mountstatus); if(curst > -1 && curst < MNT_S_STATAMOUNT) return statuses[curst]; return "'Unknown status'"; } @@ -256,10 +258,7 @@ static bool guess_speed(){ // connect to mount bool mount_connect(){ - if(isemulated){ - atomic_store(&mountstatus, MNT_S_STOPPED); - return true; - } + if(isemulated) return true; if(!mount_dev) return false; pthread_mutex_lock(&mntdev_mutex); if(!chkconn() && !guess_speed()) return false; @@ -277,20 +276,17 @@ bool mount_connect(){ } void mount_disconnect(){ - if(isemulated) return; + if(isemulated){ + emulation_stop(); + return; + } pthread_mutex_trylock(&mntdev_mutex); // at least, try if(mount_dev) close(mount_dev->comfd); pthread_mutex_unlock(&mntdev_mutex); } -// point to ra/dec over serial -static bool mount_pointto(double ra, double dec){ - (void) ra; (void) dec; - ; - return true; -} - /** + * TODO: change angles to RAD! * send input RA/Decl (j2000!) coordinates to tel * ra in hours (0..24), decl in degrees (-90..90) * @return true if all OK @@ -301,9 +297,18 @@ bool mount_point(double ra, double dec){ DBG("Set RA/Decl to %s", buf); LOGMSG("Try to set RA/Decl to %s", buf); norm_RADEC(&ra, &dec); - bool (*pointfunction)(double, double) = mount_pointto; - if(isemulated) pointfunction = point_emulation; - return pointfunction(ra, dec); + if(isemulated) return point_emulation(ra, dec); + // run real pointing to ra(hrs) & dec (deg) + return false; +} + +bool mount_pointAZ(double A, double Z){ + DBG("Point to stationary object, A=%g, Z=%g", A, Z); + if(isemulated){ + return pointAZ_emulation(A, Z); + } + ; // run real pointing + return false; } void set_emulation_mode(){ @@ -314,9 +319,75 @@ mount_status_t mount_getcoords(double *ra, double *dec){ if(!ra || !dec) return MNT_S_ERROR; if(isemulated){ get_emul_coords(ra, dec); - DBG("Emulated coordinates: %g, %g", *ra, *dec); - }else{ - ; // get real coordinates + DBG("Emulated coordinates: %gh, %gdeg", RAD2HRS(*ra), RAD2DEG(*dec)); + return emulation_status(); } + ; // get real coordinates return mount_status(); } + +/** + * @brief mount_stop - stop any moving + * @return false if failed + */ +bool mount_stop(){ + if(isemulated){ + emulation_stop(); + }else{ + return mount_stop(); + } + return true; +} + +/** + * @brief mount_tracking_start - start tracking from current position + * @return false if failed + */ +bool mount_tracking_start(){ + if(isemulated){ + emul_start_tracking(); + }else{ + return false; + } + return true; +} + +/** + * @brief mount_park - start parking + * @return false if failed to run command + */ +bool mount_park(){ + if(isemulated) return pointAZ_emulation(ParkCoords.az, ParkCoords.zd); + return mount_pointAZ(ParkCoords.az, ParkCoords.zd); +} + +/** + * @brief mount_setParkAz - set parking azimuth + * @param az - [-180, 360) degrees + * @return false if az out of range + */ +bool mount_setParkAz(double az){ + if(az < 0.) az += 360.; + if(az < 0. || az >= 360.) return false; + ParkCoords.az = DEG2RAD(az); + return true; +} + +/** + * @brief mount_setParkZD - set parking zenith distance + * @param zd - [0, 90] + * @return false if zd out of range + */ +bool mount_setParkZD(double zd){ + if(zd < 0. || zd > 90.) return false; + ParkCoords.zd = DEG2RAD(zd); + return true; +} + +/** + * @brief mount_getPark - get parking coordinates + * @param c (o) - az/zd + */ +void mount_getPark(horizCrds_t *c){ + if(c) *c = ParkCoords; +} diff --git a/Daemons/10micron_stellarium/mount.h b/Daemons/10micron_stellarium/mount.h index 19863c7..d27feb9 100644 --- a/Daemons/10micron_stellarium/mount.h +++ b/Daemons/10micron_stellarium/mount.h @@ -62,3 +62,11 @@ void mount_disconnect(); mount_status_t mount_getcoords(double *ra, double *dec); bool mount_point(double ra, double dec); +bool mount_pointAZ(double A, double Z); +bool mount_stop(); +bool mount_tracking_start(); +bool mount_park(); + +bool mount_setParkAz(double az); +bool mount_setParkZD(double zd); +void mount_getPark(horizCrds_t *c); diff --git a/Daemons/10micron_stellarium/server.c b/Daemons/10micron_stellarium/server.c index 6c05a5a..29800ac 100644 --- a/Daemons/10micron_stellarium/server.c +++ b/Daemons/10micron_stellarium/server.c @@ -16,6 +16,8 @@ * along with this program. If not, see . */ +#include +#include #include #include #include @@ -35,11 +37,23 @@ // commands #define CMD_UNIXT "unixt" #define CMD_STATUS "status" -#define CMD_RELAY "relay" -#define CMD_OPEN "open" -#define CMD_CLOSE "close" #define CMD_STOP "stop" -#define CMD_HALF "half" +#define CMD_TAGRA "tagra" +#define CMD_TAGDEC "tagdec" +#define CMD_TAGHA "tagha" +#define CMD_TAGAZ "tagaz" +#define CMD_TAGZD "tagzd" +#define CMD_TELRA "telra" +#define CMD_TELDEC "teldec" +#define CMD_GOTORD "gotord" +#define CMD_GOTORH "gotorh" +#define CMD_GOTOAZ "gotoaz" +#define CMD_STOP "stop" +#define CMD_TRACK "track" +#define CMD_PARK "park" +#define CMD_PARKAZ "parkaz" +#define CMD_PARKZD "parkzd" + // main command socket static sl_sock_t *cmd_socket = NULL; @@ -76,10 +90,227 @@ static sl_sock_hresult_e status(sl_sock_t *c, sl_sock_hitem_t *item, _U_ const c return RESULT_SILENCE; } +static int parse_key_value(const char *req, double *val){ + if(!req) return 0; // is getter + DBG("parsing of %s", req); + double d; + if(sscanf(req, "%lf", &d) != 1) return -1; // error + if(val) *val = d; + return 1; // is setter +} + +// setters of RA/DEC/HA/Az/ZD (TODO: fix `parse_key_value` for HH:MM:SS/DD:MM:SS/DDD.DD/HHH.HH formats!) +static sl_sock_hresult_e cmd_tagra(sl_sock_t *c, sl_sock_hitem_t *item, const char *req){ + double val; + int res = parse_key_value(req, &val); + if(res < 0) return RESULT_BADVAL; + if(res > 0){ // setter + if(mount_setInpRA(val)) return RESULT_OK; + return RESULT_BADVAL; + }else{ // getter + polarCrds_t p; + mount_getInpCoords(&p); + double ra_h = RAD2HRS(p.ra); + char buf[64]; + snprintf(buf, sizeof(buf), "%s=%.6f\n", item->key, ra_h); + sl_sock_sendstrmessage(c, buf); + } + return RESULT_SILENCE; +} + +static sl_sock_hresult_e cmd_tagdec(sl_sock_t *c, sl_sock_hitem_t *item, const char *req) { + double val; + int res = parse_key_value(req, &val); + if(res < 0) return RESULT_BADVAL; + if(res > 0){ + if(mount_setInpDec(val)) return RESULT_OK; + return RESULT_BADVAL; + }else{ + polarCrds_t p; + mount_getInpCoords(&p); + double dec_d = RAD2DEG(p.dec); + char buf[64]; + snprintf(buf, sizeof(buf), "%s=%.6f\n", item->key, dec_d); + sl_sock_sendstrmessage(c, buf); + } + return RESULT_SILENCE; +} + +static sl_sock_hresult_e cmd_tagha(sl_sock_t *c, sl_sock_hitem_t *item, const char *req) { + double val; + int res = parse_key_value(req, &val); + if(res < 0) return RESULT_BADVAL; + if(res > 0){ + if(mount_setInpHA(val)) return RESULT_OK; + return RESULT_BADVAL; + }else{ + polarCrds_t p; + mount_getInpCoords(&p); + double ha_h = RAD2HRS(p.ha); + char buf[64]; + snprintf(buf, sizeof(buf), "%s=%.6f\n", item->key, ha_h); + sl_sock_sendstrmessage(c, buf); + } + return RESULT_SILENCE; +} + +static sl_sock_hresult_e cmd_tagaz(sl_sock_t *c, sl_sock_hitem_t *item, const char *req) { + double val; + int res = parse_key_value(req, &val); + if(res < 0) return RESULT_BADVAL; + if(res > 0){ + if(mount_setInpA(val)) return RESULT_OK; + return RESULT_BADVAL; + }else{ + horizCrds_t h; + mount_getInpHor(&h); + double az_d = RAD2DEG(h.az); + char buf[64]; + snprintf(buf, sizeof(buf), "%s=%.6f\n", item->key, az_d); + sl_sock_sendstrmessage(c, buf); + } + return RESULT_SILENCE; +} + +static sl_sock_hresult_e cmd_tagzd(sl_sock_t *c, sl_sock_hitem_t *item, const char *req) { + double val; + int res = parse_key_value(req, &val); + if(res < 0) return RESULT_BADVAL; + if(res > 0){ + if(mount_setInpZ(val)) return RESULT_OK; + return RESULT_BADVAL; + }else{ + horizCrds_t h; + mount_getInpHor(&h); + double zd_d = RAD2DEG(h.zd); + char buf[64]; + snprintf(buf, sizeof(buf), "%s=%.6f\n", item->key, zd_d); + sl_sock_sendstrmessage(c, buf); + } + return RESULT_SILENCE; +} + +static sl_sock_hresult_e cmd_telra(sl_sock_t *c, sl_sock_hitem_t *item, _U_ const char *req) { + double ra, dec; + if(mount_getcoords(&ra, &dec) == MNT_S_ERROR) return RESULT_FAIL; + char buf[64]; + double ra_h = RAD2HRS(ra); + snprintf(buf, sizeof(buf), "%s=%.6f\n", item->key, ra_h); + sl_sock_sendstrmessage(c, buf); + return RESULT_SILENCE; +} + +static sl_sock_hresult_e cmd_teldec(sl_sock_t *c, sl_sock_hitem_t *item, _U_ const char *req) { + double ra, dec; + if(mount_getcoords(&ra, &dec) == MNT_S_ERROR) return RESULT_FAIL; + char buf[64]; + double dec_d = RAD2DEG(dec); + snprintf(buf, sizeof(buf), "%s=%.6f\n", item->key, dec_d); + sl_sock_sendstrmessage(c, buf); + return RESULT_SILENCE; +} + +static sl_sock_hresult_e cmd_gotord(_U_ sl_sock_t *c, _U_ sl_sock_hitem_t *item, _U_ const char *req) { + polarCrds_t p; + mount_getInpCoords(&p); + double ra_h = RAD2HRS(p.ra); + double dec_d = RAD2DEG(p.dec); + if(!mount_point(ra_h, dec_d)) return RESULT_FAIL; + return RESULT_OK; +} + +static sl_sock_hresult_e cmd_gotorh(_U_ sl_sock_t *c, _U_ sl_sock_hitem_t *item, _U_ const char *req) { + polarCrds_t p; + mount_getInpCoords(&p); + sMJD_t mjd; + if(!get_MJDt(NULL, &mjd)) return RESULT_FAIL; + double LST; + if(!get_LST(&mjd, &LST)) return RESULT_FAIL; + double RA_rad = eraAnp(LST - p.ha); + double ra_h = RAD2HRS(RA_rad); + double dec_d = RAD2DEG(p.dec); + if(!mount_point(ra_h, dec_d)) return RESULT_FAIL; + return RESULT_OK; +} + +static sl_sock_hresult_e cmd_gotoaz(_U_ sl_sock_t *c, _U_ sl_sock_hitem_t *item, _U_ const char *req) { + horizCrds_t h; + mount_getInpHor(&h); + if(mount_pointAZ(RAD2DEG(h.az), RAD2DEG(h.zd))) return RESULT_OK; + return RESULT_FAIL; +} + +static sl_sock_hresult_e cmd_stop(_U_ sl_sock_t *c, _U_ sl_sock_hitem_t *item, _U_ const char *req) { + mount_stop(); + return RESULT_OK; +} + +// run tracking from current position +static sl_sock_hresult_e cmd_track(_U_ sl_sock_t *c, _U_ sl_sock_hitem_t *item, _U_ const char *req) { + if(mount_tracking_start()) return RESULT_OK; + return RESULT_FAIL; +} + +static sl_sock_hresult_e cmd_park(_U_ sl_sock_t *c, _U_ sl_sock_hitem_t *item, _U_ const char *req){ + if(mount_park()) return RESULT_OK; + return RESULT_FAIL; +} + +// set/get parking coordinates +static sl_sock_hresult_e cmd_parkaz(sl_sock_t *c, sl_sock_hitem_t *item, const char *req){ + double val; + int res = parse_key_value(req, &val); + if(res < 0) return RESULT_BADVAL; + if(res > 0){ + if(mount_setParkAz(val)) return RESULT_OK; + return RESULT_BADVAL; + }else{ + horizCrds_t h; + mount_getPark(&h); + char buf[64]; + snprintf(buf, sizeof(buf), "%s=%.6f\n", item->key, RAD2DEG(h.az)); + sl_sock_sendstrmessage(c, buf); + } + return RESULT_SILENCE; +} +static sl_sock_hresult_e cmd_parkzd(sl_sock_t *c, sl_sock_hitem_t *item, const char *req){ + double val; + int res = parse_key_value(req, &val); + if(res < 0) return RESULT_BADVAL; + if(res > 0){ + if(mount_setParkZD(val)) return RESULT_OK; + return RESULT_BADVAL; + }else{ + horizCrds_t h; + mount_getPark(&h); + char buf[64]; + snprintf(buf, sizeof(buf), "%s=%.6f\n", item->key, RAD2DEG(h.zd)); + sl_sock_sendstrmessage(c, buf); + } + return RESULT_SILENCE; +} + + + // and all handlers collection static sl_sock_hitem_t handlers[] = { - {dtimeh, CMD_UNIXT, "get server's UNIX time", NULL}, + {cmd_gotoaz, CMD_GOTOAZ, "point telescope by input Az/ZD and stop", NULL}, + {cmd_gotord, CMD_GOTORD, "point telescope by input RA/Dec and start tracking", NULL}, + {cmd_gotorh, CMD_GOTORH, "point telescope by input RA/HA and start tracking", NULL}, + {cmd_park, CMD_PARK, "park telescope", NULL}, + {cmd_parkaz, CMD_PARKAZ, "set parking azimuth (Deg: 0 - north, 90 - east)", NULL}, + {cmd_parkzd, CMD_PARKZD, "set parking zenith distance (Deg)", NULL}, {status, CMD_STATUS, "get mount status", NULL}, + {cmd_stop, CMD_STOP, "stop telescope", NULL}, + {cmd_tagaz, CMD_TAGAZ, "get/set target azimuth (Deg)", NULL}, + {cmd_tagdec, CMD_TAGDEC, "get/set target declination (Deg)", NULL}, + {cmd_tagha, CMD_TAGHA, "get/set target hour angle (Hrs)", NULL}, + {cmd_tagra, CMD_TAGRA, "get/set target right acsention (Hrs)", NULL}, + {cmd_tagzd, CMD_TAGZD, "get/set target zenith distance (Deg)", NULL}, + {cmd_teldec, CMD_TELDEC, "get current telescope declination (Deg)", NULL}, + {cmd_telra, CMD_TELRA, "get current telescope right acsention (Hrs)", NULL}, + {cmd_track, CMD_TRACK, "start tracking from current position", NULL}, + {dtimeh, CMD_UNIXT, "get server's UNIX time", NULL}, {NULL, NULL, NULL, NULL} }; diff --git a/Daemons/10micron_stellarium/stellarium.c b/Daemons/10micron_stellarium/stellarium.c index e232a93..0db4b57 100644 --- a/Daemons/10micron_stellarium/stellarium.c +++ b/Daemons/10micron_stellarium/stellarium.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -68,12 +69,10 @@ STATUS (4 bytes, signed integer): status of the telescope, currently unused. */ -#define DEG2DEC(degr) ((int32_t)(degr / 90. * ((double)0x40000000))) -#define DEG2RA(degr) ((uint32_t)(degr / 180. * ((double)0x80000000))) -#define HRS2RA(degr) ((uint32_t)(degr / 12. * ((double)0x80000000))) -#define DEC2DEG(i32) (((double)i32)*90./((double)0x40000000)) -#define RA2DEG(u32) (((double)u32)*180. /((double)0x80000000)) -#define RA2HRS(u32) (((double)u32)*12. /((double)0x80000000)) +#define RAD2DEC(rad) ((int32_t)((rad) / ERFA_DPI * ((double)0x80000000))) +#define RAD2RA(rad) ((uint32_t)((rad) / ERFA_DPI * ((double)0x80000000))) +#define DEC2DEG(i32) (((double)(i32))*90./((double)0x40000000)) +#define RA2HRS(u32) (((double)(u32))*12. /((double)0x80000000)) typedef struct __attribute__((__packed__)){ uint16_t len; @@ -126,23 +125,9 @@ static bool proc_data(uint8_t *data, ssize_t len){ return false; } // convert RA/DEC to degrees - double tagRA = RA2DEG(ra), tagDec = DEC2DEG(dec); - DBG("RA: %u (%g degr), DEC: %d (%g degr)", ra, tagRA, dec, tagDec); - LOGMSG("(stellarium) RA: %u (%g degr), DEC: %d (%g degr)", ra, tagRA, dec, tagDec); -#if 0 - // check RA/DEC - horizCrds_t hnow; // without refraction - polarCrds_t p2000, pnow; - p2000.ra = DEG2RAD(tagRA); - p2000.dec = DEG2RAD(tagDec); - // now J2000 obs Jnow - if(!get_ObsPlace(NULL, &p2000, &pnow, &hnow)){ - WARNX("Can't convert coordinates to Jnow"); - return false; - } - tagRA = RAD2DEG(pnow.ra - pnow.eo); - tagDec = RAD2DEG(pnow.dec); -#endif + double tagRA = RA2HRS(ra), tagDec = DEC2DEG(dec); + DBG("RA: %u (%g hrs), DEC: %d (%g degr)", ra, tagRA, dec, tagDec); + LOGMSG("(stellarium) RA: %u (%g hrs), DEC: %d (%g degr)", ra, tagRA, dec, tagDec); return (mount_setInpRA(tagRA) && mount_setInpDec(tagDec) && mount_setInpMJD(ERFA_DJM00)); } @@ -184,10 +169,9 @@ static void *handle_socket(void *sockd){ continue; } //DBG("got : %g/%g", RA, Decl); - dout.ra = htole32(HRS2RA(RA)); - dout.dec = (int32_t)htole32(DEG2DEC(Decl)); + dout.ra = htole32(RAD2RA(RA)); + dout.dec = (int32_t)htole32(RAD2DEC(Decl)); if(!send_data((uint8_t*)&dout, sizeof(outdata), sock)) break; - //DBG("sent ra = %g, dec = %g", RA2HRS(dout.ra), DEC2DEG(dout.dec)); if(!sl_canread(sock)){ sleep(1); continue;