Skip to content

Commit

Permalink
Tracking error fixes (#549)
Browse files Browse the repository at this point in the history
* Fixing direction depending on where pier is pointed.

Closes #495
  • Loading branch information
wtgee authored Aug 19, 2018
1 parent 0848bed commit 709d7f7
Show file tree
Hide file tree
Showing 5 changed files with 201 additions and 74 deletions.
8 changes: 4 additions & 4 deletions pocs/images.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,10 +129,10 @@ def pointing_error(self):
d_ra = self.pointing.ra - self.header_pointing.ra

self._pointing_error = OffsetError(
d_ra.to(
u.arcsec), d_dec.to(
u.arcsec), mag.to(
u.arcsec))
d_ra.to(u.arcsec),
d_dec.to(u.arcsec),
mag.to(u.arcsec)
)

return self._pointing_error

Expand Down
119 changes: 117 additions & 2 deletions pocs/mount/mount.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ def __init__(self, location, commands=None, *args, **kwargs
self._state = 'Parked'

self.sidereal_rate = ((360 * u.degree).to(u.arcsec) / (86164 * u.second))
self.ra_guide_rate = 0.5 # Sidereal
self.dec_guide_rate = 0.5 # Sidereal
self.ra_guide_rate = 0.9 # Sidereal
self.dec_guide_rate = 0.9 # Sidereal
self._tracking_rate = 1.0 # Sidereal
self._tracking = 'Sidereal'
self._movement_speed = ''
Expand Down Expand Up @@ -311,6 +311,121 @@ def distance_from_target(self):

return separation

def get_tracking_correction(self, offset_info, pointing_ha):
"""Determine the needed tracking corrections from current position.
This method will determine the direction and number of milliseconds to
correct the mount for each axis in order to correct for any tracking
drift. The Declination axis correction ('north' or 'south') depends on
the movement of the camera box with respect to the pier, which can be
determined from the Hour Angle (HA) of the pointing image in the sequence.
Note:
Correction values below 50ms will be skipped and values above 99999ms
will be clipped.
Args:
offset_info (`OffsetError`): A named tuple describing the offset
error. See `pocs.images.OffsetError`.
pointing_ha (float): The Hour Angle (HA) of the mount at the
beginning of the observation sequence in degrees. This affects
the direction of the Dec adjustment.
Returns:
dict: Offset corrections for each axis as needed ::
dict: {
# axis: (arcsec, millisecond, direction)
'ra': (float, float, str),
'dec': (float, float, str),
}
"""
pier_side = 'east'
if pointing_ha <= 12:
pier_side = 'west'

self.logger.debug("Mount pier side: {}".format(pier_side))

axis_corrections = {
'dec': None,
'ra': None,
}

for axis in axis_corrections.keys():
# find the number of ms and direction for Dec axis
offset = getattr(offset_info, 'delta_{}'.format(axis))
offset_ms = self.get_ms_offset(offset, axis=axis)

if axis == 'dec':
# Determine which direction to move based on direction mount
# is moving (i.e. what side it started on).
if pier_side == 'east':
if offset_ms >= 0:
delta_direction = 'north'
else:
delta_direction = 'south'
else:
if offset_ms >= 0:
delta_direction = 'south'
else:
delta_direction = 'north'
else:
if offset_ms >= 0:
delta_direction = 'west'
else:
delta_direction = 'east'

offset_ms = abs(offset_ms.value)

# Skip short corrections
if offset_ms <= 50:
continue

# Ensure we don't try to move for too long
max_time = 99999

# Correct long offset
if offset_ms > max_time:
offset_ms = max_time

axis_corrections[axis] = (offset, offset_ms, delta_direction)

return axis_corrections

def correct_tracking(self, correction_info, axis_timeout=30.):
""" Make tracking adjustment corrections.
Args:
correction_info (dict[tuple]): Correction info to be applied, see
`get_tracking_correction`.
axis_timeout (float, optional): Timeout for adjustment in each axis,
default 30 seconds.
Raises:
`error.Timeout`: Timeout error.
"""
for axis, corrections in correction_info.items():
offset = corrections[0]
offset_ms = corrections[1]
delta_direction = corrections[2]

self.logger.info("Adjusting {}: {} {:0.2f} ms {:0.2f}".format(
axis, delta_direction, offset_ms, offset))

self.mount.query(
'move_ms_{}'.format(delta_direction),
'{:05.0f}'.format(offset_ms)
)

# Adjust tracking for `axis_timeout` seconds then fail if not done.
start_tracking_time = current_time()
while self.mount.is_tracking is False:
if (current_time() - start_tracking_time).sec > axis_timeout:
raise error.Timeout("Tracking adjustment timeout: {}".format(axis))

self.logger.debug("Waiting for {} tracking adjustment".format(axis))
time.sleep(0.5)


##################################################################################################
# Movement methods
Expand Down
78 changes: 17 additions & 61 deletions pocs/observatory.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import os
import time

from collections import OrderedDict
from datetime import datetime
Expand Down Expand Up @@ -342,67 +341,24 @@ def update_tracking(self):
if self.current_offset_info is not None:
self.logger.debug("Updating the tracking")

# find the number of ms and direction for Dec axis
dec_offset = self.current_offset_info.delta_dec
dec_ms = self.mount.get_ms_offset(dec_offset, axis='dec')
if dec_offset >= 0:
dec_direction = 'north'
else:
dec_direction = 'south'
# Get the pier side of pointing image
pointing_ha = self.current_observation.pointing_image.header_ha

# find the number of ms and direction for RA axis
ra_offset = self.current_offset_info.delta_ra
ra_ms = self.mount.get_ms_offset(ra_offset, axis='ra')
if ra_offset >= 0:
ra_direction = 'west'
else:
ra_direction = 'east'

dec_ms = abs(dec_ms.value) * 1.5 # TODO(wtgee): Figure out why 1.5
ra_ms = abs(ra_ms.value) * 1.

# Ensure we don't try to move for too long
max_time = 99999

# Correct the Dec axis (if offset is large enough)
if dec_ms > max_time:
dec_ms = max_time

if dec_ms >= 50:
self.logger.info("Adjusting Dec: {} {:0.2f} ms {:0.2f}".format(
dec_direction, dec_ms, dec_offset))
if dec_ms >= 1. and dec_ms <= max_time:
self.mount.query('move_ms_{}'.format(
dec_direction), '{:05.0f}'.format(dec_ms))

# Adjust tracking for up to 30 seconds then fail if not done.
start_tracking_time = current_time()
while self.mount.is_tracking is False:
if (current_time() - start_tracking_time).sec > 30:
raise Exception("Trying to adjust Dec tracking for more than 30 seconds")

self.logger.debug("Waiting for Dec tracking adjustment")
time.sleep(0.1)

# Correct the RA axis (if offset is large enough)
if ra_ms > max_time:
ra_ms = max_time

if ra_ms >= 50:
self.logger.info("Adjusting RA: {} {:0.2f} ms {:0.2f}".format(
ra_direction, ra_ms, ra_offset))
if ra_ms >= 1. and ra_ms <= max_time:
self.mount.query('move_ms_{}'.format(
ra_direction), '{:05.0f}'.format(ra_ms))

# Adjust tracking for up to 30 seconds then fail if not done.
start_tracking_time = current_time()
while self.mount.is_tracking is False:
if (current_time() - start_tracking_time).sec > 30:
raise Exception("Trying to adjust RA tracking for more than 30 seconds")

self.logger.debug("Waiting for RA tracking adjustment")
time.sleep(0.1)
try:
pointing_ha = pointing_ha.value
except AttributeError:
pass

self.logger.debug("Pointing HA: {}".format(pointing_ha))
correction_info = self.mount.get_tracking_correction(
self.current_offset_info,
pointing_ha
)

try:
self.mount.correct_tracking(correction_info)
except error.Timeout:
self.logger.warning("Timeout while correcting tracking")

def get_standard_headers(self, observation=None):
"""Get a set of standard headers
Expand Down
7 changes: 0 additions & 7 deletions pocs/tests/bisque/test_mount.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,13 +115,6 @@ def test_update_location(mount, config):
assert mount.location == location2


# def test_target_coords_below_horizon(mount, target_down):
# mount.initialize()

# assert mount.set_target_coordinates(target_down) is False
# assert mount.get_target_coordinates() is None


def test_target_coords(mount, target):
mount.initialize(unpark=True)

Expand Down
63 changes: 63 additions & 0 deletions pocs/tests/test_ioptron.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,33 @@
import os
import pytest

from astropy.coordinates import EarthLocation
from astropy import units as u

from pocs.images import OffsetError
from pocs.mount.ioptron import Mount
from pocs.utils.config import load_config


@pytest.fixture
def location():
config = load_config(ignore_local=True)
loc = config['location']
return EarthLocation(lon=loc['longitude'], lat=loc['latitude'], height=loc['elevation'])


@pytest.fixture(scope="function")
def mount(config, location):
try:
del os.environ['POCSTIME']
except KeyError:
pass

config['mount'] = {
'brand': 'bisque',
'template_dir': 'resources/bisque',
}
return Mount(location=location, config=config)


@pytest.mark.with_mount
Expand Down Expand Up @@ -64,3 +89,41 @@ def test_unpark_park(self):
assert self.mount.is_parked is False
self.mount.home_and_park()
assert self.mount.is_parked is True


def test_get_tracking_correction(mount):

offsets = [
# HA, ΔRA, ΔDec, Magnitude
(2, -13.0881456, 1.4009, 12.154),
(2, -13.0881456, -1.4009, 12.154),
(2, 13.0881456, 1.4009, 12.154),
(14, -13.0881456, 1.4009, 12.154),
(14, 13.0881456, 1.4009, 12.154),
]

corrections = [
(103.49, 'south', 966.84, 'east'),
(103.49, 'north', 966.84, 'east'),
(103.49, 'south', 966.84, 'west'),
(103.49, 'north', 966.84, 'east'),
(103.49, 'north', 966.84, 'west'),
]

for offset, correction in zip(offsets, corrections):
pointing_ha = offset[0]
offset_info = OffsetError(
offset[1] * u.arcsec,
offset[2] * u.arcsec,
offset[3] * u.arcsec
)
correction_info = mount.get_tracking_correction(offset_info, pointing_ha)

dec_info = correction_info['dec']
ra_info = correction_info['ra']

assert dec_info[1] == pytest.approx(correction[0], rel=1e-2)
assert dec_info[2] == correction[1]

assert ra_info[1] == pytest.approx(correction[2], rel=1e-2)
assert ra_info[2] == correction[3]

0 comments on commit 709d7f7

Please sign in to comment.