[build] Apply spotless for java formatting (#1768)

Update checkstyle config to be compatible with spotless.

Co-authored-by: Austin Shalit <austinshalit@gmail.com>
This commit is contained in:
Peter Johnson
2020-12-29 22:45:16 -08:00
committed by GitHub
parent e563a0b7db
commit a751fa22d2
883 changed files with 16526 additions and 17751 deletions

View File

@@ -4,13 +4,6 @@
package edu.wpi.first.cameraserver;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;
import edu.wpi.cscore.AxisCamera;
import edu.wpi.cscore.CameraServerJNI;
import edu.wpi.cscore.CvSink;
@@ -29,27 +22,28 @@ import edu.wpi.first.networktables.EntryListenerFlags;
import edu.wpi.first.networktables.NetworkTable;
import edu.wpi.first.networktables.NetworkTableEntry;
import edu.wpi.first.networktables.NetworkTableInstance;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Singleton class for creating and keeping camera servers.
* Also publishes camera information to NetworkTables.
* Singleton class for creating and keeping camera servers. Also publishes camera information to
* NetworkTables.
*/
public final class CameraServer {
public static final int kBasePort = 1181;
@Deprecated
public static final int kSize640x480 = 0;
@Deprecated
public static final int kSize320x240 = 1;
@Deprecated
public static final int kSize160x120 = 2;
@Deprecated public static final int kSize640x480 = 0;
@Deprecated public static final int kSize320x240 = 1;
@Deprecated public static final int kSize160x120 = 2;
private static final String kPublishName = "/CameraPublisher";
private static CameraServer server;
/**
* Get the CameraServer instance.
*/
/** Get the CameraServer instance. */
public static synchronized CameraServer getInstance() {
if (server == null) {
server = new CameraServer();
@@ -61,12 +55,12 @@ public final class CameraServer {
private String m_primarySourceName;
private final Map<String, VideoSource> m_sources;
private final Map<String, VideoSink> m_sinks;
private final Map<Integer, NetworkTable> m_tables; // indexed by source handle
private final Map<Integer, NetworkTable> m_tables; // indexed by source handle
// source handle indexed by sink handle
private final Map<Integer, Integer> m_fixedSources;
private final NetworkTable m_publishTable;
private final VideoListener m_videoListener; //NOPMD
private final int m_tableListener; //NOPMD
private final VideoListener m_videoListener; // NOPMD
private final int m_tableListener; // NOPMD
private int m_nextPort;
private String[] m_addresses;
@@ -75,14 +69,15 @@ public final class CameraServer {
switch (VideoSource.getKindFromInt(CameraServerJNI.getSourceKind(source))) {
case kUsb:
return "usb:" + CameraServerJNI.getUsbCameraPath(source);
case kHttp: {
String[] urls = CameraServerJNI.getHttpCameraUrls(source);
if (urls.length > 0) {
return "ip:" + urls[0];
} else {
return "ip:";
case kHttp:
{
String[] urls = CameraServerJNI.getHttpCameraUrls(source);
if (urls.length > 0) {
return "ip:" + urls[0];
} else {
return "ip:";
}
}
}
case kCv:
return "cv:";
default:
@@ -98,8 +93,7 @@ public final class CameraServer {
@SuppressWarnings({"MissingJavadocMethod", "PMD.AvoidUsingHardCodedIP"})
private synchronized String[] getSinkStreamValues(int sink) {
// Ignore all but MjpegServer
if (VideoSink.getKindFromInt(CameraServerJNI.getSinkKind(sink))
!= VideoSink.Kind.kMjpeg) {
if (VideoSink.getKindFromInt(CameraServerJNI.getSinkKind(sink)) != VideoSink.Kind.kMjpeg) {
return new String[0];
}
@@ -117,7 +111,7 @@ public final class CameraServer {
values.add(makeStreamValue(CameraServerJNI.getHostname() + ".local", port));
for (String addr : m_addresses) {
if ("127.0.0.1".equals(addr)) {
continue; // ignore localhost
continue; // ignore localhost
}
values.add(makeStreamValue(addr, port));
}
@@ -130,7 +124,7 @@ public final class CameraServer {
private synchronized String[] getSourceStreamValues(int source) {
// Ignore all but HttpCamera
if (VideoSource.getKindFromInt(CameraServerJNI.getSourceKind(source))
!= VideoSource.Kind.kHttp) {
!= VideoSource.Kind.kHttp) {
return new String[0];
}
@@ -148,7 +142,7 @@ public final class CameraServer {
int sinkSource = CameraServerJNI.getSinkSource(sink);
if (source == sinkSource
&& VideoSink.getKindFromInt(CameraServerJNI.getSinkKind(sink))
== VideoSink.Kind.kMjpeg) {
== VideoSink.Kind.kMjpeg) {
// Add USB-only passthrough
String[] finalValues = Arrays.copyOf(values, values.length + 1);
int port = CameraServerJNI.getMjpegServerPort(sink);
@@ -161,17 +155,20 @@ public final class CameraServer {
return values;
}
@SuppressWarnings({"MissingJavadocMethod",
"PMD.AvoidUsingHardCodedIP",
"PMD.CyclomaticComplexity"})
@SuppressWarnings({
"MissingJavadocMethod",
"PMD.AvoidUsingHardCodedIP",
"PMD.CyclomaticComplexity"
})
private synchronized void updateStreamValues() {
// Over all the sinks...
for (VideoSink i : m_sinks.values()) {
int sink = i.getHandle();
// Get the source's subtable (if none exists, we're done)
int source = Objects.requireNonNullElseGet(m_fixedSources.get(sink),
() -> CameraServerJNI.getSinkSource(sink));
int source =
Objects.requireNonNullElseGet(
m_fixedSources.get(sink), () -> CameraServerJNI.getSinkSource(sink));
if (source == 0) {
continue;
@@ -230,8 +227,14 @@ public final class CameraServer {
/// The returned string is "{width}x{height} {format} {fps} fps".
@SuppressWarnings("MissingJavadocMethod")
private static String videoModeToString(VideoMode mode) {
return mode.width + "x" + mode.height + " " + pixelFormatToString(mode.pixelFormat)
+ " " + mode.fps + " fps";
return mode.width
+ "x"
+ mode.height
+ " "
+ pixelFormatToString(mode.pixelFormat)
+ " "
+ mode.fps
+ " fps";
}
@SuppressWarnings("MissingJavadocMethod")
@@ -270,14 +273,18 @@ public final class CameraServer {
case kEnum:
if (isNew) {
entry.setDefaultDouble(event.value);
table.getEntry(infoName + "/min").setDouble(
CameraServerJNI.getPropertyMin(event.propertyHandle));
table.getEntry(infoName + "/max").setDouble(
CameraServerJNI.getPropertyMax(event.propertyHandle));
table.getEntry(infoName + "/step").setDouble(
CameraServerJNI.getPropertyStep(event.propertyHandle));
table.getEntry(infoName + "/default").setDouble(
CameraServerJNI.getPropertyDefault(event.propertyHandle));
table
.getEntry(infoName + "/min")
.setDouble(CameraServerJNI.getPropertyMin(event.propertyHandle));
table
.getEntry(infoName + "/max")
.setDouble(CameraServerJNI.getPropertyMax(event.propertyHandle));
table
.getEntry(infoName + "/step")
.setDouble(CameraServerJNI.getPropertyStep(event.propertyHandle));
table
.getEntry(infoName + "/default")
.setDouble(CameraServerJNI.getPropertyDefault(event.propertyHandle));
} else {
entry.setDouble(event.value);
}
@@ -297,8 +304,12 @@ public final class CameraServer {
}
}
@SuppressWarnings({"MissingJavadocMethod", "PMD.UnusedLocalVariable", "PMD.ExcessiveMethodLength",
"PMD.NPathComplexity"})
@SuppressWarnings({
"MissingJavadocMethod",
"PMD.UnusedLocalVariable",
"PMD.ExcessiveMethodLength",
"PMD.NPathComplexity"
})
private CameraServer() {
m_defaultUsbDevice = new AtomicInteger();
m_sources = new HashMap<>();
@@ -321,176 +332,204 @@ public final class CameraServer {
// - "PropertyInfo/{Property}" - Property supporting information
// Listener for video events
m_videoListener = new VideoListener(event -> {
switch (event.kind) {
case kSourceCreated: {
// Create subtable for the camera
NetworkTable table = m_publishTable.getSubTable(event.name);
m_tables.put(event.sourceHandle, table);
table.getEntry("source").setString(makeSourceValue(event.sourceHandle));
table.getEntry("description").setString(
CameraServerJNI.getSourceDescription(event.sourceHandle));
table.getEntry("connected").setBoolean(
CameraServerJNI.isSourceConnected(event.sourceHandle));
table.getEntry("streams").setStringArray(getSourceStreamValues(event.sourceHandle));
try {
VideoMode mode = CameraServerJNI.getSourceVideoMode(event.sourceHandle);
table.getEntry("mode").setDefaultString(videoModeToString(mode));
table.getEntry("modes").setStringArray(getSourceModeValues(event.sourceHandle));
} catch (VideoException ignored) {
// Do nothing. Let the other event handlers update this if there is an error.
}
break;
}
case kSourceDestroyed: {
NetworkTable table = m_tables.get(event.sourceHandle);
if (table != null) {
table.getEntry("source").setString("");
table.getEntry("streams").setStringArray(new String[0]);
table.getEntry("modes").setStringArray(new String[0]);
}
break;
}
case kSourceConnected: {
NetworkTable table = m_tables.get(event.sourceHandle);
if (table != null) {
// update the description too (as it may have changed)
table.getEntry("description").setString(
CameraServerJNI.getSourceDescription(event.sourceHandle));
table.getEntry("connected").setBoolean(true);
}
break;
}
case kSourceDisconnected: {
NetworkTable table = m_tables.get(event.sourceHandle);
if (table != null) {
table.getEntry("connected").setBoolean(false);
}
break;
}
case kSourceVideoModesUpdated: {
NetworkTable table = m_tables.get(event.sourceHandle);
if (table != null) {
table.getEntry("modes").setStringArray(getSourceModeValues(event.sourceHandle));
}
break;
}
case kSourceVideoModeChanged: {
NetworkTable table = m_tables.get(event.sourceHandle);
if (table != null) {
table.getEntry("mode").setString(videoModeToString(event.mode));
}
break;
}
case kSourcePropertyCreated: {
NetworkTable table = m_tables.get(event.sourceHandle);
if (table != null) {
putSourcePropertyValue(table, event, true);
}
break;
}
case kSourcePropertyValueUpdated: {
NetworkTable table = m_tables.get(event.sourceHandle);
if (table != null) {
putSourcePropertyValue(table, event, false);
}
break;
}
case kSourcePropertyChoicesUpdated: {
NetworkTable table = m_tables.get(event.sourceHandle);
if (table != null) {
try {
String[] choices = CameraServerJNI.getEnumPropertyChoices(event.propertyHandle);
table.getEntry("PropertyInfo/" + event.name + "/choices").setStringArray(choices);
} catch (VideoException ignored) {
// ignore
}
}
break;
}
case kSinkSourceChanged:
case kSinkCreated:
case kSinkDestroyed:
case kNetworkInterfacesChanged: {
m_addresses = CameraServerJNI.getNetworkInterfaces();
updateStreamValues();
break;
}
default:
break;
}
}, 0x4fff, true);
m_videoListener =
new VideoListener(
event -> {
switch (event.kind) {
case kSourceCreated:
{
// Create subtable for the camera
NetworkTable table = m_publishTable.getSubTable(event.name);
m_tables.put(event.sourceHandle, table);
table.getEntry("source").setString(makeSourceValue(event.sourceHandle));
table
.getEntry("description")
.setString(CameraServerJNI.getSourceDescription(event.sourceHandle));
table
.getEntry("connected")
.setBoolean(CameraServerJNI.isSourceConnected(event.sourceHandle));
table
.getEntry("streams")
.setStringArray(getSourceStreamValues(event.sourceHandle));
try {
VideoMode mode = CameraServerJNI.getSourceVideoMode(event.sourceHandle);
table.getEntry("mode").setDefaultString(videoModeToString(mode));
table
.getEntry("modes")
.setStringArray(getSourceModeValues(event.sourceHandle));
} catch (VideoException ignored) {
// Do nothing. Let the other event handlers update this if there is an error.
}
break;
}
case kSourceDestroyed:
{
NetworkTable table = m_tables.get(event.sourceHandle);
if (table != null) {
table.getEntry("source").setString("");
table.getEntry("streams").setStringArray(new String[0]);
table.getEntry("modes").setStringArray(new String[0]);
}
break;
}
case kSourceConnected:
{
NetworkTable table = m_tables.get(event.sourceHandle);
if (table != null) {
// update the description too (as it may have changed)
table
.getEntry("description")
.setString(CameraServerJNI.getSourceDescription(event.sourceHandle));
table.getEntry("connected").setBoolean(true);
}
break;
}
case kSourceDisconnected:
{
NetworkTable table = m_tables.get(event.sourceHandle);
if (table != null) {
table.getEntry("connected").setBoolean(false);
}
break;
}
case kSourceVideoModesUpdated:
{
NetworkTable table = m_tables.get(event.sourceHandle);
if (table != null) {
table
.getEntry("modes")
.setStringArray(getSourceModeValues(event.sourceHandle));
}
break;
}
case kSourceVideoModeChanged:
{
NetworkTable table = m_tables.get(event.sourceHandle);
if (table != null) {
table.getEntry("mode").setString(videoModeToString(event.mode));
}
break;
}
case kSourcePropertyCreated:
{
NetworkTable table = m_tables.get(event.sourceHandle);
if (table != null) {
putSourcePropertyValue(table, event, true);
}
break;
}
case kSourcePropertyValueUpdated:
{
NetworkTable table = m_tables.get(event.sourceHandle);
if (table != null) {
putSourcePropertyValue(table, event, false);
}
break;
}
case kSourcePropertyChoicesUpdated:
{
NetworkTable table = m_tables.get(event.sourceHandle);
if (table != null) {
try {
String[] choices =
CameraServerJNI.getEnumPropertyChoices(event.propertyHandle);
table
.getEntry("PropertyInfo/" + event.name + "/choices")
.setStringArray(choices);
} catch (VideoException ignored) {
// ignore
}
}
break;
}
case kSinkSourceChanged:
case kSinkCreated:
case kSinkDestroyed:
case kNetworkInterfacesChanged:
{
m_addresses = CameraServerJNI.getNetworkInterfaces();
updateStreamValues();
break;
}
default:
break;
}
},
0x4fff,
true);
// Listener for NetworkTable events
// We don't currently support changing settings via NT due to
// synchronization issues, so just update to current setting if someone
// else tries to change it.
m_tableListener = NetworkTableInstance.getDefault().addEntryListener(kPublishName + "/",
event -> {
String relativeKey = event.name.substring(kPublishName.length() + 1);
m_tableListener =
NetworkTableInstance.getDefault()
.addEntryListener(
kPublishName + "/",
event -> {
String relativeKey = event.name.substring(kPublishName.length() + 1);
// get source (sourceName/...)
int subKeyIndex = relativeKey.indexOf('/');
if (subKeyIndex == -1) {
return;
}
String sourceName = relativeKey.substring(0, subKeyIndex);
VideoSource source = m_sources.get(sourceName);
if (source == null) {
return;
}
// get source (sourceName/...)
int subKeyIndex = relativeKey.indexOf('/');
if (subKeyIndex == -1) {
return;
}
String sourceName = relativeKey.substring(0, subKeyIndex);
VideoSource source = m_sources.get(sourceName);
if (source == null) {
return;
}
// get subkey
relativeKey = relativeKey.substring(subKeyIndex + 1);
// get subkey
relativeKey = relativeKey.substring(subKeyIndex + 1);
// handle standard names
String propName;
if ("mode".equals(relativeKey)) {
// reset to current mode
event.getEntry().setString(videoModeToString(source.getVideoMode()));
return;
} else if (relativeKey.startsWith("Property/")) {
propName = relativeKey.substring(9);
} else if (relativeKey.startsWith("RawProperty/")) {
propName = relativeKey.substring(12);
} else {
return; // ignore
}
// handle standard names
String propName;
if ("mode".equals(relativeKey)) {
// reset to current mode
event.getEntry().setString(videoModeToString(source.getVideoMode()));
return;
} else if (relativeKey.startsWith("Property/")) {
propName = relativeKey.substring(9);
} else if (relativeKey.startsWith("RawProperty/")) {
propName = relativeKey.substring(12);
} else {
return; // ignore
}
// everything else is a property
VideoProperty property = source.getProperty(propName);
switch (property.getKind()) {
case kNone:
return;
case kBoolean:
// reset to current setting
event.getEntry().setBoolean(property.get() != 0);
return;
case kInteger:
case kEnum:
// reset to current setting
event.getEntry().setDouble(property.get());
return;
case kString:
// reset to current setting
event.getEntry().setString(property.getString());
return;
default:
return;
}
}, EntryListenerFlags.kImmediate | EntryListenerFlags.kUpdate);
// everything else is a property
VideoProperty property = source.getProperty(propName);
switch (property.getKind()) {
case kNone:
return;
case kBoolean:
// reset to current setting
event.getEntry().setBoolean(property.get() != 0);
return;
case kInteger:
case kEnum:
// reset to current setting
event.getEntry().setDouble(property.get());
return;
case kString:
// reset to current setting
event.getEntry().setString(property.getString());
return;
default:
return;
}
},
EntryListenerFlags.kImmediate | EntryListenerFlags.kUpdate);
}
/**
* Start automatically capturing images to send to the dashboard.
*
* <p>You should call this method to see a camera feed on the dashboard.
* If you also want to perform vision processing on the roboRIO, use
* getVideo() to get access to the camera images.
* <p>You should call this method to see a camera feed on the dashboard. If you also want to
* perform vision processing on the roboRIO, use getVideo() to get access to the camera images.
*
* <p>The first time this overload is called, it calls
* {@link #startAutomaticCapture(int)} with device 0, creating a camera
* named "USB Camera 0". Subsequent calls increment the device number
* <p>The first time this overload is called, it calls {@link #startAutomaticCapture(int)} with
* device 0, creating a camera named "USB Camera 0". Subsequent calls increment the device number
* (e.g. 1, 2, etc).
*/
public UsbCamera startAutomaticCapture() {
@@ -502,8 +541,8 @@ public final class CameraServer {
/**
* Start automatically capturing images to send to the dashboard.
*
* <p>This overload calls {@link #startAutomaticCapture(String, int)} with
* a name of "USB Camera {dev}".
* <p>This overload calls {@link #startAutomaticCapture(String, int)} with a name of "USB Camera
* {dev}".
*
* @param dev The device number of the camera interface
*/
@@ -541,8 +580,7 @@ public final class CameraServer {
}
/**
* Start automatically capturing images to send to the dashboard from
* an existing camera.
* Start automatically capturing images to send to the dashboard from an existing camera.
*
* @param camera Camera
*/
@@ -556,8 +594,7 @@ public final class CameraServer {
/**
* Adds an Axis IP camera.
*
* <p>This overload calls {@link #addAxisCamera(String, String)} with
* name "Axis Camera".
* <p>This overload calls {@link #addAxisCamera(String, String)} with name "Axis Camera".
*
* @param host Camera host IP or DNS name (e.g. "10.x.y.11")
*/
@@ -568,8 +605,7 @@ public final class CameraServer {
/**
* Adds an Axis IP camera.
*
* <p>This overload calls {@link #addAxisCamera(String, String[])} with
* name "Axis Camera".
* <p>This overload calls {@link #addAxisCamera(String, String[])} with name "Axis Camera".
*
* @param hosts Array of Camera host IPs/DNS names
*/
@@ -606,10 +642,9 @@ public final class CameraServer {
}
/**
* Adds a virtual camera for switching between two streams. Unlike the
* other addCamera methods, this returns a VideoSink rather than a
* VideoSource. Calling setSource() on the returned object can be used
* to switch the actual source of the stream.
* Adds a virtual camera for switching between two streams. Unlike the other addCamera methods,
* this returns a VideoSink rather than a VideoSource. Calling setSource() on the returned object
* can be used to switch the actual source of the stream.
*/
public MjpegServer addSwitchedCamera(String name) {
// create a dummy CvSource
@@ -623,11 +658,11 @@ public final class CameraServer {
}
/**
* Get OpenCV access to the primary camera feed. This allows you to
* get images from the camera for image processing on the roboRIO.
* Get OpenCV access to the primary camera feed. This allows you to get images from the camera for
* image processing on the roboRIO.
*
* <p>This is only valid to call after a camera feed has been added
* with startAutomaticCapture() or addServer().
* <p>This is only valid to call after a camera feed has been added with startAutomaticCapture()
* or addServer().
*/
public CvSink getVideo() {
VideoSource source;
@@ -644,8 +679,8 @@ public final class CameraServer {
}
/**
* Get OpenCV access to the specified camera. This allows you to get
* images from the camera for image processing on the roboRIO.
* Get OpenCV access to the specified camera. This allows you to get images from the camera for
* image processing on the roboRIO.
*
* @param camera Camera (e.g. as returned by startAutomaticCapture).
*/
@@ -670,8 +705,8 @@ public final class CameraServer {
}
/**
* Get OpenCV access to the specified camera. This allows you to get
* images from the camera for image processing on the roboRIO.
* Get OpenCV access to the specified camera. This allows you to get images from the camera for
* image processing on the roboRIO.
*
* @param name Camera name
*/
@@ -687,8 +722,8 @@ public final class CameraServer {
}
/**
* Create a MJPEG stream with OpenCV input. This can be called to pass custom
* annotated images to the dashboard.
* Create a MJPEG stream with OpenCV input. This can be called to pass custom annotated images to
* the dashboard.
*
* @param name Name to give the stream
* @param width Width of the image being sent
@@ -750,8 +785,8 @@ public final class CameraServer {
/**
* Get server for the primary camera feed.
*
* <p>This is only valid to call after a camera feed has been added
* with startAutomaticCapture() or addServer().
* <p>This is only valid to call after a camera feed has been added with startAutomaticCapture()
* or addServer().
*/
public VideoSink getServer() {
synchronized (this) {

View File

@@ -4,7 +4,6 @@
package edu.wpi.first.cameraserver;
public interface CameraServerShared {
/**
* get the main thread id func.

View File

@@ -7,48 +7,36 @@ package edu.wpi.first.cameraserver;
public final class CameraServerSharedStore {
private static CameraServerShared cameraServerShared;
private CameraServerSharedStore() {
}
private CameraServerSharedStore() {}
/**
* get the CameraServerShared object.
*/
/** get the CameraServerShared object. */
public static synchronized CameraServerShared getCameraServerShared() {
if (cameraServerShared == null) {
cameraServerShared = new CameraServerShared() {
cameraServerShared =
new CameraServerShared() {
@Override
public void reportVideoServer(int id) {
@Override
public void reportVideoServer(int id) {}
}
@Override
public void reportUsbCamera(int id) {}
@Override
public void reportUsbCamera(int id) {
@Override
public void reportDriverStationError(String error) {}
}
@Override
public void reportAxisCamera(int id) {}
@Override
public void reportDriverStationError(String error) {
}
@Override
public void reportAxisCamera(int id) {
}
@Override
public Long getRobotMainThreadId() {
return null;
}
};
@Override
public Long getRobotMainThreadId() {
return null;
}
};
}
return cameraServerShared;
}
/**
* set the CameraServerShared object.
*/
/** set the CameraServerShared object. */
public static synchronized void setCameraServerShared(CameraServerShared shared) {
cameraServerShared = shared;
}

View File

@@ -7,17 +7,16 @@ package edu.wpi.first.vision;
import org.opencv.core.Mat;
/**
* A vision pipeline is responsible for running a group of
* OpenCV algorithms to extract data from an image.
* A vision pipeline is responsible for running a group of OpenCV algorithms to extract data from an
* image.
*
* @see VisionRunner
* @see VisionThread
*/
public interface VisionPipeline {
/**
* Processes the image input and sets the result objects.
* Implementations should make these objects accessible.
* Processes the image input and sets the result objects. Implementations should make these
* objects accessible.
*/
void process(Mat image);
}

View File

@@ -4,16 +4,15 @@
package edu.wpi.first.vision;
import org.opencv.core.Mat;
import edu.wpi.cscore.CvSink;
import edu.wpi.cscore.VideoSource;
import edu.wpi.first.cameraserver.CameraServerSharedStore;
import org.opencv.core.Mat;
/**
* A vision runner is a convenient wrapper object to make it easy to run vision pipelines
* from robot code. The easiest way to use this is to run it in a {@link VisionThread}
* and use the listener to take snapshots of the pipeline's outputs.
* A vision runner is a convenient wrapper object to make it easy to run vision pipelines from robot
* code. The easiest way to use this is to run it in a {@link VisionThread} and use the listener to
* take snapshots of the pipeline's outputs.
*
* @see VisionPipeline
* @see VisionThread
@@ -42,17 +41,16 @@ public class VisionRunner<P extends VisionPipeline> {
* @param pipeline the vision pipeline that ran
*/
void copyPipelineOutputs(P pipeline);
}
/**
* Creates a new vision runner. It will take images from the {@code videoSource}, send them to
* the {@code pipeline}, and call the {@code listener} when the pipeline has finished to alert
* user code when it is safe to access the pipeline's outputs.
* Creates a new vision runner. It will take images from the {@code videoSource}, send them to the
* {@code pipeline}, and call the {@code listener} when the pipeline has finished to alert user
* code when it is safe to access the pipeline's outputs.
*
* @param videoSource the video source to use to supply images for the pipeline
* @param pipeline the vision pipeline to run
* @param listener a function to call after the pipeline has finished running
* @param pipeline the vision pipeline to run
* @param listener a function to call after the pipeline has finished running
*/
public VisionRunner(VideoSource videoSource, P pipeline, Listener<? super P> listener) {
this.m_pipeline = pipeline;
@@ -61,15 +59,15 @@ public class VisionRunner<P extends VisionPipeline> {
}
/**
* Runs the pipeline one time, giving it the next image from the video source specified
* in the constructor. This will block until the source either has an image or throws an error.
* If the source successfully supplied a frame, the pipeline's image input will be set,
* the pipeline will run, and the listener specified in the constructor will be called to notify
* it that the pipeline ran.
* Runs the pipeline one time, giving it the next image from the video source specified in the
* constructor. This will block until the source either has an image or throws an error. If the
* source successfully supplied a frame, the pipeline's image input will be set, the pipeline will
* run, and the listener specified in the constructor will be called to notify it that the
* pipeline ran.
*
* <p>This method is exposed to allow teams to add additional functionality or have their own
* ways to run the pipeline. Most teams, however, should just use {@link #runForever} in its own
* thread using a {@link VisionThread}.</p>
* <p>This method is exposed to allow teams to add additional functionality or have their own ways
* to run the pipeline. Most teams, however, should just use {@link #runForever} in its own thread
* using a {@link VisionThread}.
*/
public void runOnce() {
Long id = CameraServerSharedStore.getCameraServerShared().getRobotMainThreadId();
@@ -95,11 +93,11 @@ public class VisionRunner<P extends VisionPipeline> {
}
/**
* A convenience method that calls {@link #runOnce()} in an infinite loop. This must
* be run in a dedicated thread, and cannot be used in the main robot thread because
* it will freeze the robot program.
* A convenience method that calls {@link #runOnce()} in an infinite loop. This must be run in a
* dedicated thread, and cannot be used in the main robot thread because it will freeze the robot
* program.
*
* <p><strong>Do not call this method directly from the main thread.</strong></p>
* <p><strong>Do not call this method directly from the main thread.</strong>
*
* @throws IllegalStateException if this is called from the main robot thread
* @see VisionThread
@@ -116,9 +114,7 @@ public class VisionRunner<P extends VisionPipeline> {
}
}
/**
* Stop a RunForever() loop.
*/
/** Stop a RunForever() loop. */
public void stop() {
m_enabled = false;
}

View File

@@ -7,9 +7,9 @@ package edu.wpi.first.vision;
import edu.wpi.cscore.VideoSource;
/**
* A vision thread is a special thread that runs a vision pipeline. It is a <i>daemon</i> thread;
* it does not prevent the program from exiting when all other non-daemon threads
* have finished running.
* A vision thread is a special thread that runs a vision pipeline. It is a <i>daemon</i> thread; it
* does not prevent the program from exiting when all other non-daemon threads have finished
* running.
*
* @see VisionPipeline
* @see VisionRunner
@@ -31,14 +31,12 @@ public class VisionThread extends Thread {
* equivalent to {@code new VisionThread(new VisionRunner<>(videoSource, pipeline, listener))}.
*
* @param videoSource the source for images the pipeline should process
* @param pipeline the pipeline to run
* @param listener the listener to copy outputs from the pipeline after it runs
* @param <P> the type of the pipeline
* @param pipeline the pipeline to run
* @param listener the listener to copy outputs from the pipeline after it runs
* @param <P> the type of the pipeline
*/
public <P extends VisionPipeline> VisionThread(VideoSource videoSource,
P pipeline,
VisionRunner.Listener<? super P> listener) {
public <P extends VisionPipeline> VisionThread(
VideoSource videoSource, P pipeline, VisionRunner.Listener<? super P> listener) {
this(new VisionRunner<>(videoSource, pipeline, listener));
}
}

View File

@@ -3,11 +3,11 @@
// the WPILib BSD license file in the root directory of this project.
/**
* Classes in the {@code edu.wpi.first.vision} package are designed to
* simplify using OpenCV vision processing code from a robot program.
* Classes in the {@code edu.wpi.first.vision} package are designed to simplify using OpenCV vision
* processing code from a robot program.
*
* <p>An example use case for grabbing a yellow tote from 2015 in autonomous: <br>
*
* <p>An example use case for grabbing a yellow tote from 2015 in autonomous:
* <br>
* <pre><code>
* public class Robot extends IterativeRobot
* implements VisionRunner.Listener&lt;MyFindTotePipeline&gt; {