Skip to content

Commit

Permalink
added jevois module generation for python
Browse files Browse the repository at this point in the history
  • Loading branch information
rrossbach committed Dec 23, 2017
1 parent 978b4a9 commit c484663
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@ 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;

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";
Expand All @@ -32,6 +34,7 @@ public class CodeGenerationSettings {
* <tr><td>Language</td><td>Java</td></tr>
* <tr><td>Class name</td><td>GripPipeline</td></tr>
* <tr><td>Implement WPILib API</td><td>false</td></tr>
* <tr><td>Implement Jevois Module</td><td>false</td></tr>
* <tr><td>Save directory</td><td>User home</td></tr>
* <tr><td>Java package</td><td>Default package</td></tr>
* <tr><td>Python module</td><td>grip</td></tr>
Expand All @@ -46,6 +49,7 @@ public class CodeGenerationSettings {
* <tr><td>Language</td><td>Java</td></tr>
* <tr><td>Class name</td><td>GripPipeline</td></tr>
* <tr><td>Implement WPILib API</td><td>false</td></tr>
* <tr><td>Implement Jevois Module</td><td>false</td></tr>
* <tr><td>Save directory</td><td>User home</td></tr>
* <tr><td>Java package</td><td>Default package</td></tr>
* <tr><td>Python module</td><td>grip</td></tr>
Expand All @@ -55,6 +59,7 @@ public class CodeGenerationSettings {
this("Java",
"GripPipeline",
false,
true,
GripFileManager.GRIP_DIRECTORY.getAbsolutePath(),
"",
"grip");
Expand All @@ -67,19 +72,23 @@ 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
*/
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;
Expand All @@ -97,6 +106,10 @@ public boolean shouldImplementWpilibPipeline() {
return implementWpilibPipeline;
}

public boolean shouldImplementJevoisModule() {
return implementJevoisModule;
}

public String getSaveDir() {
return saveDir;
}
Expand Down Expand Up @@ -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());
Expand All @@ -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;
Expand Down Expand Up @@ -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.
*/
Expand All @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ public class CodeGenerationOptionsController {
@FXML
private CheckBox implementVisionPipeline;
@FXML
private CheckBox implementJevoisModule;
@FXML
private TextField classNameField;
@FXML
private Label saveLocationLabel;
Expand All @@ -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]*\\.?)+$";
Expand Down Expand Up @@ -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);
Expand All @@ -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);
}
});
}

Expand All @@ -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();
Expand Down Expand Up @@ -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())
Expand Down
17 changes: 17 additions & 0 deletions ui/src/main/java/edu/wpi/grip/ui/codegeneration/Exporter.java
Original file line number Diff line number Diff line change
Expand Up @@ -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<Step> steps;
private final CodeGenerationSettings settings;
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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);
}
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.layout.VBox?>

<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">
<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">
<children>
<GridPane fx:id="optionsGrid" alignment="CENTER_LEFT">
<columnConstraints>
Expand All @@ -24,23 +24,26 @@
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="NEVER" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="NEVER" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="NEVER" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="NEVER" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="NEVER" />
</rowConstraints>
<children>
<Label text="Language" />
<ComboBox fx:id="languageSelector" maxWidth="1.7976931348623157E308" onAction="#setLanguage" GridPane.columnIndex="1" />
<Label text="Pipeline class name" GridPane.rowIndex="2" />
<TextField fx:id="classNameField" text="Pipeline" GridPane.columnIndex="1" GridPane.hgrow="NEVER" GridPane.rowIndex="2" />
<Label text="Save location" GridPane.rowIndex="3" />
<HBox nodeOrientation="LEFT_TO_RIGHT" GridPane.columnIndex="1" GridPane.rowIndex="3" GridPane.vgrow="NEVER">
<Label text="Pipeline class name" GridPane.rowIndex="3" />
<TextField fx:id="classNameField" text="Pipeline" GridPane.columnIndex="1" GridPane.hgrow="NEVER" GridPane.rowIndex="3" />
<Label text="Save location" GridPane.rowIndex="4" />
<HBox nodeOrientation="LEFT_TO_RIGHT" GridPane.columnIndex="1" GridPane.rowIndex="4" GridPane.vgrow="NEVER">
<children>
<Label fx:id="saveLocationLabel" disable="true" maxHeight="-Infinity" minHeight="26.0" prefHeight="30.0" prefWidth="105.0" HBox.hgrow="ALWAYS" />
<Button fx:id="browseButton" alignment="CENTER" disable="true" mnemonicParsing="false" onAction="#browseForSave" prefHeight="26.0" prefWidth="82.0" text="Browse" />
</children>
</HBox>
<Label text="Implement WPILib VisionPipeline" GridPane.rowIndex="1" />
<CheckBox fx:id="implementVisionPipeline" mnemonicParsing="false" GridPane.columnIndex="1" GridPane.rowIndex="1" />
<CheckBox fx:id="implementVisionPipeline" mnemonicParsing="false" onAction="#setImplementVisionPipeline" GridPane.columnIndex="1" GridPane.rowIndex="1" />
<CheckBox fx:id="implementJevoisModule" mnemonicParsing="false" onAction="#setImplementJevoisModule" GridPane.columnIndex="1" GridPane.rowIndex="2" />
<Label text="Implement Jevois Module" GridPane.rowIndex="2" />
</children>
<padding>
<Insets left="5.0" right="5.0" top="5.0" />
Expand Down
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit c484663

Please sign in to comment.