Lidar Part 3: Improvised 3D Scanning with Neato XV-11 Lidar

Lidar setup and 3D scan

It’s been over two years since I first wrote about lidar units, and at the time I stated I wrote that the final part would be a look at the Neato XV-11 that I had purchased off of Ebay. That got delayed by several years, first due to an initially bad unit (but great response from the seller to correct the problem!), then higher priority projects and life intervened, but I’m finally ready to report. Besides playing around with the unit, I added some enhancements to the display software available from Surreal, who make the controller unit I used, and mounted the lidar on an pan-tilt system so I could do 3D scans.



Construction is really straight-forward. I mounted the lidar to a plastic base plate using some standoffs (since the drive motor sticks out underneath the unit). Then I mounted the base plate to the pan-tilt system, and mounted that to a project box I had lying around.

XV-11 lidar mounted on a servo-controlled pan/tilt system for 3D scans

The XV Lidar Controller version I used is built around a Teensy 2.0 and uses PID to monitor and control the rotation speed of the Lidar, controlling it with PWM. In addition, it reads the data coming off the lidar unit and makes the information available through a USB port.

The servos are both connected to the servo controller, which also uses an USB interface. The figure below shows the setup:

Labeled picture of the setup


I didn’t touch the firmware for the lidar controller. The source code is available through links at Surreal’s site. There are several very similar versions of visualization code in python that takes the output from the lidar controller and displays it using VPython. They all seem to start from code from Nicolas Saugnier (Xevel). I started with one of those variants. The main changes I made were 1) to add the ability to do a 3D scan by sweeping a pan/tilt mount through various pre-set pan and tilt angles and 2) to add the ability to capture and store the point cloud data for future use. In addition, I wrote a routine to then open and display the captured data using a similar interface. Additional smaller changes were made such as implementing several additional user controls and moving from the thread to the threading module.

The pan-tilt setup does not rotate the lidar around the centerpoint of itself. Therefore, in order to calculate the coordinate transformation from the lidar frame of reference to the original non-moving frame you have to do both a coordinate rotation and an angle-dependent translation of the origin. This is handled by the routine using a rotation matrix and offset adjustments.

