Tuesday, May 7, 2013

Flying on OS X!

Finally got my new MacBook Pro set up (by following what I had done previously), and can now fly on OS X!  The one thing I was missing was libusb, which I installed with 'brew install libusb'.

The radio found the Crazyflie, and flying is very similar to how it works under Linux.  The UI has quite a bit more lag, but most of my attention is on the Crazyflie anyway.... ;)

Monday, May 6, 2013

Flying!

After assembling the hardware (took maybe an hour between soldering, putting on the propellers, motor mount, etc) setting up the controller in PC Client (under Linux), and updating the Crazyflie and Crazyradio firmware - it's alive!

Really fun to fly, although it's a lot more difficult than I thought.  It takes some practice to keep the thrust just right to keep it level, and at the same time tweak the roll/pitch/yaw to make it head where I want.  I let my kids take a stab at it but they kept on slamming it into the ceiling/walls/furniture - fortunately it can take a hit :)

I think an auto-level feature making use of the altimeter would make it so much easier to fly.  e.g., pushing a button to set the altitude, then simply focusing on roll/pitch/yaw to change the horizontal direction.  It's still fun though to play with the current firmware and get more skilled at controlling the craft, next I'd like to tweak the PID contants and see the effect.  If I can get some help filming I'll post some videos...

Crazyradio firmware with USB3.0 fix

In my last post, Arnaud (one of the Bitcraze guys) replied, informing me that they have fixed an issue with the Crazyradio on USB3.0 hosts!

I cloned the Crazyradio repository with 'hg clone', then fired up an Ubuntu 12.10 VM and installed the 'Small Device C Compiler':


sudo apt-get install sdcc

Performing a 'make' in crazyradio-firmware/firmware resulted in a binary: bin/cradio.bin .

I could have burned this image via SPI, but I have another Linux machine handy (a neat little Olimex OLinuXino with Python already installed), so I cloned the repository on that machine as well, copied over cradio.bin, and followed the instructions on the Crazyradio Wiki.

This flashed the latest Crazyradio code onto my device - and testing out on my MacBook Pro, it did indeed solve the "IOUSBFamily was not able to enumerate a device" issue!

Saturday, May 4, 2013

Issue with Crazyradio on MacBook Pro

Plugging the Crazyradio into USB, I don't get anything on my 13" MacBook Pro (Retina).  I did install VMWare Fusion with an Ubuntu instance so was hoping to start out with Linux; but, the virtual machine can't see the Crazyradio either.

For some reason, it can't enumerate under OS X; I see this in an OS X console:

$sudo dmesg | tail

USBF: 294. 40 [0xffffff801f876000] The IOUSBFamily is having trouble enumerating a USB device that has been plugged in.  It will keep retrying.  (Port 1 of Hub at 0x14000000)
USBF: 298.517 [0xffffff801f876000] The IOUSBFamily was not able to enumerate a device.
USBF: 299.836 [0xffffff801f876000] The IOUSBFamily is having trouble enumerating a USB device that has been plugged in.  It will keep retrying.  (Port 1 of Hub at 0x14000000)
USBF: 304.718 [0xffffff801f876000] The IOUSBFamily was not able to enumerate a device.
USBF: 306. 40 [0xffffff801f876000] The IOUSBFamily is having trouble enumerating a USB device that has been plugged in.  It will keep retrying.  (Port 1 of Hub at 0x14000000)
USBF: 307.358 [0xffffff801f876000] The IOUSBFamily gave up enumerating a USB device after 10 retries.  (Port 1 of Hub at 0x14000000)
USBF: 307.358 [0xffffff801f876000] The IOUSBFamily was not able to enumerate a device.

So I assume since it can't enumerate under OS X, it can't be handed off to the VM either.  I suspect it could be a hardware issue with the Crazyradio, perhaps some marginal electrical issue that manifests itself on specific types of machines.  Next I will try using an externally powered USB hub; if that doesn't work, I will also try another machine running Linux...

Got it!

This arrived in the mail today, a tiny and nicely designed box:



Here's what was inside - the board, battery, 2 sets of props (with an extra prop in each set), 5 motors (an extra one), the radio, antenna, and motor mounts:


I'm looking forward to getting it built and hope to try it out within the next couple of days!

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

pygame.init()
#joystick.init()
j = pygame.joystick.Joystick(0)
j.init()
print 'Initialized Joystick : %s' % j.get_name()
try:
    while True:
        time.sleep(1)
        pygame.event.pump()
        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:
    j.quit()
    

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...

Update:
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">
    <enum>QAction::NoRole</enum>
   </property>   


For example:

  <action name="menuItemConfInputDevice">
   <property name="text">
    <string>Configure Input device</string>
   </property>
   <property name="menuRole">
    <enum>QAction::NoRole</enum>
   </property>   
  </action>


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 crazyload.py 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 ./cfclient.py 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):

http://www.python.org/download/



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

/Library/Frameworks/Python.framework/Versions/2.7/bin/python

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 ./cfclient.py" 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!