Skip to content

Commit

Permalink
Merge branch 'develop' of https://github.com/openpnp/openpnp into dev…
Browse files Browse the repository at this point in the history
…elop

* 'develop' of https://github.com/openpnp/openpnp:
  Factorize Communication code (#1050)
  Feature/OpenPnpCaptureCamera Capture FPS Test (#1053)
  • Loading branch information
vonnieda committed Sep 8, 2020
2 parents 73c8c0b + c34b1dc commit f2cf6b1
Show file tree
Hide file tree
Showing 5 changed files with 140 additions and 90 deletions.
Expand Up @@ -318,6 +318,41 @@ public void open() {
thread.start();
}

public double estimateCaptureFps() throws Exception {
ensureOpen();
if (stream == null || format == null) {
throw new Exception("Camera stream not properly initialized.");
}
// Start warmup capture timer for 1 second.
boolean warmup = true;
long t0 = System.currentTimeMillis();
long timeout = t0 + 1000;
long t1 = 0;
int capturedFrames = 0;
for (int frames = 0; frames < 480; frames++) {
stream.capture();
while (!stream.hasNewFrame()) {
}
t1 = System.currentTimeMillis();
capturedFrames++;
if (t1 > timeout) {
if (warmup) {
// Warmup complete.
warmup = false;
// Start the real capture timer of 2 seconds.
t0 = t1;
timeout = t0 + 2000;
capturedFrames = 0;
}
else {
break;
}
}
}
// Compute the fps.
return capturedFrames*1000./(t1-t0);
}

private void setPropertiesStream(CaptureStream stream) {
backLightCompensation.setStream(stream);
brightness.setStream(stream);
Expand Down
Expand Up @@ -20,15 +20,18 @@
package org.openpnp.machine.reference.camera.wizards;

import java.awt.Color;
import java.awt.Cursor;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.border.EtchedBorder;
import javax.swing.border.TitledBorder;

Expand All @@ -43,11 +46,15 @@
import org.openpnp.machine.reference.camera.OpenCvCamera.OpenCvCapturePropertyValue;
import org.openpnp.machine.reference.camera.OpenPnpCaptureCamera;
import org.openpnp.model.Configuration;
import org.openpnp.util.UiUtils;

import com.jgoodies.forms.layout.ColumnSpec;
import com.jgoodies.forms.layout.FormLayout;
import com.jgoodies.forms.layout.FormSpecs;
import com.jgoodies.forms.layout.RowSpec;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

@SuppressWarnings("serial")
public class OpenPnpCaptureCameraConfigurationWizard extends AbstractConfigurationWizard {
Expand Down Expand Up @@ -158,6 +165,9 @@ public class OpenPnpCaptureCameraConfigurationWizard extends AbstractConfigurati
private JLabel sharpnessMax;
private JLabel sharpnessDefault;
private JPanel panelGeneral;
private JLabel lblCaptureFps;
private JTextField nativeFps;
private JButton btnTest;

public OpenPnpCaptureCameraConfigurationWizard(OpenPnpCaptureCamera camera) {
this.camera = camera;
Expand Down Expand Up @@ -205,6 +215,24 @@ private void createUi() {
fps.setToolTipText("<html>\nFrame rate for live camera view. Lower uses less CPU and does not affect vision speed.\n<br>0 will update the camera view only when vision or machine movement happens.\n<br>10 FPS is a good starting point.\n</html>\n");
panelGeneral.add(fps, "4, 6");
fps.setColumns(10);

lblCaptureFps = new JLabel("Capture FPS");
lblCaptureFps.setToolTipText("<html>\r\n<p>The test captures frames as fast as possible and computes the average FPS obtained.</p>\r\n<p>Frames are copied from the camera buffer and converted to Java images, <br/>\r\nbut no additional processing is done (no lens calibration, no transforms etc.)</p>\r\n<p>For most accurate results, set Preview PFS to 0.</p>\r\n</html>");
panelGeneral.add(lblCaptureFps, "2, 8, right, default");

nativeFps = new JTextField();
nativeFps.setEditable(false);
panelGeneral.add(nativeFps, "4, 8, fill, default");
nativeFps.setColumns(10);

btnTest = new JButton("Test");
btnTest.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
applyAction.actionPerformed(e);
testNativeFps();
}
});
panelGeneral.add(btnTest, "6, 8");

deviceCb.addActionListener(l -> {
formatCb.removeAllItems();
Expand Down Expand Up @@ -683,6 +711,22 @@ protected void saveToModel() {
camera.open();
}

protected void testNativeFps() {
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
nativeFps.setText("Testing...");
SwingUtilities.invokeLater(() -> {
UiUtils.messageBoxOnException(() -> {
try {
double fps = camera.estimateCaptureFps();
nativeFps.setText(String.format(Locale.US, "%.0f", fps));
}
finally {
setCursor(Cursor.getDefaultCursor());
}
});
});
}

class BooleanInverter extends Converter<Boolean, Boolean> {
@Override
public Boolean convertForward(Boolean arg0) {
Expand Down
Expand Up @@ -55,11 +55,58 @@ public String getLineEnding() {

abstract public String getConnectionName();

abstract public String readLine() throws TimeoutException, IOException;
abstract public void writeLine(String data) throws IOException;
abstract public void writeBytes(byte[] data) throws IOException;

abstract public int read() throws TimeoutException, IOException;
abstract public void write(int d) throws IOException;

/**
* Read a line from the input stream. Blocks for the default timeout. If the read times out a
* TimeoutException is thrown. Any other failure to read results in an IOExeption;
*
* @return
* @throws TimeoutException
* @throws IOException
*/
public String readLine() throws TimeoutException, IOException {
return readUntil("\r\n");
}

public void writeLine(String data) throws IOException {
writeBytes(data.getBytes());
writeBytes(getLineEndingType().getLineEnding().getBytes());
}

/**
* Read the input stream until one of the characters is found. Blocks for the default timeout. If the read times out
* a TimeoutException is thrown. Any other failure to read results in an IOExeption;
*
* @param characters list of ending characters
* @return
* @throws TimeoutException
* @throws IOException
*/
public String readUntil(String characters) throws TimeoutException, IOException {
StringBuffer line = new StringBuffer();
while (true) {
int ch = read();
if (ch == -1) {
return null;
}
else if (characters.indexOf((char)ch) >= 0) {
if (line.length() > 0) {
return line.toString();
}
}
else {
line.append((char) ch);
}
}
}

public void write(int d) throws IOException {
byte[] b = new byte[] { (byte) d };
writeBytes(b);
}

public void setLineEndingType(LineEndingType lineEndingType) {
this.lineEndingType = lineEndingType;
Expand Down
Expand Up @@ -136,43 +136,6 @@ public static String[] getPortNames() {
return portNames.toArray(new String[] {});
}

/**
* Read a line from the serial port. Blocks for the default timeout. If the read times out a
* TimeoutException is thrown. Any other failure to read results in an IOExeption;
*
* @return
* @throws TimeoutException
* @throws IOException
*/
public String readLine() throws TimeoutException, IOException {
StringBuffer line = new StringBuffer();
while (true) {
int ch = read();
if (ch == '\n' || ch == '\r') {
if (line.length() > 0) {
return line.toString();
}
}
else {
line.append((char) ch);
}
}
}

public void writeLine(String data) throws IOException
{
byte[] b = data.getBytes();
int l = serialPort.writeBytes(b, b.length);
if (l == -1) {
throw new IOException("Write error.");
}
b = getLineEndingType().getLineEnding().getBytes();
l = serialPort.writeBytes(b, b.length);
if (l == -1) {
throw new IOException("Write error.");
}
}

public int read() throws TimeoutException, IOException {
byte[] b = new byte[1];
int l = serialPort.readBytes(b, 1);
Expand All @@ -184,15 +147,15 @@ public int read() throws TimeoutException, IOException {
}
return b[0];
}

public void write(int d) throws IOException {
byte[] b = new byte[] { (byte) d };
int l = serialPort.writeBytes(b, 1);

public void writeBytes(byte[] data) throws IOException {
int l = serialPort.writeBytes(data, data.length);
if (l == -1) {
throw new IOException("Write error.");
}
}


public String getConnectionName() {
return "serial://" + portName;
}
Expand Down
Expand Up @@ -50,51 +50,6 @@ public String getConnectionName(){
return "tcp://" + ipAddress + ":" + port;
}

/**
* Read a line from the socket. Blocks for the default timeout. If the read times out a
* TimeoutException is thrown. Any other failure to read results in an IOExeption;
*
* @return
* @throws TimeoutException
* @throws IOException
*/
public String readLine() throws TimeoutException, IOException {
StringBuffer line = new StringBuffer();
while (true) {
try {
int ch = input.read();
if (ch == -1) {
return null;
}
else if (ch == '\n' || ch == '\r') {
if (line.length() > 0) {
return line.toString();
}
}
else {
line.append((char) ch);
}
}
catch (IOException ex) {
if (ex.getCause() instanceof SocketTimeoutException) {
throw new TimeoutException(ex.getMessage());
}
throw ex;
}
}
}

public void writeLine(String data) throws IOException
{
try {
output.write(data.getBytes());
output.write(getLineEndingType().getLineEnding().getBytes());
}
catch (IOException ex) {
throw ex;
}
}

public int read() throws TimeoutException, IOException {
try {
return input.read();
Expand All @@ -106,11 +61,17 @@ public int read() throws TimeoutException, IOException {
throw ex;
}
}


@Override
public void write(int d) throws IOException {
output.write(d);
}

@Override
public void writeBytes(byte[] data) throws IOException {
output.write(data);
}

public String getIpAddress() {
return ipAddress;
}
Expand Down

0 comments on commit f2cf6b1

Please sign in to comment.