Skip to content

Commit 8fc5311

Browse files
author
Cameron Tetford
committed
Polar Align Calc
1 parent 914a7f7 commit 8fc5311

File tree

1 file changed

+116
-0
lines changed

1 file changed

+116
-0
lines changed

Software/Addons/AutoPA/polaralign.py

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
#!/usr/bin/env python3
2+
import math
3+
from astropy.coordinates import SkyCoord, EarthLocation, AltAz, Angle
4+
from astropy import units as u
5+
from astropy.time import Time
6+
from astropy.utils import iers
7+
import sys, subprocess
8+
9+
def polarcalc(mylat, mylong, myelev, observing_time, p1RA, p1DEC, p2RA, p2DEC, p3RA, p3DEC):
10+
#iers.conf.auto_download = False
11+
#iers.conf.auto_max_age = None
12+
13+
#Create time object based on given time
14+
observing_time = Time(observing_time)
15+
16+
#Create location object based on lat/long/elev
17+
observing_location = EarthLocation(lat=mylat*u.deg, lon=mylong*u.deg, height=myelev*u.m)
18+
19+
#Create coordinate objects for each point
20+
p1 = SkyCoord(p1RA, p1DEC, unit='deg')
21+
p2 = SkyCoord(p2RA, p2DEC, unit='deg')
22+
p3 = SkyCoord(p3RA, p3DEC, unit='deg')
23+
p1X = (90 - p1.dec.degree) * math.cos(p1.ra.radian)
24+
p1Y = (90 - p1.dec.degree) * math.sin(p1.ra.radian)
25+
p2X = (90 - p2.dec.degree) * math.cos(p2.ra.radian)
26+
p2Y = (90 - p2.dec.degree) * math.sin(p2.ra.radian)
27+
p3X = (90 - p3.dec.degree) * math.cos(p3.ra.radian)
28+
p3Y = (90 - p3.dec.degree) * math.sin(p3.ra.radian)
29+
30+
#Calculate center of circle using three points in the complex plane. DEC is treated as unitless for the purposes of the calculation.
31+
x, y, z = complex(p1X,p1Y), complex(p2X,p2Y), complex(p3X,p3Y)
32+
w = z-x
33+
w /= y-x
34+
c = (x-y)*(w-abs(w)**2)/2j/w.imag-x
35+
resultX = -c.real
36+
resultY = c.imag
37+
38+
#Convert X/Y values of circle into RA/DEC
39+
resultDEC = (90 - math.sqrt(resultX**2 + resultY**2))
40+
resultRA = math.atan2(resultY, resultX)*360 / (2*math.pi)
41+
if resultRA < 0:
42+
resultRA = (180-abs(resultRA))+180
43+
44+
#Create coordinate object for current alignment offset
45+
offset = SkyCoord(resultRA, resultDEC, frame='itrs', unit='deg', representation_type='spherical', obstime=Time(observing_time))
46+
print(f"Current alignment in RA/DEC: {Angle(resultRA*u.deg).to_string(u.hour, precision=2)}/{Angle(resultDEC*u.deg).to_string(u.degree, precision=2)}.")
47+
48+
#Create coordinate object for pole
49+
pole = SkyCoord(0, 90, frame='itrs', unit='deg', representation_type='spherical', obstime=Time(observing_time))
50+
51+
#Create coordinate object for pole
52+
poleAzAlt = pole.transform_to(AltAz(obstime=Time(observing_time),location=observing_location))
53+
print(f"True polar alignment in Az./Alt.: 0h00m00s/{poleAzAlt.alt.to_string(u.degree, precision=2)}.")
54+
55+
#Transform current alignment to Alt/Az coordinate system
56+
offsetAzAlt = offset.transform_to(AltAz(obstime=Time(observing_time),location=observing_location))
57+
print(f"Current alignment in Az./Alt.: {offsetAzAlt.az.to_string(u.hour, precision=2)}/{offsetAzAlt.alt.to_string(u.degree, precision=2)}.")
58+
59+
#Calculate offset deltas from pole
60+
#Normalize the azimuth values to between -180 and 180 degrees prior to determining offset.
61+
errorAz = (((poleAzAlt.az.deg + 180) % 360 - 180)-((offsetAzAlt.az.deg + 180) % 360 - 180))*60
62+
print(f"Azimuth error correction is: {errorAz:.4f} arcminutes.")
63+
errorAlt = (poleAzAlt.alt.deg-offsetAzAlt.alt.deg)*60
64+
print(f"Altitude error correction is: {errorAlt:.4f} arcminutes.")
65+
66+
return errorAz, errorAlt
67+
68+
#Latitude in degrees
69+
mylat = float(sys.argv[1])
70+
71+
#Longitude in degrees
72+
mylong = float(sys.argv[2])
73+
74+
#Elevation in meters
75+
myelev = float(sys.argv[3])
76+
77+
#YYYY-MM-DD HH:MM:SS format
78+
time = sys.argv[4]
79+
80+
#All RA/DEC values must be in compatible format to Astropy.coordinates library.
81+
#Preferrably degrees, but 00h00m00.0s and 00d00m00.0s should also work
82+
p1RA = float(sys.argv[5])
83+
p1DEC = float(sys.argv[6])
84+
p2RA = float(sys.argv[7])
85+
p2DEC = float(sys.argv[8])
86+
p3RA = float(sys.argv[9])
87+
p3DEC = float(sys.argv[10])
88+
89+
#Serial port address for Arduino, typically /dev/ttyACM0 in Astroberry, possibly /dev/ttyACM1
90+
if len(sys.argv) <= 11:
91+
serialport = "/dev/ttyACM0"
92+
else:
93+
serialport = sys.argv[11]
94+
95+
result = polarcalc(mylat, mylong, myelev, time, p1RA, p1DEC, p2RA, p2DEC, p3RA, p3DEC)
96+
97+
#Verify error correction can be handled by AutoPA hardware (assuming it is in home/centered position)
98+
moveAz = "N"
99+
if abs(result[0]) > 120:
100+
moveAz = input("Azimuth error may be out of bounds of hardware capabilities if not in home position. Continue? (Y/N): ")
101+
else:
102+
moveAz = "Y"
103+
if moveAz.upper() == "Y":
104+
#Call process to move azimuth using elevated privileges to override any existing serial connection
105+
subprocess.call(['sudo', './altaz.py', "az", str(result[0]), serialport])
106+
107+
moveAlt = "N"
108+
if result[1] > 168:
109+
moveAz = input("Altitude error may be out of bounds of hardware capabilities if not in home position. Continue? (Y/N): ")
110+
elif result[1] > 432:
111+
moveAz = input("Altitude error may be out of bounds of hardware capabilities if not in home position. Continue? (Y/N): ")
112+
else:
113+
moveAlt = "Y"
114+
if moveAlt.upper() == "Y":
115+
#Call process to move altitude using elevated privileges to override any existing serial connection
116+
subprocess.call(['sudo', './altaz.py', "alt", str(result[1]), serialport])

0 commit comments

Comments
 (0)