Commit 61ad69e3 authored by Tammo Jan Dijkema's avatar Tammo Jan Dijkema
Browse files

Merge branch refactor

parents 75826d0f 336a023b
......@@ -106,30 +106,12 @@ venv.bak/
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff:
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/dictionaries
# Sensitive or high-churn files:
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
# Gradle:
.idea/**/gradle.xml
.idea/**/libraries
.idea
# CMake
cmake-build-debug/
cmake-build-release/
# Mongo Explorer plugin:
.idea/**/mongoSettings.xml
## File-based project format:
*.iws
......@@ -144,13 +126,9 @@ out/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
#!/usr/bin/env python
from setuptools import setup, find_packages
from setuptools import setup
meta = dict(name='telescope',
version='1.1.1',
author='Tammo Jan Dijkema',
author_email='T.J.Dijkema@camras.nl',
url='https://gitlab.camras.nl/dijkema/telescope',
description='Software for the CAMRAS Dwingeloo Radio Telescope',
platforms='Linux, Mac OSX',
py_modules=['telescope'],
include_package_data=True,
data_files=[('', ['telescope.ini',]),],
install_requires=['astropy','configparser','numpy']
meta = dict(name = 'telescope',
version = '1.1.1',
author = 'Tammo Jan Dijkema',
author_email = 'T.J.Dijkema@camras.nl',
url = 'https://gitlab.camras.nl/dijkema/telescope',
description = 'Software for the CAMRAS Dwingeloo Radio Telescope',
platforms = 'Linux, Mac OSX',
py_modules = ['telescope'],
include_package_data = True,
data_files=[('', ['telescope.ini',]), ],
install_requires=['astropy', 'configparser', 'numpy']
)
setup(**meta)
......@@ -2,17 +2,16 @@ from __future__ import print_function
import socket
import logging
from astropy.coordinates import SkyCoord, AltAz, RangeError
from astropy import units as u
from astropy.coordinates import SkyCoord, RangeError
from configparser import ConfigParser
import astropy.units as u
import os.path
import numpy as np
import threading
import select
import time
config = ConfigParser()
config.readfp(open(os.path.join(os.path.dirname(__file__), 'telescope.ini')))
config.read_file(open(os.path.join(os.path.dirname(__file__), 'telescope.ini')))
logging.basicConfig(level=logging.DEBUG)
......@@ -20,22 +19,25 @@ _telescope__num_instances = 0
__version__ = "1.1.1"
class telescope():
def __init__(self, setmode=None, consoleHost=None):
'''
Initializes a telescope instance. The mode for writing can be
'J2000' or 'AZEL'.
'''
global __num_instances
if setmode not in ('J2000', 'AZEL', None):
raise ValueError("Mode must be None, 'J2000' or 'AZEL', not " + setmode)
self.setmode = setmode
class Telescope:
def __init__(self, setMode=None, consoleHost=None):
"""
Initializes a telescope instance
:param setMode: The mode for writing. Can be 'J2000' or 'AZEL'
:param consoleHost: Address of the console. E.g. 'console' or 'consoledemo.dmz.camras.nl'
"""
global _telescope__num_instances
if setMode not in ('J2000', 'AZEL', None):
raise ValueError("Mode must be None, 'J2000' or 'AZEL', not " + setMode)
self.setmode = setMode
if consoleHost is None:
consoleHost = config.get('Console','HostName')
consoleHost = config.get('Console', 'HostName')
if consoleHost == 'console':
if socket.gethostname()=="mercurius":
if setMode is not None and socket.gethostname() == "mercurius":
logging.warning("You are using the actual console, not a demo!")
else:
raise ValueError("Talking to the actual console can only be done from mercurius")
......@@ -52,22 +54,22 @@ class telescope():
self.refraction_enabled = None
self.model_enabled = None
__num_instances += 1
_telescope__num_instances += 1
if __num_instances != 1:
if _telescope__num_instances != 1:
raise RuntimeError("Do not make more than one telescope instance.")
self._outsocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
if self.setmode == 'J2000':
try:
self._outsocket.connect((consoleHost,
config.getint('Console','Port_Write_J2000')))
config.getint('Console', 'Port_Write_J2000')))
except socket.gaierror as e:
raise IOError("Could not connect to DT J2000 port: " + str(e))
elif self.setmode == 'AZEL':
try:
self._outsocket.connect((consoleHost,
config.getint('Console','Port_Write_AzEl')))
config.getint('Console', 'Port_Write_AzEl')))
except socket.gaierror as e:
raise IOError("Could not connect to DT AZEL port: " + str(e))
......@@ -76,14 +78,14 @@ class telescope():
self._offsetsocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
self._offsetsocket.connect((consoleHost,
config.getint('Console','Port_Write_Offset')))
config.getint('Console', 'Port_Write_Offset')))
except socket.gaierror as e:
raise IOError("Could not connect to DT Offset port: " + str(e))
self._event_j2000 = threading.Event()
thread_read_j2000 = threading.Thread(target=self._readj2000, args=(
consoleHost,
config.getint('Console','Port_Read_J2000')))
config.getint('Console', 'Port_Read_J2000')))
thread_read_j2000.daemon = True
thread_read_j2000.start()
......@@ -94,20 +96,23 @@ class telescope():
thread_read_traces.daemon = True
thread_read_traces.start()
def _readj2000(self, consolehost, j2000_read_port):
'''
Poll the socket with the j2000 info, store its values in class members.
'''
def _readj2000(self, consoleHost, j2000_read_port):
"""
Poll the socket with the J2000 info, store its values in class members
:param consoleHost: Hostname
:param j2000_read_port: Port with J200 info
:return: None
"""
try:
self._j2000socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self._j2000socket.connect((consolehost, j2000_read_port))
self._j2000socket.connect((consoleHost, j2000_read_port))
except socket.error:
raise IOError("Cannot connect to j2000 status server")
while True:
readable, writable, exceptional = select.select(
[self._j2000socket], [], [])
if len(exceptional)>0:
if len(exceptional) > 0:
raise IOError("Error with j2000 read socket")
msg = readable[0].recv(4096).decode("UTF-8")
vals = msg.strip().split()
......@@ -131,6 +136,13 @@ class telescope():
self._event_j2000.set()
def _readtraces(self, tracehost, traceport):
"""
Poll the socket with the traces (a running 'trace2port' instance), store the trace values
in class members
:param tracehost: Hostname
:param traceport: Port at which trace2port is running
:return: None
"""
'''
Poll the socket with the traces, store their values in class members
'''
......@@ -143,20 +155,26 @@ class telescope():
while True:
readable, writable, exceptional = select.select(
[self._tracesocket], [], [])
if len(exceptional)>0:
if len(exceptional) > 0:
raise IOError("Error with trace read socket")
msg = readable[0].recv(4096).decode("UTF-8")
vals = msg.strip().split()
self.az = (float(vals[0])*u.rad).to(u.deg)
self.el = (float(vals[1])*u.rad).to(u.deg)
self.dist_az = (float(vals[2])*u.rad).to(u.deg)
self.dist_el = (float(vals[3])*u.rad).to(u.deg)
self.az = (float(vals[0]) * u.rad).to(u.deg)
self.el = (float(vals[1]) * u.rad).to(u.deg)
self.dist_az = (float(vals[2]) * u.rad).to(u.deg)
self.dist_el = (float(vals[3]) * u.rad).to(u.deg)
self.speed_az = float(vals[4])
self.speed_el = float(vals[5])
self.focusbox_pos = float(vals[6])
self._event_traces.set()
def setRaDec(self, setpoint):
"""
Set the J2000 setpoint of the telescope.
Only works if the telescope is in J2000 mode.
:param setpoint: New setpoint. An astropy SkyCoord or a tuple (ra, dec) in radians
:return: None
"""
'''
Set the J2000 setpoint of the telescope.
Only works if the setmode is 'J2000'.
......@@ -167,7 +185,7 @@ class telescope():
raise ValueError("Cannot set Ra/Dec if mode is not J2000")
if isinstance(setpoint, tuple):
coord = SkyCoord(ra =setpoint[0] * u.radian,
setpoint = SkyCoord(ra=setpoint[0] * u.radian,
dec=setpoint[1] * u.radian)
(ra, dec) = setpoint.to_string('hmsdms').split()
......@@ -177,12 +195,13 @@ class telescope():
self._outsocket.send(cmd)
def setAzEl(self, setpoint):
'''
"""
Set the AzEl setpoint of the telescope.
Only works if the setmode is 'AZEL'
setpoint should be a tuple of degrees or of astropy Quantity
'''
:param setpoint: New setpoint. A tuple of floats (interpreted as degrees), or
a tuple of astropy Quantity
:return: None
"""
if self.setmode != 'AZEL':
raise ValueError("Cannot set Az/El if mode is not AZEL")
......@@ -197,11 +216,12 @@ class telescope():
self._outsocket.send(cmd)
def setOffset(self, offset):
'''
"""
Set the offset of the telescope in Az / El.
offset should be a tuple of degrees or of astropy Quantity
'''
:param offset: New setpoint. A tuple of floats (interpreted as radians), or
a tuple of astropy Quantity
:return: None
"""
if self.setmode is None:
raise ValueError("Cannot set offset if mode is None")
......@@ -220,103 +240,109 @@ class telescope():
self._offsetsocket.send(cmd)
def getFocusboxPosition(self, waitForUpdate=False):
'''
Get the focusbox position. If waitForUpdate=True, it waits for the
next signal from the socket.
Returns an astropy quantity
'''
"""
Get the focusbox position.
:param waitForUpdate: wait for the next signal from the socket
:return: Astropy quantity with the focusbox position
"""
if waitForUpdate or self.focusbox_pos is None:
self._event_traces.clear()
self._event_traces.wait()
return self.focusbox_pos * 0.1 * u.m
def getAzEl(self, waitForUpdate=False):
'''
"""
Get azimut and elevation. If waitForUpdate=True, it waits for the
next signal from the socket.
Returns a tuple (az, el) as astropy quantity
'''
"""
if waitForUpdate or self.az is None or self.radec is None:
self._event_traces.clear()
self._event_traces.wait()
return (self.az, self.el)
def getDistance(self, waitForUpdate=False):
'''
"""
Get distance in azimut and elevation. If waitForUpdate=True, it waits
for the next signal from the socket.
Returns a tuple (dist_az, dist_el) as astropy quantity
'''
"""
if waitForUpdate or self.dist_az is None or self.dist_el is None:
self._event_traces.clear()
self._event_traces.wait()
return (self.dist_az, self.dist_el)
def getRaDec(self, waitForUpdate=False):
'''
"""
Get current Ra/Dec. If waitForUpdate=True, it waits for the
next signal from the socket.
Returns an astropy SkyCoord
'''
"""
if waitForUpdate or self.radec is None:
self._event_traces.clear()
self._event_traces.wait()
return self.radec
def getSetpoint_RaDec(self, waitForUpdate=False):
'''
"""
Get current Ra/Dec setpoint. If waitForUpdate=True, it waits for the
next signal from the socket.
Returns an astropy SkyCoord
'''
"""
if waitForUpdate or self.radec is None:
self._event_traces.clear()
self._event_traces.wait()
return self.setpoint_radec
def waitUntilThere(self, tolerance=0.01*u.deg):
'''
def waitUntilThere(self, tolerance=0.01 * u.deg):
"""
Wait until distance to the setpoint gets within tolerance
'''
"""
logging.info("Waiting to reach setpoint")
distIsSmall = False
while not distIsSmall:
diff = self.getDistance(waitForUpdate=True)
distIsSmall = abs(self.dist_el)<tolerance and abs(self.dist_az)<tolerance
distIsSmall = abs(self.dist_el) < tolerance and abs(self.dist_az) < tolerance
def waitUntilMoving(self, tolerance=0.01*u.deg):
'''
def waitUntilMoving(self, tolerance=0.01 * u.deg):
"""
Wait until the telescope reckognizes that it is not at its setpoint
'''
"""
logging.info("Waiting to set setpoint")
distIsBig = False
while not distIsBig:
dist = self.getDistance(waitForUpdate=True)
distIsBig = dist[0]>tolerance or dist[1]>tolerance
distIsBig = dist[0] > tolerance or dist[1] > tolerance
def getJ2000(self):
'''
"""
Generates dicts with 'radec' and 'setpoint_radec',
containing radec and setpoint_radec, at whichever
speed the console is outputting them (probably once a second).
'''
"""
self._event_traces.clear()
while True:
self._event_j2000.wait()
self._event_j2000.clear()
yield({'radec': self.radec,
yield ({'radec': self.radec,
'setpoint_radec': self.setpoint_radec})
def getTraces(self):
'''
"""
Generates a dict of all traces from trace2port at whichever
rate trace2port generates them (probably once a second).
'''
"""
self._event_traces.clear()
while True:
self._event_traces.wait()
self._event_traces.clear()
yield({'position_azel': (self.az, self.el),
yield ({'position_azel': (self.az, self.el),
'distance': (self.dist_az, self.dist_el),
'speed': (self.speed_az, self.speed_el)})
class telescope(Telescope):
def __init__(self, *args, **kwargs):
super(Telescope, self).__init__(*args, **kwargs)
logging.warning("Please use the new class name Telescope (with capital T)")
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment