Instrument Neutral Distributed Interface INDI 2.2.5
altaz.c
Go to the documentation of this file.
1#include "astr.c"
2#include "ctar.c"
3#include "vtel.c"
4
5/*--------------------------------------------------------------------*/
6
7#include "spk.h"
8#include <sofa.h>
9#include <stdio.h>
10
11/*
12** - - - - - -
13** A L T A Z
14** - - - - - -
15**
16** Simple pointing kernel demonstrator for an altazimuth mount.
17**
18** This revision: 2024 July 12
19**
20** Author P.T.Wallace - see license notice at end.
21*/
22
23int main ()
24{
25/* Arcseconds and degrees to radians */
26 const double AS2R = 4.848136811095359935899141e-6;
27 const double D2R = 1.745329251994329576923691e-2;
28
29/* 180 deg in radians */
30 const double D180 = 3.141592653589793238462643;
31
32/* VT constituents */
33 spkEOP eop; /* polar motion and UT1-UTC (from IERS) */
34 spkOBS obs; /* site location and mount type */
35 spkAIR air; /* local weather readings */
36 spkOPT opt; /* focal length and color */
37 spkPM pm; /* 7-term pointing model */
38 spkPO po; /* image position in focal plane */
39 spkAX3 ax3; /* achieved roll, pitch, rotator angles */
40 spkUTC utc; /* UTC date and time */
41 spkAST ast; /* target-independent astrometric parameters */
42 spkTAR tar; /* sky target */
43
44 spkTAR tar2; /* another target */
45 spkPO po2; /* another hotspot */
46
47/* Names of sky coordinate systems */
48 static char *csys[] = {
49 "illegal",
50 "ICRS",
51 "apparent",
52 "altaz"
53 };
54
55/* Miscellaneous */
56 char s;
57 int i, j, i4[4], it;
58 double rc, dc, pr, pd, px, rv, ypa, soln[5], tara, tare, tarr, tarp,
59 dt, a, aold, bold, rold, da, db, dr;
60
61
62/*
63** --------------------------------------------
64** Initialize a starting set of VT constituents
65** --------------------------------------------
66**
67** Some of these will be used throughout the application, in some cases
68** unchanged and in others periodically updated, while there will be
69** other instances - different hotspots say - that are selected when
70** needed. The starting set is enough to get the system running and
71** tracking a star.
72*/
73
74/* Earth orientation parameters. */
75 eop.xp = 50.995e-3 * AS2R; /* polar motion */
76 eop.yp = 376.723e-3 * AS2R; /* polar motion */
77 eop.dut1 = 155.0675e-3; /* UT1-UTC */
78
79/* Site. */
80 if ( iauAf2a ( '-', 5, 41, 54.2, /* east longitude */
81 &obs.slon ) ) return -1;
82 if ( iauAf2a ( '-', 15, 57, 42.8, /* geodetic latitude */
83 &obs.slat ) ) return -1;
84 obs.sh = 625.0; /* altitude */
85 obs.mount = ALTAZ; /* mount type */
86 obs.pavoid = 0.5 * D2R; /* zenith avoidance */
87
88/* Weather. */
89 air.p = 952.0; /* pressure (hPA=mB) */
90 air.t = 18.5; /* temperature (Celsius) */
91 air.h = 0.83; /* humidity */
92
93/* Optics. */
94 opt.fl = 3000.0; /* focal length (mm) */
95 opt.wl = 0.55; /* wavelength (micrometers) */
96
97/* Pointing model. */
98 pm.pia = 25.0 * AS2R; /* +IA */
99 pm.pib = 15.0 * AS2R; /* +IE */
100 pm.pvd = 0.0 * AS2R; /* +FLOP */
101 pm.pca = -110.0 * AS2R; /* +CA */
102 pm.pnp = 8.0 * AS2R; /* +NPAE */
103 pm.paw = 999.9 * AS2R; /* +AW */
104 pm.pan = -12.0 * AS2R; /* +AN */
105
106 pm.ga = 0.0 * AS2R; /* guiding correction to pm.pca */
107 pm.gb = 0.0 * AS2R; /* guiding correction to pm.pib */
108
109/* The three axes. */
110 ax3.a = 0.0 * D2R; /* achieved azimuth (south zero right-handed) */
111 ax3.b = 0.0 * D2R; /* achieved elevation */
112 ax3.r = 30.0 * D2R; /* achieved rotator angle */
113
114/* Hotspot (i.e. pointing origin). */
115 po.x = 10.0;
116 po.y = 20.0;
117
118/* UTC date & time. */
119 utc.iy = 2013; /* year (CE) */
120 utc.mo = 4; /* month (1-12) */
121 utc.id = 2; /* day (1-28,29,30,31) */
122 utc.ih = 23; /* hour */
123 utc.mi = 15; /* minute */
124 utc.sec = 43.55; /* seconds (0-59.999... or 0-60.999...) */
125
126/* Astrometry. */
127 if ( spkAstr ( 1, utc, 0.0,
128 &eop, &obs, &air, &opt, &ast ) ) return -1;
129
130/* Target (in this case from a star catalog entry). */
131 if ( iauTf2a ( ' ', 14, 34, 16.81183, &rc ) ) return -1;
132 if ( iauAf2a ( '-', 12, 31, 10.3965, &dc ) ) return -1;
133 pr = atan2 ( -354.45e-3 * AS2R, cos(dc) );
134 pd = 595.35e-3 * AS2R;
135 px = 164.99e-3;
136 rv = 0.0;
137 spkCtar ( rc, dc, pr, pd, px, rv, &ast, &tar );
138
139/* Required position angle of +y axis. */
140 ypa = 30.0 * D2R;
141
142/*
143** --------------------
144** Demonstrate tracking
145** --------------------
146**
147** From one second ago up to and including now, at intervals of
148** 0.05 seconds, compute three-axis angle demands and velocities.
149**
150** The seconds are strictly UT1, which in this application can be
151** regarded as the same as SI seconds.
152**
153** It is assumed that the astrometry parameters have been computed for
154** "now" using spkAstr with jfull = TRUE, and that the track is relative
155** to this time and involves only jfull = FALSE calls to spkAstr. In
156** some implementations occasional use of the jfull = TRUE option during
157** tracking may be best.
158**
159** Updating the model terms is performed each time through, but an
160** economical implementation would probably elect to do it less
161** frequently, say at 1 Hz. If the update intervals are too long, the
162** corrections will not keep up with changing flexure etc. and will
163** also inject small glitches into the tracking demands.
164**
165** This demonstration shows just one way of computing the tracking
166** demands, and gives some indication of the level of intricacy that a
167** real TCS application would require. At first sight all that is
168** involved is to take the current target direction and hotspot
169** coordinates and solve the VT for the axis demands. However, there is
170** an interplay between the three axes that has to be resolved, and
171** the servo systems controlling the axis may well expect velocity
172** feedforward information (and conceivably acceleration and higher
173** derivatives). Consequently generating each new set of demands is
174** likely to involve multiple VT solutions, and the precise way this is
175** done will be something for the application developer to decide.
176**
177** A feature of the demonstration is that the velocities are NOT
178** computed by differencing successive demands, though this approach
179** would be efficient and may well work as it would in the present
180** simulation of sidereal tracking. The potential difficulty is in the
181** general case, where the observing program is free to introduce abrupt
182** changes to target, hotspot etc. The resulting velocity glitches can
183** cause adverse reactions from servo systems and inject unwanted
184** transients into the tracking. The demonstration code instead
185** recomputes the demands from last time, but using the current target
186** and hotspot. This means that the velocities always reflect a steady
187** background track if if something changed since last time.
188*/
189
190 printf ( "\n-----------------------------------"
191 "---------------------------------\n\n" );
192
193 printf ( " TAI azimuth elevation"
194 " rotator\n" );
195
196/* Initialize the per-timestep changes in the three axes. */
197 da = 0.0;
198 db = 0.0;
199 dr = 0.0;
200
201/* Initialize the time offset. */
202 dt = 0.0;
203
204/* The demonstration track (20Hz for 1s). */
205 for ( i = 0; i <= 20; i++ ) {
206
207 /* Solve for previous roll,pitch demands and field orientation. */
208 j = spkVtel ( AXES, &obs, &opt, &pm, &ast, &ax3, &tar, &po,
209 &tara, &tare, &tarr, &tarp, soln );
210 if ( j ) {
211 printf ( "spkVtel status = %d\n", j);
212 return -1;
213 }
214
215 /* The roll, pitch and rotator demands then. */
216 aold = soln[0];
217 bold = soln[1];
218 rold = iauAnpm ( soln[4] + ypa );
219
220 /* New time offset (seconds) relative to provided UTC. */
221 dt = ( (double) (i-20) ) / 20.0;
222
223 /* Update astrometry to that time. */
224 if ( spkAstr ( 0, utc, dt,
225 &eop, &obs, &air, &opt, &ast ) ) return -1;
226
227 /* Iterate to let roll/pitch/rotator angles settle. */
228 for ( it = 0; it < 2; it++ ) {
229
230 /* Extrapolated encoder readings. */
231 ax3.a = aold + da;
232 ax3.b = bold + db;
233 ax3.r = rold + dr;
234
235 /* Solve for roll,pitch demands and field orientation. */
236 j = spkVtel ( AXES, &obs, &opt, &pm, &ast, &ax3, &tar, &po,
237 &tara, &tare, &tarr, &tarp, soln );
238 if ( j ) {
239 printf ( "spkVtel status = %d\n", j);
240 return -1;
241 }
242
243 /* Set achieved roll,pitch,rotator to match. */
244 ax3.a = soln[0];
245 ax3.b = soln[1];
246 ax3.r = iauAnp ( soln[4] + ypa );
247
248 /* Changes since last time. */
249 da = iauAnpm ( ax3.a - aold );
250 db = iauAnpm ( ax3.b - bold );
251 dr = iauAnpm ( ax3.r - rold );
252
253 /* Next iteration. */
254 }
255
256 /* Update the pointing model (see note). */
257 pm.pia = 25.0 * AS2R; /* +IA */
258 pm.pib = 15.0 * AS2R; /* +IE */
259 pm.pvd = 10.0 * AS2R * cos(tare); /* +TF */
260 pm.pca = -110.0 * AS2R; /* +CA */
261 pm.pnp = 8.0 * AS2R; /* +NPAE */
262 pm.paw = 999.9 * AS2R; /* +AW */
263 pm.pan = -12.0 * AS2R; /* +AN */
264
265 /* Report the demands (as lefthanded altaz) and velocities. */
266 a = iauAnp ( D180 - ax3.a );
267 if ( i > 17 ) {
268 printf ( "\n%16.10f %15.10f %14.10f %15.10f deg\n",
269 ast.tai, a/D2R, ax3.b/D2R, iauAnp(ax3.r)/D2R );
270 printf ( "%+32.10f %+14.10f %+15.10f \"/s\n",
271 -20.0*da/AS2R, 20.0*db/AS2R, 20.0*dr/AS2R );
272 }
273 }
274 printf ( " MJD\n" );
275
276/*
277** -----------------------------------
278** Demonstrate solving for axis angles
279** -----------------------------------
280*/
281
282 j = spkVtel ( AXES, &obs, &opt, &pm, &ast, &ax3, &tar, &po,
283 &tara, &tare, &tarr, &tarp, soln );
284 if ( j ) {
285 printf ( "spkVtel status = %d\n", j);
286 return -1;
287 }
288
289 printf ( "\n-----------------------------------"
290 "---------------------------------\n\n" );
291 printf ( "Given:\n" );
292 printf ( " TAI = %15.9f MJD\n", ast.tai );
293 printf ( " RMA = %15.9f deg\n", ax3.r/D2R );
294 iauA2tf ( 4, iauAnp(tar.a), &s, i4 );
295 printf ( " target = %2.2d %2.2d %2.2d.%4.4d",
296 i4[0], i4[1], i4[2], i4[3] );
297 iauA2af ( 3, iauAnpm(tar.b), &s, i4 );
298 printf ( " %c%2.2d %2.2d %2.2d.%3.3d",
299 (int) s, i4[0], i4[1], i4[2], i4[3] );
300 printf ( " %s\n", csys[tar.sys] );
301 printf ( " hotspot [x,y] = %12.6f, %12.6f mm\n", po.x, po.y );
302 printf ( "Returned:\n" );
303 printf ( " encoder [Az,El] = %15.9f (N thru E), %15.9f deg\n",
304 180.0-soln[0]/D2R, soln[1]/D2R );
305 printf ( " PA of +y = %15.9f deg (%s)\n",
306 iauAnp(ax3.r-soln[4])/D2R, csys[tar.sys] );
307
308/*
309** ----------------------------------------------------
310** Demonstrate solving for RA,Dec given focal plane x,y
311** ----------------------------------------------------
312*/
313
314 po2.x = 25.0;
315 po2.y = 27.5;
316 j = spkVtel ( TARG, &obs, &opt, &pm, &ast, &ax3, &tar, &po2,
317 &tara, &tare, &tarr, &tarp, soln );
318 if ( j ) {
319 printf ( "spkVtel status = %d\n", j);
320 return -1;
321 }
322
323 printf ( "\n-----------------------------------"
324 "---------------------------------\n\n" );
325 printf ( "Given:\n" );
326 printf ( " TAI = %15.9f MJD\n", ast.tai );
327 printf ( " RMA = %15.9f deg\n", ax3.r/D2R );
328 printf ( " hotspot [x,y] = %12.6f, %12.6f mm\n", po2.x, po2.y );
329 printf ( " encoder [Az,El] = %15.9f (N thru E), %15.9f deg\n",
330 180.0-ax3.a/D2R, ax3.b/D2R );
331 printf ( "Returned:\n" );
332 iauA2tf ( 4, iauAnp(soln[0]), &s, i4 );
333 printf ( " target = %2.2d %2.2d %2.2d.%4.4d",
334 i4[0], i4[1], i4[2], i4[3] );
335 iauA2af ( 3, iauAnpm(soln[1]), &s, i4 );
336 printf ( " %c%2.2d %2.2d %2.2d.%3.3d",
337 (int) s, i4[0], i4[1], i4[2], i4[3] );
338 printf ( " %s\n", csys[tar.sys] );
339
340/*
341** ----------------------------------------------------
342** Demonstrate solving for focal plane x,y given RA,Dec
343** ----------------------------------------------------
344*/
345
346 if ( iauTf2a ( ' ', 14, 35, 35.1363560, &rc ) ) return -1;
347 if ( iauAf2a ( '-', 12, 32, 10.771790, &dc ) ) return -1;
348 spkCtar ( rc, dc, 0.0, 0.0, 0.0, 0.0, &ast, &tar2 );
349 j = spkVtel ( HOTS, &obs, &opt, &pm, &ast, &ax3, &tar2, &po,
350 &tara, &tare, &tarr, &tarp, soln );
351 if ( j ) {
352 printf ( "spkVtel status = %d\n", j);
353 return -1;
354 }
355
356 printf ( "\n-----------------------------------"
357 "---------------------------------\n\n" );
358 printf ( "Given:\n" );
359 printf ( " TAI = %15.9f MJD\n", ast.tai );
360 printf ( " RMA = %15.9f deg\n", ax3.r/D2R );
361 iauA2tf ( 4, iauAnp(tar2.a), &s, i4 );
362 printf ( " target = %2.2d %2.2d %2.2d.%4.4d",
363 i4[0], i4[1], i4[2], i4[3] );
364 iauA2af ( 3, iauAnpm(tar2.b), &s, i4 );
365 printf ( " %c%2.2d %2.2d %2.2d.%3.3d",
366 (int) s, i4[0], i4[1], i4[2], i4[3] );
367 printf ( " %s\n", csys[tar2.sys] );
368 printf ( " encoder [Az,El] = %15.9f (N thru E), %15.9f deg\n",
369 180.0-ax3.a/D2R, ax3.b/D2R );
370 printf ( "Returned:\n" );
371 printf ( " hotspot [x,y] = %12.6f, %12.6f mm\n",
372 soln[0], soln[1] );
373
374/*
375** -------------------------------
376** Determine direction of vertical
377** -------------------------------
378*/
379
380 tar2.sys = AZEL;
381 tar2.a = D180 - tara;
382 tar2.b = tare;
383 j = spkVtel ( AXES, &obs, &opt, &pm, &ast, &ax3, &tar2, &po,
384 &tara, &tare, &tarr, &tarp, soln );
385
386 printf ( "\n-----------------------------------"
387 "---------------------------------\n\n" );
388 printf ( "Given:\n" );
389 printf ( " TAI = %15.9f MJD\n", ast.tai );
390 printf ( " RMA = %15.9f deg\n", ax3.r/D2R );
391 printf ( " target = %15.9f (N thru E), %15.9f deg (%s)\n",
392 tar2.a/D2R, tar2.b/D2R, csys[tar2.sys] );
393 printf ( " hotspot [x,y] = %12.6f, %12.6f mm\n", po.x, po.y );
394 printf ( "Returned:\n" );
395 printf ( " encoder [Az,El] = %15.9f (N thru E), %15.9f deg\n",
396 180.0-ax3.a/D2R, ax3.b/D2R );
397 printf ( " PA of +y = %15.9f deg (%s)\n",
398 iauAnp(ax3.r-soln[4])/D2R, csys[tar2.sys] );
399
400 printf ( "\n-----------------------------------"
401 "---------------------------------\n" );
402
403/* Success. */
404 return 0;
405}
406
407/*----------------------------------------------------------------------
408**
409** Copyright (C) 2024 by P.T.Wallace
410**
411** Permission to use, copy, modify, and/or distribute this software for
412** any purpose with or without fee is hereby granted.
413**
414** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
415** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
416** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
417** AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
418** CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
419** OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
420** NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
421** CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
422**
423**--------------------------------------------------------------------*/
int main()
Definition altaz.c:23
int spkAstr(int jfull, spkUTC utc, double dt, spkEOP *eop, spkOBS *obs, spkAIR *air, spkOPT *opt, spkAST *ast)
Definition astr.c:4
void spkCtar(double rc, double dc, double pr, double pd, double px, double rv, spkAST *ast, spkTAR *tar)
Definition ctar.c:4
#define iauAnpm
Definition sofa.h:39
#define iauAnp
Definition sofa.h:38
@ ALTAZ
Definition spk.h:42
@ HOTS
Definition spk.h:54
@ AXES
Definition spk.h:52
@ TARG
Definition spk.h:53
@ AZEL
Definition spk.h:48
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
Definition spk.h:87
double h
Definition spk.h:90
double t
Definition spk.h:89
double p
Definition spk.h:88
Definition spk.h:136
double tai
Definition spk.h:137
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:71
double xp
Definition spk.h:72
double dut1
Definition spk.h:74
double yp
Definition spk.h:73
Definition spk.h:78
double slat
Definition spk.h:80
double slon
Definition spk.h:79
double pavoid
Definition spk.h:83
spkMOUNT mount
Definition spk.h:82
double sh
Definition spk.h:81
Definition spk.h:94
double wl
Definition spk.h:96
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
Definition spk.h:126
int mi
Definition spk.h:131
int mo
Definition spk.h:128
double sec
Definition spk.h:132
int id
Definition spk.h:129
int iy
Definition spk.h:127
int ih
Definition spk.h:130