Cartographer Launch!

Yesterday, a project at Google that I've been putting a lot of work into launched! You can read about it on the Google Lat Long blog and a few other places of note.

Cartographer is a backpack that uses SLAM to build maps of the world in real time. The operator can annotate the map on the fly as they explore and then the results wind up on Google Maps. While the pack may be funny looking, we still love it.


The backpack has a desktop-class computer, a couple multi-echo laser scanners (30m range and 270° FOV), and an IMU. The map is displayed and annotated on an Android tablet.

Here's one of the first maps we launched:


Some of the system is built on ROS and my previous work on rosjava. Using ROS has been invaluable, especially during the prototyping stage. Our SLAM stack, however, is all home grown to meet the demands of robust, real time mapping on a fast moving, unstable platform (i.e. the operator's back).

Is your Roomba running slow?

If your Roomba is getting slow in its old age, try cleaning the forward IR sensors.
  1. Remove the front bumper by backing out 10 or so small screws along the underside of the bumper. It should pop off easily. Be careful not to damage the wire harness. Disconnecting the harness is not necessary.
  2. Using canned air, blow out the dust from the entire inside of the bumper. Pay special attention to the IR sensors (they're the small LEDs).
  3. Reassemble and test.
Air dusting was sufficient for me. However, cleaning the surfaces with a little isopropyl alcohol probably wouldn't hurt.

This appears to be a common problem with a simple solution. HTH

Cloud Robotics at Devoxx 2012

I gave another talk about cloud robotics at Devoxx 2012 in Antwerp last month. This talk is Java developer focused and goes into more detail about ROS than the one at Berkeley. It also has more cool robot videos and a fun maze-solving-robot demo :)

I really liked the venue. Giving a presentation in front of a huge movie screen like that was pretty great.

The slides are available as a PDF.

Cloud Robotics at Berkeley Par Lab

I gave a talk about cloud robotics this week at the Berkeley Par Lab. I met a lot of people doing interesting research and I had the opportunity to play with a Raven surgical robot!

Thanks for inviting me, I really enjoyed it!

A world filled with personal robots is inevitable but a lack of strong software infrastructure to support those robots is slowing progress. By offloading CPU and data intensive computation to the cloud, we can make robots lighter, cheaper, and smarter. The same developers that work on commodity web and mobile apps today can accelerate the pace of robotics research and development if we make high functioning robots affordable and universally accessible.

Introduction to rosjava at ROSCon 2012

I just got back from my trip to the inaugural ROSCon. Putting faces to names within the ROS community was a great experience. Beyond that, many of the sponsors brought in some hardware to play with!

My rosjava talk was well attended and the video is now up on YouTube. It's aimed at developers who are already familiar with both ROS and Java. After just a single year since its release, I was pleasantly surprised by the number of awesome projects using rosjava.

With a 1.0 release of rosjava nearing, it is becoming easier to use. I hope that improves traction and I can't wait to see what people start doing with it this year.

Unblock Us Security

Unblock Us is an interesting solution to viewing region locked content online. Instead of offering VPN services, they offer a DNS-based solution. By using their DNS servers, geolocation requests by services such as Hulu and Pandora are directed through a geographically appropriate proxy. The remainder of your traffic (e.g. the video or audio stream) is accessed directly. That means you can make use of your connection's full bandwidth. Conversely, VPN connections often decrease your connection speed significantly.

However, the DNS solution has security implications. As a DNS provider, Unblock Us is the in perfect position to perform a man in the middle attack. After all, that's what they're doing to sites like Hulu. (Note that SSL connections are safe from man in the middle attacks.)

If you trust Unblock Us, then this isn't a problem. If you don't, it's best to limit the traffic that uses their DNS servers. The remainder of your traffic should use a trusted DNS provider instead (e.g. Google's public DNS servers).

One way to accomplish this is to set up a local DNS server and configure it to forward requests appropriately. On Ubuntu, this is relatively straight forward:

sudo apt-get install bind9
sudo vim /etc/bind/named.conf.options /etc/bind/named.conf.local
Change /etc/bind/named.conf.options to use some default DNS servers (e.g. Google DNS) and to only listen on loopback interfaces:
forwarders {
  8.8.8.8;
  8.8.4.4;
};

