Skip to content

Commit dc52336

Browse files
committed
Refactor Operation Interface (#586)
* Refactor Operation Interface - Operations now use local state variables for input and output sockets rather than regenerating them on the fly - Moved name, description, category, icon, and aliases to a separate description object - Socket classes are now interfaces - Refactors Generated Operations to be in source code - Changed socket get methods to return List<FooSocket> instead of FooSocket<?>[]
1 parent 8af109c commit dc52336

File tree

133 files changed

+3988
-2503
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

133 files changed

+3988
-2503
lines changed

buildSrc/src/main/java/edu/wpi/gripgenerator/FileParser.java

Lines changed: 0 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,7 @@
1010
import com.github.javaparser.ast.type.PrimitiveType;
1111
import edu.wpi.gripgenerator.defaults.DefaultValueCollector;
1212
import edu.wpi.gripgenerator.defaults.EnumDefaultValue;
13-
import edu.wpi.gripgenerator.defaults.ObjectDefaultValue;
1413
import edu.wpi.gripgenerator.defaults.PrimitiveDefaultValue;
15-
import edu.wpi.gripgenerator.settings.DefinedMethod;
16-
import edu.wpi.gripgenerator.settings.DefinedMethodCollection;
17-
import edu.wpi.gripgenerator.settings.DefinedParamType;
1814
import edu.wpi.gripgenerator.templates.OperationList;
1915

2016
import java.io.ByteArrayInputStream;
@@ -113,9 +109,6 @@ public Expression getDefaultValue(String defaultValue) {
113109
returnMap.putAll(parseOpenImgprc(compilationUnit, collector, operationList));
114110

115111
}
116-
117-
// Generate the Operation List class last
118-
returnMap.put(operationList.getClassName(), operationList.getDeclaration());
119112
return returnMap;
120113
}
121114

