Merge branch 'TrackingTesting' into 'master'

Interim Tracking testing

See merge request vato007/picar!4
This commit is contained in:
Michael Pivato
2020-08-23 11:53:12 +00:00
116 changed files with 523 additions and 476 deletions

4
.vscode/launch.json vendored
View File

@@ -10,9 +10,9 @@
"request": "launch", "request": "launch",
"module": "car", "module": "car",
"env": { "env": {
"CAR_LIDAR": "LIDAR_MOCK",
"CAR_VEHICLE": "CAR_MOCK", "CAR_VEHICLE": "CAR_MOCK",
// "LIDAR_DEVICE": "/dev/tty.usbserial-0001" // "CAR_LIDAR": "/dev/tty.usbserial-0001",
"CAR_LIDAR": "LIDAR_MOCK"
} }
}, },
{ {

View File

@@ -13,13 +13,15 @@ let package = Package(
// .package(url: /* package url */, from: "1.0.0"), // .package(url: /* package url */, from: "1.0.0"),
.package(url: "https://github.com/grpc/grpc-swift.git", from: "1.0.0-alpha.12"), .package(url: "https://github.com/grpc/grpc-swift.git", from: "1.0.0-alpha.12"),
.package(url: "https://github.com/uraimo/SwiftyGPIO.git", from: "1.0.0"), .package(url: "https://github.com/uraimo/SwiftyGPIO.git", from: "1.0.0"),
.package(url: "https://vato.ddns.net/gitlab/vato007/swiftrplidar.git", .branch("master")),
.package(url: "https://vato.ddns.net/gitlab/vato007/SwiftSerial.git", .branch("dtr_support"))
], ],
targets: [ targets: [
// Targets are the basic building blocks of a package. A target can define a module or a test suite. // Targets are the basic building blocks of a package. A target can define a module or a test suite.
// Targets can depend on other targets in this package, and on products in packages which this package depends on. // Targets can depend on other targets in this package, and on products in packages which this package depends on.
.target( .target(
name: "SwiftyCar", name: "SwiftyCar",
dependencies: ["SwiftyGPIO", .product(name: "GRPC", package: "grpc-swift")]), dependencies: ["SwiftyGPIO", .product(name: "GRPC", package: "grpc-swift"), "SwiftRPLidar"]),
.testTarget( .testTarget(
name: "SwiftyCarTests", name: "SwiftyCarTests",
dependencies: ["SwiftyCar"]), dependencies: ["SwiftyCar"]),

View File

@@ -0,0 +1,61 @@
//
// LidarProvider.swift
//
//
// Created by Michael Pivato on 10/7/20.
//
import Foundation
import GRPC
import NIO
import SwiftProtobuf
import SwiftRPLidar
class LidarProvider: Persontracking_PersonTrackingProvider {
private let lidar: SwiftRPLidar
private var shouldScan: Bool = false
init(lidar: SwiftRPLidar) {
self.lidar = lidar
}
func set_tracking_group(request: Persontracking_Int32Value, context: StatusOnlyCallContext) -> EventLoopFuture<Google_Protobuf_Empty> {
return context.eventLoop.makeSucceededFuture(Google_Protobuf_Empty())
}
func stop_tracking(request: Google_Protobuf_Empty, context: StatusOnlyCallContext) -> EventLoopFuture<Google_Protobuf_Empty> {
shouldScan = false
return context.eventLoop.makeSucceededFuture(Google_Protobuf_Empty())
}
func start_tracking(request: Google_Protobuf_Empty, context: StatusOnlyCallContext) -> EventLoopFuture<Google_Protobuf_Empty> {
return context.eventLoop.makeSucceededFuture(Google_Protobuf_Empty())
}
func record(request: Google_Protobuf_BoolValue, context: StatusOnlyCallContext) -> EventLoopFuture<Google_Protobuf_Empty> {
return context.eventLoop.makeSucceededFuture(Google_Protobuf_Empty())
}
func save_lidar(request: MotorControl_SaveRequest, context: StatusOnlyCallContext) -> EventLoopFuture<Google_Protobuf_Empty> {
return context.eventLoop.makeSucceededFuture(Google_Protobuf_Empty())
}
func lidar_stream(request: Persontracking_StreamMessage, context: StreamingResponseCallContext<Persontracking_PointScan>) -> EventLoopFuture<GRPCStatus> {
shouldScan = true
try! lidar.iterScans{scan in
_ = context.sendResponse(.with{protoScan in
protoScan.points = scan.map{ point in
Persontracking_Point.with{ protoPoint in
protoPoint.angle = Double(point.angle)
protoPoint.distance = Double(point.distance)
// Placeholder group number.
protoPoint.groupNumber = 0
}
}
})
return shouldScan
}
return context.eventLoop.makeSucceededFuture(.ok)
}
}

View File

@@ -19,8 +19,8 @@ class MotorProvider: MotorControl_CarControlProvider{
func set_throttle(request: MotorControl_ThrottleRequest, context: StatusOnlyCallContext) -> EventLoopFuture<MotorControl_ThrottleResponse> { func set_throttle(request: MotorControl_ThrottleRequest, context: StatusOnlyCallContext) -> EventLoopFuture<MotorControl_ThrottleResponse> {
self.vehicle.throttle = request.throttle self.vehicle.throttle = request.throttle
return context.eventLoop.makeSucceededFuture(.with{ return context.eventLoop.makeSucceededFuture(.with{ throttle in
$0.throttleSet = true throttle.throttleSet = true
}) })
} }

View File

@@ -7,6 +7,8 @@
import NIO import NIO
import GRPC import GRPC
import SwiftRPLidar
import SwiftSerial
func doServer() throws { func doServer() throws {
// Copied from examples // Copied from examples
@@ -16,13 +18,18 @@ func doServer() throws {
try! group.syncShutdownGracefully() try! group.syncShutdownGracefully()
} }
let lidar = createLidar()
lidar.iterMeasurements{measruement in
print(measruement.quality)
return false
}
// Create a provider using the features we read. // Create a provider using the features we read.
let provider = try MotorProvider(vehicle: getVehicle2D()) let provider = try MotorProvider(vehicle: getVehicle2D())
let trackingProvider = LidarProvider(lidar: lidar)
// Start the server and print its address once it has started. // Start the server and print its address once it has started.
let server = Server.insecure(group: group) let server = Server.insecure(group: group)
.withServiceProviders([provider]) .withServiceProviders([provider, trackingProvider])
.bind(host: "localhost", port: 0) .bind(host: "localhost", port: 0)
server.map { server.map {
@@ -37,11 +44,27 @@ func doServer() throws {
}.wait() }.wait()
} }
func createLidar() -> SwiftRPLidar{
return try! SwiftRPLidar(onPort: SerialPort(path: "/dev/cu.usbserial0001"))
}
// Entry-Point to the Swift Car Controller // Entry-Point to the Swift Car Controller
print("Starting Server") print("Starting Server")
do{ do{
try doServer() try doServer()
} }
catch{ catch{
print("Server failed") print("Server failed")
} }
extension SerialPort: LidarSerial{
public func setBaudrate(baudrate: Int) {
// TODO: handle different baudrates. Only need this for now.
switch baudrate{
default:
setSettings(receiveRate: .baud115200, transmitRate: .baud115200, minimumBytesToRead: 1)
}
}
}

View File

@@ -36,9 +36,9 @@ dependencies {
testImplementation 'junit:junit:4.12' testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.2.0' androidTestImplementation 'androidx.test:runner:1.2.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
implementation 'io.grpc:grpc-okhttp:1.28.1' // CURRENT_GRPC_VERSION implementation 'io.grpc:grpc-okhttp:1.29.0' // CURRENT_GRPC_VERSION
implementation 'io.grpc:grpc-protobuf-lite:1.28.1' // CURRENT_GRPC_VERSION implementation 'io.grpc:grpc-protobuf-lite:1.29.0' // CURRENT_GRPC_VERSION
implementation 'io.grpc:grpc-stub:1.28.1' // CURRENT_GRPC_VERSION implementation 'io.grpc:grpc-stub:1.29.0' // CURRENT_GRPC_VERSION
implementation 'javax.annotation:javax.annotation-api:1.2' implementation 'javax.annotation:javax.annotation-api:1.2'
implementation 'org.zeromq:jeromq:0.5.2' implementation 'org.zeromq:jeromq:0.5.2'
} }

View File

@@ -2,11 +2,11 @@ package org.vato.carcontroller.LIDAR;
import android.content.Context; import android.content.Context;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.Paint; import android.graphics.Paint;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.SurfaceHolder; import android.view.SurfaceHolder;
import android.view.SurfaceView; import android.view.SurfaceView;
@@ -17,9 +17,14 @@ import com.google.protobuf.Empty;
import org.vato.carcontroller.PersonTrackingGrpc; import org.vato.carcontroller.PersonTrackingGrpc;
import org.vato.carcontroller.PointScan; import org.vato.carcontroller.PointScan;
import org.vato.carcontroller.StreamMessage;
import org.vato.carcontroller.Updaters.AbstractUpdater; import org.vato.carcontroller.Updaters.AbstractUpdater;
import org.vato.carcontroller.Updaters.GrpcUpdater;
import org.vato.carcontroller.Updaters.ZmqUpdater; import org.vato.carcontroller.Updaters.ZmqUpdater;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import io.grpc.ManagedChannel; import io.grpc.ManagedChannel;
@@ -27,7 +32,8 @@ import io.grpc.ManagedChannelBuilder;
import io.grpc.stub.StreamObserver; import io.grpc.stub.StreamObserver;
public class LidarView extends SurfaceView public class LidarView extends SurfaceView
implements AbstractUpdater.MapChangedListener<PointScan> { implements AbstractUpdater.MapChangedListener<PointScan>,
GrpcUpdater.GrpcUpdateBootstrapper<PointScan> {
private static final String LIDAR_TOPIC = "lidar_map"; private static final String LIDAR_TOPIC = "lidar_map";
@@ -35,10 +41,12 @@ public class LidarView extends SurfaceView
private Thread lidarThread; private Thread lidarThread;
private String port; private String port;
private SurfaceHolder surfaceHolder; private SurfaceHolder surfaceHolder;
private boolean useGrpcStreams;
PersonTrackingGrpc.PersonTrackingStub stub; PersonTrackingGrpc.PersonTrackingStub stub;
private float timeBetweenMessages;
private Map<Integer, Paint> groupNumPaints = new HashMap<>();
private int mBitmapX, mBitmapY, mViewWidth, mViewHeight; private int mViewWidth, mViewHeight, centreX, centreY;
private Bitmap mBitmap;
public LidarView(Context context) { public LidarView(Context context) {
super(context); super(context);
@@ -60,8 +68,15 @@ public class LidarView extends SurfaceView
String host = prefs.getString("host", "10.0.0.53"); String host = prefs.getString("host", "10.0.0.53");
port = prefs.getString("zmqPort", "5050"); port = prefs.getString("zmqPort", "5050");
String gRPCPort = prefs.getString("port", "50051"); String gRPCPort = prefs.getString("port", "50051");
useGrpcStreams = prefs.getBoolean("use_grpc_streams", false);
timeBetweenMessages = prefs.getFloat("lidar_timeout", 0.1f);
if (useGrpcStreams) {
lidar = new GrpcUpdater<>(PointScan.getDefaultInstance().getParserForType(), this);
} else {
lidar = new ZmqUpdater<>(PointScan.getDefaultInstance().getParserForType(), LIDAR_TOPIC, lidar = new ZmqUpdater<>(PointScan.getDefaultInstance().getParserForType(), LIDAR_TOPIC,
host, port); host, port);
}
lidar.addMapChangedListener(this); lidar.addMapChangedListener(this);
surfaceHolder = getHolder(); surfaceHolder = getHolder();
lidarThread = new Thread(lidar); lidarThread = new Thread(lidar);
@@ -74,7 +89,16 @@ public class LidarView extends SurfaceView
* Called by MainActivity.onResume() to start a thread. * Called by MainActivity.onResume() to start a thread.
*/ */
public void resume() { public void resume() {
StreamObserver<Empty> response = new StreamObserver<Empty>() { if (useGrpcStreams) {
lidarThread.start();
} else {
doZmqLidarStream();
}
}
private void doZmqLidarStream() {
// use async grpc method, ZMQ doesn't need to connect straight away.
stub.startTracking(Empty.newBuilder().build(), new StreamObserver<Empty>() {
@Override @Override
public void onNext(Empty value) { public void onNext(Empty value) {
lidarThread.start(); lidarThread.start();
@@ -90,14 +114,16 @@ public class LidarView extends SurfaceView
public void onCompleted() { public void onCompleted() {
// Don't care. // Don't care.
} }
}; });
// use async grpc method, ZMQ doesn't need to connect straight away.
stub.startTracking(Empty.newBuilder().build(), response);
} }
@Override @Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) { protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh); super.onSizeChanged(w, h, oldw, oldh);
mViewWidth = w;
mViewHeight = h;
centreX = w / 2;
centreY = h / 2;
} }
@Override @Override
@@ -115,11 +141,26 @@ public class LidarView extends SurfaceView
public void stop() { public void stop() {
// TODO: Use grpc to tell zmq to stop.
lidar.stop(); lidar.stop();
StreamObserver<Empty> responseObserver = new StreamObserver<Empty>() {
@Override
public void onNext(Empty value) {
}
@Override
public void onError(Throwable t) {
Log.d("LIDAR", "Failed to stop SLAM", t);
}
@Override
public void onCompleted() {
}
};
stub.stopTracking(Empty.newBuilder().build(), responseObserver);
try { try {
lidarThread.join(1000); lidarThread.join(1000);
} catch (InterruptedException e) { } catch (InterruptedException e) {
Log.d("LIDAR", "Lidar failed to join", e);
} }
} }
@@ -129,21 +170,62 @@ public class LidarView extends SurfaceView
Canvas canvas = surfaceHolder.lockCanvas(); Canvas canvas = surfaceHolder.lockCanvas();
canvas.save(); canvas.save();
canvas.drawColor(Color.WHITE); canvas.drawColor(Color.WHITE);
for (Point point : points.getPointsList().stream().map(Point::fromProtoPoint).collect( // TODO: Do an initial pass to find the max distance, which will be a scale factor for the other points.
double maxDistance = 0;
for (org.vato.carcontroller.Point point : points.getPointsList()) {
if (point.getDistance() > maxDistance) {
maxDistance = point.getDistance();
}
}
final double maxDistanceFinal = maxDistance;
// Apply scaling factor from max distance.
for (Point point : points.getPointsList().stream().map(
point -> org.vato.carcontroller.Point.newBuilder(point).setDistance(
point.getDistance() / maxDistanceFinal * mViewHeight).build()).map(
Point::fromProtoPoint)
.collect(
Collectors.toList())) { Collectors.toList())) {
// Now for each point, draw a circle for the point (so it's big enough) in the correct spot, // Now for each point, draw a circle for the point (so it's big enough) in the correct spot,
// and create a colour for that point to paint it correctly. // and create a colour for that point to paint it correctly.
// TODO: Dynamically change the colour of the paint object based on the point group number. if (!groupNumPaints.containsKey(point.groupNumber)) {
canvas.drawCircle((float) point.x, (float) point.y, 5, new Paint()); Paint paint = new Paint();
paint.setColor(
Color.HSVToColor(new float[]{convertGroupNumberToHue(
point.groupNumber), 1f, 1f}));
groupNumPaints.put(point.groupNumber, paint);
}
canvas.drawCircle((float) point.x + centreX,
(float) point.y + centreY, 5,
Objects.requireNonNull(groupNumPaints
.get(point.groupNumber))); // Can't be null as we just added it.
} }
canvas.restore(); canvas.restore();
surfaceHolder.unlockCanvasAndPost(canvas); surfaceHolder.unlockCanvasAndPost(canvas);
} }
} }
/**
* @param groupNumber
* @return
*/
private static int convertGroupNumberToHue(int groupNumber) {
return (43 * groupNumber) % 360;
}
@Override
public void bootstrap(StreamObserver<PointScan> responseObserver) {
stub.lidarStream(
StreamMessage.newBuilder().setTimeBetweenMessages(timeBetweenMessages).build(),
responseObserver);
}
private static class Point { private static class Point {
private double x; private double x;
private double y; private double y;
private int groupNumber;
private Point(double x, double y) { private Point(double x, double y) {
this.x = x; this.x = x;
@@ -151,7 +233,9 @@ public class LidarView extends SurfaceView
} }
static Point fromProtoPoint(org.vato.carcontroller.Point point) { static Point fromProtoPoint(org.vato.carcontroller.Point point) {
return fromHist(point.getDistance(), point.getAngle()); Point p = fromHist(point.getDistance(), point.getAngle());
p.groupNumber = point.getGroupNumber();
return p;
} }
static Point fromHist(double distance, double angle) { static Point fromHist(double distance, double angle) {
@@ -159,8 +243,8 @@ public class LidarView extends SurfaceView
} }
static Point fromHist(double distance, double angle, Point offset) { static Point fromHist(double distance, double angle, Point offset) {
return new Point(distance * Math.sin(angle) + offset.x, return new Point(distance * Math.sin(Math.toRadians(angle)) + offset.x,
distance * Math.cos(angle) + offset.y); distance * Math.cos(Math.toRadians(angle)) + offset.y);
} }
} }

View File

@@ -7,6 +7,7 @@ import android.graphics.Canvas;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.Paint; import android.graphics.Paint;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.util.Log;
import android.view.SurfaceHolder; import android.view.SurfaceHolder;
import android.view.SurfaceView; import android.view.SurfaceView;
@@ -128,6 +129,20 @@ public class SlamView extends SurfaceView implements AbstractUpdater.MapChangedL
public void stop() { public void stop() {
// TODO: Use grpc to tell zmq to stop. // TODO: Use grpc to tell zmq to stop.
slam.stop(); slam.stop();
stub.stopStreaming(Empty.newBuilder().build(), new StreamObserver<Empty>() {
@Override
public void onNext(Empty value) {
}
@Override
public void onError(Throwable t) {
Log.d("SLAM", "Failed to stop SLAM", t);
}
@Override
public void onCompleted() {
}
});
try { try {
mapThread.join(1000); mapThread.join(1000);
} catch (InterruptedException e) { } catch (InterruptedException e) {

View File

@@ -10,13 +10,14 @@ import io.grpc.stub.StreamObserver;
public class GrpcUpdater<T extends MessageLite> extends AbstractUpdater<T> { public class GrpcUpdater<T extends MessageLite> extends AbstractUpdater<T> {
GrpcUpdateBootstrapper<T> bootstrapper; GrpcUpdateBootstrapper<T> bootstrapper;
public GrpcUpdater(Parser parser, GrpcUpdateBootstrapper bootstrapper) { public GrpcUpdater(Parser<T> parser, GrpcUpdateBootstrapper<T> bootstrapper) {
super(parser); super(parser);
this.bootstrapper = bootstrapper; this.bootstrapper = bootstrapper;
} }
@Override @Override
public void stop() { public void stop() {
// TODO... may not be needed here.
} }

View File

@@ -46,6 +46,14 @@
</PreferenceCategory> </PreferenceCategory>
<PreferenceCategory>
<EditTextPreference
android:defaultValue="0.1"
android:title="LiDAR time between scan fetches."
app:key="lidar_timeout"
app:useSimpleSummaryProvider="true" />
</PreferenceCategory>
<PreferenceCategory android:title="0MQ SLAM Connection"> <PreferenceCategory android:title="0MQ SLAM Connection">
<EditTextPreference <EditTextPreference
android:key="zmqPort" android:key="zmqPort"

View File

@@ -6,7 +6,7 @@ buildscript {
jcenter() jcenter()
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:3.6.3' classpath 'com.android.tools.build:gradle:4.0.1'
classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.10' classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.10'
// NOTE: Do not place your application dependencies here; they belong // NOTE: Do not place your application dependencies here; they belong

View File

@@ -1,296 +0,0 @@
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: raft.proto
import sys
_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1'))
from google.protobuf import descriptor as _descriptor
from google.protobuf import message as _message
from google.protobuf import reflection as _reflection
from google.protobuf import symbol_database as _symbol_database
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor.FileDescriptor(
name='raft.proto',
package='raft',
syntax='proto3',
serialized_options=None,
serialized_pb=_b('\n\nraft.proto\x12\x04raft\"\x7f\n\rAppendEntries\x12\x0c\n\x04term\x18\x01 \x01(\r\x12\x10\n\x08leaderId\x18\x02 \x01(\t\x12\x14\n\x0cprevLogIndex\x18\x03 \x01(\r\x12\x13\n\x0bprevLogTerm\x18\x04 \x01(\r\x12\x14\n\x0cleaderCommit\x18\x05 \x01(\r\x12\r\n\x05\x65ntry\x18\x06 \x03(\t\"6\n\x15\x41ppendEntriesResponse\x12\x0c\n\x04term\x18\x01 \x01(\r\x12\x0f\n\x07success\x18\x02 \x01(\x08\"[\n\x0bRequestVote\x12\x0c\n\x04term\x18\x01 \x01(\r\x12\x13\n\x0b\x63\x61ndidateId\x18\x02 \x01(\t\x12\x14\n\x0clastLogIndex\x18\x03 \x01(\r\x12\x13\n\x0blastLogTerm\x18\x04 \x01(\r\"I\n\x13RequestVoteResponse\x12\x0c\n\x04term\x18\x01 \x01(\r\x12\x13\n\x0bvoteGranted\x18\x02 \x01(\x08\x12\x0f\n\x07voterId\x18\x03 \x01(\t2\x90\x01\n\x04Raft\x12\x46\n\x10\x41ppendEntriesRPC\x12\x13.raft.AppendEntries\x1a\x1b.raft.AppendEntriesResponse\"\x00\x12@\n\x0eRequestVoteRPC\x12\x11.raft.RequestVote\x1a\x19.raft.RequestVoteResponse\"\x00\x62\x06proto3')
)
_APPENDENTRIES = _descriptor.Descriptor(
name='AppendEntries',
full_name='raft.AppendEntries',
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
name='term', full_name='raft.AppendEntries.term', index=0,
number=1, type=13, cpp_type=3, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='leaderId', full_name='raft.AppendEntries.leaderId', index=1,
number=2, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=_b("").decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='prevLogIndex', full_name='raft.AppendEntries.prevLogIndex', index=2,
number=3, type=13, cpp_type=3, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='prevLogTerm', full_name='raft.AppendEntries.prevLogTerm', index=3,
number=4, type=13, cpp_type=3, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='leaderCommit', full_name='raft.AppendEntries.leaderCommit', index=4,
number=5, type=13, cpp_type=3, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='entry', full_name='raft.AppendEntries.entry', index=5,
number=6, type=9, cpp_type=9, label=3,
has_default_value=False, default_value=[],
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
],
extensions=[
],
nested_types=[],
enum_types=[
],
serialized_options=None,
is_extendable=False,
syntax='proto3',
extension_ranges=[],
oneofs=[
],
serialized_start=20,
serialized_end=147,
)
_APPENDENTRIESRESPONSE = _descriptor.Descriptor(
name='AppendEntriesResponse',
full_name='raft.AppendEntriesResponse',
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
name='term', full_name='raft.AppendEntriesResponse.term', index=0,
number=1, type=13, cpp_type=3, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='success', full_name='raft.AppendEntriesResponse.success', index=1,
number=2, type=8, cpp_type=7, label=1,
has_default_value=False, default_value=False,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
],
extensions=[
],
nested_types=[],
enum_types=[
],
serialized_options=None,
is_extendable=False,
syntax='proto3',
extension_ranges=[],
oneofs=[
],
serialized_start=149,
serialized_end=203,
)
_REQUESTVOTE = _descriptor.Descriptor(
name='RequestVote',
full_name='raft.RequestVote',
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
name='term', full_name='raft.RequestVote.term', index=0,
number=1, type=13, cpp_type=3, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='candidateId', full_name='raft.RequestVote.candidateId', index=1,
number=2, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=_b("").decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='lastLogIndex', full_name='raft.RequestVote.lastLogIndex', index=2,
number=3, type=13, cpp_type=3, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='lastLogTerm', full_name='raft.RequestVote.lastLogTerm', index=3,
number=4, type=13, cpp_type=3, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
],
extensions=[
],
nested_types=[],
enum_types=[
],
serialized_options=None,
is_extendable=False,
syntax='proto3',
extension_ranges=[],
oneofs=[
],
serialized_start=205,
serialized_end=296,
)
_REQUESTVOTERESPONSE = _descriptor.Descriptor(
name='RequestVoteResponse',
full_name='raft.RequestVoteResponse',
filename=None,
file=DESCRIPTOR,
containing_type=None,
fields=[
_descriptor.FieldDescriptor(
name='term', full_name='raft.RequestVoteResponse.term', index=0,
number=1, type=13, cpp_type=3, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='voteGranted', full_name='raft.RequestVoteResponse.voteGranted', index=1,
number=2, type=8, cpp_type=7, label=1,
has_default_value=False, default_value=False,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor(
name='voterId', full_name='raft.RequestVoteResponse.voterId', index=2,
number=3, type=9, cpp_type=9, label=1,
has_default_value=False, default_value=_b("").decode('utf-8'),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR),
],
extensions=[
],
nested_types=[],
enum_types=[
],
serialized_options=None,
is_extendable=False,
syntax='proto3',
extension_ranges=[],
oneofs=[
],
serialized_start=298,
serialized_end=371,
)
DESCRIPTOR.message_types_by_name['AppendEntries'] = _APPENDENTRIES
DESCRIPTOR.message_types_by_name['AppendEntriesResponse'] = _APPENDENTRIESRESPONSE
DESCRIPTOR.message_types_by_name['RequestVote'] = _REQUESTVOTE
DESCRIPTOR.message_types_by_name['RequestVoteResponse'] = _REQUESTVOTERESPONSE
_sym_db.RegisterFileDescriptor(DESCRIPTOR)
AppendEntries = _reflection.GeneratedProtocolMessageType('AppendEntries', (_message.Message,), dict(
DESCRIPTOR = _APPENDENTRIES,
__module__ = 'raft_pb2'
# @@protoc_insertion_point(class_scope:raft.AppendEntries)
))
_sym_db.RegisterMessage(AppendEntries)
AppendEntriesResponse = _reflection.GeneratedProtocolMessageType('AppendEntriesResponse', (_message.Message,), dict(
DESCRIPTOR = _APPENDENTRIESRESPONSE,
__module__ = 'raft_pb2'
# @@protoc_insertion_point(class_scope:raft.AppendEntriesResponse)
))
_sym_db.RegisterMessage(AppendEntriesResponse)
RequestVote = _reflection.GeneratedProtocolMessageType('RequestVote', (_message.Message,), dict(
DESCRIPTOR = _REQUESTVOTE,
__module__ = 'raft_pb2'
# @@protoc_insertion_point(class_scope:raft.RequestVote)
))
_sym_db.RegisterMessage(RequestVote)
RequestVoteResponse = _reflection.GeneratedProtocolMessageType('RequestVoteResponse', (_message.Message,), dict(
DESCRIPTOR = _REQUESTVOTERESPONSE,
__module__ = 'raft_pb2'
# @@protoc_insertion_point(class_scope:raft.RequestVoteResponse)
))
_sym_db.RegisterMessage(RequestVoteResponse)
_RAFT = _descriptor.ServiceDescriptor(
name='Raft',
full_name='raft.Raft',
file=DESCRIPTOR,
index=0,
serialized_options=None,
serialized_start=374,
serialized_end=518,
methods=[
_descriptor.MethodDescriptor(
name='AppendEntriesRPC',
full_name='raft.Raft.AppendEntriesRPC',
index=0,
containing_service=None,
input_type=_APPENDENTRIES,
output_type=_APPENDENTRIESRESPONSE,
serialized_options=None,
),
_descriptor.MethodDescriptor(
name='RequestVoteRPC',
full_name='raft.Raft.RequestVoteRPC',
index=1,
containing_service=None,
input_type=_REQUESTVOTE,
output_type=_REQUESTVOTERESPONSE,
serialized_options=None,
),
])
_sym_db.RegisterServiceDescriptor(_RAFT)
DESCRIPTOR.services_by_name['Raft'] = _RAFT
# @@protoc_insertion_point(module_scope)

View File

@@ -1,63 +0,0 @@
# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
import grpc
import MyRaft.raft_pb2 as raft__pb2
class RaftStub(object):
# missing associated documentation comment in .proto file
pass
def __init__(self, channel):
"""Constructor.
Args:
channel: A grpc.Channel.
"""
self.AppendEntriesRPC = channel.unary_unary(
'/raft.Raft/AppendEntriesRPC',
request_serializer=raft__pb2.AppendEntries.SerializeToString,
response_deserializer=raft__pb2.AppendEntriesResponse.FromString,
)
self.RequestVoteRPC = channel.unary_unary(
'/raft.Raft/RequestVoteRPC',
request_serializer=raft__pb2.RequestVote.SerializeToString,
response_deserializer=raft__pb2.RequestVoteResponse.FromString,
)
class RaftServicer(object):
# missing associated documentation comment in .proto file
pass
def AppendEntriesRPC(self, request, context):
# missing associated documentation comment in .proto file
pass
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def RequestVoteRPC(self, request, context):
# missing associated documentation comment in .proto file
pass
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def add_RaftServicer_to_server(servicer, server):
rpc_method_handlers = {
'AppendEntriesRPC': grpc.unary_unary_rpc_method_handler(
servicer.AppendEntriesRPC,
request_deserializer=raft__pb2.AppendEntries.FromString,
response_serializer=raft__pb2.AppendEntriesResponse.SerializeToString,
),
'RequestVoteRPC': grpc.unary_unary_rpc_method_handler(
servicer.RequestVoteRPC,
request_deserializer=raft__pb2.RequestVote.FromString,
response_serializer=raft__pb2.RequestVoteResponse.SerializeToString,
),
}
generic_handler = grpc.method_handlers_generic_handler(
'raft.Raft', rpc_method_handlers)
server.add_generic_rpc_handlers((generic_handler,))

View File

@@ -1,28 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.id=":car" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="android-gradle" name="Android-Gradle">
<configuration>
<option name="GRADLE_PROJECT_PATH" value=":car" />
<option name="LAST_SUCCESSFUL_SYNC_AGP_VERSION" />
<option name="LAST_KNOWN_AGP_VERSION" />
</configuration>
</facet>
<facet type="java-gradle" name="Java-Gradle">
<configuration>
<option name="BUILD_FOLDER_PATH" value="$MODULE_DIR$/build" />
<option name="BUILDABLE" value="false" />
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.gradle" />
<excludeFolder url="file://$MODULE_DIR$/build" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Bundled Protobuf Distribution" level="application" />
</component>
</module>

Binary file not shown.

View File

@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-6.4.1-bin.zip
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists

2
gradlew vendored
View File

@@ -82,6 +82,7 @@ esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM. # Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
@@ -129,6 +130,7 @@ fi
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"` APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"` JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath # We build the pattern for arguments to be converted via cygpath

1
gradlew.bat vendored
View File

@@ -84,6 +84,7 @@ set CMD_LINE_ARGS=%*
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle @rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%

View File

@@ -16,7 +16,7 @@ message Int32Value{
message Point{ message Point{
double angle = 1; double angle = 1;
int32 distance = 2; double distance = 2;
int32 group_number = 3; int32 group_number = 3;
} }
@@ -24,6 +24,9 @@ message PointScan{
repeated Point points = 1; repeated Point points = 1;
} }
message StreamMessage{
float time_between_messages = 1;
}
service PersonTracking{ service PersonTracking{
rpc set_tracking_group(Int32Value) returns (google.protobuf.Empty) {} rpc set_tracking_group(Int32Value) returns (google.protobuf.Empty) {}
@@ -36,4 +39,6 @@ service PersonTracking{
rpc save_lidar(MotorControl.SaveRequest) returns (google.protobuf.Empty) {} rpc save_lidar(MotorControl.SaveRequest) returns (google.protobuf.Empty) {}
rpc lidar_stream(StreamMessage) returns (stream PointScan) {}
} }

View File

Before

Width:  |  Height:  |  Size: 408 B

After

Width:  |  Height:  |  Size: 408 B

View File

Before

Width:  |  Height:  |  Size: 419 B

After

Width:  |  Height:  |  Size: 419 B

View File

@@ -1,4 +1,7 @@
FROM python:3.6-slim FROM vato.ddns.net:8083/python:3
ARG PYPI_USERNAME
ARG PYPI_PASSWORD
RUN apt-get update RUN apt-get update
# OpenCV has a LOT of dependencies. # OpenCV has a LOT of dependencies.
@@ -17,14 +20,14 @@ RUN apt-get install -y \
&& rm -rf /var/lib/apt/lists/* && rm -rf /var/lib/apt/lists/*
COPY requirements.txt / COPY requirements.txt /
RUN pip install --trusted-host pypi.python.org -r requirements.txt RUN pip install --index-url https://${PYPI_USERNAME}:${PYPI_PASSWORD}@vato.ddns.net/nexus/repository/pypi-grouped/simple -r requirements.txt
WORKDIR /app WORKDIR /app
COPY . /app COPY ./src /app
# We aren't listening, just connecting, so probs won't need this. # We aren't listening, just connecting, so probs won't need this.
# EXPOSE 1883 # EXPOSE 1883
ENV PYTHONPATH=/app ENV PYTHONPATH=/app
CMD ["python", "DecisionSystem/CentralisedDecision/cameraserver.py", "-V", "/app/HandRecognitionMacbookFixed.mp4"] CMD ["python", "-m", "car"]

View File

@@ -1,9 +1,10 @@
numpy numpy
opencv-python opencv-python
six six
wheel
paho-mqtt paho-mqtt
u-msgpack-python u-msgpack-python
grpcio-tools grpcio-tools
rplidar rplidar
breezyslam
pyzmq pyzmq
wheel

View File

Before

Width:  |  Height:  |  Size: 13 MiB

After

Width:  |  Height:  |  Size: 13 MiB

View File

Before

Width:  |  Height:  |  Size: 1.9 MiB

After

Width:  |  Height:  |  Size: 1.9 MiB

View File

@@ -1,6 +1,6 @@
import car.slam.SlamController_pb2_grpc as grpc import car.slam.SlamController_pb2_grpc as grpc
import car.slam.SlamController_pb2 as proto import car.slam.SlamController_pb2 as proto
import car.empty_pb2 as empty import google.protobuf.empty_pb2 as empty
import car.slam.slam_streamer as slam import car.slam.slam_streamer as slam
from .slam_processor import SlamProcessor from .slam_processor import SlamProcessor

View File

@@ -1,10 +1,12 @@
import math import math
import numpy as np
from . import icp
class Group: class Group:
def __init__(self, number, points=[]): def __init__(self, number):
self._points = points self._points = []
self._number = number self._number = number
self._minX = None self._minX = None
self._maxX = None self._maxX = None
@@ -28,7 +30,7 @@ class Group:
def _update_min_max(self, new_point): def _update_min_max(self, new_point):
""" """
Updates the in and max points for this group. Updates the min and max points for this group.
This is to determine when assigning groups whether the This is to determine when assigning groups whether the
same group is selected. same group is selected.
""" """
@@ -104,35 +106,46 @@ def calc_groups(scan):
Returns Returns
------- -------
list ndarray
List of groups that were found. Array of groups that were found.
""" """
prevPoint = None prevPoint = None
currentGroup = None currentGroup = Group(0)
allGroups = [] allGroups = [currentGroup]
currentGroupNumber = 0 currentGroupNumber = 0
# assume the list is already sorted. # assume the list is already sorted.
for point in scan: for point in scan:
if prevPoint is None: if prevPoint is None:
prevPoint = point prevPoint = point
currentGroup.add_point(point)
continue continue
# Distances are in mm. # Distances are in mm.
# within 1cm makes a group. Will need to play around with this. # within 10cm makes a group. Will need to play around with this.
if (point[2] - prevPoint[2]) ** 2 < 10 ** 2: if (point[2] - prevPoint[2]) ** 2 < 100 ** 2:
if currentGroup is None:
currentGroup = Group(currentGroupNumber)
allGroups.append(currentGroup)
currentGroup.add_point(point) currentGroup.add_point(point)
else: else:
if currentGroup is not None:
currentGroupNumber += 1 currentGroupNumber += 1
currentGroup = None currentGroup = Group(currentGroupNumber)
currentGroup.add_point(point)
allGroups.append(currentGroup)
prevPoint = point prevPoint = point
return np.array(allGroups)
return allGroups
def calc_groups_edge_algorithm(scan):
"""
Calculates groups using an edge algorithm. This takes advantage of numpy arrays
and vectorisation, rather than the primitive python loop grouping, resulting in
faster grouping speeds.
"""
allGroups = []
scanArray = np.array(scan)
def edge_algorithm():
pass
def find_centre(group): def find_centre(group):
@@ -156,13 +169,59 @@ def assign_groups(prev_groups, new_groups):
""" """
Assigns group numbers to a new scan based on the groups of an old scan. Assigns group numbers to a new scan based on the groups of an old scan.
""" """
max_group_number = 0
unassigned_groups = []
for group in prev_groups: for group in prev_groups:
old_centre = find_centre(group) old_centre = find_centre(group)
for new_group in new_groups: for new_group in new_groups:
new_centre = find_centre(new_group) new_centre = find_centre(new_group)
# They are considered the same if the new group and old group centres are within 5cm. # They are considered the same if the new group and old group centres are within 10cm.
if ((new_centre[0] - old_centre[0]) ** 2 + (new_centre[1] - old_centre[1]) ** 2) < 50 ** 2: if ((new_centre[0] - old_centre[0]) ** 2 + (new_centre[1] - old_centre[1]) ** 2) < 50 ** 2:
new_group.number = group.number new_group.number = group.number
if group.number > max_group_number:
max_group_number = group.number
continue
# If this is reached, then no matching groups were found.
unassigned_groups.append(new_group)
for group in unassigned_groups:
max_group_number += 1
group.number = max_group_number
return new_groups
def assign_groups_II(prev_groups, new_groups):
"""
Performs the assign groups algorithm, but instead of being greedy to assign, it will match up the
closest groups for each group.
Additionally, the centre of mass for a group of points is now used, which is less prone to the effects of
outliers as the existing find_centre algorithm.
An ICP rotation/translation is not made in this algorithm, as it's assumed that the scans are quick enough for
there to not be a significant difference between scans that would require ICP.
"""
max_group_number = 0
unassigned_groups = []
def centres_from_groups(groups):
return np.array([icp.calc_mass_centre(np.array([convert_lidar_to_cartesian(point) for point in group.get_points()])) for group in groups])
old_group_centres = centres_from_groups(prev_groups)
old_group_indexes = np.arange(len(old_group_centres))
new_group_centers = centres_from_groups(new_groups)
new_group_indexes = np.arange(len(new_group_centers))
closest_points = icp.closest_points(new_group_centers, old_group_centres)
# Now assign the new groups to the closest matching old group, if the distance is within a certain threshold.
for i, point in enumerate(closest_points):
matching_groups = prev_groups[old_group_centres == point]
# TODO: Check the centres are within a certain threshold.
new_groups[i].number = prev_groups[0].number
# TODO: Go through to put all groups into one (if multiple groups get same number) to avoid splits.
return new_groups return new_groups

View File

@@ -1,6 +1,6 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
'''Animates distances and measurment quality''' '''Animates distances and measurment quality'''
from car.tracking.mock_lidar import MockLidar from car.tracking..devices.mock_lidar import MockLidar
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
import numpy as np import numpy as np
import matplotlib.animation as animation import matplotlib.animation as animation

View File

@@ -2,7 +2,7 @@
Animates distances and angle of lidar Animates distances and angle of lidar
Uses model-free algorithms to track grouping of points (objects/groups) Uses model-free algorithms to track grouping of points (objects/groups)
""" """
from tracking.mock_lidar import MockLidar from car.tracking.devices.mock_lidar import MockLidar
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
import numpy as np import numpy as np
import matplotlib.animation as animation import matplotlib.animation as animation
@@ -35,7 +35,7 @@ class Bunch:
def run(): def run():
lidar = MockLidar(loader.load_scans_bytes_file("tracking/out.pickle")) lidar = MockLidar(loader.load_scans_bytes_file("pycar/src/car/tracking/out.pickle"))
fig = plt.figure() fig = plt.figure()
ax = plt.subplot(111, projection='polar') ax = plt.subplot(111, projection='polar')
line = ax.scatter([0, 0], [0, 0], s=5, c=[IMIN, IMAX], line = ax.scatter([0, 0], [0, 0], s=5, c=[IMIN, IMAX],

View File

@@ -3,10 +3,9 @@ from .. import lidar_loader as loader
import os import os
MOCK_DEVICE = "LIDAR_MOCK" MOCK_DEVICE = "LIDAR_MOCK"
RPLIDAR = "LIDAR_RPLIDAR"
def get_lidar(device=None, connection='/dev/ttyUSB0'): def get_lidar(device=None):
actual_device = None actual_device = None
try: try:
actual_device = device if device is not None else os.environ["CAR_LIDAR"] actual_device = device if device is not None else os.environ["CAR_LIDAR"]
@@ -14,17 +13,14 @@ def get_lidar(device=None, connection='/dev/ttyUSB0'):
print( print(
'No lidar device specified and the CAR_LIDAR environment variable is not set.') 'No lidar device specified and the CAR_LIDAR environment variable is not set.')
if actual_device == MOCK_DEVICE: if actual_device == MOCK_DEVICE:
return MockLidar(loader.load_scans_bytes_file("car/src/car/tracking/out.pickle")) return MockLidar(loader.load_scans_bytes_file("pycar/src/car/tracking/out.pickle"))
elif actual_device == RPLIDAR: elif actual_device != '':
try: try:
# TODO: Cleanup connection setting, probably don't need to pass it into the method.
from rplidar import RPLidar from rplidar import RPLidar
if "LIDAR_DEVICE" in os.environ: return RPLidar(device)
return RPLidar(os.environ['LIDAR_DEVICE'])
return RPLidar(connection)
except ImportError: except ImportError:
print('Could not import RPLidar. Have you downloaded rplidar?') print('Could not import RPLidar. Have you downloaded rplidar?')
else: else:
print('No valid lidar device found. Please choose one of ' + print('No valid lidar device found. Please choose ' +
MOCK_DEVICE + ' or ' + RPLIDAR) MOCK_DEVICE + ' or a dn address for the lidar device.')
return None return None

Some files were not shown because too many files have changed in this diff Show More