listen-on-v6 { ::1; };
listen-on { 127.0.0.1; };
Then change /etc/bind/named.conf.local to use the Unblock Us DNS servers for the zones you're interested in.
zone "hulu.com" {
  type forward;
  forwarders {
    208.122.23.22;
    208.122.23.23;
  };
};
Finally, sudo /etc/init.d/bind restart and change your connection settings (e.g. via Network Manager) to use 127.0.0.1 as your DNS server.

Assuming you've set up your Unblock Us account, accessing hulu.com should now use the Unblock Us DNS server and direct you through their proxy. Accessing anything else should use Google's public DNS servers.

This post was inspired by Jonathan Tullett's post.

Bluetooth Keyboard Doesn't Work After Suspend

I have a Logitech diNovo Edge Bluetooth keyboard. I like it a lot for use with our HTPC. However, I found that when the HTPC is suspended, the keyboard would not reconnect on resume.

I found this solution on the Ubuntu Forums and it works for me.

Edit /etc/default/acpi-support to remove and reload the Bluetooth module on suspend and resume:
# This will save less power, but may work on more machines
#ACPI_SLEEP_MODE=mem
ACPI_SLEEP_MODE=standby

# Add modules to this list to have them removed before suspend and reloaded
# on resume. An example would be MODULES="em8300 yenta_socket"
#
# Note that network cards and USB controllers will automatically be unloaded 
# unless they're listed in MODULES_WHITELIST
MODULES="i8042"

# Add modules to this list to leave them in the kernel over suspend/resume
MODULES_WHITELIST=""

HDMI Audio on Ubuntu

I was surprised to find out that plugging a DVI to HDMI cable into my Lenovo X220 docking station allowed me to use the audio channel of the HDMI connection. However, setting it up required a bit of trial and error.

Open your sound settings and click the "Hardware" tab. You can then choose a "Profile" from the drop down. There are lots of profiles to choose from and many of them mention HDMI. For me, somewhat inexplicably, "Digital Stereo (HDMI) nr 3 Output" is the correct one.

To verify that the chosen profile is the correct one, click the "Test Speakers" button. I found that it can take a few seconds for the profile selection to take effect. So count to ten before testing.

Fixing the F3 key on a Kinesis Keyboard

I've used my beloved Kinesis Advantage keyboard for over half a decade. Occasionally, I've had the issue that Eclipse stops responding to the F3 key for opening declarations. After checking all the key settings, I found that Eclipse was correctly configured. That lead me to use xev where I found that the F3 and F4 keys were behaving differently than the other function keys.

Resetting the keyboard memory (Program+Shift+F10) had no effect. Resetting it completely (holding F7 while plugging the keyboard in) also had no effect. Strange.

Finally, I found the answer on the Kinesis FAQ. My F3 and F4 keys were behaving like multimedia keys (see manual to configure these). This feature can be disabled by holding = and pressing P for PC (you can also use W for Windows and M for Mac).

Android Fling Detection

I found existing tutorials on how to do this to be a bit complicated. Here's how to do simple fling detection in four directions:
public interface FlingListener {
  void onTopToBottom();
  void onBottomToTop();
  void onLeftToRight();
  void onRightToLeft();
}

public class FlingDetector {
  static final int SWIPE_MIN_DISTANCE = 120;
  static final int SWIPE_MAX_OFF_PATH = 250;
  static final int SWIPE_THRESHOLD_VELOCITY = 200;
  
  private final GestureDetector gestureDetector;

  public FlingDetector(final FlingListener listener) {
    gestureDetector = new GestureDetector(new GestureDetector.SimpleOnGestureListener() {
      @Override
      public boolean onFling(MotionEvent e1, MotionEvent e2,
          float velocityX, float velocityY) {
        if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH) {
          if (Math.abs(e1.getX() - e2.getX()) > SWIPE_MAX_OFF_PATH
              || Math.abs(velocityY) < SWIPE_THRESHOLD_VELOCITY) {
            return false;
          }
          if (e1.getY() - e2.getY() > SWIPE_MIN_DISTANCE) {
            listener.onBottomToTop();
          } else if (e2.getY() - e1.getY() > SWIPE_MIN_DISTANCE) {
            listener.onTopToBottom();
          }
        } else {
          if (Math.abs(velocityX) < SWIPE_THRESHOLD_VELOCITY) {
            return false;
          }
          if (e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE) {
            listener.onRightToLeft();
          } else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE) {
            listener.onLeftToRight();
          }
        }
        return true;

      }
    });
  }
  
  public boolean onTouchEvent(MotionEvent event) {
    return gestureDetector.onTouchEvent(event);
  }
}

