diff --git a/core/src/main/java/edu/wpi/grip/core/settings/CodeGenerationSettings.java b/core/src/main/java/edu/wpi/grip/core/settings/CodeGenerationSettings.java
index aa87cafdbd..0b54dc4152 100644
--- a/core/src/main/java/edu/wpi/grip/core/settings/CodeGenerationSettings.java
+++ b/core/src/main/java/edu/wpi/grip/core/settings/CodeGenerationSettings.java
@@ -13,6 +13,7 @@ public class CodeGenerationSettings {
private final String language;
private final String className;
private final boolean implementWpilibPipeline;
+ private final boolean implementJevoisModule;
private final String saveDir;
private final String packageName;
private final String moduleName;
@@ -20,6 +21,7 @@ public class CodeGenerationSettings {
public static final String LANGUAGE = "language";
public static final String CLASS_NAME = "className";
public static final String IMPLEMENT_WPILIB_PIPELINE = "implementVisionPipeline";
+ public static final String IMPLEMENT_JEVOIS_MODULE = "implementJevoisModule";
public static final String SAVE_DIR = "saveDir";
public static final String PACKAGE_NAME = "packageName";
public static final String MODULE_NAME = "moduleName";
@@ -32,6 +34,7 @@ public class CodeGenerationSettings {
*
Language
Java
*
Class name
GripPipeline
*
Implement WPILib API
false
+ *
Implement Jevois Module
false
*
Save directory
User home
*
Java package
Default package
*
Python module
grip
@@ -46,6 +49,7 @@ public class CodeGenerationSettings {
*
Language
Java
*
Class name
GripPipeline
*
Implement WPILib API
false
+ *
Implement Jevois Module
false
*
Save directory
User home
*
Java package
Default package
*
Python module
grip
@@ -55,6 +59,7 @@ public class CodeGenerationSettings {
this("Java",
"GripPipeline",
false,
+ true,
GripFileManager.GRIP_DIRECTORY.getAbsolutePath(),
"",
"grip");
@@ -67,6 +72,8 @@ public class CodeGenerationSettings {
* @param className the name of the class to generate
* @param implementWpilibPipeline if the generated class should implement the
* WPILib VisionPipeline interface
+ * @param implementJevoisModule if we should generate a full Jevois Module
+ * for the GRIP pipeline
* @param saveDir the directory to save the generated file to
* @param packageName the name of the Java package to place the file in
* @param moduleName the name of the Python module
@@ -74,12 +81,14 @@ public class CodeGenerationSettings {
private CodeGenerationSettings(String language,
String className,
boolean implementWpilibPipeline,
+ boolean implementJevoisModule,
String saveDir,
String packageName,
String moduleName) {
this.language = language;
this.className = className;
this.implementWpilibPipeline = implementWpilibPipeline;
+ this.implementJevoisModule = implementJevoisModule;
this.saveDir = saveDir;
this.packageName = packageName;
this.moduleName = moduleName;
@@ -97,6 +106,10 @@ public boolean shouldImplementWpilibPipeline() {
return implementWpilibPipeline;
}
+ public boolean shouldImplementJevoisModule() {
+ return implementJevoisModule;
+ }
+
public String getSaveDir() {
return saveDir;
}
@@ -124,6 +137,7 @@ public static Builder builder(CodeGenerationSettings defaultSettings) {
.language(defaultSettings.getLanguage())
.className(defaultSettings.getClassName())
.implementVisionPipeline(defaultSettings.shouldImplementWpilibPipeline())
+ .implementJevoisModule(defaultSettings.shouldImplementJevoisModule())
.saveDir(defaultSettings.getSaveDir())
.packageName(defaultSettings.getPackageName())
.moduleName(defaultSettings.getModuleName());
@@ -134,6 +148,7 @@ public static final class Builder {
private String language;
private String className;
private Boolean implementVisionPipeline;
+ private Boolean implementJevoisModule;
private String saveDir;
private String packageName;
private String moduleName;
@@ -174,6 +189,11 @@ public Builder implementVisionPipeline(boolean implementVisionPipeline) {
return this;
}
+ public Builder implementJevoisModule(boolean implementJevoisModule) {
+ this.implementJevoisModule = implementJevoisModule;
+ return this;
+ }
+
/**
* Sets the package of the generated Java class.
*/
@@ -199,6 +219,7 @@ public CodeGenerationSettings build() {
checkNotNull(language, LANGUAGE),
checkNotNull(className, CLASS_NAME),
checkNotNull(implementVisionPipeline, IMPLEMENT_WPILIB_PIPELINE),
+ checkNotNull(implementJevoisModule, IMPLEMENT_JEVOIS_MODULE),
checkNotNull(saveDir, SAVE_DIR),
checkNotNull(packageName, PACKAGE_NAME),
checkNotNull(moduleName, MODULE_NAME)
diff --git a/ui/src/main/java/edu/wpi/grip/ui/codegeneration/CodeGenerationOptionsController.java b/ui/src/main/java/edu/wpi/grip/ui/codegeneration/CodeGenerationOptionsController.java
index cfad2cce0f..80041f5630 100644
--- a/ui/src/main/java/edu/wpi/grip/ui/codegeneration/CodeGenerationOptionsController.java
+++ b/ui/src/main/java/edu/wpi/grip/ui/codegeneration/CodeGenerationOptionsController.java
@@ -52,6 +52,8 @@ public class CodeGenerationOptionsController {
@FXML
private CheckBox implementVisionPipeline;
@FXML
+ private CheckBox implementJevoisModule;
+ @FXML
private TextField classNameField;
@FXML
private Label saveLocationLabel;
@@ -69,6 +71,8 @@ public class CodeGenerationOptionsController {
private TextField moduleNameField;
private Language language;
+ private boolean canImplementPipeline;
+ private boolean canImplementJevoisModule;
private static final String CLASS_NAME_REGEX = "^|([A-Z][a-z]*)+$";
private static final String PACKAGE_REGEX = "^|([a-z]+[a-z0-9]*\\.?)+$";
@@ -96,6 +100,7 @@ private void loadSettings(CodeGenerationSettings settings) {
packageNameField.setText(settings.getPackageName());
moduleNameField.setText(settings.getModuleName());
implementVisionPipeline.setSelected(settings.shouldImplementWpilibPipeline());
+ implementJevoisModule.setSelected(settings.shouldImplementJevoisModule());
Language language = Language.get(settings.getLanguage());
if (language != null) {
languageSelector.getSelectionModel().select(language);
@@ -114,11 +119,16 @@ private static void setTextFilter(TextField f, String regex) {
private void updateImplementButton() {
// Use runLater because pipeline change events are fired before the pipeline actually updates
Platform.runLater(() -> {
- boolean canImplementPipeline = canImplementVisionPipeline();
+ canImplementPipeline = canImplementVisionPipeline();
implementVisionPipeline.setDisable(!canImplementPipeline);
+ canImplementJevoisModule = language == Language.PYTHON;
+ implementJevoisModule.setDisable(!canImplementJevoisModule);
if (!canImplementPipeline) {
implementVisionPipeline.setSelected(false);
}
+ if (!canImplementJevoisModule) {
+ implementJevoisModule.setSelected(false);
+ }
});
}
@@ -140,6 +150,30 @@ private boolean canImplementVisionPipeline() {
return supportedLanguage && onlyOneImageInput && noConnectedNonImageInputs;
}
+ @FXML
+ private void setImplementVisionPipeline() {
+ if (implementVisionPipeline.isSelected()) {
+ implementJevoisModule.setSelected(false);
+ implementJevoisModule.setDisable(true);
+ } else {
+ if (canImplementJevoisModule) {
+ implementJevoisModule.setDisable(false);
+ }
+ }
+ }
+
+ @FXML
+ private void setImplementJevoisModule() {
+ if (implementJevoisModule.isSelected()) {
+ implementVisionPipeline.setSelected(false);
+ implementVisionPipeline.setDisable(true);
+ } else {
+ if (canImplementPipeline) {
+ implementVisionPipeline.setDisable(false);
+ }
+ }
+ }
+
@FXML
private void setLanguage() {
this.language = languageSelector.getSelectionModel().getSelectedItem();
@@ -214,6 +248,7 @@ public CodeGenerationSettings getOptions() {
.language(language.name)
.className(classNameField.getText())
.implementVisionPipeline(implementVisionPipeline.isSelected())
+ .implementJevoisModule(implementJevoisModule.isSelected())
.saveDir(saveLocationLabel.getText())
.packageName(packageNameField.getText())
.moduleName(moduleNameField.getText())
diff --git a/ui/src/main/java/edu/wpi/grip/ui/codegeneration/Exporter.java b/ui/src/main/java/edu/wpi/grip/ui/codegeneration/Exporter.java
index 8ca281a93a..060249a540 100644
--- a/ui/src/main/java/edu/wpi/grip/ui/codegeneration/Exporter.java
+++ b/ui/src/main/java/edu/wpi/grip/ui/codegeneration/Exporter.java
@@ -31,6 +31,7 @@
public class Exporter implements Runnable {
private static final Logger logger = Logger.getLogger(Exporter.class.getName());
private static final String PIPELINE_TEMPLATE = "Pipeline.vm";
+ private static final String PIPELINE_JEVOIS_TEMPLATE = "PipelineJevoisRunner.vm";
private static final String PIPELINE_HTEMPLATE = "Pipeline.h.vm";
private final ImmutableList steps;
private final CodeGenerationSettings settings;
@@ -87,6 +88,8 @@ public void run() {
context.put(CodeGenerationSettings.SAVE_DIR, settings.getSaveDir());
context.put(CodeGenerationSettings.IMPLEMENT_WPILIB_PIPELINE,
settings.shouldImplementWpilibPipeline());
+ context.put(CodeGenerationSettings.IMPLEMENT_JEVOIS_MODULE,
+ settings.shouldImplementJevoisModule());
context.put(CodeGenerationSettings.PACKAGE_NAME, settings.getPackageName());
context.put(CodeGenerationSettings.MODULE_NAME, settings.getModuleName());
context.put("pipeline", new TPipeline(steps));
@@ -167,6 +170,20 @@ private void generateCode(VelocityEngine ve,
} catch (UnsupportedEncodingException | FileNotFoundException e) {
logger.log(Level.SEVERE, "Unable to write to file", e);
}
+ if (settings.shouldImplementJevoisModule()) {
+ File jevoisRunner = new File(new File(settings.getSaveDir()),
+ "GRIPRunner." + lang.extension );
+ logger.info("Generating " + lang.name + " Jevois module code to "
+ + jevoisRunner.getAbsolutePath());
+ Template runner = ve.getTemplate(templateDir + "/" + PIPELINE_JEVOIS_TEMPLATE);
+ StringWriter swRunner = new StringWriter();
+ runner.merge(context, swRunner);
+ try (PrintWriter pwRunner = new PrintWriter(jevoisRunner.getAbsolutePath(), "UTF-8")) {
+ pwRunner.println(swRunner);
+ } catch (UnsupportedEncodingException | FileNotFoundException e) {
+ logger.log(Level.SEVERE, "Unable to create Jevois module", e);
+ }
+ }
}
/**
diff --git a/ui/src/main/resources/edu/wpi/grip/ui/codegeneration/CodegenDialog.fxml b/ui/src/main/resources/edu/wpi/grip/ui/codegeneration/CodegenDialog.fxml
index b129c81427..5261064839 100644
--- a/ui/src/main/resources/edu/wpi/grip/ui/codegeneration/CodegenDialog.fxml
+++ b/ui/src/main/resources/edu/wpi/grip/ui/codegeneration/CodegenDialog.fxml
@@ -14,7 +14,7 @@
-
+
@@ -24,23 +24,26 @@
+
-
-
-
-
+
+
+
+
-
+
+
+
diff --git a/ui/src/main/resources/edu/wpi/grip/ui/codegeneration/python/PipelineJevoisRunner.vm b/ui/src/main/resources/edu/wpi/grip/ui/codegeneration/python/PipelineJevoisRunner.vm
new file mode 100644
index 0000000000..367bfd035b
--- /dev/null
+++ b/ui/src/main/resources/edu/wpi/grip/ui/codegeneration/python/PipelineJevoisRunner.vm
@@ -0,0 +1,29 @@
+#set($enums = [])
+#set($lines = false)
+import libjevois as jevois
+import cv2
+import numpy as np
+import $moduleName
+
+class GRIPRunner:
+
+ def __init__(self):
+ self.pipeline = $moduleName.$className()
+
+ def process(self, inframe, outframe = None):
+ # Execute the pipeline
+ img = inframe.getCvBGR()
+ self.pipeline.process(img)
+
+ # stream to USB output if current mapping is setup for that
+ if outframe is not None:
+#foreach($step in $pipeline.getSteps())#if($foreach.last)#foreach($output in $step.getOutputs())
+#set($oName = $tMeth.pyName($output.name()))
+#if($oName.contains("contour") || $oName.contains("hull"))
+ cv2.drawContours(img,self.pipeline.$tMeth.pyName($output.name()), -1, (0,255,0),2)
+#end#end#end#end
+ outframe.sendCvBGR(img)
+
+# TODO: send contour report over USB
+# TODO: add parameter(s) to enable/disable individual values of the report over USB
+