PYTHON (Robotics Project)
Robotics/.DS_Store
__MACOSX/Robotics/._.DS_Store
Robotics/__pycache__/finch.cpython-34.pyc
__MACOSX/Robotics/__pycache__/._finch.cpython-34.pyc
Robotics/__pycache__/finch.cpython-35.pyc
__MACOSX/Robotics/__pycache__/._finch.cpython-35.pyc
Robotics/__pycache__/finchconnection.cpython-34.pyc
__MACOSX/Robotics/__pycache__/._finchconnection.cpython-34.pyc
Robotics/__pycache__/finchconnection.cpython-35.pyc
__MACOSX/Robotics/__pycache__/._finchconnection.cpython-35.pyc
__MACOSX/Robotics/.___pycache__
Robotics/Finch Python API Description.pdf
Finch Python Package Description
Description of Files finch.py – Contains the Finch API functions for controlling Finch
finchconnection.py – Contains low level functions for sending and receiving data over USB, used by
finch.py
hidapi32/64.dll, libhidapi.dylib, libhidapi32/64.so, libhidapipi.so – compiled C libraries used by
finchconnection.py to scan for USB devices (specifically, the Finch) and open a connection. dll files are
for Windows, dylib is for OSX, and so is for Linux.
accelerationExampleOne.py, accelerationExampleTwo.py, dance.py, wanderer.py, alarm.py,
lapswimmer.py, musicexample.py, racedriver.py, tapExample.py, testfinchfunctions.py – Example
Python programs, open them for more information on what each one does.
notes.py – helper class used by musicexample.py to simplify playing lots of notes on the Finch buzzer.
Finch API
General close – closes the connection to the Finch
Usage: call this when your program is exiting to cleanly close the Finch connection. This will shut off the
motors and then send the Finch back to idle mode (color changing)
halt – convenience function to shut off the Finch LED and finch motors
Usage: call whenever you wish the Finch to stop moving and turn off its LED with one function call. Will
not shut off the buzzer.
Outputs led – controls the Finch beak color
Usage: hex triplet string: finch.led(‘#0000FF’) or 0-255 RGB values: finch.led(0, 0, 255). The first value indicates the red intensity, second is green, third is blue.
wheels – Controls the power sent to the left and right wheels
Usage: values must range from -1.0 to 1.0 for each wheel, use left=right=0.0 to stop. Examples:
finch.wheels(1.0, 1.0) # full forward
finch.wheels(-1.0, -1.0) # full reverse
finch.wheels(0.7, -0.3) # 70% forward on left wheel, 30% reverse on right wheel
buzzer – outputs sound over the Finch buzzer
Usage: pass two parameters, duration in seconds followed by frequency in Hertz. Frequencies between 20 and 20,000 are audible. Example (plays 440 Hz note for ½ second): finch.buzzer(0.5, 440).
Note that this function does not delay program execution; to delay, use buzzer_with_delay. If two buzzer functions are called one after the other, only the second will play. For example, the following will only play a single 880 Hz note:
finch.buzzer(0.5, 220)
finch.buzzer(0.5, 880)
buzzer_with_delay – outputs sound over the Finch buzzer, then blocks the program for delay equal to
the duration of the note. Same usage as buzzer.
Sensors temperature – returns temperature in degrees Celcius.
Usage: my_temperature = finch.temperature()
light – returns the left and right light sensor readings, values range from 0.0 (dark) to 1.0 (bright)
Usage: left_light_sensor, right_light_sensor = finch.light()
obstacle – returns obstacle sensor readings, values are False for no obstacle, True for obstacle detected
Usage: left_obstacle, right_obstacle = finch.obstacle()
acceleration – returns (x, y, z, tap, shake).
Usage: x, y, and z, are the acceleration readings in units of G's, and range from -1.5 to 1.5. When the
finch is horisontal, z is close to 1, x, y close to 0. When the finch stands on its tail, y, z are close to 0, x is
close to -1. When the finch is held with its left wing down, x, z are close to 0, y is close to 1.
tap, shake are boolean values -- true if the corresponding event has happened.
__MACOSX/Robotics/._Finch Python API Description.pdf
Robotics/finch.py
# Functions to control Finch robot. # The Finch is a robot for computer science education. Its design is the result # of a four year study at Carnegie Mellon's CREATE lab. # http://www.finchrobot.com # See included examples and documentation for how to use the API import time import finchconnection class Finch(): def __init__(self): self.connection = finchconnection.ThreadedFinchConnection() self.connection.open() def led(self, *args): """Control three LEDs (orbs). - hex triplet string: led('#00FF8B') or 0-255 RGB values: led(0, 255, 139) """ if len(args) == 3: r, g, b = [int(x) % 256 for x in args] elif (len(args) == 1 and isinstance(args[0], str)): color = args[0].strip() if len(color) == 7 and color.startswith('#'): r = int(color[1:3], 16) g = int(color[3:5], 16) b = int(color[5:7], 16) else: return self.connection.send(b'O', [r, g, b]) def buzzer(self, duration, frequency): """ Outputs sound. Does not wait until a note is done beeping. duration - duration to beep, in seconds (s). frequency - integer frequency, in hertz (HZ). """ millisec = int(duration * 1000) self.connection.send(b'B', [(millisec & 0xff00) >> 8, millisec & 0x00ff, (frequency & 0xff00) >> 8, frequency & 0x00ff]) def buzzer_with_delay(self, duration, frequency): """ Outputs sound. Waits until a note is done beeping. duration - duration to beep, in seconds (s). frequency - integer frequency, in hertz (HZ). """ millisec = int(duration * 1000) self.connection.send(b'B', [(millisec & 0xff00) >> 8, millisec & 0x00ff, (frequency & 0xff00) >> 8, frequency & 0x00ff]) time.sleep(duration*1.05) def light(self): """ Get light sensor readings. The values ranges from 0.0 to 1.0. returns - a tuple(left, right) of two real values """ self.connection.send(b'L') data = self.connection.receive() if data is not None: left = data[0] / 255.0 right = data[1] / 255.0 return left, right def obstacle(self): """Get obstacle sensor readings. returns - a tuple(left,right) of two boolean values """ self.connection.send(b'I') data = self.connection.receive() if data is not None: left = data[0] != 0 right = data[1] != 0 return left, right def temperature(self): """ Returns temperature in degrees Celcius. """ self.connection.send(b'T') data = self.connection.receive() if data is not None: return (data[0] - 127) / 2.4 + 25; def convert_raw_accel(self, a): """Converts the raw acceleration obtained from the hardware into G's""" if a > 31: a -= 64 return a * 1.6 / 32.0 def acceleration(self): """ Returns the (x, y, z, tap, shake). x, y, and z, are the acceleration readings in units of G's, and range from -1.5 to 1.5. When the finch is horisontal, z is close to 1, x, y close to 0. When the finch stands on its tail, y, z are close to 0, x is close to -1. When the finch is held with its left wing down, x, z are close to 0, y is close to 1. tap, shake are boolean values -- true if the correspondig event has happened. """ self.connection.send(b'A') data = self.connection.receive() if data is not None: x = self.convert_raw_accel(data[1]) y = self.convert_raw_accel(data[2]) z = self.convert_raw_accel(data[3]) tap = (data[4] & 0x20) != 0 shake = (data[4] & 0x80) != 0 return (x, y, z, tap, shake) def wheels(self, left, right): """ Controls the left and right wheels. Values must range from -1.0 (full throttle reverse) to 1.0 (full throttle forward). use left = right = 0.0 to stop. """ dir_left = int(left < 0) dir_right = int(right < 0) left = min(abs(int(left * 255)), 255) right = min(abs(int(right * 255)), 255) self.connection.send(b'M', [dir_left, left, dir_right, right]) def halt(self): """ Set all motors and LEDs to off. """ self.connection.send(b'X', [0]) def close(self): self.connection.close()
__MACOSX/Robotics/._finch.py
Robotics/finchconnection.py
# This module implements connection of a Finch robot via USB. It is used by # finch.py to send and receive commands from the Finch. # The Finch is a robot for computer science education. Its design is the result # of a four year study at Carnegie Mellon's CREATE lab. # http://www.finchrobot.com import atexit import os import ctypes import threading import time import platform import sys VENDOR_ID = 0x2354 DEVICE_ID = 0x1111 HIDAPI_LIBRARY_PATH = os.environ.get('HIDAPI_LIB_PATH', './') PING_FREQUENCY_SECONDS = 2.0 # seconds # Detect which operating system is present and load corresponding library system = platform.system() if system == 'Windows': if sys.maxsize > 2**32: hid_api = ctypes.CDLL(os.path.join(HIDAPI_LIBRARY_PATH, "hidapi64.dll")) else: hid_api = ctypes.CDLL(os.path.join(HIDAPI_LIBRARY_PATH, "hidapi32.dll")) elif system == 'Linux': if sys.maxsize > 2**32: hid_api = ctypes.CDLL(os.path.join(HIDAPI_LIBRARY_PATH, "libhidapi64.so")) else: hid_api = ctypes.CDLL(os.path.join(HIDAPI_LIBRARY_PATH, "libhidapi32.so" )) elif system == 'Darwin': hid_api = ctypes.CDLL(os.path.join(HIDAPI_LIBRARY_PATH, "libhidapi.dylib")) else: hid_api = ctypes.CDLL(os.path.join(HIDAPI_LIBRARY_PATH, "libhidapipi.so")) def _inherit_docstring(cls): def doc_setter(method): parent = getattr(cls, method.__name__) method.__doc__ = parent.__doc__ return method return doc_setter class FinchConnection: """ USB connection to the Finch robot. Uses the HID API to read and write from the robot. """ c_finch_handle = ctypes.c_void_p(None) c_io_buffer = ctypes.c_char_p(None) cmd_id = 0 def is_open(self): """Returns True if connected to the robot.""" return bool(self.c_finch_handle) def open(self): """ Connect to the robot. This method looks for a USB port the Finch is connceted to. """ _before_new_finch_connection(self) if self.is_open(): self.close() try: hid_api.hid_open.restype = ctypes.c_void_p self.c_finch_handle = hid_api.hid_open( ctypes.c_ushort(VENDOR_ID), ctypes.c_ushort(DEVICE_ID), ctypes.c_void_p(None)) self.c_io_buffer = ctypes.create_string_buffer(9) _new_finch_connected(self) self.cmd_id = self.read_cmd_id() except: raise Exception("Failed to connect to the Finch robot.") def close(self): """ Disconnect the robot. """ if self.c_finch_handle: self.send(b'R', [0]) # exit to idle (rest) mode hid_api.hid_close.argtypes = [ctypes.c_void_p] hid_api.hid_close(self.c_finch_handle) self.c_finch_handle = ctypes.c_void_p(None) self.c_io_buffer = ctypes.c_char_p(None) global _open_finches if self in _open_finches: _open_finches.remove(self) def read_cmd_id(self): """ Read the robot's internal command counter. """ #self.send('z', receive = True) self.send(b'z') data = self.receive() return data[0] def send(self, command, payload=()): """Send a command to the robot (internal). command: The command ASCII character payload: a list of up to 6 bytes of additional command info """ if not self.is_open(): raise Exception("Connection to Finch was closed.") # Format the buffer to contain the contents of the payload. for i in range(7): self.c_io_buffer[i] = b'\x00' self.c_io_buffer[1] = command[0] python_version = sys.version_info[0] if payload: for i in range(len(payload)): if python_version >= 3: self.c_io_buffer[i+2] = payload[i] else: self.c_io_buffer[i+2] = bytes(chr(payload[i])) # Make sure command id is incremented if this is a receive case else: self.cmd_id = (self.cmd_id + 1) % 256 # Make sure the command id is incremented so that two calls to obstacle() don't cause the system to hang #self.cmd_id = (self.cmd_id + 1) % 256 #if self.cmd_id == 0: # self.cmd_id = 1 if python_version >= 3: self.c_io_buffer[8] = self.cmd_id else: self.c_io_buffer[8] = bytes(chr(self.cmd_id)) # Write to the Finch bufffer res = 0 while not res: hid_api.hid_write.argtypes = [ctypes.c_void_p, ctypes.c_char_p, ctypes.c_size_t] res = hid_api.hid_write(self.c_finch_handle, self.c_io_buffer, ctypes.c_size_t(9)) def receive(self): """ Read the data from the Finch buffer. """ res = 9 while res > 0: hid_api.hid_read.argtypes = [ctypes.c_void_p, ctypes.c_char_p, ctypes.c_size_t] if system == 'Darwin': res = hid_api.hid_read(self.c_finch_handle, self.c_io_buffer, ctypes.c_size_t(9)) else: res = hid_api.hid_read_timeout(self.c_finch_handle, self.c_io_buffer, ctypes.c_size_t(9), 50) if self.cmd_id == ord(self.c_io_buffer[8]): break return [ord(self.c_io_buffer[i]) for i in range(9)] class ThreadedFinchConnection(FinchConnection): """Threaded implementation of Finch Connection""" lock = None thread = None main_thread = None last_cmd_sent = time.time() @_inherit_docstring(FinchConnection) def open(self): FinchConnection.open(self) if not self.is_open(): return self.lock = threading.Lock() self.thread = threading.Thread(target=self.__class__._pinger, args=(self, )) self.main_thread = threading.current_thread() self.thread.start() @_inherit_docstring(FinchConnection) def send(self, command, payload=(), receive=False): try: if self.lock is not None: self.lock.acquire() #FinchConnection.send(self, command, payload=payload, receive=receive) FinchConnection.send(self, command, payload=payload) self.last_cmd_sent = time.time() finally: if self.lock is not None: self.lock.release() @_inherit_docstring(FinchConnection) def receive(self): try: if self.lock is not None: self.lock.acquire() data = FinchConnection.receive(self) finally: if self.lock is not None: self.lock.release() return data def _pinger(self): """ Sends keep-alive commands every few secconds of inactivity. """ while True: if not self.lock: break if not self.c_finch_handle: break if not self.main_thread.isAlive(): break try: self.lock.acquire() now = time.time() if self.last_cmd_sent: delta = now - self.last_cmd_sent else: delta = PING_FREQUENCY_SECONDS if delta >= PING_FREQUENCY_SECONDS: FinchConnection.send(self, b'z') FinchConnection.receive(self) self.last_cmd_sent = now finally: self.lock.release() time.sleep(0.1) @_inherit_docstring(FinchConnection) def close(self): FinchConnection.close(self) self.thread.join() self.lock = None self.thread = None # Functions that handle the list of open finches _open_finches = [] def _before_new_finch_connection(finch): global _open_finches # close other connections for robot in _open_finches: if robot.is_open(): robot.close() def _new_finch_connected(finch): global _open_finches if finch not in _open_finches: _open_finches.append(finch) def _close_all_finches(): global _open_finches if not _open_finches: return for finch in _open_finches: if finch.is_open(): finch.close() atexit.register(_close_all_finches)
__MACOSX/Robotics/._finchconnection.py
Robotics/hidapi32.dll
__MACOSX/Robotics/._hidapi32.dll
Robotics/hidapi64.dll
__MACOSX/Robotics/._hidapi64.dll
Robotics/libhidapi.dylib
__MACOSX/Robotics/._libhidapi.dylib
Robotics/libhidapi32.so
__MACOSX/Robotics/._libhidapi32.so
Robotics/libhidapi64.so
__MACOSX/Robotics/._libhidapi64.so
Robotics/libhidapipi.so
__MACOSX/Robotics/._libhidapipi.so
Robotics/LICENSE.txt
The MIT License (MIT) Copyright (c) 2013 BirdBrain Technologies LLC Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
__MACOSX/Robotics/._LICENSE.txt
Robotics/test.py
from finch import Finch def main(): tweety = Finch() # print(tweety.temperature()) # left, right = tweety.light() # print("Light: ", left) # tweety.led(0, 0, 255) left, right = tweety.obstacle() while not left: left, right = tweety.obstacle() tweety.wheels(1.0, 1.0) for x in range(1000): tweety.wheels(-1.0, -1.0) for x in range(1000): tweety.wheels(-1.0, 1.0) for x in range(1000): tweety.wheels(1.0, 1.0) # for x in range(10000): # tweety.wheels(1.0, 1.0) # for x in range(10000): # # tweety.buzzer(1, 446) tweety.close() main()
__MACOSX/Robotics/._test.py
Robotics/test2.py
from finch import Finch def main(): tweety = Finch() print("temperature: " + str(tweety.temperature())) left, right = tweety.light() print("Light: ", left) tweety.led(255, 0, 0) left, right = tweety.obstacle() while not left: left, right = tweety.obstacle() tweety.wheels(1.0, 1.0) tweety.halt() for x in range(200): tweety.wheels(1.0, -1.0) tweety.halt() for x in range(100): tweety.wheels(-0.2, 0.3) tweety.halt() for x in range(100): tweety.wheels(-0.1, -1.0) tweety.halt() for x in range(100): tweety.wheels(1.0, 1.0) tweety.halt() for x in range(100): tweety.wheels(1.0, -1.0) tweety.halt() for x in range(100): tweety.wheels(1.0, 1.0) for x in range(100): tweety.buzzer(0.5, 880) tweety.buzzer(1, 446) tweety.close() main()
__MACOSX/Robotics/._test2.py
Robotics/testfinchfunctions.py
# testfinchfunctions, an example program for the Finch # Tests all parts of the Finch: prints all sensor values, changes the led # moves the wheels and beeps the buzzer. from time import sleep from finch import Finch finch = Finch() print('Temperature %5.2f' % finch.temperature()) print() finch.wheels(1.0, -1.0) sleep(0.5) finch.wheels(0.0, 0.0) for count in range(5): finch.led(0, 50*count, 0) x, y, z, tap, shake = finch.acceleration() print ('Acceleration %5.3f, %5.3f %5.3f %s %s' % (x, y, z, tap, shake)) left_light, right_light = finch.light() print ('Lights %5.3f, %5.3f' % (left_light, right_light)) left_obstacle, right_obstacle = finch.obstacle() print('Obstacles %s, %s' % (left_obstacle, right_obstacle)) print() finch.buzzer(0.8, 100*count) sleep(1) finch.led('#FF0000') finch.buzzer(5, 440) sleep(5) finch.halt() finch.close()