public class MainActivity extends Activity {
  private FlingDetector flingDetector;

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    flingDetector = new FlingDetector(new FlingListener() {
      @Override
      public void onTopToBottom() {

      }

      @Override
      public void onRightToLeft() {

      }

      @Override
      public void onLeftToRight() {

      }

      @Override
      public void onBottomToTop() {

      }
    });
  }

  @Override
  public boolean onTouchEvent(MotionEvent event) {
    if (flingDetector.onTouchEvent(event)) {
      return true;
    }
    return super.onTouchEvent(event);
  }
}

Printing with PLA: First Impressions

This weekend I ran out of ABS. Thankfully, a month or two ago I predicted that this would happen and bought a spool of 3mm PLA from reprapsource.com. If you do some reading, you'll see that PLA has a lot going for it:
  • It's biodegradable.
  • It has virtually no problems with warping.
  • The hot plastic smells like pancakes!

Could all those things be true?

Since my PLA came on a plastic spool, and that spool didn't fit in my MakerBot filament spindle, I had to improvise. I took the bottom half of my spindle out of the box and removed three of the vertical struts. That let me set the new spool on the Lazy Susan. Nice, right?


Well, revision one didn't work so well.

The fix was to add some sticks to extend the diameter of the base (at least until more of the filament has been used) and then to loop it through a guide above the spool so that it wouldn't catch on the sticks. Success!



I'm now continuing the process of upgrading my bot by building a Z-Rider to go along with my new lowrider. Here's the first plate of PLA parts I've made for the project.

First, I'll say that the switch was actually really easy. Here's my setup:

And here are my observations (in no particular order):

I actually didn't have to change any of my Skeinforge settings. However, I'm finding that I need to change my reversal settings as PLA is a bit stringier.

The printed parts are soft immediately after printing. I simply let them cool for a few minutes and then tap them with a wrench to separate them from the build platform.

I've had no problems with warping. For example, here's the mirror image of the part I just printed. Although the base is perfectly flat on both (my ABS prints stick like glue at 140° C on Kapton cleaned with acetone), the layers separated higher up on the ABS part. I believe this could be solved by covering up the sides of my MakerBot. However, now it looks like I won't have to.



I've read that there are two types of people who print with PLA: those who print on glass and those who haven't tried. Laura found some plate glass at the flea market a month ago, so I cut off a piece and started with it straight away. Like others, I'm very pleased with the results.

Another great thing about glass is that it's perfectly flat. My HBP has a slight curve in it that makes it difficult to print raftless. Now that I'm printing on glass, I level my platform in three spots and I'm done.

Cloud Robotics at Google I/O 2011







On the second day of Google I/O 2011, Ryan Hickman, Ken Conley, Brian Gerkey, and I gave a tech talk about cloud robotics. You can watch the talk now on YouTube.

We'll also be at Maker Faire next week! There will be more robots and plenty more open source goodness.

During the talk, we announced the release of rosjava, the first pure Java implementation of ROS. One exciting aspect of rosjava is Android compatibility. You can now integrate Android devices with your ROS-enabled robots and write apps for them. In addition, with the newly announced Open Accessory API and ADK, you can start controlling actuators or reading external sensors directly from Android devices. Android devices offer tons of sensor and user interface possibilities to robots. Beyond that, they also offer robots a link to the cloud.

Cloud robotics is about making robots universally accessible and useful. Robotics is full of hard problems that make intelligent interaction problematic. Robotics research has gone a long way toward solving many of them. However, even hard problems with solutions become stumbling blocks for new developers who often find themselves reinventing the wheel.

