Skip to content

Commit 092c759

Browse files
committed
Made performance improvements, trippled speed. Named each thread.
1 parent c5780f7 commit 092c759

2 files changed

Lines changed: 115 additions & 52 deletions

File tree

src/main/java/com/apw/carcontrol/MrModule.java

Lines changed: 114 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,40 @@
1212
import java.awt.event.KeyListener;
1313

1414
import java.util.ArrayList;
15+
import java.util.Arrays;
16+
import java.util.List;
1517
import java.util.Map;
1618
import java.util.concurrent.CompletableFuture;
1719
import java.util.concurrent.ExecutionException;
20+
import java.util.concurrent.ExecutorService;
1821
import java.util.concurrent.Executors;
1922
import java.util.concurrent.Future;
2023
import java.util.concurrent.ScheduledExecutorService;
24+
import java.util.concurrent.ThreadFactory;
2125
import java.util.concurrent.TimeUnit;
2226
import javax.swing.JFrame;
27+
import org.jetbrains.annotations.NotNull;
2328

2429
public class MrModule extends JFrame implements Runnable, KeyListener {
2530

31+
private ExecutorService steeringExec = Executors.newSingleThreadExecutor(new NamedThreadFactory("steering"));
32+
private ExecutorService speedExec = Executors.newSingleThreadExecutor(new NamedThreadFactory("speed"));
33+
private ExecutorService imageRGBExec = Executors.newSingleThreadExecutor(new NamedThreadFactory("imageRGB"));
34+
private ExecutorService imageBWExec = Executors.newSingleThreadExecutor(new NamedThreadFactory("imageBW"));
35+
private ExecutorService imageSimpleExec = Executors.newSingleThreadExecutor(new NamedThreadFactory("imageSimple"));
36+
private ExecutorService cameraImageExec = Executors.newSingleThreadExecutor(new NamedThreadFactory("cameraReader"));
2637
private PWMController driveSys = new ArduinoIO();
27-
private ArrayList<Module> modules = new ArrayList<>(); // Contains each module
38+
private List<Module> modules = new ArrayList<>(); // Contains each module
39+
private final WindowModule windowModule;
40+
private final ArduinoModule arduinoModule;
41+
private final ImageManagementModule imageManagementModule;
42+
private final SpeedControlModule speedControlModule;
43+
private final SteeringModule steeringModule;
2844
private final CarControl carControl; // A CarControl that holds data for each module
2945
private CarControl speedControl; // A CarControl that holds data specifically for speed
3046
private CarControl steeringControl; // A CarControl that holds data specifically for steering
47+
private long frameNumber = 0L;
48+
private long lastTime = 0L;
3149

3250
private boolean initialized = false;
3351

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

52-
createModules(hasWindow, winWidth, winHeight);
70+
// Create modules
71+
windowModule = createWindowModule(hasWindow, winWidth, winHeight);
72+
arduinoModule = new ArduinoModule(driveSys);
73+
imageManagementModule = new ImageManagementModule(winWidth, winHeight, carControl.getTile());
74+
speedControlModule = new SpeedControlModule();
75+
steeringModule = new SteeringModule();
76+
77+
initializeModules(windowModule, arduinoModule, imageManagementModule, speedControlModule, steeringModule);
5378

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

6590
Future run = executorService.submit(this);
@@ -71,18 +96,8 @@ private void headlessInit() {
7196
}
7297
}
7398

