Skip to content

Commit

Permalink
Merge pull request IMRCLab#321 from IMRCLab/feature_crazyfliepy_flake8
Browse files Browse the repository at this point in the history
crazyflie_py: fix flake8 and pep256 issues
  • Loading branch information
whoenig committed Oct 24, 2023
2 parents 5024041 + 76462db commit 5b49969
Show file tree
Hide file tree
Showing 13 changed files with 399 additions and 316 deletions.
9 changes: 8 additions & 1 deletion .github/workflows/ci-ros2.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,21 @@ jobs:
sudo apt update
sudo apt install -y libusb-1.0-0-dev
- name: install pip dependencies
# TODO: would be better to follow https://answers.ros.org/question/370666/how-to-declare-an-external-python-dependency-in-ros2/
# but this requires some upstream changes
run: |
pip install rowan
- uses: actions/checkout@v2
- name: build and test ROS 2
uses: ros-tooling/action-ros-ci@v0.3
with:
# TODO: removed crazyflie_interfaces since it causes some test failures
package-name: |
crazyflie
crazyflie_examples
crazyflie_interfaces
crazyflie_py
crazyflie_sim
target-ros2-distro: ${{ matrix.ros_distribution }}
vcs-repo-file-url: rosinstall
2 changes: 1 addition & 1 deletion crazyflie_py/crazyflie_py/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
from .crazyswarm_py import Crazyswarm

__all__ = ["Crazyswarm"]
__all__ = ['Crazyswarm']
344 changes: 207 additions & 137 deletions crazyflie_py/crazyflie_py/crazyflie.py

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions crazyflie_py/crazyflie_py/crazyswarm_py.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import rclpy

from . import genericJoystick
from .crazyflie import TimeHelper, CrazyflieServer
from .crazyflie import CrazyflieServer, TimeHelper


class Crazyswarm:

def __init__(self):
rclpy.init()

self.allcfs = CrazyflieServer()
self.timeHelper = TimeHelper(self.allcfs)

Expand Down
13 changes: 7 additions & 6 deletions crazyflie_py/crazyflie_py/genericJoystick.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import time
import copy
# import pyglet

from . import keyboard

# class JoyStickHandler:
Expand All @@ -20,7 +20,9 @@
# def on_joyhat_motion(joystick, hat_x, hat_y):
# pass


class Joystick:

def __init__(self, timeHelper):
# joysticks = pyglet.input.get_joysticks()
# joystick = joysticks[0]
Expand All @@ -35,14 +37,14 @@ def __init__(self, timeHelper):
self.js = linuxjsdev.Joystick()
devices = self.js.devices()
if len(devices) == 0:
print("Warning: No joystick found!")
print('Warning: No joystick found!')
else:
ids = [dev["id"] for dev in devices]
ids = [dev['id'] for dev in devices]
# For backwards compatibility, always choose device 0 if available.
self.joyID = 0 if 0 in ids else devices[0]["id"]
self.joyID = 0 if 0 in ids else devices[0]['id']
self.js.open(self.joyID)
except ImportError:
print("Warning: Joystick only supported on Linux.")
print('Warning: Joystick only supported on Linux.')

# def on_joybutton_press(joystick, button):
# print(button)
Expand Down Expand Up @@ -77,7 +79,6 @@ def waitUntilButtonPressed(self):
while keyPoller.poll() is not None:
self.timeHelper.sleep(0.01)


def checkIfAnyButtonIsPressed(self):
if self.joyID is not None:
state = self.js.read(self.joyID)
Expand Down
9 changes: 6 additions & 3 deletions crazyflie_py/crazyflie_py/joystick.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
import time

import rospy
from sensor_msgs.msg import Joy


class Joystick:

def __init__(self):
self.lastButtonState = 0
self.buttonWasPressed = False
rospy.Subscriber("/joy", Joy, self.joyChanged)
rospy.Subscriber('/joy', Joy, self.joyChanged)

def joyChanged(self, data):
if (not self.buttonWasPressed and
data.buttons[5] == 1 and
self.lastButtonState == 0):
data.buttons[5] == 1 and
self.lastButtonState == 0):
self.buttonWasPressed = True
self.lastButtonState = data.buttons[5]

