I am developing an application for Raspberry Pi to control an amateur telescope on AltAzimutal mount.
The azimutal axis is not perfectly aligned with the zenith. In this case one can point onto 2 or 3 stars and find the transformation matrix between apparent telescope and equatorial coordinates. The method can be seen here. I want to implement this method with astropy
, but I don't understand how I can define the reference frame of the tilted telescope.
I calculate the transformatin matrix and give it as an argument for the new frame. But I get an error.
Here is the code:
# coding: utf-8
""" Astropy coordinate class for the tilted telescope coordinate system """
from __future__ import division, print_function
# Third-party
import numpy as np
from numpy import cos, sin
from astropy.coordinates import frame_transform_graph
from astropy.coordinates.angles import rotation_matrix
import astropy.coordinates as coord
import astropy.units as u
__all__ = ["MyFrame"]
import astropy.coordinates as coord
class MyFrame(coord.BaseCoordinateFrame):
"""
A topocentric spherical coordinate system defined by the telescope on tilted Altzimutal mount
http://www.geocities.jp/toshimi_taki/aim/aim.htm
Parameters
----------
matrix: the transformation matrix obtained by 2 stars method ( http://www.geocities.jp/toshimi_taki/aim/aim.htm)
representation : `BaseRepresentation` or None
A representation object or None to have no data (or use the other keywords)
Lambda : `Angle`, optional, must be keyword
The longitude-like angle corresponding to Sagittarius' orbit.
Beta : `Angle`, optional, must be keyword
The latitude-like angle corresponding to Sagittarius' orbit.
"""
default_representation = coord.UnitSphericalRepresentation
frame_specific_representation_info = {
'spherical': [coord.RepresentationMapping('lon', 'az'),
coord.RepresentationMapping('lat', 'alt'),
coord.RepresentationMapping('distance', 'distance')],
'unitspherical': [coord.RepresentationMapping('lon', 'az'),
coord.RepresentationMapping('lat', 'alt')]
}
def __init__(self,matrix,*args, **kwargs):
super(MyFrame, self).__init__(*args, **kwargs)
self.matrix=matrix
# equatorial (ICRS ) to tilted telescope AltAz coordinates
@frame_transform_graph.transform(coord.FunctionTransform, coord.ICRS, MyFrame)
def equatorial_to_telescope(icrs_frame, telescope_frame):
""" Compute the transformation from icrs spherical to
topocentric telescope coordinates.
"""
matrix=np.matrix(([1,0,0],[0,1,0],[0,0,1]))
C0=icrs_frame.represent_as(coord.CartesianRepresentation).xyz.value
l0=matrix.dot(C0)
altAZ=coord.SkyCoord(x=l0[0,0],y=l0[0,1],z=l0[0,2],frame='altaz',representation='cartesian').represent_as(coord.UnitSphericalRepresentation)
return MyFrame(az=altAZ.lon.to(u.deg), alt=altAZ.lat.to(*u.deg))
Here is the call of this class:
import myFrame as fr
import astropy.coordinates as coord
import astropy.units as u
import numpy as np
matrix=np.matrix(([1,0,0],[0,1,0],[0,0,1]))
m=fr.MyFrame()
icrs = coord.ICRS(152.88572*u.degree, 11.57281*u.degree)
mfr=icrs.transform_to(m)
Here is the error code:
TypeError Traceback (most recent call last)
<ipython-input-14-33f2cd1fa087> in <module>()
----> 1 mfr=icrs.transform_to(m)
/home/maksim/MyPython/astropy/coordinates/baseframe.pyc in transform_to(self, new_frame)
839 msg = 'Cannot transform from {0} to {1}'
840 raise ConvertError(msg.format(self.__class__, new_frame.__class__))
--> 841 return trans(self, new_frame)
842
843 def is_transformable_to(self, new_frame):
/home/maksim/MyPython/astropy/coordinates/transformations.pyc in __call__(self, fromcoord, toframe)
915 frattrs[inter_frame_attr_nm] = attr
916
--> 917 curr_toframe = t.tosys(**frattrs)
918 curr_coord = t(curr_coord, curr_toframe)
919
TypeError: __init__() takes at least 2 arguments (1 given)
I understand the error message: the definition of my constructor does not correspond to expectation of astropy
BaseFrame.
How can I transfer extern matrix to BaseCoordinateFrame instance?
You don't need or want to override the __init__
on your frame class to include the transformation matrix as an argument. Instead, because an specific frame defined in your frame class depends on this matrix it should be defined as a FrameAttribute
as demonstrated in the example in the docs: http://docs.astropy.org/en/stable/coordinates/frames.html#defining-a-new-frame
Looking at those docs I can see that the purpose of defining frame attributes is not as clear as it could be. But in short, merely adding an __init__
argument tells the coordinate machinery nothing about the purpose of that argument / attribute--it doesn't in any way indicate that this is a defining parameter of frames in this class of frames. That's information that the framework needs to know about and keep track of.
When you define matrix
as a frame attribute on your class it will automatically set up an accessor for the attribute (i.e. self.matrix
) and will also accept the matrix as an argument to the frame's initializer.
One thing that I'm not sure this immediately supports is a FrameAttribute
that is required to initialize the frame (usually each attribute has a default value). This could be implemented by a simple wrapper around the base __init__
though it also might not be a bad idea for a feature request.