Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added jevois module generation for python #872

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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" />
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't aligned correctly. Tabs vs spaces?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm possibly. I didn't edit that file manually so I guess SceneBuilder didn't align. I'll update manually

<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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you plan to do this before this is merged?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to yes - I also have some refactoring in the template I'd like to include (using socket type rather than name to determine whether or not to generate the drawing code). I'll amend the commit over the next couple of days; please let me know if any other thins to look at as well.


Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ public void export(String fileName) {
.className(fileName)
.saveDir(codeDir.getAbsolutePath())
.implementVisionPipeline(false)
.implementJevoisModule(false)
.packageName("")
.moduleName("")
.build(),
Expand All @@ -77,6 +78,7 @@ public void export(String fileName) {
.className(fileName)
.saveDir(codeDir.getAbsolutePath())
.implementVisionPipeline(false)
.implementJevoisModule(false)
.packageName("")
.moduleName(fileName)
.build(),
Expand All @@ -87,6 +89,7 @@ public void export(String fileName) {
.className(fileName)
.saveDir(codeDir.getAbsolutePath())
.implementVisionPipeline(false)
.implementJevoisModule(false)
.packageName("")
.moduleName("")
.build(),
Expand Down