Instrument Neutral Distributed Interface INDI 2.2.5
vtel.c
Go to the documentation of this file.
1#include "sofa.h"
2#include "spk.h"
3
4static void Aim ( double rm[3][3], double pae[3],
5 double *xaim, double *yaim, double *zaim );
6
7static int A2e ( double xaim, double yaim, double zaim,
8 double xtel, double ytel, double ztel,
9 double pia, double pib, double pnp,
10 double srma, double crma,
11 double xpo, double ypo, double ga, double gb,
12 double *ea1, double *eb1,
13 double *ea2, double *eb2 );
14
15static int A2tp ( double xaim, double yaim, double zaim,
16 double xtel, double ytel, double ztel,
17 double pnp, double a, double b,
18 double *xi, double *eta );
19
20static void Bs ( double xtel, double ytel, double ztel,
21 double srma, double crma,
22 double xpo, double ypo, double ga, double gb,
23 double *xbs, double *ybs, double *zbs );
24
25static int Sky ( double enca, double encb,
26 double xtel, double ytel, double ztel,
27 double pia, double pib, double pnp,
28 double srma, double crma,
29 double xpo, double ypo, double ga, double gb,
30 double rm[3][3], spkAST* ast, spkSYS sys,
31 double *tara, double *tarb );
32
33int spkVtel ( spkVTS isoln, spkOBS* obs, spkOPT* opt, spkPM* pm,
34 spkAST* ast, spkAX3* ax3, spkTAR* tar, spkPO* po,
35 double* tara, double* tare, double* tarr, double* tarp,
36 double soln[5] )
37/*
38** - - - - - - - -
39** s p k V t e l
40** - - - - - - - -
41**
42** Solve a "virtual telescope" (Note 1).
43**
44** Given:
45** isoln spkVTS what to solve for (Note 3)
46** obs spkOBS* observatory
47** opt spkOPT* optics (for focal length)
48** pm spkPM* pointing model (Note 4)
49** ast spkAST* astrometry parameters (Note 5)
50** ax3 spkAX3* achieved roll, pitch, rotator angles (radians)
51** tar spkTAR* target (ICRS, apparent or altaz)
52** po spkPO* hotspot x,y (same units as focal length)
53**
54** Returned:
55** tara double* target observed azimuth (N thru E, radians)
56** tare double* target observed elevation (radians)
57** tarr double* target roll (radians)
58** tarp double* target pitch (radians)
59** soln double[5] solution (Notes 3,8)
60**
61** Returned (function value):
62** int status: +1 = pole avoidance occurred
63** 0 = OK
64** -1 = no solutions
65** -2 = geometrically impossible
66** -3 = illegal target system
67**
68** Notes:
69**
70** 1) The virtual telescope (see reference) is a data construct that
71** describes the relationship between three aspects of pointing a
72** telescope, namely the coordinates of the celestial target, the
73** position in the focal plane of the imaged target, and the angles
74** to which the mount axes must be set in order to acquire the
75** image. Given any two of these, along with certain other
76** information, the third can be deduced. The scheme is as follows:
77**
78** [ TARGET ] <- target [a,b] and type
79** v
80** astronomical transformations <- TDB, UT1, site
81** v
82** refraction <- weather, color
83** v
84** [ observed Az,El ]
85** v
86** mount type
87** v
88** [ nominal roll,pitch ]
89** v
90** mount misorientation <- AW, AN
91** v
92** [ AIM ]
93** | }
94** roll }
95** | } -> encoder demands
96** roll/pitch nonperp }
97** | } <- NP, IA, IB
98** pitch }
99** | }
100** [ BORESIGHT ]
101** ^
102** guiding <- ga, gb
103** ^
104** hotspot <- [x,y] and rotator angle
105** ^
106** [ TELESCOPE ]
107** ^
108** vertical deflection <- VD
109** ^
110** tel/pitch nonperp <- CA
111** ^
112** [ 1,0,0 ]
113**
114** Thus a telescope can track a star by knowing the RA,Dec and the
115** desired image x,y, and repeatedly solving for mount angles as the
116** astronomical transformations progress. Or the mapping between
117** sky coordinates and focal plane coordinates can be sampled, in
118** both directions.
119**
120** 2) The coordinate systems used are oriented as follows.
121**
122** The longitude and latitude coordinates of the (arbitrarily
123** oriented) mount are called roll/pitch. If the mount is an
124** altazimuth, the roll coordinate is pi-azimuth (where in this
125** case azimuth is north zero left-handed) and the pitch coordinate
126** is elevation. If the mount is an equatorial, roll is -HA and
127** pitch is declination.
128**
129** The AIM vector is the pointing direction in the mount roll/pitch
130** coordinate system (see Note 7).
131**
132** The TELESCOPE vector is with respect to:
133**
134** x-axis: at right angles to both the roll and pitch axes
135** y-axis: along the pitch axis
136** z-axis: at right angles to the other two axes
137**
138** In the absence of either collimation error or vertical deflection
139** the TELESCOPE vector is [1,0,0].
140**
141** The BORESIGHT vector is expressed in a right-handed Cartesian
142** system where the x,y plane contains the telescope and the pitch
143** axis, and the x-axis is close to the telescope.
144**
145** Focal plane x/y is right-handed as seen by the light approaching
146** the focal plane in a non-mirror-imaging telescope such as a
147** refractor. This means that when projected onto the sky the x/y
148** axes are left-handed.
149**
150** Zero rotator angle is when the projection on the sky of the
151** focal plane y axis points at the negative mount pole, hence
152** downwards in an altazimuth and south in an equatorial. The angle
153** increases counterclockwise on the sky.
154**
155** 3) The argument isoln specifies what quantities are to be solved
156** for:
157**
158** o If isoln = AXES, the result is the mount axis angles required
159** to image the target onto the desired x,y, known as the
160** "hotspot". There can be two sets of these angles, one
161** corresponding to the "beyond the pole" state of the mount.
162** Also computed is the field orientation, in the form of the
163** position angle of the rotating focal plane's y-axis.
164** n.b. The given argument ax3 is needed for other purposes and
165** must contain valid "achieved" angles.
166**
167** o If isoln = TARG, the result is the celestial coordinates of
168** the target. The supported systems are ICRS astrometric
169** [RA,Dec], geocentric apparent [RA,Dec] and observed [Az,El],
170** the latter left-handed (N thru E). The given argument tar is
171** needed for other purposes and must contain a valid target.
172**
173** o If isoln = HOTS, the result is the x,y position of the image
174** in the rotating focal plane. The given argument po is not
175** used and need not be initialized.
176**
177** o If isoln = DEFT (or any other value) no solution takes place -
178** see the next sentence.
179**
180** Irrespective of the isoln value, the target's observed place as
181** right-handed [az,el] and mount [roll,pitch] are returned, for
182** general purposes including the calculation of pointing-model
183** terms.
184**
185** 4) The pointing model pm comprises seven terms, called IA, IB, VD,
186** CA, NP, AW and AN. A typical operational pointing model would
187** contain a greater variety, each being mapped onto the most
188** natural one of the seven.
189**
190** 5) The astrometry parameters ast can be formed by calling the
191** spkAstr function with the appropriate UTC specified. In spkAstr
192** the argument jfull controls whether a complete recalculation is
193** to be carried out or merely the Earth rotation angle. A common
194** strategy would be to recompute the parameters prior to acquiring
195** a new target (or even once a night), and to update only the ERA
196** at the rate of the tracking loop, typically 20 Hz.
197**
198** 6) The returned tara and tare are the observed place (i.e. the
199** pointing direction) as left-handed az,el, where az runs north
200** through east.
201**
202** 7) The returned tarr and tarp are the target observed place in
203** mount roll,pitch, called AIM in the Note 1 diagram. For an
204** equatorial mount, the nominal orientation of the roll,pitch
205** frame makes tarr minus hour angle and tarp declination. For an
206** altazimuth mount, the nominal orientation makes tarr pi minus the
207** north-through-east azimuth and tarp elevation (more properly
208** called altitude). For both types of mount, the actual
209** orientation depends on data members pan and paw in the spkPM
210** pointing-model structure. These are typically a few tens of
211** arcseconds, and are called polar misalignment for an equatorial
212** and azimuth axis tilt in an altazimuth.
213**
214** 8) The soln array receives from one to five doubles, depending on
215** the isoln argument, as follows:
216**
217** isoln AXES HOTS TARG else
218**
219** soln[0] r x f -
220** soln[1] p y g -
221**
222** soln[2] rb - - -
223** soln[3] pb - - -
224**
225** soln[4] th - - -
226**
227** Unused soln elements (marked -) are undefined. Everything but
228** x and y are radians.
229**
230** For the AXES solution:
231**
232** . The results r,p and rb,pb are the roll,pitch mount pointing
233** demands needed to image the target onto the hotspot.
234**
235** The "b" pair are for the "beyond the pole" configuration. It
236** is up to the telescope control application to decide whether
237** r,p or rb,pb are to be used as drive demands. For equatorials
238** the "b" set represents below the pole in a fork or horseshoe
239** mount and one of the "meridian flip" cases in GEMs and
240** cross-axis mounts. The "b" set are not commonly used for
241** altazimuths, though they could be in designs where "through the
242** zenith" is allowed.
243**
244** . The th result is the rotator demand that will, at the hotspot,
245** make the y-axis of the rotating focal plane point north (or up)
246** in the target's celestial coordinate system.
247**
248** If the desired field orientation (i.e. the desired position
249** angle of the y-axis, counterclockwise from north) is ypa, the
250** rotator demand is th + ypa. In altazimuth telescopes in
251** particular this will provide the ever-changing tracking demands
252** for the rotator. The same is true for equatorials, though
253** usually the rotator is not driven continuously and the small
254** residual field rotations neglected.
255**
256** It is important to understand that the soln[4] value is for the
257** achieved mount orientation, supplied in the ax3 structure, and
258** whether this is close to r,p or rb,pb depends on the current
259** "beyond the pole" status.
260**
261** For the HOTS solution, the x,y results are the coordinates of the
262** target's image given the current mount pointing. They are in the
263** units chosen for the telescope focal length in the spkOBS
264** structure, for example millimeters, and are on the rotating focal
265** plane, so will stay constant for a specific place on an
266** instrument, such as a spectrograph slit.
267**
268** For the TARG solution, the f,g results are the sky position that
269** corresponds to the hotspot x,y given the current mount pointing.
270** This is an [RA,Dec] when the target's system is ICRS or APPT, or
271** [Az,El] (left-handed) for the AZEL case.
272**
273** Reference:
274**
275** Wallace, P.T., 2002, "A rigorous algorithm for telescope
276** pointing", Advanced Telescope and Instrumentation Control
277** Software II, edited by Lewis, Hilton, proceedings of the SPIE,
278** 4848, 125 (referred to here as W02).
279**
280** Called: iauAnpm, iauAtciqz, iauAtioq, iauC2s, iauIr, iauPas, iauRx,
281** iauRy, iauRxp, iauS2c, iauAnp, A2e, A2tp, Aim, Sky
282**
283** This revision: 2024 July 10
284**
285** Author P.T.Wallace - see license notice at end.
286*/
287{
288/* Angles in radians */
289 const double D90 = 1.570796326794896619231322, /* pi/2 */
290 D180 = 3.141592653589793238462643, /* pi */
291 ARCSEC = 4.848136811095359935899141e-6; /* 1 arcsec */
292
293/* A tiny number */
294 const double TINY = 1e-20;
295
296 int j, jpav;
297 double atar, etar, ri, di, aob, zob, hob, dob, rob, pae[3], rm[3][3],
298 p[3], srma, crma, a, b, ad, ed, x, y, z, a1, b1, a2, b2, au,
299 bu, xi, eta, f, xtel, ytel, ztel, w;
300
301
302/*
303** ---------------------------------------------
304** Obtain the target direction as observed Az,El
305** ---------------------------------------------
306*/
307
308/* Is the target Az,El? */
309 if ( tar->sys == AZEL ) {
310
311 /* Yes; use it as it is. */
312 atar = tar->a;
313 etar = tar->b;
314
315 } else {
316
317 /* Otherwise it's an RA,Dec. Which sort? */
318 if ( tar->sys == ICRS ) {
319
320 /* ICRS; transform into CIRS. */
321 iauAtciqz ( tar->a, tar->b, &ast->astrom, &ri, &di );
322
323 } else if ( tar->sys == APPT ) {
324
325 /* Apparent; transform into CIRS. */
326 ri = tar->a + ast->eo;
327 di = tar->b;
328
329 } else {
330
331 /* Unrecognized target system; give up. */
332 return -3;
333 }
334
335 /* Transform CIRS RA,Dec to observed place. */
336 iauAtioq ( ri, di, &ast->astrom, &aob, &zob, &hob, &dob, &rob );
337
338 /* Pointing direction, Az,El (n.b. north zero, left-handed). */
339 atar = aob;
340 etar = D90 - zob;
341 }
342
343/* Return the left-handed az,el. */
344 *tara = atar;
345 *tare = etar;
346
347/* Express as south zero right-handed az,el vector. */
348 iauS2c ( D180 - atar, etar, pae );
349
350/*
351** --------------------------------
352** Obtain the mount attitude matrix (W02 4.2.2, matrix M)
353** --------------------------------
354*/
355
356/* Initialize the nominal mount attitude matrix M0 to identity. */
357 iauIr ( rm );
358
359/* If EQUAT, y-rotation by colatitude. */
360 if ( obs->mount == EQUAT ) iauRy ( obs->slat - D90 , rm );
361
362/* Apply the pole displacements to give matrix M. */
363 iauRy ( -pm->pan, rm );
364 iauRx ( pm->paw, rm );
365
366/* Use it to return the observed place as mount roll,pitch. */
367 iauRxp ( rm, pae, p );
368 iauC2s ( p, tarr, tarp );
369
370/*
371** -----------------------------------
372** Functions of achieved rotator angle
373** -----------------------------------
374*/
375
376 srma = sin(ax3->r);
377 crma = cos(ax3->r);
378
379/*
380** ---------------------------
381** Obtain the TELESCOPE vector (W02 4.2.14)
382** ---------------------------
383*/
384
385/* Remove index errors from the mount roll,pitch. */
386 a = ax3->a + pm->pia;
387 b = ax3->b + pm->pib;
388
389/* Rotate into az,el (left-handed). */
390 iauS2c ( a, b, p );
391 iauTrxp ( rm, p, p );
392 iauC2s ( p, &ad, &ed );
393
394/* Raise by the vertical deflection to give undrooped version.
395** Original: iauS2c(ad, ed + pm->pvd, p)
396** The original constant formula is consistent with Wallace's own usage where
397** pvd was tuned empirically against real observations (see point.c). It is
398** inconsistent, however, when pvd is set from Pmfit's fitted TF coefficient,
399** because Pmfit models TF as bf[5]*sin(z) = bf[5]*cos(el) (Bfun Note 4).
400** When pvd = pm[5] (the Pmfit coefficient), the sin(z) factor must be applied
401** here; omitting it produces site-dependent residuals of several arcseconds. */
402 iauS2c ( ad, ed + pm->pvd * cos(ed), p );
403
404/* Rotate back into the mount system. */
405 iauRxp ( rm, p, p );
406
407/* The undrooped TELESCOPE vector. */
408 x = cos(pm->pca);
409 y = sin(pm->pca);
410 z = 0.0;
411
412/* Undrooped telescope direction to encoder roll,pitch. */
413 j = A2e ( p[0], p[1], p[2], x, y, z, 0.0, 0.0, pm->pnp, srma, crma,
414 0.0, 0.0, 0.0, 0.0, &a1, &b1, &a2, &b2 );
415 if ( j ) return -1;
416
417/* Select the solution that matches the current posture. */
418 if ( fabs(ax3->b) < D90 ) {
419 au = a1;
420 bu = b1;
421 } else {
422 au = a2;
423 bu = b2;
424 }
425
426/* Drooped telescope direction as xi,eta. */
427 iauS2c ( a, b, p );
428 j = A2tp ( p[0], p[1], p[2], x, y, z, pm->pnp, au, bu, &xi, &eta );
429 if ( j ) return -2;
430
431/* Use xi,eta to determine the TELESCOPE vector. */
432 f = sqrt ( 1.0 + xi*xi + eta*eta );
433 xtel = ( x - xi*y ) / f;
434 ytel = ( y + xi*x ) / f;
435 ztel = eta / f;
436
437/*
438** --------------------------------
439** What is the VT to be solved for?
440** --------------------------------
441*/
442
443 jpav = 0;
444 switch ( isoln ) {
445
446 case AXES:
447
448 /*
449 ** ----------------------------
450 ** Solve for roll,pitch demands (W02 4.2.10)
451 ** ----------------------------
452 */
453
454 /* Obtain the AIM vector. */
455 Aim ( rm, pae, &x, &y, &z );
456
457 /* Safe it if too close to the mount pole. */
458 w = sqrt ( x*x + y*y );
459 if ( w < obs->pavoid ){
460 if ( x == 0.0 && y == 0.0 ) x = y = TINY;
461 w = obs->pavoid / w;
462 x *= w;
463 y *= w;
464 z = sqrt ( 1.0 - x*x - y*y );
465 jpav = 1;
466 }
467
468 /* Safe AIM to ENCODER demands. */
469 j = A2e ( x, y, z, xtel, ytel, ztel,
470 pm->pia, pm->pib, pm->pnp, srma, crma,
471 po->x/opt->fl, po->y/opt->fl, pm->ga, pm->gb,
472 &a1, &b1, &a2, &b2 );
473 if ( j ) return -1;
474
475 /* Solution 1 roll demand, in range +/- pi. */
476 soln[0] = iauAnpm(a1);
477
478 /* Solution 1 pitch demand. */
479 soln[1] = b1;
480
481 /* Solution 2 roll demand, in range +/- pi. */
482 soln[2] = iauAnpm(a2);
483
484 /* Solution 2 pitch demand. */
485 soln[3] = b2;
486
487 /*
488 ** -------------------------------
489 ** Determine the field orientation (W02 4.3)
490 ** -------------------------------
491 **
492 ** Note that the solution uses the roll,pitch supplied in the ax3
493 ** struct, not the values just calculated. A typical application
494 ** will, during tracking, extrapolate the axis positions so that the
495 ** starting point is is a good estimate of what is being solved for.
496 **
497 ** The achieved rotator angle used here is in the form of the sine
498 ** and cosine srma,crma, obtained from ax3.r earlier.
499 */
500
501 /* The current pointing origin (in focal lengths). */
502 x = po->x / opt->fl;
503 y = po->y / opt->fl;
504
505 /* Solve for celestial coordinates. */
506 j = Sky ( ax3->a, ax3->b, xtel, ytel, ztel,
507 pm->pia, pm->pib, pm->pnp, srma, crma,
508 x, y, pm->ga, pm->gb, rm, ast, tar->sys,
509 &a1, &b1 );
510 if ( j ) return -3;
511
512 /* Displace 1 arcsec in the +y direction. */
513 y += ARCSEC;
514
515 /* Solve for celestial coordinates. */
516 j = Sky ( ax3->a, ax3->b, xtel, ytel, ztel,
517 pm->pia, pm->pib, pm->pnp, srma, crma,
518 x, y, pm->ga, pm->gb, rm, ast, tar->sys,
519 &a2, &b2 );
520 if ( j ) return -3;
521
522 /* If Az,El change to right-handed coordinates. */
523 if ( tar->sys == AZEL ) {
524 a1 = -a1;
525 a2 = -a2;
526 }
527
528 /* Use the original and displaced P.O. to obtain the P.A. of +y. */
529 w = iauPas ( a1, b1, a2, b2 );
530
531 /* The rotator demand that will make the +y axis point north/up. */
532 soln[4] = iauAnp ( ax3->r - w );
533 break;
534
535 case HOTS:
536
537 /*
538 ** ------------------------
539 ** Solve for image position (W02 4.2.12)
540 ** ------------------------
541 */
542
543 /* Obtain the AIM vector. */
544 Aim ( rm, pae, &x, &y, &z );
545
546 /* Correct the demanded roll,pitch for index errors. */
547 a = ax3->a + pm->pia;
548 b = ax3->b + pm->pib;
549
550 /* Determine the image [xi,eta]. */
551 j = A2tp ( x, y, z, xtel, ytel, ztel, pm->pnp, a, b, &xi, &eta );
552 if ( j ) return -2;
553
554 /* Omit the guiding contributions from the result. */
555 xi -= pm->ga;
556 eta -= pm->gb;
557
558 /* Rotate into [x,y] coordinates. */
559 x = - xi*crma + eta*srma;
560 y = - xi*srma - eta*crma;
561
562 /* Return the x,y in user units. */
563 soln[0] = x * opt->fl;
564 soln[1] = y * opt->fl;
565
566 break;
567
568 case TARG:
569
570 /*
571 ** ----------------
572 ** Solve for target (W02 4.2.13)
573 ** ----------------
574 */
575
576 /* Solve for celestial coordinates. */
577 j = Sky ( ax3->a, ax3->b, xtel, ytel, ztel,
578 pm->pia, pm->pib, pm->pnp, srma, crma,
579 po->x/opt->fl, po->y/opt->fl, pm->ga, pm->gb,
580 rm, ast, tar->sys,
581 &a, &b );
582 if ( j ) return -3;
583
584 /* Return the Az,El or RA,Dec. */
585 soln[0] = iauAnp(a);
586 soln[1] = b;
587
588 break;
589
590 default:
591
592 /* Return only the star direction (altaz and mount). */
593 break;
594 }
595
596/* Exit with pole avoidance warning. */
597 if ( jpav ) return 1;
598
599/* Success. */
600 return 0;
601
602}
603
604/*--------------------------------------------------------------------*/
605
606static void Aim ( double rm[3][3], double pae[3],
607 double *xaim, double *yaim, double *zaim )
608
609/*
610** - - - -
611** A i m
612** - - - -
613**
614** Obtain the AIM vector components. (W02 4.2.3)
615**
616** Given:
617** rm double[3][3] mount attitude matrix (W02 4.2.2, matrix M)
618** pae double[3] pointing direction (right-handed az,el)
619**
620** Returned:
621** xaim double* AIM x-coordinate
622** yaim double* AIM y-coordinate
623** zaim double* AIM z-coordinate
624*/
625{
626 double prp[3];
627
628
629/* Rotate pointing direction into mount roll,pitch frame. */
630 iauRxp ( rm, pae, prp );
631
632/* The AIM vector components. */
633 *xaim = prp[0];
634 *yaim = prp[1];
635 *zaim = prp[2];
636
637}
638
639/*--------------------------------------------------------------------*/
640
641static int A2e ( double xaim, double yaim, double zaim,
642 double xtel, double ytel, double ztel,
643 double pia, double pib, double pnp,
644 double srma, double crma,
645 double xpo, double ypo, double ga, double gb,
646 double *ea1, double *eb1, double *ea2, double *eb2 )
647
648/*
649** - - - -
650** A 2 e
651** - - - -
652**
653** Partial sky to encoders tracking function that starts with the AIM
654** vector and ends with the equivalent ENCODER demands. (W02 4.2.10.)
655**
656** Given:
657** xaim double AIM x-coordinate (Note 1)
658** yaim double AIM y-coordinate (Note 1)
659** zaim double AIM z-coordinate (Note 1)
660** xtel double TELESCOPE vector, x-component (Note 1)
661** ytel double TELESCOPE vector, y-component (Note 1)
662** ztel double TELESCOPE vector, z-component (Note 1)
663** pia double 7-term pointing model IA (radians)
664** pib double 7-term pointing model IB (radians)
665** pnp double 7-term pointing model NP (radians)
666** srma double sine of rotator mechanical angle
667** crma double cosine of rotator mechanical angle
668** xpo double pointing origin x (in focal lengths)
669** ypo double pointing origin y (in focal lengths)
670** ga double guiding correction, collimation
671** gb double guiding correction, pitch
672**
673** Returned:
674** ea1 double* roll coordinate, first solution (Note 2)
675** eb1 double* pitch coordinate, first solution (Note 2)
676** ea2 double* roll coordinate, second solution (Note 2)
677** eb2 double* pitch coordinate, second solution (Note 2)
678**
679** Returned (function value):
680** int status: 0 = OK
681** else = no solutions (Note 3)
682**
683** Called: Bs
684**
685** Notes:
686**
687** 1 The AIM vector is the pointing direction in the mount roll/pitch
688** coordinate system (see Note 4).
689**
690** The TELESCOPE vector [xt,yt,zt] is with respect to:
691**
692** x-axis: at right angles to both the roll and pitch axes
693** y-axis: along the pitch axis
694** z-axis: at right angles to the other two axes
695**
696** In the absence of either collimation error or vertical deflection
697** the TELESCOPE vector is [1,0,0].
698**
699** The BORESIGHT vector [xbs,ybs,zbs] is expressed in a right-handed
700** Cartesian system where the x,y plane contains the telescope and
701** the pitch axis, and the x-axis is close to the telescope.
702**
703** 2 For any accessible target, there are two solutions; depending on
704** the type of mount, the two solutions correspond to above/below
705** the pole, nearside/farside of the zenith, east/west of the pier,
706** and so on.
707**
708** 3 Near the pole of the mount, especially when the collimation error
709** or nonperpendicularity are large, there may be no combination of
710** mount angles that images the target at the desired place. In
711** such cases, the returned status is the "no solutions" value, and
712** the returned roll and pitch are set to safe values.
713**
714** 4 The only supported case is where the rotator is mounted on the
715** telescope, for example Cass.
716*/
717
718{
719 const double TINY = 1e-20;
720
721 int j;
722 double xbs, ybs, zbs, snp, cnp, p, s, c, b1, b2, sb, cb, x, y,
723 a1, a2;
724
725
726/* Initialize status to OK. */
727 j= 0;
728
729/*
730** ---------------------------
731** Obtain the BORESIGHT vector
732** ---------------------------
733*/
734
735 Bs ( xtel, ytel, ztel, srma, crma, xpo, ypo, ga, gb,
736 &xbs, &ybs, &zbs );
737
738/* Deal with extreme case. */
739 if ( xbs == 0.0 ) {
740 j = -1;
741 xbs = TINY;
742 }
743
744/*
745** ----------------------------------------
746** From AIM and BORESIGHT solve for posture
747** ----------------------------------------
748*/
749
750/* Functions of a/b nonperpendicularity. */
751 snp = sin(pnp);
752 cnp = cos(pnp);
753
754/* Deal with extreme NP = +/-90 deg case. */
755 if ( cnp == 0.0 ) {
756 j = -1;
757 cnp = TINY;
758 }
759
760/* Solve for pitch angle (two solutions). */
761 p = atan2(zbs,xbs);
762 s = zaim + snp*ybs;
763 c = xaim*xaim + yaim*yaim - ybs*(2.0*zaim*snp+ybs) - snp*snp;
764 if ( c >= 0.0 ) {
765 c = sqrt(c);
766 } else {
767 j = -1;
768 c = 0.0;
769 }
770 b1 = atan2(s,c) - p;
771 b2 = atan2(s,-c) - p;
772
773/* Solution 1: rotate boresight vector, first Ry(b) then Rx(np). */
774 sb = sin(b1);
775 cb = cos(b1);
776 x = cb*xbs - sb*zbs;
777 y = snp*sb*xbs + cnp*ybs + snp*cb*zbs;
778
779/* Solve for remaining rotation, Rz(-a). */
780 a1 = ( x*x + y*y ) != 0.0 ?
781 atan2 ( yaim*x - xaim*y, x*xaim + y*yaim ) : 0.0;
782
783/* Same for solution 2. */
784 sb = sin(b2);
785 cb = cos(b2);
786 x = cb*xbs - sb*zbs;
787 y = snp*sb*xbs + cnp*ybs + snp*cb*zbs;
788 a2 = ( x*x + y*y ) != 0.0 ?
789 atan2 ( yaim*x - xaim*y, x*xaim + y*yaim ) : 0.0;
790
791/* Apply the index errors. */
792 *ea1 = a1 - pia;
793 *eb1 = b1 - pib;
794 *ea2 = a2 - pia;
795 *eb2 = b2 - pib;
796
797/* Status. */
798 return j;
799
800}
801
802/*--------------------------------------------------------------------*/
803
804static int A2tp ( double xaim, double yaim, double zaim,
805 double xtel, double ytel, double ztel,
806 double pnp, double a, double b,
807 double *xi, double *eta )
808
809/*
810** - - - - - - - -
811** t c s A 2 t p
812** - - - - - - - -
813**
814** In a "virtual telescope", given the AIM vector, and knowing the
815** mount roll/pitch, determine the [xi,eta] position of the image in
816** the focal plane. (W02 4.2.11.)
817**
818** Given:
819** xaim double AIM x-coordinate
820** yaim double AIM y-coordinate
821** zaim double AIM z-coordinate
822** xtel double TELESCOPE vector, x-component
823** ytel double TELESCOPE vector, y-component
824** ztel double TELESCOPE vector, z-component
825** pnp double 7-term pointing model NP (radians)
826** a double mount "roll" (Note 1)
827** b double mount "pitch" (Note 1)
828**
829** Returned:
830** xi double* image xi-coordinate (Note 2)
831** eta double* image eta-coordinate (Note 2)
832**
833** Returned (function value):
834** int* status: 0 = OK
835** else = geometrically impossible
836**
837** Notes:
838**
839** 1 The roll and pitch (a,b) are corrected for index errors,
840** i.e. they are the encoder settings plus the index errors.
841**
842** 2 In impossible cases, the status is set to an error value, and
843** xi and eta are undefined.
844*/
845
846{
847 const double TINY = 1e-20;
848
849 int j;
850 double rp[3][3], p[3], xb, yb, zb, x, y, z, r2, r, w, d;
851
852/* Obtain the posture matrix (W02 4.2.5). */
853 iauIr ( rp );
854 iauRy ( b, rp );
855 iauRx ( pnp, rp );
856 iauRz ( -a, rp );
857
858/* Use it to derotate AIM, giving BORESIGHT. */
859 p[0] = xaim;
860 p[1] = yaim;
861 p[2] = zaim;
862 iauTrxp ( rp, p, p );
863 xb = p[0];
864 yb = p[1];
865 zb = p[2];
866
867/* Deduce the image [xi,eta] that makes BORESIGHT and TELESCOPE match. */
868 x = xtel;
869 y = ytel;
870 z = ztel;
871 r2 = x*x + y*y;
872 r = sqrt ( r2 );
873 if ( r == 0.0 ) {
874 r = 1e-20;
875 x = r;
876 }
877 w = xb*x + yb*y;
878 d = w + zb*z;
879 if ( d > TINY ) {
880 j = 0;
881 } else if ( d >= 0.0 ) {
882 j = 1;
883 d = TINY;
884 } else if ( d > -TINY ) {
885 j = 2;
886 d = -TINY;
887 } else {
888 j = 3;
889 }
890 d *= r;
891 *xi = ( yb*x - xb*y ) / d;
892 *eta = ( zb*r2 - z*w ) / d;
893
894/* Return the status. */
895 return j;
896
897}
898
899/*--------------------------------------------------------------------*/
900
901static void Bs ( double xtel, double ytel, double ztel,
902 double srma, double crma,
903 double xpo, double ypo, double ga, double gb,
904 double *xbs, double *ybs, double *zbs )
905
906/*
907** - - -
908** B s
909** - - -
910**
911** Determine the telescope BORESIGHT direction, in a right-handed
912** Cartesian system where the x,y plane contains the nominal telescope
913** and the pitch axis, and the x-axis is close to the telescope.
914**
915** See W02 4.2.9.
916**
917** Given:
918** xtel double TELESCOPE vector, x-component
919** ytel double TELESCOPE vector, y-component
920** ztel double TELESCOPE vector, z-component
921** srma double sine of rotator mechanical angle
922** crma double cosine of rotator mechanical angle
923** xpo double pointing-origin x (in focal lengths)
924** ypo double pointing-origin y (in focal lengths)
925** ga double guiding correction, collimation
926** gb double guiding correction, pitch
927**
928** Returned:
929** xbs double* BORESIGHT x-coordinate
930** ybs double* BORESIGHT y-coordinate
931** zbs double* BORESIGHT z-coordinate
932**
933** Note:
934**
935** The only supported case is where the rotator is mounted on the
936** telescope - Newtonian, Cassegrain etc.
937*/
938
939{
940 double xi, eta, f, r, w;
941
942
943/* Pointing-origin position wrt rotator axis (W02 4.2.6). */
944 xi = - xpo*crma - ypo*srma;
945 eta = xpo*srma - ypo*crma;
946
947/* Displace rotator axis to allow for guiding (W02 4.2.8). */
948 xi += ga;
949 eta += gb;
950
951/* Apply to TELESCOPE, giving BORESIGHT (W02 4.2.9). */
952 f = sqrt ( 1.0 + xi*xi + eta*eta );
953 r = sqrt ( xtel*xtel + ytel*ytel );
954 if ( r == 0.0 ) {
955 r = 1e-20;
956 xtel = r;
957 }
958 w = eta*ztel;
959 *xbs = ( xtel - ( xi*ytel + w*xtel ) / r ) / f;
960 *ybs = ( ytel + ( xi*xtel - w*ytel ) / r ) / f;
961 *zbs = ( ztel + eta*r ) / f;
962
963}
964
965/*--------------------------------------------------------------------*/
966
967static int Sky ( double enca, double encb,
968 double xtel, double ytel, double ztel,
969 double pia, double pib, double pnp,
970 double srma, double crma,
971 double xpo, double ypo, double ga, double gb,
972 double rm[3][3], spkAST* ast, spkSYS sys,
973 double *tara, double *tarb )
974/*
975** - - - -
976** S k y
977** - - - -
978**
979** In a "virtual telescope", calculate the target coordinates that
980** correspond to the specified mount encoder demands and pointing-
981** origin.
982**
983** Given:
984** enca double mount "roll" encoder demand
985** encb double mount "pitch" encoder demand
986** xtel double TELESCOPE vector, x-component
987** ytel double TELESCOPE vector, y-component
988** ztel double TELESCOPE vector, z-component
989** pia double 7-term pointing model IA (radians)
990** pib double 7-term pointing model IB (radians)
991** pnp double 7-term pointing model NP (radians)
992** srma double sine of rotator mechanical angle
993** crma double cosine of rotator mechanical angle
994** xpo double pointing-origin x (in focal lengths)
995** ypo double pointing-origin y (in focal lengths)
996** ga double guiding correction, collimation
997** gb double guiding correction, pitch
998** rm double mount attitude matrix (Note 1)
999** ast spkAST* astrometry quantities
1000** sys spkSYS system for results
1001**
1002** Returned:
1003** tara double* target "longitude" (radians, Note 2)
1004** tarb double* target "latitude" (radians, Note 2)
1005**
1006** Returned (function value):
1007** int* status: 0 = OK
1008** else = illegal sys
1009**
1010** Called: iauAticq, iauAtoiq, iauC2s, iauIr, iauRx, iauRy, iauRz,
1011** iauRxp, iauTrxp, Bs
1012**
1013** Notes:
1014**
1015** 1 The mount attitude matrix is matrix M in W02 4.2.2. It rotates
1016** az,el (south zero right-handed) into roll,pitch.
1017**
1018** 2 The returned coordinates targa,targb are in the specified
1019** coordinate system. For sys = ALTAZ, tara is the azimuth (north
1020** zero left-handed) and tarb is the elevation. For sys = APPT
1021** they are geocentric apparent RA,Dec (equinox based) and for
1022** sys = ICRS they are ICRS astrometric RA,Dec.
1023*/
1024
1025{
1026 const double D180 = 3.141592653589793238462643; /* pi */
1027 const double D90 = 1.570796326794896619231322; /* pi/2 */
1028
1029 double a, b, rp[3][3], p[3], az, el, aob, ri, di;
1030
1031
1032/* Incorporate the index errors into the mount roll,pitch. */
1033 a = enca + pia;
1034 b = encb + pib;
1035
1036/* Obtain the posture matrix (W02 4.2.5). */
1037 iauIr ( rp );
1038 iauRy ( b, rp );
1039 iauRx ( pnp, rp );
1040 iauRz ( -a, rp );
1041
1042/* Obtain the BORESIGHT vector. */
1043 Bs ( xtel, ytel, ztel, srma, crma, xpo, ypo, ga, gb, p, p+1, p+2 );
1044
1045/* Rotate coordinate system of BORESIGHT, giving AIM. */
1046 iauRxp ( rp, p, p );
1047
1048/* Derotate aim into observed az,el (south zero right-handed). */
1049 iauTrxp ( rm, p, p );
1050 iauC2s ( p, &az, &el );
1051
1052/* Conventional north zero left-handed azimuth. */
1053 aob = D180 - az;
1054
1055/* What is the target coordinate system? */
1056 if ( sys == AZEL ) {
1057
1058 /* Return observed az,el (north zero left-handed). */
1059 *tara = aob;
1060 *tarb = el;
1061
1062 } else {
1063
1064 /* RA,Dec: get geocentric apparent CIRS. */
1065 iauAtoiq ( "A", aob, D90-el, &ast->astrom, &ri, &di );
1066
1067 /* Apparent or astrometric? */
1068 if ( sys == APPT ) {
1069
1070 /* Return equinox based geocentric apparent place. */
1071 *tara = ri - ast->eo;
1072 *tarb = di;
1073
1074 } else if ( sys == ICRS) {
1075
1076 /* Return ICRS astrometric place. */
1077 iauAticq ( ri, di, &ast->astrom, tara, tarb );
1078
1079 } else {
1080
1081 /* Illegal sys: abort. */
1082 return -1;
1083 }
1084 }
1085
1086/* Success. */
1087 return 0;
1088
1089}
1090
1091/*----------------------------------------------------------------------
1092**
1093** Copyright (C) 2024 by P.T.Wallace
1094**
1095** Permission to use, copy, modify, and/or distribute this software for
1096** any purpose with or without fee is hereby granted.
1097**
1098** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
1099** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
1100** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
1101** AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
1102** CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
1103** OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
1104** NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
1105** CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1106**
1107**--------------------------------------------------------------------*/
#define TINY
#define iauIr
Definition sofa.h:46
#define iauAtoiq
Definition sofa.h:74
#define iauTrxp
Definition sofa.h:51
#define iauAtioq
Definition sofa.h:73
#define iauAnpm
Definition sofa.h:39
#define iauC2s
Definition sofa.h:43
#define iauAticq
Definition sofa.h:72
#define iauRy
Definition sofa.h:48
#define iauAnp
Definition sofa.h:38
#define iauRxp
Definition sofa.h:50
#define iauRx
Definition sofa.h:47
#define iauAtciqz
Definition sofa.h:71
#define iauS2c
Definition sofa.h:42
#define iauRz
Definition sofa.h:49
#define iauPas
Definition sofa.h:54
@ EQUAT
Definition spk.h:41
spkVTS
Definition spk.h:52
@ HOTS
Definition spk.h:54
@ AXES
Definition spk.h:52
@ TARG
Definition spk.h:53
spkSYS
Definition spk.h:46
@ APPT
Definition spk.h:47
@ AZEL
Definition spk.h:48
@ ICRS
Definition spk.h:46
Definition spk.h:136
double eo
Definition spk.h:139
iauASTROM astrom
Definition spk.h:138
Definition spk.h:119
double b
Definition spk.h:121
double a
Definition spk.h:120
double r
Definition spk.h:122
Definition spk.h:78
double slat
Definition spk.h:80
double pavoid
Definition spk.h:83
spkMOUNT mount
Definition spk.h:82
Definition spk.h:94
double fl
Definition spk.h:95
Definition spk.h:100
double pib
Definition spk.h:102
double ga
Definition spk.h:108
double paw
Definition spk.h:106
double pca
Definition spk.h:104
double pnp
Definition spk.h:105
double pia
Definition spk.h:101
double pvd
Definition spk.h:103
double gb
Definition spk.h:109
double pan
Definition spk.h:107
Definition spk.h:113
double x
Definition spk.h:114
double y
Definition spk.h:115
Definition spk.h:143
spkSYS sys
Definition spk.h:144
double a
Definition spk.h:145
double b
Definition spk.h:146
DISPLAY_INFO di
Definition stvdriver.c:95
int spkVtel(spkVTS isoln, spkOBS *obs, spkOPT *opt, spkPM *pm, spkAST *ast, spkAX3 *ax3, spkTAR *tar, spkPO *po, double *tara, double *tare, double *tarr, double *tarp, double soln[5])
Definition vtel.c:33