Skip to content

Commit

Permalink
Add sun shield rotation for NEOS
Browse files Browse the repository at this point in the history
  • Loading branch information
dahlend committed Aug 30, 2024
1 parent 66fab1e commit 69eac7e
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 12 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).


## [Unreleased]

### Added

- Added sunshield rotation calculation for NEO Surveyor.


## [0.3.0] - 2024 - 8 - 28


Expand Down
23 changes: 11 additions & 12 deletions docs/code_structure.rst
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
Code Organization
=================

Goals of kete
---------------
kete is a collection of tools for calculating the orbits and expected fluxes for minor
planets specifically for the purpose of estimating which objects are visible in current,
past, or future sky surveys. Specifically the goal is that these calculations may be
performed on the full set of all known asteroids in a reasonable amount of time on a
laptop.
Goals of Kete
-------------
Kete is a collection of tools for calculating the orbits and expected fluxes for minor
planets for the purpose of estimating which objects are visible in current, past, or
future sky surveys. Specifically the goal is that these calculations may be performed
on the full set of all known asteroids in a reasonable amount of time on a laptop.

Propagation
~~~~~~~~~~~
Expand Down Expand Up @@ -37,7 +36,7 @@ decades at this point, and is often used to keep track of the ephemeris of plane
satellites (both natural and artificial), asteroids, and comets. Essentially the motion
of anything in the Solar System can be encoded in some flavor of SPICE kernel. The
primary downside of using cSPICE is that there is no native support for multi-core cpu
queries (an artifact of the age of the code). kete has native multi-core support for
queries (an artifact of the age of the code). Kete has native multi-core support for
the majority of all commonly used SPICE kernels.


Expand All @@ -59,8 +58,8 @@ the most common type of errors to do with memory allocation and management. In a
to this, Rust has excellent native multi-core support, especially for embarrassingly
parallel problems such as the orbit propagation required for kete.

kete Core
~~~~~~~~~~~
Kete Core
~~~~~~~~~
The Rust core of the library, which does the underlying orbit and flux calculations is
written entirely without any reference to Python. This core part is available as
`kete_core`, and programming can be done entirely within Rust for tools which do not
Expand All @@ -80,8 +79,8 @@ the `kete_core`. Ideally there should be no 'business' logic contained within th
wrappers, and they should largely exist to provide convenient mappings from the Python
concepts to the Rust internal organization.

kete Python
~~~~~~~~~~~~~
Kete Python
~~~~~~~~~~~
The remaining part of the code which is strictly Python is mostly quality of life
functions, plotting, and web query code. There is little to no mathematics or physics
contained within the Python.
73 changes: 73 additions & 0 deletions src/kete/neos.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import numpy as np

BANDS: list[float] = [4700.0, 8000.0]
"""Effective wavelength of the NC1 and NC2 bands in nm."""

Expand All @@ -22,3 +24,74 @@
[500.0, 1.01897, 0.96149],
]
"""Expected color correction required for black body sources at 300k"""


def sunshield_rotation(sun2obs, pointing):
"""
Calculate the angle the field of view must be rotated around the pointing
vector by in order to place the sun shield directly between the telescope
and sun.
The rotation is defined as the angle needed to move the sun shield from
the Z-axis down to the angle required to place it between the
sun and telescope. The angle is defined by the right hand rule applied
along the pointing vector.
Pointing vector must be at least about a half an arcsecond from the poles
in order to be computable.
Note that no coordinate frames are specified here, this provides the
rotation in the current frame from the frame's Z-axis. Provided inputs
are assumed to be from the matching frame.
Parameters
----------
sun2obs :
The vector from the spacecraft to the observer, units are arbitrary,
must be 1 dimensional.
pointing :
The vector along which the telescope is pointing, the spacecraft's
Z-axis.
Returns
-------
float
Angle in degrees around the pointing vector the spacecraft must be
rotated to place the sun shield between the telescope and the sun.
"""
obs2sun = -np.array(sun2obs)

# normalize for safety
pointing = np.array(pointing) / np.linalg.norm(pointing)

# The normal vector for the plane defined by the sun and pointing vectors.
sun_plane_normal = np.cross(obs2sun, pointing)
sun_plane_normal /= np.linalg.norm(sun_plane_normal)

# Assuming that the spacecraft body z is along the pointing vector and
# body y-axis (sun shield) is facing directly up in the current frame.
# This means the body x-axis is defined by:
# sc_x = cross((0, 0, 1), pointing) = (-pointing.y, pointing.x, 0)
# This vector is the normal through the plane defined by the pointing and
# the Z-axis of the plane.
obs_body_x = np.array([-pointing[1], pointing[0], 0])

r = np.linalg.norm(obs_body_x)
if r < 1e-6:
# Safety check, this definition is bad near poles.
raise ValueError(
(
"Nearly pointing at the pole, cannot compute within about half "
"an arcsecond of the pole. It is strongly recommended to not "
"use this angular definition so close to poles, quaternions are "
"the better choice."
)
)
obs_body_x /= r

# The great circle distance from the body_x to the sun_plane_normal is
# an absolute rotation, so if the sun is on the "left" vs "right"
# is not captured, and an additional calculation is needed to find
# the sign of the rotation.
sign = np.sign(np.dot(obs_body_x, obs2sun))
return sign * np.degrees(np.arccos(np.dot(sun_plane_normal, obs_body_x)))

0 comments on commit 69eac7e

Please sign in to comment.