Auto-Pilot the Neato XV-11 from Python
This repository contains code for
running a stubbed version of the XV-11 AutoPylot
program, which allows you to auto-pilot the
Neato XV-11 wirelessly from source code written in Python.
The stubbed agent class contains an empty init
method and a getAxes method that accepts a LIDAR scan
from the XV-11 and returns an (x, y) axis pair representing
a virtual joystick position.
By modifying just these two methods you can exploit the XV-11's onboard LIDAR for
exploring
obstacle avoidance,
SLAM, and other tasks, without having to write any of your own
communication or serial-port code
As with AR.Drone Autopylot, the idea is that you start driving the robot around using manual control (joystick axis), and it switches to autopilot mode when you click a button. Autopilot runs by sending the XV-11 the same joystick axis commands as in manual mode. Grabbing the joystick again or clicking another button takes it out of autopilot.
- Obviously, an XV-11. Make sure it has the current firmware. An XV-21 will probably work too, but I haven't tried one.
- A small computer with wifi capability to mount onboard the XV-11 without blocking the LIDAR scan. Raspberry Pi works well for this. The Raspberry Pi 3 has a Broadcom wifi chip onboard, saving you the hassle of finding a wifi adapter that supports ad-hoc networking.
- A battery to power the onboard computer, if it doesn't have one built in. This rechargeable battery provided around three hours of power for my Raspberry Pi, via a six-inch micro USB cable.
- A short USB A to mini-B cable to connect the onboard computer to the XV-11's USB port.
- Velcro tape to keep the onboard computer (and battery) attached securely to the XV-11.
- A laptop computer on which to run the client program, which will talk over wifi to the server program running on the onboard computer. I have tested the client on Windows, Mac OS X, and Linux, and the server on Mac OS X and Linux.
- A PS3 gamepad controller, Logitech joystick, or similar device for driving the XV-11 from the laptop. The client will work without such a device, allowing you to drive using the arrow keys on your keyboard, but you'll have more fun using a real controller. I used an inexpensive, wired PS3 controller knockoff like this one.
Both the server and client are written in Python, so you will need to have Python running on both the laptop and onboard computer. I have tested both the server and client in Python 2 and Python 3. You will also need the following packages:
-
BreezyPythonGUI on the laptop.
- Pyserial on the onboard computer.
- Pygame on the laptop: not strictly necessary, but enables joystick control.
If you're using a Raspberry Pi as your onboard computer, you'll probably use one of the USB ports for the wifi dongle and the other for connecting to the XV-11's mini-USB port. In that case, connecting the Pi to a USB keyboard and mouse to do the following steps is going to be impossible. So for the following steps I recommend talking to the Pi over a wired network, using the Ethernet jack. Once you've got everything connected, do the following:
- Look at the HOST and PORT variables
in neatopylot_header.py to make sure they won't interfere
with anything else you may be running on your network (unlikely), and modify
them if they do.
- Copy the source code from your laptop to your onboard computer.
- Set up an ad-hoc network on the onboard computer.
For the Raspberry Pi I found several web pages
describing how to do this by modifying configuration files in /etc,
but I couldn't get any of them to work. So I wrote a little Python script
neatopylot_wifistart.py and included it in the repository.
Of course, you will need to run this script using sudo.
If you sudo the script from /etc/rc.local, you can get
it to run automatically every time you boot your Pi:
python /home/pi/NeatoPylot/neatopylot_wifistart.py
You can then follow the instructions in this repository to get your Pi to serve up a dhcp network.
If the onboard computer is a Mac, I would follow the procedure described here.
- From your laptop, join the ad-hoc network that you just created in
the previous step. If you use my script to create the network, it will be
called Neato-Raspberry-Pi.
- On your onboard computer, make sure that the value of the DEVICE
variable in neatopylot_server.py matches the name
of the device mapped to the XV-11's USB connection in /dev.
On my Raspberry Pi, this was /dev/ttyACM0.
- On your onboard computer, run the neatopylot_server.py
script. It will wait for a client to connect.
- On your laptop computer, run the neatopylot_client.py
script. It will pop up a window showing the XV-11's LIDAR. You can then
use your gaming console or the arrow keys to drive the XV-11 around. If you
use the arrow keys, make sure you've selected the popup window, so it will
get the arrow-key events.
- In neatopylot_agent.py modify the getAxes() method and (if needed) the __init__() method, to do something more interesting than just turning around to the right.
I set up the client so that it drives on Axes 2 and 3 (the lower-right joystick) and the autopilot is activated by Button 9 (the start button). If you want to modify these settings, edit the FIRST_AXIS and AUTOPILOT_BUTTON variables in neatopylot_client.py. Occasionally the server will halt without shutting down the LIDAR motor, leaving the XV-11 in test mode – bad news, because you can't power it down, use it to vacuum, etc. If this happens, you can run the neatopylot_shutdown.py script on the server to stop the LIDAR motor and take the XV-11 out of test mode.
- I have had problems using Pygame on the Mac. If this happens, change
the pygame import at the top of neatopylot_server.py
as follows:
#import pygame pygame = None
Then use the arrow keys to drive the XV-11, and the spacebar to toggle the autopilot.
- If you opt not to use a game controller and use the arrow
keys to steer (spacebar to toggle autopilot), the response is a bit sluggish.
This is because I could not get the key-release interrupt to work correctly
in the Tkinter package that underlies BreezyPythonGUI.
Again, if you get this working yourself, please
let me know!
- Pygame may
report the joystick value without your asking to see it.
- There is a lot more sensor data that one could retrieve from the XV-11. The LIDAR scan, retrieved via the GetLDSScan command, is the only data I found useful, but if you would like to use other commands Get* from the list, let me know – and feel free of course to modify the code yourself!
If you're already using the ROS platform, you might also look into the XV-11 Driver there.
Copyright and licensing information can be found in the header of each source file. Please contact me with questions or suggestions.