@@ -126,70 +119,6 @@ public static Map<String, CompilationUnit> parseOpenImgprc(CompilationUnit imgpr
126119
OpenCVEnumVisitor enumVisitor = new OpenCVEnumVisitor(baseClassName, collector);
127120
enumVisitor.visit(imgprocDeclaration, compilationUnits);
128121
compilationUnits.putAll(enumVisitor.generateCompilationUnits());
129-
130-
DefinedMethodCollection collection = new DefinedMethodCollection(baseClassName,
131-
new DefinedMethod("Sobel", false, "Mat", "Mat"
132-
).addDescription("Find edges by calculating the requested derivative order for the given image."),
133-
new DefinedMethod("medianBlur", false, "Mat", "Mat"
134-
).addDescription("Apply a Median blur to an image."),
135-
new DefinedMethod("GaussianBlur", false,
136-
new DefinedParamType("Mat"),
137-
new DefinedParamType("Mat"),
138-
new DefinedParamType("Size").setDefaultValue(new ObjectDefaultValue("Size", "1", "1"))
139-
).addDescription("Apply a Gaussian blur to an image."),
140-
new DefinedMethod("Laplacian", "Mat", "Mat"
141-
).addDescription("Find edges by calculating the Laplacian for the given image."),
142-
new DefinedMethod("dilate", false,
143-
new DefinedParamType("Mat"),
144-
new DefinedParamType("Mat"),
145-
new DefinedParamType("Mat").setDefaultValue(new ObjectDefaultValue("Mat"))
146-
).addDescription("Expands areas of higher values in an image."),
147-
new DefinedMethod("Canny", false,
148-
new DefinedParamType("Mat"),
149-
new DefinedParamType("Mat", DefinedParamType.DefinedParamDirection.OUTPUT)
150-
).addDescription("Apply a \\\"canny edge detection\\\" algorithm to an image."),
151-
new DefinedMethod("threshold", false,
152-
new DefinedParamType("Mat"),
153-
new DefinedParamType("Mat"),
154-
new DefinedParamType("double"),
155-
new DefinedParamType("double"),
156-
new DefinedParamType("int").setLiteralDefaultValue("THRESH_BINARY")
157-
).addDescription("Apply a fixed-level threshold to each array element in an image."),
158-
new DefinedMethod("adaptiveThreshold", false,
159-
new DefinedParamType("Mat"),
160-
new DefinedParamType("Mat"),
161-
new DefinedParamType("double"),
162-
new DefinedParamType("int").setLiteralDefaultValue("ADAPTIVE_THRESH_MEAN_C"),
163-
new DefinedParamType("int").setLiteralDefaultValue("THRESH_BINARY")
164-
).addDescription("Transforms a grayscale image to a binary image)."),
165-
new DefinedMethod("erode", false,
166-
new DefinedParamType("Mat"),
167-
new DefinedParamType("Mat"),
168-
new DefinedParamType("Mat").setDefaultValue(new ObjectDefaultValue("Mat"))
169-
).addDescription("Expands areas of lower values in an image."),
170-
new DefinedMethod("cvtColor", false,
171-
new DefinedParamType("Mat"),
172-
new DefinedParamType("Mat"),
173-
new DefinedParamType("int").setLiteralDefaultValue("COLOR_BGR2BGRA")
174-
).addDescription("Convert an image from one color space to another."),
175-
new DefinedMethod("applyColorMap", true,
176-
new DefinedParamType("Mat"),
177-
new DefinedParamType("Mat"),
178-
new DefinedParamType("int").setLiteralDefaultValue("COLORMAP_AUTUMN")
179-
).addDescription("Apply a MATLAB equivalent colormap to an image."),
180-
new DefinedMethod("resize", false,
181-
new DefinedParamType("Mat"),
182-
new DefinedParamType("Mat"),
183-
new DefinedParamType("Size").setDefaultValue(new ObjectDefaultValue("Size"))
184-
).addDescription("Resize the image to the specified size."),
185-
new DefinedMethod("rectangle", false,
186-
new DefinedParamType("Mat", DefinedParamType.DefinedParamDirection.INPUT_AND_OUTPUT),
187-
new DefinedParamType("Point")
188-
).addDescription("Draw a rectangle (outline or filled) on an image.")
189-
).setDirectionDefaults(DefinedParamType.DefinedParamDirection.OUTPUT, "dst")
190-
.setIgnoreDefaults("dtype", "ddepth");
191-
new OpenCVMethodVisitor(collection).visit(imgprocDeclaration, compilationUnits);
192-
collection.generateCompilationUnits(collector, compilationUnits, operations);
193122
return compilationUnits;
194123
}
195124