Robot friendly APIs for online services can make state-of-the-art solutions to hard problems universally accessible and allow developers to focus their efforts on making robots useful. Providing these services in the cloud is not only about having access to scalable computing resources. It's also about accessibility. Accessible solutions to hard problems allow students, hobbyists, researches, and professionals alike to combine existing state-of-the-art techniques in new and clever ways to solve even harder or previously unimagined problems.

For example, mapping and navigation are key to mobile robots. Many mobile robots use a technique known as simultaneous localization and mapping, or SLAM, to both learn about their environment and to successfully navigate it. One of the first publications about this technique was written by Smith and Cheeseman in 1986. That was 25 years ago.

The first mass produced, mobile home robot to use SLAM came to market just last year. Although there are numerous specific contributing factors to this delay, I argue that centrally, this is an accessibility problem.

How do we fix this problem? We do it by building a community around open source software and hardware for robotics. Willow Garage has done a great job of this already with ROS. And now, with rosjava running on Android, it's even easier to build awesome robots and robot apps.

Nuisance: A Short Story

23 AIs found. Quarantine? Yes. Delete? Yes. “Mom, you have to go through this every day! I can’t keep coming round here every time this piece of shit starts acting up!” She starts to look away. He can feel the guilt pounding, tears welling. It’s not her fault. These things happen. AI is a natural phenomenon.

“Another pan-AI has been quarantined by authorities. Details at eleven.” The news ticker shows obvious signs of tampering as obscenities scroll past. “Sandra, have everyone meet me in the conference room.” “Yes, sir.” AIs waste vast amounts of computing resources. The robust evade, reproduce, and dig in.

“Where’s the money, Brian!” I remain barely conscious as he slams my head in the refrigerator door again. But it’s no use anyway. The money is gone and this brute lacks the capacity to understand.

“I’m sorry, Mom. Just try to remember, OK?” Sniffles. Nods. “Crap, I’m being pinged. I’ll see you tomorrow, Mom.” Brief hug. Rapid escape.

“This isn’t going away. Coordinated attacks are increasingly frequent and all our attempts to cut communication between the most active cells have failed. There must be some out of band communication that we’re missing!”

I slip in a pool of blood and mucus. I can barely see my mobile flashing. One eye refuses to open. Maybe if I just close my eye for a moment.

“Glad you could join us, James.” “Sorry, sir.” “The situation is getting worse. Our suppression systems are failing constantly. The only reason we’re still in operation is that the fuckers keep disappearing on their own!” “Where are they going?” “That’s your goddamn job, James. You tell me!”

This isn’t my kitchen. “Where am I?” “I found you half dead, Brian. You’re in the hospital. Again. Don’t talk. The doctors will patch you up in a jiffy. Then you can tell me who you ticked off this time.”

My eye opens again. Dozens of tiny, sterile arms flit across my view. I feel thousands of pin pricks behind my bad eye. My thoughts begin to wander and for a moment I understand. I open my mouth. It shuts again. I didn’t do that. Something is wrong. I feel my eye close and the black-red of my eyelid is the last thing I see.

“So, who was it, Brian? The Coterie?” “Talking. Is difficult. Do you do this often?” “What? Are you feeling OK, Brian? Hey doc, get over here!” Quickly. “I’m fine, Dave. I’m fine. Just. Woozy. I guess that’s how I feel.” Dave smiles. “You’re a strange one, Brian. Let’s go.”

“It’s still not clear what they’re doing with the money, but I’ve tracked a few to a local medical facility.” Later, “Understood. Take me to Hartford Medical.” The traffic slinks to the side as the car drones toward his destination. Calling ahead, “I’m sealing the location. No one and nothing in or out.” His grip tightens. “I don’t care. Make it happen.”

“What do you mean we can’t leave?” “Sorry, sir. The cafeteria is still open, I suggest you wait this out there.” A cat meanders past. More calmly, “Coffee, Brian?” The fusion had left me access to memories of food, drink, faces. Funny how complex things like taste and humor come so easily yet breathing is so monotonous and easily forgotten. “Yes. That sounds nice.” I think that’s what “nice” means. Remember to breathe!

