Skip to content

Commit f6fad18

Browse files
committed
added jevois module generation for python
1 parent 978b4a9 commit f6fad18

File tree

6 files changed

+115
-7
lines changed

6 files changed

+115
-7
lines changed

core/src/main/java/edu/wpi/grip/core/settings/CodeGenerationSettings.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,15 @@ public class CodeGenerationSettings {
1313
private final String language;
1414
private final String className;
1515
private final boolean implementWpilibPipeline;
16+
private final boolean implementJevoisModule;
1617
private final String saveDir;
1718
private final String packageName;
1819
private final String moduleName;
1920

2021
public static final String LANGUAGE = "language";
2122
public static final String CLASS_NAME = "className";
2223
public static final String IMPLEMENT_WPILIB_PIPELINE = "implementVisionPipeline";
24+
public static final String IMPLEMENT_JEVOIS_MODULE = "implementJevoisModule";
2325
public static final String SAVE_DIR = "saveDir";
2426
public static final String PACKAGE_NAME = "packageName";
2527
public static final String MODULE_NAME = "moduleName";
@@ -32,6 +34,7 @@ public class CodeGenerationSettings {
3234
* <tr><td>Language</td><td>Java</td></tr>
3335
* <tr><td>Class name</td><td>GripPipeline</td></tr>
3436
* <tr><td>Implement WPILib API</td><td>false</td></tr>
37+
* <tr><td>Implement Jevois Module</td><td>false</td></tr>
3538
* <tr><td>Save directory</td><td>User home</td></tr>
3639
* <tr><td>Java package</td><td>Default package</td></tr>
3740
* <tr><td>Python module</td><td>grip</td></tr>
@@ -46,6 +49,7 @@ public class CodeGenerationSettings {
4649
* <tr><td>Language</td><td>Java</td></tr>
4750
* <tr><td>Class name</td><td>GripPipeline</td></tr>
4851
* <tr><td>Implement WPILib API</td><td>false</td></tr>
52+
* <tr><td>Implement Jevois Module</td><td>false</td></tr>
4953
* <tr><td>Save directory</td><td>User home</td></tr>
5054
* <tr><td>Java package</td><td>Default package</td></tr>
5155
* <tr><td>Python module</td><td>grip</td></tr>
@@ -55,6 +59,7 @@ public class CodeGenerationSettings {
5559
this("Java",
5660
"GripPipeline",
5761
false,
62+
true,
5863
GripFileManager.GRIP_DIRECTORY.getAbsolutePath(),
5964
"",
6065
"grip");
@@ -67,19 +72,23 @@ public class CodeGenerationSettings {
6772
* @param className the name of the class to generate
6873
* @param implementWpilibPipeline if the generated class should implement the
6974
* WPILib VisionPipeline interface
75+
* @param implementJevoisModule if we should generate a full Jevois Module
76+
* for the GRIP pipeline
7077
* @param saveDir the directory to save the generated file to
7178
* @param packageName the name of the Java package to place the file in
7279
* @param moduleName the name of the Python module
7380
*/
7481
private CodeGenerationSettings(String language,
7582
String className,
7683
boolean implementWpilibPipeline,
84+
boolean implementJevoisModule,
7785
String saveDir,
7886
String packageName,
7987
String moduleName) {
8088
this.language = language;
8189
this.className = className;
8290
this.implementWpilibPipeline = implementWpilibPipeline;
91+
this.implementJevoisModule = implementJevoisModule;
8392
this.saveDir = saveDir;
8493
this.packageName = packageName;
8594
this.moduleName = moduleName;
@@ -97,6 +106,10 @@ public boolean shouldImplementWpilibPipeline() {
97106
return implementWpilibPipeline;
98107
}
99108

109+
public boolean shouldImplementJevoisModule() {
110+
return implementJevoisModule;
111+
}
112+
100113
public String getSaveDir() {
101114
return saveDir;
102115
}
@@ -124,6 +137,7 @@ public static Builder builder(CodeGenerationSettings defaultSettings) {
124137
.language(defaultSettings.getLanguage())
125138
.className(defaultSettings.getClassName())
126139
.implementVisionPipeline(defaultSettings.shouldImplementWpilibPipeline())
140+
.implementJevoisModule(defaultSettings.shouldImplementJevoisModule())
127141
.saveDir(defaultSettings.getSaveDir())
128142
.packageName(defaultSettings.getPackageName())
129143
.moduleName(defaultSettings.getModuleName());
@@ -134,6 +148,7 @@ public static final class Builder {
134148
private String language;
135149
private String className;
136150
private Boolean implementVisionPipeline;
151+
private Boolean implementJevoisModule;
137152
private String saveDir;
138153
private String packageName;
139154
private String moduleName;
@@ -174,6 +189,11 @@ public Builder implementVisionPipeline(boolean implementVisionPipeline) {
174189
return this;
175190
}
176191

192+
public Builder implementJevoisModule(boolean implementJevoisModule) {
193+
this.implementJevoisModule = implementJevoisModule;
194+
return this;
195+
}
196+
177197
/**
178198
* Sets the package of the generated Java class.
179199
*/
@@ -199,6 +219,7 @@ public CodeGenerationSettings build() {
199219
checkNotNull(language, LANGUAGE),
200220
checkNotNull(className, CLASS_NAME),
201221
checkNotNull(implementVisionPipeline, IMPLEMENT_WPILIB_PIPELINE),
222+
checkNotNull(implementJevoisModule, IMPLEMENT_JEVOIS_MODULE),
202223
checkNotNull(saveDir, SAVE_DIR),
203224
checkNotNull(packageName, PACKAGE_NAME),
204225
checkNotNull(moduleName, MODULE_NAME)

ui/src/main/java/edu/wpi/grip/ui/codegeneration/CodeGenerationOptionsController.java

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ public class CodeGenerationOptionsController {
5252
@FXML
5353
private CheckBox implementVisionPipeline;
5454
@FXML
55+
private CheckBox implementJevoisModule;
56+
@FXML
5557
private TextField classNameField;
5658
@FXML
5759
private Label saveLocationLabel;
@@ -69,6 +71,8 @@ public class CodeGenerationOptionsController {
6971
private TextField moduleNameField;
7072

7173
private Language language;
74+
private boolean canImplementPipeline;
75+
private boolean canImplementJevoisModule;
7276

7377
private static final String CLASS_NAME_REGEX = "^|([A-Z][a-z]*)+$";
7478
private static final String PACKAGE_REGEX = "^|([a-z]+[a-z0-9]*\\.?)+$";
@@ -96,6 +100,7 @@ private void loadSettings(CodeGenerationSettings settings) {
96100
packageNameField.setText(settings.getPackageName());
97101
moduleNameField.setText(settings.getModuleName());
98102
implementVisionPipeline.setSelected(settings.shouldImplementWpilibPipeline());
103+
implementJevoisModule.setSelected(settings.shouldImplementJevoisModule());
99104
Language language = Language.get(settings.getLanguage());
100105
if (language != null) {
101106
languageSelector.getSelectionModel().select(language);
@@ -114,11 +119,16 @@ private static void setTextFilter(TextField f, String regex) {
114119
private void updateImplementButton() {
115120
// Use runLater because pipeline change events are fired before the pipeline actually updates
116121
Platform.runLater(() -> {
117-
boolean canImplementPipeline = canImplementVisionPipeline();
122+
canImplementPipeline = canImplementVisionPipeline();
118123
implementVisionPipeline.setDisable(!canImplementPipeline);
124+
canImplementJevoisModule = language == Language.PYTHON;
125+
implementJevoisModule.setDisable(!canImplementJevoisModule);
119126
if (!canImplementPipeline) {
120127
implementVisionPipeline.setSelected(false);
121128
}
129+
if (!canImplementJevoisModule) {
130+
implementJevoisModule.setSelected(false);
131+
}
122132
});
123133
}
124134

@@ -140,6 +150,30 @@ private boolean canImplementVisionPipeline() {
140150
return supportedLanguage && onlyOneImageInput && noConnectedNonImageInputs;
141151
}
142152

153+
@FXML
154+
private void setImplementVisionPipeline() {
155+
if (implementVisionPipeline.isSelected()) {
156+
implementJevoisModule.setSelected(false);
157+
implementJevoisModule.setDisable(true);
158+
} else {
159+
if (canImplementJevoisModule) {
160+
implementJevoisModule.setDisable(false);
161+
}
162+
}
163+
}
164+
165+
@FXML
166+
private void setImplementJevoisModule() {
167+
if (implementJevoisModule.isSelected()) {
168+
implementVisionPipeline.setSelected(false);
169+
implementVisionPipeline.setDisable(true);
170+
} else {
171+
if (canImplementPipeline) {
172+
implementVisionPipeline.setDisable(false);
173+
}
174+
}
175+
}
176+
143177
@FXML
144178
private void setLanguage() {
145179
this.language = languageSelector.getSelectionModel().getSelectedItem();
@@ -214,6 +248,7 @@ public CodeGenerationSettings getOptions() {
214248
.language(language.name)
215249
.className(classNameField.getText())
216250
.implementVisionPipeline(implementVisionPipeline.isSelected())
251+
.implementJevoisModule(implementJevoisModule.isSelected())
217252
.saveDir(saveLocationLabel.getText())
218253
.packageName(packageNameField.getText())
219254
.moduleName(moduleNameField.getText())

ui/src/main/java/edu/wpi/grip/ui/codegeneration/Exporter.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
public class Exporter implements Runnable {
3232
private static final Logger logger = Logger.getLogger(Exporter.class.getName());
3333
private static final String PIPELINE_TEMPLATE = "Pipeline.vm";
34+
private static final String PIPELINE_JEVOIS_TEMPLATE = "PipelineJevoisRunner.vm";
3435
private static final String PIPELINE_HTEMPLATE = "Pipeline.h.vm";
3536
private final ImmutableList<Step> steps;
3637
private final CodeGenerationSettings settings;
@@ -87,6 +88,8 @@ public void run() {
8788
context.put(CodeGenerationSettings.SAVE_DIR, settings.getSaveDir());
8889
context.put(CodeGenerationSettings.IMPLEMENT_WPILIB_PIPELINE,
8990
settings.shouldImplementWpilibPipeline());
91+
context.put(CodeGenerationSettings.IMPLEMENT_JEVOIS_MODULE,
92+
settings.shouldImplementJevoisModule());
9093
context.put(CodeGenerationSettings.PACKAGE_NAME, settings.getPackageName());
9194
context.put(CodeGenerationSettings.MODULE_NAME, settings.getModuleName());
9295
context.put("pipeline", new TPipeline(steps));
@@ -167,6 +170,20 @@ private void generateCode(VelocityEngine ve,
167170
} catch (UnsupportedEncodingException | FileNotFoundException e) {
168171
logger.log(Level.SEVERE, "Unable to write to file", e);
169172
}
173+
if (settings.shouldImplementJevoisModule()) {
174+
File jevoisRunner = new File(new File(settings.getSaveDir()),
175+
"GRIPRunner." + lang.extension );
176+
logger.info("Generating " + lang.name + " Jevois module code to "
177+
+ jevoisRunner.getAbsolutePath());
178+
Template runner = ve.getTemplate(templateDir + "/" + PIPELINE_JEVOIS_TEMPLATE);
179+
StringWriter swRunner = new StringWriter();
180+
runner.merge(context, swRunner);
181+
try (PrintWriter pwRunner = new PrintWriter(jevoisRunner.getAbsolutePath(), "UTF-8")) {
182+
pwRunner.println(swRunner);
183+
} catch (UnsupportedEncodingException | FileNotFoundException e) {
184+
logger.log(Level.SEVERE, "Unable to create Jevois module", e);
185+
}
186+
}
170187
}
171188

172189
/**

ui/src/main/resources/edu/wpi/grip/ui/codegeneration/CodegenDialog.fxml

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
<?import javafx.scene.layout.StackPane?>
1515
<?import javafx.scene.layout.VBox?>
1616

17-
<VBox fx:id="root" xmlns="http://javafx.com/javafx/8.0.65" xmlns:fx="http://javafx.com/fxml/1" fx:controller="edu.wpi.grip.ui.codegeneration.CodeGenerationOptionsController">
17+
<VBox fx:id="root" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1" fx:controller="edu.wpi.grip.ui.codegeneration.CodeGenerationOptionsController">
1818
<children>
1919
<GridPane fx:id="optionsGrid" alignment="CENTER_LEFT">
2020
<columnConstraints>
@@ -24,23 +24,26 @@
2424
<rowConstraints>
2525
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="NEVER" />
2626
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="NEVER" />
27+
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="NEVER" />
2728
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="NEVER" />
2829
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="NEVER" />
2930
</rowConstraints>
3031
<children>
3132
<Label text="Language" />
3233
<ComboBox fx:id="languageSelector" maxWidth="1.7976931348623157E308" onAction="#setLanguage" GridPane.columnIndex="1" />
33-
<Label text="Pipeline class name" GridPane.rowIndex="2" />
34-
<TextField fx:id="classNameField" text="Pipeline" GridPane.columnIndex="1" GridPane.hgrow="NEVER" GridPane.rowIndex="2" />
35-
<Label text="Save location" GridPane.rowIndex="3" />
36-
<HBox nodeOrientation="LEFT_TO_RIGHT" GridPane.columnIndex="1" GridPane.rowIndex="3" GridPane.vgrow="NEVER">
34+
<Label text="Pipeline class name" GridPane.rowIndex="3" />
35+
<TextField fx:id="classNameField" text="Pipeline" GridPane.columnIndex="1" GridPane.hgrow="NEVER" GridPane.rowIndex="3" />
36+
<Label text="Save location" GridPane.rowIndex="4" />
37+
<HBox nodeOrientation="LEFT_TO_RIGHT" GridPane.columnIndex="1" GridPane.rowIndex="4" GridPane.vgrow="NEVER">
3738
<children>
3839
<Label fx:id="saveLocationLabel" disable="true" maxHeight="-Infinity" minHeight="26.0" prefHeight="30.0" prefWidth="105.0" HBox.hgrow="ALWAYS" />
3940
<Button fx:id="browseButton" alignment="CENTER" disable="true" mnemonicParsing="false" onAction="#browseForSave" prefHeight="26.0" prefWidth="82.0" text="Browse" />
4041
</children>
4142
</HBox>
4243
<Label text="Implement WPILib VisionPipeline" GridPane.rowIndex="1" />
43-
<CheckBox fx:id="implementVisionPipeline" mnemonicParsing="false" GridPane.columnIndex="1" GridPane.rowIndex="1" />
44+
<CheckBox fx:id="implementVisionPipeline" mnemonicParsing="false" onAction="#setImplementVisionPipeline" GridPane.columnIndex="1" GridPane.rowIndex="1" />
45+
<CheckBox fx:id="implementJevoisModule" mnemonicParsing="false" onAction="#setImplementJevoisModule" GridPane.columnIndex="1" GridPane.rowIndex="2" />
46+
<Label text="Implement Jevois Module" GridPane.rowIndex="2" />
4447
</children>
4548
<padding>
4649
<Insets left="5.0" right="5.0" top="5.0" />
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#set($enums = [])
2+
#set($lines = false)
3+
import libjevois as jevois
4+
import cv2
5+
import numpy as np
6+
import $moduleName
7+
8+
class GRIPRunner:
9+
10+
def __init__(self):
11+
self.pipeline = $moduleName.$className()
12+
13+
def process(self, inframe, outframe = None):
14+
# Execute the pipeline
15+
img = inframe.getCvBGR()
16+
self.pipeline.process(img)
17+
18+
# stream to USB output if current mapping is setup for that
19+
if outframe is not None:
20+
#foreach($step in $pipeline.getSteps())#if($foreach.last)#foreach($output in $step.getOutputs())
21+
#set($oName = $tMeth.pyName($output.name()))
22+
#if($oName.contains("contour") || $oName.contains("hull"))
23+
cv2.drawContours(img,self.pipeline.$tMeth.pyName($output.name()), -1, (0,255,0),2)
24+
#end#end#end#end
25+
outframe.sendCvBGR(img)
26+
27+
# TODO: send contour report over USB
28+
# TODO: add parameter(s) to enable/disable individual values of the report over USB
29+

ui/src/test/java/edu/wpi/grip/ui/codegeneration/tools/PipelineGenerator.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ public void export(String fileName) {
6767
.className(fileName)
6868
.saveDir(codeDir.getAbsolutePath())
6969
.implementVisionPipeline(false)
70+
.implementJevoisModule(false)
7071
.packageName("")
7172
.moduleName("")
7273
.build(),
@@ -77,6 +78,7 @@ public void export(String fileName) {
7778
.className(fileName)
7879
.saveDir(codeDir.getAbsolutePath())
7980
.implementVisionPipeline(false)
81+
.implementJevoisModule(false)
8082
.packageName("")
8183
.moduleName(fileName)
8284
.build(),
@@ -87,6 +89,7 @@ public void export(String fileName) {
8789
.className(fileName)
8890
.saveDir(codeDir.getAbsolutePath())
8991
.implementVisionPipeline(false)
92+
.implementJevoisModule(false)
9093
.packageName("")
9194
.moduleName("")
9295
.build(),

0 commit comments

Comments
 (0)