r''' Frame definition. Based on JUI-ADST-INST-TN-000122_01
The frame of the JDC is defined, though it is not the final.
JDC's frame0
**Spacecraft frame**
* +z: nadir deck
* -z: zenith deck.
* -x: HGA
JDC will be located at the edge of +x/-z.
**JDC1 frame**
* +z: JDC symmetric axis. The JDC looking hemisphere is +x hemisphere.
* +x: Open direction (same direction as SC frame)
* -x: Toward the thruster (and HGA direction)
Note also that JDC would have a tilt around y axis, due to the contamination from
the thrusters.
The angle of tilt is not yet determined.
Thus, this angle would be given as a parameter.
**Conversion between JDC & SC**
The conversion matrix is as follows:
.. math::
x_SC \cos\theta 0 \sin\theta x_JDC
y_SC = 0 -1 0 y_JDC
z_SC \sin\theta 0 -\cos\theta z_JDC
**Convert between the JDC0 angles and vectors**
The converion of the angles to JDC1 frame is implemented.
See :func:`angles2jdc` and :func:`jdc2angles`.
The definition follows the definition of myself.
Thus, the coordinate system may be chagned in the future.
The definition is consistent to the one defined in :mod:`fov1 <irfpy.jdc.fov1>`.
The elevation angle, :math:`\theta`, 0 is the zenith (z axis) and 180 for the nadir looking direction.
The azimutha angle, :math:`\phi`, 0 is x axis and 90 for y axis.
Angle :math:`\theta` and :math:`\phi` is the polar coordinate system
of the JDC1 frame.
**Convert from NSC vectors to physical frame**
The conversion is implemented in :mod:`irfpy.pep.pep_attitude` module.
'''
import numpy as np
[docs]def angles2jdc(theta, phi):
r''' Return the unit vector corresponding to the given angles.
:param theta: Theta in degrees. Float or (N,) shape np.array.
:type theta: float
:param phi: Phi in degrees. Float or (N,) shape np.array.
:type phi: float
:returns: The corresponding vector with shape of (3,) or (3, N)
:rtype: ``np.array``
>>> print(angles2jdc(0, 0))
[ 0. 0. 1.]
The following returns the corresponding vector for
:math:`(\theta, \phi) = (0, 0), (1, 1), (2, 2), ...`
at once.
>>> print(angles2jdc(np.arange(181), np.arange(181)).shape)
(3, 181)
'''
t = np.deg2rad(theta); p = np.deg2rad(phi)
x = np.sin(t) * np.cos(p)
y = np.sin(t) * np.sin(p)
z = np.cos(t)
return np.array([x, y, z])
[docs]def jdc2angles(vec):
''' Return the JDC angle for the corresponding JDC vector.
:param vec: np.array, with (3,) or (3, N) shape.
:type vec: np.array
:returns: Theta and Phi
:rtype: np.array with (2,) or (2, N) shape.
>>> print(jdc2angles([1, 0, 0]))
[90. 0.]
For multiple vectors, you can convert to angles.
Note that the shape should be (3, N), thus, the array should look like
``np.array([[x0, x1, x2, ...], [y0, y1, y2, ...], [z0, z1, z2, ...]])``
>>> print(jdc2angles([[1, 10, 0, 1], [0, 0, 1, 0], [0, 0, 0, 1]]))
[[90. 90. 90. 45.]
[ 0. 0. 90. 0.]]
'''
# vec is (3,) or (3, N)
veclen = np.sqrt((np.array(vec) ** 2).sum(0)) # Now, scalar or (N,)
vu = vec / veclen # Now, (3,) or (3, N)
t = np.arccos(vu[2])
p = np.arctan2(vu[1], vu[0])
return np.array([np.rad2deg(t), np.rad2deg(p)])
[docs]def nsc2jdc(vecnsc, tilt=0):
''' Convert from NSC to JDC.
:param vec: (3,) or (3,N) array.
:param tilt: Tilt angle in degrees.
vec should be (3,) or (3,N) array.
>>> nsc = [ 1., -2., 3.]
>>> print(nsc2jdc(nsc))
[ 1. 2. -3.]
>>> nsc = [-1.41421356, -2., 2.82842712]
>>> print(nsc2jdc(nsc, tilt=45))
[ 1. 2. -2.99999999]
>>> nscs = [[ 2., 1., 0., -1., 2.,],
... [-1., -1., -1., -1., -1.],
... [-3., -1., 0., 1., 3.]]
>>> print(nsc2jdc(nscs))
[[ 2. 1. 0. -1. 2.]
[ 1. 1. 1. 1. 1.]
[ 3. 1. 0. -1. -3.]]
'''
c = np.cos(np.deg2rad(tilt))
s = np.sin(np.deg2rad(tilt))
mat = np.array([[c, 0, s], [0, -1, 0], [s, 0, -c]]).T
vecjdc = mat.dot(vecnsc)
return vecjdc
[docs]def jdc2nsc(vecjdc, tilt=0):
''' Convert from JDC to (N)SC.
:param vec: (3,) or (3,N) array.
:param tilt: Tilt angle in degrees.
.. math::
x_SC \cos\theta 0 \sin\theta x_JDC
y_SC = 0 -1 0 y_JDC
z_SC \sin\theta 0 -\cos\theta z_JDC
>>> jdc = [1, 2, -3]
>>> print(jdc2nsc(jdc))
[ 1. -2. 3.]
>>> print(jdc2nsc(jdc, tilt=45))
[-1.41421356 -2. 2.82842712]
>>> jdcs = [ [ 2, 1, 0, -1, 2],
... [ 1, 1, 1, 1, 1],
... [ 3, 1, 0, -1, -3]]
>>> print(jdc2nsc(jdcs))
[[ 2. 1. 0. -1. 2.]
[-1. -1. -1. -1. -1.]
[-3. -1. 0. 1. 3.]]
'''
c = np.cos(np.deg2rad(tilt))
s = np.sin(np.deg2rad(tilt))
mat = np.array([[c, 0, s], [0, -1, 0], [s, 0, -c]])
vecnsc = mat.dot(vecjdc)
return vecnsc
import unittest
import doctest
[docs]def doctests():
return unittest.TestSuite((
doctest.DocTestSuite(),
))
if __name__ == '__main__':
unittest.main(defaultTest='doctests')