Skip to content
This repository

Welcome to the NXV11 wiki!

Latest and updated info is now gathered here:

http://xv11hacking.wikispaces.com/LIDAR+Sensor


Here are some stuff about the Laser Distance Sensor (LDS) on the Neato Robotics XV-11 vacuum cleaner.

The data on this page and in the provided code are not based on official information, so take everything with a grain of salt...

See https://sites.google.com/site/chenglung/home/xv-11-open-lidar-project-matlab-script too for a matlab version with it's own improvements !

and here for the original Trossen Robotics thread

and here http://random-workshop.blogspot.com/ for new data and info.

2010/11/25 : aww, man ! I just go away for one day and the data format has changed :s

Data format for firmware V2.4 (recent production units)

A full revolution will yield 90 packets, containing 4 consecutive readings each. The length of a packet is 22 bytes. This amounts to a total of 360 readings (1 per degree) on 1980 bytes.

Each packet is organized as follows:

<start byte> <index> <speed> <Data 0> <Data 1> <Data 2> <Data 3> <checksum>

where:

  • start byte is always FA

  • index is the index byte in the 90 packets, going from A0 (packet 0, readings 0 to 3) to F9 (packet 89, readings 356 to 359).

  • speed is a two-byte information, little-endian. It represents the speed, in 64th of RPM (aka value in RPM represented in fixed point, with 6 bits used for the decimal part).

  • Data 0 to Data 3 are the 4 readings. Each one is 4 bytes long, and organized as follows :

byte 0 : <distance 7:0>

byte 1 : <"invalid data" flag> <"strength warning" flag> <distance 13:8>

byte 2 : <signal strength 7:0>

byte 3 : <signal strength 15:8>

As chenglung points out, the distance information is in mm, and coded on 13 or 14 bits. This would put the tests made by Sparkfun in a room of around 3.3m x 3.9m (11ft x 13 ft ?), which seems reasonable to me. The maximum distance is around 6m.

The bit 7 of byte 1 seems to indicate that the distance could not be calculated.

It's interesting to see that when this bit is set, the second byte is always 80, and the values of the first byte seem to be only 02, 03, 21, 25, 35 or 50... When it's 21, then the whole block is 21 80 XX XX, but for all the other values it's the data block is YY 80 00 00 maybe it's a code to say what type of error ? (35 is preponderant, 21 seems to be when the beam is interrupted by the supports of the cover) .

The bit 6 of byte 1 is a warning when the reported strength is greatly inferior to what is expected at this distance. This may happen when the material has a low reflectance (black material...), or when the dot does not have the expected size or shape (porous material, transparent fabric, grid, edge of an object...), or maybe when there are parasitic reflections (glass... ).

Byte 2 and 3 are the LSB and MSB of the strength indication. This value can get very high when facing a retroreflector.

  • checksum is a two-byte checksum of the packet.

The algorithm is as follows, provided that data is the list of the 20 first bytes, in the same order they arrived in.

(sorry for the poor rendition of the code, seems like this formating is buggy. See the code, line 111)

    def checksum(data):
        # group the data by word, little endian
        data_list = []
        for t in range(10):
            data_list.append( data[2*t] + (data[2*t+1] &lt;&lt; 8) )
        # compute the checksum.
        chk32 = 0
        for data in data_list:
            chk32 = (chk32 &lt;&lt; 1) + data

        # return a value wrapped around on 15bits, and truncated to still fit into 15 bits
        checksum = (chk32 &amp; 0x7FFF) + ( chk32 &gt;&gt; 15 ) # wrap around to fit into 15 bits
        checksum = checksum &amp; 0x7FFF # truncate to 15 bits
        return int( checksum )

Data format for firmware 2.1 (Sparkfun scans, pre-production units)

The periodicity of the data is 1446 bytes.

It is organized as follow :

5A A5 00 C0 XX XX <data>

where XX XX is an information about the current rotation speed of the module, in clock ticks (little endian). FJ_Sanchez and shimniok posted interesting data about this.

<data> is composed of 360 group of 4 bytes, organized like this :

byte 0 : <distance 7:0>

byte 1 : <"invalid data" flag> <"quality warning" flag> <distance 13:8>

byte 2 : <quality 7:0>

byte 3 : <quality 15:8>

As chenglung points out, the distance information is in mm, and coded on 13 or 14 bits. This would put the tests made by Sparkfun in a room of around 3.3m x 3.9m (11ft x 13 ft ?), which seems reasonable to me. 13 bits should be enough if the sensor is destined to work up to 6m. This needs some tests...

The bit 7 of byte 1 seems to indicate that the distance could not be calculated.

It's interesting to see that when this bit is set, the second byte is always 80, and the values of the first byte seem to be only 02, 03, 21, 25, 35 or 50... When it's 21, then the whole block is 21 80 XX XX, but for all the other values it's the data block is YY 80 00 00 maybe it's a code to say what type of error ? (35 is preponderant, 21 seems to be when the beam is interrupted by the supports of the cover) . Another thing to have a look to is the temporal repartition of the data... the first sample after the sync seems to always be 21 80 XX XX, and when this pattern appears again, it's immediately after an other value, without the 0.2ms interval we can see most of the time between two blocks of 4...

The bit 6 of byte 1 is a warning when the reported strength is greatly inferior to what is expected at this distance. This may happen when the material has a low reflectance (black material...), or when the dot does not have the expected size or shape (porous material, transparent fabric, grid, edge of an object...), or maybe when there are parasitic reflections (glass... ).

Byte 2 and 3 are the LSB and MSB of the strength indication. This value can get very high when facing a retroreflector.

Something went wrong with that request. Please try again.