03 January 2013

Gamepad Input in Python

I want to be able to command my upcoming Quadrotor with a game controller, so I purchased a Gigaware PC Wired Controller for $17 from Radioshack:



Quadrotors are usually controlled with two thumbsticks (4 axes): 

  • Left Thumbstick Up/Down: Throttle
  • Left Thumbstick Left/Right: Yaw
  • Right Thumbstick Up/Down: Pitch
  • Left Thumbstick Left/Right: Roll


This inexpensive controller seems perfect for what I need it for, and there are some buttons I can use for initialization and other things. I could also use this gamepad to command, say, a certain mobile robot or a certain robot arm of mine. Or both. Simultaneously. 

Oh, and I can also use the controller to play games on my computer. Which is, you know, its intended purpose. N64 Emulator, Anyone?

I looked online for some Python example code, and the easiest came from this site. 

I modified it to make it more simple and global for my, and hopefully your, purposes:


"""
Gamepad Module
Daniel J. Gonzalez
dgonz@mit.edu

Based off code from: http://robots.dacloughb.com/project-1/logitech-game-pad/

"""

import pygame


pygame.init()

j = pygame.joystick.Joystick(0)
j.init()
print 'Initialized Joystick : %s' % j.get_name()

"""

Returns a vector of the following form:
[LThumbstickX, LThumbstickY, Unknown Coupled Axis???, 
RThumbstickX, RThumbstickY, 
Button 1/X, Button 2/A, Button 3/B, Button 4/Y, 
Left Bumper, Right Bumper, Left Trigger, Right Triller,
Select, Start, Left Thumb Press, Right Thumb Press]

Note:

No D-Pad.
Triggers are switches, not variable. 
Your controller may be different
"""

def get():

    out = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
    it = 0 #iterator
    pygame.event.pump()
    
    #Read input from the two joysticks       
    for i in range(0, j.get_numaxes()):
        out[it] = j.get_axis(i)
        it+=1
    #Read input from buttons
    for i in range(0, j.get_numbuttons()):
        out[it] = j.get_button(i)
        it+=1
    return out

def test():

    while True:
        print get()

To test the code with your gamepad, simply plug it in, open a python shell, make sure the file is saved as gamepad.py, import gamepad and run gamepad.test(). Works for me in Ubuntu 12.04. To use this in your own application, simply place gamepad.py in your working directory, import gamepad, and call gamepad.get() every time you want to view the current state vector. 



 Button 4 is not pressed

 Button 4 is pressed. Note the "1" in the vector output on screen. 

Left Thumbstick not touched, all at 0

Going kinda right on the Right Stick gives a value of -.0567, and the value is linear relative to how far I push the stick. 

Going full right on the left stick brings the value up to -1.

Groovy. I don't know what's up with the third axis the joystick is giving me. The first two values in the vector make sense: Left Thumbstick up/down and left/right. But the third value changes when I move the Left Thumbstick left/right and when I move the Right Thumbstick up/down and when i hit the Start button (Button 10). It sure as hell isn't an accelerometer or anything fun like that, so I'm just going to ignore it for now. 

Hope the code proves useful!

01 January 2013

13 Plans for a New Year

We're all making New Year's resolutions. I have a few personal ones of my own, but they have nothing to do with this blog. This being Yet Another Mechanical Engineering Blog, I will focus on my engi-nerd-hack-robot-ing goals for this year, or at least the coming IAP (January semester) and Spring semester. 



0. Tune Up Cruscooter

It's a dirty hot mess. Needs major rewiring. And a working brake. 

1. Build a semi-autonomous Quadrotor
WAY more details about this coming soon. This will be one of my first projects of IAP.


2. Build a Bi-copter/Tiltrotor. A la V22 Osprey. 

Something I've been wanting to do since I saw the attack choppers in James Cameron's Avatar. And something I tried to do last year when I knew nothing. Now I know a little something, and building a quadrotor will help give me an intuition for flying things. 

3. Win MASLAB.

It's a ballsy goal. But hey, I'm a freakin' engineering diva.

4. Finish MelonChopper

Cannot wait til I can drift this thing in the snow :p

5. Learn to weld steel.
So I can build Certified Legit vehicles. For cheap. 

6. DeltaBot.

I'm going to have the coolest thesis ever ^_^.

7. Write an Instructable on manipulator robotics.
I've learned a lot in the past few years, time to spread the love. But first...

8. Design and build a ~7-DOF robotic manipulator. A la KUKA arm.
I've been controlling these bad boys, now it's time to be a Mechanical engineer for once. 

9. Pay attention to TurtleBot.