Expand Down
7 changes: 4 additions & 3 deletions crazyflie_py/crazyflie_py/keyboard.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import sys
import select
import sys
import termios


class KeyPoller():

def __enter__(self):
# Save the terminal settings
self.fd = sys.stdin.fileno()
Expand All @@ -16,11 +17,11 @@ def __enter__(self):

return self

def __exit__(self, type, value, traceback):
def __exit__(self, type, value, traceback): # noqa A002
termios.tcsetattr(self.fd, termios.TCSAFLUSH, self.old_term)

def poll(self):
dr,dw,de = select.select([sys.stdin], [], [], 0)
dr, dw, de = select.select([sys.stdin], [], [], 0)
if not dr == []:
return sys.stdin.read(1)
return None
83 changes: 40 additions & 43 deletions crazyflie_py/crazyflie_py/linuxjsdev.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
"""
Linux joystick driver using the Linux input_joystick subsystem. Requires sysfs
to be mounted on /sys and /dev/input/js* to be readable.
Linux joystick driver using the Linux input_joystick subsystem.
Requires sysfs to be mounted on /sys and /dev/input/js* to be readable.
This module is very linux specific but should work on any CPU platform
"""
Expand All @@ -36,19 +37,19 @@
import sys

if not sys.platform.startswith('linux'):
raise ImportError("Only supported on Linux")
raise ImportError('Only supported on Linux')

try:
import fcntl
except ImportError as e:
raise Exception("fcntl library probably not installed ({})".format(e))
raise Exception('fcntl library probably not installed ({})'.format(e))

__author__ = 'Bitcraze AB'
__all__ = ['Joystick']

logger = logging.getLogger(__name__)

JS_EVENT_FMT = "@IhBB"
JS_EVENT_FMT = '@IhBB'
JE_TIME = 0
JE_VALUE = 1
JE_TYPE = 2
Expand All @@ -62,24 +63,23 @@
JSIOCGAXES = 0x80016a11
JSIOCGBUTTONS = 0x80016a12

MODULE_MAIN = "Joystick"
MODULE_NAME = "linuxjsdev"
MODULE_MAIN = 'Joystick'
MODULE_NAME = 'linuxjsdev'


class JEvent(object):
"""
Joystick event class. Encapsulate single joystick event.
"""
"""Joystick event class. Encapsulate single joystick event."""

def __init__(self, evt_type, number, value):
self.type = evt_type
self.number = number
self.value = value