@@ -201,62 +130,6 @@ public static Map<String, CompilationUnit> parseOpenCVCore(CompilationUnit coreD
201130
enumVisitor.visit(coreDeclaration, compilationUnits);
202131
compilationUnits.putAll(enumVisitor.generateCompilationUnits());
203132

204-
DefinedMethodCollection collection = new DefinedMethodCollection(baseClassName,
205-
new DefinedMethod("add", true, "Mat", "Mat", "Mat")
206-
.addDescription("Calculate the per-pixel sum of two images."),
207-
new DefinedMethod("subtract", true, "Mat", "Mat", "Mat")
208-
.addDescription("Calculate the per-pixel difference between two images."),
209-
new DefinedMethod("multiply", false, "Mat", "Mat", "Mat")
210-
.addDescription("Calculate the per-pixel scaled product of two images."),
211-
new DefinedMethod("divide", false, "Mat", "Mat", "Mat")
212-
.addDescription("Perform per-pixel division of two images."),
213-
new DefinedMethod("scaleAdd", false, "Mat", "double", "Mat", "Mat")
214-
.addDescription("Calculate the sum of two images where one image is multiplied by a scalar."),
215-
// new DefinedMethod("normalize", false, "Mat", "Mat"),
216-
new DefinedMethod("addWeighted", false, "Mat")
217-
.addDescription("Calculate the weighted sum of two images."),
218-
new DefinedMethod("flip", false,
219-
new DefinedParamType("Mat"),
220-
new DefinedParamType("Mat"),
221-
new DefinedParamType("int").setLiteralDefaultValue("Y_AXIS"))
222-
.addDescription("Flip image around vertical, horizontal, or both axes."),
223-
new DefinedMethod("bitwise_and", true, "Mat", "Mat", "Mat")
224-
.addDescription("Calculate the per-element bitwise conjunction of two images."),
225-
new DefinedMethod("bitwise_or", true, "Mat", "Mat", "Mat")
226-
.addDescription("Calculate the per-element bit-wise disjunction of two images."),
227-
new DefinedMethod("bitwise_xor", true, "Mat", "Mat", "Mat")
228-
.addDescription("Calculate the per-element bit-wise \\\"exclusive or\\\" on two images."),
229-
new DefinedMethod("bitwise_not", true, "Mat", "Mat")
230-
.addDescription("Calculate per-element bit-wise inversion of an image."),
231-
new DefinedMethod("absdiff", false, "Mat", "Mat")
232-
.addDescription("Calculate the per-element absolute difference of two images."),
233-
new DefinedMethod("compare", true,
234-
new DefinedParamType("Mat"),
235-
new DefinedParamType("Mat"),
236-
new DefinedParamType("Mat"),
237-
new DefinedParamType("int").setLiteralDefaultValue("CMP_EQ")
238-
).addDescription("Compare each pixel in two images using a given rule."),
239-
new DefinedMethod("max", false, "Mat", "Mat")
240-
.addDescription("Calculate per-element maximum of two images."),
241-
new DefinedMethod("min", false, "Mat", "Mat")
242-
.addDescription("Calculate the per-element minimum of two images."),
243-
new DefinedMethod("extractChannel", false, "Mat", "Mat")
244-
.addDescription("Extract a single channel from a image."),
245-
new DefinedMethod("transpose", false, "Mat", "Mat")
246-
.addDescription("Calculate the transpose of an image.")
247-
// new DefinedMethod("sqrt", false, "Mat", "Mat"),
248-
// new DefinedMethod("pow", false,
249-
// new DefinedParamType("Mat"),
250-
// new DefinedParamType("double")
251-
// .setDefaultValue(new PrimitiveDefaultValue(new PrimitiveType(PrimitiveType.Primitive.Double), "1"))
252-
// )
253-
).setDirectionDefaults(DefinedParamType.DefinedParamDirection.OUTPUT, "dst")
254-
.setIgnoreDefaults("dtype", "ddepth");
255-
new OpenCVMethodVisitor(collection).visit(coreDeclaration, compilationUnits);
256-
257-
collection.generateCompilationUnits(collector, compilationUnits, operations);
258-
259-
260133
return compilationUnits;
261134
}
262135

