Skip to content

Commit

Permalink
Made performance improvements, trippled speed. Named each thread.
Browse files Browse the repository at this point in the history
  • Loading branch information
KevinPaulsen committed Aug 12, 2018
1 parent c5780f7 commit 092c759
Show file tree
Hide file tree
Showing 2 changed files with 115 additions and 52 deletions.
161 changes: 114 additions & 47 deletions src/main/java/com/apw/carcontrol/MrModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,40 @@
import java.awt.event.KeyListener;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import javax.swing.JFrame;
import org.jetbrains.annotations.NotNull;

public class MrModule extends JFrame implements Runnable, KeyListener {

private ExecutorService steeringExec = Executors.newSingleThreadExecutor(new NamedThreadFactory("steering"));
private ExecutorService speedExec = Executors.newSingleThreadExecutor(new NamedThreadFactory("speed"));
private ExecutorService imageRGBExec = Executors.newSingleThreadExecutor(new NamedThreadFactory("imageRGB"));
private ExecutorService imageBWExec = Executors.newSingleThreadExecutor(new NamedThreadFactory("imageBW"));
private ExecutorService imageSimpleExec = Executors.newSingleThreadExecutor(new NamedThreadFactory("imageSimple"));
private ExecutorService cameraImageExec = Executors.newSingleThreadExecutor(new NamedThreadFactory("cameraReader"));
private PWMController driveSys = new ArduinoIO();
private ArrayList<Module> modules = new ArrayList<>(); // Contains each module
private List<Module> modules = new ArrayList<>(); // Contains each module
private final WindowModule windowModule;
private final ArduinoModule arduinoModule;
private final ImageManagementModule imageManagementModule;
private final SpeedControlModule speedControlModule;
private final SteeringModule steeringModule;
private final CarControl carControl; // A CarControl that holds data for each module
private CarControl speedControl; // A CarControl that holds data specifically for speed
private CarControl steeringControl; // A CarControl that holds data specifically for steering
private long frameNumber = 0L;
private long lastTime = 0L;

private boolean initialized = false;

Expand All @@ -49,7 +67,14 @@ private MrModule(boolean realCam, boolean hasWindow) {
final int winHeight = carControl.getImageHeight();
carControl.updateWindowDims(getWidth(), getHeight());

createModules(hasWindow, winWidth, winHeight);
// Create modules
windowModule = createWindowModule(hasWindow, winWidth, winHeight);
arduinoModule = new ArduinoModule(driveSys);
imageManagementModule = new ImageManagementModule(winWidth, winHeight, carControl.getTile());
speedControlModule = new SpeedControlModule();
steeringModule = new SteeringModule();

initializeModules(windowModule, arduinoModule, imageManagementModule, speedControlModule, steeringModule);

headlessInit();
}
Expand All @@ -59,7 +84,7 @@ private MrModule(boolean realCam, boolean hasWindow) {
*/
private void headlessInit() {
// driveSys = new ArduinoIO();
final ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
final ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory("Frame Scheduler"));
executorService.scheduleAtFixedRate(this, initDelay, Math.round(1000.0 / FPS), TimeUnit.MILLISECONDS);

Future run = executorService.submit(this);
Expand All @@ -71,18 +96,8 @@ private void headlessInit() {
}
}

private void createModules(boolean useWindowModule, int winWidth, int winHeight) {
if(useWindowModule) {
WindowModule windowModule = new WindowModule(winWidth, winHeight);
windowModule.addKeyListener(this);
modules.add(windowModule);
}

modules.add(new ImageManagementModule(winWidth, winHeight, carControl.getTile()));
modules.add(new SpeedControlModule());
modules.add(new SteeringModule());
modules.add(new ArduinoModule(driveSys));
//modules.add(new LatencyTestModule());
private void initializeModules(Module... moduleArray) {
modules = Arrays.asList(moduleArray);

for (Module module : modules) {
module.initialize(carControl);
Expand All @@ -91,6 +106,17 @@ private void createModules(boolean useWindowModule, int winWidth, int winHeight)
initialized = true;
}

private WindowModule createWindowModule(boolean useWindowModule, int winWidth, int winHeight) {
final WindowModule winModule;
if (useWindowModule) {
winModule = new WindowModule(winWidth, winHeight);
winModule.addKeyListener(this);
} else {
winModule = null;
}
return winModule;
}

/**
* <p>
* Update method is called once every FPS.
Expand All @@ -99,48 +125,69 @@ private void createModules(boolean useWindowModule, int winWidth, int winHeight)
* run after ImageManagement process their respective image.
* </p>
*/
private void update() {
private void update(long frameNumber) {
//read the camera image, and update windowModule.
carControl.readCameraImage();
carControl.setEdges(getInsets());
modules.get(0).update(carControl);
modules.get(4).update(carControl);
CompletableFuture<Void> cameraImage = CompletableFuture
.runAsync(() -> {
carControl.readCameraImage();
carControl.setEdges(getInsets());
windowModule.update(carControl);
arduinoModule.update(carControl);
}, cameraImageExec);

// FIXME: Does not print exceptions to console.
ImageManagementModule imageModule = (ImageManagementModule) modules.get(1);

// Start Thread to get the RGB image. (for camera)
CompletableFuture<CarControl> futureRGBImage = CompletableFuture.supplyAsync(() -> {
carControl.setRGBImage(imageModule.getRGBRaster(carControl.getRecentCameraImage()));
carControl.setRenderedImage(carControl.getRGBImage());
return carControl;
});
final byte[] recentImage = carControl.getRecentCameraImage();

// Start Thread to get the black and white image (for steering)
CompletableFuture<CarControl> futureBWImage = CompletableFuture.supplyAsync(() -> {
steeringControl.setRGBImage(imageModule.getBlackWhiteRaster(carControl.getRecentCameraImage()));
return steeringControl;
});
// Start Thread to get the simple image (for speed)
CompletableFuture<CarControl> futureSimpleImage = CompletableFuture.supplyAsync(() -> {
speedControl.setProcessedImage(imageModule.getSimpleColorRaster(carControl.getRecentCameraImage()));
return speedControl;
});

// Call steering Module after futureBWImage is finished
CompletableFuture<Void> futureSteering = futureBWImage.thenAcceptAsync(carControl -> modules.get(3).update(carControl));
CompletableFuture<Void> futureSteering = cameraImage
.thenApplyAsync(v -> setBWImage(recentImage), imageBWExec)
// Call steering Module after futureBWImage is finished
.thenAcceptAsync(steeringModule::update, steeringExec);

CompletableFuture<CarControl> futureRGBImage = CompletableFuture.completedFuture(null);
if (frameNumber % 2 == 1) {
futureRGBImage = cameraImage
.thenApplyAsync(v -> setRGBImage(recentImage), imageRGBExec);
}

// Call speed module after futureSimpleImage is finished
CompletableFuture<Void> futureSpeed = futureSimpleImage.thenAcceptAsync(carControl -> modules.get(2).update(carControl));
CompletableFuture<Void> futureSpeed = CompletableFuture.completedFuture(null);
if (frameNumber % 3 == 1) {
// Start Thread to get the simple image (for speed)
futureSpeed = cameraImage
.thenApplyAsync(v -> setSimpleImage(recentImage), imageSimpleExec)
.thenAcceptAsync(speedControlModule::update, speedExec);
}

// Run when all finished.
CompletableFuture.allOf(futureSpeed, futureSteering, futureRGBImage)
.thenAccept(v -> paint())
.exceptionally(ex -> {
System.out.println(ex.getMessage());
ex.printStackTrace();
return null;
})
.join();

}

private CarControl setRGBImage(byte[] recentImage) {
carControl.setRGBImage(imageManagementModule.getRGBRaster(recentImage));
carControl.setRenderedImage(carControl.getRGBImage());
return carControl;
}

private CarControl setBWImage(byte[] recentImage) {
steeringControl.setRGBImage(imageManagementModule.getBlackWhiteRaster(recentImage));
return steeringControl;
}

private CarControl setSimpleImage(byte[] recentImage) {
speedControl.setProcessedImage(imageManagementModule.getSimpleColorRaster(recentImage));
return speedControl;
}

private void paint() {
if (!modules.isEmpty()) {
for (Module module : modules) {
Expand All @@ -151,16 +198,24 @@ private void paint() {

@Override
public void run() {
if(!initialized) {
return;
if (initialized) {
//printElapsedTime();
try {
update(++frameNumber);
//paint();
} catch (Exception e) {
e.printStackTrace();
}
}
}

try {
update();
//paint();
} catch(Exception e) {
e.printStackTrace();
private void printElapsedTime() {
final long curTime = System.currentTimeMillis();
if (lastTime == 0) {
lastTime = curTime;
}
System.out.println("Time: " + (lastTime - curTime));
lastTime = curTime;
}

public static void main(String[] args) {
Expand Down Expand Up @@ -196,4 +251,16 @@ public void keyReleased(KeyEvent e) { }
@Override
public void keyTyped(KeyEvent e) { }

public static class NamedThreadFactory implements ThreadFactory {
private final String name;

public NamedThreadFactory(String name) {
this.name = name;
}

@Override
public Thread newThread(@NotNull Runnable r) {
return new Thread(r, name);
}
}
}
6 changes: 1 addition & 5 deletions src/main/java/com/apw/speedcon/SpeedControlModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,14 @@
import com.apw.carcontrol.CamControl;
import com.apw.carcontrol.CarControl;
import com.apw.carcontrol.Module;
import com.apw.imagemanagement.ImageManipulator;
import com.apw.pedestrians.Constant;
import com.apw.pedestrians.PedestrianDetector;
import com.apw.pedestrians.blobtrack.MovingBlob;
import com.apw.pedestrians.image.Color;
import com.apw.pedestrians.image.Pixel;
import com.apw.sbcio.PWMController;
import com.apw.sbcio.fakefirm.ArduinoIO;

import java.awt.*;
import java.awt.event.KeyEvent;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

Expand Down Expand Up @@ -98,7 +94,7 @@ public void update(CarControl control) {

onUpdate(control);
control.accelerate(true, (int) Math.min(Constants.MAX_SPEED, getNextSpeed()));
System.out.println("getNextSpeed(): " + (int) Math.min(Constants.MAX_SPEED, getNextSpeed()));
//System.out.println("getNextSpeed(): " + (int) Math.min(Constants.MAX_SPEED, getNextSpeed()));
}

@Override
Expand Down

0 comments on commit 092c759

Please sign in to comment.