def __repr__(self):
return "JEvent(type={}, number={}, value={})".format(
return 'JEvent(type={}, number={}, value={})'.format(
self.type, self.number, self.value)


# Constants
TYPE_BUTTON = 1
TYPE_AXIS = 2
Expand All @@ -90,64 +90,64 @@ class _JS():
def __init__(self, num, name):
self.num = num
self.name = name
self._f_name = "/dev/input/js{}".format(num)
self._f_name = '/dev/input/js{}'.format(num)
self._f = None

self.opened = False
self.buttons = []
self.axes = []
self._prev_pressed = {}

def open(self):
def open(self): # noqa: A003
if self._f:
raise Exception("{} at {} is already "
"opened".format(self.name, self._f_name))
raise Exception('{} at {} is already '
'opened'.format(self.name, self._f_name))

self._f = open("/dev/input/js{}".format(self.num), "rb")
self._f = open('/dev/input/js{}'.format(self.num), 'rb')
fcntl.fcntl(self._f.fileno(), fcntl.F_SETFL, os.O_NONBLOCK)

# Get number of axis and button
val = ctypes.c_int()
if fcntl.ioctl(self._f.fileno(), JSIOCGAXES, val) != 0:
self._f.close()
self._f = None
raise Exception("Failed to read number of axes")
raise Exception('Failed to read number of axes')

self.axes = list(0 for i in range(val.value))
self.axes = [0 for i in range(val.value)]
if fcntl.ioctl(self._f.fileno(), JSIOCGBUTTONS, val) != 0:
self._f.close()
self._f = None
raise Exception("Failed to read number of axes")
raise Exception('Failed to read number of axes')

self.buttons = list(0 for i in range(val.value))
self.buttons = [0 for i in range(val.value)]
self.__initvalues()

def close(self):
"""Open the joystick device"""
"""Open the joystick device."""
if not self._f:
return

logger.info("Closed {} ({})".format(self.name, self.num))
logger.info('Closed {} ({})'.format(self.name, self.num))

self._f.close()
self._f = None

def __initvalues(self):
"""Read the buttons and axes initial values from the js device"""
"""Read the buttons and axes initial values from the js device."""
for _ in range(len(self.axes) + len(self.buttons)):
data = self._f.read(struct.calcsize(JS_EVENT_FMT))
jsdata = struct.unpack(JS_EVENT_FMT, data)
self.__updatestate(jsdata)

def __updatestate(self, jsdata):
"""Update the internal absolute state of buttons and axes"""
"""Update the internal absolute state of buttons and axes."""
if jsdata[JE_TYPE] & JS_EVENT_AXIS != 0:
self.axes[jsdata[JE_NUMBER]] = jsdata[JE_VALUE] / 32768.0
elif jsdata[JE_TYPE] & JS_EVENT_BUTTON != 0:
self.buttons[jsdata[JE_NUMBER]] = jsdata[JE_VALUE]

def __decode_event(self, jsdata):
""" Decode a jsdev event into a dict """
"""Decode a jsdev event into a dict."""
# TODO: Add timestamp?
if jsdata[JE_TYPE] & JS_EVENT_AXIS != 0:
return JEvent(evt_type=TYPE_AXIS,
Expand All @@ -159,7 +159,7 @@ def __decode_event(self, jsdata):
value=jsdata[JE_VALUE] / 32768.0)

def _read_all_events(self):
"""Consume all the events queued up in the JS device"""
"""Consume all the events queued up in the JS device."""
try:
while True:
data = self._f.read(struct.calcsize(JS_EVENT_FMT))
Expand All @@ -170,7 +170,7 @@ def _read_all_events(self):
logger.info(str(e))
self._f.close()
self._f = None
raise IOError("Device has been disconnected")
raise IOError('Device has been disconnected')
except TypeError:
pass
except ValueError:
Expand All @@ -182,19 +182,17 @@ def _read_all_events(self):
pass

def read(self):
""" Returns a list of all joystick event since the last call """
"""Return a list of all joystick event since the last call."""
if not self._f:
raise Exception("Joystick device not opened")
raise Exception('Joystick device not opened')

self._read_all_events()

return [self.axes, self.buttons]


class Joystick():
"""
Linux jsdev implementation of the Joystick class
"""
"""Linux jsdev implementation of the Joystick class."""

def __init__(self):
self.name = MODULE_NAME
Expand All @@ -203,31 +201,30 @@ def __init__(self):

def devices(self):
"""
Returns a list containing an {"id": id, "name": name} dict for each
detected device. Result is cached once one or more devices are found.
Return a list containing an {'id': id, 'name': name} dict for each detected device.
Result is cached once one or more devices are found.
"""
if len(self._devices) == 0:
syspaths = glob.glob("/sys/class/input/js*")
syspaths = glob.glob('/sys/class/input/js*')

for path in syspaths:
device_id = int(os.path.basename(path)[2:])
with open(path + "/device/name") as namefile:
with open(path + '/device/name') as namefile:
name = namefile.read().strip()
self._js[device_id] = _JS(device_id, name)
self._devices.append({"id": device_id, "name": name})
self._devices.append({'id': device_id, 'name': name})

return self._devices

def open(self, device_id):
"""
Open the joystick device. The device_id is given by available_devices
"""
def open(self, device_id): # noqa: A003
"""Open the joystick device. The device_id is given by available_devices."""
self._js[device_id].open()

def close(self, device_id):
"""Open the joystick device"""
"""Open the joystick device."""
self._js[device_id].close()

def read(self, device_id):
""" Returns a list of all joystick event since the last call """
"""Return a list of all joystick event since the last call."""
return self._js[device_id].read()
Loading

0 comments on commit 5b49969

Please sign in to comment.