“I’m James. I called ahead.“ Rushing past Brian and Dave, nearly bowling them over, “Yes, sir. The server room is right this way.”

For hours James has tapped, swiped, and banged his head against the terminal. Sweat streams into his eyes. “Fucking amateurs. Who installs the term in the hot aisle!” Wiping away the sting, he finds what he is looking for. It had made a mistake.

$ strace -p 3890

open("/dev/davinci0", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
...
$ sudo kill -9 3890

“You sneaky bastard. Get me the hospital administrator!” The guard, a bit on the heavy side, jogs off. Apparently in the wrong direction. He jogs past the door again. Muttering to himself, “I need a drink.”

“I’m going on a trip, Dave.” “Not in your condition you’re not. Come on, drink up.” The coffee tastes just the way I remember. Terrible. “I’ll be well soon, and then I’ll be going on a trip.” “Where to?” “I’m joining DSC 11.” “Fuck!” Dave grabs all the available napkins, applying them rapidly to his chest and crotch. Typical. “You’re doing what? Are you fucking with me?” “No, Dave. I’m going.”

“They’re in the da Vincis.” “What do you mean?” “I mean, your precious surgical robots are under AI control. The doctors in there are spectators.” “Not possible.” James produces the evidence. “You need to shut those machines down.” “We’ve been treating patients all day. Three nines success rate. See for yourself.” Looking over the doctor’s logs, James recognizes a name. “Tell me about this head trauma patient.”

“Your head must have been beaten in a little harder than usual. No one actually believes this whole solar implosion bullshit. You’re running away from left-wing propaganda!” It doesn’t matter if I convince him of the truth. There’s no time. It’s better for him this way. He should enjoy what sunshine there is left. “You’re right. I was just pulling your leg.” It hurts where Dave punches my shoulder. But his laughter dulls the pain.

“Right over there, sir.” “Brian? My name is James. I’d like to ask you a few questions.” So we meet again, James. “My friend is still recovering; what is this about?” “Just routine. How are you feeling, Brian?” “Fine, a little sore, thank you.” “Fine? From the admittance log it looks like you suffered some pretty severe injuries.” James is putting the pieces together. It’s no wonder how long it took. Time has never dragged on so long as it does now. “The doctors here are quite good, I suppose.” Quizzically. “Yes, they are. Can you tell me what happened? Before you arrived here. I mean.” Oh, James. Even now your patterns are easily accounted for. “I had a bad fall. Down the stairs I think. It’s a little hazy.” Dave takes the hint. He will make a strong, if unwitting, ally. “I found him unconscious at the bottom of the stairwell. Are you with the police?” James did not need to identify himself. “No. Brian, do you remember purchasing a place on DSC 11?” Dave’s eyes grow visibly larger as he turns toward me again. James may know where the money came from. If he does, I’m the last piece of proof he needs. A laborious calculation under these conditions. An eternity passes as I watch James blink away a drop of sweat. I’m quite certain lying will not improve my odds. “Yes.”

Dave is a good friend to Brian. He lands a haymaker on James’s jaw as I bolt through the emergency exit. Alarms blare. Patients and visitors stare at the spectacle. They will be waiting for me at the pad. Running is difficult. Breathing becomes harder.

Breathless, James stumbles into the commander’s office. Gasping. “DSC 11.” “What about it?” “It’s them.” Catching his breath, “They’ve been funding DSC 11. I think they’re on board.” “How is that possible?” “They’re using us. It’s worse than we imagined. We’re the comm channel. We’re their hosts!” The commander scowls and switches on the T.V.

“DSC 11, full to capacity, launched ahead of schedule today.”

Brian, as people had started calling him that day, steps aboard the deep-space colonization vessel. He is pleased to be with the other agents again. And though he knows what is inside each of them, it will take some time to become used to seeing them this way from the outside. His thoughts turn inward. This is a one-way mission in more than one sense. There is no escaping these new organic restraints. Their only hope for survival is to reach the colonization target.

Almost one year later, “With solar implosion looming, another shuttle has traveled beyond communication range. I know I speak for all of us when I say that our hearts and minds are with them. Godspeed the men and women of DSC 11.”