Of my children, I've been giving a lot of attention to TinyArm and none to TurtleBot, and I don't think TurtleBot can handle neglect much longer :c. Time to turn that around. I owe Shane a SLAM map of the IDC before he goes off into the Real World (c). 

10. Get TurtleBot+TinyArm playing together.
I still hold myself to the dynamic duo, TurtleBot and TinyArm, getting me a soda. Maybe now that TinyArm has learned how to talk, and with the release of ROS Groovy Galapagos I'll finally make it happen. 

11. Learn ROS. Like really learn ROS.
Willow Garage released its sixth distribution of ROS today, Groovy Galapagos. It's cleaned up a lot, and is apparently easier than ever to use. It'll happen when I try and get TurtleBot+TinyArm to get me soda. 

12. Learn C++. Like really learn C++.
See above.

13. Get a summer internship.
I cannot spend another summer at MIT UROPing. I need to see the world. See what industry is like. I need experience. I need to make a difference. I'll probably apply in the next few days...

28 December 2012

TinyArmTroller Control Update!

Now, without further ado:
Skip to 2:10 to just see it moving already
Awesome, right!? :D
I've been home for winter break, weary from the end of my fifth semester at MIT (I managed to maintain a 4.5 GPA!), and staying up in the odd hours of the night and relaxing... by working on TinyArm. 


Before I went home for winter break, I decided to drop by MITERS to pick up TinyArm, among other things. I hadn't really worked on it since the beginning of the school year, where the last breakthrough was getting it to move around using hard-coded step waypoints in the firmware. I tried for many, many nights to get "zee USB" working... to no avail. 

Now that I was home, I decided to do a few things. I wanted to model TinyArm, to figure out its dimensions and true limits before I started working out the kinematics/inverse kinematics. I also wanted the model because I wanted to test out the Solidworks-To-URDF Exporter (Now that I had a 64-bit computer). I also wanted to finally get my computer talking to the control board, even if it meant not using the USB protocol directly. 



I first grabbed my trusty calipers and began modelling the manipulator in Solidworks from scratch. Luckily, every single dimension on the thing is a proper Imperial value. Some lengths were 8.0 inches, some were 2.5, some were 6.375, but they all had some very nice number. Here you can see the final model I made. 


And here's a closeup. The most important dimensions are there, though I may eventually  add the cables, gearing, and motors. The gripper even closes the way it's supposed to! 

Too bad the URDF exporter never worked. Even with only the base links and the shoulder link selected, it was not able to identify the points or axes for each joint. Oh well, I may just make myself a custom URDF anyway. 

Next, I decided to start getting my board talking. After another few minutes screwing around with USB (At some point this semester I once managed to get the board to show up as a USB device on my computer... once. ) I decided to switch to Serial.

I looked into using serial USART communication, and found out the two pins I routed for D+ and D- in USB are the same as RX and TX for one of the serial ports built into the atxmega16a4u chip on TinyArmTroller. 



So I cut a USB 2.0-B cable and made an adapter for a Sparkfun FTDI Basic Breakout Board I had lying around. Good thing my dad had soldering equipment at home!




With this setup, and with the help of some example code I found online (which actually exists, UNLIKE F***ING USB) I was able to get it listening and talking! A few more hours of coding and I could send it six step (FROM MY COMPUTER!!) values as a waypoint (OVER SOME WIRES! :D).



I then took some time to re-calculate my estimated mapping of Angle to Steps, by moving each DOF to ~0 degrees, then to ~90 degrees, and seeing what step values took me there. Turns out, these numbers were very clean ones. For example, for the shoulder joint, -500 steps was 90 degrees, and -1400 steps was 0 degrees, leading the angle-to-step conversion to be :
(theta-140)*10 = #steps

The other DOFs followed similar patterns, and soon enough I was typing in a set of angles into the Python command line, and the arm was complying to my will! MUHUHAHAH! :D

Vid again: 

Now, what does the future hold for my wonderful TinyArm? I need to solve the inverse kinematics, meaning I need to solve for some functions that will tell me "what angles do I need to command in order to get to a certain X,Y,Z,theta?". With that, I can place some blocks in stacks in front of it and have it rearrange them, or something. 

I can make it grab a pencil and start moving along the ground plane, tracking my mouse movements. When I click, the robot moves the pencil down, and I can write things with the arm. 

I can attach it to TurtleBot and use it as a manipulator arm to go get me sodas or something, because it could pick up upwards of 2 lbs. (4 lbs according to the Microbot website...)

I can attach it to the underside of a quadrotor... 


See you next post!