74-
private void createModules(boolean useWindowModule, int winWidth, int winHeight) {
75-
if(useWindowModule) {
76-
WindowModule windowModule = new WindowModule(winWidth, winHeight);
77-
windowModule.addKeyListener(this);
78-
modules.add(windowModule);
79-
}
80-
81-
modules.add(new ImageManagementModule(winWidth, winHeight, carControl.getTile()));
82-
modules.add(new SpeedControlModule());
83-
modules.add(new SteeringModule());
84-
modules.add(new ArduinoModule(driveSys));
85-
//modules.add(new LatencyTestModule());
99+
private void initializeModules(Module... moduleArray) {
100+
modules = Arrays.asList(moduleArray);
86101

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

109+
private WindowModule createWindowModule(boolean useWindowModule, int winWidth, int winHeight) {
110+
final WindowModule winModule;
111+
if (useWindowModule) {
112+
winModule = new WindowModule(winWidth, winHeight);
113+
winModule.addKeyListener(this);
114+
} else {
115+
winModule = null;
116+
}
117+
return winModule;
118+
}
119+
94120
/**
95121
* <p>
96122
* Update method is called once every FPS.
@@ -99,48 +125,69 @@ private void createModules(boolean useWindowModule, int winWidth, int winHeight)
99125
* run after ImageManagement process their respective image.
100126
* </p>
101127
*/
102-
private void update() {
128+
private void update(long frameNumber) {
103129
//read the camera image, and update windowModule.
104-
carControl.readCameraImage();
105-
carControl.setEdges(getInsets());
106-
modules.get(0).update(carControl);
107-
modules.get(4).update(carControl);
130+
CompletableFuture<Void> cameraImage = CompletableFuture
131+
.runAsync(() -> {
132+
carControl.readCameraImage();
133+
carControl.setEdges(getInsets());
134+
windowModule.update(carControl);
135+
arduinoModule.update(carControl);
136+
}, cameraImageExec);
108137

109138
// FIXME: Does not print exceptions to console.
110-
ImageManagementModule imageModule = (ImageManagementModule) modules.get(1);
139+
111140
// Start Thread to get the RGB image. (for camera)
112-
CompletableFuture<CarControl> futureRGBImage = CompletableFuture.supplyAsync(() -> {
113-
carControl.setRGBImage(imageModule.getRGBRaster(carControl.getRecentCameraImage()));
114-
carControl.setRenderedImage(carControl.getRGBImage());
115-
return carControl;
116-
});
141+
final byte[] recentImage = carControl.getRecentCameraImage();
142+
117143
// Start Thread to get the black and white image (for steering)
118-
CompletableFuture<CarControl> futureBWImage = CompletableFuture.supplyAsync(() -> {
119-
steeringControl.setRGBImage(imageModule.getBlackWhiteRaster(carControl.getRecentCameraImage()));
120-
return steeringControl;
121-
});
122-
// Start Thread to get the simple image (for speed)
123-
CompletableFuture<CarControl> futureSimpleImage = CompletableFuture.supplyAsync(() -> {
124-
speedControl.setProcessedImage(imageModule.getSimpleColorRaster(carControl.getRecentCameraImage()));
125-
return speedControl;
126-
});
127-
128-
// Call steering Module after futureBWImage is finished
129-
CompletableFuture<Void> futureSteering = futureBWImage.thenAcceptAsync(carControl -> modules.get(3).update(carControl));
144+
CompletableFuture<Void> futureSteering = cameraImage
145+
.thenApplyAsync(v -> setBWImage(recentImage), imageBWExec)
146+
// Call steering Module after futureBWImage is finished
147+
.thenAcceptAsync(steeringModule::update, steeringExec);
148+
149+
CompletableFuture<CarControl> futureRGBImage = CompletableFuture.completedFuture(null);
150+
if (frameNumber % 2 == 1) {
151+
futureRGBImage = cameraImage
152+
.thenApplyAsync(v -> setRGBImage(recentImage), imageRGBExec);
153+
}
154+
130155
// Call speed module after futureSimpleImage is finished
131-
CompletableFuture<Void> futureSpeed = futureSimpleImage.thenAcceptAsync(carControl -> modules.get(2).update(carControl));
156+
CompletableFuture<Void> futureSpeed = CompletableFuture.completedFuture(null);
157+
if (frameNumber % 3 == 1) {
158+
// Start Thread to get the simple image (for speed)
159+
futureSpeed = cameraImage
160+
.thenApplyAsync(v -> setSimpleImage(recentImage), imageSimpleExec)
161+
.thenAcceptAsync(speedControlModule::update, speedExec);
162+
}
132163

133164
// Run when all finished.
134165
CompletableFuture.allOf(futureSpeed, futureSteering, futureRGBImage)
135166
.thenAccept(v -> paint())
136167
.exceptionally(ex -> {
137-
System.out.println(ex.getMessage());
168+
ex.printStackTrace();
138169
return null;
139170
})
140171
.join();
141172

142173
}
143174

175+
private CarControl setRGBImage(byte[] recentImage) {
176+
carControl.setRGBImage(imageManagementModule.getRGBRaster(recentImage));
177+
carControl.setRenderedImage(carControl.getRGBImage());
178+
return carControl;
179+
}
180+
181+
private CarControl setBWImage(byte[] recentImage) {
182+
steeringControl.setRGBImage(imageManagementModule.getBlackWhiteRaster(recentImage));
183+
return steeringControl;
184+
}
185+
186+
private CarControl setSimpleImage(byte[] recentImage) {
187+
speedControl.setProcessedImage(imageManagementModule.getSimpleColorRaster(recentImage));
188+
return speedControl;
189+
}
190+
144191
private void paint() {
145192
if (!modules.isEmpty()) {
146193
for (Module module : modules) {
@@ -151,16 +198,24 @@ private void paint() {
151198

152199
@Override
153200
public void run() {
154-
if(!initialized) {
155-
return;
201+
if (initialized) {
202+
//printElapsedTime();
203+
try {
204+
update(++frameNumber);
205+
//paint();
206+
} catch (Exception e) {
207+
e.printStackTrace();
208+
}
156209
}
210+
}
157211

158-
try {
159-
update();
160-
//paint();
161-
} catch(Exception e) {
162-
e.printStackTrace();
212+
private void printElapsedTime() {
213+
final long curTime = System.currentTimeMillis();
214+
if (lastTime == 0) {
215+
lastTime = curTime;
163216
}
217+
System.out.println("Time: " + (lastTime - curTime));
218+
lastTime = curTime;
164219
}
165220

166221
public static void main(String[] args) {
@@ -196,4 +251,16 @@ public void keyReleased(KeyEvent e) { }
196251
@Override
197252
public void keyTyped(KeyEvent e) { }
198253

254+
public static class NamedThreadFactory implements ThreadFactory {
255+
private final String name;
256+
257+
public NamedThreadFactory(String name) {
258+
this.name = name;
259+
}
260+
261+
@Override
262+
public Thread newThread(@NotNull Runnable r) {
263+
return new Thread(r, name);
264+
}
265+
}
199266
}

src/main/java/com/apw/speedcon/SpeedControlModule.java

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,14 @@
33
import com.apw.carcontrol.CamControl;
44
import com.apw.carcontrol.CarControl;
55
import com.apw.carcontrol.Module;
6-
import com.apw.imagemanagement.ImageManipulator;
76
import com.apw.pedestrians.Constant;
87
import com.apw.pedestrians.PedestrianDetector;
98
import com.apw.pedestrians.blobtrack.MovingBlob;
109
import com.apw.pedestrians.image.Color;
1110
import com.apw.pedestrians.image.Pixel;
12-
import com.apw.sbcio.PWMController;
13-
import com.apw.sbcio.fakefirm.ArduinoIO;
1411

1512
import java.awt.*;
1613
import java.awt.event.KeyEvent;
17-
import java.io.IOException;
1814
import java.util.ArrayList;
1915
import java.util.List;
2016

@@ -98,7 +94,7 @@ public void update(CarControl control) {
9894

9995
onUpdate(control);
10096
control.accelerate(true, (int) Math.min(Constants.MAX_SPEED, getNextSpeed()));
101-
System.out.println("getNextSpeed(): " + (int) Math.min(Constants.MAX_SPEED, getNextSpeed()));
97+
//System.out.println("getNextSpeed(): " + (int) Math.min(Constants.MAX_SPEED, getNextSpeed()));
10298
}
10399

104100
@Override

0 commit comments

Comments
 (0)