Files
picar/app/src/main/java/com/example/carcontroller/SLAM/SlamView.java

135 lines
4.3 KiB
Java

package com.example.carcontroller.SLAM;
import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import androidx.preference.PreferenceManager;
import com.example.carcontroller.Empty;
import com.example.carcontroller.SlamControlGrpc;
import com.example.carcontroller.SlamDetails;
import com.example.carcontroller.SlamLocation;
import com.google.protobuf.ByteString;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import io.grpc.stub.StreamObserver;
public class SlamView extends SurfaceView implements SlamUpdater.MapChangedListener {
private SlamUpdater slam;
private Thread mapThread;
private Context context;
private int width;
private SurfaceHolder surfaceHolder;
private Paint paint;
private SlamControlGrpc.SlamControlStub stub;
private ManagedChannel channel;
private int mapSizePixels;
private int mapSizeMeters;
public SlamView(Context context) {
super(context);
this.context = context;
init();
}
public SlamView(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
init();
}
public SlamView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.context = context;
init();
}
private void init() {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
String host = prefs.getString("host", "10.0.0.53");
String port = prefs.getString("zmqPort", "5050");
String gRPCPort = prefs.getString("port", "50051");
mapSizePixels = Integer.parseInt(prefs.getString("MAPSIZEPIXELS", "540"));
mapSizeMeters = Integer.parseInt(prefs.getString("MAPSIZEMETRES", "10"));
slam = new ZmqSlamUpdater(host, port);
slam.addMapChangedListener(this);
surfaceHolder = getHolder();
paint = new Paint();
paint.setColor(Color.BLUE);
mapThread = new Thread(slam);
channel = ManagedChannelBuilder.forAddress(host, Integer.parseInt(gRPCPort)).usePlaintext().build();
stub = SlamControlGrpc.newStub(channel);
}
/**
* Called by MainActivity.onResume() to start a thread.
*/
public void resume() {
StreamObserver<Empty> response = new StreamObserver<Empty>() {
@Override
public void onNext(Empty value) {
mapThread.start();
}
@Override
public void onError(Throwable t) {
// TODO: close the activity,
System.out.println(t.getMessage());
}
@Override
public void onCompleted() {
// Don't care.
}
};
// use async grpc method, ZMQ doesn't need to connect straight away.
stub.startMapStreaming(SlamDetails.newBuilder().setMapSizePixels(mapSizePixels).setMapSizeMeters(mapSizeMeters).build(), response);
}
public void stop() {
// Use grpc to tell the loader to stop. Interrupt the loader thread as well.
slam.stop();
try {
mapThread.join();
} catch (InterruptedException e) {
}
}
@Override
public void mapChanged(ByteString map, SlamLocation location) {
if (surfaceHolder.getSurface().isValid()) {
Canvas canvas = surfaceHolder.lockCanvas();
canvas.save();
canvas.drawColor(Color.WHITE);
// Using width as we want square.
Bitmap bitmap = Bitmap.createBitmap(width, width, Bitmap.Config.ALPHA_8);
for (int i = 0; i < width; i++) {
for (int j = 0; j < width; j++) {
// 0-255 is appropriate for the config used.
bitmap.setPixel(i, j, map.byteAt(i * width + j));
}
}
canvas.drawBitmap(bitmap, 0, 0, paint);
canvas.restore();
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
@Override
protected void onSizeChanged(int w, int b, int oldW, int oldB) {
super.onSizeChanged(w, b, oldW, oldB);
width = w;
}
}