Make the lidar streamer ready to work with main controller

This commit is contained in:
Piv
2020-04-16 21:12:12 +09:30
parent 65c19e7494
commit ed371d3a2f
9 changed files with 53 additions and 23 deletions

View File

@@ -59,3 +59,6 @@ def getZmqPubSubStreamer(port):
def getTestingStreamer():
return TestStreamer()
# TODO: Create a general get method that will get the streamer based on an
# environment variable that is set.

View File

@@ -38,7 +38,7 @@ class CarServer():
return MotorServicer(self.vehicle)
def create_slam_servicer(self):
return SlamServicer('/dev/ttyUSB0')
return SlamServicer()
def create_lidar_servicer(self):
return LidarServicer()

View File

@@ -7,9 +7,9 @@ from multiprocessing import Process
class SlamServicer(grpc.SlamControlServicer):
slam_thread = None
def __init__(self, lidar_connection):
def __init__(self):
print('Servicer initialised')
self.slam = slam.SlamStreamer(lidar_connection=lidar_connection)
self.slam = slam.SlamStreamer()
def start_map_streaming(self, request, context):
print('Received Map Start Streaming Request')

View File

@@ -15,10 +15,9 @@ import tracking.devices.factory as lidar_fact
class SlamStreamer:
can_scan = False
def __init__(self, map_pixels=None, map_meters=None, lidar_connection=None, port=None):
def __init__(self, map_pixels=None, map_meters=None, port=None):
self._map_pixels = map_pixels
self._map_meters = map_meters
self._lidar_connection = lidar_connection
self._port = port
def start(self):
@@ -40,8 +39,8 @@ class SlamStreamer:
# Adapted from BreezySLAM rpslam example.
# Connect to Lidar unit. For some reason it likes to be done twice, otherwise it errors out...
lidar = lidar_fact.get_lidar(self._lidar_connection)
lidar = lidar_fact.get_lidar(self._lidar_connection)
lidar = lidar_fact.get_lidar()
lidar = lidar_fact.get_lidar()
print('Initialised lidar')

View File

@@ -186,7 +186,9 @@ def updateCarVelocity(oldGroup, newGroup):
tuple (DistanceChange, AngleChange)
A tuple containing how the groups' centres changed in the form (distance,angle)
"""
return (find_centre(newGroup))
old_polar = convert_cartesian_to_lidar(*find_centre(oldGroup))
new_centre = convert_cartesian_to_lidar(*find_centre(newGroup))
return (new_centre[0] - old_polar[0], new_centre[1] - old_polar[1])
def dualServoChange(newCentre, changeTuple):

View File

View File

@@ -2,8 +2,11 @@ from tracking.devices.mock_lidar import MockLidar
from rplidar import RPLidar
import tracking.lidar_loader as loader
connection = "TEST"
# connection = '/dev/ttyUSB0'
def get_lidar(connection: str):
def get_lidar():
# Need a way to configure this, maybe with environment variables
if connection == 'TEST':
return MockLidar(loader.load_scans_bytes_file("tracking/out.pickle"))
else:

View File

@@ -19,12 +19,13 @@ class LidarCache():
self.run = True
self.tracking_group_number = -1
self.currentGroups = None
self._group_listeners = []
def start_cache(self, sender):
self.thread = Thread(target=self.do_scanning, args=[sender])
def start_cache(self):
self.thread = Thread(target=self.do_scanning)
self.thread.start()
def do_scanning(self, listener):
def do_scanning(self):
"""Performs scans whilst cache is running, and will pass calculated groups data to the sender.
Parameters
@@ -33,8 +34,6 @@ class LidarCache():
Any object that includes the onGroupsChanged method.
"""
# Create the 0MQ socket first. This should not be passed between threads.
self._mFactory = listener
# Batch over scans, so we don't need to do our own batching to determine groups
# TODO: Implement custom batching, as iter_scans can be unreliable
@@ -65,7 +64,21 @@ class LidarCache():
pointScan.points.append(tracker_pb.Point(
angle=point[1], distance=point[2], group_number=group.number))
self._mFactory.onGroupsChanged(pointScan)
for listener in self._group_listeners:
listener.onGroupsChanged(pointScan)
def add_groups_changed_listener(self, listener):
"""
Add a listener for a change in scans. THis will provide a tuple with the new group
scans, which can then be sent off to a network listener for display, or to update the
vehicle with a new velocity.
Parameters
----------
listener
An object that implements the onGroupsChanged(message) method.
"""
self._group_listeners.append(listener)
def stop_scanning(self):
self.run = False

View File

@@ -3,21 +3,25 @@ from tracking.lidar_tracker_pb2_grpc import PersonTrackingServicer
from tracking.lidar_cache import LidarCache
from multiprocessing import Process
import messaging.message_factory as mf
from rplidar import RPLidar
from messaging import messages
import tracking.devices.factory as lidar_factory
from messaging import messages
import tracking.algorithms as alg
class LidarServicer(PersonTrackingServicer):
def __init__(self):
def __init__(self, vehicle=None):
# TODO: Put the rplidar creation in a factory or something, to make it possible to test this servicer.
# Also, it would allow creating the service without the lidar being connected.
self.cache = LidarCache(RPLidar('/dev/ttyUSB0'), measurements=100)
self.cache = LidarCache(lidar_factory.get_lidar(), measurements=100)
self.cache.add_groups_changed_listener(self)
self._mFactory = None
self._port = None
self._vehicle = vehicle
self._tracked_group = None
def set_tracking_group(self, request, context):
pass
self._tracked_group = request.value
def stop_tracking(self, request, context):
self.cache.stop_scanning()
@@ -25,10 +29,16 @@ class LidarServicer(PersonTrackingServicer):
def start_tracking(self, request, context):
"""Starts the lidar cache, streaming on the provided port."""
self._port = request.value
self.cache.start_cache(self)
self.cache.start_cache()
def onGroupsChanged(self, message):
if self._mFactory is None:
# Create the zmq socket in the thread that it will be used, just to be safe.
self._mFactory = mf.getZmqPubSubStreamer(self._port)
self._mFactory.send_message_topic("lidar_map", messages.ProtoMessage(message=message.SerializeToString()))
if self._tracked_group is not None and self._vehicle is not None:
# Update vehicle to correctly follow the tracked group.
# Leave for now, need to work out exactly how this will change.
# alg.dualServoChange(alg.find_centre())
pass