core/src/main/java/edu/wpi/grip/core/Connection.java

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ public void onConnectionAdded(ConnectionAddedEvent event) {
5858

5959
@Subscribe
6060
public void onOutputChanged(SocketChangedEvent e) {
61-
if (e.getSocket() == outputSocket) {
61+
if (e.isRegarding(outputSocket)) {
6262
inputSocket.setValueOptional(outputSocket.getValue());
6363
}
6464
}
@@ -76,14 +76,14 @@ public void removeConnection(StepRemovedEvent e) {
7676
// Remove this connection if one of the steps it was connected to was removed
7777
for (OutputSocket socket : e.getStep().getOutputSockets()) {
7878
if (socket == this.outputSocket) {
79-
this.eventBus.post(new ConnectionRemovedEvent(this));
79+
remove();
8080
return;
8181
}
8282
}
8383

8484
for (InputSocket socket : e.getStep().getInputSockets()) {
8585
if (socket == this.inputSocket) {
86-
this.eventBus.post(new ConnectionRemovedEvent(this));
86+
remove();
8787
return;
8888
}
8989
}
@@ -94,9 +94,16 @@ public void removeConnection(SourceRemovedEvent e) {
9494
// Remove this connection if it's from a source that was removed
9595
for (OutputSocket socket : e.getSource().getOutputSockets()) {
9696
if (socket == this.outputSocket) {
97-
this.eventBus.post(new ConnectionRemovedEvent(this));
97+
remove();
9898
return;
9999
}
100100
}
101101
}
102+
103+
/**
104+
* Removes this connection from the pipeline.
105+
*/
106+
public void remove() {
107+
eventBus.post(new ConnectionRemovedEvent(this));
108+
}
102109
}

core/src/main/java/edu/wpi/grip/core/GRIPCoreModule.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@
1212
import edu.wpi.grip.core.events.UnexpectedThrowableEvent;
1313
import edu.wpi.grip.core.serialization.Project;
1414
import edu.wpi.grip.core.settings.SettingsProvider;
15+
import edu.wpi.grip.core.sockets.InputSocket;
16+
import edu.wpi.grip.core.sockets.InputSocketImpl;
17+
import edu.wpi.grip.core.sockets.OutputSocket;
18+
import edu.wpi.grip.core.sockets.OutputSocketImpl;
1519
import edu.wpi.grip.core.sources.CameraSource;
1620
import edu.wpi.grip.core.sources.ImageFileSource;
1721
import edu.wpi.grip.core.sources.MultiImageFileSource;
@@ -109,6 +113,9 @@ public <I> void hear(TypeLiteral<I> type, TypeEncounter<I> encounter) {
109113

110114
bind(ConnectionValidator.class).to(Pipeline.class);
111115
bind(Source.SourceFactory.class).to(Source.SourceFactoryImpl.class);
116+
117+
bind(InputSocket.Factory.class).to(InputSocketImpl.FactoryImpl.class);
118+
bind(OutputSocket.Factory.class).to(OutputSocketImpl.FactoryImpl.class);
112119
install(new FactoryModuleBuilder()
113120
.implement(CameraSource.class, CameraSource.class)
114121
.build(CameraSource.Factory.class));

core/src/main/java/edu/wpi/grip/core/Main.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@
66
import com.google.inject.Injector;
77
import edu.wpi.grip.core.events.ExceptionClearedEvent;
88
import edu.wpi.grip.core.events.ExceptionEvent;
9+
import edu.wpi.grip.core.operations.CVOperations;
910
import edu.wpi.grip.core.operations.Operations;
1011
import edu.wpi.grip.core.operations.network.GRIPNetworkModule;
1112
import edu.wpi.grip.core.serialization.Project;
1213
import edu.wpi.grip.core.sources.GRIPSourcesHardwareModule;
13-
import edu.wpi.grip.generated.CVOperations;
1414

1515
import javax.inject.Inject;
1616
import java.io.File;
@@ -27,6 +27,7 @@ public class Main {
2727
@Inject private PipelineRunner pipelineRunner;
2828
@Inject private EventBus eventBus;
2929
@Inject private Operations operations;
30+
@Inject private CVOperations cvOperations;
3031
@Inject private Logger logger;
3132

3233
@SuppressWarnings("PMD.SystemPrintln")
@@ -45,7 +46,7 @@ public void start(String[] args) throws IOException, InterruptedException {
4546
}
4647

4748
operations.addOperations();
48-
CVOperations.addOperations(eventBus);
49+
cvOperations.addOperations();
4950

5051
final String projectPath = args[0];
5152

Lines changed: 14 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -1,112 +1,40 @@
11
package edu.wpi.grip.core;
22

3-
import com.google.common.collect.ImmutableSet;
4-
import com.google.common.eventbus.EventBus;
53
import edu.wpi.grip.core.sockets.InputSocket;
64
import edu.wpi.grip.core.sockets.OutputSocket;
7-
import edu.wpi.grip.core.sockets.SocketsProvider;
85

9-
import java.io.InputStream;
10-
import java.util.Optional;
6+
import java.util.List;
117

128
/**
13-
* The common interface used by <code>Step</code>s in a pipeline to call various operations. There is usually only one
14-
* instance of any class that implements <code>Operation</code>, which is called whenever that operation is used.
9+
* The common interface used by <code>Step</code>s in a pipeline to call various operations. Each instance of an
10+
* operation in the pipeline is handled by a unique instance of that {@code Operation} class.
1511
*/
1612
public interface Operation {
1713

18-
enum Category {
19-
IMAGE_PROCESSING,
20-
FEATURE_DETECTION,
21-
NETWORK,
22-
LOGICAL,
23-
OPENCV,
24-
MISCELLANEOUS,
25-
}
26-
27-
/**
28-
* @return The unique user-facing name of the operation, such as "Gaussian Blur"
29-
*/
30-
String getName();
31-
32-
/**
33-
* @return Any old unique user-facing names of the operation. This is used to preserve compatibility with
34-
* old versions of GRIP if the operation name changes.
35-
*/
36-
default ImmutableSet<String> getAliases() {
37-
return ImmutableSet.of();
38-
}
39-
40-
41-
/**
42-
* @return A description of the operation.
43-
*/
44-
String getDescription();
45-
46-
/**
47-
* @return What category the operation falls under. This is used to organize them in the GUI
48-
*/
49-
default Category getCategory() {
50-
return Category.MISCELLANEOUS;
51-
}
52-
5314
/**
54-
* @return An {@link InputStream} of a 128x128 image to show the user as a representation of the operation.
55-
*/
56-
default Optional<InputStream> getIcon() {
57-
return Optional.empty();
58-
}
59-
60-
default SocketsProvider createSockets(EventBus eventBus) {
61-
return new SocketsProvider(createInputSockets(eventBus), createOutputSockets(eventBus));
62-
}
63-
/**
64-
* @param eventBus The Guava {@link EventBus} used by the application.
65-
* @return An array of sockets for the inputs that the operation expects.
66-
*/
67-
InputSocket<?>[] createInputSockets(EventBus eventBus);
68-
69-
/**
70-
* @param eventBus The Guava {@link EventBus} used by the application.
71-
* @return An array of sockets for the outputs that the operation produces.
15+
* @return A list of sockets for the inputs that the operation expects.
16+
*
17+
* @implNote The returned list should be immutable (i.e. read-only)
7218
*/
73-
OutputSocket<?>[] createOutputSockets(EventBus eventBus);
19+
List<InputSocket> getInputSockets();
7420

7521
/**
76-
* Override this to provide persistent per-step data
22+
* @return A list of sockets for the outputs that the operation produces.
23+
*
24+
* @implNote The returned list should be immutable (i.e. read-only)
7725
*/
78-
default Optional<?> createData() {
79-
return Optional.empty();
80-
}
26+
List<OutputSocket> getOutputSockets();
8127

8228
/**
83-
* Perform the operation on the specified inputs, storing the results in the specified outputs.
84-
*
85-
* @param inputs An array obtained from {@link #createInputSockets(EventBus)}. The caller can set the value of
86-
* each socket to an actual parameter for the operation.
87-
* @param outputs An array obtained from {@link #createOutputSockets(EventBus)}. The outputs of the operation will
88-
* be stored in these sockets.
89-
* @param data Optional data to be passed to the operation
29+
* Performs this {@code Operation}.
9030
*/
91-
default void perform(InputSocket<?>[] inputs, OutputSocket<?>[] outputs, Optional<?> data) {
92-
perform(inputs, outputs);
93-
}
94-
95-
default void perform(InputSocket<?>[] inputs, OutputSocket<?>[] outputs) {
96-
throw new UnsupportedOperationException("Perform was not overridden");
97-
}
31+
void perform();
9832

9933
/**
10034
* Allows the step to clean itself up when removed from the pipeline.
10135
* This should only be called by {@link Step#setRemoved()} to ensure correct synchronization.
102-
*
103-
* @param inputs An array obtained from {@link #createInputSockets(EventBus)}. The caller can set the value of
104-
* each socket to an actual parameter for the operation.
105-
* @param outputs An array obtained from {@link #createOutputSockets(EventBus)}. The outputs of the operation will
106-
* be stored in these sockets.
107-
* @param data Optional data to be passed to the operation
10836
*/
109-
default void cleanUp(InputSocket<?>[] inputs, OutputSocket<?>[] outputs, Optional<?> data) {
37+
default void cleanUp() {
11038
/* no-op */
11139
}
11240
}

0 commit comments

Comments
 (0)