Provide a generic way to receive zmq updates for lidar and slam.

This commit is contained in:
Piv
2020-03-22 19:01:40 +10:30
parent dc832d8a5d
commit 03f6c2b9f7
12 changed files with 97 additions and 75 deletions

2
.idea/misc.xml generated
View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK"> <component name="ProjectRootManager" version="2" languageLevel="JDK_1_9" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" /> <output url="file://$PROJECT_DIR$/build/classes" />
</component> </component>
<component name="ProjectType"> <component name="ProjectType">

View File

@@ -19,8 +19,8 @@ android {
} }
} }
compileOptions { compileOptions {
sourceCompatibility = 1.8 sourceCompatibility = 9.8
targetCompatibility = 1.8 targetCompatibility = 9.8
} }
} }

View File

@@ -13,7 +13,7 @@
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/AppTheme"> android:theme="@style/AppTheme">
<activity android:name=".SLAM.SlamController"></activity> <activity android:name=".SLAM.SlamController"></activity>
<activity android:name=".LidarTrackingController" /> <activity android:name=".LIDAR.LidarTrackingController" />
<activity <activity
android:name=".SettingsActivity" android:name=".SettingsActivity"
android:label="@string/title_activity_settings" android:label="@string/title_activity_settings"

View File

@@ -1,8 +1,10 @@
package com.example.carcontroller; package com.example.carcontroller.LIDAR;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle; import com.example.carcontroller.R;
public class LidarTrackingController extends AppCompatActivity { public class LidarTrackingController extends AppCompatActivity {

View File

@@ -1,4 +1,4 @@
package com.example.carcontroller; package com.example.carcontroller.LIDAR;
import android.content.Context; import android.content.Context;
import android.graphics.Bitmap; import android.graphics.Bitmap;
@@ -8,6 +8,8 @@ import android.view.MotionEvent;
import android.view.SurfaceHolder; import android.view.SurfaceHolder;
import android.view.SurfaceView; import android.view.SurfaceView;
import com.example.carcontroller.PersonTrackingGrpc;
public class LidarView extends SurfaceView implements Runnable { public class LidarView extends SurfaceView implements Runnable {
private boolean running; private boolean running;

View File

@@ -1,22 +1,17 @@
package com.example.carcontroller; package com.example.carcontroller;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.view.Menu; import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.widget.SeekBar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import com.example.carcontroller.LIDAR.LidarTrackingController;
import com.example.carcontroller.SLAM.SlamController; import com.example.carcontroller.SLAM.SlamController;
import java.util.concurrent.CountDownLatch;
import io.grpc.stub.StreamObserver;
public class MainActivity extends AppCompatActivity { public class MainActivity extends AppCompatActivity {

View File

@@ -1,36 +0,0 @@
package com.example.carcontroller.SLAM;
import com.example.carcontroller.SlamLocation;
import com.example.carcontroller.SlamScan;
import com.google.protobuf.ByteString;
import java.util.HashSet;
import java.util.Set;
public abstract class SlamUpdater implements Runnable {
private Set<MapChangedListener> listeners;
public SlamUpdater() {
init();
}
protected void init() {
listeners = new HashSet<>();
}
public void addMapChangedListener(MapChangedListener listener) {
listeners.add(listener);
}
protected void fireMapChanged(SlamScan scan) {
listeners.forEach(listener -> listener.mapChanged(scan.getMap(), scan.getLocation()));
}
public abstract void stop();
public interface MapChangedListener {
void mapChanged(ByteString map, SlamLocation location);
}
}

View File

@@ -16,21 +16,25 @@ import com.example.carcontroller.Empty;
import com.example.carcontroller.SlamControlGrpc; import com.example.carcontroller.SlamControlGrpc;
import com.example.carcontroller.SlamDetails; import com.example.carcontroller.SlamDetails;
import com.example.carcontroller.SlamLocation; import com.example.carcontroller.SlamLocation;
import com.example.carcontroller.SlamScan;
import com.example.carcontroller.Updaters.AbstractUpdater;
import com.example.carcontroller.Updaters.ZmqUpdater;
import com.google.protobuf.ByteString; import com.google.protobuf.ByteString;
import io.grpc.ManagedChannel; import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder; import io.grpc.ManagedChannelBuilder;
import io.grpc.stub.StreamObserver; import io.grpc.stub.StreamObserver;
public class SlamView extends SurfaceView implements SlamUpdater.MapChangedListener { public class SlamView extends SurfaceView implements AbstractUpdater.MapChangedListener<SlamScan> {
private SlamUpdater slam; private static final String SLAM_TOPIC = "slam_map";
private AbstractUpdater<SlamScan> slam;
private Thread mapThread; private Thread mapThread;
private Context context; private Context context;
private SurfaceHolder surfaceHolder; private SurfaceHolder surfaceHolder;
private Paint paint; private Paint paint;
private SlamControlGrpc.SlamControlStub stub; private SlamControlGrpc.SlamControlStub stub;
private ManagedChannel channel;
private int mapSizePixels; private int mapSizePixels;
private int mapSizeMeters; private int mapSizeMeters;
private String port; private String port;
@@ -60,15 +64,14 @@ public class SlamView extends SurfaceView implements SlamUpdater.MapChangedListe
String gRPCPort = prefs.getString("port", "50051"); String gRPCPort = prefs.getString("port", "50051");
mapSizePixels = Integer.parseInt(prefs.getString("MAPSIZEPIXELS", "540")); mapSizePixels = Integer.parseInt(prefs.getString("MAPSIZEPIXELS", "540"));
mapSizeMeters = Integer.parseInt(prefs.getString("MAPSIZEMETRES", "10")); mapSizeMeters = Integer.parseInt(prefs.getString("MAPSIZEMETRES", "10"));
slam = new ZmqSlamUpdater(host, port); slam = new ZmqUpdater<>(SlamScan.getDefaultInstance().getParserForType(), SLAM_TOPIC, host, port);
slam.addMapChangedListener(this); slam.addMapChangedListener(this);
surfaceHolder = getHolder(); surfaceHolder = getHolder();
paint = new Paint(); paint = new Paint();
paint.setColor(Color.BLUE); paint.setColor(Color.BLUE);
mapThread = new Thread(slam); mapThread = new Thread(slam);
channel = ManagedChannelBuilder.forAddress(host, Integer.parseInt(gRPCPort)).usePlaintext().build(); ManagedChannel channel = ManagedChannelBuilder.forAddress(host, Integer.parseInt(gRPCPort)).usePlaintext().build();
stub = SlamControlGrpc.newStub(channel); stub = SlamControlGrpc.newStub(channel);
} }
/** /**
@@ -106,12 +109,15 @@ public class SlamView extends SurfaceView implements SlamUpdater.MapChangedListe
try { try {
mapThread.join(); mapThread.join();
} catch (InterruptedException e) { } catch (InterruptedException e) {
} }
} }
@Override @Override
public void mapChanged(ByteString map, SlamLocation location) { public void mapChanged(SlamScan scan) {
updateView(scan.getMap(), scan.getLocation());
}
private void updateView(ByteString map, SlamLocation location) {
if (surfaceHolder.getSurface().isValid()) { if (surfaceHolder.getSurface().isValid()) {
Canvas canvas = surfaceHolder.lockCanvas(); Canvas canvas = surfaceHolder.lockCanvas();
canvas.save(); canvas.save();

View File

@@ -0,0 +1,51 @@
package com.example.carcontroller.Updaters;
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.MessageLite;
import com.google.protobuf.Parser;
import java.util.HashSet;
import java.util.Set;
/**
* Provides an abstract way to receive updates from a remote host (i.e. the rc car).
* Subclasses of this implement the approriate connection mechanisms to continuously receive
* new updates of messages.
* Specifically, protobuf serialisation support is provided
*
* @param <T> The message type that will continuously be received
*/
public abstract class AbstractUpdater<T extends MessageLite> implements Runnable {
private Set<MapChangedListener<T>> listeners;
private Parser<T> parser;
public AbstractUpdater(Parser<T> parser) {
this.parser = parser;
init();
}
protected void init() {
listeners = new HashSet<>();
}
public void addMapChangedListener(MapChangedListener<T> listener) {
listeners.add(listener);
}
protected void fireMapChanged(T scan) {
listeners.forEach(listener -> listener.mapChanged(scan));
}
public abstract void stop();
public interface MapChangedListener<T extends MessageLite> {
void mapChanged(T points);
}
protected T parseMessage(byte[] messageBytes) throws InvalidProtocolBufferException {
return parser.parseFrom(messageBytes);
}
}

View File

@@ -1,7 +1,8 @@
package com.example.carcontroller.SLAM; package com.example.carcontroller.Updaters;
import com.example.carcontroller.SlamScan;
import com.google.protobuf.InvalidProtocolBufferException; import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.MessageLite;
import com.google.protobuf.Parser;
import org.zeromq.SocketType; import org.zeromq.SocketType;
import org.zeromq.ZContext; import org.zeromq.ZContext;
@@ -10,20 +11,21 @@ import org.zeromq.ZMQ;
import java.util.Arrays; import java.util.Arrays;
/** /**
* Connects to Pi and retrieves updates of the SLAM map, * Provides a way to easily deal with zeromq sub sockets that use protobuf
* notifying listeners of changes to the map when they arrive. *
* Uses 0MQ for the transport. * @param <T>
*/ */
public class ZmqSlamUpdater extends SlamUpdater { public class ZmqUpdater<T extends MessageLite> extends AbstractUpdater<T> {
private ZContext context; private ZContext context;
private String host; private String host;
private String port; private String port;
private boolean running = false; private boolean running = false;
private static final byte[] SLAM_SUBSCRIPTION = "slam_map".getBytes(); private final byte[] SUBSCRIPTION;
public ZmqSlamUpdater(String host, String port) { public ZmqUpdater(Parser<T> parser, String topic, String host, String port) {
super(); super(parser);
this.SUBSCRIPTION = topic.getBytes();
this.host = host; this.host = host;
this.port = port; this.port = port;
init(); init();
@@ -42,12 +44,12 @@ public class ZmqSlamUpdater extends SlamUpdater {
// Receive map from zmq and update appropriately. // Receive map from zmq and update appropriately.
try (ZMQ.Socket socket = context.createSocket(SocketType.SUB)) { try (ZMQ.Socket socket = context.createSocket(SocketType.SUB)) {
socket.connect("tcp://" + host + ":" + port); socket.connect("tcp://" + host + ":" + port);
socket.subscribe(SLAM_SUBSCRIPTION); socket.subscribe(SUBSCRIPTION);
while (running) { while (running) {
byte[] map = socket.recv(); byte[] map = socket.recv();
// Don't want to do the event when we just receive the header. // Don't want to do the event when we just receive the header.
if (!Arrays.equals(map, SLAM_SUBSCRIPTION)) { if (!Arrays.equals(map, SUBSCRIPTION)) {
fireMapChanged(SlamScan.parseFrom(map)); fireMapChanged(parseMessage(map));
} }
} }
} catch (InvalidProtocolBufferException e) { } catch (InvalidProtocolBufferException e) {

View File

@@ -4,9 +4,9 @@
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
tools:context=".LidarTrackingController"> tools:context=".LIDAR.LidarTrackingController">
<com.example.carcontroller.LidarView <com.example.carcontroller.LIDAR.LidarView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:id="@+id/lidarMap"/> android:id="@+id/lidarMap"/>

View File

@@ -4,7 +4,7 @@
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
tools:context=".LidarTrackingController"> tools:context=".LIDAR.LidarTrackingController">
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"