The servos are controlled through a servo controller, with the controlling software ( being an enhanced version of the python control software available through Pololu that was originally developed by Juhapekka Piiroinen and Brian Wu. My version corrects some comments which were inconsistent with actual implementation, fixed bugs in the set_speed routine, and added “is_moving” as a API interface to be able to check whether or not each individual servo was moving.

The point cloud data is stored in a simple csv file with column headings. Each row has the x, y, and z coordinates, as well as the intensity value for the returned data point (provided by the XV-11), and a flag that is set to 1 if the XV-11 has declared that the intensity is lower than would normally be expected given the range.

When displaying the results, either during a scan or from a file, the user can select to color code the display by intensity, by height of the point (the z value), or by neither. In the latter case, points with the warning flag set are shown in red. In addition, as in the original software, the user can toggle showing lines from the lidar out to each data point and also an outer line connecting the points.

The software, along with some sample point cloud files, can be found on my Neato-XV-Lidar-Tools repository on GitHub.

A Note on VPython Versions

The original visualization code was written for Python 2.x and for VPython 2.6 or earlier. After some deliberation, I decided not to update this. Post version 6, VPython internals have been entirely redone, with some minor changes to how things are coded. However VPython 7 currently has issues with Spyder, that I use as my development environment, while VPython 6 won’t run in Python 3.x, and never will. It shouldn’t be a hard lift to convert the code, but note that if you update it to run under Python 3 you’ll also need to update to VPython 7 or later, while updating VPython alone may create issues depending upon your development environment. So it’s best to make both updates at the same time.

Sample Results

This first scan is a 2D scan from the floor of my kitchen, with annotation added. It clearly shows the walls and cabinets, as well as the doorways. Note that the 2nd doorway from the bottom is to a stairway to the basement. Clearly either a 3D scan or an additional sensor would be needed to keep a robot using the lidar from falling down the stairs, which the lidar just sees as an opening at it’s level!

2D Lidar scan of my kitchen

As mentioned above, one option is to display lines from the lidar unit out to the point data, This is shown in the annotated scan below:

2D Scan showing lines to each data point

The display options also allow you to color code the data points based on either their intensity or their height off the ground. Examples of the same scene using these two options are shown below. In the intensity scan, you can see that nearby objects, as a general rule, show green (highest intensity), however the brown leather of my theater seats do not reflect well, and hence they appear in orange, even though they aren’t very far away from the lidar unit.

3D scan, with colors indicating height

3D scan with colors depicting intensity of the return

Even after calibrating the pan and tilt angles the alignment is not perfect. This is most clearly seen by rotating the view to give a top/down view and noting that the lines for vertical surfaces do not all overlap on the display. The 3D results weren’t as good as I’d hoped, but it certainly works as a proof of concept. The 2D results are very good, given the price of the unit, and I could envision modifying the code to, for example rapidly capture snapshots and use the code to train a machine learning program.

Potential Enhancements

One clear shortcoming in the current implementation is the need to carefully calibrate the servo command values and the angles. This takes some trial and error, and is not 100% repeatable. In addition, one has to take into account the fact that as the unit tilts, the central origin point of the lidar moves, and where it moves to is also a function of the pan angle. One of the effects of this setup is that unlike an expensive multi-laser scanning unit, each 360 degree scan is an arc from low to high to low, rather than covering a fixed elevation angle from horizontal. This makes the output harder to interpret visually. The 3D scanning kit from Sweep takes a different approach, rotating the lidar unit 90 degrees, so that it scans vertically rather than horizontally, and then uses a single stepper motor to rotate the unit through 360 degrees. Both the use of a single rotation axis and the use of a stepper motor rather than a servo likely increase the precision.

With either 2D or 3D scanning, the lidar can be used indoors as a sensor for mobile robots (as that’s what it was used for originally, after all). There’s an interesting blog post about using this lidar unit for Simultaneous Location And Mapping (SLAM). I may try mounting the lidar and a Raspberry Pi on a mobile robot and give that a try.

Hobbyist Lidar of note

When I wrote my previous posts on Lidar units, the cheapest 360 degree scanning unit that was suitable for outdoor use cost over $1,000. While both Velodyne and Quanergy have promised sub $1,000 solid-state automotive grade lidar units (at least if bought in automotive industry quantities) within the next 12 months, in the meantime, hobbyists now have the Scanse Sweep. This unit uses the previously reported on LIDAR-Lite as it’s core lidar unit. The specs state that it has a range of 40 meters, a resolution of 1cm, and that because it uses coded signals, it works outdoors as well as indoors. The price, as of today, is $349. This is higher than its original price when launched, which is likely driven by the fact that the cost of LIDAR-Lite units have gone up since it’s come back into production by it’s new owner, Garmin.  The LIDAR-Lite v3 itself has a list price of  $149.59.  While certainly not an automotive great sensor, the Scanse Sweep looks like a good product for outdoor as well as indoor projects, including scale vehicle projects, at an affordable price.

Lidar: Coming Soon at a Price You Can Afford (part 1)

Google’s automated vehicles are instantly identifiable by the rotating lidar unit mounted on their roofs, and most other automated driving research vehicles are also using lidar, either in similar roof mounted systems (e.g., Bosch), or in multiple units, each with less than a 360 degree field of view (e.g., Carnegie Mellon). These are very powerful, 3D scanning sensors, but they don’t come cheap. According to reports, Google uses a sensor from Velodyne that costs approximately $75,000. Some of those with less than a 360 degree scan can be had at less than half that price, but you need several of them. I don’t think any hobbyists (unless they are in the 1%) are going to run out to get one to use in their robotics project. A good video showing the processed information derived from the Google car is viewable here:

Until just a few years ago, that was about it. If you wanted to experiment with a lidar unit, you needed to shell out over $10,000. But that’s changed, and it’s starting to change even faster.

 Lidar on the Cheap

Lidar generally works by sending out a laser signal and measuring the time it takes to get a reflected signal back from an object. Like radar, you get a range and direction. this distinguishes lidar from laser rangefinders, which determine distance only (and at least one vendor,  apparently wanting to exploit the interest in lidar, advertises their rangefinder as a lidar unit). Lidars are not mass-produced, and sophisticated electronics that handle are precise at processing extremely tight time frames (the time of flight difference for a radar return from 1 meter versus 10 meters is EXTREMELY small). Very precise mechanical parts are typically required.

 The Neato XV-11

However, in 2010, Neato Robotics introduced a new robotic vacuum cleaner that got robotics hobbyists very excited. Not because they don’t like dirty floors, but because it incorporated a lidar unit as part of its navigation system. And the entire vacuum cleaner, lidar included, cost less than $400. Hobbyists got right to work hacking the lidar unit, and, while the manufacturer doesn’t sell just the lidar units, they are available on ebay and other sources for under $100 each! The interface has been reverse engineered and documented on many websites, including the XV11hacking wiki. Interface code for ROS and other platforms, e.g., arduino, have also been developed. At least one vendor, Get Surreal, sells a controller board for this unit to simplify use.

Part of the cost reduction comes from using a different approach for ranging. Rather than using time of flight for the lidar signal, the Neato unit uses  triangulation, with a laser diode emitter and an imager receiver. This eliminates the need for extremely time-precise electronics.  A technical paper on their lidar, A Low-Cost Laser Distance Sensor, is available on the web.

Obviously these units don’t compare with a $75,000 unit. Their range is on the order of 6 meters (nice for indoor or slow speed operation, but hardly something you can build an autonomous passenger vehicle around). The resolution is lower, and they produce a 2D scan, not a 3D scan. A nice, short, video demo of the type of performance you might expect is at One could mount one on a tilt platform and produce a 3D point cloud from multiple scans at different angles of elevation, but it would be slower. This video shows that approach, albeit for a different lidar unit.

Neato Robotics XV-11 lidar with top removed

the XV-11 Unit, with the top removed. (photo source: Sparkfun)

I’ve got an XV-11 unit and controller board on order, and will report about it in part 3 of this series (which could be awhile in coming).


The XV-11 was the first low-cost lidar unit for hobbyists, but new options at a variety of price ranges are coming available. Robopeak has introduced what appears to be a similar unit to the XV-11, the RP developed and designed for hobbyists and researchers.  Priced at $399, it includes, according to reviewers who have purchased the product, good sample drivers for several platforms, including ROS and arduinos, as well as a full SDK and good documentation (something that won’t be found when buying an XV-11 unit on ebay). For many, the greater ease of use and reduced time would be worth the price difference from an XV-11.


RPLIDAR Unit (photo source: DFRobot)


A number of low-priced laser range-finders advertise themselves as lidars, but with this exception, I’ve looked at only systems that scan, either in 2D or 3D as lidars. While a range-finder (1D), the LIDAR-Lite has some very interesting advertised capabilities at a low price point, which might make it worth exploring putting it on a rotating platform as a lidar unit. Rather than directly measuring time of flight, as more expensive units do, or using triangulation like the NX-2, it sends out a coded waveform and, if I understand what they are saying on their website, uses signal processing to look at the shift coming back as compared with an identical reference signal.

The unit is very small (21 X 48.3 X 35.5 mm) along with a similarly sized single PCB board and costs $89. Keep in mind this is for a range-finder. You’d still have to have a precision panning platform to use it as the core of a full lidar. What makes this unit interesting is that with the $89 laser version, with optics, they claim a maximum range of 30-60 meters, and that it works outdoors in sunlight, which is, as far as I can tell, unprecedented for such a low-cost unit. 

Deeper Pockets

Part 2 of this series will discuss some of what’s available for budgets of $1,000 – $10,000, including the recently announced Velodyne Puck.

Velodyne "Puck" 3D Scanning lidar

Velodyne “Puck” 3D Scanning lidar