Simplifying Lidar
Author: Aiden Dumas
Using Lidar is fundamental for a robot’s understanding of its environment. It is the basis of many critical mapping and navigation tools such as SLAM and AMCL, but when not using a premade algorithm or just using Lidar for more simple tasks, some preprocessing can make Lidar readings much more understandable for us as programmers. Here I share a preprocessing simplification I use to make Lidar intuitive to work with for my own algorithms.
It essentially boils down to bundling subranges of the Lidar readings into regions. The idea for this can be found from: Article The simple preprocessing takes the 360 values of Lidar’s range method (360 distance measurements for 360 degrees around the robot) and gives you a much smaller number of values representing more intuitive concepts such as “forward”, “left”, “behind”. The processing is done by creating your subscriber for the Lidar message: scan_sub = rospy.Subscriber(‘scan’, LaserScan, scan_cb)
Our callback function (named scan_cb as specified above), will receive the message as such: def scan_cb(msg):
And depending on how often we want to preprocess a message, we can pass the 360 degree values to our preprocessing function: ranges = preprocessor(msg.ranges)
In my practice, calling this preprocessing step as often as the message was received by the subscriber didn’t have any slowdown effect on my programs. The processor function itself is defined as follows:
def preprocessor(all_ranges):
ranges = [float[(‘inf’)] * 20
ranges _index = 0
index = -9
sum = 0
batch = 0
actual = 0
for i in range(360):
curr = all_ranges[index]
if curr != float(‘inf” and not isnan(curr):
sum += curr
actual += 1
batch += 1
index += 1
if batch == 18:
if actual != 0:
ranges[ranges_index] = sum/actual
ranges_index += 1
sum = 0
batch = 0
actual = 0
return ranges
def averager(direction_ranges):
real = 0
sum = 0
for i in ranges:
if i != float(‘inf’) and not isnan(i):
real += 1
sum += 1
return float(‘inf’) if real == 0 else sum/real
def cardinal_directions(ranges):
directions = {“Front”: float(‘inf’), “Back”: float(‘inf’), “Left”: float(‘inf’), “Right”: float(‘inf’)}
plus_minus = 9
Front = ranges[-plus_minus:] + ranges[:plus_minus]
Backward = ranges[180 - plus_minus:180+plus_minus]
Left = ranges[90 - plus_minus:90+plus_minus]
Right = ranges[270-plus_minus:270 + plus_minus]
directions_before_processed = {“”Front”: Front, “Back”: Back, “Left”: Left, “Right”: Right}
for direction, data in directions_before_processed:
directions[direction] = averager(data)
return directions