Skip to content

Instantly share code, notes, and snippets.

@godber
Last active January 14, 2016 13:11
Show Gist options
  • Save godber/b21fd797182d1937c331 to your computer and use it in GitHub Desktop.
Save godber/b21fd797182d1937c331 to your computer and use it in GitHub Desktop.
Simple FLIR Pan Tilt Head Python Module
#!/usr/bin/env python
# notional mosaic activity, without image acquisition
# sleeps removed since pan/tilt are now blocking
import time
from ptu import PanTiltUnit
def main():
ptu = PanTiltUnit('hostname', '4000')
# (p1,t1)
positions = (
(0, 0),
(500, 0),
(1000, 0),
(1500, 0),
(1500, 500),
(1000, 500),
(500, 500),
(0, 500),
)
for pos in positions:
pan, tilt = pos
ptu.pan = pan
ptu.tilt = tilt
ptu.close()
if __name__ == '__main__':
main()
import sys
import telnetlib
import logging
import time
import re
class PanTiltUnit(object):
"""PanTiltUnit commands a FLIR PTU
Example:
>>> from ptu import PanTiltUnit
>>> ptu = PanTiltUnit('hostname', '4000')
>>> ptu.pan
0
>>> ptu.pan = 1000
>>> ptu.pan
1000
>>> ptu.close()
"""
POS_REGEX = re.compile(
r"\* Current (?P<direction>(Pan|Tilt)) position is (?P<position>\d+)\r\n"
)
def __init__(self, host, port, no_connect=None):
super(PanTiltUnit, self).__init__()
self.host = host
self.port = port
self._connection = None
if not no_connect:
self._connect()
def _connect(self):
logging.info("Connecting to %s:%s" % (self.host, self.port))
self._connection = telnetlib.Telnet(self.host, self.port)
logging.debug(self._connection.read_until("*"))
def close(self):
self._connection.close()
def _set_position(self, direction, position):
if direction == 'pan':
message = 'pp' + str(position) + "\r\n"
elif direction == 'tilt':
message = 'tp' + str(position) + "\r\n"
else:
raise ValueError("direction must be 'pan' or 'tilt'")
logging.debug(message)
self._connection.write(message)
logging.debug(self._connection.read_until("*"))
# block while PTU still in motion
while self._get_position(direction) != position:
time.sleep(0.1)
def _get_position(self, direction):
"""Returns current position for direction ('pan' or 'tilt')
Keep in mind that pan position can be changing and this will return the
instantaneous position which may differ from the target position.
"""
if direction == 'pan':
self._connection.write("pp\r\n")
# read the pp\r\n line to junk variable, just to get rid of it
_ = self._connection.read_until("pp\r\n")
expected_direction = 'Pan'
elif direction == 'tilt':
self._connection.write("tp\r\n")
# read the tp\r\n line to junk variable, just to get rid of it
_ = self._connection.read_until("tp\r\n")
else:
raise ValueError("direction must be 'pan' or 'tilt'")
# read in line with position information
position_line = self._connection.read_until("\r\n")
logging.debug(position_line)
# extract out the postion information from the response received above
match = re.match(PanTiltUnit.POS_REGEX, position_line)
if match:
# we cast the pan/tilt position value to integer so it is easier
# do to math with the value
return int(match.group('position'))
else:
logging.error("WARNING: Position not found for: %s" % direction)
@property
def pan(self):
return self._get_position('pan')
@pan.setter
def pan(self, position):
self._set_position('pan', position)
@property
def tilt(self):
return self._get_position('tilt')
@tilt.setter
def tilt(self, position):
self._set_position('tilt', position)
def main():
pass
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment