Thursday, February 28, 2013

gamepad issues on OS X

The PC client currently supports the use of a 4-axis gamepad (e.g., PS3 controller) for flying.  I ordered a $10 USB controller from eBay, plugged it in, and tried some of the default settings.

The gamepad was recognized, and values showed up in the client for pitch/roll/yaw/thrust as the axis were moved; however, one of the axis always changed 2 of the controls, and the range wasn't correct for 1 of the axis.

I found a tool called HID_n_Seek to look at the output from all of the USB endpoints, and discovered that there are actually 5 endpoints that change value as the axis are moved.  4 of them behaved as expected, and 1 of them seemed to combine the output from a few different axis.

Likewise, a test using pygame (which is currently used by the Crazyflie PC client for the joystick input) showed the same thing.  I found this test script:

#!/usr/bin/env python

import pygame, time
#from pygame import joystick, event

j = pygame.joystick.Joystick(0)
print 'Initialized Joystick : %s' % j.get_name()
    while True:
        for i in range(0, j.get_numaxes()):
            if j.get_axis(i) != 0.00:
                print 'Axis %i reads %.2f' % (i, j.get_axis(i))
        for i in range(0, j.get_numbuttons()):
            if j.get_button(i) != 0:
                print 'Button %i reads %i' % (i, j.get_button(i))
except KeyboardInterrupt:

Which produced output like this:

Axis 0 reads 0.00
Axis 1 reads 0.00
Axis 2 reads 0.05
Axis 3 reads 0.00
Axis 4 reads 0.00

After moving each axis, it appears that we we want to ignore axis 2.  i.e., the mapping looks like this:

Axis 0 - Left stick (L = -1.0, R = 1.0)
Axis 1 - Left stick (U = -1.0, D = 1.0)
Axis 3 - Right stick (L = -1.0, R = 1.0)
Axis 4 - Right stick (U = -1.0, D = 1.0)
IGNORE AXIS 2 (affect by all sticks)

So now it's simply a matter of figuring out the best way to modify the Crazyflie PC client to use axis 0, 1, 3, and 4 for input, and skip axis 2.  Remapping the configs/input/*.json fixes the axis; for example:

     "axis": [
          {"name":"Roll", "type":"Input.AXIS", "id":4, "scale":1.0, "key":"roll"},
          {"name":"Pitch", "type":"Input.AXIS", "id":3, "scale":-1.0, "key":"pitch"},
          {"name":"Yaw", "type":"Input.AXIS", "id":0, "scale":1.0, "key":"yaw"},
          {"name":"Thrust", "type":"Input.AXIS", "id":1, "scale":-1.0, "key":"thrust"},
          {"name":"Pitch Cal+", "type":"Input.BUTTON", "id":7, "scale":-1.0, "key":"pitchcal"},
          {"name":"Pitch Cal-", "type":"Input.BUTTON", "id":5, "scale":1.0, "key":"pitchcal"},
          {"name":"Roll Cal +", "type":"Input.BUTTON", "id":6, "scale":1.0, "key":"rollcal"},
          {"name":"Roll Cal -", "type":"Input.BUTTON", "id":8, "scale":-1.0, "key":"rollcal"},
          {"name":"Killswtich", "type":"Input.BUTTON", "id":14, "scale":1.0, "key":"estop"},
          {"name":"Exit", "type":"Input.BUTTON", "id":12, "scale":1.0, "key":"exit"}

However, that breaks one of the buttons (because the buttons should be 4-7, not 5-8, and the inputs are stored as an array indexed by the id, so we can't have both a button and axis at id 4).  So perhaps need to make a code change such that we can have an axis/button with the same id...

I created a patch back on 3/1 that got merged in; this controller should work under OS X now.

Wednesday, February 27, 2013

Qt menu and OS X

One strange issue I noticed with crazyflie-pc-client is that it appeared to be missing some menubar items.  Specifically, "Configure Input device", "Exit", "Options", and "Help".  It took some digging but I finally found this:

QMenuBar on Mac OS X

QMenuBar on Mac OS X is a wrapper for using the system-wide menu bar. If you have multiple menu bars in one dialog the outermost menu bar (normally inside a widget with widget flag Qt::Window) will be used for the system-wide menu bar.
Qt for Mac OS X also provides a menu bar merging feature to make QMenuBar conform more closely to accepted Mac OS X menu bar layout. The merging functionality is based on string matching the title of a QMenu entry. These strings are translated (using QObject::tr()) in the "QMenuBar" context. If an entry is moved its slots will still fire as if it was in the original place. The table below outlines the strings looked for and where the entry is placed if matched:
String matchesPlacementNotes
about.*Application Menu | About <application name>The application name is fetched from the Info.plist file (see note below). If this entry is not found no About item will appear in the Application Menu.
config, options, setup, settings or preferencesApplication Menu | PreferencesIf this entry is not found the Settings item will be disabled
quit or exitApplication Menu | Quit <application name>If this entry is not found a default Quit item will be created to call QApplication::quit()
You can override this behavior by using the QAction::menuRole() property.

So, Qt parses the name of the menu bar items, and if they even partially match certain string (e.g., "configure"), it will move the item into what it thinks is a Mac native menu bar!!

Since this is probably not what we want here, adding the following to an action disables this feature:

   <property name="menuRole">

For example:

  <action name="menuItemConfInputDevice">
   <property name="text">
    <string>Configure Input device</string>
   <property name="menuRole">

Monday, February 25, 2013

building the firmware on OS X

This is pretty straightforward - first, download and install GNU Tools for ARM.  I put them in /usr and set the path in .bash_profile like so:

export PATH=$PATH:/usr/gcc-arm-none-eabi-4_7-2012q4/bin

then, simply cd to crazyflie-firmware and make cload.  It should build and result in something like:

Build 2:aba6937b9dab () CLEAN
   text   data    bss    dec    hex filename
  79620    460  16344  96424  178a8 cflie.elf

Note that "cload" will make a version of the copter firmware that can be updated using the Crazyload radio bootloader (for example, via the script).

Monday, February 18, 2013

Setting up on OS X

I wanted to get the environment set up and running on OS X.  According to their wiki, that's one area where they could use help.  So, getting the client app running seemed like a good place to start.

First I installed Mercurial from the installer on the home page, which is what they use for source control.  I then pulled down all of the source code repositories found on Bitbucket here, with "hg clone".

In the crazyflie-pc-client repository, cd'ing to cfclient and attempting  python ./ resulted in:

No pyusb installation found, exiting!

Installing pyusb on OS X is easy:

sudo easy_install pyusb

Attempting to run it again results in another missing dependency error for pygame; first I attempted to resolve that with:

sudo easy_install pygame

However, that resulted in a bunch of errors, and I would up instead installing the binary package for Lion, available on the pygame website, which seemed to install OK.

The next dependency issue I hit was with PyQT4.  I attempted to install the binaries for that as well, found on the PyQtX project.

Unfortunately, attempting to install that resulted in an error:  "Python 2.7 from official python website is not installed.".

The version of Python on my machine (OS X Lion, Version 10.7.5) is:

python -V
Python 2.7.1

So I'm not sure why PyQT4 was complaining, but I went ahead and installed the latest stable 2.7.x Python release (Python 2.7.3 Mac OS X 64-bit/32-bit x86-64/i386 Installer):

Which appeared to install "python2.7-32", the only 2.7.3 version of Python I could find in my path.

Next, the PyQT4 install finally was able to be started, but it indicated that it requires the Qt Libraries to be installed - specifically, 4.8.2.  I found some versions on the Qt Project home page, but the closest was 4.8.4.

I installed the 4.8.4 version of Qt, then continued with the PyQT4 install, and finally PyQT4 appeared to have installed successfully, with an ugly confirmation dialog:

Now back to cfclient.  Attempting to run again with 2.7.3 resulted in this:

$ python2.7-32  ./ 
Traceback (most recent call last):
  File "./", line 74, in <module>
    from ui.main import MainUI
  File "/Users/mikevoyt/Development/repositories/crazyflie/crazyflie-pc-client/cfclient/ui/", line 36, in <module>
    from PyQt4 import Qt, QtCore, QtGui, uic
ImportError: dlopen(/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/PyQt4/, 2): no suitable image found.  Did find:
/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/PyQt4/ mach-o, but wrong architecture

This had me stumped a bit; 'python -V' was still showing 2.7.1 while 'python2.7-32 -V' seemed to be the only version of Python I had installed showing 2.7.3.  Well it turns out the '-32' is the 32-bit version (duh), and the PyQt4 binary only supports the 64-bit version.  I found the 64-bit version along with the other versions here:


The version of 'python2.7' in my path was pointing to a binary in /System/Library/Frameworks, which explains why it was still back at 2.7.1 (so apparently all of the pre-installed Python versions are in /System, while the install put the new versions in /Library).

So after moving /usr/bin/python off to the side, and creating a simlink to the new version in /usr/bin:

sudo ln -s /Library/Frameworks/Python.framework/Versions/2.7/bin/python

finally, "pyton ./" finally brought up the UI!

So after a few hours of downloading libraries, Googling, poking around, and some luck, I was finally able to run the Python client app on OS X.  This is one of the reasons it'd be nice to create a native OS X app (with maybe a very lightweight Pyton library for communications) for controlling the device.  For now though this should be a good place to start figuring out how stuff works.

Wednesday, February 13, 2013

Ordered the kit

So I came across an article last week on TechCrunch that mentioned a really interesting project called CrazyFlie, a "nano quadcopter".  Check out the YouTube video:

It's basically a flying ARM development board, with a 2.4GHz wireless controller.  This seemed like too much fun to pass up, so I ordered the kit, which should ship on 5/3/2013.  There is a basic kit for $149, but I ordered the $173 kit, which contains some extra sensors - a magnetometer and altimeter.

It comes as a kit, so it must be assembled before even basic flying can be performed.  Once that's working, there's a few things I'd like to develop and play around with - for example, there is currently no software support for the altimeter.  I'd also like to play with some algorithms for implementing a hover mode, and (re)learn some control theory.  Plus I think my kids will be fascinated :)  So, stay tuned, as I hope to update this blog as I learn more about the hardware/firmware/software... and hack on the Crazyflie!